diff options
Diffstat (limited to 'src/graphui/classes/com/jogamp/graph')
6 files changed, 257 insertions, 76 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Container.java b/src/graphui/classes/com/jogamp/graph/ui/Container.java index 545ceec60..82f2fda4f 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Container.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Container.java @@ -32,6 +32,7 @@ import java.util.Comparator; import java.util.List; import com.jogamp.graph.ui.Shape.Visitor2; +import com.jogamp.math.Matrix4f; import com.jogamp.math.geom.AABBox; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.opengl.GL2ES2; @@ -48,9 +49,29 @@ public interface Container { /** Returns number of {@link Shape}s, see {@link #getShapes()}. */ int getShapeCount(); - /** Returns added {@link Shape}s, see {@link #addShape(Shape)}. */ + /** Returns {@link #addShape(Shape) added} {@link Shape}s. */ List<Shape> getShapes(); + /** + * Returns {@link #addShape(Shape) added shapes} which are rendered and sorted by z-axis in ascending order toward z-near. + * <p> + * The rendered shapes are {@link Shape#isVisible() visible} and not deemed outside of this container due to {@link #isCullingEnabled() culling}. + * </p> + * <p> + * Only rendered shapes are considered for picking/activation. + * </p> + * <p> + * The returned list is data-race free, i.e. won't be mutated by the rendering thread + * as it gets completely replace at each rendering loop using a local volatile reference.<br/> + * Only when disposing the container, the list gets cleared, hence {@Link List#size()} shall be used in the loop. + * </p> + * @see #addShape(Shape) + * @see #isCullingEnabled() + * @see Shape#isVisible() + * @see #isOutside(PMVMatrix4f, Shape) + */ + List<Shape> getRenderedShapes(); + /** Adds a {@link Shape}. */ void addShape(Shape s); @@ -89,14 +110,46 @@ public interface Container { /** Returns {@link AABBox} dimension of given {@link Shape} from this container's perspective, i.e. world-bounds if performing from the {@link Scene}. */ AABBox getBounds(final PMVMatrix4f pmv, Shape shape); - /** Enable or disable {@link PMVMatrix4f#getFrustum()} culling per {@link Shape}. Default is disabled. */ - void setFrustumCullingEnabled(final boolean v); + /** Enable or disable {@link PMVMatrix4f#getFrustum() Project-Modelview (PMv) frustum} culling per {@link Shape} for this container. Default is disabled. */ + void setPMvCullingEnabled(final boolean v); + + /** Return whether {@link #setPMvCullingEnabled(boolean) Project-Modelview (PMv) frustum culling} is enabled for this container. */ + boolean isPMvCullingEnabled(); + + /** + * Return whether {@link #setPMvCullingEnabled(boolean) Project-Modelview (PMv) frustum culling} + * or {@link Group#setClipMvFrustum(com.jogamp.math.geom.Frustum) Group's Modelview (Mv) frustum clipping} + * is enabled for this container. Default is disabled. + */ + boolean isCullingEnabled(); + + /** + * Returns whether the given {@link Shape} is completely outside of this container. + * <p> + * Note: If method returns false, the box may only be partially inside, i.e. intersects with this container + * </p> + * @param pmv current {@link PMVMatrix4f} of this container + * @param shape the {@link Shape} to test + * @see #isOutside2(Matrix4f, Shape, PMVMatrix4f) + * @see Shape#isOutside() + */ + public boolean isOutside(final PMVMatrix4f pmv, final Shape shape); - /** Return whether {@link #setFrustumCullingEnabled(boolean) frustum culling} is enabled. */ - boolean isFrustumCullingEnabled(); + /** + * Returns whether the given {@link Shape} is completely outside of this container. + * <p> + * Note: If method returns false, the box may only be partially inside, i.e. intersects with this container + * </p> + * @param mvCont copy of the model-view {@link Matrix4f) of this container + * @param shape the {@link Shape} to test + * @param pmvShape current {@link PMVMatrix4f} of the shape to test + * @see #isOutside(PMVMatrix4f, Shape) + * @see Shape#isOutside() + */ + public boolean isOutside2(final Matrix4f mvCont, final Shape shape, final PMVMatrix4f pmvShape); /** - * Traverses through the graph up until {@code shape} and apply {@code action} on it. + * Traverses through the graph up until {@code shape} of {@link Container#getShapes()} and apply {@code action} on it. * @param pmv * @param shape * @param action @@ -105,14 +158,16 @@ public interface Container { boolean forOne(final PMVMatrix4f pmv, final Shape shape, final Runnable action); /** - * Traverses through the graph and apply {@link Visitor1#visit(Shape)} for each, stop if it returns true. + * Traverses through the graph and apply {@link Visitor1#visit(Shape)} for each {@link Shape} of {@link Container#getShapes()}, + * stops 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 */ boolean forAll(Visitor1 v); /** - * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each, stop if it returns true. + * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each {@link Shape} of {@link Container#getShapes()}, + * stops if it returns true. * @param pmv * @param v * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false @@ -120,7 +175,8 @@ public interface Container { boolean forAll(final PMVMatrix4f pmv, Visitor2 v); /** - * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each, stop if it returns true. + * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each {@link Shape} of {@link Container#getShapes()}, + * stops if it returns true. * * Each {@link Container} level is sorted using {@code sortComp} * @param sortComp @@ -129,4 +185,17 @@ public interface Container { * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false */ boolean forSortedAll(final Comparator<Shape> sortComp, final PMVMatrix4f pmv, final Visitor2 v); -}
\ No newline at end of file + + /** + * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each {@link Shape} of {@link Container#getRenderedShapes()}, + * stops if it returns true. + * <p> + * Each {@link Container} level is sorted using {@code sortComp} + * </p> + * @param sortComp + * @param pmv + * @param v + * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false + */ + public boolean forAllRendered(final Comparator<Shape> sortComp, final PMVMatrix4f pmv, final Visitor2 v); +} diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java index af07d4053..391c0170b 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Group.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java @@ -82,6 +82,9 @@ public class Group extends Shape implements Container { private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>(); private Shape[] drawShapeArray = new Shape[0]; // reduce memory re-alloc @ display + private final List<Shape> renderedShapesB0 = new ArrayList<Shape>(); + private final List<Shape> renderedShapesB1 = new ArrayList<Shape>(); + private volatile List<Shape> renderedShapes = renderedShapesB1; /** Enforced fixed size. In case z-axis is NaN, its 3D z-axis will be adjusted. */ private final Vec3f fixedSize = new Vec3f(); private Layout layouter; @@ -151,7 +154,7 @@ public class Group extends Shape implements Container { public Group setFixedSize(final Vec3f v) { fixedSize.set(v); return this; } /** * Enforce size of this group to given 2 dimensions, - * adjusting the 3D z-axis {@link #getBounds()} giving room for potential clipping via {@link #setClipOnBounds(boolean)} or {@link #setClipFrustum(Frustum)}. + * adjusting the 3D z-axis {@link #getBounds()} giving room for potential clipping via {@link #setClipOnBounds(boolean)} or {@link #setClipMvFrustum(Frustum)}. * @see #setFixedSize(Vec3f) */ public Group setFixedSize(final Vec2f v) { fixedSize.set(v.x(), v.y(), Float.NaN); return this; } @@ -161,13 +164,13 @@ public class Group extends Shape implements Container { public Vec2f getFixedSize(final Vec2f out) { out.set(fixedSize.x(), fixedSize.y()); return out; } /** - * Enable {@link Frustum} clipping on {@link #getBounds()} for this group and its shapes as follows + * Enable Modelview (Mv) {@link Frustum} clipping on {@link #getBounds()} for this group and its shapes as follows * <ul> * <li>Discard {@link Shape} {@link #draw(GL2ES2, RegionRenderer) rendering} if not intersecting {@code clip-box}.</li> * <li>Otherwise perform pixel-accurate clipping inside the shader to {@code clip-box}.</li> * </ul> * <p> - * {@link #setClipFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. + * {@link #setClipMvFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. * </p> * <p> * With clipping enabled, the 3D z-axis {@link #getBounds()} depth @@ -175,7 +178,7 @@ public class Group extends Shape implements Container { * </p> * @param v boolean to toggle clipping * @return this instance for chaining - * @see #setClipFrustum(Frustum) + * @see #setClipMvFrustum(Frustum) * @see #setFixedSize(Vec2f) * @see #setFixedSize(Vec3f) */ @@ -184,14 +187,14 @@ public class Group extends Shape implements Container { public boolean getClipOnBounds() { return clipOnBounds; } /** - * Enable {@link Frustum} clipping on explicit given pre-multiplied w/ Mv-matrix {@code clip-box} + * Enable Modelview (Mv) {@link Frustum} clipping on explicit given pre-multiplied w/ Mv-matrix {@code clip-box} * for this group and its shapes as follows * <ul> * <li>Discard {@link Shape} {@link #draw(GL2ES2, RegionRenderer) rendering} if not intersecting {@code clip-box}.</li> * <li>Otherwise perform pixel-accurate clipping inside the shader to {@code clip-box}.</li> * </ul> * <p> - * {@link #setClipFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. + * {@link #setClipMvFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. * </p> * <p> * With clipping enabled, the 3D z-axis {@link #getBounds()} depth @@ -203,9 +206,9 @@ public class Group extends Shape implements Container { * @see #setFixedSize(Vec2f) * @see #setFixedSize(Vec3f) */ - public Group setClipFrustum(final Frustum v) { clipFrustum = v; return this; } - /** Returns {@link #setClipFrustum(Frustum)} value */ - public Frustum getClipFrustum() { return clipFrustum; } + public Group setClipMvFrustum(final Frustum v) { clipFrustum = v; return this; } + /** Returns {@link #setClipMvFrustum(Frustum)} value */ + public Frustum getClipMvFrustum() { return clipFrustum; } @Override public int getShapeCount() { return shapes.size(); } @@ -214,6 +217,9 @@ public class Group extends Shape implements Container { public List<Shape> getShapes() { return shapes; } @Override + public List<Shape> getRenderedShapes() { return renderedShapes; } + + @Override public void addShape(final Shape s) { shapes.add(s); s.setParent(this); @@ -305,6 +311,8 @@ public class Group extends Shape implements Container { } shapes.clear(); drawShapeArray = new Shape[0]; + renderedShapesB0.clear(); + renderedShapesB1.clear(); } @Override @@ -315,6 +323,8 @@ public class Group extends Shape implements Container { } shapes.clear(); drawShapeArray = new Shape[0]; + renderedShapesB0.clear(); + renderedShapesB1.clear(); if( null != border ) { border.destroy(gl, renderer); border = null; @@ -324,10 +334,61 @@ public class Group extends Shape implements Container { private boolean doFrustumCulling = false; @Override - public final void setFrustumCullingEnabled(final boolean v) { doFrustumCulling = v; } + public final void setPMvCullingEnabled(final boolean v) { doFrustumCulling = v; } + + @Override + public final boolean isPMvCullingEnabled() { return doFrustumCulling; } @Override - public final boolean isFrustumCullingEnabled() { return doFrustumCulling; } + public final boolean isCullingEnabled() { return doFrustumCulling || clipOnBounds || null != clipFrustum; } + + @Override + public final boolean isOutside(final PMVMatrix4f pmv, final Shape shape) { + final AABBox shapeBox = shape.getBounds(); + final boolean useClipFrustum = null != clipFrustum; + if( useClipFrustum || clipOnBounds ) { + final Frustum frustumMv = useClipFrustum ? clipFrustum : tempC00.set( box ).transform( pmv.getMv() ).updateFrustumPlanes(tempF00); + pmv.pushMv(); + shape.applyMatToMv(pmv); + final boolean res; + if( doFrustumCulling && pmv.getFrustum().isOutside( shapeBox ) ) { + res = true; + } else { + final Cube shapeMv = tempC01.set( shapeBox ).transform( pmv.getMv() ); + res = frustumMv.isOutside( shapeMv ); + } + pmv.popMv(); + return res; + } else if( doFrustumCulling ){ + pmv.pushMv(); + shape.applyMatToMv(pmv); + final boolean res = pmv.getFrustum().isOutside( shapeBox ); + pmv.popMv(); + return res; + } else { + return false; + } + } + @Override + public boolean isOutside2(final Matrix4f mvCont, final Shape shape, final PMVMatrix4f pmvShape) { + final AABBox shapeBox = shape.getBounds(); + final boolean useClipFrustum = null != clipFrustum; + if( useClipFrustum || clipOnBounds ) { + final Frustum frustumMv = useClipFrustum ? clipFrustum : tempC00.set( box ).transform( mvCont ).updateFrustumPlanes(tempF00); + final boolean res; + if( doFrustumCulling && pmvShape.getFrustum().isOutside( shapeBox ) ) { + res = true; + } else { + final Cube shapeMv = tempC01.set( shapeBox ).transform( pmvShape.getMv() ); + res = frustumMv.isOutside( shapeMv ); + } + return res; + } else if( doFrustumCulling ){ + return pmvShape.getFrustum().isOutside( shapeBox ); + } else { + return false; + } + } @Override protected void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final Vec4f rgba) { @@ -338,6 +399,9 @@ public class Group extends Shape implements Container { drawShapeArray = shapeArray; // keep backup Arrays.sort(shapeArray, 0, shapeCount, Shape.ZAscendingComparator); + final List<Shape> iShapes = renderedShapes == renderedShapesB0 ? renderedShapesB1 : renderedShapesB0; + iShapes.clear(); + final boolean useClipFrustum = null != clipFrustum; if( useClipFrustum || clipOnBounds ) { final Frustum origClipFrustum = renderer.getClipFrustum(); @@ -358,6 +422,7 @@ public class Group extends Shape implements Container { ( !doFrustumCulling || !pmv.getFrustum().isOutside( shapeBox ) ) ) { shape.draw(gl, renderer); + iShapes.add(shape); } pmv.popMv(); } @@ -371,11 +436,13 @@ public class Group extends Shape implements Container { shape.applyMatToMv(pmv); if( !doFrustumCulling || !pmv.getFrustum().isOutside( shape.getBounds() ) ) { shape.draw(gl, renderer); + iShapes.add(shape); } pmv.popMv(); } } } + renderedShapes = iShapes; if( null != border ) { border.draw(gl, renderer); } @@ -594,7 +661,7 @@ public class Group extends Shape implements Container { @Override public boolean contains(final Shape s) { - return TreeTool.contains(shapes, s); + return TreeTool.contains(this, s); } @Override public Shape getShapeByIdx(final int id) { @@ -605,11 +672,11 @@ public class Group extends Shape implements Container { } @Override public Shape getShapeByID(final int id) { - return TreeTool.getShapeByID(shapes, id); + return TreeTool.getShapeByID(this, id); } @Override public Shape getShapeByName(final String name) { - return TreeTool.getShapeByName(shapes, name); + return TreeTool.getShapeByName(this, name); } @Override @@ -633,22 +700,27 @@ public class Group extends Shape implements Container { @Override public boolean forOne(final PMVMatrix4f pmv, final Shape shape, final Runnable action) { - return TreeTool.forOne(shapes, pmv, shape, action); + return TreeTool.forOne(this, pmv, shape, action); } @Override public boolean forAll(final Visitor1 v) { - return TreeTool.forAll(shapes, v); + return TreeTool.forAll(this, v); } @Override public boolean forAll(final PMVMatrix4f pmv, final Visitor2 v) { - return TreeTool.forAll(shapes, pmv, v); + return TreeTool.forAll(this, pmv, v); } @Override public boolean forSortedAll(final Comparator<Shape> sortComp, final PMVMatrix4f pmv, final Visitor2 v) { - return TreeTool.forSortedAll(sortComp, shapes, pmv, v); + return TreeTool.forSortedAll(this, sortComp, pmv, v); + } + + @Override + public boolean forAllRendered(final Comparator<Shape> sortComp, final PMVMatrix4f pmv, final Visitor2 v) { + return TreeTool.forAllRendered(this, pmv, v); } } diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java index b3ae5c9a0..45f406ea0 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java @@ -131,6 +131,9 @@ public final class Scene implements Container, GLEventListener { private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>(); private Shape[] displayShapeArray = new Shape[0]; // reduce memory re-alloc @ display + private final List<Shape> renderedShapesB0 = new ArrayList<Shape>(); + private final List<Shape> renderedShapesB1 = new ArrayList<Shape>(); + private volatile List<Shape> renderedShapes = renderedShapesB1; private final AtomicReference<Tooltip> toolTipActive = new AtomicReference<Tooltip>(); private final AtomicReference<Shape> toolTipHUD = new AtomicReference<Shape>(); @@ -219,10 +222,13 @@ public final class Scene implements Container, GLEventListener { public final int getClearMask() { return clearMask; } @Override - public final void setFrustumCullingEnabled(final boolean v) { doFrustumCulling = v; } + public final void setPMvCullingEnabled(final boolean v) { doFrustumCulling = v; } @Override - public final boolean isFrustumCullingEnabled() { return doFrustumCulling; } + public final boolean isPMvCullingEnabled() { return doFrustumCulling; } + + @Override + public final boolean isCullingEnabled() { return doFrustumCulling; } public synchronized void attachGLAutoDrawable(final GLAutoDrawable drawable) { cDrawable = drawable; @@ -270,6 +276,9 @@ public final class Scene implements Container, GLEventListener { public List<Shape> getShapes() { return shapes; } @Override + public List<Shape> getRenderedShapes() { return renderedShapes; } + + @Override public void addShape(final Shape s) { shapes.add(s); } @@ -334,7 +343,7 @@ public final class Scene implements Container, GLEventListener { @Override public boolean contains(final Shape s) { - return TreeTool.contains(shapes, s); + return TreeTool.contains(this, s); } @Override public Shape getShapeByIdx(final int id) { @@ -345,11 +354,11 @@ public final class Scene implements Container, GLEventListener { } @Override public Shape getShapeByID(final int id) { - return TreeTool.getShapeByID(shapes, id); + return TreeTool.getShapeByID(this, id); } @Override public Shape getShapeByName(final String name) { - return TreeTool.getShapeByName(shapes, name); + return TreeTool.getShapeByName(this, name); } /** Returns {@link RegionRenderer#getSampleCount()}. */ @@ -448,7 +457,27 @@ public final class Scene implements Container, GLEventListener { pmvMatrixSetup.setPlaneBox(planeBox, renderer.getMatrix(), renderer.getViewport()); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public final boolean isOutside(final PMVMatrix4f pmv, final Shape shape) { + if( doFrustumCulling ){ + pmv.pushMv(); + shape.applyMatToMv(pmv); + final boolean res = pmv.getFrustum().isOutside( shape.getBounds() ); + pmv.popMv(); + return res; + } else { + return false; + } + } + @Override + public boolean isOutside2(final Matrix4f mvCont, final Shape shape, final PMVMatrix4f pmvShape) { + if( doFrustumCulling ){ + return pmvShape.getFrustum().isOutside( shape.getBounds() ); + } else { + return false; + } + } + @Override public void display(final GLAutoDrawable drawable) { final int shapeCount = shapes.size(); @@ -457,6 +486,8 @@ public final class Scene implements Container, GLEventListener { displayShapeArray = shapeArray; // keep backup Arrays.sort(shapeArray, 0, shapeCount, Shape.ZAscendingComparator); + final List<Shape> iShapes = renderedShapes == renderedShapesB0 ? renderedShapesB1 : renderedShapesB0; + iShapes.clear(); final GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -476,10 +507,12 @@ public final class Scene implements Container, GLEventListener { if( !doFrustumCulling || !pmv.getFrustum().isOutside( shape.getBounds() ) ) { shape.draw(gl, renderer); + iShapes.add(shape); } pmv.popMv(); } } + renderedShapes = iShapes; renderer.enable(gl, false); synchronized ( syncDisplayedOnce ) { displayedOnce = true; @@ -573,6 +606,8 @@ public final class Scene implements Container, GLEventListener { } shapes.clear(); displayShapeArray = new Shape[0]; + renderedShapesB0.clear(); + renderedShapesB1.clear(); disposeActions.clear(); if( drawable == cDrawable ) { cDrawable = null; @@ -622,7 +657,7 @@ public final class Scene implements Container, GLEventListener { final Ray ray = new Ray(); final Shape[] shape = { null }; final int[] shapeIdx = { -1 }; - forSortedAll(Shape.ZDescendingComparator, pmv, (final Shape s, final PMVMatrix4f pmv2) -> { + TreeTool.forAllRendered(this, pmv, (final Shape s, final PMVMatrix4f pmv2) -> { shapeIdx[0]++; final boolean ok = s.isInteractive() && pmv.mapWinToRay(glWinX, glWinY, winZ0, winZ1, viewport, ray); if( ok ) { @@ -777,7 +812,7 @@ public final class Scene implements Container, GLEventListener { */ @Override public boolean forOne(final PMVMatrix4f pmv, final Shape shape, final Runnable action) { - return TreeTool.forOne(shapes, pmv, shape, action); + return TreeTool.forOne(this, pmv, shape, action); } /** @@ -788,7 +823,7 @@ public final class Scene implements Container, GLEventListener { */ @Override public boolean forAll(final PMVMatrix4f pmv, final Visitor2 v) { - return TreeTool.forAll(shapes, pmv, v); + return TreeTool.forAll(this, pmv, v); } /** @@ -798,7 +833,7 @@ public final class Scene implements Container, GLEventListener { */ @Override public boolean forAll(final Visitor1 v) { - return TreeTool.forAll(shapes, v); + return TreeTool.forAll(this, v); } /** @@ -812,20 +847,12 @@ public final class Scene implements Container, GLEventListener { */ @Override public boolean forSortedAll(final Comparator<Shape> sortComp, final PMVMatrix4f pmv, final Visitor2 v) { - try { - return TreeTool.forSortedAll(sortComp, shapes, pmv, v); - } catch (final java.lang.IllegalArgumentException iae) { - System.err.println("Caught: "+iae.getMessage()); - System.err.println("float[] descendingZValues = { "); - for(final Shape s : shapes) { - final int thisBits = Float.floatToIntBits(s.getAdjustedZ()); - System.err.println(" Float.intBitsToFloat(0x"+Integer.toHexString(thisBits)+"),"); - } - System.err.println(" };"); - iae.printStackTrace(); - throw iae; - // return true; - } + return TreeTool.forSortedAll(this, sortComp, pmv, v); + } + + @Override + public boolean forAllRendered(final Comparator<Shape> sortComp, final PMVMatrix4f pmv, final Visitor2 v) { + return TreeTool.forAllRendered(this, pmv, v); } /** diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java index 1811d2f61..32d1402b0 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java @@ -310,13 +310,21 @@ public abstract class Shape { /** Returns true if this shape denotes a {@link Group}, otherwise false. */ public boolean isGroup() { return false; } - /** Returns true if this shape is visible, otherwise false. */ + /** + * Returns true if this shape is set {@link #setVisible(boolean) visible} by the user, otherwise false. Defaults to true. + * <p> + * Note that invisible shapes are not considered for picking/activation. + * </p> + * @see #isInteractive() + */ public final boolean isVisible() { return isIO(IO_VISIBLE); } /** - * Enable or disable this shape's visibility. + * Enable (default) or disable this shape's visibility. + * <p> + * Note that invisible shapes are not considered for picking/activation. + * </p> * <p> - * Note that invisible shapes are still considered for picking/activation. - * To completely mute the shape, issue {@link #setInteractive(boolean)} as well. + * This visibility flag is toggled by the user only. * </p> */ public final Shape setVisible(final boolean v) { return setIO(IO_VISIBLE, v); } @@ -1567,7 +1575,7 @@ public abstract class Shape { public Tooltip getTooltip() { return tooltip; } /** - * Set whether this shape is interactive, + * Set whether this shape is interactive in general, * i.e. any user interaction like * - {@link #isToggleable()} * - {@link #isDraggable()} @@ -1575,14 +1583,16 @@ public abstract class Shape { * but excluding programmatic changes. * @param v new value for {@link #isInteractive()} * @see #isInteractive() + * @see #isVisible() * @see #setDraggable(boolean) * @see #setResizable(boolean) * @see #setDragAndResizeable(boolean) */ public final Shape setInteractive(final boolean v) { return setIO(IO_INTERACTIVE, v); } /** - * Returns if this shape allows user interaction, see {@link #setInteractive(boolean)} + * Returns if this shape allows user interaction in general, see {@link #setInteractive(boolean)} * @see #setInteractive(boolean) + * @see #isVisible() */ public final boolean isInteractive() { return isIO(IO_INTERACTIVE); } diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java index 4c5a6d1f0..1e6a37be4 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java @@ -115,7 +115,9 @@ public class MediaPlayer extends Widget { final float ctrlCellWidth = (aratio-2*borderSzS)/ctrlCells; final float ctrlCellHeight = ctrlCellWidth; - final float ctrlSliderHeight = ctrlCellHeight/15f; + final float ctrlSliderHeightMin = ctrlCellHeight/15f; // bar-height + final float ctrlSliderHeightMax = 3f * ctrlSliderHeightMin; // knob-height + final float infoGroupHeight = 1/7f; final Shape[] zoomReplacement = { null }; final Vec3f[] zoomOrigScale = { null }; @@ -131,11 +133,10 @@ public class MediaPlayer extends Widget { final RangeSlider ctrlSlider; { - final float knobScale = 3f; - final float knobHeight = ctrlSliderHeight * knobScale; - ctrlSlider = new RangeSlider(renderModes, new Vec2f(aratio - knobHeight, ctrlSliderHeight), knobScale, new Vec2f(0, 100), 1, 0); - final float dx = knobHeight / 2f; - final float dy = ( knobHeight - ctrlSliderHeight ) * 0.5f; + final float knobScale = ctrlSliderHeightMax / ctrlSliderHeightMin; + ctrlSlider = new RangeSlider(renderModes, new Vec2f(aratio - ctrlSliderHeightMax, ctrlSliderHeightMin), knobScale, new Vec2f(0, 100), 1, 0); + final float dx = ctrlSliderHeightMax / 2f; + final float dy = ( ctrlSliderHeightMax - ctrlSliderHeightMin ) * 0.5f; ctrlSlider.setPaddding(new Padding(0, dx, ctrlCellHeight-dy, dx)); } ctrlSlider.setName("mp.slider"); @@ -210,11 +211,10 @@ public class MediaPlayer extends Widget { infoGroup.setName("mp.info").setInteractive(false); this.addShape( infoGroup.setVisible(false) ); { - final float sz = 1/7f; - final Rectangle rect = new Rectangle(renderModes & ~Region.AA_RENDERING_MASK, aratio, sz, 0); + final Rectangle rect = new Rectangle(renderModes & ~Region.AA_RENDERING_MASK, aratio, infoGroupHeight, 0); rect.setName("mp.info.blend").setInteractive(false); rect.setColor(0, 0, 0, alphaBlend); - rect.setPaddding(new Padding(0, 0, 1f-sz, 0)); + rect.setPaddding(new Padding(0, 0, 1f-infoGroupHeight, 0)); infoGroup.addShape(rect); } { @@ -468,13 +468,6 @@ public class MediaPlayer extends Widget { this.setBorderColor(borderColorA); } else { this.setBorderColor(borderColor); - } - if( ctrlGroup.isActive() || ctrlSlider.isActive() ) { - ctrlSlider.setVisible(true); - ctrlBlend.setVisible(true); - ctrlGroup.setVisible(true); - infoGroup.setVisible(true); - } else { ctrlSlider.setVisible(false); ctrlBlend.setVisible(false); ctrlGroup.setVisible(false); @@ -483,6 +476,16 @@ public class MediaPlayer extends Widget { }); this.addMouseListener(new Shape.MouseGestureAdapter() { @Override + public void mouseMoved(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + final Vec3f p = shapeEvent.objPos; + final boolean c = ( ctrlCellHeight + ctrlSliderHeightMax ) > p.y() || p.y() > ( 1f - infoGroupHeight ); + ctrlSlider.setVisible(c); + ctrlBlend.setVisible(c); + ctrlGroup.setVisible(c); + infoGroup.setVisible(c); + } + @Override public void mouseReleased(final MouseEvent e) { mButton.setPressedColorMod(1f, 1f, 1f, 1f); } diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java index 838a39254..9143a9431 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java @@ -171,9 +171,9 @@ public class RangedGroup extends Widget { // Mv pre-multiplied Frustum, clippedContent is on same PMV final Frustum clipFrustum = tempC00.set( clippedContent.getBounds() ).transform( pmv.getMv() ).updateFrustumPlanes(tempF00); - content.setClipFrustum(clipFrustum); + content.setClipMvFrustum(clipFrustum); super.drawImpl0(gl, renderer, rgba); - content.setClipFrustum(null); + content.setClipMvFrustum(null); } } private final Frustum tempF00 = new Frustum(); // OK, synchronized |