aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/Region.java48
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java6
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java83
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java62
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java57
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java45
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl8
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl14
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp3
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java243
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java4
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java3
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java343
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureButton.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java244
21 files changed, 827 insertions, 377 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java
index 230fa324d..45ad20f1b 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/Region.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java
@@ -105,9 +105,12 @@ public abstract class Region {
public static final int DEFAULT_TWO_PASS_TEXTURE_UNIT = 0;
+ protected static final int DIRTY_SHAPE = 1 << 0 ;
+ protected static final int DIRTY_STATE = 1 << 1 ;
+
private final int renderModes;
private int quality;
- private boolean dirty = true;
+ private int dirty = DIRTY_SHAPE | DIRTY_STATE;
private int numVertices = 0;
protected final AABBox box = new AABBox();
protected Frustum frustum = null;
@@ -187,7 +190,7 @@ public abstract class Region {
public final void setQuality(int q) { quality=q; }
protected void clearImpl() {
- dirty = true;
+ dirty = DIRTY_SHAPE | DIRTY_STATE;
numVertices = 0;
box.reset();
}
@@ -356,7 +359,7 @@ public abstract class Region {
// int vertsDupCountV = 0, vertsDupCountT = 0;
System.err.println("Region.addOutlineShape().X: box "+box);
}
- setDirty(true);
+ markShapeDirty();
}
public final void addOutlineShapes(final List<OutlineShape> shapes, final AffineTransform transform, final float[] rgbaColor) {
@@ -371,32 +374,35 @@ public abstract class Region {
}
/**
- * Check if this region is dirty. A region is marked dirty when new
- * Vertices, Triangles, and or Lines are added after a call to update().
- * <p>
- * A region is also dirty if other render attributes or parameters are changed!
- * </p>
- *
- * @return true if region is Dirty, false otherwise
- *
- * @see update(GL2ES2)
+ * Mark this region's shape dirty, i.e. it's
+ * Vertices, Triangles, and or Lines changed.
*/
- public final boolean isDirty() {
- return dirty;
+ public final void markShapeDirty() {
+ dirty |= DIRTY_SHAPE;
+ }
+ /** Returns true if this region's shape are dirty, see {@link #markShapeDirty()}. */
+ public final boolean isShapeDirty() {
+ return 0 != ( dirty & DIRTY_SHAPE ) ;
}
-
/**
- * See {@link #isDirty()}.
+ * Mark this region's state dirty, i.e.
+ * it's render attributes or parameters changed.
*/
- protected final void setDirty(boolean v) {
- dirty = v;
+ public final void markStateDirty() {
+ dirty |= DIRTY_STATE;
+ }
+ /** Returns true if this region's state is dirty, see {@link #markStateDirty()}. */
+ public final boolean isStateDirty() {
+ return 0 != ( dirty & DIRTY_STATE ) ;
}
+
/**
- * See {@link #isDirty()}.
+ * See {@link #markShapeDirty()} and {@link #markStateDirty()}.
*/
- public final void markDirty() {
- dirty = true;
+ protected final void clearDirtyBits(int v) {
+ dirty &= ~v;
}
+ protected final int getDirtyBits() { return dirty; }
public String toString() {
return "Region["+getRenderModeString(this.renderModes)+", q "+quality+", dirty "+dirty+", vertices "+numVertices+", box "+box+"]";
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
index 3c6045a1f..49c1944b1 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
@@ -83,7 +83,7 @@ public abstract class GLRegion extends Region {
/**
* Updates a graph region by updating the ogl related
- * objects for use in rendering if {@link #isDirty()}.
+ * objects for use in rendering if {@link #isShapeDirty()}.
* <p>Allocates the ogl related data and initializes it the 1st time.<p>
* <p>Called by {@link #draw(GL2ES2, RenderState, int, int, int)}.</p>
*/
@@ -139,11 +139,11 @@ public abstract class GLRegion extends Region {
* @see RegionRenderer#enable(GL2ES2, boolean)
*/
public final void draw(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount) {
- if(isDirty()) {
+ if( isShapeDirty() ) {
updateImpl(gl);
- setDirty(false);
}
drawImpl(gl, renderer, sampleCount);
+ clearDirtyBits(DIRTY_SHAPE|DIRTY_STATE);
}
protected abstract void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount);
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
index 7337aca36..a0a318a49 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
@@ -32,15 +32,19 @@ import java.util.Iterator;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLES2;
import javax.media.opengl.GLException;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import jogamp.graph.curve.opengl.shader.AttributeNames;
+import jogamp.graph.curve.opengl.shader.UniformNames;
import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.texture.TextureSequence;
import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.graph.curve.Region;
@@ -65,10 +69,12 @@ public class RegionRenderer {
/**
* Default {@link GL#GL_BLEND} <i>enable</i> {@link GLCallback},
- * turning on the {@link GL#GL_BLEND} state and setting up
- * {@link GL#glBlendFunc(int, int) glBlendFunc}({@link GL#GL_SRC_ALPHA}, {@link GL#GL_ONE_MINUS_SRC_ALPHA}).
+ * turning-off depth writing via {@link GL#glDepthMask(boolean)} and turning-on the {@link GL#GL_BLEND} state.
* <p>
- * Implementation also sets {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint}.
+ * Implementation also sets {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint},
+ * which will cause {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method}
+ * to set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function}
+ * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering.
* </p>
* @see #create(RenderState, GLCallback, GLCallback)
* @see #enable(GL2ES2, boolean)
@@ -76,16 +82,17 @@ public class RegionRenderer {
public static final GLCallback defaultBlendEnable = new GLCallback() {
@Override
public void run(final GL gl, final RegionRenderer renderer) {
+ gl.glDepthMask(false);
gl.glEnable(GL.GL_BLEND);
gl.glBlendEquation(GL.GL_FUNC_ADD); // default
- gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
renderer.rs.setHintMask(RenderState.BITHINT_BLENDING_ENABLED);
}
};
/**
* Default {@link GL#GL_BLEND} <i>disable</i> {@link GLCallback},
- * simply turning off the {@link GL#GL_BLEND} state.
+ * simply turning-off the {@link GL#GL_BLEND} state
+ * and turning-on depth writing via {@link GL#glDepthMask(boolean)}.
* <p>
* Implementation also clears {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint}.
* </p>
@@ -97,6 +104,7 @@ public class RegionRenderer {
public void run(final GL gl, final RegionRenderer renderer) {
renderer.rs.clearHintMask(RenderState.BITHINT_BLENDING_ENABLED);
gl.glDisable(GL.GL_BLEND);
+ gl.glDepthMask(true);
}
};
@@ -160,7 +168,7 @@ public class RegionRenderer {
* <p>Shall be called by a {@code draw()} method, e.g. {@link RegionRenderer#draw(GL2ES2, Region, int)}</p>
*
* @param gl referencing the current GLContext to which the ShaderState is bound to
- * @param renderModes TODO
+ * @param renderModes
* @throws GLException if initialization failed
*/
public final void init(final GL2ES2 gl, final int renderModes) throws GLException {
@@ -270,6 +278,8 @@ public class RegionRenderer {
private static String USE_COLOR_CHANNEL = "#define USE_COLOR_CHANNEL 1\n";
private static String USE_COLOR_TEXTURE = "#define USE_COLOR_TEXTURE 1\n";
private static String DEF_SAMPLE_COUNT = "#define SAMPLE_COUNT ";
+ private static String MAIN_BEGIN = "void main (void)\n{\n";
+ private static final String gcuTexture2D = "gcuTexture2D";
private String getVersionedShaderName() {
return "curverenderer01";
@@ -367,14 +377,16 @@ public class RegionRenderer {
* @param pass1
* @param quality
* @param sampleCount
+ * @param colorTexSeq
* @return true if a new shader program is being used and hence external uniform-data and -location,
* as well as the attribute-location must be updated, otherwise false.
*/
public final boolean useShaderProgram(final GL2ES2 gl, final int renderModes,
- final boolean pass1, final int quality, final int sampleCount) {
+ final boolean pass1, final int quality, final int sampleCount, final TextureSequence colorTexSeq) {
final ShaderModeSelector1 sel1 = pass1 ? ShaderModeSelector1.selectPass1(renderModes) :
ShaderModeSelector1.selectPass2(renderModes, quality, sampleCount);
final boolean isTwoPass = Region.isTwoPass( renderModes );
+ final boolean isPass1ColorTexSeq = pass1 && null != colorTexSeq;
final int shaderKey = sel1.ordinal() | ( HIGH_MASK & renderModes ) | ( isTwoPass ? TWO_PASS_BIT : 0 );
/**
@@ -404,15 +416,40 @@ public class RegionRenderer {
}
final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, vertexShaderName, true);
final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, versionedBaseName+"-segment-head", true);
- int posVp = rsVp.defaultShaderCustomization(gl, true, true);
+
+ int posVp = 0;
+ int posFp = 0;
+
+ if( isPass1ColorTexSeq && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) {
+ if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
+ throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
+ }
+ }
+ boolean supressGLSLVersionES30 = false;
+ if( isPass1ColorTexSeq && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) {
+ if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ supressGLSLVersionES30 = true;
+ }
+ }
+ posVp = rsVp.defaultShaderCustomization(gl, !supressGLSLVersionES30, true);
// rsFp.defaultShaderCustomization(gl, true, true);
- int posFp = rsFp.addGLSLVersion(gl);
- if( gl.isGLES2() && ! gl.isGLES3() ) {
+ posFp = supressGLSLVersionES30 ? 0 : rsFp.addGLSLVersion(gl);
+ if( isPass1ColorTexSeq ) {
+ posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getRequiredExtensionsShaderStub());
+ }
+ if( pass1 && supressGLSLVersionES30 || ( gl.isGLES2() && !gl.isGLES3() ) ) {
posFp = rsFp.insertShaderSource(0, posFp, ShaderCode.createExtensionDirective(GLExtensions.OES_standard_derivatives, ShaderCode.ENABLE));
}
- final String rsFpDefPrecision = getFragmentShaderPrecision(gl);
- if( null != rsFpDefPrecision ) {
- rsFp.insertShaderSource(0, posFp, rsFpDefPrecision);
+ if( false ) {
+ final String rsFpDefPrecision = getFragmentShaderPrecision(gl);
+ if( null != rsFpDefPrecision ) {
+ posFp = rsFp.insertShaderSource(0, posFp, rsFpDefPrecision);
+ }
+ } else {
+ posFp = rsFp.addDefaultShaderPrecision(gl, posFp);
}
if( Region.hasColorChannel( renderModes ) ) {
posVp = rsVp.insertShaderSource(0, posVp, USE_COLOR_CHANNEL);
@@ -426,20 +463,35 @@ public class RegionRenderer {
posFp = rsFp.insertShaderSource(0, posFp, DEF_SAMPLE_COUNT+sel1.sampleCount+"\n");
}
+ final String texLookupFuncName;
+ if( isPass1ColorTexSeq ) {
+ posFp = rsFp.insertShaderSource(0, posFp, "uniform "+colorTexSeq.getTextureSampler2DType()+" "+UniformNames.gcu_ColorTexUnit+";\n");
+ texLookupFuncName = colorTexSeq.getTextureLookupFunctionName(gcuTexture2D);
+ posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getTextureLookupFragmentShaderImpl());
+ } else {
+ texLookupFuncName = null;
+ }
+
+ posFp = rsFp.insertShaderSource(0, -1, MAIN_BEGIN);
+
final String passS = pass1 ? "-pass1-" : "-pass2-";
final String shaderSegment = versionedBaseName+passS+sel1.tech+sel1.sub+".glsl";
if(DEBUG) {
System.err.printf("RegionRendererImpl01.useShaderProgram.1: segment %s%n", shaderSegment);
}
try {
- posFp = rsFp.insertShaderSource(0, -1, AttributeNames.class, shaderSegment);
+ posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, shaderSegment);
} catch (IOException ioe) {
throw new RuntimeException("Failed to read: "+shaderSegment, ioe);
}
if( 0 > posFp ) {
throw new RuntimeException("Failed to read: "+shaderSegment);
}
- posFp = rsFp.insertShaderSource(0, -1, "}\n");
+ posFp = rsFp.insertShaderSource(0, posFp, "}\n");
+
+ if( isPass1ColorTexSeq ) {
+ rsFp.replaceInShaderSource(gcuTexture2D, texLookupFuncName);
+ }
sp = new ShaderProgram();
sp.add(rsVp);
@@ -461,5 +513,4 @@ public class RegionRenderer {
}
return true;
}
-
} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
index 818526cd7..7eb34a62d 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
@@ -53,9 +53,9 @@ public class RenderState {
* Shall be set via {@link #setHintMask(int)} and cleared via {@link #clearHintMask(int)}.
* </p>
* <p>
- * Due to alpha blending and multipass rendering, e.g. {@link Region#VBAA_RENDERING_BIT},
- * the clear-color shall be set to the {@link #getColorStaticUniform() foreground color} and <i>zero alpha</i>,
- * otherwise blending will amplify the scene's clear-color.
+ * If set, {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method}
+ * will set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function}
+ * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering.
* </p>
* <p>
* Shall be called by custom code, e.g. via {@link RegionRenderer}'s
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
index 33527381d..b52308e05 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
@@ -46,6 +46,7 @@ import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureSequence;
public class VBORegion2PMSAAES2 extends GLRegion {
@@ -96,7 +97,7 @@ public class VBORegion2PMSAAES2 extends GLRegion {
*/
public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) {
final RenderState rs = renderer.getRenderState();
- final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount);
+ final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq);
final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
final boolean updateLocLocal;
if( pass1 ) {
@@ -250,11 +251,22 @@ public class VBORegion2PMSAAES2 extends GLRegion {
gca_ColorsAttr.seal(gl, true);
gca_ColorsAttr.enableBuffer(gl, false);
}
- if( null != gcu_ColorTexUnit ) {
- colorTexBBox[0] = box.getMinX();
- colorTexBBox[1] = box.getMinY();
- colorTexBBox[2] = box.getMaxX();
- colorTexBBox[3] = box.getMaxY();
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+ final Texture tex = frame.getTexture();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float tcSx = 1f / ( tc.right() - tc.left() );
+ colorTexBBox[0] = box.getMinX() * tcSx;
+ colorTexBBox[2] = box.getMaxX() * tcSx;
+ if( tex.getMustFlipVertically() ) {
+ final float tcSy = 1f / ( tc.bottom() - tc.top() );
+ colorTexBBox[1] = box.getMaxY() * tcSy;
+ colorTexBBox[3] = box.getMinY() * tcSy;
+ } else {
+ final float tcSy = 1f / ( tc.top() - tc.bottom() );
+ colorTexBBox[1] = box.getMinY() * tcSy;
+ colorTexBBox[3] = box.getMaxY() * tcSy;
+ }
}
gca_FboVerticesAttr.seal(gl, false);
{
@@ -364,9 +376,8 @@ public class VBORegion2PMSAAES2 extends GLRegion {
System.err.printf("XXX.Scale %d * [%f x %f]: %d x %d%n",
sampleCount[0], winWidth, winHeight, targetFboWidth, targetFboHeight);
}
- if( hasDelta || fboDirty || null == fbo || ( fbo != null && fbo.getNumSamples() != sampleCount[0] ) ) {
+ if( hasDelta || fboDirty || isShapeDirty() || null == fbo || ( fbo != null && fbo.getNumSamples() != sampleCount[0] ) ) {
// FIXME: rescale
-
final float minX = box.getMinX()-diffObjBorderWidth;
final float minY = box.getMinY()-diffObjBorderHeight;
final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth;
@@ -384,10 +395,10 @@ public class VBORegion2PMSAAES2 extends GLRegion {
FloatUtil.makeOrthof(pmvMatrix02, 0, true, minX, maxX, minY, maxY, -1, 1);
useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount);
- } else {
- gca_FboTexCoordsAttr.setVBOWritten(false);
+ } else if( isStateDirty() ) {
+ useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+ renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount);
}
- // System.out.println("Scale: " + matrix.glGetMatrixf().get(1+4*3) +" " + matrix.glGetMatrixf().get(2+4*3));
useShaderProgram(gl, renderer, getRenderModes(), false, getQuality(), sampleCount[0]);
renderFBO(gl, rs, vpWidth, vpHeight, sampleCount[0]);
}
@@ -396,6 +407,11 @@ public class VBORegion2PMSAAES2 extends GLRegion {
private void renderFBO(final GL2ES2 gl, final RenderState rs, final int width, final int height, final int sampleCount) {
gl.glViewport(0, 0, width, height);
+ if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+ // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
fbo.use(gl, fbo.getSamplingSink());
@@ -419,6 +435,8 @@ public class VBORegion2PMSAAES2 extends GLRegion {
throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight);
}
+ final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED);
+
if(null == fbo) {
fboWidth = targetFboWidth;
fboHeight = targetFboHeight;
@@ -433,7 +451,10 @@ public class VBORegion2PMSAAES2 extends GLRegion {
// FIXME: shall not use bilinear (GL_LINEAR), due to MSAA ???
// ssink.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
ssink.attachTexture2D(gl, 0, true, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ if( !blendingEnabled ) {
+ // no depth-buffer w/ blending
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ }
}
fbo.setSamplingSink(ssink);
fbo.resetSamplingSink(gl); // validate
@@ -453,9 +474,20 @@ public class VBORegion2PMSAAES2 extends GLRegion {
//render texture
gl.glViewport(0, 0, fboWidth, fboHeight);
+ if( blendingEnabled ) {
+ gl.glClearColor(0f, 0f, 0f, 0.0f);
+ gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending
+ // For already pre-multiplied alpha values, use:
+ // gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+ // Multiply RGB w/ Alpha, preserve alpha for renderFBO(..)
+ gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
+ }
- gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
renderRegion(gl);
+
fbo.unbind(gl);
fboDirty = false;
}
@@ -468,7 +500,7 @@ public class VBORegion2PMSAAES2 extends GLRegion {
gca_ColorsAttr.enableBuffer(gl, true);
}
indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
- if( null != gcu_ColorTexUnit ) {
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
final Texture tex = frame.getTexture();
@@ -479,7 +511,7 @@ public class VBORegion2PMSAAES2 extends GLRegion {
gcu_ColorTexUnit.setData(colorTexUnit);
gl.glUniform(gcu_ColorTexUnit);
}
- gl.glUniform(gcu_ColorTexBBox); // FIXME: Only if changed!
+ gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
gl.glDrawElements(GL2ES2.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
tex.disable(gl); // nop on core
} else {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
index c623eddb7..cea292210 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
@@ -49,6 +49,7 @@ import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureSequence;
public class VBORegion2PVBAAES2 extends GLRegion {
@@ -131,7 +132,7 @@ public class VBORegion2PVBAAES2 extends GLRegion {
*/
public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) {
final RenderState rs = renderer.getRenderState();
- final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount);
+ final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq);
final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
final boolean updateLocLocal;
if( pass1 ) {
@@ -295,11 +296,22 @@ public class VBORegion2PVBAAES2 extends GLRegion {
gca_ColorsAttr.seal(gl, true);
gca_ColorsAttr.enableBuffer(gl, false);
}
- if( null != gcu_ColorTexUnit ) {
- colorTexBBox[0] = box.getMinX();
- colorTexBBox[1] = box.getMinY();
- colorTexBBox[2] = box.getMaxX();
- colorTexBBox[3] = box.getMaxY();
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+ final Texture tex = frame.getTexture();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float tcSx = 1f / ( tc.right() - tc.left() );
+ colorTexBBox[0] = box.getMinX() * tcSx;
+ colorTexBBox[2] = box.getMaxX() * tcSx;
+ if( tex.getMustFlipVertically() ) {
+ final float tcSy = 1f / ( tc.bottom() - tc.top() );
+ colorTexBBox[1] = box.getMaxY() * tcSy;
+ colorTexBBox[3] = box.getMinY() * tcSy;
+ } else {
+ final float tcSy = 1f / ( tc.top() - tc.bottom() );
+ colorTexBBox[1] = box.getMinY() * tcSy;
+ colorTexBBox[3] = box.getMaxY() * tcSy;
+ }
}
gca_FboVerticesAttr.seal(gl, false);
{
@@ -419,7 +431,7 @@ public class VBORegion2PVBAAES2 extends GLRegion {
System.err.printf("XXX.Scale %d * [%f x %f]: %d x %d%n",
sampleCount[0], winWidth, winHeight, targetFboWidth, targetFboHeight);
}
- if( hasDelta || fboDirty || null == fbo ) {
+ if( hasDelta || fboDirty || isShapeDirty() || null == fbo ) {
final int maxLength = Math.max(targetFboWidth, targetFboHeight);
if( maxLength > maxTexSize[0] ) {
if( targetFboWidth > targetFboHeight ) {
@@ -503,6 +515,9 @@ public class VBORegion2PVBAAES2 extends GLRegion {
FloatUtil.makeOrthof(pmvMatrix02, 0, true, minX, maxX, minY, maxY, -1, 1);
useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, newFboWidth, newFboHeight, vpWidth, vpHeight, sampleCount[0]);
+ } else if( isStateDirty() ) {
+ useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+ renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, fboWidth, fboHeight, vpWidth, vpHeight, sampleCount[0]);
}
useShaderProgram(gl, renderer, getRenderModes(), false, getQuality(), sampleCount[0]);
renderFBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount[0]);
@@ -513,6 +528,11 @@ public class VBORegion2PVBAAES2 extends GLRegion {
final int vpWidth, final int vpHeight, final int sampleCount) {
gl.glViewport(0, 0, vpWidth, vpHeight);
+ if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+ // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
gl.glUniform(gcu_FboTexSize);
gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
@@ -539,6 +559,8 @@ public class VBORegion2PVBAAES2 extends GLRegion {
throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight);
}
+ final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED);
+
if(null == fbo) {
fboWidth = newFboWidth;
fboHeight = newFboHeight;
@@ -553,7 +575,10 @@ public class VBORegion2PVBAAES2 extends GLRegion {
// FIXME: FXAA requires bilinear filtering!
// texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ if( !blendingEnabled ) {
+ // no depth-buffer w/ blending
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ }
if( DEBUG_FBO_1 ) {
System.err.printf("XXX.createFBO: %dx%d%n%s%n", fboWidth, fboHeight, fbo.toString());
}
@@ -576,7 +601,17 @@ public class VBORegion2PVBAAES2 extends GLRegion {
//render texture
gl.glViewport(0, 0, fboWidth, fboHeight);
- gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
+ if( blendingEnabled ) {
+ gl.glClearColor(0f, 0f, 0f, 0.0f);
+ gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending
+ // For already pre-multiplied alpha values, use:
+ // gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+ // Multiply RGB w/ Alpha, preserve alpha for renderFBO(..)
+ gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
+ }
renderRegion(gl);
@@ -593,7 +628,7 @@ public class VBORegion2PVBAAES2 extends GLRegion {
gca_ColorsAttr.enableBuffer(gl, true);
}
indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
- if( null != gcu_ColorTexUnit ) {
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
final Texture tex = frame.getTexture();
@@ -604,7 +639,7 @@ public class VBORegion2PVBAAES2 extends GLRegion {
gcu_ColorTexUnit.setData(colorTexUnit);
gl.glUniform(gcu_ColorTexUnit);
}
- gl.glUniform(gcu_ColorTexBBox); // FIXME: Only if changed!
+ gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
gl.glDrawElements(GL2ES2.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
tex.disable(gl); // nop on core
} else {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
index 0ec139a0f..24d53c1a2 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
@@ -43,6 +43,7 @@ import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureSequence;
public class VBORegionSPES2 extends GLRegion {
@@ -149,11 +150,23 @@ public class VBORegionSPES2 extends GLRegion {
gca_ColorsAttr.seal(gl, true);
gca_ColorsAttr.enableBuffer(gl, false);
}
- if( null != gcu_ColorTexUnit ) {
- colorTexBBox[0] = box.getMinX();
- colorTexBBox[1] = box.getMinY();
- colorTexBBox[2] = box.getMaxX();
- colorTexBBox[3] = box.getMaxY();
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+ final Texture tex = frame.getTexture();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float tcSx = 1f / ( tc.right() - tc.left() );
+ colorTexBBox[0] = box.getMinX() * tcSx;
+ colorTexBBox[2] = box.getMaxX() * tcSx;
+ final float tcSy;
+ if( tex.getMustFlipVertically() ) {
+ tcSy = 1f / ( tc.bottom() - tc.top() );
+ colorTexBBox[1] = box.getMaxY() * tcSy;
+ colorTexBBox[3] = box.getMinY() * tcSy;
+ } else {
+ tcSy = 1f / ( tc.top() - tc.bottom() );
+ colorTexBBox[1] = box.getMinY() * tcSy;
+ colorTexBBox[3] = box.getMaxY() * tcSy;
+ }
}
indicesBuffer.seal(gl, true);
indicesBuffer.enableBuffer(gl, false);
@@ -164,6 +177,7 @@ public class VBORegionSPES2 extends GLRegion {
}
}
+ private static final boolean throwOnError = false; // FIXME
/**
* <p>
* Since multiple {@link Region}s may share one
@@ -177,7 +191,7 @@ public class VBORegionSPES2 extends GLRegion {
*/
public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final int quality) {
final RenderState rs = renderer.getRenderState();
- final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, true, quality, 0);
+ final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, true, quality, 0, colorTexSeq);
final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
final boolean updateLocLocal = !sp.equals(spPass1);
spPass1 = sp;
@@ -185,16 +199,16 @@ public class VBORegionSPES2 extends GLRegion {
System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
}
if( updateLocLocal ) {
- rs.updateAttributeLoc(gl, true, gca_VerticesAttr, true);
- rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, true);
+ rs.updateAttributeLoc(gl, true, gca_VerticesAttr, throwOnError);
+ rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, throwOnError);
if( null != gca_ColorsAttr ) {
- rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true);
+ rs.updateAttributeLoc(gl, true, gca_ColorsAttr, throwOnError);
}
}
- rsLocal.update(gl, rs, updateLocLocal, renderModes, true, true);
+ rsLocal.update(gl, rs, updateLocLocal, renderModes, true, throwOnError);
if( null != gcu_ColorTexUnit ) {
- rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true);
- rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, true);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, throwOnError);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, throwOnError);
}
}
@@ -216,7 +230,12 @@ public class VBORegionSPES2 extends GLRegion {
gca_ColorsAttr.enableBuffer(gl, true);
}
indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
- if( null != gcu_ColorTexUnit ) {
+
+ if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+ gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
final Texture tex = frame.getTexture();
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
index 83b312a0b..447242438 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
@@ -2,9 +2,9 @@
if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
// pass-1: Lines
#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
- mgl_FragColor = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
#elif defined(USE_COLOR_TEXTURE)
- mgl_FragColor = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
#elif defined(USE_COLOR_CHANNEL)
mgl_FragColor = gcv_Color * gcu_ColorStatic;
#else
@@ -22,10 +22,10 @@
float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
- vec4 t = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a);
#elif defined(USE_COLOR_TEXTURE)
- vec4 t = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a);
#elif defined(USE_COLOR_CHANNEL)
mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
index 92f0fc07b..fa2608365 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
@@ -3,7 +3,11 @@
if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
// pass-1: Lines
-#ifdef USE_COLOR_CHANNEL
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
+#elif defined(USE_COLOR_TEXTURE)
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
+#elif defined(USE_COLOR_CHANNEL)
mgl_FragColor = gcv_Color * gcu_ColorStatic;
#else
mgl_FragColor = gcu_ColorStatic;
@@ -25,7 +29,13 @@
float position = rtex.y - (rtex.x * (1.0 - rtex.x));
float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
-#ifdef USE_COLOR_CHANNEL
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_TEXTURE)
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_CHANNEL)
mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
#else
mgl_FragColor = vec4(gcu_ColorStatic.rgb, gcu_ColorStatic.a * a);
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
index 74a1dea4e..26e2bcf24 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
@@ -17,6 +17,3 @@
#define GetSample(texUnit, texCoord, psize, cx, cy, offX, offY) texture2D(texUnit, texCoord + psize * vec2(cx+offX, cy+offY))
-void main (void)
-{
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
index ae7fa8490..cd014b732 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
@@ -7,7 +7,6 @@ uniform vec4 gcu_ColorStatic;
uniform float gcu_Weight;
#ifdef USE_COLOR_TEXTURE
- uniform sampler2D gcu_ColorTexUnit;
uniform vec4 gcu_ColorTexBBox;
#endif
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
index 5704f3e7a..ad12e11e1 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
@@ -202,7 +202,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
final int height = drawable.getHeight();
GL2ES2 gl = drawable.getGL().getGL2ES2();
- gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// final float zDistance0 = 500f;
@@ -217,9 +217,6 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
- if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
- gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- }
final float pixelSizeFName = font.getPixelSize(fontSizeFName, dpiH);
final float pixelSizeHead = font.getPixelSize(fontSizeHead, dpiH);
final float pixelSizeBottom = font.getPixelSize(fontSizeBottom, dpiH);
@@ -281,22 +278,21 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
pmv.glTranslatef(getXTran(), getYTran(), getZTran());
pmv.glRotatef(getAngle(), 0, 1, 0);
rs.setColorStatic(0.9f, 0.0f, 0.0f, 1.0f);
- if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
- gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
- }
if( bottomTextUseFrustum ) {
regionBottom.setFrustum(pmv.glGetFrustum());
}
if(!userInput) {
if( bottomTextUseFrustum ) {
- TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount(), null, null);
+ TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount(),
+ textRegionUtil.tempT1, textRegionUtil.tempT2);
} else {
textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount());
}
} else {
if( bottomTextUseFrustum ) {
- TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount(), null, null);
+ TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount(),
+ textRegionUtil.tempT1, textRegionUtil.tempT2);
} else {
textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
index f9f9d58a0..211e4c387 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
@@ -2,6 +2,8 @@ package com.jogamp.opengl.test.junit.graph.demos;
import java.io.File;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
@@ -22,8 +24,10 @@ import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.InputEvent;
-import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.PinchToZoomGesture;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
+import com.jogamp.newt.event.MouseEvent.PointerClass;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.VectorUtil;
@@ -34,8 +38,12 @@ import com.jogamp.opengl.test.junit.graph.demos.ui.RoundButton;
import com.jogamp.opengl.test.junit.graph.demos.ui.SceneUIController;
import com.jogamp.opengl.test.junit.graph.demos.ui.TextureButton;
import com.jogamp.opengl.test.junit.graph.demos.ui.UIShape;
-import com.jogamp.opengl.test.junit.jogl.demos.TextureSequenceDemo01;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
public class GPUUISceneGLListener0A implements GLEventListener {
@@ -168,7 +176,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
LabelButton button = new LabelButton(SVertex.factory(), renderModes, font, "Next Text", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart,ystart-diffY*buttons.size(), 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( null != labels[currentText] ) {
@@ -186,8 +194,8 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button.setName(100); // FIXME: DEBUG tag
button.translate(xstart,ystart - diffY*buttons.size(), 0f);
button.setToggleable(true);
- button.setToggleState(fpsLabel.isEnabled());
- button.addMouseListener(new MouseAdapter() {
+ button.setToggle(fpsLabel.isEnabled());
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final GLAnimatorControl a = cDrawable.getAnimator();
@@ -202,8 +210,8 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "v-sync", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart,ystart - diffY*buttons.size(), 0f);
button.setToggleable(true);
- button.setToggleState(gl.getSwapInterval()>0);
- button.addMouseListener(new MouseAdapter() {
+ button.setToggle(gl.getSwapInterval()>0);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
cDrawable.invoke(false, new GLRunnable() {
@@ -224,13 +232,13 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "< tilt >", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart,ystart - diffY*buttons.size(), 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
- if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
rotateButtons(new float[] { 0f, -5f, 0f}); // left-half pressed
} else {
rotateButtons(new float[] { 0f, 5f, 0f}); // right-half pressed
@@ -246,14 +254,14 @@ public class GPUUISceneGLListener0A implements GLEventListener {
if( pass2Mode ) { // second column to the left
button = new LabelButton(SVertex.factory(), renderModes, font, "< samples >", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart,ystart - diffY*buttons.size(), 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
int sampleCount = sceneUIController.getSampleCount();
- if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
// left-half pressed
if( sampleCount > 0 ) {
sampleCount-=1;
@@ -272,15 +280,15 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "< quality >", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart,ystart - diffY*buttons.size(), 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
int quality = shapeEvent.shape.getQuality();
- if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
// left-half pressed
if( quality > 0 ) {
quality--;
@@ -300,9 +308,10 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "Quit", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart,ystart - diffY*buttons.size(), 0f);
- button.setColor(0.8f, 0.0f, 0.0f, 1.0f);
- button.setSelectedColorMod(0.8f, 0.8f, 0.8f, 1.0f);
- button.addMouseListener(new MouseAdapter() {
+ button.setColor(0.7f, 0.0f, 0.0f, 1.0f);
+ button.setLabelColor(1.2f, 1.2f, 1.2f);
+ button.setPressedColorMod(1.1f, 0.0f, 0.0f, 1.0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
new Thread() {
@@ -325,7 +334,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
int k = 0; // row
button = new LabelButton(SVertex.factory(), renderModes, font, "y flip", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
rotateButtons(new float[] { 0f, 180f, 0f});
@@ -336,7 +345,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
k++;
button = new LabelButton(SVertex.factory(), renderModes, font, "x flip", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
rotateButtons(new float[] { 180f, 0f, 0f});
@@ -347,18 +356,18 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "+", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
// rel position to center
- final float dx = shapeEvent.rotPosition[0] - shapeEvent.rotBounds.getCenter()[0] ;
- final float dy = shapeEvent.rotPosition[1] - shapeEvent.rotBounds.getCenter()[1] ;
+ final float dx = shapeEvent.objPos[0] - shapeEvent.shape.getBounds().getCenter()[0] ;
+ final float dy = shapeEvent.objPos[1] - shapeEvent.shape.getBounds().getCenter()[1] ;
// per-cent position to center (remove dependency on dimension)
- final float awdx = Math.abs(dx)/shapeEvent.rotBounds.getWidth();
- final float awdy = Math.abs(dy)/shapeEvent.rotBounds.getHeight();
+ final float awdx = Math.abs(dx)/shapeEvent.shape.getBounds().getWidth();
+ final float awdy = Math.abs(dy)/shapeEvent.shape.getBounds().getHeight();
float tx = 0, ty = 0;
if ( awdx > awdy ) {
tx = dx < 0 ? -5 : 5;
@@ -374,14 +383,14 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "< space >", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
final float dx, dy;
- if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
dx=-0.01f; dy=-0.005f;
} else {
dx=0.01f; dy=0.005f;
@@ -398,14 +407,14 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "< corner >", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
final float dc;
- if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
dc=-0.1f;
} else {
dc=0.1f;
@@ -423,7 +432,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "reset", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
resetButtons();
@@ -434,7 +443,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
button = new LabelButton(SVertex.factory(), renderModes, font, "screenshot", buttonXSize, buttonYSize, labelZOffset);
button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
- button.addMouseListener(new MouseAdapter() {
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
cDrawable.invoke(false, new GLRunnable() {
@@ -451,15 +460,80 @@ public class GPUUISceneGLListener0A implements GLEventListener {
}
if(true) {
- final TextureSequenceDemo01 texSeq = new TextureSequenceDemo01(true);
- gl.glActiveTexture(GL.GL_TEXTURE0 + texSeq.getTextureUnit());
- texSeq.initGLResources(gl);
+ final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault();
final TextureButton texButton = new TextureButton(renderer.getRenderState().getVertexFactory(), renderModes,
- 2f*buttonXSize, 2f*buttonYSize, texSeq);
+ 2f*buttonXSize, 2f*buttonYSize, mPlayer) {
+ @Override
+ protected void destroyImpl(GL2ES2 gl, RegionRenderer renderer) {
+ mPlayer.destroy(gl);
+ }
+ @Override
+ public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount) {
+ if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) {
+ try {
+ System.err.println("XXX InitGL.pre: "+mPlayer);
+ mPlayer.initGL(gl);
+ mPlayer.setAudioVolume( 0f );
+ System.err.println("XXX Play.pre: "+mPlayer);
+ GLMediaPlayer.State r = mPlayer.play();
+ System.err.println("XXX Play.post: "+r+", "+mPlayer);
+ markStateDirty();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ super.drawShape(gl, renderer, sampleCount);
+ markStateDirty(); // keep on going
+ } };
+ texButton.setEnabled(false); // wait until data is avail. (shader)
texButton.translate(xstart + diffX*5, ystart - diffY*1, 0f);
texButton.setToggleable(true);
+ texButton.setToggle(false); // toggle == false -> mute audio
+ texButton.setToggleOffColorMod(0f, 1f, 0f, 1.0f);
texButton.addMouseListener(dragZoomRotateListener);
+ texButton.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ mPlayer.setAudioVolume( texButton.isToggleOn() ? 1f : 0f );
+ } } );
buttons.add(texButton);
+ mPlayer.addEventListener(new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) {
+ // texButton.markStateDirty();
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) {
+ System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCube State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ texButton.setEnabled(true); // data and shader is available ..
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ // FIXME: mPlayer.resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
+ } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) {
+ final StreamException se = mPlayer.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ }
+ }
+ });
+ try {
+ final URI streamLoc = new URI("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ mPlayer.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
}
}
@@ -613,7 +687,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
System.err.println("GPUUISceneGLListener0A: dispose (0)");
}
- sceneUIController.dispose(drawable);
+ sceneUIController.dispose(drawable); // disposes all registered UIShapes
GL2ES2 gl = drawable.getGL().getGL2ES2();
renderer.destroy(gl);
@@ -735,8 +809,8 @@ public class GPUUISceneGLListener0A implements GLEventListener {
* We can share this instance w/ all UI elements,
* since only mouse action / gesture is complete for a single one (press, drag, released and click).
*/
- private final MouseAdapter dragZoomRotateListener = new MouseAdapter() {
- int dragLastX=-1, dragLastY=-1;
+ private final UIShape.MouseGestureAdapter dragZoomRotateListener = new UIShape.MouseGestureAdapter() {
+ float dragFirstX=-1f, dragFirstY=-1f;
boolean dragFirst = false;
@Override
@@ -753,34 +827,23 @@ public class GPUUISceneGLListener0A implements GLEventListener {
@Override
public void mouseDragged(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
- if(e.getPointerCount()==2) {
- // 2 pointers zoom ..
- if(dragFirst) {
- dragLastX = Math.abs(e.getY(0)-e.getY(1));
- dragFirst=false;
- return;
- }
- int nv = Math.abs(e.getY(0)-e.getY(1));
- int dy = nv - dragLastX;
- dragLastX = nv;
-
- shapeEvent.shape.translate(0f, 0f, 2 * Math.signum(dy));
- } else {
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ if( e.getPointerCount() == 1 ) {
// 1 pointer drag
if(dragFirst) {
- dragLastX = e.getX();
- dragLastY = e.getY();
+ dragFirstX = shapeEvent.objPos[0]; // e.getX();
+ dragFirstY = shapeEvent.objPos[1]; // e.getY();
dragFirst=false;
return;
}
- final int nx = e.getX();
- final int ny = e.getY();
- shapeEvent.shape.translate(nx-dragLastX, -(ny-dragLastY), 0f);
- dragLastX = nx;
- dragLastY = ny;
- float[] tx = shapeEvent.shape.getTranslate();
+ final float nx = shapeEvent.objPos[0]; // e.getX();
+ final float ny = shapeEvent.objPos[1]; // e.getY();
+ final float dx = nx - dragFirstX;
+ final float dy = ny - dragFirstY;
+ // final float dy = -(ny - dragLastY);
+ shapeEvent.shape.translate(dx, dy, 0f);
+ final float[] tx = shapeEvent.shape.getTranslate();
actionText = String.format("Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]);
}
}
@@ -789,15 +852,37 @@ public class GPUUISceneGLListener0A implements GLEventListener {
@Override
public void mouseWheelMoved(MouseEvent e) {
final Object attachment = e.getAttachment();
- if( attachment instanceof UIShape.EventDetails ) {
- final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
- if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) ) {
- float tz = 8f*e.getRotation()[1]; // vertical: wheel
- System.err.println("tz.4 "+tz);
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass();
+ if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) {
+ // offscreen vertical mouse wheel zoom
+ final float tz = 8f*e.getRotation()[1]; // vertical: wheel
+ System.err.println("Rotate.Zoom.W: "+tz);
+ shapeEvent.shape.translate(0f, 0f, tz);
+ } else if( isOnscreen || e.isControlDown() ) {
+ final float[] rot = VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f);
+ if( isOnscreen ) {
+ System.err.println("XXX: "+e);
+ // swap axis for onscreen rotation matching natural feel
+ final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp;
+ VectorUtil.scaleVec3(rot, rot, 2f);
+ }
+ shapeEvent.shape.getRotation().rotateByEuler( rot );
+ }
+ }
+ }
+ @Override
+ public void gestureDetected(GestureEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ if( e instanceof PinchToZoomGesture.ZoomEvent ) {
+ final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e;
+ final float tz = ze.getDelta() * ze.getScale();
+ System.err.println("Rotate.Zoom.G: "+tz);
shapeEvent.shape.translate(0f, 0f, tz);
- } else if( e.isControlDown() ) {
- shapeEvent.shape.getRotation().rotateByEuler( VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f) );
}
}
- } };
+ } };
} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java
index a15e2acdd..1056bb0f9 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java
@@ -104,7 +104,7 @@ public class CrossHair extends UIShape {
}
@Override
- public String toString() {
- return "CrossHair [" + translate[0]+getWidth()/2f+" / "+translate[1]+getHeight()/2f+" "+getWidth() + "x" + getHeight() + ", "+box+"]";
+ public String getSubString() {
+ return super.getSubString()+", dim "+getWidth() + "x" + getHeight();
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java
index 37a82fe0f..175d18135 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java
@@ -110,7 +110,8 @@ public class Label extends UIShape {
}
@Override
- public String toString(){
- return "Label [" + font.toString() + ", size " + pixelSize + ", " + getText() + "]";
+ public String getSubString() {
+ final int m = Math.min(text.length(), 8);
+ return super.getSubString()+", psize " + pixelSize + ", '" + text.substring(0, m)+"'";
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java
index 336ce7526..573dd5604 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java
@@ -99,6 +99,7 @@ public class Label0 {
@Override
public final String toString(){
- return "Label0 [" + font.toString() + ", " + getText() + "]";
+ final int m = Math.min(text.length(), 8);
+ return "Label0 ['" + text.substring(0, m) + "']";
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java
index 64cf794c6..90237f56c 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java
@@ -56,9 +56,12 @@ public class LabelButton extends RoundButton {
final Font labelFont, final String labelText,
final float width, final float height, final float labelZOffset) {
super(factory, renderModes | Region.COLORCHANNEL_RENDERING_BIT, width, height);
- this.label = new Label0(labelFont, labelText, new float[] { 0.9f, 0.9f, 0.9f, 1.0f });
+ this.label = new Label0(labelFont, labelText, new float[] { 1.33f, 1.33f, 1.33f, 1.0f }); // 0.75 * 1.33 = 1.0
this.labelZOffset = labelZOffset;
- setLabelColor(1.0f, 1.0f, 1.0f);
+ setColor(0.75f, 0.75f, 0.75f, 1.0f);
+ setPressedColorMod(0.9f, 0.9f, 0.9f, 0.7f);
+ setToggleOffColorMod(0.65f, 0.65f, 0.65f, 1.0f);
+ setToggleOnColorMod(0.85f, 0.85f, 0.85f, 1.0f);
}
@Override
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java
index 45907ad6a..4581223d7 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java
@@ -1,6 +1,8 @@
package com.jogamp.opengl.test.junit.graph.demos.ui;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
@@ -10,8 +12,12 @@ import javax.media.opengl.GLRunnable;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.PinchToZoomGesture;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.Quaternion;
@@ -35,9 +41,12 @@ public class SceneUIController implements GLEventListener{
private final float[] sceneScale = new float[3];
private final float[] scenePlaneOrigin = new float[3];
- private int activeId = -1;
+
+ private volatile UIShape activeShape = null;
private SBCMouseListener sbcMouseListener = null;
+ private SBCGestureListener sbcGestureListener = null;
+ private PinchToZoomGesture pinchToZoomGesture = null;
private GLAutoDrawable cDrawable = null;
@@ -61,12 +70,21 @@ public class SceneUIController implements GLEventListener{
if(null == sbcMouseListener) {
sbcMouseListener = new SBCMouseListener();
window.addMouseListener(sbcMouseListener);
+ sbcGestureListener = new SBCGestureListener();
+ window.addGestureListener(sbcGestureListener);
+ pinchToZoomGesture = new PinchToZoomGesture(window.getNativeSurface(), false);
+ window.addGestureHandler(pinchToZoomGesture);
}
}
public void detachInputListenerFrom(GLWindow window) {
if(null != sbcMouseListener) {
window.removeMouseListener(sbcMouseListener);
+ sbcMouseListener = null;
+ window.removeGestureListener(sbcGestureListener);
+ sbcGestureListener = null;
+ window.removeGestureHandler(pinchToZoomGesture);
+ pinchToZoomGesture = null;
}
}
@@ -76,7 +94,6 @@ public class SceneUIController implements GLEventListener{
public void addShape(UIShape b) {
shapes.add(b);
}
-
public void removeShape(UIShape b) {
shapes.remove(b);
}
@@ -109,41 +126,6 @@ public class SceneUIController implements GLEventListener{
cDrawable = drawable;
}
- public int pickShape(final int glWinX, final int glWinY) {
- final float winZ0 = 0f;
- final float winZ1 = 0.3f;
- /**
- final FloatBuffer winZRB = Buffers.newDirectFloatBuffer(1);
- gl.glReadPixels( x, y, 1, 1, GL2ES2.GL_DEPTH_COMPONENT, GL.GL_FLOAT, winZRB);
- winZ1 = winZRB.get(0); // dir
- */
-
- final PMVMatrix pmv = renderer.getMatrix();
- pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
-
- final Ray ray = new Ray();
- final int shapeCount = shapes.size();
- for(int i=0; i<shapeCount; i++) {
- final UIShape uiShape = shapes.get(i);
- if( uiShape.isEnabled() ) {
- pmv.glPushMatrix();
- transformShape(pmv, uiShape);
-
- pmv.gluUnProjectRay(glWinX, glWinY, winZ0, winZ1, viewport, 0, ray);
- // System.err.printf("Pick: mapped.0: [%d, %d, %f/%f] -> %s%n", winX, winY, winZ0, winZ1, ray);
-
- pmv.glPopMatrix();
- final AABBox box = shapes.get(i).getBounds();
- final boolean hit = box.intersectsRay(ray);
- // System.err.println("Test: "+box+" -> hit "+hit+", shape: "+uiShape);
- if( hit ) {
- return i;
- }
- }
- }
- return -1;
- }
-
private void transformShape(final PMVMatrix pmv, final UIShape uiShape) {
final float[] uiTranslate = uiShape.getTranslate();
pmv.glTranslatef(uiTranslate[0], uiTranslate[1], uiTranslate[2]);
@@ -173,6 +155,21 @@ public class SceneUIController implements GLEventListener{
}
}
+ private static Comparator<UIShape> shapeZAscComparator = new Comparator<UIShape>() {
+ @Override
+ public int compare(final UIShape s1, final UIShape s2) {
+ final float s1Z = s1.getBounds().getMinZ()+s1.getTranslate()[2];
+ final float s2Z = s2.getBounds().getMinZ()+s2.getTranslate()[2];
+ if( FloatUtil.isEqual(s1Z, s2Z, FloatUtil.EPSILON) ) {
+ return 0;
+ } else if( s1Z < s2Z ){
+ return -1;
+ } else {
+ return 1;
+ }
+ } };
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void display(GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
@@ -183,9 +180,17 @@ public class SceneUIController implements GLEventListener{
final PMVMatrix pmv = renderer.getMatrix();
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- final int shapeCount = shapes.size();
+ final Object[] shapesS = shapes.toArray();
+ Arrays.sort(shapesS, (Comparator)shapeZAscComparator);
+
+ renderer.enable(gl, true);
+
+ //final int shapeCount = shapes.size();
+ final int shapeCount = shapesS.length;
for(int i=0; i<shapeCount; i++) {
- final UIShape uiShape = shapes.get(i);
+ // final UIShape uiShape = shapes.get(i);
+ final UIShape uiShape = (UIShape)shapesS[i];
+ // System.err.println("Id "+i+": "+uiShape);
if( uiShape.isEnabled() ) {
uiShape.validate(gl, renderer);
pmv.glPushMatrix();
@@ -194,11 +199,108 @@ public class SceneUIController implements GLEventListener{
pmv.glPopMatrix();
}
}
+
+ renderer.enable(gl, false);
+ }
+
+ public void pickShape(final int glWinX, final int glWinY, final float[] objPos, final UIShape[] shape, final Runnable runnable) {
+ if( null == cDrawable ) {
+ return;
+ }
+ cDrawable.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable drawable) {
+ shape[0] = pickShapeImpl(glWinX, glWinY, objPos);
+ if( null != shape[0] ) {
+ runnable.run();
+ }
+ return true;
+ } } );
+ }
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private UIShape pickShapeImpl(final int glWinX, final int glWinY, final float[] objPos) {
+ final float winZ0 = 0f;
+ final float winZ1 = 0.3f;
+ /**
+ final FloatBuffer winZRB = Buffers.newDirectFloatBuffer(1);
+ gl.glReadPixels( x, y, 1, 1, GL2ES2.GL_DEPTH_COMPONENT, GL.GL_FLOAT, winZRB);
+ winZ1 = winZRB.get(0); // dir
+ */
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+
+ final Ray ray = new Ray();
+
+ final Object[] shapesS = shapes.toArray();
+ Arrays.sort(shapesS, (Comparator)shapeZAscComparator);
+
+ for(int i=shapesS.length-1; i>=0; i--) {
+ final UIShape uiShape = (UIShape)shapesS[i];
+
+ if( uiShape.isEnabled() ) {
+ pmv.glPushMatrix();
+ transformShape(pmv, uiShape);
+ final boolean ok = pmv.gluUnProjectRay(glWinX, glWinY, winZ0, winZ1, viewport, 0, ray);
+ pmv.glPopMatrix();
+ if( ok ) {
+ final AABBox sbox = uiShape.getBounds();
+ if( sbox.intersectsRay(ray) ) {
+ // System.err.printf("Pick.0: shape %d, [%d, %d, %f/%f] -> %s%n", i, glWinX, glWinY, winZ0, winZ1, ray);
+ if( null == sbox.getRayIntersection(objPos, ray, FloatUtil.EPSILON, true, dpyTmp1V3, dpyTmp2V3, dpyTmp3V3) ) {
+ throw new InternalError("Ray "+ray+", box "+sbox);
+ }
+ // System.err.printf("Pick.1: shape %d @ [%f, %f, %f], within %s%n", i, objPos[0], objPos[1], objPos[2], uiShape.getBounds());
+ return uiShape;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ private final float[] dpyTmp1V3 = new float[3];
+ private final float[] dpyTmp2V3 = new float[3];
+ private final float[] dpyTmp3V3 = new float[3];
+
+ public void windowToShapeCoords(final UIShape activeShape, final int glWinX, final int glWinY, final float[] objPos, final Runnable runnable) {
+ if( null == cDrawable || null == activeShape ) {
+ return;
+ }
+ cDrawable.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable drawable) {
+ if( windowToShapeCoordsImpl(activeShape, glWinX, glWinY, objPos) ) {
+ runnable.run();
+ }
+ return true;
+ } } );
+ }
+ private boolean windowToShapeCoordsImpl(final UIShape activeShape, final int glWinX, final int glWinY, final float[] objPos) {
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+
+ pmv.glPushMatrix();
+ transformShape(pmv, activeShape);
+ boolean res = false;
+ final float[] ctr = activeShape.getBounds().getCenter();
+ if( pmv.gluProject(ctr[0], ctr[1], ctr[2], viewport, 0, dpyTmp1V3, 0) ) {
+ // System.err.printf("winToShapeCoords.0: shape %d: obj [%f, %f, %f] -> win [%f, %f, %f]%n", shapeId, ctr[0], ctr[1], ctr[2], dpyTmp1V3[0], dpyTmp1V3[1], dpyTmp1V3[2]);
+ if( pmv.gluUnProject(glWinX, glWinY, dpyTmp1V3[2], viewport, 0, objPos, 0) ) {
+ // System.err.printf("winToShapeCoords.1: shape %d: win [%d, %d, %f] -> obj [%f, %f, %f]%n", shapeId, glWinX, glWinY, dpyTmp1V3[2], objPos[0], objPos[1], objPos[2]);
+ res = true;
+ }
+ }
+ pmv.glPopMatrix();
+ return res;
}
@Override
public void dispose(GLAutoDrawable drawable) {
System.err.println("SceneUIController: dispose");
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ for(int i=0; i<shapes.size(); i++) {
+ shapes.get(i).destroy(gl, renderer);
+ }
+ shapes.clear();
cDrawable = null;
}
@@ -229,12 +331,11 @@ public class SceneUIController implements GLEventListener{
final float[] obj00Coord = new float[3];
final float[] obj11Coord = new float[3];
final float[] winZ = new float[1];
- final int[] view = new int[] { 0, 0, width, height };
- mapWin2ObjectCoords(pmv, view, zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord);
+ mapWin2ObjectCoords(pmv, viewport, zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord);
System.err.printf("Reshape: mapped.00: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", 0f, 0f, orthoDist, winZ[0], obj00Coord[0], obj00Coord[1], obj00Coord[2]);
- mapWin2ObjectCoords(pmv, view, zNear, zFar, width, height, orthoDist, winZ, obj11Coord);
+ mapWin2ObjectCoords(pmv, viewport, zNear, zFar, width, height, orthoDist, winZ, obj11Coord);
System.err.printf("Reshape: mapped.11: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", (float)width, (float)height, orthoDist, winZ[0], obj11Coord[0], obj11Coord[1], obj11Coord[2]);
nearPlane1Box.setSize( obj00Coord[0], // lx
@@ -261,71 +362,128 @@ public class SceneUIController implements GLEventListener{
pmv.glScalef(sceneScale[0], sceneScale[1], sceneScale[2]);
}
- public UIShape getActiveUI() {
- if( 0 > activeId ) {
+ public final UIShape getShape(final int id) {
+ if( 0 > id ) {
return null;
}
- return shapes.get(activeId);
+ return shapes.get(id);
+ }
+ public final UIShape getActiveShape() {
+ return activeShape;
}
public void release() {
- activeId = -1;
+ setActiveShape(null);
+ }
+ private void setActiveShape(final UIShape shape) {
+ activeShape = shape;
}
- private class SBCMouseListener implements MouseListener {
- int lx=-1, ly=-1;
+ private final class SBCGestureListener implements GestureHandler.GestureListener {
+ @Override
+ public void gestureDetected(final GestureEvent gh) {
+ if( null != activeShape ) {
+ // gesture .. delegate to active shape!
+ final InputEvent orig = gh.getTrigger();
+ if( orig instanceof MouseEvent ) {
+ final MouseEvent e = (MouseEvent) orig;
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ final float[] objPos = new float[3];
+ final UIShape shape = activeShape;
+ windowToShapeCoords(shape, glWinX, glWinY, objPos, new Runnable() {
+ public void run() {
+ shape.dispatchGestureEvent(gh, glWinX, glWinY, objPos);
+ } } );
+ }
+ }
+ }
+ }
- void clear() {
- lx = -1; ly = -1;
+ final void dispatchMouseEvent(final MouseEvent e, final int glWinX, final int glWinY) {
+ if( null == activeShape ) {
+ dispatchMouseEventPickShape(e, glWinX, glWinY, true);
+ } else {
+ dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
}
+ }
+ final void dispatchMouseEventPickShape(final MouseEvent e, final int glWinX, final int glWinY, final boolean setActive) {
+ final float[] objPos = new float[3];
+ final UIShape[] shape = { null };
+ pickShape(glWinX, glWinY, objPos, shape, new Runnable() {
+ public void run() {
+ if( setActive ) {
+ setActiveShape(shape[0]);
+ }
+ shape[0].dispatchMouseEvent(e, glWinX, glWinY, objPos);
+ } } );
+ }
+ final void dispatchMouseEventForShape(final UIShape shape, final MouseEvent e, final int glWinX, final int glWinY) {
+ final float[] objPos = new float[3];
+ windowToShapeCoords(shape, glWinX, glWinY, objPos, new Runnable() {
+ public void run() {
+ shape.dispatchMouseEvent(e, glWinX, glWinY, objPos);
+ } } );
+ }
- @Override
- public void mouseClicked(MouseEvent e) {
- UIShape uiShape = getActiveUI();
- if(uiShape != null){
- uiShape.dispatchMouseEvent(e, e.getX(), viewport[3]-e.getY());
- }
- clear();
- release();
+ private class SBCMouseListener implements MouseListener {
+ int lx=-1, ly=-1, lId=-1;
+
+ void clear() {
+ lx = -1; ly = -1; lId = -1;
}
@Override
public void mousePressed(final MouseEvent e) {
- if(null==cDrawable) {
- return;
+ if( -1 == lId || e.getPointerId(0) == lId ) {
+ lx = e.getX();
+ ly = e.getY();
+ lId = e.getPointerId(0);
}
-
// flip to GL window coordinates
final int glWinX = e.getX();
- final int glWinY = viewport[3] - e.getY();
-
- // Avoid race condition w/ matrix instance,
- // even thought we do not require a GL operation!
- cDrawable.invoke(true, new GLRunnable() {
- @Override
- public boolean run(GLAutoDrawable drawable) {
- activeId = pickShape(glWinX, glWinY);
- final UIShape uiShape = getActiveUI();
- if(uiShape != null) {
- uiShape.dispatchMouseEvent(e, glWinX, glWinY);
- }
- return true;
- } } );
+ final int glWinY = viewport[3] - e.getY() - 1;
+ dispatchMouseEvent(e, glWinX, glWinY);
}
@Override
public void mouseReleased(MouseEvent e) {
- final UIShape uiShape = getActiveUI();
- if(uiShape != null){
- uiShape.dispatchMouseEvent(e, e.getX(), viewport[3]-e.getY());
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ dispatchMouseEvent(e, glWinX, glWinY);
+ if( 1 == e.getPointerCount() ) {
+ // Release active shape: last pointer has been lifted!
+ release();
+ clear();
}
}
@Override
- public void mouseDragged(MouseEvent e) {
- final UIShape uiShape = getActiveUI();
- if(uiShape != null) {
- uiShape.dispatchMouseEvent(e, e.getX(), viewport[3]-e.getY());
+ public void mouseClicked(final MouseEvent e) {
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ // activeId should have been released by mouseRelease() already!
+ dispatchMouseEventPickShape(e, glWinX, glWinY, false);
+ // Release active shape: last pointer has been lifted!
+ release();
+ clear();
+ }
+
+ @Override
+ public void mouseDragged(final MouseEvent e) {
+ // drag activeShape, if no gesture-activity, only on 1st pointer
+ if( null != activeShape && !pinchToZoomGesture.isWithinGesture() && e.getPointerId(0) == lId ) {
+ lx = e.getX();
+ ly = e.getY();
+
+ // dragged .. delegate to active shape!
+ // flip to GL window coordinates
+ final int glWinX = lx;
+ final int glWinY = viewport[3] - ly - 1;
+ dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
}
}
@@ -333,24 +491,17 @@ public class SceneUIController implements GLEventListener{
public void mouseWheelMoved(final MouseEvent e) {
// flip to GL window coordinates
final int glWinX = lx;
- final int glWinY = viewport[3] - ly;
-
- cDrawable.invoke(true, new GLRunnable() {
- @Override
- public boolean run(GLAutoDrawable drawable) {
- activeId = pickShape(glWinX, glWinY);
- final UIShape uiShape = getActiveUI();
- if(uiShape != null) {
- uiShape.dispatchMouseEvent(e, glWinX, glWinY);
- }
- return true;
- } } );
+ final int glWinY = viewport[3] - ly - 1;
+ dispatchMouseEventPickShape(e, glWinX, glWinY, true);
}
@Override
public void mouseMoved(MouseEvent e) {
- lx = e.getX();
- ly = e.getY();
+ if( -1 == lId || e.getPointerId(0) == lId ) {
+ lx = e.getX();
+ ly = e.getY();
+ lId = e.getPointerId(0);
+ }
}
@Override
public void mouseEntered(MouseEvent e) { }
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureButton.java
index eeb5e19f3..5b00d1e3b 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureButton.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureButton.java
@@ -47,8 +47,10 @@ public class TextureButton extends RoundButton {
final float width, final float height, final TextureSequence texSeq) {
super(factory, renderModes | Region.COLORTEXTURE_RENDERING_BIT, width, height);
this.texSeq = texSeq;
- setColor(1.0f, 1.0f, 1.0f, 1.0f);
- setSelectedColorMod(0.9f, 0.9f, 0.9f, 0.9f);
+ setColor(0.8f, 0.8f, 0.8f, 1.0f);
+ setPressedColorMod(1.1f, 1.1f, 1.1f, 0.7f);
+ setToggleOffColorMod(0.8f, 0.8f, 0.8f, 1.0f);
+ setToggleOnColorMod(1.0f, 1.0f, 1.0f, 1.0f);
}
@Override
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java
index 90eb7d4f0..d019e696e 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java
@@ -100,7 +100,7 @@ public class UIGLListener01 extends UIListenerBase01 {
@Override
public void dispose(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
button.destroy(gl, getRegionRenderer());
super.dispose(drawable);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java
index 419370af9..2e9d33a78 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java
@@ -36,20 +36,21 @@ 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.curve.opengl.RenderState;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
+import com.jogamp.newt.event.GestureHandler.GestureListener;
+import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.NEWTEvent;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.opengl.math.Quaternion;
-import com.jogamp.opengl.math.VectorUtil;
import com.jogamp.opengl.math.geom.AABBox;
public abstract class UIShape {
public static final boolean DRAW_DEBUG_BOX = false;
- protected static final int DIRTY_SHAPE = 1 << 0 ;
+ protected static final int DIRTY_SHAPE = 1 << 0 ;
protected static final int DIRTY_STATE = 1 << 1 ;
private final Factory<? extends Vertex> vertexFactory;
@@ -67,16 +68,22 @@ public abstract class UIShape {
protected int dirty = DIRTY_SHAPE | DIRTY_STATE;
protected float shapesSharpness = OutlineShape.DEFAULT_SHARPNESS;
- protected final float[] rgbaColor = {0.6f, 0.6f, 0.6f, 1.0f};
- protected final float[] selectedRGBAModulate = {1.4f, 1.4f, 1.4f, 1.0f};
+ /** Default base-color w/o color channel, will be modulated w/ pressed- and toggle color */
+ protected final float[] rgbaColor = {0.75f, 0.75f, 0.75f, 1.0f};
+ /** Default pressed color-factor w/o color channel, modulated base-color. 0.75 * 1.2 = 0.9 */
+ protected final float[] pressedRGBAModulate = {1.2f, 1.2f, 1.2f, 0.7f};
+ /** Default toggle color-factor w/o color channel, modulated base-color. 0.75 * 1.13 ~ 0.85 */
+ protected final float[] toggleOnRGBAModulate = {1.13f, 1.13f, 1.13f, 1.0f};
+ /** Default toggle color-factor w/o color channel, modulated base-color. 0.75 * 0.86 ~ 0.65 */
+ protected final float[] toggleOffRGBAModulate = {0.86f, 0.86f, 0.86f, 1.0f};
private int name = -1;
private boolean down = false;
- private boolean toggle =false;
+ private boolean toggle = false;
private boolean toggleable = false;
private boolean enabled = true;
- private ArrayList<MouseListener> mouseListeners = new ArrayList<MouseListener>();
+ private ArrayList<MouseGestureListener> mouseListeners = new ArrayList<MouseGestureListener>();
public UIShape(final Factory<? extends Vertex> factory, final int renderModes) {
this.vertexFactory = factory;
@@ -199,35 +206,58 @@ public abstract class UIShape {
*/
public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount) {
final float r, g, b, a;
- final boolean isSelect;
- if( isPressed() || getToggleState() ) {
- isSelect = true;
- r = rgbaColor[0]*selectedRGBAModulate[0];
- g = rgbaColor[1]*selectedRGBAModulate[1];
- b = rgbaColor[2]*selectedRGBAModulate[2];
- a = rgbaColor[3]*selectedRGBAModulate[3];
- } else {
- isSelect = false;
- r = rgbaColor[0];
- g = rgbaColor[1];
- b = rgbaColor[2];
- a = rgbaColor[3];
- }
-
- if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
- gl.glClearColor(r, g, b, 0.0f);
- }
- final RenderState rs = renderer.getRenderState();
-
- if( Region.hasColorChannel( renderModes ) || Region.hasColorTexture( renderModes ) ) {
- if( isSelect ) {
- rs.setColorStatic(selectedRGBAModulate[0], selectedRGBAModulate[1], selectedRGBAModulate[2], selectedRGBAModulate[3]);
+ final boolean isPressed = isPressed(), isToggleOn = isToggleOn();
+ final boolean modBaseColor = !Region.hasColorChannel( renderModes ) && !Region.hasColorTexture( renderModes );
+ if( modBaseColor ) {
+ if( isPressed ) {
+ r = rgbaColor[0]*pressedRGBAModulate[0];
+ g = rgbaColor[1]*pressedRGBAModulate[1];
+ b = rgbaColor[2]*pressedRGBAModulate[2];
+ a = rgbaColor[3]*pressedRGBAModulate[3];
+ } 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];
+ } else {
+ r = rgbaColor[0]*toggleOffRGBAModulate[0];
+ g = rgbaColor[1]*toggleOffRGBAModulate[1];
+ b = rgbaColor[2]*toggleOffRGBAModulate[2];
+ a = rgbaColor[3]*toggleOffRGBAModulate[3];
+ }
} else {
- rs.setColorStatic(1.0f, 1.0f, 1.0f, 1.0f);
+ r = rgbaColor[0];
+ g = rgbaColor[1];
+ b = rgbaColor[2];
+ a = rgbaColor[3];
}
} else {
- rs.setColorStatic(r, g, b, a);
+ if( isPressed ) {
+ r = pressedRGBAModulate[0];
+ g = pressedRGBAModulate[1];
+ b = pressedRGBAModulate[2];
+ a = pressedRGBAModulate[3];
+ } else if( isToggleable() ) {
+ if( isToggleOn ) {
+ r = toggleOnRGBAModulate[0];
+ g = toggleOnRGBAModulate[1];
+ b = toggleOnRGBAModulate[2];
+ a = toggleOnRGBAModulate[3];
+ } else {
+ r = toggleOffRGBAModulate[0];
+ g = toggleOffRGBAModulate[1];
+ b = toggleOffRGBAModulate[2];
+ a = toggleOffRGBAModulate[3];
+ }
+ } else {
+ r = rgbaColor[0];
+ g = rgbaColor[1];
+ b = rgbaColor[2];
+ a = rgbaColor[3];
+ }
}
+ renderer.getRenderState().setColorStatic(r, g, b, a);
getRegion(gl, renderer).draw(gl, renderer, sampleCount);
}
@@ -252,12 +282,10 @@ public abstract class UIShape {
region.addOutlineShape(shape, null, rgbaColor);
}
region.setQuality(regionQuality);
- // dirty &= ~(DIRTY_SHAPE | DIRTY_STATE);
- dirty = 0;
+ dirty &= ~(DIRTY_SHAPE|DIRTY_STATE);
} else if( isStateDirty() ) {
- region.markDirty();
- // dirty &= ~DIRTY_STATE;
- dirty = 0;
+ region.markStateDirty();
+ dirty &= ~DIRTY_STATE;
}
}
@@ -286,14 +314,27 @@ public abstract class UIShape {
this.rgbaColor[2] = b;
this.rgbaColor[3] = a;
}
- public final void setSelectedColorMod(float r, float g, float b, float a){
- this.selectedRGBAModulate[0] = r;
- this.selectedRGBAModulate[1] = g;
- this.selectedRGBAModulate[2] = b;
- this.selectedRGBAModulate[3] = a;
+ public final void setPressedColorMod(float r, float g, float b, float a) {
+ this.pressedRGBAModulate[0] = r;
+ this.pressedRGBAModulate[1] = g;
+ this.pressedRGBAModulate[2] = b;
+ this.pressedRGBAModulate[3] = a;
+ }
+ public final void setToggleOnColorMod(float r, float g, float b, float a) {
+ this.toggleOnRGBAModulate[0] = r;
+ this.toggleOnRGBAModulate[1] = g;
+ this.toggleOnRGBAModulate[2] = b;
+ this.toggleOnRGBAModulate[3] = a;
+ }
+ public final void setToggleOffColorMod(float r, float g, float b, float a) {
+ this.toggleOffRGBAModulate[0] = r;
+ this.toggleOffRGBAModulate[1] = g;
+ this.toggleOffRGBAModulate[2] = b;
+ this.toggleOffRGBAModulate[3] = a;
}
- public String toString() {
+ @Override
+ public final String toString() {
return getClass().getSimpleName()+"["+getSubString()+"]";
}
@@ -307,12 +348,8 @@ public abstract class UIShape {
public void setPressed(final boolean b) {
this.down = b;
- if( isToggleable() && b ) {
- toggle = !toggle;
- }
markStateDirty();
}
-
public boolean isPressed() {
return this.down;
}
@@ -320,60 +357,93 @@ public abstract class UIShape {
public void setToggleable(final boolean toggleable) {
this.toggleable = toggleable;
}
-
public boolean isToggleable() {
return toggleable;
}
-
- public void setToggleState(final boolean v) {
+ public void setToggle(final boolean v) {
toggle = v;
markStateDirty();
}
- public boolean getToggleState() { return toggle; }
+ public void toggle() {
+ if( isToggleable() ) {
+ toggle = !toggle;
+ }
+ markStateDirty();
+ }
+ public boolean isToggleOn() { return toggle; }
- public final void addMouseListener(final MouseListener l) {
+ public final void addMouseListener(final MouseGestureListener l) {
if(l == null) {
return;
}
@SuppressWarnings("unchecked")
- ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
+ final ArrayList<MouseGestureListener> clonedListeners = (ArrayList<MouseGestureListener>) mouseListeners.clone();
clonedListeners.add(l);
mouseListeners = clonedListeners;
}
- public final void removeMouseListener(MouseListener l) {
+ public final void removeMouseListener(final MouseGestureListener l) {
if (l == null) {
return;
}
@SuppressWarnings("unchecked")
- ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
+ final ArrayList<MouseGestureListener> clonedListeners = (ArrayList<MouseGestureListener>) mouseListeners.clone();
clonedListeners.remove(l);
mouseListeners = clonedListeners;
}
/**
+ * Combining {@link MouseListener} and {@link GestureListener}
+ */
+ public static interface MouseGestureListener extends MouseListener, GestureListener {
+ }
+
+ /**
+ * Convenient adapter combining dummy implementation for {@link MouseListener} and {@link GestureListener}
+ */
+ public static abstract class MouseGestureAdapter extends MouseAdapter implements MouseGestureListener {
+ @Override
+ public void gestureDetected(GestureEvent gh) {
+ }
+ }
+
+ /**
* {@link UIShape} event details for propagated {@link NEWTEvent}s
* containing reference of {@link #shape the intended shape} as well as
- * the {@link #rotPosition rotated relative position} and {@link #rotBounds bounding box}.
+ * the {@link #objPos rotated relative position} and {@link #rotBounds bounding box}.
* The latter fields are also normalized to lower-left zero origin, allowing easier usage.
*/
- public static class EventDetails {
+ public static class PointerEventInfo {
/** The intended {@link UIShape} instance for this event */
public final UIShape shape;
- /** The {@link AABBox} of the intended {@link UIShape}, rotated about {@link UIShape#getRotation()} and normalized to lower-left zero origin.*/
- public final AABBox rotBounds;
- /** The relative mouse pointer position inside the intended {@link UIShape}, rotated about {@link UIShape#getRotation()} and normalized to lower-left zero origin. */
- public final float[] rotPosition;
-
- EventDetails(final UIShape shape, final AABBox rotatedBounds, final float[] rotatedRelPos) {
+ /** The relative pointer position inside the intended {@link UIShape}. */
+ public final float[] objPos;
+ /** window x-position in OpenGL model space */
+ public final int glWinX;
+ /** window y-position in OpenGL model space */
+ public final int glWinY;
+
+ PointerEventInfo(final int glWinX, final int glWinY, final UIShape shape, final float[] objPos) {
+ this.glWinX = glWinX;
+ this.glWinY = glWinY;
this.shape = shape;
- this.rotBounds = rotatedBounds;
- this.rotPosition = rotatedRelPos;
+ this.objPos = objPos;
}
public String toString() {
- return "EventDetails[pos "+rotPosition[0]+", "+rotPosition[1]+", "+rotPosition[2]+
- ", "+rotBounds+", "+shape+"]";
+ return "EventDetails[winPos ["+glWinX+", "+glWinY+"], objPos ["+objPos[0]+", "+objPos[1]+", "+objPos[2]+"], "+shape+"]";
+ }
+ }
+
+ /**
+ * @param e original Newt {@link GestureEvent}
+ * @param glWinX x-position in OpenGL model space
+ * @param glWinY y-position in OpenGL model space
+ */
+ public final void dispatchGestureEvent(final GestureEvent e, final int glWinX, final int glWinY, final float[] objPos) {
+ e.setAttachment(new PointerEventInfo(glWinX, glWinY, this, objPos));
+ for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
+ mouseListeners.get(i).gestureDetected(e);
}
}
@@ -381,36 +451,28 @@ public abstract class UIShape {
*
* @param e original Newt {@link MouseEvent}
* @param glX x-position in OpenGL model space
- * @param glY x-position in OpenGL model space
+ * @param glY y-position in OpenGL model space
*/
- public final void dispatchMouseEvent(final MouseEvent e, final int glX, final int glY) {
- // rotate bounding box and normalize to 0/0
- final Quaternion rot = getRotation();
- final float[] bLow = new float[3];
- VectorUtil.copyVec3(bLow, 0, getBounds().getLow(), 0);
- VectorUtil.scaleVec3(bLow, bLow, -1f);
- final AABBox rbox = new AABBox(getBounds());
- rbox.translate(bLow);
- rbox.rotate(rot);
-
- // get unrotated relative position within shape, rotate and normalize to 0/0
- final float[] relPos = new float[] { glX, glY, 0f };
- VectorUtil.subVec3(relPos, relPos, getTranslate());
- VectorUtil.addVec3(relPos, relPos, bLow);
- rot.rotateVector(relPos, 0, relPos, 0);
-
- // set as attachment
- e.setAttachment(new EventDetails(this, rbox, relPos));
+ public final void dispatchMouseEvent(final MouseEvent e, final int glWinX, final int glWinY, final float[] objPos) {
+ e.setAttachment(new PointerEventInfo(glWinX, glWinY, this, objPos));
final short eventType = e.getEventType();
- if( MouseEvent.EVENT_MOUSE_PRESSED == eventType ) {
- setPressed(true);
- } else if ( MouseEvent.EVENT_MOUSE_RELEASED == eventType ) {
- setPressed(false);
+ if( 1 == e.getPointerCount() ) {
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ toggle();
+ break;
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ setPressed(true);
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ setPressed(false);
+ break;
+ }
}
for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
- final MouseListener l = mouseListeners.get(i);
+ final MouseGestureListener l = mouseListeners.get(i);
switch( eventType ) {
case MouseEvent.EVENT_MOUSE_CLICKED:
l.mouseClicked(e);