summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-03-28 04:41:10 +0200
committerSven Gothel <[email protected]>2023-03-28 04:41:10 +0200
commit55b552bb87fb1fefcf53dd7784a53d605969de96 (patch)
treea470a11d7327637202a6cbefdd564e96182e8c04
parent34632c59b5f664c41ef52a4abb9e3e1b484657d4 (diff)
GraphUI: Decouple GraphShape from Shape, i.e. allow future Shape w/o Graph/GLRegion
-rw-r--r--make/scripts/tests.sh6
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java170
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java4
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java4
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java4
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java4
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java4
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java179
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java12
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java311
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java10
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java6
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java3
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java3
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java32
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java3
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java6
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java6
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java7
19 files changed, 469 insertions, 305 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 66a960869..69ff56d40 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -955,6 +955,7 @@ function testawtswt() {
#
# Graph
#
+#testnoawt com.jogamp.opengl.test.junit.graph.TestFontScale01NOUI $*
#testnoawt com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.TestFontsNEWT00 $*
#testnoawt com.jogamp.opengl.test.junit.graph.TestTextRendererNEWTBugXXXX $*
@@ -1011,10 +1012,11 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo00 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo01 $*
+#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo01b $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo02 $*
-testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo03 $*
+#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo03 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo10 $*
-#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo20 $*
+testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo20 $*
#testnoawt com.jogamp.opengl.demos.av.MovieCube $*
#testnoawt com.jogamp.opengl.demos.av.MovieSimple $*
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
index 433521933..82f09a38a 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
@@ -45,6 +45,7 @@ import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.font.FontScale;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.graph.ui.gl.Scene;
import com.jogamp.graph.ui.gl.Scene.PMVMatrixSetup;
import com.jogamp.graph.ui.gl.Shape;
@@ -264,6 +265,7 @@ public class UISceneDemo20 implements GLEventListener {
private int renderModes;
private final Font font;
+ private final Font fontButtons;
private final Font fontFPS;
private final Uri filmURL;
@@ -363,7 +365,9 @@ public class UISceneDemo20 implements GLEventListener {
}
System.err.println("Font "+font.getFullFamilyName());
- fontFPS = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMonoBold.ttf",
+ fontButtons = FontFactory.get(FontFactory.UBUNTU).getDefault();
+
+ fontFPS = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMono.ttf",
FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
System.err.println("Font FPS "+fontFPS.getFullFamilyName());
@@ -389,11 +393,6 @@ public class UISceneDemo20 implements GLEventListener {
buttons.get(i).getRotation().rotateByEuler( angdeg );
}
}
- private void translateButtons(final float tx, final float ty, final float tz) {
- for(int i=0; i<buttons.size(); i++) {
- buttons.get(i).move(tx, ty, tz);
- }
- }
private void setButtonsSpacing(final float dx, final float dy) {
for(int i=0; i<buttons.size(); i++) {
@@ -445,14 +444,14 @@ public class UISceneDemo20 implements GLEventListener {
final float buttonYSize = buttonXSize / 2.5f;
final float button2XSize = 2f*buttonXSize;
final float button2YSize = 2f*buttonYSize;
- System.err.println("Button Size: scale "+scale+", "+buttonXSize+" x "+buttonYSize);
+ System.err.println("Button Size: "+buttonXSize+" x "+buttonYSize+", scale "+scale);
final float xStartLeft = 0f; // aligned to left edge w/ space via reshape
final float xStartRight = -button2XSize - button2XSize/8f; // aligned to right edge via reshape
final float yStartTop = 0f; // aligned to top edge w/ space via reshape
final float diffX = 1.2f * buttonXSize;
final float diffY = 1.5f * buttonYSize;
- Button button = new Button(renderModes, font, "Next Text", buttonXSize, buttonYSize);
+ Button button = new Button(renderModes, fontButtons, " Next Text ", buttonXSize, buttonYSize);
button.setName(BUTTON_NEXTTEXT);
button.move(xStartLeft, yStartTop-diffY*buttons.size(), 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@@ -469,7 +468,7 @@ public class UISceneDemo20 implements GLEventListener {
button.addMouseListener(dragZoomRotateListener);
buttons.add(button);
- button = new Button(renderModes, font, "Show FPS", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "Show fps", buttonXSize, buttonYSize);
button.setName(BUTTON_FPS);
button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.setToggleable(true);
@@ -486,7 +485,7 @@ public class UISceneDemo20 implements GLEventListener {
button.addMouseListener(dragZoomRotateListener);
buttons.add(button);
- button = new Button(renderModes, font, "V-Sync", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, " V-Sync ", buttonXSize, buttonYSize);
button.setName(BUTTON_VSYNC);
button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.setToggleable(true);
@@ -510,7 +509,7 @@ public class UISceneDemo20 implements GLEventListener {
button.addMouseListener(dragZoomRotateListener);
buttons.add(button);
- button = new Button(renderModes, font, "< Tilt >", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "< Tilt >", buttonXSize, buttonYSize);
button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -529,7 +528,7 @@ public class UISceneDemo20 implements GLEventListener {
buttons.add(button);
if( pass2Mode ) { // second column to the left
- button = new Button(renderModes, font, "< Samples >", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "< Samples >", buttonXSize, buttonYSize);
button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -548,32 +547,34 @@ public class UISceneDemo20 implements GLEventListener {
button.addMouseListener(dragZoomRotateListener);
buttons.add(button);
- button = new Button(renderModes, font, "< Quality >", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "< Quality >", buttonXSize, buttonYSize);
button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
- int quality = shapeEvent.shape.getQuality();
+ if( shapeEvent.shape instanceof GraphShape ) {
+ int quality = ((GraphShape)shapeEvent.shape).getQuality();
- if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
- // left-half pressed
- if( quality > 0 ) {
- quality--;
- }
- } else {
- // right-half pressed
- if( quality < Region.MAX_QUALITY ) {
- quality++;
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
+ // left-half pressed
+ if( quality > 0 ) {
+ quality--;
+ }
+ } else {
+ // right-half pressed
+ if( quality < Region.MAX_QUALITY ) {
+ quality++;
+ }
}
+ scene.setAllShapesQuality(quality);
}
- scene.setAllShapesQuality(quality);
} } );
button.addMouseListener(dragZoomRotateListener);
buttons.add(button);
}
- button = new Button(renderModes, font, "Quit", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "Quit", buttonXSize, buttonYSize);
button.setName(BUTTON_QUIT);
button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.setColor(0.7f, 0.0f, 0.0f, 1.0f);
@@ -601,7 +602,7 @@ public class UISceneDemo20 implements GLEventListener {
{
final int j = 1; // column
int k = 0; // row
- button = new Button(renderModes, font, "Y Flip", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "Y Flip", buttonXSize, buttonYSize);
button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -612,7 +613,7 @@ public class UISceneDemo20 implements GLEventListener {
buttons.add(button);
k++;
- button = new Button(renderModes, font, "X Flip", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "X Flip", buttonXSize, buttonYSize);
button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -623,7 +624,7 @@ public class UISceneDemo20 implements GLEventListener {
buttons.add(button);
k++;
- button = new Button(renderModes, font, "< Space >", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "< Space >", buttonXSize, buttonYSize);
button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -644,7 +645,7 @@ public class UISceneDemo20 implements GLEventListener {
buttons.add(button);
k++;
- button = new Button(renderModes, font, "< Corner >", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "< Corner >", buttonXSize, buttonYSize);
button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -665,7 +666,7 @@ public class UISceneDemo20 implements GLEventListener {
buttons.add(button);
k++;
- button = new Button(renderModes, font, "Reset", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, " Reset ", buttonXSize, buttonYSize);
button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -676,7 +677,7 @@ public class UISceneDemo20 implements GLEventListener {
buttons.add(button);
k++;
- button = new Button(renderModes, font, "Snapshot", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, " Snapshot ", buttonXSize, buttonYSize);
button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -727,8 +728,7 @@ public class UISceneDemo20 implements GLEventListener {
}
if( true ) {
final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true);
- final ImageButton imgButton = new ImageButton(renderModes, button2XSize,
- button2YSize, imgSeq);
+ final ImageButton imgButton = new ImageButton(renderModes, button2XSize, button2YSize, imgSeq);
try {
imgSeq.addFrame(gl, UISceneDemo20.class, "button-released-145x53.png", TextureIO.PNG);
imgSeq.addFrame(gl, UISceneDemo20.class, "button-pressed-145x53.png", TextureIO.PNG);
@@ -777,9 +777,8 @@ public class UISceneDemo20 implements GLEventListener {
System.err.println("Gears Anim: End");
}
}).start();
- final GLButton b = new GLButton(renderModes, button2XSize,
- button2YSize, texUnitGLELButton,
- gears, false /* useAlpha */);
+ final GLButton b = new GLButton(renderModes, button2XSize, button2YSize,
+ texUnitGLELButton, gears, false /* useAlpha */);
b.setName(BUTTON_GLEL);
b.setToggleable(true);
b.setToggle(false); // toggle == true -> animation
@@ -833,44 +832,27 @@ public class UISceneDemo20 implements GLEventListener {
private static final boolean enableOthers = true;
- private void setupUI(final GLAutoDrawable drawable, final AABBox sceneBox) {
- final float[/*2*/] sceneSize = { 0f, 0f };
- scene.surfaceToPlaneSize(new int[] { 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()}, sceneSize);
-
- final float modelSizeFixed = fontSizeFixedNorm * sceneSize[1];
- jogampLabel = new Label(renderModes, font, modelSizeFixed, jogamp);
+ private void initLabels(final GL2ES2 gl) {
+ jogampLabel = new Label(renderModes, font, fontSizeFixedNorm, jogamp);
jogampLabel.addMouseListener(dragZoomRotateListener);
- scene.addShape(jogampLabel);
jogampLabel.setEnabled(enableOthers);
+ scene.addShape(jogampLabel);
- final float pixelSize10Pt = FontScale.toPixels(fontSizePt, dpiV);
- final float modelSize10Pt = pixelSize10Pt / drawable.getSurfaceHeight() * sceneSize[1];
- System.err.println("10Pt PixelSize: Display "+dpiV+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixe-size, "+modelSize10Pt+" model-size");
- truePtSizeLabel = new Label(renderModes, font, modelSize10Pt, truePtSize);
- scene.addShape(truePtSizeLabel);
+ truePtSizeLabel = new Label(renderModes, font, truePtSize);
truePtSizeLabel.setEnabled(enableOthers);
- truePtSizeLabel.move(0, - 1.5f * jogampLabel.getLineHeight(), 0f);
truePtSizeLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f);
+ scene.addShape(truePtSizeLabel);
/**
*
* [Label] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 18.814816
* [FPS] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 15.679012
*/
- final float pixelSizeFPS = fontSizeFpsNorm * drawable.getSurfaceHeight();
- final float modelSizeFPS = pixelSizeFPS / drawable.getSurfaceHeight() * sceneSize[1];
- fpsLabel = new Label(renderModes, fontFPS, modelSizeFPS, "Nothing there yet");
+ fpsLabel = new Label(renderModes, fontFPS, "Nothing there yet");
fpsLabel.addMouseListener(dragZoomRotateListener);
- scene.addShape(fpsLabel);
fpsLabel.setEnabled(enableOthers);
fpsLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f);
- fpsLabel.move(0f, modelSizeFPS * (fontFPS.getMetrics().getLineGap() - fontFPS.getMetrics().getDescent()), 0f);
-
- final float sx = sceneBox.getWidth();
- final float sy = sceneBox.getHeight();
- final float sxy = sx > sy ? sx : sy;
- initButtons(drawable.getGL().getGL2ES2(), sxy);
- scene.addShapes(buttons);
+ scene.addShape(fpsLabel);
}
@Override
@@ -920,6 +902,7 @@ public class UISceneDemo20 implements GLEventListener {
gl.glEnable(GL.GL_BLEND);
initTexts();
+ initLabels(gl);
scene.init(drawable);
@@ -937,20 +920,24 @@ public class UISceneDemo20 implements GLEventListener {
// Layout all shapes: Relational move regarding object coordinates
//
System.err.println("Reshape: Scene Plane.0 "+scene.getBounds());
- final float lastWidth = scene.getBounds().getWidth();
- final float lastHeight = scene.getBounds().getHeight();
- System.err.println("Reshape: Scene Plane.0 "+lastWidth+" x "+lastHeight);
+ final float lastSceneWidth = scene.getBounds().getWidth();
+ final float lastSceneHeight = scene.getBounds().getHeight();
+ System.err.println("Reshape: Scene Plane.0 "+lastSceneWidth+" x "+lastSceneHeight);
scene.reshape(drawable, x, y, width, height);
final AABBox sceneBox = scene.getBounds();
System.err.println("Reshape: Scene Plane.1 "+sceneBox);
- if( scene.getShapes().isEmpty() ) {
- setupUI(drawable, sceneBox);
+ final float sceneWidth = sceneBox.getWidth();
+ final float sceneHeight = sceneBox.getHeight();
+ final float button_sxy = sceneWidth > sceneHeight ? sceneWidth : sceneHeight;
+ if( buttons.isEmpty() ) {
+ initButtons(drawable.getGL().getGL2ES2(), button_sxy);
+ scene.addShapes(buttons);
}
- final float dw = sceneBox.getWidth() - lastWidth;
- final float dh = sceneBox.getHeight() - lastHeight;
+ final float dw = sceneWidth - lastSceneWidth;
+ final float dh = sceneHeight - lastSceneHeight;
final float dz = 0f;
final float dyTop = dh * relTop;
@@ -970,16 +957,33 @@ public class UISceneDemo20 implements GLEventListener {
// System.err.println("Button["+i+"].RM: "+buttons.get(i));
}
- final float dxMiddleAbs = sceneBox.getWidth() * relMiddle;
- final float dyTopLabelAbs = sceneBox.getHeight() - 2f*jogampLabel.getLineHeight();
- jogampLabel.moveTo(dxMiddleAbs, dyTopLabelAbs, dz);
- truePtSizeLabel.moveTo(dxMiddleAbs, dyTopLabelAbs, dz);
- truePtSizeLabel.moveTo(dxMiddleAbs, dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight(), 0f);
- fpsLabel.move(0f, 0f, 0f);
+ jogampLabel.setScale(sceneHeight, sceneHeight, 1f);
+
+ final float dxMiddleAbs = sceneWidth * relMiddle;
+ final float dyTopLabelAbs = sceneHeight - jogampLabel.getScaledLineHeight();
+ jogampLabel.moveTo(dxMiddleAbs, dyTopLabelAbs - jogampLabel.getScaledLineHeight(), dz);
+ {
+ final float pixelSize10Pt = FontScale.toPixels(fontSizePt, dpiV);
+ final float scale = pixelSize10Pt / height * sceneHeight; // normalize with dpi / surfaceHeight
+ System.err.println("10Pt PixelSize: Display "+dpiV+" dpi, fontSize "+fontSizePt+" pt, "+FontScale.ptToMM(fontSizePt)+" mm -> "+pixelSize10Pt+" pixels, "+scale+" scene-size");
+ truePtSizeLabel.setScale(scale, scale, 1f);
+ truePtSizeLabel.moveTo(dxMiddleAbs, dyTopLabelAbs - jogampLabel.getScaledLineHeight() - truePtSizeLabel.getScaledLineHeight(), dz);
+ }
+ {
+ final AABBox fbox = fontFPS.getGlyphBounds(scene.getStatusText(drawable, renderModes, fpsLabel.getQuality(), dpiV));
+ final float scale = sceneWidth / ( 1.4f * fbox.getWidth() ); // add 40% width
+ fpsLabel.setScale(scale, scale, 1f);
+ fpsLabel.moveTo(sceneBox.getMinX(), sceneBox.getMinY() + scale * ( fontFPS.getMetrics().getLineGap() - fontFPS.getMetrics().getDescent() ), 0f);
+ fpsLabel.validate(drawable.getGL().getGL2ES2());
+ System.err.println("StatusLabel Scale: " + scale + " = " + sceneWidth + " / " + fbox.getWidth() + ", " + fbox);
+ System.err.println("StatusLabel: " + fpsLabel);
+ }
if( null != labels[currentText] ) {
+ labels[currentText].setScale(sceneHeight, sceneHeight, 1f);
labels[currentText].moveTo(dxMiddleAbs,
- dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight()
- - 1.5f * truePtSizeLabel.getLineHeight(), 0f);
+ dyTopLabelAbs - jogampLabel.getScaledLineHeight()
+ - 1.5f * truePtSizeLabel.getScaledLineHeight()
+ - labels[currentText].getScaledHeight(), 0f);
System.err.println("Label["+currentText+"] MOVE: "+labels[currentText]);
System.err.println("Label["+currentText+"] MOVE: "+Arrays.toString(labels[currentText].getPosition()));
}
@@ -1017,15 +1021,19 @@ public class UISceneDemo20 implements GLEventListener {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
if(null == labels[currentText]) {
- final float pixelSizeFixed = fontSizeFixedNorm * scene.getBounds().getHeight();
- final float dyTop = scene.getBounds().getHeight() - 2f*jogampLabel.getLineHeight();
- final float dxMiddle = scene.getBounds().getWidth() * relMiddle;
- labels[currentText] = new Label(renderModes, font, pixelSizeFixed, strings[currentText]);
+ final AABBox sbox = scene.getBounds();
+ final float sceneHeight = sbox.getHeight();
+ final float dyTop = sbox.getHeight() - jogampLabel.getScaledLineHeight();
+ final float dxMiddle = sbox.getWidth() * relMiddle;
+ labels[currentText] = new Label(renderModes, font, fontSizeFixedNorm, strings[currentText]);
+ labels[currentText].setScale(sceneHeight, sceneHeight, 1f);
labels[currentText].setColor(0.1f, 0.1f, 0.1f, 1.0f);
labels[currentText].setEnabled(enableOthers);
+ labels[currentText].validate(gl);
labels[currentText].move(dxMiddle,
- dyTop - 1.5f * jogampLabel.getLineHeight()
- - 1.5f * truePtSizeLabel.getLineHeight(), 0f);
+ dyTop - jogampLabel.getScaledLineHeight()
+ - 1.5f * truePtSizeLabel.getScaledLineHeight()
+ - labels[currentText].getScaledHeight(), 0f);
labels[currentText].addMouseListener(dragZoomRotateListener);
scene.addShape(labels[currentText]);
System.err.println("Label["+currentText+"] CTOR: "+labels[currentText]);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java
index f467b7a9d..6d6b69063 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java
@@ -29,14 +29,14 @@ package com.jogamp.opengl.demos.graph.ui.testshapes;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.geom.plane.Winding;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
* GPU based resolution independent test object
* - Ubuntu-Light, lower case 'o'
* - TTF Shape for Glyph 82
*/
-public class Glyph01UbuntuLight_o extends Shape {
+public class Glyph01UbuntuLight_o extends GraphShape {
public Glyph01UbuntuLight_o(final int renderModes) {
super(renderModes);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java
index 92284060f..2ee21a9f6 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java
@@ -28,14 +28,14 @@
package com.jogamp.opengl.demos.graph.ui.testshapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
* GPU based resolution independent test object
* - Ubuntu-Light, lower case 'æ'
* - TTF Shape for Glyph 193
*/
-public class Glyph02UbuntuLight_ae extends Shape {
+public class Glyph02UbuntuLight_ae extends GraphShape {
public Glyph02UbuntuLight_ae(final int renderModes) {
super(renderModes);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java
index 266d96c93..8d8fd2133 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java
@@ -28,14 +28,14 @@
package com.jogamp.opengl.demos.graph.ui.testshapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
* GPU based resolution independent test object
* - FreeMono-Regular, capital case 'M'
* - TTF Shape for Glyph 48
*/
-public class Glyph03FreeMonoRegular_M extends Shape {
+public class Glyph03FreeMonoRegular_M extends GraphShape {
public Glyph03FreeMonoRegular_M(final int renderModes) {
super(renderModes);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java
index 4f89d14f1..8bab9d5c7 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java
@@ -28,14 +28,14 @@
package com.jogamp.opengl.demos.graph.ui.testshapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
* GPU based resolution independent test object
* - FreeSans, '0'
* - TTF Shape for Glyph 19
*/
-public class Glyph04FreeSans_0 extends Shape {
+public class Glyph04FreeSans_0 extends GraphShape {
public Glyph04FreeSans_0(final int renderModes) {
super(renderModes);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java
index 726565129..ed461d0b8 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java
@@ -28,14 +28,14 @@
package com.jogamp.opengl.demos.graph.ui.testshapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
* GPU based resolution independent test object
* - FreeSans, '0'
* - TTF Shape for Glyph 19
*/
-public class Glyph05FreeSerifBoldItalic_ae extends Shape {
+public class Glyph05FreeSerifBoldItalic_ae extends GraphShape {
public Glyph05FreeSerifBoldItalic_ae(final int renderModes) {
super(renderModes);
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java b/src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java
new file mode 100644
index 000000000..85037ccd4
--- /dev/null
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/GraphShape.java
@@ -0,0 +1,179 @@
+/**
+ * Copyright 2010-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.graph.ui.gl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.geom.AABBox;
+
+/**
+ * Graph based {@link GLRegion} UI {@link Shape}
+ * <p>
+ * GraphUI is GPU based and resolution independent.
+ * </p>
+ * <p>
+ * GraphUI is intended to become an immediate- and retained-mode API.
+ * </p>
+ * @see Scene
+ */
+public abstract class GraphShape extends Shape {
+ protected final Factory<? extends Vertex> vertexFactory;
+
+ protected final int renderModes;
+ protected GLRegion region = null;
+ protected float oshapeSharpness = OutlineShape.DEFAULT_SHARPNESS;
+ private int regionQuality = Region.MAX_QUALITY;
+ private final List<GLRegion> dirtyRegions = new ArrayList<GLRegion>();
+
+ public GraphShape(final int renderModes) {
+ super();
+ this.vertexFactory = OutlineShape.getDefaultVertexFactory();
+ this.renderModes = renderModes;
+ }
+
+ public final int getRenderModes() { return renderModes; }
+
+ public final int getQuality() { return regionQuality; }
+ public final void setQuality(final int q) {
+ this.regionQuality = q;
+ if( null != region ) {
+ region.setQuality(q);
+ }
+ }
+ public final void setSharpness(final float sharpness) {
+ this.oshapeSharpness = sharpness;
+ markShapeDirty();
+ }
+ public final float getSharpness() {
+ return oshapeSharpness;
+ }
+
+ @Override
+ public boolean hasColorChannel() {
+ return Region.hasColorChannel(renderModes) || Region.hasColorTexture(renderModes);
+ }
+
+ private final void clearDirtyRegions(final GL2ES2 gl) {
+ for(final GLRegion r : dirtyRegions) {
+ r.destroy(gl);
+ }
+ dirtyRegions.clear();
+ }
+
+ @Override
+ protected final void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer) {
+ clearImpl(gl, renderer);
+ clearDirtyRegions(gl);
+ if( null != region ) {
+ region.clear(gl);
+ }
+ }
+
+ @Override
+ protected final void destroyImpl0(final GL2ES2 gl, final RegionRenderer renderer) {
+ destroyImpl(gl, renderer);
+ clearDirtyRegions(gl);
+ if( null != region ) {
+ region.destroy(gl);
+ region = null;
+ }
+ }
+
+ @Override
+ protected final void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, final float[] rgba) {
+ if( null != rgba ) {
+ renderer.getRenderState().setColorStatic(rgba);
+ }
+ region.draw(gl, renderer, sampleCount);
+ }
+
+ protected GLRegion createGLRegion(final GLProfile glp) {
+ return GLRegion.create(glp, renderModes, null);
+ }
+
+ @Override
+ protected final void validateImpl(final GLProfile glp, final GL2ES2 gl) {
+ if( null != gl ) {
+ clearDirtyRegions(gl);
+ }
+ if( isShapeDirty() || null == region ) {
+ if( null == region ) {
+ region = createGLRegion(glp);
+ } else if( null == gl ) {
+ dirtyRegions.add(region);
+ region = createGLRegion(glp);
+ } else {
+ region.clear(gl);
+ }
+ addShapeToRegion();
+ region.setQuality(regionQuality);
+ } else if( isStateDirty() ) {
+ region.markStateDirty();
+ }
+ }
+
+ protected OutlineShape createDebugOutline(final OutlineShape shape, final AABBox box) {
+ final float d = 0.025f;
+ final float tw = box.getWidth() + d*2f;
+ final float th = box.getHeight() + d*2f;
+
+ final float minX = box.getMinX() - d;
+ final float minY = box.getMinY() - d;
+ final float z = 0; // box.getMinZ() + 0.025f;
+
+ // CCW!
+ shape.moveTo(minX, minY, z);
+ shape.lineTo(minX+tw, minY, z);
+ shape.lineTo(minX+tw, minY + th, z);
+ shape.lineTo(minX, minY + th, z);
+ shape.closePath();
+
+ // shape.addVertex(minX, minY, z, true);
+ // shape.addVertex(minX+tw, minY, z, true);
+ // shape.addVertex(minX+tw, minY + th, z, true);
+ // shape.addVertex(minX, minY + th, z, true);
+ // shape.closeLastOutline(true);
+
+ return shape;
+ }
+
+ protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+
+ protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+
+
+}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
index e40152a02..16f695a2f 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
@@ -246,12 +246,18 @@ public final class Scene implements GLEventListener {
public void setAllShapesQuality(final int q) {
for(int i=0; i<shapes.size(); i++) {
- shapes.get(i).setQuality(q);
+ final Shape shape = shapes.get(i);
+ if( shape instanceof GraphShape ) {
+ ((GraphShape)shape).setQuality(q);
+ }
}
}
public void setAllShapesSharpness(final float sharpness) {
for(int i=0; i<shapes.size(); i++) {
- shapes.get(i).setSharpness(sharpness);
+ final Shape shape = shapes.get(i);
+ if( shape instanceof GraphShape ) {
+ ((GraphShape)shape).setSharpness(sharpness);
+ }
}
}
public void markAllShapesDirty() {
@@ -351,7 +357,7 @@ public final class Scene implements GLEventListener {
// FIXME
// System.err.printf("drawGL: color %f, index %d of [0..%d[%n", color, i, shapeCount);
renderer.getRenderState().setColorStatic(color, color, color, 1f);
- shape.drawGLSelect(gl, renderer, sampleCount0);
+ shape.drawToSelect(gl, renderer, sampleCount0);
} else {
shape.draw(gl, renderer, sampleCount0);
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java
index 9a91b7649..94fc471f2 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java
@@ -28,19 +28,12 @@
package com.jogamp.graph.ui.gl;
import java.util.ArrayList;
-import java.util.List;
import com.jogamp.nativewindow.NativeWindowException;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
-import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Vertex.Factory;
-import com.jogamp.graph.geom.plane.AffineTransform;
import com.jogamp.newt.event.GestureHandler.GestureEvent;
import com.jogamp.newt.event.GestureHandler.GestureListener;
import com.jogamp.newt.event.MouseAdapter;
@@ -55,13 +48,16 @@ import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.PMVMatrix;
/**
- * GraphUI Shape
+ * Generic UI Shape, potentially using a Graph via {@link GraphShape} or other means of representing content.
* <p>
* A shape includes the following build-in user-interactions
* - drag shape w/ 1-pointer click, see {@link #setDraggable(boolean)}
* - resize shape w/ 1-pointer click and drag in 1/4th bottom-left and bottom-right corner, see {@link #setResizable(boolean)}.
* </p>
* <p>
+ * A shape is expected to have its 0/0 origin in its bottom-left corner, otherwise the drag-zoom sticky-edge will not work as expected.
+ * </p>
+ * <p>
* GraphUI is GPU based and resolution independent.
* </p>
* <p>
@@ -79,25 +75,13 @@ public abstract class Shape {
private static final int DIRTY_SHAPE = 1 << 0 ;
private static final int DIRTY_STATE = 1 << 1 ;
- protected final Factory<? extends Vertex> vertexFactory;
- private final int renderModes;
protected final AABBox box;
- protected final AffineTransform tempT1 = new AffineTransform();
- protected final AffineTransform tempT2 = new AffineTransform();
- protected final AffineTransform tempT3 = new AffineTransform();
- protected final AffineTransform tempT4 = new AffineTransform();
-
private final float[] position = new float[] { 0f, 0f, 0f };
private final Quaternion rotation = new Quaternion();
private final float[] rotOrigin = new float[] { 0f, 0f, 0f };
private final float[] scale = new float[] { 1f, 1f, 1f };
- protected GLRegion region = null;
- protected float oshapeSharpness = OutlineShape.DEFAULT_SHARPNESS;
- private int regionQuality = Region.MAX_QUALITY;
- private final List<GLRegion> dirtyRegions = new ArrayList<GLRegion>();
-
private volatile int dirty = DIRTY_SHAPE | DIRTY_STATE;
private final Object dirtySync = new Object();
@@ -122,9 +106,7 @@ public abstract class Shape {
private Listener onMoveListener = null;
- public Shape(final int renderModes) {
- this.vertexFactory = OutlineShape.getDefaultVertexFactory();
- this.renderModes = renderModes;
+ public Shape() {
this.box = new AABBox();
}
@@ -138,36 +120,27 @@ public abstract class Shape {
/** Enable or disable this shape, i.e. its visibility. */
public final void setEnabled(final boolean v) { enabled = v; }
- private final void clearDirtyRegions(final GL2ES2 gl) {
- for(final GLRegion r : dirtyRegions) {
- r.destroy(gl);
- }
- dirtyRegions.clear();
- }
-
/**
* Clears all data and reset all states as if this instance was newly created
* @param gl TODO
* @param renderer TODO
*/
public final void clear(final GL2ES2 gl, final RegionRenderer renderer) {
- clearImpl(gl, renderer);
- clearDirtyRegions(gl);
- if( null != region ) {
- region.clear(gl);
+ synchronized ( dirtySync ) {
+ clearImpl0(gl, renderer);
+ position[0] = 0f;
+ position[1] = 0f;
+ position[2] = 0f;
+ rotation.setIdentity();
+ rotOrigin[0] = 0f;
+ rotOrigin[1] = 0f;
+ rotOrigin[2] = 0f;
+ scale[0] = 1f;
+ scale[1] = 1f;
+ scale[2] = 1f;
+ box.reset();
+ markShapeDirty();
}
- position[0] = 0f;
- position[1] = 0f;
- position[2] = 0f;
- rotation.setIdentity();
- rotOrigin[0] = 0f;
- rotOrigin[1] = 0f;
- rotOrigin[2] = 0f;
- scale[0] = 1f;
- scale[1] = 1f;
- scale[2] = 1f;
- box.reset();
- markShapeDirty();
}
/**
@@ -176,12 +149,7 @@ public abstract class Shape {
* @param renderer
*/
public final void destroy(final GL2ES2 gl, final RegionRenderer renderer) {
- destroyImpl(gl, renderer);
- clearDirtyRegions(gl);
- if( null != region ) {
- region.destroy(gl);
- region = null;
- }
+ destroyImpl0(gl, renderer);
position[0] = 0f;
position[1] = 0f;
position[2] = 0f;
@@ -198,6 +166,7 @@ public abstract class Shape {
public final void onMove(final Listener l) { onMoveListener = l; }
+ /** Move to scaled position. Position ends up in PMVMatrix w/o scaling. */
public final void moveTo(final float tx, final float ty, final float tz) {
position[0] = tx;
position[1] = ty;
@@ -207,40 +176,58 @@ public abstract class Shape {
}
// System.err.println("Shape.setTranslate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
- public final void move(final float tx, final float ty, final float tz) {
- position[0] += tx;
- position[1] += ty;
- position[2] += tz;
+
+ /** Move about scaled distance. Position ends up in PMVMatrix w/o scaling. */
+ public final void move(final float dtx, final float dty, final float dtz) {
+ position[0] += dtx;
+ position[1] += dty;
+ position[2] += dtz;
if( null != onMoveListener ) {
onMoveListener.run(this);
}
// System.err.println("Shape.translate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
- /** Returns float[3] position, i.e. translation. */
+ /** Returns float[3] position, i.e. unscaled translation. */
public final float[] getPosition() { return position; }
- /** Returns float[3] rotation in degrees. */
+
+ /** Returns {@link Quaternion} for rotation. */
public final Quaternion getRotation() { return rotation; }
- public final float[] getRotationOrigin() { return rotOrigin; }
- public final void setRotationOrigin(final float rx, final float ry, final float rz) {
+ /** Return float[3] unscaled rotation origin, aka pivot. */
+ public final float[] getRotationPivot() { return rotOrigin; }
+ /** Set unscaled rotation origin, aka pivot. Usually the {@link #getBounds()} center and should be set while {@link #validateImpl(GLProfile, GL2ES2)}. */
+ public final void setRotationPivot(final float rx, final float ry, final float rz) {
rotOrigin[0] = rx;
rotOrigin[1] = ry;
rotOrigin[2] = rz;
}
+ /**
+ * Set unscaled rotation origin, aka pivot. Usually the {@link #getBounds()} center and should be set while {@link #validateImpl(GLProfile, GL2ES2)}.
+ * @param pivot float[3] rotation origin
+ */
+ public final void setRotationPivot(final float[/*3*/] pivot) {
+ System.arraycopy(pivot, 0, rotOrigin, 0, 3);
+ }
+
+ /** Set scale factor to given scale. */
public final void setScale(final float sx, final float sy, final float sz) {
scale[0] = sx;
scale[1] = sy;
scale[2] = sz;
}
+ /** Multiply current scale factor by given scale. */
public final void scale(final float sx, final float sy, final float sz) {
scale[0] *= sx;
scale[1] *= sy;
scale[2] *= sz;
}
- /** Returns float[3] scale factors */
+ /** Returns float[3] scale factors. */
public final float[] getScale() { return scale; }
+ /** Returns X-axis scale factor. */
public final float getScaleX() { return scale[0]; }
+ /** Returns Y-axis scale factor. */
public final float getScaleY() { return scale[1]; }
+ /** Returns Z-axis scale factor. */
public final float getScaleZ() { return scale[2]; }
/**
@@ -263,10 +250,10 @@ public abstract class Shape {
}
}
- private final boolean isShapeDirty() {
+ protected final boolean isShapeDirty() {
return 0 != ( dirty & DIRTY_SHAPE ) ;
}
- private final boolean isStateDirty() {
+ protected final boolean isStateDirty() {
return 0 != ( dirty & DIRTY_STATE ) ;
}
@@ -321,94 +308,72 @@ public abstract class Shape {
return box;
}
- public final int getRenderModes() { return renderModes; }
-
- public GLRegion getRegion(final GL2ES2 gl) {
- validate(gl);
- return region;
- }
-
- /** Experimental OpenGL selection draw command used by {@link Scene}. */
- public void drawGLSelect(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ /** Experimental selection draw command used by {@link Scene}. */
+ public void drawToSelect(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
synchronized ( dirtySync ) {
validate(gl);
- region.draw(gl, renderer, sampleCount);
+ drawImpl0(gl, renderer, sampleCount, null);
}
}
+ private final float[] rgba_tmp = { 0, 0, 0, 1 };
+
/**
- * Renders {@link OutlineShape} using local {@link GLRegion} which might be cached or updated.
+ * Renders the shape.
* <p>
- * No matrix operations (translate, scale, ..) are performed.
+ * {@link #setTransform(PMVMatrix)} is expected to be completed beforehand.
* </p>
* @param gl the current GL object
- * @param renderer the used {@link RegionRenderer}, also source of {@link RegionRenderer#getMatrix()} and {@link RegionRenderer#getViewport()}.
+ * @param renderer {@link RegionRenderer} which might be used for Graph Curve Rendering, also source of {@link RegionRenderer#getMatrix()} and {@link RegionRenderer#getViewport()}.
* @param sampleCount sample count if used by Graph renderModes
*/
public void draw(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
- final float r, g, b, a;
final boolean isPressed = isPressed(), isToggleOn = isToggleOn();
- final boolean modBaseColor = !Region.hasColorChannel( renderModes ) && !Region.hasColorTexture( renderModes );
- if( modBaseColor ) {
+ final float[] rgba;
+ if( hasColorChannel() ) {
if( isPressed ) {
- r = rgbaColor[0]*pressedRGBAModulate[0];
- g = rgbaColor[1]*pressedRGBAModulate[1];
- b = rgbaColor[2]*pressedRGBAModulate[2];
- a = rgbaColor[3]*pressedRGBAModulate[3];
+ rgba = pressedRGBAModulate;
} else if( isToggleable() ) {
if( isToggleOn ) {
- r = rgbaColor[0]*toggleOnRGBAModulate[0];
- g = rgbaColor[1]*toggleOnRGBAModulate[1];
- b = rgbaColor[2]*toggleOnRGBAModulate[2];
- a = rgbaColor[3]*toggleOnRGBAModulate[3];
+ rgba = toggleOnRGBAModulate;
} else {
- r = rgbaColor[0]*toggleOffRGBAModulate[0];
- g = rgbaColor[1]*toggleOffRGBAModulate[1];
- b = rgbaColor[2]*toggleOffRGBAModulate[2];
- a = rgbaColor[3]*toggleOffRGBAModulate[3];
+ rgba = toggleOffRGBAModulate;
}
} else {
- r = rgbaColor[0];
- g = rgbaColor[1];
- b = rgbaColor[2];
- a = rgbaColor[3];
+ rgba = rgbaColor;
}
} else {
+ rgba = rgba_tmp;
if( isPressed ) {
- r = pressedRGBAModulate[0];
- g = pressedRGBAModulate[1];
- b = pressedRGBAModulate[2];
- a = pressedRGBAModulate[3];
+ rgba[0] = rgbaColor[0]*pressedRGBAModulate[0];
+ rgba[1] = rgbaColor[1]*pressedRGBAModulate[1];
+ rgba[2] = rgbaColor[2]*pressedRGBAModulate[2];
+ rgba[3] = rgbaColor[3]*pressedRGBAModulate[3];
} else if( isToggleable() ) {
if( isToggleOn ) {
- r = toggleOnRGBAModulate[0];
- g = toggleOnRGBAModulate[1];
- b = toggleOnRGBAModulate[2];
- a = toggleOnRGBAModulate[3];
+ rgba[0] = rgbaColor[0]*toggleOnRGBAModulate[0];
+ rgba[1] = rgbaColor[1]*toggleOnRGBAModulate[1];
+ rgba[2] = rgbaColor[2]*toggleOnRGBAModulate[2];
+ rgba[3] = rgbaColor[3]*toggleOnRGBAModulate[3];
} else {
- r = toggleOffRGBAModulate[0];
- g = toggleOffRGBAModulate[1];
- b = toggleOffRGBAModulate[2];
- a = toggleOffRGBAModulate[3];
+ rgba[0] = rgbaColor[0]*toggleOffRGBAModulate[0];
+ rgba[1] = rgbaColor[1]*toggleOffRGBAModulate[1];
+ rgba[2] = rgbaColor[2]*toggleOffRGBAModulate[2];
+ rgba[3] = rgbaColor[3]*toggleOffRGBAModulate[3];
}
} else {
- r = rgbaColor[0];
- g = rgbaColor[1];
- b = rgbaColor[2];
- a = rgbaColor[3];
+ rgba[0] = rgbaColor[0];
+ rgba[1] = rgbaColor[1];
+ rgba[2] = rgbaColor[2];
+ rgba[3] = rgbaColor[3];
}
}
- renderer.getRenderState().setColorStatic(r, g, b, a);
synchronized ( dirtySync ) {
validate(gl);
- region.draw(gl, renderer, sampleCount);
+ drawImpl0(gl, renderer, sampleCount, rgba);
}
}
- protected GLRegion createGLRegion(final GLProfile glp) {
- return GLRegion.create(glp, renderModes, null);
- }
-
/**
* Validates the shape's underlying {@link GLRegion}.
* <p>
@@ -418,8 +383,15 @@ public abstract class Shape {
* @see #validate(GLProfile)
*/
public final void validate(final GL2ES2 gl) {
- validateImpl(gl.getGLProfile(), gl);
+ synchronized ( dirtySync ) {
+ if( isShapeDirty() ) {
+ box.reset();
+ }
+ validateImpl(gl.getGLProfile(), gl);
+ dirty = 0;
+ }
}
+
/**
* Validates the shape's underlying {@link GLRegion} w/o a current {@link GL2ES2} object
* <p>
@@ -429,30 +401,12 @@ public abstract class Shape {
* @see #validate(GL2ES2)
*/
public final void validate(final GLProfile glp) {
- validateImpl(glp, null);
- }
- private final void validateImpl(final GLProfile glp, final GL2ES2 gl) {
synchronized ( dirtySync ) {
- if( null != gl ) {
- clearDirtyRegions(gl);
- }
- if( isShapeDirty() || null == region ) {
+ if( isShapeDirty() ) {
box.reset();
- if( null == region ) {
- region = createGLRegion(glp);
- } else if( null == gl ) {
- dirtyRegions.add(region);
- region = createGLRegion(glp);
- } else {
- region.clear(gl);
- }
- addShapeToRegion();
- region.setQuality(regionQuality);
- dirty &= ~(DIRTY_SHAPE|DIRTY_STATE);
- } else if( isStateDirty() ) {
- region.markStateDirty();
- dirty &= ~DIRTY_STATE;
}
+ validateImpl(glp, null);
+ dirty = 0;
}
}
@@ -769,21 +723,6 @@ public abstract class Shape {
return rgbaColor;
}
- public final int getQuality() { return regionQuality; }
- public final void setQuality(final int q) {
- this.regionQuality = q;
- if( null != region ) {
- region.setQuality(q);
- }
- }
- public final void setSharpness(final float sharpness) {
- this.oshapeSharpness = sharpness;
- markShapeDirty();
- }
- public final float getSharpness() {
- return oshapeSharpness;
- }
-
/**
* Set base color.
* <p>
@@ -842,9 +781,27 @@ public abstract class Shape {
}
public String getSubString() {
+ final String pivotS;
+ if( !VectorUtil.isVec3Zero(rotOrigin, 0, FloatUtil.EPSILON) ) {
+ pivotS = "pivot["+rotOrigin[0]+", "+rotOrigin[1]+", "+rotOrigin[2]+"], ";
+ } else {
+ pivotS = "";
+ }
+ final String scaleS;
+ if( !VectorUtil.isVec3Equal(scale, 0, VectorUtil.VEC3_ONE, 0, FloatUtil.EPSILON) ) {
+ scaleS = "scale["+scale[0]+", "+scale[1]+", "+scale[2]+"], ";
+ } else {
+ scaleS = "scale 1, ";
+ }
+ final String rotateS;
+ if( !rotation.isIdentity() ) {
+ rotateS = "rot "+rotation+", ";
+ } else {
+ rotateS = "";
+ }
return "enabled "+enabled+", toggle[able "+toggleable+", state "+toggle+"], pos["+position[0]+", "+position[1]+", "+position[2]+
- "], scale["+scale[0]+", "+scale[1]+", "+scale[2]+
- "], box "+box;
+ "], "+pivotS+scaleS+rotateS+
+ "box "+box;
}
//
@@ -1187,39 +1144,25 @@ public abstract class Shape {
//
//
- protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+ protected abstract void validateImpl(final GLProfile glp, final GL2ES2 gl);
+
+ protected abstract void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, float[] rgba);
+
+ protected abstract void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer);
- protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
+ protected abstract void destroyImpl0(final GL2ES2 gl, final RegionRenderer renderer);
protected abstract void addShapeToRegion();
+ /**
+ * Returns true if implementation uses an extra color channel or texture
+ * which will be modulated with the passed rgba color {@link #drawImpl0(GL2ES2, RegionRenderer, int[], float[])}.
+ *
+ * Otherwise the base color will be modulated and passed to {@link #drawImpl0(GL2ES2, RegionRenderer, int[], float[])}.
+ */
+ public abstract boolean hasColorChannel();
+
//
//
//
-
- protected OutlineShape createDebugOutline(final OutlineShape shape, final AABBox box) {
- final float d = 0.025f;
- final float tw = box.getWidth() + d*2f;
- final float th = box.getHeight() + d*2f;
-
- final float minX = box.getMinX() - d;
- final float minY = box.getMinY() - d;
- final float z = 0; // box.getMinZ() + 0.025f;
-
- // CCW!
- shape.moveTo(minX, minY, z);
- shape.lineTo(minX+tw, minY, z);
- shape.lineTo(minX+tw, minY + th, z);
- shape.lineTo(minX, minY + th, z);
- shape.closePath();
-
- // shape.addVertex(minX, minY, z, true);
- // shape.addVertex(minX+tw, minY, z, true);
- // shape.addVertex(minX+tw, minY + th, z, true);
- // shape.addVertex(minX, minY + th, z, true);
- // shape.closeLastOutline(true);
-
- return shape;
- }
-
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java
index 88d6f04c7..90cd11b71 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Button.java
@@ -33,12 +33,14 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.math.geom.AABBox;
import jogamp.graph.ui.shapes.Label0;
/**
- * A GraphUI text labeled {@link RoundButton} {@link Shape}
+ * A GraphUI text labeled {@link RoundButton} {@link GraphShape}
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
@@ -60,6 +62,10 @@ public class Button extends RoundButton {
private float spacingX = DEFAULT_SPACING_X;
private float spacingY = DEFAULT_SPACING_Y;
+ private final AffineTransform tempT1 = new AffineTransform();
+ private final AffineTransform tempT2 = new AffineTransform();
+ private final AffineTransform tempT3 = new AffineTransform();
+
public Button(final int renderModes, final Font labelFont,
final String labelText, final float width,
final float height) {
@@ -126,7 +132,7 @@ public class Button extends RoundButton {
System.err.printf("Button.X: lbox2 %s%n", lbox2);
}
- setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+ setRotationPivot( ctr );
if( DRAW_DEBUG_BOX ) {
System.err.println("XXX.Button: Added Shape: "+shape+", "+box);
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java
index e8ec28d36..534e6fc7b 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/CrossHair.java
@@ -28,15 +28,15 @@
package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * A GraphUI Crosshair {@link Shape}
+ * A GraphUI Crosshair {@link GraphShape}
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
*/
-public class CrossHair extends Shape {
+public class CrossHair extends GraphShape {
private float width, height, lineWidth;
public CrossHair(final int renderModes, final float width, final float height, final float linewidth) {
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java
index 0d51ff09b..5fdb7991b 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/GLButton.java
@@ -37,12 +37,13 @@ import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.texture.ImageSequence;
import com.jogamp.opengl.util.texture.Texture;
/**
- * A GraphUI {@link GLEventListener} based {@link TexSeqButton} {@link Shape}.
+ * A GraphUI {@link GLEventListener} based {@link TexSeqButton} {@link GraphShape}.
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java
index bbc4975bf..d5718d98a 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/ImageButton.java
@@ -29,10 +29,11 @@ package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.util.texture.ImageSequence;
/**
- * A GraphUI {@link ImageSequence} based {@link TexSeqButton} {@link Shape}.
+ * A GraphUI {@link ImageSequence} based {@link TexSeqButton} {@link GraphShape}.
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java
index 65371875d..cad8689ec 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Label.java
@@ -29,6 +29,7 @@ package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.opengl.GLRegion;
@@ -36,21 +37,25 @@ import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.Font.Glyph;
import com.jogamp.graph.geom.plane.AffineTransform;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * A GraphUI text label {@link Shape}
+ * A GraphUI text label {@link GraphShape}
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
*/
-public class Label extends Shape {
- protected Font font;
- protected float fontScale;
- protected String text;
+public class Label extends GraphShape {
+ private Font font;
+ private float fontScale;
+ private String text;
+
+ private final AffineTransform tempT1 = new AffineTransform();
+ private final AffineTransform tempT2 = new AffineTransform();
+ private final AffineTransform tempT3 = new AffineTransform();
/**
- * Label ctor
+ * Label ctor using a separate {@code fontScale} to scale the em-sized type glyphs
* @param renderModes region renderModes
* @param font the font
* @param fontScale font-scale factor, by which the em-sized type glyphs shall be scaled
@@ -63,6 +68,19 @@ public class Label extends Shape {
this.text = text;
}
+ /**
+ * Label ctor using em-size type glyphs
+ * @param renderModes region renderModes
+ * @param font the font
+ * @param text the text to render
+ */
+ public Label(final int renderModes, final Font font, final String text) {
+ super(renderModes);
+ this.font = font;
+ this.fontScale = 1f;
+ this.text = text;
+ }
+
/** Return the text to be rendered. */
public String getText() {
return text;
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java
index 8f9ccda3e..6b26c58b8 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java
@@ -30,13 +30,14 @@ package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.common.util.InterruptSource;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
/**
- * A GraphUI {@link GLMediaPlayer} based {@link TexSeqButton} {@link Shape}.
+ * A GraphUI {@link GLMediaPlayer} based {@link TexSeqButton} {@link GraphShape}.
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java
index f027d92bc..4a8c29f2a 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/Rectangle.java
@@ -28,15 +28,15 @@
package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * A GraphUI Rectangle {@link Shape}
+ * A GraphUI Rectangle {@link GraphShape}
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
*/
-public class Rectangle extends Shape {
+public class Rectangle extends GraphShape {
private float width, height, lineWidth;
public Rectangle(final int renderModes, final float width, final float height, final float linewidth) {
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java
index 8dde441d9..93ba4f0dc 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/RoundButton.java
@@ -28,10 +28,10 @@
package com.jogamp.graph.ui.gl.shapes;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
/**
- * An abstract GraphUI round Button {@link Shape}
+ * An abstract GraphUI round Button {@link GraphShape}
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
@@ -40,7 +40,7 @@ import com.jogamp.graph.ui.gl.Shape;
* To render it rectangular, {@link #setCorner(float)} to zero.
* </p>
*/
-public abstract class RoundButton extends Shape {
+public abstract class RoundButton extends GraphShape {
/** {@value} */
public static final float DEFAULT_CORNER = 1f;
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java
index 19d9a228a..5afe1c373 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/TexSeqButton.java
@@ -31,11 +31,11 @@ import com.jogamp.opengl.GLProfile;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.ui.gl.Shape;
+import com.jogamp.graph.ui.gl.GraphShape;
import com.jogamp.opengl.util.texture.TextureSequence;
/**
- * An abstract GraphUI {@link TextureSequence} {@link RoundButton} {@link Shape}.
+ * An abstract GraphUI {@link TextureSequence} {@link RoundButton} {@link GraphShape}.
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
@@ -73,8 +73,7 @@ public abstract class TexSeqButton extends RoundButton {
region.addOutlineShape(shape, null, rgbaColor);
box.resize(shape.getBounds());
- final float[] ctr = box.getCenter();
- setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+ setRotationPivot( box.getCenter() );
if( DRAW_DEBUG_BOX ) {
System.err.println("XXX.UIShape.TextureSeqButton: Added Shape: "+shape+", "+box);