From 55b552bb87fb1fefcf53dd7784a53d605969de96 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Tue, 28 Mar 2023 04:41:10 +0200
Subject: GraphUI: Decouple GraphShape from Shape, i.e. allow future Shape w/o
Graph/GLRegion
---
.../classes/com/jogamp/graph/ui/gl/GraphShape.java | 179 ++++++++++++
.../classes/com/jogamp/graph/ui/gl/Scene.java | 12 +-
.../classes/com/jogamp/graph/ui/gl/Shape.java | 311 +++++++++------------
.../com/jogamp/graph/ui/gl/shapes/Button.java | 10 +-
.../com/jogamp/graph/ui/gl/shapes/CrossHair.java | 6 +-
.../com/jogamp/graph/ui/gl/shapes/GLButton.java | 3 +-
.../com/jogamp/graph/ui/gl/shapes/ImageButton.java | 3 +-
.../com/jogamp/graph/ui/gl/shapes/Label.java | 32 ++-
.../com/jogamp/graph/ui/gl/shapes/MediaButton.java | 3 +-
.../com/jogamp/graph/ui/gl/shapes/Rectangle.java | 6 +-
.../com/jogamp/graph/ui/gl/shapes/RoundButton.java | 6 +-
.../jogamp/graph/ui/gl/shapes/TexSeqButton.java | 7 +-
12 files changed, 366 insertions(+), 212 deletions(-)
create mode 100644 src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java
(limited to 'src/graphui/classes/com/jogamp')
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java b/src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java
new file mode 100644
index 000000000..85037ccd4
--- /dev/null
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java
@@ -0,0 +1,179 @@
+/**
+ * Copyright 2010-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 com.jogamp.graph.ui.gl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.geom.AABBox;
+
+/**
+ * Graph based {@link GLRegion} UI {@link Shape}
+ *
+ * GraphUI is GPU based and resolution independent.
+ *
+ *
+ * GraphUI is intended to become an immediate- and retained-mode API.
+ *
+ * @see Scene
+ */
+public abstract class GraphShape extends Shape {
+ protected final Factory extends Vertex> vertexFactory;
+
+ protected final int renderModes;
+ protected GLRegion region = null;
+ protected float oshapeSharpness = OutlineShape.DEFAULT_SHARPNESS;
+ private int regionQuality = Region.MAX_QUALITY;
+ private final List dirtyRegions = new ArrayList();
+
+ public GraphShape(final int renderModes) {
+ super();
+ this.vertexFactory = OutlineShape.getDefaultVertexFactory();
+ this.renderModes = renderModes;
+ }
+
+ public final int getRenderModes() { return renderModes; }
+
+ public final int getQuality() { return regionQuality; }
+ public final void setQuality(final int q) {
+ this.regionQuality = q;
+ if( null != region ) {
+ region.setQuality(q);
+ }
+ }
+ public final void setSharpness(final float sharpness) {
+ this.oshapeSharpness = sharpness;
+ markShapeDirty();
+ }
+ public final float getSharpness() {
+ return oshapeSharpness;
+ }
+
+ @Override
+ public boolean hasColorChannel() {
+ return Region.hasColorChannel(renderModes) || Region.hasColorTexture(renderModes);
+ }
+
+ private final void clearDirtyRegions(final GL2ES2 gl) {
+ for(final GLRegion r : dirtyRegions) {
+ r.destroy(gl);
+ }
+ dirtyRegions.clear();
+ }
+
+ @Override
+ protected final void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer) {
+ clearImpl(gl, renderer);
+ clearDirtyRegions(gl);
+ if( null != region ) {
+ region.clear(gl);
+ }
+ }
+
+ @Override
+ protected final void destroyImpl0(final GL2ES2 gl, final RegionRenderer renderer) {
+ destroyImpl(gl, renderer);
+ clearDirtyRegions(gl);
+ if( null != region ) {
+ region.destroy(gl);
+ region = null;
+ }
+ }
+
+ @Override
+ protected final void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, final float[] rgba) {
+ if( null != rgba ) {
+ renderer.getRenderState().setColorStatic(rgba);
+ }
+ region.draw(gl, renderer, sampleCount);
+ }
+
+ protected GLRegion createGLRegion(final GLProfile glp) {
+ return GLRegion.create(glp, renderModes, null);
+ }
+
+ @Override
+ protected final void validateImpl(final GLProfile glp, final GL2ES2 gl) {
+ if( null != gl ) {
+ clearDirtyRegions(gl);
+ }
+ if( isShapeDirty() || null == region ) {
+ if( null == region ) {
+ region = createGLRegion(glp);
+ } else if( null == gl ) {
+ dirtyRegions.add(region);
+ region = createGLRegion(glp);
+ } else {
+ region.clear(gl);
+ }
+ addShapeToRegion();
+ region.setQuality(regionQuality);
+ } else if( isStateDirty() ) {
+ region.markStateDirty();
+ }
+ }
+
+ protected OutlineShape createDebugOutline(final OutlineShape shape, final AABBox box) {
+ final float d = 0.025f;
+ final float tw = box.getWidth() + d*2f;
+ final float th = box.getHeight() + d*2f;
+
+ final float minX = box.getMinX() - d;
+ final float minY = box.getMinY() - d;
+ final float z = 0; // box.getMinZ() + 0.025f;
+
+ // CCW!
+ shape.moveTo(minX, minY, z);
+ shape.lineTo(minX+tw, minY, z);
+ shape.lineTo(minX+tw, minY + th, z);
+ shape.lineTo(minX, minY + th, z);
+ shape.closePath();
+
+ // shape.addVertex(minX, minY, z, true);
+ // shape.addVertex(minX+tw, minY, z, true);
+ // shape.addVertex(minX+tw, minY + th, z, true);
+ // shape.addVertex(minX, minY + th, z, true);
+ // shape.closeLastOutline(true);
+
+ return shape;
+ }
+
+ protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+
+ protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+
+
+}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
index e40152a02..16f695a2f 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
@@ -246,12 +246,18 @@ public final class Scene implements GLEventListener {
public void setAllShapesQuality(final int q) {
for(int i=0; i
* A shape includes the following build-in user-interactions
* - drag shape w/ 1-pointer click, see {@link #setDraggable(boolean)}
* - resize shape w/ 1-pointer click and drag in 1/4th bottom-left and bottom-right corner, see {@link #setResizable(boolean)}.
*
*
+ * A shape is expected to have its 0/0 origin in its bottom-left corner, otherwise the drag-zoom sticky-edge will not work as expected.
+ *
+ *
* GraphUI is GPU based and resolution independent.
*
*
@@ -79,25 +75,13 @@ public abstract class Shape {
private static final int DIRTY_SHAPE = 1 << 0 ;
private static final int DIRTY_STATE = 1 << 1 ;
- protected final Factory extends Vertex> vertexFactory;
- private final int renderModes;
protected final AABBox box;
- protected final AffineTransform tempT1 = new AffineTransform();
- protected final AffineTransform tempT2 = new AffineTransform();
- protected final AffineTransform tempT3 = new AffineTransform();
- protected final AffineTransform tempT4 = new AffineTransform();
-
private final float[] position = new float[] { 0f, 0f, 0f };
private final Quaternion rotation = new Quaternion();
private final float[] rotOrigin = new float[] { 0f, 0f, 0f };
private final float[] scale = new float[] { 1f, 1f, 1f };
- protected GLRegion region = null;
- protected float oshapeSharpness = OutlineShape.DEFAULT_SHARPNESS;
- private int regionQuality = Region.MAX_QUALITY;
- private final List dirtyRegions = new ArrayList();
-
private volatile int dirty = DIRTY_SHAPE | DIRTY_STATE;
private final Object dirtySync = new Object();
@@ -122,9 +106,7 @@ public abstract class Shape {
private Listener onMoveListener = null;
- public Shape(final int renderModes) {
- this.vertexFactory = OutlineShape.getDefaultVertexFactory();
- this.renderModes = renderModes;
+ public Shape() {
this.box = new AABBox();
}
@@ -138,36 +120,27 @@ public abstract class Shape {
/** Enable or disable this shape, i.e. its visibility. */
public final void setEnabled(final boolean v) { enabled = v; }
- private final void clearDirtyRegions(final GL2ES2 gl) {
- for(final GLRegion r : dirtyRegions) {
- r.destroy(gl);
- }
- dirtyRegions.clear();
- }
-
/**
* Clears all data and reset all states as if this instance was newly created
* @param gl TODO
* @param renderer TODO
*/
public final void clear(final GL2ES2 gl, final RegionRenderer renderer) {
- clearImpl(gl, renderer);
- clearDirtyRegions(gl);
- if( null != region ) {
- region.clear(gl);
+ synchronized ( dirtySync ) {
+ clearImpl0(gl, renderer);
+ position[0] = 0f;
+ position[1] = 0f;
+ position[2] = 0f;
+ rotation.setIdentity();
+ rotOrigin[0] = 0f;
+ rotOrigin[1] = 0f;
+ rotOrigin[2] = 0f;
+ scale[0] = 1f;
+ scale[1] = 1f;
+ scale[2] = 1f;
+ box.reset();
+ markShapeDirty();
}
- position[0] = 0f;
- position[1] = 0f;
- position[2] = 0f;
- rotation.setIdentity();
- rotOrigin[0] = 0f;
- rotOrigin[1] = 0f;
- rotOrigin[2] = 0f;
- scale[0] = 1f;
- scale[1] = 1f;
- scale[2] = 1f;
- box.reset();
- markShapeDirty();
}
/**
@@ -176,12 +149,7 @@ public abstract class Shape {
* @param renderer
*/
public final void destroy(final GL2ES2 gl, final RegionRenderer renderer) {
- destroyImpl(gl, renderer);
- clearDirtyRegions(gl);
- if( null != region ) {
- region.destroy(gl);
- region = null;
- }
+ destroyImpl0(gl, renderer);
position[0] = 0f;
position[1] = 0f;
position[2] = 0f;
@@ -198,6 +166,7 @@ public abstract class Shape {
public final void onMove(final Listener l) { onMoveListener = l; }
+ /** Move to scaled position. Position ends up in PMVMatrix w/o scaling. */
public final void moveTo(final float tx, final float ty, final float tz) {
position[0] = tx;
position[1] = ty;
@@ -207,40 +176,58 @@ public abstract class Shape {
}
// System.err.println("Shape.setTranslate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
- public final void move(final float tx, final float ty, final float tz) {
- position[0] += tx;
- position[1] += ty;
- position[2] += tz;
+
+ /** Move about scaled distance. Position ends up in PMVMatrix w/o scaling. */
+ public final void move(final float dtx, final float dty, final float dtz) {
+ position[0] += dtx;
+ position[1] += dty;
+ position[2] += dtz;
if( null != onMoveListener ) {
onMoveListener.run(this);
}
// System.err.println("Shape.translate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
- /** Returns float[3] position, i.e. translation. */
+ /** Returns float[3] position, i.e. unscaled translation. */
public final float[] getPosition() { return position; }
- /** Returns float[3] rotation in degrees. */
+
+ /** Returns {@link Quaternion} for rotation. */
public final Quaternion getRotation() { return rotation; }
- public final float[] getRotationOrigin() { return rotOrigin; }
- public final void setRotationOrigin(final float rx, final float ry, final float rz) {
+ /** Return float[3] unscaled rotation origin, aka pivot. */
+ public final float[] getRotationPivot() { return rotOrigin; }
+ /** Set unscaled rotation origin, aka pivot. Usually the {@link #getBounds()} center and should be set while {@link #validateImpl(GLProfile, GL2ES2)}. */
+ public final void setRotationPivot(final float rx, final float ry, final float rz) {
rotOrigin[0] = rx;
rotOrigin[1] = ry;
rotOrigin[2] = rz;
}
+ /**
+ * Set unscaled rotation origin, aka pivot. Usually the {@link #getBounds()} center and should be set while {@link #validateImpl(GLProfile, GL2ES2)}.
+ * @param pivot float[3] rotation origin
+ */
+ public final void setRotationPivot(final float[/*3*/] pivot) {
+ System.arraycopy(pivot, 0, rotOrigin, 0, 3);
+ }
+
+ /** Set scale factor to given scale. */
public final void setScale(final float sx, final float sy, final float sz) {
scale[0] = sx;
scale[1] = sy;
scale[2] = sz;
}
+ /** Multiply current scale factor by given scale. */
public final void scale(final float sx, final float sy, final float sz) {
scale[0] *= sx;
scale[1] *= sy;
scale[2] *= sz;
}
- /** Returns float[3] scale factors */
+ /** Returns float[3] scale factors. */
public final float[] getScale() { return scale; }
+ /** Returns X-axis scale factor. */
public final float getScaleX() { return scale[0]; }
+ /** Returns Y-axis scale factor. */
public final float getScaleY() { return scale[1]; }
+ /** Returns Z-axis scale factor. */
public final float getScaleZ() { return scale[2]; }
/**
@@ -263,10 +250,10 @@ public abstract class Shape {
}
}
- private final boolean isShapeDirty() {
+ protected final boolean isShapeDirty() {
return 0 != ( dirty & DIRTY_SHAPE ) ;
}
- private final boolean isStateDirty() {
+ protected final boolean isStateDirty() {
return 0 != ( dirty & DIRTY_STATE ) ;
}
@@ -321,94 +308,72 @@ public abstract class Shape {
return box;
}
- public final int getRenderModes() { return renderModes; }
-
- public GLRegion getRegion(final GL2ES2 gl) {
- validate(gl);
- return region;
- }
-
- /** Experimental OpenGL selection draw command used by {@link Scene}. */
- public void drawGLSelect(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ /** Experimental selection draw command used by {@link Scene}. */
+ public void drawToSelect(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
synchronized ( dirtySync ) {
validate(gl);
- region.draw(gl, renderer, sampleCount);
+ drawImpl0(gl, renderer, sampleCount, null);
}
}
+ private final float[] rgba_tmp = { 0, 0, 0, 1 };
+
/**
- * Renders {@link OutlineShape} using local {@link GLRegion} which might be cached or updated.
+ * Renders the shape.
*
- * No matrix operations (translate, scale, ..) are performed.
+ * {@link #setTransform(PMVMatrix)} is expected to be completed beforehand.
*
* @param gl the current GL object
- * @param renderer the used {@link RegionRenderer}, also source of {@link RegionRenderer#getMatrix()} and {@link RegionRenderer#getViewport()}.
+ * @param renderer {@link RegionRenderer} which might be used for Graph Curve Rendering, also source of {@link RegionRenderer#getMatrix()} and {@link RegionRenderer#getViewport()}.
* @param sampleCount sample count if used by Graph renderModes
*/
public void draw(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
- final float r, g, b, a;
final boolean isPressed = isPressed(), isToggleOn = isToggleOn();
- final boolean modBaseColor = !Region.hasColorChannel( renderModes ) && !Region.hasColorTexture( renderModes );
- if( modBaseColor ) {
+ final float[] rgba;
+ if( hasColorChannel() ) {
if( isPressed ) {
- r = rgbaColor[0]*pressedRGBAModulate[0];
- g = rgbaColor[1]*pressedRGBAModulate[1];
- b = rgbaColor[2]*pressedRGBAModulate[2];
- a = rgbaColor[3]*pressedRGBAModulate[3];
+ rgba = pressedRGBAModulate;
} else if( isToggleable() ) {
if( isToggleOn ) {
- r = rgbaColor[0]*toggleOnRGBAModulate[0];
- g = rgbaColor[1]*toggleOnRGBAModulate[1];
- b = rgbaColor[2]*toggleOnRGBAModulate[2];
- a = rgbaColor[3]*toggleOnRGBAModulate[3];
+ rgba = toggleOnRGBAModulate;
} else {
- r = rgbaColor[0]*toggleOffRGBAModulate[0];
- g = rgbaColor[1]*toggleOffRGBAModulate[1];
- b = rgbaColor[2]*toggleOffRGBAModulate[2];
- a = rgbaColor[3]*toggleOffRGBAModulate[3];
+ rgba = toggleOffRGBAModulate;
}
} else {
- r = rgbaColor[0];
- g = rgbaColor[1];
- b = rgbaColor[2];
- a = rgbaColor[3];
+ rgba = rgbaColor;
}
} else {
+ rgba = rgba_tmp;
if( isPressed ) {
- r = pressedRGBAModulate[0];
- g = pressedRGBAModulate[1];
- b = pressedRGBAModulate[2];
- a = pressedRGBAModulate[3];
+ rgba[0] = rgbaColor[0]*pressedRGBAModulate[0];
+ rgba[1] = rgbaColor[1]*pressedRGBAModulate[1];
+ rgba[2] = rgbaColor[2]*pressedRGBAModulate[2];
+ rgba[3] = rgbaColor[3]*pressedRGBAModulate[3];
} else if( isToggleable() ) {
if( isToggleOn ) {
- r = toggleOnRGBAModulate[0];
- g = toggleOnRGBAModulate[1];
- b = toggleOnRGBAModulate[2];
- a = toggleOnRGBAModulate[3];
+ rgba[0] = rgbaColor[0]*toggleOnRGBAModulate[0];
+ rgba[1] = rgbaColor[1]*toggleOnRGBAModulate[1];
+ rgba[2] = rgbaColor[2]*toggleOnRGBAModulate[2];
+ rgba[3] = rgbaColor[3]*toggleOnRGBAModulate[3];
} else {
- r = toggleOffRGBAModulate[0];
- g = toggleOffRGBAModulate[1];
- b = toggleOffRGBAModulate[2];
- a = toggleOffRGBAModulate[3];
+ rgba[0] = rgbaColor[0]*toggleOffRGBAModulate[0];
+ rgba[1] = rgbaColor[1]*toggleOffRGBAModulate[1];
+ rgba[2] = rgbaColor[2]*toggleOffRGBAModulate[2];
+ rgba[3] = rgbaColor[3]*toggleOffRGBAModulate[3];
}
} else {
- r = rgbaColor[0];
- g = rgbaColor[1];
- b = rgbaColor[2];
- a = rgbaColor[3];
+ rgba[0] = rgbaColor[0];
+ rgba[1] = rgbaColor[1];
+ rgba[2] = rgbaColor[2];
+ rgba[3] = rgbaColor[3];
}
}
- renderer.getRenderState().setColorStatic(r, g, b, a);
synchronized ( dirtySync ) {
validate(gl);
- region.draw(gl, renderer, sampleCount);
+ drawImpl0(gl, renderer, sampleCount, rgba);
}
}
- protected GLRegion createGLRegion(final GLProfile glp) {
- return GLRegion.create(glp, renderModes, null);
- }
-
/**
* Validates the shape's underlying {@link GLRegion}.
*
@@ -418,8 +383,15 @@ public abstract class Shape {
* @see #validate(GLProfile)
*/
public final void validate(final GL2ES2 gl) {
- validateImpl(gl.getGLProfile(), gl);
+ synchronized ( dirtySync ) {
+ if( isShapeDirty() ) {
+ box.reset();
+ }
+ validateImpl(gl.getGLProfile(), gl);
+ dirty = 0;
+ }
}
+
/**
* Validates the shape's underlying {@link GLRegion} w/o a current {@link GL2ES2} object
*
@@ -429,30 +401,12 @@ public abstract class Shape {
* @see #validate(GL2ES2)
*/
public final void validate(final GLProfile glp) {
- validateImpl(glp, null);
- }
- private final void validateImpl(final GLProfile glp, final GL2ES2 gl) {
synchronized ( dirtySync ) {
- if( null != gl ) {
- clearDirtyRegions(gl);
- }
- if( isShapeDirty() || null == region ) {
+ if( isShapeDirty() ) {
box.reset();
- if( null == region ) {
- region = createGLRegion(glp);
- } else if( null == gl ) {
- dirtyRegions.add(region);
- region = createGLRegion(glp);
- } else {
- region.clear(gl);
- }
- addShapeToRegion();
- region.setQuality(regionQuality);
- dirty &= ~(DIRTY_SHAPE|DIRTY_STATE);
- } else if( isStateDirty() ) {
- region.markStateDirty();
- dirty &= ~DIRTY_STATE;
}
+ validateImpl(glp, null);
+ dirty = 0;
}
}
@@ -769,21 +723,6 @@ public abstract class Shape {
return rgbaColor;
}
- public final int getQuality() { return regionQuality; }
- public final void setQuality(final int q) {
- this.regionQuality = q;
- if( null != region ) {
- region.setQuality(q);
- }
- }
- public final void setSharpness(final float sharpness) {
- this.oshapeSharpness = sharpness;
- markShapeDirty();
- }
- public final float getSharpness() {
- return oshapeSharpness;
- }
-
/**
* Set base color.
*
@@ -842,9 +781,27 @@ public abstract class Shape {
}
public String getSubString() {
+ final String pivotS;
+ if( !VectorUtil.isVec3Zero(rotOrigin, 0, FloatUtil.EPSILON) ) {
+ pivotS = "pivot["+rotOrigin[0]+", "+rotOrigin[1]+", "+rotOrigin[2]+"], ";
+ } else {
+ pivotS = "";
+ }
+ final String scaleS;
+ if( !VectorUtil.isVec3Equal(scale, 0, VectorUtil.VEC3_ONE, 0, FloatUtil.EPSILON) ) {
+ scaleS = "scale["+scale[0]+", "+scale[1]+", "+scale[2]+"], ";
+ } else {
+ scaleS = "scale 1, ";
+ }
+ final String rotateS;
+ if( !rotation.isIdentity() ) {
+ rotateS = "rot "+rotation+", ";
+ } else {
+ rotateS = "";
+ }
return "enabled "+enabled+", toggle[able "+toggleable+", state "+toggle+"], pos["+position[0]+", "+position[1]+", "+position[2]+
- "], scale["+scale[0]+", "+scale[1]+", "+scale[2]+
- "], box "+box;
+ "], "+pivotS+scaleS+rotateS+
+ "box "+box;
}
//
@@ -1187,39 +1144,25 @@ public abstract class Shape {
//
//
- protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+ protected abstract void validateImpl(final GLProfile glp, final GL2ES2 gl);
+
+ protected abstract void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, float[] rgba);
+
+ protected abstract void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer);
- protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+ protected abstract void destroyImpl0(final GL2ES2 gl, final RegionRenderer renderer);
protected abstract void addShapeToRegion();
+ /**
+ * Returns true if implementation uses an extra color channel or texture
+ * which will be modulated with the passed rgba color {@link #drawImpl0(GL2ES2, RegionRenderer, int[], float[])}.
+ *
+ * Otherwise the base color will be modulated and passed to {@link #drawImpl0(GL2ES2, RegionRenderer, int[], float[])}.
+ */
+ public abstract boolean hasColorChannel();
+
//
//
//
-
- protected OutlineShape createDebugOutline(final OutlineShape shape, final AABBox box) {
- final float d = 0.025f;
- final float tw = box.getWidth() + d*2f;
- final float th = box.getHeight() + d*2f;
-
- final float minX = box.getMinX() - d;
- final float minY = box.getMinY() - d;
- final float z = 0; // box.getMinZ() + 0.025f;
-
- // CCW!
- shape.moveTo(minX, minY, z);
- shape.lineTo(minX+tw, minY, z);
- shape.lineTo(minX+tw, minY + th, z);
- shape.lineTo(minX, minY + th, z);
- shape.closePath();
-
- // shape.addVertex(minX, minY, z, true);
- // shape.addVertex(minX+tw, minY, z, true);
- // shape.addVertex(minX+tw, minY + th, z, true);
- // shape.addVertex(minX, minY + th, z, true);
- // shape.closeLastOutline(true);
-
- return shape;
- }
-
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java
index 88d6f04c7..90cd11b71 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java
@@ -33,12 +33,14 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.math.geom.AABBox;
import jogamp.graph.ui.shapes.Label0;
/**
- * A GraphUI text labeled {@link RoundButton} {@link Shape}
+ * A GraphUI text labeled {@link RoundButton} {@link GraphShape}
*
* GraphUI is GPU based and resolution independent.
*
@@ -60,6 +62,10 @@ public class Button extends RoundButton {
private float spacingX = DEFAULT_SPACING_X;
private float spacingY = DEFAULT_SPACING_Y;
+ private final AffineTransform tempT1 = new AffineTransform();
+ private final AffineTransform tempT2 = new AffineTransform();
+ private final AffineTransform tempT3 = new AffineTransform();
+
public Button(final int renderModes, final Font labelFont,
final String labelText, final float width,
final float height) {
@@ -126,7 +132,7 @@ public class Button extends RoundButton {
System.err.printf("Button.X: lbox2 %s%n", lbox2);
}
- setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+ setRotationPivot( ctr );
if( DRAW_DEBUG_BOX ) {
System.err.println("XXX.Button: Added Shape: "+shape+", "+box);
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java
index e8ec28d36..534e6fc7b 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java
@@ -28,15 +28,15 @@
package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * A GraphUI Crosshair {@link Shape}
+ * A GraphUI Crosshair {@link GraphShape}
*
* GraphUI is GPU based and resolution independent.
*
*/
-public class CrossHair extends Shape {
+public class CrossHair extends GraphShape {
private float width, height, lineWidth;
public CrossHair(final int renderModes, final float width, final float height, final float linewidth) {
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java
index 0d51ff09b..5fdb7991b 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java
@@ -37,12 +37,13 @@ import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.texture.ImageSequence;
import com.jogamp.opengl.util.texture.Texture;
/**
- * A GraphUI {@link GLEventListener} based {@link TexSeqButton} {@link Shape}.
+ * A GraphUI {@link GLEventListener} based {@link TexSeqButton} {@link GraphShape}.
*
* GraphUI is GPU based and resolution independent.
*
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java
index bbc4975bf..d5718d98a 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java
@@ -29,10 +29,11 @@ package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.util.texture.ImageSequence;
/**
- * A GraphUI {@link ImageSequence} based {@link TexSeqButton} {@link Shape}.
+ * A GraphUI {@link ImageSequence} based {@link TexSeqButton} {@link GraphShape}.
*
* GraphUI is GPU based and resolution independent.
*
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java
index 65371875d..cad8689ec 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java
@@ -29,6 +29,7 @@ package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.opengl.GLRegion;
@@ -36,21 +37,25 @@ import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.Font.Glyph;
import com.jogamp.graph.geom.plane.AffineTransform;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * A GraphUI text label {@link Shape}
+ * A GraphUI text label {@link GraphShape}
*
* GraphUI is GPU based and resolution independent.
*
*/
-public class Label extends Shape {
- protected Font font;
- protected float fontScale;
- protected String text;
+public class Label extends GraphShape {
+ private Font font;
+ private float fontScale;
+ private String text;
+
+ private final AffineTransform tempT1 = new AffineTransform();
+ private final AffineTransform tempT2 = new AffineTransform();
+ private final AffineTransform tempT3 = new AffineTransform();
/**
- * Label ctor
+ * Label ctor using a separate {@code fontScale} to scale the em-sized type glyphs
* @param renderModes region renderModes
* @param font the font
* @param fontScale font-scale factor, by which the em-sized type glyphs shall be scaled
@@ -63,6 +68,19 @@ public class Label extends Shape {
this.text = text;
}
+ /**
+ * Label ctor using em-size type glyphs
+ * @param renderModes region renderModes
+ * @param font the font
+ * @param text the text to render
+ */
+ public Label(final int renderModes, final Font font, final String text) {
+ super(renderModes);
+ this.font = font;
+ this.fontScale = 1f;
+ this.text = text;
+ }
+
/** Return the text to be rendered. */
public String getText() {
return text;
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java
index 8f9ccda3e..6b26c58b8 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java
@@ -30,13 +30,14 @@ package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.common.util.InterruptSource;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
/**
- * A GraphUI {@link GLMediaPlayer} based {@link TexSeqButton} {@link Shape}.
+ * A GraphUI {@link GLMediaPlayer} based {@link TexSeqButton} {@link GraphShape}.
*
* GraphUI is GPU based and resolution independent.
*
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java
index f027d92bc..4a8c29f2a 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java
@@ -28,15 +28,15 @@
package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * A GraphUI Rectangle {@link Shape}
+ * A GraphUI Rectangle {@link GraphShape}
*
* GraphUI is GPU based and resolution independent.
*
*/
-public class Rectangle extends Shape {
+public class Rectangle extends GraphShape {
private float width, height, lineWidth;
public Rectangle(final int renderModes, final float width, final float height, final float linewidth) {
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java
index 8dde441d9..93ba4f0dc 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java
@@ -28,10 +28,10 @@
package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * An abstract GraphUI round Button {@link Shape}
+ * An abstract GraphUI round Button {@link GraphShape}
*
* GraphUI is GPU based and resolution independent.
*
@@ -40,7 +40,7 @@ import com.jogamp.graph.ui.gl.Shape;
* To render it rectangular, {@link #setCorner(float)} to zero.
*
*/
-public abstract class RoundButton extends Shape {
+public abstract class RoundButton extends GraphShape {
/** {@value} */
public static final float DEFAULT_CORNER = 1f;
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java
index 19d9a228a..5afe1c373 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java
@@ -31,11 +31,11 @@ import com.jogamp.opengl.GLProfile;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.util.texture.TextureSequence;
/**
- * An abstract GraphUI {@link TextureSequence} {@link RoundButton} {@link Shape}.
+ * An abstract GraphUI {@link TextureSequence} {@link RoundButton} {@link GraphShape}.
*
* GraphUI is GPU based and resolution independent.
*
@@ -73,8 +73,7 @@ public abstract class TexSeqButton extends RoundButton {
region.addOutlineShape(shape, null, rgbaColor);
box.resize(shape.getBounds());
- final float[] ctr = box.getCenter();
- setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+ setRotationPivot( box.getCenter() );
if( DRAW_DEBUG_BOX ) {
System.err.println("XXX.UIShape.TextureSeqButton: Added Shape: "+shape+", "+box);
--
cgit v1.2.3