1 package com.jogamp.opengl.test.junit.graph.demos;
2 
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URISyntaxException;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.List;
9 
10 import com.jogamp.opengl.GL;
11 import com.jogamp.opengl.GL2ES2;
12 import com.jogamp.opengl.GLAnimatorControl;
13 import com.jogamp.opengl.GLAutoDrawable;
14 import com.jogamp.opengl.GLEventListener;
15 import com.jogamp.opengl.GLPipelineFactory;
16 import com.jogamp.opengl.GLRunnable;
17 
18 import com.jogamp.common.net.Uri;
19 import com.jogamp.common.util.InterruptSource;
20 import com.jogamp.graph.curve.Region;
21 import com.jogamp.graph.curve.opengl.RegionRenderer;
22 import com.jogamp.graph.curve.opengl.RenderState;
23 import com.jogamp.graph.font.Font;
24 import com.jogamp.graph.font.FontFactory;
25 import com.jogamp.graph.geom.SVertex;
26 import com.jogamp.newt.MonitorDevice;
27 import com.jogamp.newt.Window;
28 import com.jogamp.newt.event.InputEvent;
29 import com.jogamp.newt.event.MouseEvent;
30 import com.jogamp.newt.event.PinchToZoomGesture;
31 import com.jogamp.newt.event.GestureHandler.GestureEvent;
32 import com.jogamp.newt.event.MouseEvent.PointerClass;
33 import com.jogamp.newt.opengl.GLWindow;
34 import com.jogamp.opengl.math.FloatUtil;
35 import com.jogamp.opengl.math.VectorUtil;
36 import com.jogamp.opengl.test.junit.graph.demos.ui.CrossHair;
37 import com.jogamp.opengl.test.junit.graph.demos.ui.GLEventListenerButton;
38 import com.jogamp.opengl.test.junit.graph.demos.ui.Label;
39 import com.jogamp.opengl.test.junit.graph.demos.ui.LabelButton;
40 import com.jogamp.opengl.test.junit.graph.demos.ui.MediaPlayerButton;
41 import com.jogamp.opengl.test.junit.graph.demos.ui.RoundButton;
42 import com.jogamp.opengl.test.junit.graph.demos.ui.SceneUIController;
43 import com.jogamp.opengl.test.junit.graph.demos.ui.ImageSeqButton;
44 import com.jogamp.opengl.test.junit.graph.demos.ui.UIShape;
45 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
46 import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
47 import com.jogamp.opengl.util.GLReadBufferUtil;
48 import com.jogamp.opengl.util.av.GLMediaPlayer;
49 import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
50 import com.jogamp.opengl.util.texture.ImageSequence;
51 import com.jogamp.opengl.util.texture.TextureIO;
52 
53 public class GPUUISceneGLListener0A implements GLEventListener {
54 
55     private boolean debug = false;
56     private boolean trace = false;
57 
58     private final float noAADPIThreshold;
59     private final RenderState rs;
60     private final SceneUIController sceneUIController;
61 
62     /** -1 == AUTO, TBD @ init(..) */
63     private int renderModes;
64     private RegionRenderer renderer;
65 
66     private final int fontSet = FontFactory.UBUNTU;
67     private Font font;
68 
69     private final float sceneDist = 3000f;
70     private final float zNear = 0.1f, zFar = 7000f;
71 
72     private final float relTop = 5f/6f;
73     private final float relMiddle = 2f/6f;
74     private final float relLeft = 1f/6f;
75 
76     /** Proportional Button Size to Window Height, per-vertical-pixels [PVP] */
77     private final float buttonYSizePVP = 0.084f;
78     private final float buttonXSizePVP = 0.105f;
79     private final float fontSizePt = 10f;
80     /** Proportional Font Size to Window Height  for Main Text, per-vertical-pixels [PVP] */
81     private final float fontSizeFixedPVP = 0.046f;
82     /** Proportional Font Size to Window Height for FPS Status Line, per-vertical-pixels [PVP] */
83     private final float fontSizeFpsPVP = 0.038f;
84     private float dpiH = 96;
85 
86     /**
87      * Default DPI threshold value to disable {@link Region#VBAA_RENDERING_BIT VBAA}: {@value} dpi
88      * @see #GPUUISceneGLListener0A(float)
89      * @see #GPUUISceneGLListener0A(float, boolean, boolean)
90      */
91     public static final float DefaultNoAADPIThreshold = 200f;
92 
93     private int currentText = 0;
94 
95     private String actionText = null;
96     private Label[] labels = null;
97     private String[] strings = null;
98     private final List<RoundButton> buttons = new ArrayList<RoundButton>();
99     private int buttonsLeftCount = 0;
100     private Label truePtSizeLabel = null;
101     private Label jogampLabel = null;
102     private Label fpsLabel = null;
103     private CrossHair crossHairCtr = null;
104 
105     private boolean ioAttached = false;
106     private GLAutoDrawable cDrawable;
107 
108     private final GLReadBufferUtil screenshot;
109 
110     private final String jogamp = "JogAmp - Jogl Graph Module Demo";
111     private final String truePtSize = fontSizePt+" pt font size label - true scale!";
112 
GPUUISceneGLListener0A()113     public GPUUISceneGLListener0A() {
114       this(0);
115     }
116 
117     /**
118      * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold}
119      */
GPUUISceneGLListener0A(final float noAADPIThreshold)120     public GPUUISceneGLListener0A(final float noAADPIThreshold) {
121         this(noAADPIThreshold, false, false);
122     }
123 
124     /**
125      * @param renderModes
126      */
GPUUISceneGLListener0A(final int renderModes)127     public GPUUISceneGLListener0A(final int renderModes) {
128       this(renderModes, false, false);
129     }
130 
131     /**
132      * @param renderModes
133      * @param debug
134      * @param trace
135      */
GPUUISceneGLListener0A(final int renderModes, final boolean debug, final boolean trace)136     public GPUUISceneGLListener0A(final int renderModes, final boolean debug, final boolean trace) {
137         this(0f, renderModes, debug, trace);
138     }
139 
140     /**
141      * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold}
142      * @param debug
143      * @param trace
144      */
GPUUISceneGLListener0A(final float noAADPIThreshold, final boolean debug, final boolean trace)145     public GPUUISceneGLListener0A(final float noAADPIThreshold, final boolean debug, final boolean trace) {
146         this(noAADPIThreshold, 0, debug, trace);
147     }
148 
GPUUISceneGLListener0A(final float noAADPIThreshold, final int renderModes, final boolean debug, final boolean trace)149     private GPUUISceneGLListener0A(final float noAADPIThreshold, final int renderModes, final boolean debug, final boolean trace) {
150         this.noAADPIThreshold = noAADPIThreshold;
151         this.rs = RenderState.createRenderState(SVertex.factory());
152         this.debug = debug;
153         this.trace = trace;
154 
155         this.renderModes = renderModes;
156 
157         try {
158             font = FontFactory.get(FontFactory.UBUNTU).getDefault();
159         } catch (final IOException ioe) {
160             throw new RuntimeException(ioe);
161         }
162         sceneUIController = new SceneUIController(sceneDist, zNear, zFar);
163         screenshot = new GLReadBufferUtil(false, false);
164     }
165 
rotateButtons(float[] angdeg)166     private void rotateButtons(float[] angdeg) {
167         angdeg = VectorUtil.scaleVec3(angdeg, angdeg, FloatUtil.PI / 180.0f);
168         for(int i=0; i<buttons.size(); i++) {
169             buttons.get(i).getRotation().rotateByEuler( angdeg );
170         }
171     }
translateButtons(final float tx, final float ty, final float tz)172     private void translateButtons(final float tx, final float ty, final float tz) {
173         for(int i=0; i<buttons.size(); i++) {
174             buttons.get(i).translate(tx, ty, tz);
175         }
176     }
177 
setButtonsSpacing(final float dx, final float dy)178     private void setButtonsSpacing(final float dx, final float dy) {
179         for(int i=0; i<buttons.size(); i++) {
180             final RoundButton b = buttons.get(i);
181             if( b instanceof LabelButton ) {
182                 final LabelButton lb = (LabelButton) b;
183                 final float sx = lb.getSpacingX()+dx, sy = lb.getSpacingY()+dy;
184                 System.err.println("Spacing: X "+sx+", Y "+sy);
185                 lb.setSpacing(sx, sy);
186             }
187         }
188     }
189 
setButtonsCorner(final float dc)190     private void setButtonsCorner(final float dc) {
191         for(int i=0; i<buttons.size(); i++) {
192             final float c = buttons.get(i).getCorner()+dc;
193             System.err.println("Corner: "+c);
194             buttons.get(i).setCorner(c);
195         }
196     }
197 
resetButtons()198     private void resetButtons() {
199         for(int i=0; i<buttons.size(); i++) {
200             final RoundButton b = buttons.get(i);
201             b.getRotation().setIdentity();
202             b.setCorner(RoundButton.DEFAULT_CORNER);
203             if( b instanceof LabelButton ) {
204                 ((LabelButton)b).setSpacing(LabelButton.DEFAULT_SPACING_X, LabelButton.DEFAULT_SPACING_Y);
205             }
206         }
207     }
208 
initButtons(final GL2ES2 gl, final int width, final int height, final RegionRenderer renderer)209     private void initButtons(final GL2ES2 gl, final int width, final int height, final RegionRenderer renderer) {
210         final boolean pass2Mode = Region.isTwoPass( renderModes ) ;
211         buttons.clear();
212 
213         final float buttonXSize = buttonXSizePVP * width;
214         // final float buttonYSize = buttonYSizePVP * height;
215         final float buttonYSize = buttonXSize / 2.5f;
216         System.err.println("Button Size: "+buttonXSizePVP+" x "+buttonYSizePVP+" * "+width+" x "+height+" -> "+buttonXSize+" x "+buttonYSize);
217         final float xStartLeft = 0f; // aligned to left edge w/ space via reshape
218         final float yStartTop = 0f;  // aligned to top edge w/ space via reshape
219         final float diffX = 1.2f * buttonXSize;
220         final float diffY = 1.5f * buttonYSize;
221 
222         LabelButton button = new LabelButton(SVertex.factory(), renderModes, font, "Next Text", buttonXSize, buttonYSize);
223         button.translate(xStartLeft,yStartTop-diffY*buttons.size(), 0f);
224         button.addMouseListener(new UIShape.MouseGestureAdapter() {
225             @Override
226             public void mouseClicked(final MouseEvent e) {
227                 if( null != labels[currentText] ) {
228                     labels[currentText].setEnabled(false);
229                 }
230                 currentText = (currentText+1)%labels.length;
231                 if( null != labels[currentText] ) {
232                     labels[currentText].setEnabled(true);
233                 }
234             } } );
235         button.addMouseListener(dragZoomRotateListener);
236         buttons.add(button);
237 
238         button = new LabelButton(SVertex.factory(), renderModes, font, "Show FPS", buttonXSize, buttonYSize);
239         button.setName(100); // FIXME: DEBUG tag
240         button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
241         button.setToggleable(true);
242         button.setToggle(fpsLabel.isEnabled());
243         button.addMouseListener(new UIShape.MouseGestureAdapter() {
244             @Override
245             public void mouseClicked(final MouseEvent e) {
246                 final GLAnimatorControl a = cDrawable.getAnimator();
247                 if( null != a ) {
248                     a.resetFPSCounter();
249                 }
250                 fpsLabel.setEnabled(!fpsLabel.isEnabled());
251             } } );
252         button.addMouseListener(dragZoomRotateListener);
253         buttons.add(button);
254 
255         button = new LabelButton(SVertex.factory(), renderModes, font, "v-sync", buttonXSize, buttonYSize);
256         button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
257         button.setToggleable(true);
258         button.setToggle(gl.getSwapInterval()>0);
259         button.addMouseListener(new UIShape.MouseGestureAdapter() {
260             @Override
261             public void mouseClicked(final MouseEvent e) {
262                 cDrawable.invoke(false, new GLRunnable() {
263                     @Override
264                     public boolean run(final GLAutoDrawable drawable) {
265                         final GL gl = drawable.getGL();
266                         gl.setSwapInterval(gl.getSwapInterval()<=0?1:0);
267                         final GLAnimatorControl a = drawable.getAnimator();
268                         if( null != a ) {
269                             a.resetFPSCounter();
270                         }
271                         return true;
272                     }
273                 });
274             } } );
275         button.addMouseListener(dragZoomRotateListener);
276         buttons.add(button);
277 
278         button = new LabelButton(SVertex.factory(), renderModes, font, "< tilt >", buttonXSize, buttonYSize);
279         button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
280         button.addMouseListener(new UIShape.MouseGestureAdapter() {
281             @Override
282             public void mouseClicked(final MouseEvent e) {
283                 final Object attachment = e.getAttachment();
284                 if( attachment instanceof UIShape.PointerEventInfo ) {
285                     final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
286                     if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
287                         rotateButtons(new float[] { 0f, -5f, 0f}); // left-half pressed
288                     } else {
289                         rotateButtons(new float[] { 0f,  5f, 0f}); // right-half pressed
290                     }
291                 }
292             }
293             @Override
294             public void mouseWheelMoved(final MouseEvent e) {
295                 rotateButtons(new float[] { 0f,  e.getRotation()[1], 0f});
296             } } );
297         buttons.add(button);
298 
299         if( pass2Mode ) { // second column to the left
300             button = new LabelButton(SVertex.factory(), renderModes, font, "< samples >", buttonXSize, buttonYSize);
301             button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
302             button.addMouseListener(new UIShape.MouseGestureAdapter() {
303                 @Override
304                 public void mouseClicked(final MouseEvent e) {
305                     final Object attachment = e.getAttachment();
306                     if( attachment instanceof UIShape.PointerEventInfo ) {
307                         final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
308                         int sampleCount = sceneUIController.getSampleCount();
309                         if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
310                             // left-half pressed
311                             sampleCount--;
312                         } else {
313                             // right-half pressed
314                             sampleCount++;
315                         }
316                         sampleCount = sceneUIController.setSampleCount(sampleCount); // validated / clipped
317                     }
318                 } } );
319             button.addMouseListener(dragZoomRotateListener);
320             buttons.add(button);
321 
322             button = new LabelButton(SVertex.factory(), renderModes, font, "< quality >", buttonXSize, buttonYSize);
323             button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
324             button.addMouseListener(new UIShape.MouseGestureAdapter() {
325                 @Override
326                 public void mouseClicked(final MouseEvent e) {
327                     final Object attachment = e.getAttachment();
328                     if( attachment instanceof UIShape.PointerEventInfo ) {
329                         final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
330                         int quality = shapeEvent.shape.getQuality();
331 
332                         if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
333                             // left-half pressed
334                             if( quality > 0 ) {
335                                 quality--;
336                             }
337                         } else {
338                             // right-half pressed
339                             if( quality < Region.MAX_QUALITY ) {
340                                 quality++;
341                             }
342                         }
343                         sceneUIController.setAllShapesQuality(quality);
344                     }
345                 } } );
346             button.addMouseListener(dragZoomRotateListener);
347             buttons.add(button);
348         }
349 
350         button = new LabelButton(SVertex.factory(), renderModes, font, "Quit", buttonXSize, buttonYSize);
351         button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
352         button.setColor(0.7f, 0.0f, 0.0f, 1.0f);
353         button.setLabelColor(1.2f, 1.2f, 1.2f);
354         button.setPressedColorMod(1.1f, 0.0f, 0.0f, 1.0f);
355         button.addMouseListener(new UIShape.MouseGestureAdapter() {
356             @Override
357             public void mouseClicked(final MouseEvent e) {
358                 new InterruptSource.Thread() {
359                     public void run() {
360                         if( null != cDrawable ) {
361                             final GLAnimatorControl actrl = cDrawable.getAnimator();
362                             if( null != actrl ) {
363                                 actrl.stop();
364                             }
365                             cDrawable.destroy();
366                         }
367                     } }.start();
368             } } );
369         button.addMouseListener(dragZoomRotateListener);
370         buttons.add(button);
371 
372         // second column to the left
373         {
374             final int j = 1; // column
375             int k = 0; // row
376             button = new LabelButton(SVertex.factory(), renderModes, font, "y flip", buttonXSize, buttonYSize);
377             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
378             button.addMouseListener(new UIShape.MouseGestureAdapter() {
379                 @Override
380                 public void mouseClicked(final MouseEvent e) {
381                     rotateButtons(new float[] { 0f, 180f, 0f});
382                 } } );
383             button.addMouseListener(dragZoomRotateListener);
384             buttons.add(button);
385 
386             k++;
387             button = new LabelButton(SVertex.factory(), renderModes, font, "x flip", buttonXSize, buttonYSize);
388             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
389             button.addMouseListener(new UIShape.MouseGestureAdapter() {
390                 @Override
391                 public void mouseClicked(final MouseEvent e) {
392                     rotateButtons(new float[] { 180f, 0f, 0f});
393                 } } );
394             button.addMouseListener(dragZoomRotateListener);
395             buttons.add(button);
396             k++;
397 
398             button = new LabelButton(SVertex.factory(), renderModes, font, "+", buttonXSize, buttonYSize);
399             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
400             button.addMouseListener(new UIShape.MouseGestureAdapter() {
401                 @Override
402                 public void mouseClicked(final MouseEvent e) {
403                     final Object attachment = e.getAttachment();
404                     if( attachment instanceof UIShape.PointerEventInfo ) {
405                         final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
406                         // rel position to center
407                         final float dx = shapeEvent.objPos[0] - shapeEvent.shape.getBounds().getCenter()[0] ;
408                         final float dy = shapeEvent.objPos[1] - shapeEvent.shape.getBounds().getCenter()[1] ;
409                         // per-cent position to center (remove dependency on dimension)
410                         final float awdx = Math.abs(dx)/shapeEvent.shape.getBounds().getWidth();
411                         final float awdy = Math.abs(dy)/shapeEvent.shape.getBounds().getHeight();
412                         float tx = 0, ty = 0;
413                         if ( awdx > awdy  ) {
414                             tx = dx < 0 ? -5 : 5;
415                         } else {
416                             ty = dy < 0 ? -5 : 5;
417                         }
418                         translateButtons(tx, ty, 0f);
419                     }
420                 } } );
421             button.addMouseListener(dragZoomRotateListener);
422             buttons.add(button);
423             k++;
424 
425             button = new LabelButton(SVertex.factory(), renderModes, font, "< space >", buttonXSize, buttonYSize);
426             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
427             button.addMouseListener(new UIShape.MouseGestureAdapter() {
428                 @Override
429                 public void mouseClicked(final MouseEvent e) {
430                     final Object attachment = e.getAttachment();
431                     if( attachment instanceof UIShape.PointerEventInfo ) {
432                         final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
433                         final float dx, dy;
434                         if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
435                             dx=-0.01f; dy=-0.005f;
436                         } else {
437                             dx=0.01f; dy=0.005f;
438                         }
439                         setButtonsSpacing(dx, dy);
440                     }
441                 }
442                 @Override
443                 public void mouseWheelMoved(final MouseEvent e) {
444                     setButtonsSpacing(e.getRotation()[0]/100f, e.getRotation()[1]/200f);
445                 } } );
446             buttons.add(button);
447             k++;
448 
449             button = new LabelButton(SVertex.factory(), renderModes, font, "< corner >", buttonXSize, buttonYSize);
450             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
451             button.addMouseListener(new UIShape.MouseGestureAdapter() {
452                 @Override
453                 public void mouseClicked(final MouseEvent e) {
454                     final Object attachment = e.getAttachment();
455                     if( attachment instanceof UIShape.PointerEventInfo ) {
456                         final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
457                         final float dc;
458                         if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
459                             dc=-0.1f;
460                         } else {
461                             dc=0.1f;
462                         }
463                         setButtonsCorner(dc);
464                     }
465 
466                 }
467                 @Override
468                 public void mouseWheelMoved(final MouseEvent e) {
469                     setButtonsCorner(e.getRotation()[1]/20f);
470                 } } );
471             buttons.add(button);
472             k++;
473 
474             button = new LabelButton(SVertex.factory(), renderModes, font, "reset", buttonXSize, buttonYSize);
475             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
476             button.addMouseListener(new UIShape.MouseGestureAdapter() {
477                 @Override
478                 public void mouseClicked(final MouseEvent e) {
479                     resetButtons();
480                 } } );
481             button.addMouseListener(dragZoomRotateListener);
482             buttons.add(button);
483             k++;
484 
485             button = new LabelButton(SVertex.factory(), renderModes, font, "screenshot", buttonXSize, buttonYSize);
486             button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
487             button.addMouseListener(new UIShape.MouseGestureAdapter() {
488                 @Override
489                 public void mouseClicked(final MouseEvent e) {
490                     cDrawable.invoke(false, new GLRunnable() {
491                         @Override
492                         public boolean run(final GLAutoDrawable drawable) {
493                             printScreen(drawable.getGL());
494                             return true;
495                         }
496                     });
497                 } } );
498             button.addMouseListener(dragZoomRotateListener);
499             buttons.add(button);
500             k++;
501         }
502 
503         buttonsLeftCount = buttons.size();
504 
505         final float button2XSize = 2f*buttonXSize;
506         final float button2YSize = 2f*buttonYSize;
507         final float xStartRight = -button2XSize - 8f; // aligned to right edge via reshape
508         final int texUnitMediaPlayer, texUnitImageButton, texUnitGLELButton;
509         if( false ) {
510             texUnitMediaPlayer=0;
511             texUnitImageButton=0;
512             texUnitGLELButton=0;
513         } else {
514             // works - but not required ..
515             texUnitMediaPlayer=1;
516             texUnitImageButton=2;
517             texUnitGLELButton=3;
518         }
519 
520         if( true ) {
521             final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault();
522             mPlayer.setTextureUnit(texUnitMediaPlayer);
523             final MediaPlayerButton mPlayerButton = new MediaPlayerButton(renderer.getRenderState().getVertexFactory(), renderModes,
524                                                                           button2XSize, button2YSize, mPlayer);
525             mPlayerButton.setVerbose(true);
526             mPlayerButton.addDefaultEventListener();
527             mPlayerButton.translate(xStartRight, yStartTop - diffY*1, 0f);
528             mPlayerButton.setToggleable(true);
529             mPlayerButton.setToggle(false); // toggle == false -> mute audio
530             mPlayerButton.setToggleOffColorMod(0f, 1f, 0f, 1.0f);
531             mPlayerButton.addMouseListener(dragZoomRotateListener);
532             mPlayerButton.addMouseListener(new UIShape.MouseGestureAdapter() {
533                 @Override
534                 public void mouseClicked(final MouseEvent e) {
535                     mPlayer.setAudioVolume( mPlayerButton.isToggleOn() ? 1f : 0f );
536                 } } );
537             buttons.add(mPlayerButton);
538             try {
539                 final Uri streamLoc = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
540                 mPlayer.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
541             } catch (final URISyntaxException e1) {
542                 e1.printStackTrace();
543             }
544         }
545         if( true ) {
546             final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true);
547             final ImageSeqButton imgButton = new ImageSeqButton(renderer.getRenderState().getVertexFactory(), renderModes,
548                                                                 button2XSize, button2YSize, imgSeq);
549             try {
550                 imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-released-145x53.png", TextureIO.PNG);
551                 imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-pressed-145x53.png", TextureIO.PNG);
552             } catch (final IOException e2) {
553                 e2.printStackTrace();
554             }
555             imgSeq.setManualStepping(true);
556             imgButton.translate(xStartRight, yStartTop - diffY*2.5f, 0f);
557             imgButton.addMouseListener(dragZoomRotateListener);
558             imgButton.addMouseListener(new UIShape.MouseGestureAdapter() {
559                 @Override
560                 public void mousePressed(final MouseEvent e) {
561                     imgButton.setCurrentIdx(1);
562                     System.err.println("XXX: "+imgButton);
563                 }
564                 @Override
565                 public void mouseReleased(final MouseEvent e) {
566                     imgButton.setCurrentIdx(0);
567                 } } );
568             buttons.add(imgButton);
569         }
570         if( true ) {
571             // Issues w/ OSX and NewtCanvasAWT when rendering / animating
572             // Probably related to CALayer - FBO - FBO* (of this button)
573             final GLEventListener glel;
574             if( true ) {
575                 final GearsES2 gears = new GearsES2(0);
576                 gears.setVerbose(false);
577                 gears.setClearColor(new float[] { 0.9f, 0.9f, 0.9f, 1f } );
578                 glel = gears;
579             } else if( false ) {
580                 glel = new RedSquareES2(0);
581             } else {
582                 glel = new GLEventListener() {
583                     @Override
584                     public void init(final GLAutoDrawable drawable) {
585                     }
586 
587                     @Override
588                     public void dispose(final GLAutoDrawable drawable) {
589                     }
590 
591                     @Override
592                     public void display(final GLAutoDrawable drawable) {
593                         final GL2ES2 gl = drawable.getGL().getGL2ES2();
594                         gl.glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
595                         // gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
596                         gl.glClear(GL.GL_COLOR_BUFFER_BIT);
597                     }
598 
599                     @Override
600                     public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
601                     }
602 
603                 };
604             }
605             final GLEventListenerButton glelButton = new GLEventListenerButton(renderer.getRenderState().getVertexFactory(), renderModes,
606                                                                        button2XSize, button2YSize,
607                                                                        texUnitGLELButton, glel, false /* useAlpha */,
608                                                                        (int)(button2XSize), (int)(button2YSize));
609             glelButton.setToggleable(true);
610             glelButton.setToggle(false); // toggle == true -> animation
611             glelButton.setAnimate(false);
612             glelButton.translate(xStartRight, yStartTop - diffY*4f, 0f);
613             glelButton.addMouseListener(dragZoomRotateListener);
614             glelButton.addMouseListener(new UIShape.MouseGestureAdapter() {
615                 @Override
616                 public void mouseClicked(final MouseEvent e) {
617                     glelButton.setAnimate( glelButton.isToggleOn() );
618                 } } );
619             buttons.add(glelButton);
620         }
621     }
622 
initTexts()623     private void initTexts() {
624         strings = new String[4];
625         int i = 0;
626 
627         strings[i++] =
628                      "- Mouse Scroll Over Object\n"+
629                      "   - General\n"+
630                      "     - Z Translation\n"+
631                      "     - Ctrl: Y-Rotation (Shift: X-Rotation)\n"+
632                      "   - Tilt, Space and Corner\n"+
633                      "     - Their respective action via wheel\n"+
634                      "       (shift = other value)\n"+
635                      "\n"+
636                      "- Mouse Drag On Object\n"+
637                      "   - Click on Object and drag mouse\n"+
638                      "   - Current postion in status line at bottom\n"+
639                      "\n"+
640                      "- Tilt Button Rotate Whole Button Group";
641 
642         strings[i++] = "abcdefghijklmn\nopqrstuvwxyz\n"+
643                        "ABCDEFGHIJKL\n"+
644                        "MNOPQRSTUVWXYZ\n"+
645                        "0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
646 
647         strings[i++] = "The quick brown fox\njumps over the lazy\ndog";
648 
649         strings[i++] =
650             "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec \n"+
651             "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel\n"+
652             "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices\n"+
653             "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia\n"+
654             "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat\n"+
655             "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum\n"+
656             "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin.\n";
657 
658         labels = new Label[i];
659     }
660 
661 
662     final boolean enableOthers = true;
663 
664     @Override
init(final GLAutoDrawable drawable)665     public void init(final GLAutoDrawable drawable) {
666         final Object upObj = drawable.getUpstreamWidget();
667         if( upObj instanceof Window ) {
668             final Window upWin = (Window)upObj;
669             final MonitorDevice mm = upWin.getMainMonitor();
670             final float[] monitorDPI = mm.getPixelsPerMM(new float[2]);
671             monitorDPI[0] *= 25.4f;
672             monitorDPI[1] *= 25.4f;
673             final float[] sDPI = upWin.getPixelsPerMM(new float[2]);
674             sDPI[0] *= 25.4f;
675             sDPI[1] *= 25.4f;
676             dpiH = sDPI[1];
677             System.err.println("Monitor detected: "+mm);
678             System.err.println("Monitor dpi: "+monitorDPI[0]+" x "+monitorDPI[1]);
679             System.err.println("Surface scale: native "+Arrays.toString(upWin.getMaximumSurfaceScale(new float[2]))+", current "+Arrays.toString(upWin.getCurrentSurfaceScale(new float[2])));
680             System.err.println("Surface dpi "+sDPI[0]+" x "+sDPI[1]);
681         } else {
682             System.err.println("Using default DPI of "+dpiH);
683         }
684         if( 0 == renderModes && !FloatUtil.isZero(noAADPIThreshold, FloatUtil.EPSILON)) {
685             final boolean noAA = dpiH >= noAADPIThreshold;
686             final String noAAs = noAA ? " >= " : " < ";
687             System.err.println("AUTO RenderMode: dpi "+dpiH+noAAs+noAADPIThreshold+" -> noAA "+noAA);
688             renderModes = noAA ? 0 : Region.VBAA_RENDERING_BIT;
689         }
690         if(drawable instanceof GLWindow) {
691             System.err.println("GPUUISceneGLListener0A: init (1)");
692             final GLWindow glw = (GLWindow) drawable;
693             attachInputListenerTo(glw);
694         } else {
695             System.err.println("GPUUISceneGLListener0A: init (0)");
696         }
697         System.err.println("Chosen: "+drawable.getChosenGLCapabilities());
698         cDrawable = drawable;
699         GL2ES2 gl = drawable.getGL().getGL2ES2();
700         if(debug) {
701             gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ).getGL2ES2();
702         }
703         if(trace) {
704             gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2();
705         }
706 
707         try {
708             font = FontFactory.get(fontSet).getDefault();
709         } catch (final IOException ioe) {
710             throw new RuntimeException(ioe);
711         }
712 
713         renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
714         rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
715         // renderer = RegionRenderer.create(rs, null, null);
716 
717         gl.setSwapInterval(1);
718         gl.glEnable(GL.GL_DEPTH_TEST);
719         gl.glEnable(GL.GL_BLEND);
720 
721         renderer.init(gl, renderModes);
722 
723         initTexts();
724 
725         sceneUIController.setRenderer(renderer);
726 
727         final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight();
728         jogampLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFixed, jogamp);
729         jogampLabel.addMouseListener(dragZoomRotateListener);
730         sceneUIController.addShape(jogampLabel);
731         jogampLabel.setEnabled(enableOthers);
732 
733         final float pixelSize10Pt = font.getPixelSize(fontSizePt, dpiH);
734         System.err.println("10Pt PixelSize: Display "+dpiH+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixel-size");
735         truePtSizeLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSize10Pt, truePtSize);
736         sceneUIController.addShape(truePtSizeLabel);
737         truePtSizeLabel.setEnabled(enableOthers);
738         truePtSizeLabel.translate(0, - 1.5f * jogampLabel.getLineHeight(), 0f);
739         truePtSizeLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f);
740 
741         /**
742          *
743          * [Label] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 18.814816
744          * [FPS] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 15.679012
745          */
746         final float pixelSizeFPS = fontSizeFpsPVP * drawable.getSurfaceHeight();
747         fpsLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFPS, "Nothing there yet");
748         fpsLabel.addMouseListener(dragZoomRotateListener);
749         sceneUIController.addShape(fpsLabel);
750         fpsLabel.setEnabled(enableOthers);
751         fpsLabel.setColor(0.3f, 0.3f, 0.3f, 1.0f);
752 
753         crossHairCtr = new CrossHair(renderer.getRenderState().getVertexFactory(), 0, 100f, 100f, 2f);
754         crossHairCtr.addMouseListener(dragZoomRotateListener);
755         sceneUIController.addShape(crossHairCtr);
756         crossHairCtr.setEnabled(true);
757         crossHairCtr.translate(0f, 0f, -1f);
758 
759         initButtons(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), renderer);
760         for(int i=0; i<buttons.size(); i++) {
761             sceneUIController.addShape(buttons.get(i));
762         }
763 
764         sceneUIController.init(drawable);
765 
766         final GLAnimatorControl a = drawable.getAnimator();
767         if( null != a ) {
768             a.resetFPSCounter();
769         }
770     }
771 
772     @Override
dispose(final GLAutoDrawable drawable)773     public void dispose(final GLAutoDrawable drawable) {
774         if(drawable instanceof GLWindow) {
775             System.err.println("GPUUISceneGLListener0A: dispose (1)");
776             final GLWindow glw = (GLWindow) drawable;
777             detachInputListenerFrom(glw);
778         } else {
779             System.err.println("GPUUISceneGLListener0A: dispose (0)");
780         }
781 
782         sceneUIController.dispose(drawable); // disposes all registered UIShapes
783 
784         final GL2ES2 gl = drawable.getGL().getGL2ES2();
785         renderer.destroy(gl);
786         screenshot.dispose(gl);
787     }
788 
789     private int shotCount = 0;
790 
printScreen(final GL gl)791     public void printScreen(final GL gl)  {
792         final String modeS = Region.getRenderModeString(jogampLabel.getRenderModes());
793         final String filename = String.format("GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png",
794                 shotCount++, renderer.getWidth(), renderer.getHeight(),
795                 modeS, sceneUIController.getSampleCount());
796         gl.glFinish(); // just make sure rendering finished ..
797         if(screenshot.readPixels(gl, false)) {
798             screenshot.write(new File(filename));
799             System.err.println("Wrote: "+filename);
800         }
801     }
802 
803     @Override
display(final GLAutoDrawable drawable)804     public void display(final GLAutoDrawable drawable) {
805         // System.err.println("GPUUISceneGLListener0A: display");
806         final GL2ES2 gl = drawable.getGL().getGL2ES2();
807 
808         if(null == labels[currentText]) {
809             final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight();
810             final float dyTop = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight();
811             final float dxMiddle = drawable.getSurfaceWidth() * relMiddle;
812             labels[currentText] = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFixed, strings[currentText]);
813             labels[currentText].setColor(0.1f, 0.1f, 0.1f, 1.0f);
814             labels[currentText].setEnabled(enableOthers);
815             labels[currentText].translate(dxMiddle,
816                                           dyTop - 1.5f * jogampLabel.getLineHeight()
817                                                 - 1.5f * truePtSizeLabel.getLineHeight(), 0f);
818             labels[currentText].addMouseListener(dragZoomRotateListener);
819             sceneUIController.addShape(labels[currentText]);
820             System.err.println("Label["+currentText+"] CTOR: "+labels[currentText]);
821             System.err.println("Label["+currentText+"] CTOR: "+Arrays.toString(labels[currentText].getTranslate()));
822         }
823         if( fpsLabel.isEnabled() ) {
824             final float lfps, tfps, td;
825             final GLAnimatorControl animator = drawable.getAnimator();
826             if( null != animator ) {
827                 lfps = animator.getLastFPS();
828                 tfps = animator.getTotalFPS();
829                 td = animator.getTotalFPSDuration()/1000f;
830             } else {
831                 lfps = 0f;
832                 tfps = 0f;
833                 td = 0f;
834             }
835             final String modeS = Region.getRenderModeString(renderModes);
836             final String text;
837             if( null == actionText ) {
838                 final String timePrec = gl.isGLES() ? "4.0" : "4.1";
839                 text = String.format("%03.1f/%03.1f fps, v-sync %d, dpi %.1f, fontSize %.1f, %s-samples %d, q %d, td %"+timePrec+"f, blend %b, alpha %d, msaa %d",
840                     lfps, tfps, gl.getSwapInterval(), dpiH, fontSizeFixedPVP, modeS, sceneUIController.getSampleCount(), fpsLabel.getQuality(), td,
841                     renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED),
842                     drawable.getChosenGLCapabilities().getAlphaBits(),
843                     drawable.getChosenGLCapabilities().getNumSamples());
844             } else {
845                 text = String.format("%03.1f/%03.1f fps, v-sync %d, fontSize %.1f, %s",
846                     lfps, tfps, gl.getSwapInterval(), fontSizeFixedPVP, actionText);
847             }
848             fpsLabel.setText(text);
849         }
850         sceneUIController.display(drawable);
851     }
852 
853 
854     float lastWidth = 0f, lastHeight = 0f;
855 
856     @Override
reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height)857     public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
858         System.err.println("GPUUISceneGLListener0A: reshape");
859 
860         //
861         // Layout all shapes: Relational move regarding window coordinates
862         //
863         final float dw = width - lastWidth;
864         final float dh = height - lastHeight;
865 
866         final float dz = 0f;
867         final float dyTop = dh * relTop;
868         final float dxLeft = dw * relLeft;
869         final float dxRight = dw;
870 
871         for(int i=0; i<buttons.size() && i<buttonsLeftCount; i++) {
872             buttons.get(i).translate(dxLeft, dyTop, dz);
873         }
874         for(int i=buttonsLeftCount; i<buttons.size(); i++) {
875             buttons.get(i).translate(dxRight, dyTop, dz);
876         }
877         final float dxMiddleAbs = width * relMiddle;
878         final float dyTopLabelAbs = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight();
879         jogampLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs, dz);
880         truePtSizeLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs, dz);
881         truePtSizeLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight(), 0f);
882         fpsLabel.translate(0f, 0f, 0f);
883         if( null != labels[currentText] ) {
884             labels[currentText].setTranslate(dxMiddleAbs,
885                                              dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight()
886                                              - 1.5f * truePtSizeLabel.getLineHeight(), 0f);
887             System.err.println("Label["+currentText+"] MOVE: "+labels[currentText]);
888             System.err.println("Label["+currentText+"] MOVE: "+Arrays.toString(labels[currentText].getTranslate()));
889         }
890         crossHairCtr.translate(dw/2f, dh/2f, 0f);
891 
892         sceneUIController.reshape(drawable, x, y, width, height);
893 
894         lastWidth = width;
895         lastHeight = height;
896    }
897 
attachInputListenerTo(final GLWindow window)898     public void attachInputListenerTo(final GLWindow window) {
899         if ( !ioAttached ) {
900             ioAttached = true;
901             sceneUIController.attachInputListenerTo(window);
902         }
903     }
904 
detachInputListenerFrom(final GLWindow window)905     public void detachInputListenerFrom(final GLWindow window) {
906         if ( ioAttached ) {
907             ioAttached = false;
908             sceneUIController.detachInputListenerFrom(window);
909         }
910     }
911 
912     /**
913      * We can share this instance w/ all UI elements,
914      * since only mouse action / gesture is complete for a single one (press, drag, released and click).
915      */
916     private final UIShape.MouseGestureAdapter dragZoomRotateListener = new UIShape.MouseGestureAdapter() {
917         float dragFirstX=-1f, dragFirstY=-1f;
918         boolean dragFirst = false;
919 
920         @Override
921         public void mousePressed(final MouseEvent e) {
922             dragFirst = true;
923         }
924 
925         @Override
926         public void mouseReleased(final MouseEvent e) {
927             dragFirst = false;
928             actionText = null;
929         }
930 
931         @Override
932         public void mouseDragged(final MouseEvent e) {
933             final Object attachment = e.getAttachment();
934             if( attachment instanceof UIShape.PointerEventInfo ) {
935                 final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
936                 if( e.getPointerCount() == 1 ) {
937                     // 1 pointer drag
938                     if(dragFirst) {
939                         dragFirstX = shapeEvent.objPos[0]; // e.getX();
940                         dragFirstY = shapeEvent.objPos[1]; // e.getY();
941                         dragFirst=false;
942                         return;
943                     }
944                     final float nx = shapeEvent.objPos[0]; // e.getX();
945                     final float ny = shapeEvent.objPos[1]; // e.getY();
946                     final float dx = nx - dragFirstX;
947                     final float dy = ny - dragFirstY;
948                     // final float dy = -(ny - dragLastY);
949                     shapeEvent.shape.translate(dx, dy, 0f);
950                     final float[] tx = shapeEvent.shape.getTranslate();
951                     actionText = String.format("Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]);
952                 }
953             }
954         }
955 
956         @Override
957         public void mouseWheelMoved(final MouseEvent e) {
958             final Object attachment = e.getAttachment();
959             if( attachment instanceof UIShape.PointerEventInfo ) {
960                 final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
961                 final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass();
962                 if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) {
963                     // offscreen vertical mouse wheel zoom
964                     final float tz = 8f*e.getRotation()[1]; // vertical: wheel
965                     System.err.println("Rotate.Zoom.W: "+tz);
966                     shapeEvent.shape.translate(0f, 0f, tz);
967                 } else if( isOnscreen || e.isControlDown() ) {
968                     final float[] rot =  VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f);
969                     if( isOnscreen ) {
970                         System.err.println("XXX: "+e);
971                         // swap axis for onscreen rotation matching natural feel
972                         final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp;
973                         VectorUtil.scaleVec3(rot, rot, 2f);
974                     }
975                     shapeEvent.shape.getRotation().rotateByEuler( rot );
976                 }
977             }
978         }
979         @Override
980         public void gestureDetected(final GestureEvent e) {
981             final Object attachment = e.getAttachment();
982             if( attachment instanceof UIShape.PointerEventInfo ) {
983                 final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
984                 if( e instanceof PinchToZoomGesture.ZoomEvent ) {
985                     final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e;
986                     final float tz = ze.getDelta() * ze.getScale();
987                     System.err.println("Rotate.Zoom.G: "+tz);
988                     shapeEvent.shape.translate(0f, 0f, tz);
989                 }
990             }
991         } };
992 }
993