diff options
author | Sven Gothel <[email protected]> | 2014-03-16 06:07:07 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-03-16 06:07:07 +0100 |
commit | 5e728baa72517865d602580b920d9bdfdfb26c65 (patch) | |
tree | 7d9429bab13e5122c610e73bc3742570a55eaeb0 /src/test/com/jogamp/opengl | |
parent | 8352cb7c5d8cc971c87f13fe9f61e346c4d2c541 (diff) |
Bug 801: Revisit UIShape/SceneController (Ray-Picking, Full Object/Model driven, ..) TODO: Transformations
SceneUIController handles shapes generic: Rendering, selecting and event traversing.
All data (transforms ..) are provided by UIShape.
UIShape:
- Dispatching NEWT MouseEvent's on MouseEventListener
- Separates the 2d-transforms for shape/region
and 3d transform, scale and rotation
GPUUISceneGLListener0A Demo code merely
aggregates the shapes and attaches listener, hence includes
the 'application logic'.
Working:
- picking any shape
- dragging, zooming, actions
TODO:
- Fix transformations, actually the rotations (button) look odd
probably due to 'unlucky' rotation center and axis.
+++
RegionRenderer: Removed Matrix ops, which shall be applied on PMVMatrix
Diffstat (limited to 'src/test/com/jogamp/opengl')
10 files changed, 514 insertions, 451 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java index d109ba1cc..f89ce101c 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java @@ -34,6 +34,7 @@ import javax.media.opengl.GL2ES2; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLProfile; +import javax.media.opengl.fixedfunc.GLMatrixFunc; import org.junit.Assert; import org.junit.BeforeClass; @@ -50,6 +51,7 @@ import com.jogamp.graph.geom.SVertex; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.test.junit.util.NEWTGLContext; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderState; @@ -190,8 +192,12 @@ public class TestTextRendererNEWT10 extends UITestCase { AABBox textBox = font.getStringBounds(text, fontSize); dx += font.getAdvanceWidth('X', fontSize) * column; dy -= (int)textBox.getHeight() * ( row + 1 ); - textRenderUtil.renderer.resetModelview(null); - textRenderUtil.renderer.translate(gl, dx, dy, z0); + + final PMVMatrix pmv = textRenderUtil.renderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(dx, dy, z0); + textRenderUtil.renderer.updateMatrix(gl); textRenderUtil.drawString3D(gl, font, fontSize, text, texSize); lastRow = row; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java index 6dd86e10c..feab048ea 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java @@ -31,11 +31,13 @@ package com.jogamp.opengl.test.junit.graph.demos; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.opengl.util.PMVMatrix; /** Demonstrate the rendering of multiple outlines into one region/OutlineShape * These Outlines are not necessary connected or contained. @@ -115,10 +117,12 @@ public class GPURegionGLListener01 extends GPURegionRendererListenerBase01 { gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); final RegionRenderer regionRenderer = getRenderer(); - - regionRenderer.resetModelview(null); - regionRenderer.translate(null, getXTran(), getYTran(), getZTran()); - regionRenderer.rotate(gl, getAngle(), 0, 1, 0); + final PMVMatrix pmv = regionRenderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(getXTran(), getYTran(), getZTran()); + pmv.glRotatef(getAngle(), 0, 1, 0); + regionRenderer.updateMatrix(gl); if( weight != regionRenderer.getWeight()) { regionRenderer.setWeight(gl, weight); } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java index d0afc8ad0..8fbc73522 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java @@ -34,11 +34,13 @@ import java.util.List; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.opengl.util.PMVMatrix; /** Demonstrate the rendering of multiple OutlineShapes * into one region @@ -118,9 +120,12 @@ public class GPURegionGLListener02 extends GPURegionRendererListenerBase01 { final RegionRenderer regionRenderer = getRenderer(); - regionRenderer.resetModelview(null); - regionRenderer.translate(null, getXTran(), getYTran(), getZTran()); - regionRenderer.rotate(gl, getAngle(), 0, 1, 0); + final PMVMatrix pmv = regionRenderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(getXTran(), getYTran(), getZTran()); + pmv.glRotatef(getAngle(), 0, 1, 0); + regionRenderer.updateMatrix(gl); if( weight != regionRenderer.getWeight()) { regionRenderer.setWeight(gl, weight); } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index 03f04a752..30c6bdea5 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -41,6 +41,7 @@ import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLRunnable; +import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; @@ -148,7 +149,8 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { final PMVMatrix pmv = renderer.getMatrix(); renderer.reshapePerspective(null, 45.0f, width, height, zNear, zFar); - renderer.resetModelview(null); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); renderer.updateMatrix(gl); System.err.printf("Reshape: zNear %f, zFar %f%n", zNear, zFar); System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum()); 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 7fcb9a848..a74fd407a 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 @@ -34,6 +34,7 @@ import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLException; +import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; @@ -213,7 +214,8 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB final RegionRenderer renderer = getRenderer(); final PMVMatrix pmv = renderer.getMatrix(); - renderer.resetModelview(null); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); renderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f); if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) { gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -242,7 +244,6 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB drawable.getChosenGLCapabilities().getAlphaBits()); // bottom, half line up - renderer.resetModelview(null); pmv.glTranslatef(nearPlaneX0, nearPlaneY0+(nearPlaneS * pixelSizeFPS / 2f), nearPlaneZ0); renderer.updateMatrix(gl); @@ -253,7 +254,8 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB float dx = width-fontNameBox.getWidth()-2f; float dy = height - 10f; - renderer.resetModelview(null); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0); renderer.updateMatrix(gl); System.err.printf("FontN: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy)); @@ -263,7 +265,8 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB dy += -fontNameBox.getHeight() - 10f; if(null != headtext) { - renderer.resetModelview(null); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); System.err.printf("Head: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy)); pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0); // pmv.glTranslatef(x0, y1, z0); @@ -273,11 +276,13 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB dy += -headbox.getHeight() - font.getLineHeight(pixelSizeBottom); - renderer.resetModelview(null); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0); System.err.printf("Bottom: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy)); - renderer.translate(null, getXTran(), getYTran(), getZTran()); - renderer.rotate(gl, getAngle(), 0, 1, 0); + pmv.glTranslatef(getXTran(), getYTran(), getZTran()); + pmv.glRotatef(getAngle(), 0, 1, 0); + renderer.updateMatrix(gl); renderer.setColorStatic(gl, 1.0f, 0.0f, 0.0f); if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) { gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f); 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 1102f2d7d..72c5d6a17 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 @@ -20,11 +20,12 @@ import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.Quaternion; import com.jogamp.opengl.test.junit.graph.demos.ui.Label; import com.jogamp.opengl.test.junit.graph.demos.ui.RIButton; import com.jogamp.opengl.test.junit.graph.demos.ui.SceneUIController; -import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.test.junit.graph.demos.ui.UIShape; import com.jogamp.opengl.util.glsl.ShaderState; public class GPUUISceneGLListener0A implements GLEventListener { @@ -33,28 +34,19 @@ public class GPUUISceneGLListener0A implements GLEventListener { private boolean trace = false; private final int renderModes; - private final int[] sampleCount = new int[1]; - private final int[] texSize2 = new int[1]; private final RenderState rs; private final SceneUIController sceneUIController; - protected final float zNear = 0.1f, zFar = 7000f; - /** Describing the bounding box in model-coordinates of the near-plane parallel at distance one. */ - protected final AABBox nearPlane1Box; private RegionRenderer renderer; int fontSet = FontFactory.UBUNTU; Font font; + final float buttonXSize = 84f; + final float buttonYSize = buttonXSize/2.5f; final float fontSizeFixed = 12f; final float fontSizeFPS = 10f; float dpiH = 96; - private float xTran = 0f; - private float yTran = 0; - private float zTran = 0f; - private float rotButtonsY = 0f; - private float rotTextY = 0f; - private final float zoomText = 1f; private int currentText = 0; private Label[] labels = null; @@ -64,8 +56,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { private Label fpsLabel = null; private final int numSelectable = 6; - private MultiTouchListener multiTouchListener = null; - private boolean showFPS = true; + private boolean ioAttached = false; private GLAutoDrawable cDrawable; private final String jogamp = "JogAmp - Jogl Graph Module Demo"; @@ -81,8 +72,6 @@ public class GPUUISceneGLListener0A implements GLEventListener { public GPUUISceneGLListener0A(RenderState rs, int renderModes, boolean debug, boolean trace) { this.rs = rs; this.renderModes = renderModes; - this.sampleCount[0] = 4; - this.texSize2[0] = 0; this.debug = debug; this.trace = trace; @@ -93,11 +82,23 @@ public class GPUUISceneGLListener0A implements GLEventListener { ioe.printStackTrace(); } sceneUIController = new SceneUIController(); - nearPlane1Box = new AABBox(); } - final float buttonXSize = 84f; - final float buttonYSize = buttonXSize/2.5f; + private void rotateButtons(MouseEvent e, float angdeg) { + for(int i=0; i<buttons.length; i++) { + rotateInstance(e, buttons[i].getRotation(), angdeg); + } + } + private void rotateInstance(MouseEvent e, Quaternion quat, float angdeg) { + final float angrad = angdeg * FloatUtil.PI / 180.0f; + if( e.isControlDown() ) { + quat.rotateByAngleZ(angrad); + } else if( e.isShiftDown() ) { + quat.rotateByAngleX(angrad); + } else { + quat.rotateByAngleY(angrad); + } + } private void initButtons() { buttons = new RIButton[numSelectable]; @@ -106,32 +107,44 @@ public class GPUUISceneGLListener0A implements GLEventListener { final float ystart = 0f; final float diff = 1.5f * buttonYSize; - buttons[0] = new RIButton(SVertex.factory(), font, "Next Text", buttonXSize, buttonYSize){ - @Override - public void onClick(MouseEvent e) { - currentText = (currentText+1)%3; - } - }; - buttons[0].translate(xstart,ystart); + buttons[0] = new RIButton(SVertex.factory(), font, "Next Text", buttonXSize, buttonYSize); + buttons[0].translate(xstart,ystart, 0f); buttons[0].setLabelColor(1.0f, 1.0f, 1.0f); + buttons[0].addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if( null != labels[currentText] ) { + labels[currentText].setEnabled(false); + } + currentText = (currentText+1)%3; + if( null != labels[currentText] ) { + labels[currentText].setEnabled(true); + } + } } ); + buttons[0].addMouseListener(new DragAndZoomListener(buttons[0])); - buttons[1] = new RIButton(SVertex.factory(), font, "Show FPS", buttonXSize, buttonYSize){ + buttons[1] = new RIButton(SVertex.factory(), font, "Show FPS", buttonXSize, buttonYSize); + buttons[1].translate(xstart,ystart - diff, 0f); + buttons[1].setToggleable(true); + buttons[1].setLabelColor(1.0f, 1.0f, 1.0f); + buttons[1].addMouseListener(new MouseAdapter() { @Override - public void onClick(MouseEvent e) { + public void mouseClicked(MouseEvent e) { final GLAnimatorControl a = cDrawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); } - showFPS = !showFPS; - } - }; - buttons[1].translate(xstart,ystart - diff); - buttons[1].setToggleable(true); - buttons[1].setLabelColor(1.0f, 1.0f, 1.0f); + fpsLabel.setEnabled(!fpsLabel.isEnabled()); + } } ); + buttons[1].addMouseListener(new DragAndZoomListener(buttons[1])); - buttons[2] = new RIButton(SVertex.factory(), font, "v-sync", buttonXSize, buttonYSize){ + buttons[2] = new RIButton(SVertex.factory(), font, "v-sync", buttonXSize, buttonYSize); + buttons[2].translate(xstart,ystart-diff*2, 0f); + buttons[2].setToggleable(true); + buttons[2].setLabelColor(1.0f, 1.0f, 1.0f); + buttons[2].addMouseListener(new MouseAdapter() { @Override - public void onClick(MouseEvent e) { + public void mouseClicked(MouseEvent e) { cDrawable.invoke(false, new GLRunnable() { @Override public boolean run(GLAutoDrawable drawable) { @@ -144,50 +157,42 @@ public class GPUUISceneGLListener0A implements GLEventListener { return true; } }); - } - }; - buttons[2].translate(xstart,ystart-diff*2); - buttons[2].setToggleable(true); - buttons[2].setLabelColor(1.0f, 1.0f, 1.0f); + } } ); + buttons[2].addMouseListener(new DragAndZoomListener(buttons[2])); - buttons[3] = new RIButton(SVertex.factory(), font, "Tilt +Y", buttonXSize, buttonYSize) { - @Override - public void onClick(MouseEvent e) { - if( e.isShiftDown() ) { - rotButtonsY+=5; - } else { - rotTextY+=5f; - } - } - }; - buttons[3].translate(xstart,ystart-diff*3); + buttons[3] = new RIButton(SVertex.factory(), font, "Tilt +Y", buttonXSize, buttonYSize); + buttons[3].translate(xstart,ystart-diff*3, 0f); buttons[3].setLabelColor(1.0f, 1.0f, 1.0f); - - buttons[4] = new RIButton(SVertex.factory(), font, "Tilt -Y", buttonXSize, buttonYSize){ + buttons[3].addMouseListener(new MouseAdapter() { @Override - public void onClick(MouseEvent e) { - if( e.isShiftDown() ) { - rotButtonsY-=5f; - } else { - rotTextY-=5f; - } - } - }; - buttons[4].translate(xstart,ystart-diff*4); - buttons[4].setLabelColor(1.0f, 1.0f, 1.0f); + public void mouseClicked(MouseEvent e) { + rotateButtons(e, 5f); + } } ); + buttons[3].addMouseListener(new DragAndZoomListener(buttons[3])); - buttons[5] = new RIButton(SVertex.factory(), font, "Quit", buttonXSize, buttonYSize){ + buttons[4] = new RIButton(SVertex.factory(), font, "Tilt -Y", buttonXSize, buttonYSize); + buttons[4].translate(xstart,ystart-diff*4, 0f); + buttons[4].setLabelColor(1.0f, 1.0f, 1.0f); + buttons[4].addMouseListener(new MouseAdapter() { @Override - public void onClick(MouseEvent e) { - cDrawable.destroy(); - } - }; - buttons[5].translate(xstart,ystart-diff*5); + public void mouseClicked(MouseEvent e) { + rotateButtons(e, -5f); + } } ); + buttons[4].addMouseListener(new DragAndZoomListener(buttons[4])); + + buttons[5] = new RIButton(SVertex.factory(), font, "Quit", buttonXSize, buttonYSize); + buttons[5].translate(xstart,ystart-diff*5, 0f); buttons[5].setColor(0.8f, 0.0f, 0.0f); buttons[5].setLabelColor(1.0f, 1.0f, 1.0f); buttons[5].setSelectedColor(0.8f, 0.8f, 0.8f); buttons[5].setLabelSelectedColor(0.8f, 0.0f, 0.0f); + buttons[5].addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + cDrawable.destroy(); + } } ); + buttons[5].addMouseListener(new DragAndZoomListener(buttons[5])); } private void initTexts() { @@ -252,22 +257,32 @@ public class GPUUISceneGLListener0A implements GLEventListener { renderer.init(gl); renderer.setAlpha(gl, 1.0f); - renderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f); initTexts(); initButtons(); - sceneUIController.setRenderer(renderer, renderModes, sampleCount); + sceneUIController.setRenderer(renderer); sceneUIController.addShape(buttons[0]); sceneUIController.addShape(buttons[1]); sceneUIController.addShape(buttons[2]); sceneUIController.addShape(buttons[3]); sceneUIController.addShape(buttons[4]); sceneUIController.addShape(buttons[5]); - sceneUIController.init(drawable); final float pixelSizeFixed = font.getPixelSize(fontSizeFixed, dpiH); jogampLabel = new Label(SVertex.factory(), font, pixelSizeFixed, jogamp); + jogampLabel.addMouseListener(new DragAndZoomListener(jogampLabel)); + sceneUIController.addShape(jogampLabel); + + final float pixelSizeFPS = font.getPixelSize(fontSizeFPS, dpiH); + fpsLabel = new Label(renderer.getRenderState().getVertexFactory(), font, pixelSizeFPS, "Nothing there yet"); + fpsLabel.translate(0f, 0f, 0f); // FIXME + fpsLabel.addMouseListener(new DragAndZoomListener(fpsLabel)); + fpsLabel.addMouseListener(new DragAndZoomListener(fpsLabel)); + sceneUIController.addShape(fpsLabel); + + sceneUIController.init(drawable); + final GLAnimatorControl a = drawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); @@ -290,56 +305,26 @@ public class GPUUISceneGLListener0A implements GLEventListener { renderer.destroy(gl); } + protected void setupPMV(GLAutoDrawable drawable) { + + } + @Override public void display(GLAutoDrawable drawable) { // System.err.println("GPUUISceneGLListener0A: display"); final GL2ES2 gl = drawable.getGL().getGL2ES2(); - final int width = drawable.getWidth(); - final int height = drawable.getHeight(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - final float pixelSizeFixed = font.getPixelSize(fontSizeFixed, dpiH); - - float dx = width * 1f/6f; - float dy = height - height/6f; - - renderer.resetModelview(null); - // Keep Buttons static .. - // sceneUIController.setTranslate(nearPlaneX0+xTran+(dx*nearPlaneSx), nearPlaneY0+yTran+((dy-buttonYSize)*nearPlaneSy), nearPlaneZ0+zTran); - sceneUIController.setTranslate(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+((dy-buttonYSize)*nearPlaneSy), nearPlaneZ0); - sceneUIController.setScale(nearPlaneSx, nearPlaneSy, 1f); - sceneUIController.setRotation(0, rotButtonsY, 0); - sceneUIController.display(drawable); - - dx = width * 1f/3f; - - renderer.resetModelview(null); - renderer.translate(null, nearPlaneX0+xTran+(dx*nearPlaneSx), nearPlaneY0+yTran+(dy*nearPlaneSy), nearPlaneZ0+zTran); - renderer.rotate(null, rotTextY , 0, 1, 0); - renderer.scale(null, nearPlaneSx*zoomText, nearPlaneSy*zoomText, 1f); - renderer.updateMatrix(gl); - renderer.setColorStatic(gl, 0.0f, 1.0f, 0.0f); - jogampLabel.drawShape(gl, renderer, sampleCount, false); - dy -= 3f * jogampLabel.getLineHeight(); if(null == labels[currentText]) { + final float pixelSizeFixed = font.getPixelSize(fontSizeFixed, dpiH); + float dx = drawable.getWidth() * 1f/3f; labels[currentText] = new Label(SVertex.factory(), font, pixelSizeFixed, strings[currentText]); labels[currentText].setColor(0, 0, 0); + labels[currentText].translate(dx, -3f * jogampLabel.getLineHeight(), 0f); + labels[currentText].setEnabled(true); + labels[currentText].addMouseListener(new DragAndZoomListener(labels[currentText])); + sceneUIController.addShape(labels[currentText]); } - labels[currentText].validate(gl, renderer); - - renderer.resetModelview(null); - renderer.translate(null, nearPlaneX0+xTran+(dx*nearPlaneSx), nearPlaneY0+yTran+(dy*nearPlaneSy), nearPlaneZ0+zTran); - renderer.rotate(null, rotTextY, 0, 1, 0); - renderer.scale(null, nearPlaneSx*zoomText, nearPlaneSy*zoomText, 1f); - renderer.updateMatrix(gl); - renderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f); - labels[currentText].drawShape(gl, renderer, sampleCount, false); - - if( showFPS ) { - final float pixelSizeFPS = font.getPixelSize(fontSizeFPS, dpiH); + if( fpsLabel.isEnabled() ) { final float lfps, tfps, td; final GLAnimatorControl animator = drawable.getAnimator(); if( null != animator ) { @@ -353,98 +338,53 @@ public class GPUUISceneGLListener0A implements GLEventListener { } final String modeS = Region.getRenderModeString(renderer.getRenderModes()); final String text = String.format("%03.1f/%03.1f fps, v-sync %d, fontSize %.1f, %s-samples %d, td %4.1f, blend %b, alpha-bits %d", - lfps, tfps, gl.getSwapInterval(), fontSizeFixed, modeS, sampleCount[0], td, + lfps, tfps, gl.getSwapInterval(), fontSizeFixed, modeS, sceneUIController.getSampleCount(), td, renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED), drawable.getChosenGLCapabilities().getAlphaBits()); - if(null != fpsLabel) { - fpsLabel.clear(gl, renderer); - fpsLabel.setText(text); - } else { - fpsLabel = new Label(renderer.getRenderState().getVertexFactory(), font, pixelSizeFPS, text); - } - renderer.resetModelview(null); - renderer.translate(null, nearPlaneX0, nearPlaneY0+(nearPlaneSy * pixelSizeFPS / 2f), nearPlaneZ0); - renderer.scale(null, nearPlaneSx, nearPlaneSy, 1f); - renderer.updateMatrix(gl); - fpsLabel.drawShape(gl, renderer, sampleCount, false); + fpsLabel.clear(gl, renderer); + fpsLabel.setText(text); } + sceneUIController.display(drawable); } - public static void mapWin2ObjectCoords(final PMVMatrix pmv, final int[] view, - final float zNear, final float zFar, - float orthoX, float orthoY, float orthoDist, - final float[] winZ, final float[] objPos) { - winZ[0] = (1f/zNear-1f/orthoDist)/(1f/zNear-1f/zFar); - pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0); - } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { System.err.println("GPUUISceneGLListener0A: reshape"); - GL2ES2 gl = drawable.getGL().getGL2ES2(); - final PMVMatrix pmv = renderer.getMatrix(); - renderer.reshapePerspective(gl, 45.0f, width, height, zNear, zFar); - renderer.resetModelview(null); - renderer.updateMatrix(gl); - System.err.printf("Reshape: zNear %f, zFar %f%n", zNear, zFar); - System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum()); - { - final float orthoDist = 1f; - 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); - 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); - 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 - obj00Coord[1], // ly - obj00Coord[2], // lz - obj11Coord[0], // hx - obj11Coord[1], // hy - obj11Coord[2] );// hz - System.err.printf("Reshape: dist1Box: %s%n", nearPlane1Box); + float dx = width * 1f/3f; + jogampLabel.setTranslate(dx, 0f, 0f); + fpsLabel.setTranslate(0f, 0f, 0f); // FIXME + if( null != labels[currentText] ) { + labels[currentText].setTranslate(dx, -3f * jogampLabel.getLineHeight(), 0f); } - sceneUIController.reshape(drawable, x, y, width, height); - final float dist = 100f; - nearPlaneX0 = nearPlane1Box.getMinX() * dist; - nearPlaneY0 = nearPlane1Box.getMinY() * dist; - nearPlaneZ0 = nearPlane1Box.getMinZ() * dist; - final float xd = nearPlane1Box.getWidth() * dist; - final float yd = nearPlane1Box.getHeight() * dist; - nearPlaneSx = xd / width; - nearPlaneSy = yd / height; - System.err.printf("Scale: [%f x %f] / [%d x %d] = [%f, %f]%n", xd, yd, width, height, nearPlaneSx, nearPlaneSy); - } - float nearPlaneX0, nearPlaneY0, nearPlaneZ0, nearPlaneSx, nearPlaneSy; + sceneUIController.reshape(drawable, x, y, width, height); + } public void attachInputListenerTo(GLWindow window) { - if ( null == multiTouchListener ) { - multiTouchListener = new MultiTouchListener(); - window.addMouseListener(multiTouchListener); + if ( !ioAttached ) { + ioAttached = true; sceneUIController.attachInputListenerTo(window); } } public void detachInputListenerFrom(GLWindow window) { - if ( null != multiTouchListener ) { - window.removeMouseListener(multiTouchListener); + if ( ioAttached ) { + ioAttached = false; sceneUIController.detachInputListenerFrom(window); } } - private class MultiTouchListener extends MouseAdapter { - int lx = 0; - int ly = 0; - + private class DragAndZoomListener extends MouseAdapter { + final UIShape shape; + int lx=-1, ly=-1; boolean first = false; + public DragAndZoomListener(UIShape shape) { + this.shape = shape; + } + @Override public void mousePressed(MouseEvent e) { first = true; @@ -457,7 +397,6 @@ public class GPUUISceneGLListener0A implements GLEventListener { @Override public void mouseDragged(MouseEvent e) { - System.err.println("demo:mousedragged "+e); if(e.getPointerCount()==2) { // 2 pointers zoom .. if(first) { @@ -467,10 +406,9 @@ public class GPUUISceneGLListener0A implements GLEventListener { } int nv = Math.abs(e.getY(0)-e.getY(1)); int dy = nv - lx; - - zTran += 2 * Math.signum(dy); - lx = nv; + + shape.translate(0f, 0f, 2 * Math.signum(dy)); } else { // 1 pointer drag if(first) { @@ -484,10 +422,9 @@ public class GPUUISceneGLListener0A implements GLEventListener { int dx = nx - lx; int dy = ny - ly; if(Math.abs(dx) > Math.abs(dy)){ - xTran += Math.signum(dx); - } - else { - yTran -= Math.signum(dy); + shape.translate(Math.signum(dx), 0f, 0f); + } else { + shape.translate(0f, -Math.signum(dy), 0f); } lx = nx; ly = ny; @@ -497,7 +434,9 @@ public class GPUUISceneGLListener0A implements GLEventListener { @Override public void mouseWheelMoved(MouseEvent e) { if( !e.isShiftDown() ) { - zTran += 2f*e.getRotation()[1]; // vertical: wheel + float tz = 2f*e.getRotation()[1]; // vertical: wheel + System.err.println("tz.4 "+tz); + shape.translate(0f, 0f, tz); } } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java index 7e4d5ec62..83ca6bed0 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java @@ -40,7 +40,7 @@ import com.jogamp.opengl.math.geom.AABBox; /** * GPU based resolution independent Button impl */ -public abstract class RIButton extends UIShape { +public class RIButton extends UIShape { private float width, height; private final Label label; /** 20 % to each side default */ @@ -86,13 +86,13 @@ public abstract class RIButton extends UIShape { } @Override - public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount, boolean select) { + public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount) { gl.glEnable(GL2ES2.GL_POLYGON_OFFSET_FILL); gl.glPolygonOffset(0.0f, 1f); - super.drawShape(gl, renderer, sampleCount, select); + super.drawShape(gl, renderer, sampleCount); gl.glDisable(GL2ES2.GL_POLYGON_OFFSET_FILL); - label.drawShape(gl, renderer, sampleCount, select); + label.drawShape(gl, renderer, sampleCount); } @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 c1149227f..fbdc72a1f 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,8 +1,5 @@ package com.jogamp.opengl.test.junit.graph.demos.ui; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.IntBuffer; import java.util.ArrayList; import javax.media.opengl.GL; @@ -12,28 +9,30 @@ import javax.media.opengl.GLEventListener; import javax.media.opengl.GLRunnable; import javax.media.opengl.fixedfunc.GLMatrixFunc; -import com.jogamp.common.nio.Buffers; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.math.FloatUtil; -import com.jogamp.opengl.math.Quaternion; +import com.jogamp.opengl.math.Ray; +import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.util.PMVMatrix; public class SceneUIController implements GLEventListener{ private final ArrayList<UIShape> shapes = new ArrayList<UIShape>(); - private int count = 0; - private int renderModes; - private int[] sampleCount; + private float sceneStartX = 0f; + private float sceneStartY = 0f; + private RegionRenderer renderer; - private final float[] translate = new float[3]; - private final float[] scale = new float[3]; - private final Quaternion quaternion = new Quaternion(); + private final int[] sampleCount = new int[1]; - private final float[] sceneClearColor = new float[]{0,0,0,0}; + private final float zNear = 0.1f, zFar = 7000f; + /** Describing the bounding box in model-coordinates of the near-plane parallel at distance one. */ + private final AABBox nearPlane1Box = new AABBox(); + private final int[] viewport = new int[] { 0, 0, 0, 0 }; + private float nearPlaneX0, nearPlaneY0, nearPlaneZ0, nearPlaneSx, nearPlaneSy; + float globMvTx, globMvTy, globMvTz; private int activeId = -1; @@ -42,22 +41,16 @@ public class SceneUIController implements GLEventListener{ private GLAutoDrawable cDrawable = null; public SceneUIController() { - this(null, 0, null); + this(null); } - public SceneUIController(RegionRenderer renderer, int renderModes, int[] sampleCount) { + public SceneUIController(RegionRenderer renderer) { this.renderer = renderer; - this.renderModes = renderModes; - this.sampleCount = sampleCount; - setScale(1f, 1f, 1f); - setTranslate(0f, 0f, 0f); - setRotation(0f, 0f, 0f); + this.sampleCount[0] = 4; } - public void setRenderer(RegionRenderer renderer, int renderModes, int[] sampleCount) { + public void setRenderer(RegionRenderer renderer) { this.renderer = renderer; - this.renderModes = renderModes; - this.sampleCount = sampleCount; } public void attachInputListenerTo(GLWindow window) { @@ -78,29 +71,92 @@ public class SceneUIController implements GLEventListener{ } public void addShape(UIShape b) { shapes.add(b); - count++; } public void removeShape(UIShape b) { - boolean found = shapes.remove(b); - if(found) { - count--; - } + shapes.remove(b); } + public int getSampleCount() { return sampleCount[0]; } + public void setSampleCount(int v) { sampleCount[0]=v; } + @Override public void init(GLAutoDrawable drawable) { System.err.println("SceneUIController: init"); cDrawable = drawable; } + + public int pickShape(final int winX, int winY) { + 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 + */ + + // flip to GL window coordinates + winY = viewport[3] - winY; + + 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(winX, winY, 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(); + float[] uiScale = uiShape.getScale(); + // System.err.printf("SceneUICtrl.render.1.0: scale.0: %f, %f, %f%n", uiScale[0], uiScale[1], uiScale[2]); + // System.err.printf("SceneUICtrl.render.1.0: translate.0: %f, %f, %f%n", uiTranslate[0], uiTranslate[1], uiTranslate[2]); + pmv.glRotate(uiShape.getRotation()); + pmv.glScalef(uiScale[0], uiScale[1], uiScale[2]); + pmv.glTranslatef(uiTranslate[0], uiTranslate[1], uiTranslate[2]); + } + @Override public void display(GLAutoDrawable drawable) { - // System.err.println("SceneUIController: display"); - final int width = drawable.getWidth(); - final int height = drawable.getHeight(); - GL2ES2 gl = drawable.getGL().getGL2ES2(); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + final PMVMatrix pmv = renderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - render(gl, width, height, renderModes, sampleCount, false); + final int shapeCount = shapes.size(); + for(int i=0; i<shapeCount; i++) { + final UIShape uiShape = shapes.get(i); + if( uiShape.isEnabled() ) { + uiShape.validate(gl, renderer); + pmv.glPushMatrix(); + transformShape(pmv, uiShape); + renderer.updateMatrix(gl); + uiShape.drawShape(gl, renderer, sampleCount); + pmv.glPopMatrix(); + // break; + } + } } @Override @@ -109,24 +165,78 @@ public class SceneUIController implements GLEventListener{ cDrawable = null; } + public static void mapWin2ObjectCoords(final PMVMatrix pmv, final int[] view, + final float zNear, final float zFar, + float orthoX, float orthoY, float orthoDist, + final float[] winZ, final float[] objPos) { + winZ[0] = (1f/zNear-1f/orthoDist)/(1f/zNear-1f/zFar); + pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0); + } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - } + viewport[0] = x; + viewport[1] = y; + viewport[2] = width; + viewport[3] = height; - public UIShape getShape(GLAutoDrawable drawable,int x, int y) { - final int width = drawable.getWidth(); - final int height = drawable.getHeight(); - GL2ES2 gl = drawable.getGL().getGL2ES2(); + sceneStartX = width * 1f/6f; + sceneStartY = height - height/6f; - int index = checkSelection(gl, x, y, width, height); - if(index == -1) - return null; - return shapes.get(index); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + final PMVMatrix pmv = renderer.getMatrix(); + renderer.reshapePerspective(gl, 45.0f, width, height, zNear, zFar); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + + System.err.printf("Reshape: zNear %f, zFar %f%n", zNear, zFar); + System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum()); + { + final float orthoDist = 1f; + 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); + 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); + 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 + obj00Coord[1], // ly + obj00Coord[2], // lz + obj11Coord[0], // hx + obj11Coord[1], // hy + obj11Coord[2] );// hz + System.err.printf("Reshape: dist1Box: %s%n", nearPlane1Box); + } + final float dist = 100f; + nearPlaneX0 = nearPlane1Box.getMinX() * dist; + nearPlaneY0 = nearPlane1Box.getMinY() * dist; + nearPlaneZ0 = nearPlane1Box.getMinZ() * dist; + final float xd = nearPlane1Box.getWidth() * dist; + final float yd = nearPlane1Box.getHeight() * dist; + nearPlaneSx = xd / width; + nearPlaneSy = yd / height; + System.err.printf("Scale: [%f x %f] / [%d x %d] = [%f, %f]%n", xd, yd, width, height, nearPlaneSx, nearPlaneSy); + + // globMvTx=nearPlaneX0+(sceneStartX*nearPlaneSx); + // globMvTy=nearPlaneY0+(sceneStartY*nearPlaneSy); + globMvTx=nearPlaneX0; + globMvTy=nearPlaneY0; + globMvTz=nearPlaneZ0; + pmv.glTranslatef(globMvTx, globMvTy, globMvTz); + pmv.glScalef(nearPlaneSx, nearPlaneSy, 1f); + pmv.glTranslatef(sceneStartX, sceneStartY, 0f); + renderer.updateMatrix(gl); } public UIShape getActiveUI() { - if(activeId == -1) + if( 0 > activeId ) { return null; + } return shapes.get(activeId); } @@ -134,145 +244,86 @@ public class SceneUIController implements GLEventListener{ activeId = -1; } - private int checkSelection(GL2ES2 gl,int x, int y, int width, int height) { - gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, 4); - gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, 4); - gl.glClearColor(sceneClearColor[0], sceneClearColor[1], sceneClearColor[2], sceneClearColor[3]); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - render(gl, width, height, 0, null, true); - ByteBuffer pixel = Buffers.newDirectByteBuffer(4); - pixel.order(ByteOrder.nativeOrder()); - IntBuffer viewport = IntBuffer.allocate(4); - gl.glGetIntegerv(GL2ES2.GL_VIEWPORT, viewport); - gl.glReadPixels(x, viewport.get(3) - y, 1, 1, GL2ES2.GL_RGBA, - GL2ES2.GL_UNSIGNED_BYTE, pixel); - - int qp = pixel.get(0) & 0xFF; - int index = Math.round(((qp/255.0f)*(count+2))-1); - if(index < 0 || index >= count) - return -1; - return index; - } + private class SBCMouseListener implements MouseListener { + int lx=-1, ly=-1; - private void render(GL2ES2 gl, int width, int height, int renderModes, int[/*1*/] sampleCount, boolean select) { - final PMVMatrix pmv = renderer.getMatrix(); - pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmv.glLoadIdentity(); - // System.err.printf("SceneUICtrl.render.1.0: scale.0: %f, %f, %f%n", scale[0], scale[1], scale[2]); - // System.err.printf("SceneUICtrl.render.1.0: translate.0: %f, %f, %f%n", translate[0], translate[1], translate[2]); - pmv.glTranslatef(translate[0], translate[1], translate[2]); - pmv.glRotate(quaternion); - pmv.glScalef(scale[0], scale[1], scale[2]); - - for(int index=0; index < count;index++){ - if(select) { - float color= index+1; - renderer.setColorStatic(gl, color/(count+2), color/(count+2), color/(count+2)); - } - final UIShape uiShape = shapes.get(index); - uiShape.validate(gl, renderer); - final float[] uiTranslate = uiShape.getTranslate(); - - pmv.glPushMatrix(); - // System.err.printf("SceneUICtrl.render.1.0: translate.1: %f, %f%n", uiTranslate[0], uiTranslate[1]); - pmv.glTranslatef(uiTranslate[0], uiTranslate[1], 0f); - renderer.updateMatrix(gl); - uiShape.drawShape(gl, renderer, sampleCount, select); - pmv.glPopMatrix(); + void clear() { + lx = -1; ly = -1; } - } - - public void setTranslate(float x, float y, float z) { - this.translate[0] = x; - this.translate[1] = y; - this.translate[2] = z; - } - - public void setScale(float x, float y, float z) { - this.scale[0] = x; - this.scale[1] = y; - this.scale[2] = z; - } - - public void setRotation(float x, float y, float z) { - quaternion.setFromEuler(x * FloatUtil.PI / 180.0f, - y * FloatUtil.PI / 180.0f, - z * FloatUtil.PI / 180.0f); - } - public float[] getSceneClearColor() { - return sceneClearColor; - } - - public void setSceneClearColor(float r, float g, float b, float a) { - this.sceneClearColor[0] = r; - this.sceneClearColor[1] = g; - this.sceneClearColor[2] = b; - this.sceneClearColor[3] = a; - } - - private class SBCMouseListener implements MouseListener { - int mouseX = -1; - int mouseY = -1; @Override public void mouseClicked(MouseEvent e) { UIShape uiShape = getActiveUI(); if(uiShape != null){ - uiShape.onClick(e); + uiShape.dispatchMouseEvent(e); } + clear(); + release(); } @Override - public void mousePressed(MouseEvent e) { + public void mousePressed(final MouseEvent e) { if(null==cDrawable) { return; } - mouseX = e.getX(); - mouseY = e.getY(); - GLRunnable runnable = new GLRunnable() { + // 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) { - UIShape s = getShape(drawable, mouseX, mouseY); - if(null != s) { - activeId = getShapes().indexOf(s); - } - else { - activeId = -1; + activeId = pickShape(e.getX(), e.getY()); + final UIShape uiShape = getActiveUI(); + if(uiShape != null) { + uiShape.setPressed(true); + uiShape.dispatchMouseEvent(e); } return false; - } - }; - cDrawable.invoke(true, runnable); - - UIShape uiShape = getActiveUI(); - - if(uiShape != null) { - uiShape.setPressed(true); - uiShape.onPressed(e); - } + } } ); } @Override public void mouseReleased(MouseEvent e) { - UIShape uiShape = getActiveUI(); + final UIShape uiShape = getActiveUI(); if(uiShape != null){ uiShape.setPressed(false); - uiShape.onRelease(e); + uiShape.dispatchMouseEvent(e); } } @Override - public void mouseMoved(MouseEvent e) { } + public void mouseDragged(MouseEvent e) { + final UIShape uiShape = getActiveUI(); + if(uiShape != null) { + uiShape.dispatchMouseEvent(e); + } + } + @Override - public void mouseEntered(MouseEvent e) { } + public void mouseWheelMoved(final MouseEvent e) { + cDrawable.invoke(true, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + activeId = pickShape(lx, ly); + final UIShape uiShape = getActiveUI(); + if(uiShape != null) { + uiShape.dispatchMouseEvent(e); + } + return false; + } } ); + } + @Override - public void mouseExited(MouseEvent e) { } + public void mouseMoved(MouseEvent e) { + lx = e.getX(); + ly = e.getY(); + } @Override - public void mouseDragged(MouseEvent e) { } + public void mouseEntered(MouseEvent e) { } @Override - public void mouseWheelMoved(MouseEvent e) { } - + public void mouseExited(MouseEvent e) { + release(); + clear(); + } } }
\ No newline at end of file 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 65d8baa01..d8b28c518 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 @@ -33,14 +33,15 @@ import java.io.IOException; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; -import com.jogamp.newt.event.MouseEvent; import com.jogamp.opengl.test.junit.graph.demos.MSAATool; +import com.jogamp.opengl.util.PMVMatrix; public class UIGLListener01 extends UIListenerBase01 { @@ -49,19 +50,8 @@ public class UIGLListener01 extends UIListenerBase01 { setMatrix(-20, 00, 0f, -50); try { final Font font = FontFactory.get(FontFactory.UBUNTU).getDefault(); - button = new RIButton(SVertex.factory(), font, "Click me!", 4f, 3f){ - @Override - public void onClick(MouseEvent e) { - } - @Override - public void onPressed(MouseEvent e) { - } - @Override - public void onRelease(MouseEvent e) { - } - - }; - button.translate(2,1); + button = new RIButton(SVertex.factory(), font, "Click me!", 4f, 3f); + button.translate(2,1,0); /** Button defaults ! button.setLabelColor(1.0f,1.0f,1.0f); button.setButtonColor(0.6f,0.6f,0.6f); @@ -95,17 +85,18 @@ public class UIGLListener01 extends UIListenerBase01 { gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - final RegionRenderer regionRenderer = getRegionRenderer(); - - regionRenderer.resetModelview(null); - - regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); - regionRenderer.rotate(gl, getAngle(), 0, 1, 0); - final int[] sampleCount = { 4 }; final float[] translate = button.getTranslate(); - regionRenderer.translate(gl, translate[0], translate[1], 0); - button.drawShape(gl, regionRenderer, sampleCount, false); + + final RegionRenderer regionRenderer = getRegionRenderer(); + final PMVMatrix pmv = regionRenderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(getXTran(), getYTran(), getZoom()); + pmv.glRotatef(getAngle(), 0, 1, 0); + pmv.glTranslatef(translate[0], translate[1], 0); + regionRenderer.updateMatrix(gl); + button.drawShape(gl, regionRenderer, sampleCount); } @Override 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 715beecca..638e4465b 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 @@ -29,6 +29,7 @@ package com.jogamp.opengl.test.junit.graph.demos.ui; import java.util.ArrayList; +import javax.media.nativewindow.NativeWindowException; import javax.media.opengl.GL2ES2; import jogamp.graph.geom.plane.AffineTransform; @@ -42,6 +43,8 @@ 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.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.opengl.math.Quaternion; import com.jogamp.opengl.math.geom.AABBox; public abstract class UIShape { @@ -52,14 +55,16 @@ public abstract class UIShape { protected final ArrayList<OutlineShapeXForm> shapes; protected static final int DIRTY_SHAPE = 1 << 0 ; - protected static final int DIRTY_POSITION = 1 << 1 ; protected static final int DIRTY_REGION = 1 << 2 ; - protected int dirty = DIRTY_SHAPE | DIRTY_POSITION | DIRTY_REGION; + protected int dirty = DIRTY_SHAPE | DIRTY_REGION; protected final AABBox box; - protected final float[] translate = new float[] { 0f, 0f }; - protected final float[] shapeTranslate = new float[] { 0f, 0f }; - protected final float[] shapeScale = new float[] { 1f, 1f }; + protected final float[] translate = new float[] { 0f, 0f, 0f }; + protected final Quaternion rotation = new Quaternion(); + protected final float[] scale = new float[] { 1f, 1f, 1f }; + + protected final float[] shapeTranslate2D = new float[] { 0f, 0f }; + protected final float[] shapeScale2D = new float[] { 1f, 1f }; private GLRegion region = null; protected final float[] color = {0.6f, 0.6f, 0.6f}; @@ -68,6 +73,8 @@ public abstract class UIShape { private boolean down = false; private boolean toggle =false; private boolean toggleable = false; + private boolean enabled = true; + private ArrayList<MouseListener> mouseListeners = new ArrayList<MouseListener>(); public UIShape(Factory<? extends Vertex> factory) { this.vertexFactory = factory; @@ -77,6 +84,9 @@ public abstract class UIShape { public final Vertex.Factory<? extends Vertex> getVertexFactory() { return vertexFactory; } + public boolean isEnabled() { return enabled; } + public void setEnabled(boolean v) { enabled = v; } + /** * Clears all data and reset all states as if this instance was newly created * @param gl TODO @@ -87,12 +97,17 @@ public abstract class UIShape { shapes.clear(); translate[0] = 0f; translate[1] = 0f; - shapeTranslate[0] = 0f; - shapeTranslate[1] = 0f; - shapeScale[0] = 1f; - shapeScale[1] = 1f; + translate[2] = 0f; + rotation.setIdentity(); + scale[0] = 1f; + scale[1] = 1f; + scale[2] = 1f; + shapeTranslate2D[0] = 0f; + shapeTranslate2D[1] = 0f; + shapeScale2D[0] = 1f; + shapeScale2D[1] = 1f; box.reset(); - dirty = DIRTY_SHAPE | DIRTY_POSITION | DIRTY_REGION; + dirty = DIRTY_SHAPE | DIRTY_REGION; } /** @@ -105,43 +120,56 @@ public abstract class UIShape { shapes.clear(); translate[0] = 0f; translate[1] = 0f; - shapeTranslate[0] = 0f; - shapeTranslate[1] = 0f; - shapeScale[0] = 1f; - shapeScale[1] = 1f; + translate[2] = 0f; + rotation.setIdentity(); + scale[0] = 1f; + scale[1] = 1f; + scale[2] = 1f; + shapeTranslate2D[0] = 0f; + shapeTranslate2D[1] = 0f; + shapeScale2D[0] = 1f; + shapeScale2D[1] = 1f; box.reset(); - dirty = DIRTY_SHAPE | DIRTY_POSITION | DIRTY_REGION; + dirty = DIRTY_SHAPE | DIRTY_REGION; } - public final void translate(float tx, float ty) { + public final void setTranslate(float tx, float ty, float tz) { + translate[0] = tx; + translate[1] = ty; + translate[2] = tz; + } + public final void translate(float tx, float ty, float tz) { translate[0] += tx; translate[1] += ty; - dirty |= DIRTY_POSITION; + translate[2] += tz; } - public final float[] getTranslate() { - if( !isShapeDirty() ) { - validatePosition(); - } - return translate; + public final float[] getTranslate() { return translate; } + public final Quaternion getRotation() { return rotation; } + public final void setScale(float sx, float sy, float sz) { + scale[0] = sx; + scale[1] = sy; + scale[2] = sz; } + public final void scale(float sx, float sy, float sz) { + scale[0] *= sx; + scale[1] *= sy; + scale[2] *= sz; + } + public final float[] getScale() { return scale; } public final void translateShape(float tx, float ty) { - shapeTranslate[0] += tx; - shapeTranslate[1] += ty; + shapeTranslate2D[0] += tx; + shapeTranslate2D[1] += ty; } public final void scaleShape(float sx, float sy) { - shapeScale[0] *= sx; - shapeScale[1] *= sy; + shapeScale2D[0] *= sx; + shapeScale2D[1] *= sy; } public final boolean isShapeDirty() { return 0 != ( dirty & DIRTY_SHAPE ) ; } - public final boolean isPositionDirty() { - return 0 != ( dirty & DIRTY_POSITION ) ; - } - public final boolean isRegionDirty() { return 0 != ( dirty & DIRTY_REGION ) ; } @@ -173,9 +201,8 @@ public abstract class UIShape { * @param gl * @param renderer * @param sampleCount - * @param select */ - public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount, boolean select) { + public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount) { final float[] _color; if( isPressed() || toggle ){ _color = selectedColor; @@ -183,23 +210,15 @@ public abstract class UIShape { _color = color; } - if(!select){ - if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) { - gl.glClearColor(_color[0], _color[1], _color[2], 0.0f); - } - renderer.setColorStatic(gl, _color[0], _color[1], _color[2]); + if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) { + gl.glClearColor(_color[0], _color[1], _color[2], 0.0f); } + renderer.setColorStatic(gl, _color[0], _color[1], _color[2]); + getRegion(gl, renderer).draw(gl, renderer, sampleCount); } public final boolean validate(GL2ES2 gl, RegionRenderer renderer) { - if( !validateShape(gl, renderer) ) { - return validatePosition(); - } - return true; - } - - private final boolean validateShape(GL2ES2 gl, RegionRenderer renderer) { if( isShapeDirty() ) { shapes.clear(); box.reset(); @@ -211,39 +230,24 @@ public abstract class UIShape { } dirty &= ~DIRTY_SHAPE; dirty |= DIRTY_REGION; - validatePosition(); - return true; - } - return false; - } - private final boolean validatePosition () { - if( isPositionDirty() && !isShapeDirty() ) { - // Subtract the bbox minx/miny from position, i.e. the shape's offset. - final AABBox box = getBounds(); - final float minX = box.getMinX(); - final float minY = box.getMinY(); - // System.err.println("XXX.UIShape: Position pre: " + translate[0] + " " + translate[1] + ", sbox "+box); - translate(-minX, -minY); - // System.err.println("XXX.UIShape: Position post: " + translate[0] + " " + translate[1] + ", sbox "+box); - dirty &= ~DIRTY_POSITION; return true; } return false; } private final void addToRegion(Region region) { - final boolean hasLocTrans = 0f != shapeTranslate[0] || 0f != shapeTranslate[1]; - final boolean hasLocScale = 1f != shapeScale[0] || 1f != shapeScale[1]; + final boolean hasLocTrans = 0f != shapeTranslate2D[0] || 0f != shapeTranslate2D[1]; + final boolean hasLocScale = 1f != shapeScale2D[0] || 1f != shapeScale2D[1]; final AffineTransform t; if( hasLocScale || hasLocTrans ) { // System.err.printf("UIShape.addToRegion: locTranslate %f x %f, locScale %f x %f%n", // shapeTranslate[0], shapeTranslate[1], shapeScale[0], shapeScale[1]); t = new AffineTransform(); if( hasLocTrans ) { - t.translate(shapeTranslate[0], shapeTranslate[1]); + t.translate(shapeTranslate2D[0], shapeTranslate2D[1]); } if( hasLocScale ) { - t.scale(shapeScale[0], shapeScale[1]); + t.scale(shapeScale2D[0], shapeScale2D[1]); } } else { t = null; @@ -280,6 +284,10 @@ public abstract class UIShape { this.selectedColor[2] = b; } + public String toString() { + return getClass().getSimpleName()+"[enabled "+enabled+", box "+box+"]"; + } + // // Input // @@ -303,9 +311,60 @@ public abstract class UIShape { this.toggleable = toggleable; } - public void onClick(MouseEvent e) { } - public void onPressed(MouseEvent e) { } - public void onRelease(MouseEvent e) { } + public final void addMouseListener(MouseListener l) { + if(l == null) { + return; + } + @SuppressWarnings("unchecked") + ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone(); + clonedListeners.add(l); + mouseListeners = clonedListeners; + } + + public final void removeMouseListener(MouseListener l) { + if (l == null) { + return; + } + @SuppressWarnings("unchecked") + ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone(); + clonedListeners.remove(l); + mouseListeners = clonedListeners; + } + + public final void dispatchMouseEvent(MouseEvent e) { + e.setAttachment(this); + for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) { + final MouseListener l = mouseListeners.get(i); + switch(e.getEventType()) { + case MouseEvent.EVENT_MOUSE_CLICKED: + l.mouseClicked(e); + break; + case MouseEvent.EVENT_MOUSE_ENTERED: + l.mouseEntered(e); + break; + case MouseEvent.EVENT_MOUSE_EXITED: + l.mouseExited(e); + break; + case MouseEvent.EVENT_MOUSE_PRESSED: + l.mousePressed(e); + break; + case MouseEvent.EVENT_MOUSE_RELEASED: + l.mouseReleased(e); + break; + case MouseEvent.EVENT_MOUSE_MOVED: + l.mouseMoved(e); + break; + case MouseEvent.EVENT_MOUSE_DRAGGED: + l.mouseDragged(e); + break; + case MouseEvent.EVENT_MOUSE_WHEEL_MOVED: + l.mouseWheelMoved(e); + break; + default: + throw new NativeWindowException("Unexpected mouse event type " + e.getEventType()); + } + } + } // // @@ -332,6 +391,7 @@ public abstract class UIShape { shape.addVertex(minX+tw, minY + th, z, true); shape.addVertex(minX, minY + th, z, true); shape.closeLastOutline(true); + return shape; } |