aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Container.java3
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Group.java74
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Scene.java76
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Shape.java10
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java2
-rw-r--r--src/graphui/classes/jogamp/graph/ui/TreeTool.java1
6 files changed, 109 insertions, 57 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Container.java b/src/graphui/classes/com/jogamp/graph/ui/Container.java
index 106ffcfe9..b2a100107 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Container.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Container.java
@@ -28,16 +28,13 @@
package com.jogamp.graph.ui;
import java.util.Collection;
-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;
import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.ui.Shape.Visitor1;
/**
* Container interface of UI {@link Shape}s
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java
index c44fbe110..157881483 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Group.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java
@@ -91,7 +91,7 @@ public class Group extends Shape implements Container {
private Rectangle border = null;
private boolean relayoutOnDirtyShapes = true;
- private boolean widgetMode = false;
+ private Scene topLevelHolder = null;
private boolean clipOnBounds = false;
private Frustum clipFrustum = null;
@@ -305,8 +305,8 @@ public class Group extends Shape implements Container {
@Override
protected void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer) {
+ disableTopLevelWidget();
for(final Shape s : shapes) {
- // s.clearImpl0(gl, renderer);
s.clear(gl, renderer);
}
shapes.clear();
@@ -317,6 +317,7 @@ public class Group extends Shape implements Container {
@Override
protected void destroyImpl0(final GL2ES2 gl, final RegionRenderer renderer) {
+ disableTopLevelWidget();
for(final Shape s : shapes) {
// s.destroyImpl0(gl, renderer);
s.destroy(gl, renderer);
@@ -488,9 +489,9 @@ public class Group extends Shape implements Container {
public boolean getRelayoutOnDirtyShapes() { return relayoutOnDirtyShapes; }
/**
- * Toggles widget behavior for this group, default is disabled.
+ * Enables top-level widget behavior for this group, default is disabled.
* <p>
- * Enabled widget behavior for a group causes
+ * Enabled top-level widget behavior for a group causes
* <ul>
* <li>the whole group to be shown on top on (mouse over) activation of one of its elements</li>
* <li>this group's {@link #addActivationListener(Listener)} to handle all it's elements activation events</li>
@@ -498,52 +499,49 @@ public class Group extends Shape implements Container {
* </ul>
* </p>
* <p>
- * This method modifies all elements of this group for enabled or disabled widget behavior.
+ * This method modifies all elements of this group for enabled or disabled top-level widget behavior.
* </p>
- * @param v enable or disable
+ * <p>
+ * Disable this behavior via {@link #disableTopLevelWidget()}, otherwise done per-default
+ * at {@link #clear(GL2ES2, RegionRenderer)} or {@link #destroy(GL2ES2, RegionRenderer)}.
+ * </p>
+ * @param scene the top-level widget holder where this {@link Group} gets registered
* @return this group for chaining
+ * @see #disableTopLevelWidget()
*/
- public final Group setWidgetMode(final boolean v) {
- widgetMode = v;
- if( v ) {
- enableUniActivationImpl(true, forwardActivation);
- } else {
- enableUniActivationImpl(false, null);
+ public final Group enableTopLevelWidget(final Scene scene) {
+ topLevelHolder = scene;
+ setWidgetChilds(true, forwardActivation);
+ scene.addTopLevel(this);
+ return this;
+ }
+ /** Disables top-level widget behavior as potentially set via {@link #enableTopLevelWidget(Scene)}. NOP if not enabled. */
+ public final Group disableTopLevelWidget() {
+ final Scene tlh = topLevelHolder;
+ topLevelHolder = null;
+ if( null != tlh ) {
+ tlh.removeTopLevel(this);
+ setWidgetChilds(false, forwardActivation);
}
return this;
}
- protected final void enableUniActivationImpl(final boolean v, final Listener activationListener) {
- for(final Shape s : shapes ) {
- if( s.isGroup() ) {
- // ((Group)s).enableUniActivationImpl(v, activationListener);
- ((Group)s).setWidgetMode(v);
+ private final void setWidgetChilds(final boolean enable, final Listener fwdActivationListener) {
+ TreeTool.forAll(this, (final Shape s) -> {
+ if( enable ) {
+ s.addActivationListener(fwdActivationListener);
+ } else {
+ s.removeActivationListener(fwdActivationListener);
}
- s.addActivationListener(activationListener);
- }
+ return false;
+ });
}
- /** Returns whether {@link #setWidgetMode(boolean)} is enabled or disabled. */
- public final boolean getWidgetMode() { return widgetMode; }
+ /** Returns whether {@link #setTopLevelWidget(boolean)} is enabled or disabled. */
+ public final boolean isTopLevelWidget() { return null != topLevelHolder; }
@Override
public boolean isActive() {
- return super.isActive() || ( widgetMode && TreeTool.forAll(this, (final Shape gs) -> { return gs.isActive(); } ) );
- }
-
- @Override
- public float getAdjustedZ() {
- final float[] v = { getAdjustedZImpl() };
- if( widgetMode && !super.isActive() ) {
- TreeTool.forAll(this, (final Shape gs) -> {
- if( gs.isActive() ) {
- v[0] = gs.getAdjustedZImpl();
- return true;
- } else {
- return false;
- }
- } );
- }
- return v[0];
+ return super.isActive() || ( isTopLevelWidget() && TreeTool.forAll(this, (final Shape gs) -> { return gs.isActive(); } ) );
}
/**
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
index 31c45359d..2ae18c5f6 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
@@ -53,7 +53,6 @@ import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.ui.Shape.Visitor2;
import com.jogamp.math.FloatUtil;
import com.jogamp.math.Matrix4f;
import com.jogamp.math.Ray;
@@ -62,7 +61,6 @@ import com.jogamp.math.Vec2f;
import com.jogamp.math.Vec3f;
import com.jogamp.math.geom.AABBox;
import com.jogamp.math.util.PMVMatrix4f;
-import com.jogamp.graph.ui.Shape.Visitor1;
import com.jogamp.newt.event.GestureHandler;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
@@ -114,6 +112,8 @@ public final class Scene implements Container, GLEventListener {
public static final float DEFAULT_Z16_EPSILON = FloatUtil.getZBufferEpsilon(16 /* zBits */, DEFAULT_SCENE_DIST, DEFAULT_ZNEAR);
/** Default Z precision scale, i.e. multiple of {@link #DEFAULT_Z16_EPSILON} for {@link #setActiveShapeZOffsetScale(float)}. Value is {@value}. */
public static final float DEFAULT_ACTIVE_ZOFFSET_SCALE = 10f;
+ /** Default Z precision scale, i.e. multiple of {@link #DEFAULT_Z16_EPSILON} for {@link #setActiveShapeZOffsetScale(float)}. Value is {@value}. */
+ public static final float DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE = 100f;
/** Default Z precision on 16-bit depth buffer using {@code -1} z-position and {@link #DEFAULT_ZNEAR}. Value is {@code 1.5256461E-4}. */
// public static final float DIST1_Z16_EPSILON = FloatUtil.getZBufferEpsilon(16 /* zBits */, -1, DEFAULT_ZNEAR);
@@ -128,6 +128,7 @@ public final class Scene implements Container, GLEventListener {
}
private static final boolean DEBUG = false;
+ private static final boolean DEBUG_PICKING = DEBUG;
private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>();
private Shape[] displayShapeArray = new Shape[0]; // reduce memory re-alloc @ display
@@ -136,6 +137,7 @@ public final class Scene implements Container, GLEventListener {
private volatile List<Shape> renderedShapes = renderedShapesB1;
private final AtomicReference<Tooltip> toolTipActive = new AtomicReference<Tooltip>();
private final AtomicReference<Shape> toolTipHUD = new AtomicReference<Shape>();
+ private final List<Group> topLevel = new ArrayList<Group>();
private boolean doFrustumCulling = false;
@@ -148,6 +150,7 @@ public final class Scene implements Container, GLEventListener {
private final AABBox planeBox = new AABBox(0f, 0f, 0f, 0f, 0f, 0f);
private volatile Shape activeShape = null;
+ private volatile Group activeTopLevel = null;
private SBCMouseListener sbcMouseListener = null;
private SBCGestureListener sbcGestureListener = null;
@@ -605,6 +608,7 @@ public final class Scene implements Container, GLEventListener {
}
}
shapes.clear();
+ topLevel.clear();
displayShapeArray = new Shape[0];
renderedShapesB0.clear();
renderedShapesB1.clear();
@@ -981,27 +985,83 @@ public final class Scene implements Container, GLEventListener {
public void releaseActiveShape() {
if( null != activeShape ) {
+ if( DEBUG_PICKING ) {
+ System.err.println("ACTIVE-RELEASE: "+activeShape);
+ }
activeShape.setActive(false, 0);
activeShape = null;
+
+ final Group lastTL = activeTopLevel;
+ activeTopLevel = null;
+ if( null != lastTL ) {
+ lastTL.setZOffset(0);
+ }
}
}
private void setActiveShape(final Shape shape) {
- if( activeShape != shape && null != shape &&
- shape.setActive(true, activeZOffsetScale * getZEpsilon(16)) )
- {
- if( null != activeShape ) {
- activeShape.setActive(false, 0);
+ final Shape lastShape = activeShape;
+ if( lastShape != shape && null != shape ) {
+ final float zEpsilon = getZEpsilon(16);
+ final boolean isTopLevel = topLevel.contains(shape);
+ final float newZOffset = ( isTopLevel ? activeZOffsetScale : activeTopLevelZOffsetScale ) * zEpsilon;
+ if( shape.setActive(true, newZOffset) ) {
+ final Group lastTL = activeTopLevel;
+ final Group thisTL = isTopLevel ? (Group)shape : getTopLevelParent(shape);
+ int mode = 0;
+ if( null != lastShape && lastTL != lastShape ) {
+ lastShape.setActive(false, 0);
+ mode += 10;
+ }
+ if( lastTL != thisTL ) {
+ mode += 100;
+ if( null!=lastTL) {
+ lastTL.setZOffset(0);
+ mode += 1000;
+ }
+ if( null!=thisTL && !isTopLevel ) {
+ thisTL.setZOffset(activeTopLevelZOffsetScale * zEpsilon);
+ mode += 2000;
+ }
+ activeTopLevel = thisTL;
+ }
+
+ if( DEBUG_PICKING ) {
+ System.err.println("ACTIVE-SHAPE: NEW mode "+mode+", isTopLevel "+isTopLevel+", s 0x"+Integer.toHexString(System.identityHashCode(shape))+", "+shape);
+ System.err.println("ACTIVE-SHAPE: NEW g 0x"+Integer.toHexString(System.identityHashCode(thisTL))+", "+thisTL);
+ System.err.println("ACTIVE-SHAPE: PRE s 0x"+Integer.toHexString(System.identityHashCode(lastShape))+", "+lastShape);
+ System.err.println("ACTIVE-SHAPE: PRE g 0x"+Integer.toHexString(System.identityHashCode(lastTL))+", "+lastTL);
+ // dumpTopLevelParent();
+ }
+ mode = mode + 0; // (void)mode ;-)
+ activeShape = shape;
}
- activeShape = shape;
}
}
private float activeZOffsetScale = DEFAULT_ACTIVE_ZOFFSET_SCALE;
+ private final float activeTopLevelZOffsetScale = DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE;
/** Returns the active {@link Shape} Z-Offset scale, defaults to {@code 10.0}. */
public float getActiveShapeZOffsetScale() { return activeZOffsetScale; }
/** Sets the active {@link Shape} Z-Offset scale, defaults to {@code 10.0}. */
public void setActiveShapeZOffsetScale(final float v) { activeZOffsetScale = v; }
+ protected void addTopLevel(final Group g) { topLevel.add(g); }
+ protected void removeTopLevel(final Group g) { topLevel.add(g); }
+ private Group getTopLevelParent(final Shape s) {
+ for(final Group g : topLevel) {
+ if(g.contains(s)) {
+ return g;
+ }
+ }
+ return null;
+ }
+ @SuppressWarnings("unused")
+ private void dumpTopLevelParent() {
+ for(final Group g : topLevel) {
+ System.err.printf("TL: %s/%s, %s%n", g.getClass().getSimpleName(), g.getName(), g);
+ }
+ }
+
private final class SBCGestureListener implements GestureHandler.GestureListener {
@Override
public void gestureDetected(final GestureEvent gh) {
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java
index d7c91ed2f..c12749222 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java
@@ -1523,7 +1523,7 @@ public abstract class Shape {
} else {
rotateS = "";
}
- final String activeS = ", active["+(isIO(IO_ACTIVE) ? "SELF," : "")+(isGroup() && isActive()?"GROUP":"")+"]";
+ final String activeS = ", active["+(isIO(IO_ACTIVE) ? "SELF," : "")+(isGroup() && isActive()?"GROUP":"")+", adjZ "+getAdjustedZ()+"]";
final String ps = hasPadding() ? padding.toString()+", " : "";
final String bs = hasBorder() ? "border[l "+getBorderThickness()+", c "+getBorderColor()+"], " : "";
final String idS = -1 != id ? ", id "+id : "";
@@ -1591,7 +1591,7 @@ public abstract class Shape {
protected final boolean setActive(final boolean v, final float zOffset) {
if( isActivable() ) {
- this.zOffset = zOffset;
+ setZOffset(zOffset);
setIO(IO_ACTIVE, v);
if( !v ) {
releaseInteraction();
@@ -1619,12 +1619,10 @@ public abstract class Shape {
}
};
- public float getAdjustedZ() {
- return getAdjustedZImpl();
- }
- protected final float getAdjustedZImpl() {
+ public final float getAdjustedZ() {
return position.z() * getScale().z() + zOffset;
}
+ /* pp */ final void setZOffset(final float v) { zOffset = v; }
/**
* Set's a new {@link Tooltip} for this shape.
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 ce810b3ef..327ce76ee 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java
@@ -571,7 +571,7 @@ public class MediaPlayer extends Widget {
ctrlGroup.addShape(cs);
}
}
- this.setWidgetMode(true);
+ this.enableTopLevelWidget(scene);
this.addActivationListener( (final Shape s) -> {
if( this.isActive() ) {
diff --git a/src/graphui/classes/jogamp/graph/ui/TreeTool.java b/src/graphui/classes/jogamp/graph/ui/TreeTool.java
index d80a6c103..dcb847932 100644
--- a/src/graphui/classes/jogamp/graph/ui/TreeTool.java
+++ b/src/graphui/classes/jogamp/graph/ui/TreeTool.java
@@ -36,7 +36,6 @@ 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.math.Matrix4f;
import com.jogamp.math.util.PMVMatrix4f;
/** Generic static {@link Shape} tree traversal tools, utilized by {@link Scene} and {@link Container} implementations. */