aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-03-17 16:14:44 +0100
committerSven Gothel <[email protected]>2014-03-17 16:14:44 +0100
commit6382ee094953fd4fef35a8e60a29b482ae1b79c3 (patch)
treeba1d0f4cc787d553346e854805f6df6433de56d9
parent8e39433ee85835a0e4a8b1bdac6c31c2518ba5b4 (diff)
Bug 801: GraphUI .. Fixed transformations, cleanup - All shape-object oriented actions.
http://jogamp.org/files/screenshots/graphui/01/
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java565
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java160
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java128
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java8
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java92
8 files changed, 685 insertions, 274 deletions
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 72c5d6a17..1d6162233 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
@@ -1,6 +1,9 @@
package com.jogamp.opengl.test.junit.graph.demos;
+import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
@@ -17,15 +20,18 @@ import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.geom.SVertex;
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.opengl.GLWindow;
import com.jogamp.opengl.math.FloatUtil;
-import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.test.junit.graph.demos.ui.CrossHair;
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.test.junit.graph.demos.ui.UIShape;
+import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.glsl.ShaderState;
public class GPUUISceneGLListener0A implements GLEventListener {
@@ -41,6 +47,11 @@ public class GPUUISceneGLListener0A implements GLEventListener {
int fontSet = FontFactory.UBUNTU;
Font font;
+
+ final float relTop = 5f/6f;
+ final float relRight = 2f/6f;
+ final float relLeft = 1f/6f;
+
final float buttonXSize = 84f;
final float buttonYSize = buttonXSize/2.5f;
final float fontSizeFixed = 12f;
@@ -49,16 +60,19 @@ public class GPUUISceneGLListener0A implements GLEventListener {
private int currentText = 0;
+ private String actionText = null;
private Label[] labels = null;
private String[] strings = null;
- private RIButton[] buttons = null;
+ private final List<RIButton> buttons = new ArrayList<RIButton>();
private Label jogampLabel = null;
private Label fpsLabel = null;
- private final int numSelectable = 6;
+ private CrossHair crossHairCtr = null;
private boolean ioAttached = false;
private GLAutoDrawable cDrawable;
+ private final GLReadBufferUtil screenshot;
+
private final String jogamp = "JogAmp - Jogl Graph Module Demo";
public GPUUISceneGLListener0A() {
@@ -82,52 +96,77 @@ public class GPUUISceneGLListener0A implements GLEventListener {
ioe.printStackTrace();
}
sceneUIController = new SceneUIController();
+ screenshot = new GLReadBufferUtil(false, false);
}
- private void rotateButtons(MouseEvent e, float angdeg) {
- for(int i=0; i<buttons.length; i++) {
- rotateInstance(e, buttons[i].getRotation(), angdeg);
+ private void rotateButtons(float[] angdeg) {
+ angdeg = VectorUtil.scaleVec3(angdeg, angdeg, FloatUtil.PI / 180.0f);
+ for(int i=0; i<buttons.size(); i++) {
+ buttons.get(i).getRotation().rotateByEuler( 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 translateButtons(float tx, float ty, float tz) {
+ for(int i=0; i<buttons.size(); i++) {
+ buttons.get(i).translate(tx, ty, tz);
+ }
+ }
+
+ private void setButtonsSpacing(float dx, float dy) {
+ for(int i=0; i<buttons.size(); i++) {
+ final float sx = buttons.get(i).getSpacingX()+dx, sy = buttons.get(i).getSpacingY()+dy;
+ System.err.println("Spacing: X "+sx+", Y "+sy);
+ buttons.get(i).setSpacing(sx, sy);
+ }
+ }
+
+ private void setButtonsCorner(float dc) {
+ for(int i=0; i<buttons.size(); i++) {
+ final float c = buttons.get(i).getCorner()+dc;
+ System.err.println("Corner: "+c);
+ buttons.get(i).setCorner(c);
+ }
+ }
+
+ private void resetButtons() {
+ for(int i=0; i<buttons.size(); i++) {
+ buttons.get(i).getRotation().setIdentity();
+ buttons.get(i).setCorner(RIButton.DEFAULT_CORNER);
+ buttons.get(i).setSpacing(RIButton.DEFAULT_SPACING_X, RIButton.DEFAULT_SPACING_Y);
}
}
- private void initButtons() {
- buttons = new RIButton[numSelectable];
+ private void initButtons(final GL gl, final RegionRenderer renderer) {
+ final boolean pass2Mode = 0 != ( renderer.getRenderModes() & ( Region.VBAA_RENDERING_BIT | Region.MSAA_RENDERING_BIT ) ) ;
+ buttons.clear();
final float xstart = 0f;
final float ystart = 0f;
- final float diff = 1.5f * buttonYSize;
+ final float diffX = 1.2f * buttonXSize;
+ final float diffY = 1.5f * buttonYSize;
- 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() {
+ RIButton button = new RIButton(SVertex.factory(), font, "Next Text", buttonXSize, buttonYSize);
+ button.translate(xstart,ystart-diffY*buttons.size(), 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( null != labels[currentText] ) {
labels[currentText].setEnabled(false);
}
- currentText = (currentText+1)%3;
+ currentText = (currentText+1)%labels.length;
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].translate(xstart,ystart - diff, 0f);
- buttons[1].setToggleable(true);
- buttons[1].setLabelColor(1.0f, 1.0f, 1.0f);
- buttons[1].addMouseListener(new MouseAdapter() {
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ button = new RIButton(SVertex.factory(), font, "Show FPS", buttonXSize, buttonYSize);
+ button.translate(xstart,ystart - diffY*buttons.size(), 0f);
+ button.setToggleable(true);
+ button.setPressed(fpsLabel.isEnabled());
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final GLAnimatorControl a = cDrawable.getAnimator();
@@ -136,13 +175,15 @@ public class GPUUISceneGLListener0A implements GLEventListener {
}
fpsLabel.setEnabled(!fpsLabel.isEnabled());
} } );
- buttons[1].addMouseListener(new DragAndZoomListener(buttons[1]));
-
- 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() {
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ button = new RIButton(SVertex.factory(), font, "v-sync", buttonXSize, buttonYSize);
+ button.translate(xstart,ystart - diffY*buttons.size(), 0f);
+ button.setToggleable(true);
+ button.setPressed(gl.getSwapInterval()>0);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
cDrawable.invoke(false, new GLRunnable() {
@@ -158,56 +199,250 @@ public class GPUUISceneGLListener0A implements GLEventListener {
}
});
} } );
- buttons[2].addMouseListener(new DragAndZoomListener(buttons[2]));
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
- 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[3].addMouseListener(new MouseAdapter() {
+ button = new RIButton(SVertex.factory(), font, "< tilt >", buttonXSize, buttonYSize);
+ button.translate(xstart,ystart - diffY*buttons.size(), 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
- rotateButtons(e, 5f);
+ 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] ) {
+ rotateButtons(new float[] { 0f, -5f, 0f}); // left-half pressed
+ } else {
+ rotateButtons(new float[] { 0f, 5f, 0f}); // right-half pressed
+ }
+ }
+ }
+ @Override
+ public void mouseWheelMoved(MouseEvent e) {
+ rotateButtons(new float[] { 0f, e.getRotation()[1], 0f});
} } );
- buttons[3].addMouseListener(new DragAndZoomListener(buttons[3]));
+ buttons.add(button);
+
+ if( pass2Mode ) { // second column to the left
+ button = new RIButton(SVertex.factory(), font, "< samples >", buttonXSize, buttonYSize);
+ button.translate(xstart,ystart - diffY*buttons.size(), 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.EventDetails ) {
+ final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ int sampleCount = sceneUIController.getSampleCount();
+ if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ // left-half pressed
+ if( sampleCount > 0 ) {
+ sampleCount-=1;
+ }
+ } else {
+ // right-half pressed
+ if( sampleCount < 8 ) {
+ sampleCount+=1;
+ }
+ }
+ sceneUIController.setSampleCount(sampleCount);
+ }
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ }
- 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() {
+ button = new RIButton(SVertex.factory(), font, "Quit", buttonXSize, buttonYSize);
+ button.translate(xstart,ystart - diffY*buttons.size(), 0f);
+ button.setColor(0.8f, 0.0f, 0.0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.setSelectedColor(0.8f, 0.8f, 0.8f);
+ button.setLabelSelectedColor(0.8f, 0.0f, 0.0f);
+ button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
- rotateButtons(e, -5f);
+ new Thread() {
+ public void run() {
+ if( null != cDrawable ) {
+ final GLAnimatorControl actrl = cDrawable.getAnimator();
+ if( null != actrl ) {
+ actrl.stop();
+ }
+ cDrawable.destroy();
+ }
+ } }.start();
} } );
- buttons[4].addMouseListener(new DragAndZoomListener(buttons[4]));
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ // second column to the left
+ {
+ int j = 1; // column
+ int k = 0; // row
+ button = new RIButton(SVertex.factory(), font, "y flip", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ rotateButtons(new float[] { 0f, 180f, 0f});
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ k++;
+ button = new RIButton(SVertex.factory(), font, "x flip", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ rotateButtons(new float[] { 180f, 0f, 0f});
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+
+ button = new RIButton(SVertex.factory(), font, "+", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.EventDetails ) {
+ final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)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] ;
+ // 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();
+ float tx = 0, ty = 0;
+ if ( awdx > awdy ) {
+ tx = dx < 0 ? -5 : 5;
+ } else {
+ ty = dy < 0 ? -5 : 5;
+ }
+ translateButtons(tx, ty, 0f);
+ }
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+
+ button = new RIButton(SVertex.factory(), font, "< space >", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.EventDetails ) {
+ final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ final float dx, dy;
+ if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ dx=-0.01f; dy=-0.005f;
+ } else {
+ dx=0.01f; dy=0.005f;
+ }
+ setButtonsSpacing(dx, dy);
+ }
+ }
+ @Override
+ public void mouseWheelMoved(MouseEvent e) {
+ setButtonsSpacing(e.getRotation()[0]/100f, e.getRotation()[1]/200f);
+ } } );
+ buttons.add(button);
+ k++;
+
+ button = new RIButton(SVertex.factory(), font, "< corner >", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.EventDetails ) {
+ final UIShape.EventDetails shapeEvent = (UIShape.EventDetails)attachment;
+ final float dc;
+ if( shapeEvent.rotPosition[0] < shapeEvent.rotBounds.getCenter()[0] ) {
+ dc=-0.1f;
+ } else {
+ dc=0.1f;
+ }
+ setButtonsCorner(dc);
+ }
- 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);
+ }
+ @Override
+ public void mouseWheelMoved(MouseEvent e) {
+ setButtonsCorner(e.getRotation()[1]/20f);
+ } } );
+ buttons.add(button);
+ k++;
+
+ button = new RIButton(SVertex.factory(), font, "reset", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ resetButtons();
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+
+ button = new RIButton(SVertex.factory(), font, "screenshot", buttonXSize, buttonYSize);
+ button.translate(xstart - diffX*j,ystart - diffY*k, 0f);
+ button.setLabelColor(1.0f, 1.0f, 1.0f);
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ cDrawable.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable drawable) {
+ printScreen(drawable.getGL());
+ return true;
+ }
+ });
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+ }
- 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() {
- strings = new String[3];
-
- strings[0] = "Next Text\n"+
- "Show FPS\n"+
- "abcdefghijklmn\nopqrstuvwxyz\n"+
- "ABCDEFGHIJKL\n"+
- "MNOPQRSTUVWXYZ\n"+
- "0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
-
- strings[1] = "The quick brown fox\njumps over the lazy\ndog";
-
- strings[2] =
+ strings = new String[4];
+ int i = 0;
+
+ strings[i++] =
+ "- Mouse Scroll Over Object\n"+
+ " - General\n"+
+ " - Z Translation\n"+
+ " - Ctrl: Y-Rotation (Shift: X-Rotation)\n"+
+ " - Tilt, Space and Corner\n"+
+ " - Their respective action via wheel (shift = other value)\n"+
+ "\n"+
+ "- Mouse Drag On Object\n"+
+ " - Click on Object and drag mouse\n"+
+ " - Notice current postion in status line at buttom\n"+
+ "\n"+
+ "- Tilt Button Rotate Whole Button Group\n"+
+ "- Window Resize Shall Maintain Layout\n";
+
+ strings[i++] = "abcdefghijklmn\nopqrstuvwxyz\n"+
+ "ABCDEFGHIJKL\n"+
+ "MNOPQRSTUVWXYZ\n"+
+ "0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
+
+ strings[i++] = "The quick brown fox\njumps over the lazy\ndog";
+
+ strings[i++] =
"Lorem ipsum dolor sit amet, consectetur\n"+
"Ut purus odio, rhoncus sit amet com\n"+
"quam iaculis urna cursus ornare. Nullam\n"+
@@ -216,9 +451,12 @@ public class GPUUISceneGLListener0A implements GLEventListener {
"Donec ut dolor et nulla tristique variu\n"+
"in lorem. Maecenas in ipsum ac justo sc\n";
- labels = new Label[3];
+ labels = new Label[i];
}
+
+ final boolean enableOthers = true;
+
@Override
public void init(GLAutoDrawable drawable) {
final Object upObj = drawable.getUpstreamWidget();
@@ -252,6 +490,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
renderer = RegionRenderer.create(rs, renderModes, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ gl.setSwapInterval(1);
gl.glEnable(GL2ES2.GL_DEPTH_TEST);
gl.glEnable(GL2ES2.GL_BLEND);
@@ -259,27 +498,30 @@ public class GPUUISceneGLListener0A implements GLEventListener {
renderer.setAlpha(gl, 1.0f);
initTexts();
- initButtons();
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]);
final float pixelSizeFixed = font.getPixelSize(fontSizeFixed, dpiH);
jogampLabel = new Label(SVertex.factory(), font, pixelSizeFixed, jogamp);
- jogampLabel.addMouseListener(new DragAndZoomListener(jogampLabel));
+ jogampLabel.addMouseListener(dragZoomRotateListener);
sceneUIController.addShape(jogampLabel);
+ jogampLabel.setEnabled(enableOthers);
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));
+ fpsLabel.addMouseListener(dragZoomRotateListener);
sceneUIController.addShape(fpsLabel);
+ fpsLabel.setEnabled(enableOthers);
+
+ crossHairCtr = new CrossHair(renderer.getRenderState().getVertexFactory(), 100f, 100f, 2f);
+ crossHairCtr.addMouseListener(dragZoomRotateListener);
+ sceneUIController.addShape(crossHairCtr);
+ crossHairCtr.setEnabled(true);
+
+ initButtons(gl, renderer);
+ for(int i=0; i<buttons.size(); i++) {
+ sceneUIController.addShape(buttons.get(i));
+ }
sceneUIController.init(drawable);
@@ -303,10 +545,21 @@ public class GPUUISceneGLListener0A implements GLEventListener {
GL2ES2 gl = drawable.getGL().getGL2ES2();
renderer.destroy(gl);
+ screenshot.dispose(gl);
}
- protected void setupPMV(GLAutoDrawable drawable) {
-
+ private int shotCount = 0;
+
+ public void printScreen(final GL gl) {
+ final String modeS = Region.getRenderModeString(renderer.getRenderModes());
+ final String filename = String.format("GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png",
+ shotCount++, renderer.getWidth(), renderer.getHeight(),
+ modeS, sceneUIController.getSampleCount());
+ gl.glFinish(); // just make sure rendering finished ..
+ if(screenshot.readPixels(gl, false)) {
+ screenshot.write(new File(filename));
+ System.err.println("Wrote: "+filename);
+ }
}
@Override
@@ -316,12 +569,13 @@ public class GPUUISceneGLListener0A implements GLEventListener {
if(null == labels[currentText]) {
final float pixelSizeFixed = font.getPixelSize(fontSizeFixed, dpiH);
- float dx = drawable.getWidth() * 1f/3f;
+ final float dyTop = drawable.getHeight() * relTop;
+ final float dxRight = drawable.getWidth() * relRight;
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]));
+ labels[currentText].setEnabled(enableOthers);
+ labels[currentText].translate(dxRight, dyTop - 1.5f * jogampLabel.getLineHeight(), 0f);
+ labels[currentText].addMouseListener(dragZoomRotateListener);
sceneUIController.addShape(labels[currentText]);
}
if( fpsLabel.isEnabled() ) {
@@ -337,29 +591,53 @@ public class GPUUISceneGLListener0A implements GLEventListener {
td = 0f;
}
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",
+ final String text;
+ if( null == actionText ) {
+ 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, sceneUIController.getSampleCount(), td,
renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED),
drawable.getChosenGLCapabilities().getAlphaBits());
- fpsLabel.clear(gl, renderer);
+ } else {
+ text = String.format("%03.1f/%03.1f fps, v-sync %d, fontSize %.1f, %s",
+ lfps, tfps, gl.getSwapInterval(), fontSizeFixed, actionText);
+ }
fpsLabel.setText(text);
}
sceneUIController.display(drawable);
}
+ float lastWidth = 0f, lastHeight = 0f;
+
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
System.err.println("GPUUISceneGLListener0A: reshape");
- float dx = width * 1f/3f;
- jogampLabel.setTranslate(dx, 0f, 0f);
- fpsLabel.setTranslate(0f, 0f, 0f); // FIXME
+ //
+ // Layout all shapes: Relational move regarding window coordinates
+ //
+ final float dw = width - lastWidth;
+ final float dh = height - lastHeight;
+
+ final float dz = 0f;
+ final float dyTop = dh * relTop;
+ final float dxRight = dw * relRight;
+ final float dxLeft = dw * relLeft;
+
+ for(int i=0; i<buttons.size(); i++) {
+ buttons.get(i).translate(dxLeft, dyTop, dz);
+ }
+ jogampLabel.translate(dxRight, dyTop, dz);
+ fpsLabel.translate(0f, 0f, 0f);
if( null != labels[currentText] ) {
- labels[currentText].setTranslate(dx, -3f * jogampLabel.getLineHeight(), 0f);
+ labels[currentText].translate(dxRight, dyTop, 0f);
}
+ crossHairCtr.translate(dw/2f, dh/2f, 0f);
sceneUIController.reshape(drawable, x, y, width, height);
+
+ lastWidth = width;
+ lastHeight = height;
}
public void attachInputListenerTo(GLWindow window) {
@@ -376,68 +654,73 @@ public class GPUUISceneGLListener0A implements GLEventListener {
}
}
- private class DragAndZoomListener extends MouseAdapter {
- final UIShape shape;
- int lx=-1, ly=-1;
- boolean first = false;
-
- public DragAndZoomListener(UIShape shape) {
- this.shape = shape;
- }
+ /**
+ * 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;
+ boolean dragFirst = false;
@Override
public void mousePressed(MouseEvent e) {
- first = true;
+ dragFirst = true;
}
@Override
public void mouseReleased(MouseEvent e) {
- first = false;
+ dragFirst = false;
+ actionText = null;
}
@Override
public void mouseDragged(MouseEvent e) {
- if(e.getPointerCount()==2) {
- // 2 pointers zoom ..
- if(first) {
- lx = Math.abs(e.getY(0)-e.getY(1));
- first=false;
- return;
- }
- int nv = Math.abs(e.getY(0)-e.getY(1));
- int dy = nv - lx;
- lx = nv;
+ 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;
- shape.translate(0f, 0f, 2 * Math.signum(dy));
- } else {
- // 1 pointer drag
- if(first) {
- lx = e.getX();
- ly = e.getY();
- first=false;
- return;
- }
- int nx = e.getX();
- int ny = e.getY();
- int dx = nx - lx;
- int dy = ny - ly;
- if(Math.abs(dx) > Math.abs(dy)){
- shape.translate(Math.signum(dx), 0f, 0f);
+ shapeEvent.shape.translate(0f, 0f, 2 * Math.signum(dy));
} else {
- shape.translate(0f, -Math.signum(dy), 0f);
+ // 1 pointer drag
+ if(dragFirst) {
+ dragLastX = e.getX();
+ dragLastY = 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();
+ actionText = String.format("Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]);
}
- lx = nx;
- ly = ny;
}
}
@Override
public void mouseWheelMoved(MouseEvent e) {
- if( !e.isShiftDown() ) {
- float tz = 2f*e.getRotation()[1]; // vertical: wheel
- System.err.println("tz.4 "+tz);
- shape.translate(0f, 0f, tz);
+ 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 = 2f*e.getRotation()[1]; // vertical: wheel
+ System.err.println("tz.4 "+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/GPUUISceneNewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java
index a371aa8b2..127d30aae 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java
@@ -33,7 +33,7 @@ public class GPUUISceneNewtDemo01 {
textGLListener.attachInputListenerTo(window);
final Animator animator = new Animator();
- animator.setUpdateFPSFrames(60, System.err);
+ animator.setUpdateFPSFrames(60, null);//System.err);
animator.add(window);
window.addWindowListener(new WindowAdapter() {
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java
index 32c3a9439..61d833f59 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java
@@ -34,7 +34,7 @@ public class GPUUISceneNewtDemo02 {
textGLListener.attachInputListenerTo(window);
final Animator animator = new Animator();
- animator.setUpdateFPSFrames(60, System.err);
+ animator.setUpdateFPSFrames(60, null); // System.err);
animator.add(window);
window.addWindowListener(new WindowAdapter() {
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 16ee148e8..78c42b2d0 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
@@ -103,6 +103,8 @@ public class Label extends UIShape {
@Override
protected void createShape(GL2ES2 gl, RegionRenderer renderer) {
TextRegionUtil.processString(shapeVisitor, new AffineTransform(), font, pixelSize, text);
+ final float[] ctr = box.getCenter();
+ setRotationOrigin( ctr[0], ctr[1], ctr[2]);
}
@Override
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 83ca6bed0..cfce04dd0 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
@@ -41,19 +41,24 @@ import com.jogamp.opengl.math.geom.AABBox;
* GPU based resolution independent Button impl
*/
public class RIButton extends UIShape {
+ /** {@value} */
+ public static final float DEFAULT_SPACING_X = 0.08f;
+ /** {@value} */
+ public static final float DEFAULT_SPACING_Y = 0.40f;
+ /** {@value} */
+ public static final float DEFAULT_CORNER = 1f;
+
private float width, height;
private final Label label;
- /** 20 % to each side default */
- private float spacing = 0.2f;
- private static final float spacingSx = 2f;
- private static final float spacingSy = 2f;
- private float corner = 1.0f;
+ private float spacingX = DEFAULT_SPACING_X;
+ private float spacingY = DEFAULT_SPACING_Y;
+ private float corner = DEFAULT_CORNER;
private float labelZOffset = -0.05f;
public RIButton(Factory<? extends Vertex> factory, Font labelFont, String labelText, float width, float height) {
super(factory);
- final float pixelSize = height * ( 1f - spacingSy*spacing ) ;
+ final float pixelSize = height * ( 1f - spacingY ) ;
System.err.printf("RIButton: height %f -> pixelSize %f%n", height, pixelSize);
this.label = new Label(factory, labelFont, pixelSize, labelText);
this.label.setSelectedColor(this.color[0], this.color[1], this.color[2]);
@@ -66,10 +71,10 @@ public class RIButton extends UIShape {
public final float getWidth() { return width; }
public final float getHeight() { return height; }
- public float getCorner() { return corner; }
- public Label getLabel() { return label; }
+ public final float getCorner() { return corner; }
+ public final Label getLabel() { return label; }
- public void setDimension(int width, int height) {
+ public void setDimension(float width, float height) {
this.width = width;
this.height = height;
dirty |= DIRTY_SHAPE | DIRTY_REGION;
@@ -97,55 +102,63 @@ public class RIButton extends UIShape {
@Override
protected void createShape(GL2ES2 gl, RegionRenderer renderer) {
+ label.clear(gl, renderer);
+
+ final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
+ if(corner == 0.0f) {
+ createSharpOutline(shape);
+ } else {
+ createCurvedOutline(shape);
+ }
+ box.resize(shape.getBounds());
+
// Precompute text-box size .. guessing pixelSize
- final float lw = getWidth() * ( 1f - spacingSx*spacing );
- final float lh = getHeight() * ( 1f - spacingSy*spacing );
- final AABBox lbox0 = label.font.getStringBounds(label.text, lh);
+ final float lPixelSize0 = 10f;
+ final float lw = width * ( 1f - spacingX ) ;
+ final float lh = height * ( 1f - spacingY ) ;
+ final AABBox lbox0 = label.font.getStringBounds(label.text, lPixelSize0);
final float lsx = lw / lbox0.getWidth();
final float lsy = lh / lbox0.getHeight();
+ final float lPixelSize1 = lsx < lsy ? lPixelSize0 * lsx : lPixelSize0 * lsy;
if( DRAW_DEBUG_BOX ) {
- final float sx = getWidth() / ( ( spacingSx*spacing + 1f ) * lbox0.getWidth() * lsx );
- final float sy = getHeight() / ( ( spacingSy*spacing + 1f ) * lbox0.getHeight() * lsy );
- System.err.printf("RIButton: bsize %f x %f, lsize %f x %f, lbox0 %f x %f -> ls %f x %f, bs %f x %f .... %s%n",
- getWidth(), getHeight(), lw, lh, lbox0.getWidth(), lbox0.getHeight(), lsx, lsy, sx, sy, this.label.text);
+ System.err.println("RIButton: spacing "+spacingX+", "+spacingY);
+ System.err.println("RIButton: bbox "+box);
+ System.err.println("RIButton: lbox "+lbox0);
+ System.err.println("RIButton: net-text "+lw+" x "+lh);
+ System.err.println("RIButton: lsx "+lsx+", lsy "+lsy+": pixelSize "+lPixelSize0+" -> "+lPixelSize1);
}
// Setting pixelSize based on actual text-box size
- final float lPixelSize1 = lh * lsy;
label.setPixelSize(lPixelSize1);
label.createShape(gl, renderer);
final AABBox lbox1 = label.getBounds();
if( DRAW_DEBUG_BOX ) {
- final float lsx1 = lw / lbox1.getWidth();
- final float lsy1 = lh / lbox1.getHeight();
- System.err.printf("RIButton: ls %f x %f, lbox1 %s .... %s%n",
- lsx1, lsy1, lbox1, this.label.text);
- }
-
- final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
- if(corner == 0.0f) {
- createSharpOutline(shape, lbox1);
- } else {
- createCurvedOutline(shape, lbox1);
+ System.err.printf("RIButton: lbox1 %s .... %s%n", lbox1, this.label.text);
}
- box.resize(shape.getBounds());
- // Center text ..
+ // Center text .. (share same center w/ button)
final float[] lctr = lbox1.getCenter();
final float[] ctr = box.getCenter();
- label.translateShape( ctr[0] - lctr[0], ctr[1] - lctr[1] );
+ final float[] ltx = new float[] { ctr[0] - lctr[0], ctr[1] - lctr[1], 0f };
+ label.translateShape( ltx[0], ltx[1] );
+ lbox1.translate( ltx );
+
+ // rotate center of button/label ..
+ label.setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+ setRotationOrigin( ctr[0], ctr[1], ctr[2]);
shapes.add(new OutlineShapeXForm(shape, null));
+
if( DRAW_DEBUG_BOX ) {
System.err.println("XXX.UIShape.RIButton: Added Shape: "+shape+", "+box);
}
}
- private void createSharpOutline(OutlineShape shape, AABBox lbox) {
- final float tw = getWidth(); // ( spacingSx*spacing + 1f ) * lbox.getWidth();
- final float th = getHeight(); // ( spacingSy*spacing + 1f ) * lbox.getHeight();
+ private void createSharpOutline(OutlineShape shape) {
+ final float tw = getWidth();
+ final float th = getHeight();
- final float minX = lbox.getMinX() - ( spacingSx / 2f * spacing * lbox.getWidth() );
- final float minY = lbox.getMinY() - ( spacingSy / 2f * spacing * lbox.getHeight() );
+ final float minX = 0;
+ final float minY = 0;
final float minZ = labelZOffset;
shape.addVertex(minX, minY, minZ, true);
@@ -154,33 +167,34 @@ public class RIButton extends UIShape {
shape.addVertex(minX, minY + th, minZ, true);
shape.closeLastOutline(true);
}
- private void createCurvedOutline(OutlineShape shape, AABBox lbox){
- final float tw = getWidth(); // ( spacingSx*spacing + 1f ) * lbox.getWidth();
- final float th = getHeight(); // ( spacingSy*spacing + 1f ) * lbox.getHeight();
- final float cw = 0.5f*corner*Math.min(tw, th);
- final float ch = 0.5f*corner*Math.min(tw, th);
+ private void createCurvedOutline(OutlineShape shape) {
+ final float tw = getWidth();
+ final float th = getHeight();
+ final float dC = 0.5f*corner*Math.min(tw, th);
- final float minX = lbox.getMinX() - ( spacingSx / 2f * spacing * getWidth() ); // lbox.getWidth() );
- final float minY = lbox.getMinY() - ( spacingSy / 2f * spacing * getHeight() ); // lbox.getHeight() );
+ final float minX = 0;
+ final float minY = 0;
final float minZ = labelZOffset;
- shape.addVertex(minX, minY + ch, minZ, true);
+ shape.addVertex(minX, minY + dC, minZ, true);
shape.addVertex(minX, minY, minZ, false);
- shape.addVertex(minX + cw, minY, minZ, true);
-
- shape.addVertex(minX + tw - cw, minY, minZ, true);
- shape.addVertex(minX + tw, minY, minZ, false);
- shape.addVertex(minX + tw, minY + ch, minZ, true);
- shape.addVertex(minX + tw, minY + th- ch, minZ, true);
- shape.addVertex(minX + tw, minY + th, minZ, false);
- shape.addVertex(minX + tw - cw, minY + th, minZ, true);
- shape.addVertex(minX + cw, minY + th, minZ, true);
- shape.addVertex(minX, minY + th, minZ, false);
- shape.addVertex(minX, minY + th - ch, minZ, true);
+ shape.addVertex(minX + dC, minY, minZ, true);
+
+ shape.addVertex(minX + tw - dC, minY, minZ, true);
+ shape.addVertex(minX + tw, minY, minZ, false);
+ shape.addVertex(minX + tw, minY + dC, minZ, true);
+ shape.addVertex(minX + tw, minY + th- dC, minZ, true);
+ shape.addVertex(minX + tw, minY + th, minZ, false);
+ shape.addVertex(minX + tw - dC, minY + th, minZ, true);
+ shape.addVertex(minX + dC, minY + th, minZ, true);
+ shape.addVertex(minX, minY + th, minZ, false);
+ shape.addVertex(minX, minY + th - dC, minZ, true);
+
shape.closeLastOutline(true);
}
+ /** Set corner size, default is {@link #DEFAULT_CORNER} */
public void setCorner(float corner) {
if(corner > 1.0f){
this.corner = 1.0f;
@@ -202,18 +216,28 @@ public class RIButton extends UIShape {
this.labelZOffset = -labelZOffset;
dirty |= DIRTY_SHAPE | DIRTY_REGION;
}
- public float getSpacing() {
- return spacing;
- }
+ public final float getSpacingX() { return spacingX; }
+ public final float getSpacingY() { return spacingY; }
- /** In percent of text label */
- public void setSpacing(float spacing) {
- if ( spacing < 0.0f ) {
- this.spacing = 0.0f;
- } else if ( spacing > 1.0f ) {
- this.spacing = 1.0f;
+ /**
+ * In percent of text label
+ * @param spacingX spacing in percent on X, default is {@link #DEFAULT_SPACING_X}
+ * @param spacingY spacing in percent on Y, default is {@link #DEFAULT_SPACING_Y}
+ */
+ public void setSpacing(float spacingX, float spacingY) {
+ if ( spacingX < 0.0f ) {
+ this.spacingX = 0.0f;
+ } else if ( spacingX > 1.0f ) {
+ this.spacingX = 1.0f;
+ } else {
+ this.spacingX = spacingX;
+ }
+ if ( spacingY < 0.0f ) {
+ this.spacingY = 0.0f;
+ } else if ( spacingY > 1.0f ) {
+ this.spacingY = 1.0f;
} else {
- this.spacing = spacing;
+ this.spacingY = spacingY;
}
dirty |= DIRTY_SHAPE | DIRTY_REGION;
}
@@ -232,8 +256,8 @@ public class RIButton extends UIShape {
@Override
public String toString() {
- return "RIButton [" + getWidth() + "x" + getHeight() + ", "
- + getLabel() + ", " + "spacing: " + spacing
- + ", " + "corner: " + corner + ", " + "shapeOffset: " + labelZOffset + " ]";
+ return "RIButton [" + translate[0]+getWidth()/2f+" / "+translate[1]+getHeight()/2f+" "+getWidth() + "x" + getHeight() + ", "
+ + getLabel() + ", " + "spacing: " + spacingX+"/"+spacingY
+ + ", " + "corner: " + corner + ", " + "shapeOffset: " + labelZOffset + ", "+box+" ]";
}
}
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 fbdc72a1f..2dab54277 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
@@ -13,15 +13,18 @@ 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.Matrix;
+import com.jogamp.opengl.math.Quaternion;
import com.jogamp.opengl.math.Ray;
+import com.jogamp.opengl.math.VectorUtil;
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 float sceneStartX = 0f;
- private float sceneStartY = 0f;
+ private final float sceneDist = 1000f;
private RegionRenderer renderer;
@@ -31,8 +34,8 @@ public class SceneUIController implements GLEventListener{
/** 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 final float[] sceneScale = new float[3];
+ private final float[] scenePlaneOrigin = new float[3];
private int activeId = -1;
@@ -78,7 +81,16 @@ public class SceneUIController implements GLEventListener{
}
public int getSampleCount() { return sampleCount[0]; }
- public void setSampleCount(int v) { sampleCount[0]=v; }
+ public void setSampleCount(int v) { sampleCount[0]=v; markAllShapesDirty(); }
+
+ public void markAllShapesDirty() {
+ for(int i=0; i<shapes.size(); i++) {
+ shapes.get(i).markDirty();
+ }
+ }
+
+ public final float[] getSceneScale() { return sceneScale; }
+ public final float[] getScenePlaneOrigin() { return scenePlaneOrigin; }
@Override
public void init(GLAutoDrawable drawable) {
@@ -86,7 +98,7 @@ public class SceneUIController implements GLEventListener{
cDrawable = drawable;
}
- public int pickShape(final int winX, int winY) {
+ public int pickShape(final int glWinX, final int glWinY) {
final float winZ0 = 0f;
final float winZ1 = 0.3f;
/**
@@ -95,9 +107,6 @@ public class SceneUIController implements GLEventListener{
winZ1 = winZRB.get(0); // dir
*/
- // flip to GL window coordinates
- winY = viewport[3] - winY;
-
final PMVMatrix pmv = renderer.getMatrix();
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
@@ -109,13 +118,13 @@ public class SceneUIController implements GLEventListener{
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.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);
+ // System.err.println("Test: "+box+" -> hit "+hit+", shape: "+uiShape);
if( hit ) {
return i;
}
@@ -124,14 +133,35 @@ public class SceneUIController implements GLEventListener{
return -1;
}
+ final Matrix m = new Matrix();
+
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]);
+ // final float dz = 100f;
+
+ final Quaternion quat = uiShape.getRotation();
+ final boolean rotate = !quat.isIdentity();
+ final float[] uiScale = uiShape.getScale();
+ final boolean scale = !VectorUtil.isVec3Equal(uiScale, 0, VectorUtil.VEC3_ONE, 0, FloatUtil.EPSILON);
+ if( rotate || scale ) {
+ final float[] rotOrigin = uiShape.getRotationOrigin();
+ final boolean pivot = !VectorUtil.isVec3Zero(rotOrigin, 0, FloatUtil.EPSILON);
+ // pmv.glTranslatef(0f, 0f, dz);
+ if( pivot ) {
+ pmv.glTranslatef(rotOrigin[0], rotOrigin[1], rotOrigin[2]);
+ }
+ if( scale ) {
+ pmv.glScalef(uiScale[0], uiScale[1], uiScale[2]);
+ }
+ if( rotate ) {
+ pmv.glRotate(quat);
+ }
+ if( pivot ) {
+ pmv.glTranslatef(-rotOrigin[0], -rotOrigin[1], -rotOrigin[2]);
+ }
+ // pmv.glTranslatef(0f, 0f, -dz);
+ }
}
@Override
@@ -154,7 +184,6 @@ public class SceneUIController implements GLEventListener{
renderer.updateMatrix(gl);
uiShape.drawShape(gl, renderer, sampleCount);
pmv.glPopMatrix();
- // break;
}
}
}
@@ -173,16 +202,13 @@ public class SceneUIController implements GLEventListener{
pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0);
}
- @Override
+ @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;
- sceneStartX = width * 1f/6f;
- sceneStartY = height - height/6f;
-
final GL2ES2 gl = drawable.getGL().getGL2ES2();
final PMVMatrix pmv = renderer.getMatrix();
renderer.reshapePerspective(gl, 45.0f, width, height, zNear, zFar);
@@ -212,24 +238,20 @@ public class SceneUIController implements GLEventListener{
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);
+ scenePlaneOrigin[0] = nearPlane1Box.getMinX() * sceneDist;
+ scenePlaneOrigin[1] = nearPlane1Box.getMinY() * sceneDist;
+ scenePlaneOrigin[2] = nearPlane1Box.getMinZ() * sceneDist;
+ sceneScale[0] = ( nearPlane1Box.getWidth() * sceneDist ) / width;
+ sceneScale[1] = ( nearPlane1Box.getHeight() * sceneDist ) / height;
+ sceneScale[2] = 1f;
+ System.err.printf("Scene Origin [%f, %f, %f]%n", scenePlaneOrigin[0], scenePlaneOrigin[1], scenePlaneOrigin[2]);
+ System.err.printf("Scene Scale %f * [%f x %f] / [%d x %d] = [%f, %f, %f]%n",
+ sceneDist, nearPlane1Box.getWidth(), nearPlane1Box.getHeight(),
+ width, height,
+ sceneScale[0], sceneScale[1], sceneScale[2]);
+
+ pmv.glTranslatef(scenePlaneOrigin[0], scenePlaneOrigin[1], scenePlaneOrigin[2]);
+ pmv.glScalef(sceneScale[0], sceneScale[1], sceneScale[2]);
renderer.updateMatrix(gl);
}
@@ -255,7 +277,7 @@ public class SceneUIController implements GLEventListener{
public void mouseClicked(MouseEvent e) {
UIShape uiShape = getActiveUI();
if(uiShape != null){
- uiShape.dispatchMouseEvent(e);
+ uiShape.dispatchMouseEvent(e, e.getX(), viewport[3]-e.getY());
}
clear();
release();
@@ -267,18 +289,22 @@ public class SceneUIController implements GLEventListener{
return;
}
+ // 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(e.getX(), e.getY());
+ activeId = pickShape(glWinX, glWinY);
final UIShape uiShape = getActiveUI();
if(uiShape != null) {
uiShape.setPressed(true);
- uiShape.dispatchMouseEvent(e);
+ uiShape.dispatchMouseEvent(e, glWinX, glWinY);
}
- return false;
+ return true;
} } );
}
@@ -287,7 +313,7 @@ public class SceneUIController implements GLEventListener{
final UIShape uiShape = getActiveUI();
if(uiShape != null){
uiShape.setPressed(false);
- uiShape.dispatchMouseEvent(e);
+ uiShape.dispatchMouseEvent(e, e.getX(), viewport[3]-e.getY());
}
}
@@ -295,21 +321,25 @@ public class SceneUIController implements GLEventListener{
public void mouseDragged(MouseEvent e) {
final UIShape uiShape = getActiveUI();
if(uiShape != null) {
- uiShape.dispatchMouseEvent(e);
+ uiShape.dispatchMouseEvent(e, e.getX(), viewport[3]-e.getY());
}
}
@Override
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(lx, ly);
+ activeId = pickShape(glWinX, glWinY);
final UIShape uiShape = getActiveUI();
if(uiShape != null) {
- uiShape.dispatchMouseEvent(e);
+ uiShape.dispatchMouseEvent(e, glWinX, glWinY);
}
- return false;
+ return true;
} } );
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
index ecd22ef71..6c192e37d 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
@@ -258,12 +258,12 @@ public abstract class UIListenerBase01 implements GLEventListener {
move(-1, 0);
}
else if(arg0.getKeyCode() == KeyEvent.VK_4){
- button.setSpacing(button.getSpacing()-0.01f);
- System.err.println("Button Spacing: " + button.getSpacing());
+ button.setSpacing(button.getSpacingX()-0.01f, button.getSpacingY()-0.005f);
+ System.err.println("Button Spacing: " + button.getSpacingX());
}
else if(arg0.getKeyCode() == KeyEvent.VK_5){
- button.setSpacing(button.getSpacing()+0.01f);
- System.err.println("Button Spacing: " + button.getSpacing());
+ button.setSpacing(button.getSpacingX()+0.01f, button.getSpacingY()+0.005f);
+ System.err.println("Button Spacing: " + button.getSpacingX());
}
else if(arg0.getKeyCode() == KeyEvent.VK_6){
button.setCorner(button.getCorner()-0.01f);
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 638e4465b..58c237e8c 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
@@ -42,9 +42,11 @@ 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.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 {
@@ -61,6 +63,7 @@ public abstract class UIShape {
protected final AABBox box;
protected final float[] translate = new float[] { 0f, 0f, 0f };
protected final Quaternion rotation = new Quaternion();
+ protected final float[] rotOrigin = new float[] { 0f, 0f, 0f };
protected final float[] scale = new float[] { 1f, 1f, 1f };
protected final float[] shapeTranslate2D = new float[] { 0f, 0f };
@@ -99,6 +102,9 @@ public abstract class UIShape {
translate[1] = 0f;
translate[2] = 0f;
rotation.setIdentity();
+ rotOrigin[0] = 0f;
+ rotOrigin[1] = 0f;
+ rotOrigin[2] = 0f;
scale[0] = 1f;
scale[1] = 1f;
scale[2] = 1f;
@@ -122,6 +128,9 @@ public abstract class UIShape {
translate[1] = 0f;
translate[2] = 0f;
rotation.setIdentity();
+ rotOrigin[0] = 0f;
+ rotOrigin[1] = 0f;
+ rotOrigin[2] = 0f;
scale[0] = 1f;
scale[1] = 1f;
scale[2] = 1f;
@@ -133,24 +142,32 @@ public abstract class UIShape {
dirty = DIRTY_SHAPE | DIRTY_REGION;
}
- public final void setTranslate(float tx, float ty, float tz) {
+ public void setTranslate(float tx, float ty, float tz) {
translate[0] = tx;
translate[1] = ty;
translate[2] = tz;
+ // System.err.println("UIShape.setTranslate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
- public final void translate(float tx, float ty, float tz) {
+ public void translate(float tx, float ty, float tz) {
translate[0] += tx;
translate[1] += ty;
translate[2] += tz;
+ // System.err.println("UIShape.translate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
public final float[] getTranslate() { return translate; }
public final Quaternion getRotation() { return rotation; }
- public final void setScale(float sx, float sy, float sz) {
+ public final float[] getRotationOrigin() { return rotOrigin; }
+ public void setRotationOrigin(float rx, float ry, float rz) {
+ rotOrigin[0] = rx;
+ rotOrigin[1] = ry;
+ rotOrigin[2] = rz;
+ }
+ public 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) {
+ public void scale(float sx, float sy, float sz) {
scale[0] *= sx;
scale[1] *= sy;
scale[2] *= sz;
@@ -166,6 +183,9 @@ public abstract class UIShape {
shapeScale2D[1] *= sy;
}
+ public final void markDirty() {
+ dirty = DIRTY_SHAPE | DIRTY_REGION;
+ }
public final boolean isShapeDirty() {
return 0 != ( dirty & DIRTY_SHAPE ) ;
}
@@ -204,7 +224,7 @@ public abstract class UIShape {
*/
public void drawShape(GL2ES2 gl, RegionRenderer renderer, int[] sampleCount) {
final float[] _color;
- if( isPressed() || toggle ){
+ if( isPressed() || toggle ) {
_color = selectedColor;
} else {
_color = color;
@@ -230,9 +250,9 @@ public abstract class UIShape {
}
dirty &= ~DIRTY_SHAPE;
dirty |= DIRTY_REGION;
- return true;
+ return false;
}
- return false;
+ return true;
}
private final void addToRegion(Region region) {
@@ -285,7 +305,7 @@ public abstract class UIShape {
}
public String toString() {
- return getClass().getSimpleName()+"[enabled "+enabled+", box "+box+"]";
+ return getClass().getSimpleName()+"[enabled "+enabled+", "+translate[0]+" / "+translate[1]+", box "+box+"]";
}
//
@@ -331,8 +351,57 @@ public abstract class UIShape {
mouseListeners = clonedListeners;
}
- public final void dispatchMouseEvent(MouseEvent e) {
- e.setAttachment(this);
+ /**
+ * {@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 latter fields are also normalized to lower-left zero origin, allowing easier usage.
+ */
+ public static class EventDetails {
+ /** 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) {
+ this.shape = shape;
+ this.rotBounds = rotatedBounds;
+ this.rotPosition = rotatedRelPos;
+ }
+
+ public String toString() {
+ return "EventDetails[pos "+rotPosition[0]+", "+rotPosition[1]+", "+rotPosition[2]+
+ ", "+rotBounds+", "+shape+"]";
+ }
+ }
+
+ /**
+ *
+ * @param e original Newt {@link MouseEvent}
+ * @param glX x-position in OpenGL model space
+ * @param glY x-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));
+
for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
final MouseListener l = mouseListeners.get(i);
switch(e.getEventType()) {
@@ -346,9 +415,11 @@ public abstract class UIShape {
l.mouseExited(e);
break;
case MouseEvent.EVENT_MOUSE_PRESSED:
+ markDirty();
l.mousePressed(e);
break;
case MouseEvent.EVENT_MOUSE_RELEASED:
+ markDirty();
l.mouseReleased(e);
break;
case MouseEvent.EVENT_MOUSE_MOVED:
@@ -386,6 +457,7 @@ public abstract class UIShape {
final float minY = box.getMinY();
final float z = box.getMinZ() + 0.025f;
+ // CCW!
shape.addVertex(minX, minY, z, true);
shape.addVertex(minX+tw, minY, z, true);
shape.addVertex(minX+tw, minY + th, z, true);