diff options
author | Sven Gothel <[email protected]> | 2023-04-05 10:06:26 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-04-05 10:06:26 +0200 |
commit | 1eb9d91bbf5d24a02c4d9e98501ff51eb7ecdcd0 (patch) | |
tree | dc1c7615f4b99d7b09c9b3c569f6e3d459dbb4e5 /src/graphui/classes/jogamp/graph/ui | |
parent | 15e60161787224e85172685f74dc0ac195969b51 (diff) |
GraphUI: Adopting Vec*f API; Adding Group; Scene + Group are Container, traversing the PMVMatrix throughout childs (-> see TreeTool).
Utilizing the Vec*f (and Matrix4f) API w/ AABBox et al renders our code more clean & safe,
see commit 15e60161787224e85172685f74dc0ac195969b51.
A Group allows to contain multiple Shapes,
hence the PMVMatrix must be traversed accordingly using TreeTool
for all operations (draw, picking, win->obj coordinates, ..).
Hence Scene + Group are now implementing Container
and reuse code via TreeTool and a Shape.Visitor*.
This will allow further simplification of user code.
Diffstat (limited to 'src/graphui/classes/jogamp/graph/ui')
-rw-r--r-- | src/graphui/classes/jogamp/graph/ui/TreeTool.java | 159 | ||||
-rw-r--r-- | src/graphui/classes/jogamp/graph/ui/shapes/Label0.java | 5 |
2 files changed, 162 insertions, 2 deletions
diff --git a/src/graphui/classes/jogamp/graph/ui/TreeTool.java b/src/graphui/classes/jogamp/graph/ui/TreeTool.java new file mode 100644 index 000000000..ff893ab56 --- /dev/null +++ b/src/graphui/classes/jogamp/graph/ui/TreeTool.java @@ -0,0 +1,159 @@ +/** + * Copyright 2023 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.ui; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import com.jogamp.graph.ui.Container; +import com.jogamp.graph.ui.Scene; +import com.jogamp.graph.ui.Shape; +import com.jogamp.graph.ui.Shape.Visitor1; +import com.jogamp.graph.ui.Shape.Visitor2; +import com.jogamp.opengl.util.PMVMatrix; + +/** Generic static {@link Shape} tree traversal tools, utilized by {@link Scene} and {@link Container} implementations. */ +public class TreeTool { + + /** + * Traverses through the graph up until {@code shape} and apply {@code action} on it. + * @param pmv + * @param shape + * @param action + * @return true to signal operation complete, i.e. {@code shape} found, otherwise false + */ + public static boolean forOne(final List<Shape> shapes, final PMVMatrix pmv, final Shape shape, final Runnable action) { + for(int i=shapes.size()-1; i>=0; i--) { + final Shape s = shapes.get(i); + if( s instanceof Container ) { + final Container c = (Container)s; + if( !c.contains(shape) ) { // fast-path: skip container + continue; + } + pmv.glPushMatrix(); + s.setTransform(pmv); + final boolean res = c.forOne(pmv, shape, action); + pmv.glPopMatrix(); + if( !res ) { throw new InternalError("Not found "+shape+" in "+c+", but contained"); } + return true; + } else { + if( s.equals(shape) ) { + pmv.glPushMatrix(); + s.setTransform(pmv); + action.run(); + pmv.glPopMatrix(); + return true; + } + } + } + return false; + } + + /** + * Traverses through the graph and apply {@link Visitor1#visit(Shape)} for each, stop if it returns true. + * @param v + * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor1#visit(Shape)} returned true, otherwise false + */ + public static boolean forAll(final List<Shape> shapes, final Visitor1 v) { + for(int i=shapes.size()-1; i>=0; i--) { + final Shape s = shapes.get(i); + boolean res; + if( s instanceof Container ) { + final Container c = (Container)s; + res = c.forAll(v); + } else { + res = v.visit(s); + } + if( res ) { + return true; + } + } + return false; + } + + /** + * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix)} for each, stop if it returns true. + * @param pmv + * @param v + * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix)} returned true, otherwise false + */ + public static boolean forAll(final List<Shape> shapes, final PMVMatrix pmv, final Visitor2 v) { + for(int i=shapes.size()-1; i>=0; i--) { + final Shape s = shapes.get(i); + pmv.glPushMatrix(); + s.setTransform(pmv); + boolean res; + if( s instanceof Container ) { + final Container c = (Container)s; + res = c.forAll(pmv, v); + } else { + res = v.visit(s, pmv); + } + pmv.glPopMatrix(); + if( res ) { + return true; + } + } + return false; + } + + /** + * Traverses through the graph and apply {@link Visitor#visit(Shape, PMVMatrix)} for each, stop if it returns true. + * + * Each {@link Container} level is sorted using {@code sortComp} + * @param sortComp + * @param pmv + * @param v + * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix)} returned true, otherwise false + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static boolean forSortedAll(final Comparator<Shape> sortComp, final List<Shape> shapes, final PMVMatrix pmv, final Visitor2 v) { + final Object[] shapesS = shapes.toArray(); + Arrays.sort(shapesS, (Comparator)sortComp); + + for(int i=shapesS.length-1; i>=0; i--) { + final Shape s = (Shape)shapesS[i]; + pmv.glPushMatrix(); + s.setTransform(pmv); + boolean res; + if( s instanceof Container ) { + final Container c = (Container)s; + res = c.forAll(pmv, v); + } else { + res = v.visit(s, pmv); + } + pmv.glPopMatrix(); + if( res ) { + return true; + } + } + return false; + } + +} diff --git a/src/graphui/classes/jogamp/graph/ui/shapes/Label0.java b/src/graphui/classes/jogamp/graph/ui/shapes/Label0.java index fe5f7f8e5..a091a89ed 100644 --- a/src/graphui/classes/jogamp/graph/ui/shapes/Label0.java +++ b/src/graphui/classes/jogamp/graph/ui/shapes/Label0.java @@ -31,6 +31,7 @@ import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.TextRegionUtil; import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.opengl.math.Vec2f; import com.jogamp.opengl.math.geom.AABBox; public class Label0 { @@ -65,10 +66,10 @@ public class Label0 { this.font = font; } - public final AABBox addShapeToRegion(final float scale, final Region region, final float[] txy, + public final AABBox addShapeToRegion(final float scale, final Region region, final Vec2f txy, final AffineTransform tmp1, final AffineTransform tmp2, final AffineTransform tmp3) { - tmp1.setToTranslation(txy[0], txy[1]); + tmp1.setToTranslation(txy.x(), txy.y()); tmp1.scale(scale, scale, tmp2); return TextRegionUtil.addStringToRegion(region, font, tmp1, text, rgbaColor, tmp2, tmp3); } |