package com.jogamp.opengl.test.junit.graph.demos; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAnimatorControl; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLRunnable; import com.jogamp.common.net.Uri; import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.Window; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.PinchToZoomGesture; import com.jogamp.newt.event.GestureHandler.GestureEvent; import com.jogamp.newt.event.MouseEvent.PointerClass; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.math.FloatUtil; import com.jogamp.opengl.math.VectorUtil; import com.jogamp.opengl.test.junit.graph.demos.ui.CrossHair; import com.jogamp.opengl.test.junit.graph.demos.ui.GLEventListenerButton; import com.jogamp.opengl.test.junit.graph.demos.ui.Label; import com.jogamp.opengl.test.junit.graph.demos.ui.LabelButton; import com.jogamp.opengl.test.junit.graph.demos.ui.MediaPlayerButton; import com.jogamp.opengl.test.junit.graph.demos.ui.RoundButton; import com.jogamp.opengl.test.junit.graph.demos.ui.SceneUIController; import com.jogamp.opengl.test.junit.graph.demos.ui.ImageSeqButton; import com.jogamp.opengl.test.junit.graph.demos.ui.UIShape; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import com.jogamp.opengl.util.GLReadBufferUtil; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.av.GLMediaPlayerFactory; import com.jogamp.opengl.util.texture.ImageSequence; import com.jogamp.opengl.util.texture.TextureIO; public class GPUUISceneGLListener0A implements GLEventListener { private boolean debug = false; private boolean trace = false; private final float noAADPIThreshold; private final RenderState rs; private final SceneUIController sceneUIController; /** -1 == AUTO, TBD @ init(..) */ private int renderModes; private RegionRenderer renderer; private final int fontSet = FontFactory.UBUNTU; private Font font; private final float sceneDist = 3000f; private final float zNear = 0.1f, zFar = 7000f; private final float relTop = 5f/6f; private final float relMiddle = 2f/6f; private final float relLeft = 1f/6f; /** Proportional Button Size to Window Height, per-vertical-pixels [PVP] */ private final float buttonYSizePVP = 0.084f; private final float buttonXSizePVP = 0.105f; private final float fontSizePt = 10f; /** Proportional Font Size to Window Height for Main Text, per-vertical-pixels [PVP] */ private final float fontSizeFixedPVP = 0.046f; /** Proportional Font Size to Window Height for FPS Status Line, per-vertical-pixels [PVP] */ private final float fontSizeFpsPVP = 0.038f; private float dpiH = 96; /** * Default DPI threshold value to disable {@link Region#VBAA_RENDERING_BIT VBAA}: {@value} dpi * @see #GPUUISceneGLListener0A(float) * @see #GPUUISceneGLListener0A(float, boolean, boolean) */ public static final float DefaultNoAADPIThreshold = 200f; private int currentText = 0; private String actionText = null; private Label[] labels = null; private String[] strings = null; private final List<RoundButton> buttons = new ArrayList<RoundButton>(); private int buttonsLeftCount = 0; private Label truePtSizeLabel = null; private Label jogampLabel = null; private Label fpsLabel = null; private CrossHair crossHairCtr = null; private boolean ioAttached = false; private GLAutoDrawable cDrawable; private final GLReadBufferUtil screenshot; private final String jogamp = "JogAmp - Jogl Graph Module Demo"; private final String truePtSize = fontSizePt+" pt font size label - true scale!"; public GPUUISceneGLListener0A() { this(0); } /** * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold} */ public GPUUISceneGLListener0A(final float noAADPIThreshold) { this(noAADPIThreshold, false, false); } /** * @param renderModes */ public GPUUISceneGLListener0A(final int renderModes) { this(renderModes, false, false); } /** * @param renderModes * @param debug * @param trace */ public GPUUISceneGLListener0A(final int renderModes, final boolean debug, final boolean trace) { this(0f, renderModes, debug, trace); } /** * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold} * @param debug * @param trace */ public GPUUISceneGLListener0A(final float noAADPIThreshold, final boolean debug, final boolean trace) { this(noAADPIThreshold, 0, debug, trace); } private GPUUISceneGLListener0A(final float noAADPIThreshold, final int renderModes, final boolean debug, final boolean trace) { this.noAADPIThreshold = noAADPIThreshold; this.rs = RenderState.createRenderState(SVertex.factory()); this.debug = debug; this.trace = trace; this.renderModes = renderModes; try { font = FontFactory.get(FontFactory.UBUNTU).getDefault(); } catch (final IOException ioe) { throw new RuntimeException(ioe); } sceneUIController = new SceneUIController(sceneDist, zNear, zFar); screenshot = new GLReadBufferUtil(false, false); } private void rotateButtons(float[] angdeg) { angdeg = VectorUtil.scaleVec3(angdeg, angdeg, FloatUtil.PI / 180.0f); for(int i=0; i<buttons.size(); i++) { buttons.get(i).getRotation().rotateByEuler( angdeg ); } } private void translateButtons(final float tx, final float ty, final float tz) { for(int i=0; i<buttons.size(); i++) { buttons.get(i).translate(tx, ty, tz); } } private void setButtonsSpacing(final float dx, final float dy) { for(int i=0; i<buttons.size(); i++) { final RoundButton b = buttons.get(i); if( b instanceof LabelButton ) { final LabelButton lb = (LabelButton) b; final float sx = lb.getSpacingX()+dx, sy = lb.getSpacingY()+dy; System.err.println("Spacing: X "+sx+", Y "+sy); lb.setSpacing(sx, sy); } } } private void setButtonsCorner(final float dc) { for(int i=0; i<buttons.size(); i++) { final float c = buttons.get(i).getCorner()+dc; System.err.println("Corner: "+c); buttons.get(i).setCorner(c); } } private void resetButtons() { for(int i=0; i<buttons.size(); i++) { final RoundButton b = buttons.get(i); b.getRotation().setIdentity(); b.setCorner(RoundButton.DEFAULT_CORNER); if( b instanceof LabelButton ) { ((LabelButton)b).setSpacing(LabelButton.DEFAULT_SPACING_X, LabelButton.DEFAULT_SPACING_Y); } } } private void initButtons(final GL2ES2 gl, final int width, final int height, final RegionRenderer renderer) { final boolean pass2Mode = Region.isTwoPass( renderModes ) ; buttons.clear(); final float buttonXSize = buttonXSizePVP * width; // final float buttonYSize = buttonYSizePVP * height; final float buttonYSize = buttonXSize / 2.5f; System.err.println("Button Size: "+buttonXSizePVP+" x "+buttonYSizePVP+" * "+width+" x "+height+" -> "+buttonXSize+" x "+buttonYSize); final float xStartLeft = 0f; // aligned to left edge w/ space 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; LabelButton button = new LabelButton(SVertex.factory(), renderModes, font, "Next Text", buttonXSize, buttonYSize); button.translate(xStartLeft,yStartTop-diffY*buttons.size(), 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { if( null != labels[currentText] ) { labels[currentText].setEnabled(false); } currentText = (currentText+1)%labels.length; if( null != labels[currentText] ) { labels[currentText].setEnabled(true); } } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); button = new LabelButton(SVertex.factory(), renderModes, font, "Show FPS", buttonXSize, buttonYSize); button.setName(100); // FIXME: DEBUG tag button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f); button.setToggleable(true); button.setToggle(fpsLabel.isEnabled()); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final GLAnimatorControl a = cDrawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); } fpsLabel.setEnabled(!fpsLabel.isEnabled()); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); button = new LabelButton(SVertex.factory(), renderModes, font, "v-sync", buttonXSize, buttonYSize); button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f); button.setToggleable(true); button.setToggle(gl.getSwapInterval()>0); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { cDrawable.invoke(false, new GLRunnable() { @Override public boolean run(final GLAutoDrawable drawable) { final GL gl = drawable.getGL(); gl.setSwapInterval(gl.getSwapInterval()<=0?1:0); final GLAnimatorControl a = drawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); } return true; } }); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); button = new LabelButton(SVertex.factory(), renderModes, font, "< tilt >", buttonXSize, buttonYSize); button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { rotateButtons(new float[] { 0f, -5f, 0f}); // left-half pressed } else { rotateButtons(new float[] { 0f, 5f, 0f}); // right-half pressed } } } @Override public void mouseWheelMoved(final MouseEvent e) { rotateButtons(new float[] { 0f, e.getRotation()[1], 0f}); } } ); buttons.add(button); if( pass2Mode ) { // second column to the left button = new LabelButton(SVertex.factory(), renderModes, font, "< samples >", buttonXSize, buttonYSize); button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; int sampleCount = sceneUIController.getSampleCount(); if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { // left-half pressed sampleCount--; } else { // right-half pressed sampleCount++; } sampleCount = sceneUIController.setSampleCount(sampleCount); // validated / clipped } } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); button = new LabelButton(SVertex.factory(), renderModes, font, "< quality >", buttonXSize, buttonYSize); button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; int quality = 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++; } } sceneUIController.setAllShapesQuality(quality); } } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); } button = new LabelButton(SVertex.factory(), renderModes, font, "Quit", buttonXSize, buttonYSize); button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f); button.setColor(0.7f, 0.0f, 0.0f, 1.0f); button.setLabelColor(1.2f, 1.2f, 1.2f); button.setPressedColorMod(1.1f, 0.0f, 0.0f, 1.0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { new InterruptSource.Thread() { public void run() { if( null != cDrawable ) { final GLAnimatorControl actrl = cDrawable.getAnimator(); if( null != actrl ) { actrl.stop(); } cDrawable.destroy(); } } }.start(); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); // second column to the left { final int j = 1; // column int k = 0; // row button = new LabelButton(SVertex.factory(), renderModes, font, "y flip", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { rotateButtons(new float[] { 0f, 180f, 0f}); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); k++; button = new LabelButton(SVertex.factory(), renderModes, font, "x flip", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { rotateButtons(new float[] { 180f, 0f, 0f}); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); k++; button = new LabelButton(SVertex.factory(), renderModes, font, "+", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; // rel position to center final float dx = shapeEvent.objPos[0] - shapeEvent.shape.getBounds().getCenter()[0] ; final float dy = shapeEvent.objPos[1] - shapeEvent.shape.getBounds().getCenter()[1] ; // per-cent position to center (remove dependency on dimension) final float awdx = Math.abs(dx)/shapeEvent.shape.getBounds().getWidth(); final float awdy = Math.abs(dy)/shapeEvent.shape.getBounds().getHeight(); float tx = 0, ty = 0; if ( awdx > awdy ) { tx = dx < 0 ? -5 : 5; } else { ty = dy < 0 ? -5 : 5; } translateButtons(tx, ty, 0f); } } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); k++; button = new LabelButton(SVertex.factory(), renderModes, font, "< space >", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; final float dx, dy; if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { dx=-0.01f; dy=-0.005f; } else { dx=0.01f; dy=0.005f; } setButtonsSpacing(dx, dy); } } @Override public void mouseWheelMoved(final MouseEvent e) { setButtonsSpacing(e.getRotation()[0]/100f, e.getRotation()[1]/200f); } } ); buttons.add(button); k++; button = new LabelButton(SVertex.factory(), renderModes, font, "< corner >", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; final float dc; if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { dc=-0.1f; } else { dc=0.1f; } setButtonsCorner(dc); } } @Override public void mouseWheelMoved(final MouseEvent e) { setButtonsCorner(e.getRotation()[1]/20f); } } ); buttons.add(button); k++; button = new LabelButton(SVertex.factory(), renderModes, font, "reset", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { resetButtons(); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); k++; button = new LabelButton(SVertex.factory(), renderModes, font, "screenshot", buttonXSize, buttonYSize); button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { cDrawable.invoke(false, new GLRunnable() { @Override public boolean run(final GLAutoDrawable drawable) { printScreen(drawable.getGL()); return true; } }); } } ); button.addMouseListener(dragZoomRotateListener); buttons.add(button); k++; } buttonsLeftCount = buttons.size(); final float button2XSize = 2f*buttonXSize; final float button2YSize = 2f*buttonYSize; final float xStartRight = -button2XSize - 8f; // aligned to right edge via reshape final int texUnitMediaPlayer, texUnitImageButton, texUnitGLELButton; if( false ) { texUnitMediaPlayer=0; texUnitImageButton=0; texUnitGLELButton=0; } else { // works - but not required .. texUnitMediaPlayer=1; texUnitImageButton=2; texUnitGLELButton=3; } if( true ) { final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault(); mPlayer.setTextureUnit(texUnitMediaPlayer); final MediaPlayerButton mPlayerButton = new MediaPlayerButton(renderer.getRenderState().getVertexFactory(), renderModes, button2XSize, button2YSize, mPlayer); mPlayerButton.setVerbose(true); mPlayerButton.addDefaultEventListener(); mPlayerButton.translate(xStartRight, yStartTop - diffY*1, 0f); mPlayerButton.setToggleable(true); mPlayerButton.setToggle(false); // toggle == false -> mute audio mPlayerButton.setToggleOffColorMod(0f, 1f, 0f, 1.0f); mPlayerButton.addMouseListener(dragZoomRotateListener); mPlayerButton.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { mPlayer.setAudioVolume( mPlayerButton.isToggleOn() ? 1f : 0f ); } } ); buttons.add(mPlayerButton); try { final Uri streamLoc = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); mPlayer.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); } catch (final URISyntaxException e1) { e1.printStackTrace(); } } if( true ) { final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true); final ImageSeqButton imgButton = new ImageSeqButton(renderer.getRenderState().getVertexFactory(), renderModes, button2XSize, button2YSize, imgSeq); try { imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-released-145x53.png", TextureIO.PNG); imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-pressed-145x53.png", TextureIO.PNG); } catch (final IOException e2) { e2.printStackTrace(); } imgSeq.setManualStepping(true); imgButton.translate(xStartRight, yStartTop - diffY*2.5f, 0f); imgButton.addMouseListener(dragZoomRotateListener); imgButton.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mousePressed(final MouseEvent e) { imgButton.setCurrentIdx(1); System.err.println("XXX: "+imgButton); } @Override public void mouseReleased(final MouseEvent e) { imgButton.setCurrentIdx(0); } } ); buttons.add(imgButton); } if( true ) { // Issues w/ OSX and NewtCanvasAWT when rendering / animating // Probably related to CALayer - FBO - FBO* (of this button) final GLEventListener glel; if( true ) { final GearsES2 gears = new GearsES2(0); gears.setVerbose(false); gears.setClearColor(new float[] { 0.9f, 0.9f, 0.9f, 1f } ); glel = gears; } else if( false ) { glel = new RedSquareES2(0); } else { glel = new GLEventListener() { @Override public void init(final GLAutoDrawable drawable) { } @Override public void dispose(final GLAutoDrawable drawable) { } @Override public void display(final GLAutoDrawable drawable) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glClearColor(0.0f, 0.0f, 1.0f, 0.0f); // gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glClear(GL.GL_COLOR_BUFFER_BIT); } @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } }; } final GLEventListenerButton glelButton = new GLEventListenerButton(renderer.getRenderState().getVertexFactory(), renderModes, button2XSize, button2YSize, texUnitGLELButton, glel, false /* useAlpha */, (int)(button2XSize), (int)(button2YSize)); glelButton.setToggleable(true); glelButton.setToggle(false); // toggle == true -> animation glelButton.setAnimate(false); glelButton.translate(xStartRight, yStartTop - diffY*4f, 0f); glelButton.addMouseListener(dragZoomRotateListener); glelButton.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { glelButton.setAnimate( glelButton.isToggleOn() ); } } ); buttons.add(glelButton); } } private void initTexts() { strings = new String[4]; int i = 0; strings[i++] = "- Mouse Scroll Over Object\n"+ " - General\n"+ " - Z Translation\n"+ " - Ctrl: Y-Rotation (Shift: X-Rotation)\n"+ " - Tilt, Space and Corner\n"+ " - Their respective action via wheel\n"+ " (shift = other value)\n"+ "\n"+ "- Mouse Drag On Object\n"+ " - Click on Object and drag mouse\n"+ " - Current postion in status line at bottom\n"+ "\n"+ "- Tilt Button Rotate Whole Button Group"; strings[i++] = "abcdefghijklmn\nopqrstuvwxyz\n"+ "ABCDEFGHIJKL\n"+ "MNOPQRSTUVWXYZ\n"+ "0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; strings[i++] = "The quick brown fox\njumps over the lazy\ndog"; strings[i++] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec \n"+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel\n"+ "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices\n"+ "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia\n"+ "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat\n"+ "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum\n"+ "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin.\n"; labels = new Label[i]; } final boolean enableOthers = true; @Override public void init(final GLAutoDrawable drawable) { final Object upObj = drawable.getUpstreamWidget(); if( upObj instanceof Window ) { final Window upWin = (Window)upObj; final MonitorDevice mm = upWin.getMainMonitor(); final float[] monitorDPI = mm.getPixelsPerMM(new float[2]); monitorDPI[0] *= 25.4f; monitorDPI[1] *= 25.4f; final float[] sDPI = upWin.getPixelsPerMM(new float[2]); sDPI[0] *= 25.4f; sDPI[1] *= 25.4f; dpiH = sDPI[1]; System.err.println("Monitor detected: "+mm); System.err.println("Monitor dpi: "+monitorDPI[0]+" x "+monitorDPI[1]); System.err.println("Surface scale: native "+Arrays.toString(upWin.getMaximumSurfaceScale(new float[2]))+", current "+Arrays.toString(upWin.getCurrentSurfaceScale(new float[2]))); System.err.println("Surface dpi "+sDPI[0]+" x "+sDPI[1]); } else { System.err.println("Using default DPI of "+dpiH); } if( 0 == renderModes && !FloatUtil.isZero(noAADPIThreshold, FloatUtil.EPSILON)) { final boolean noAA = dpiH >= noAADPIThreshold; final String noAAs = noAA ? " >= " : " < "; System.err.println("AUTO RenderMode: dpi "+dpiH+noAAs+noAADPIThreshold+" -> noAA "+noAA); renderModes = noAA ? 0 : Region.VBAA_RENDERING_BIT; } if(drawable instanceof GLWindow) { System.err.println("GPUUISceneGLListener0A: init (1)"); final GLWindow glw = (GLWindow) drawable; attachInputListenerTo(glw); } else { System.err.println("GPUUISceneGLListener0A: init (0)"); } System.err.println("Chosen: "+drawable.getChosenGLCapabilities()); cDrawable = drawable; GL2ES2 gl = drawable.getGL().getGL2ES2(); if(debug) { gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ).getGL2ES2(); } if(trace) { gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); } try { font = FontFactory.get(fontSet).getDefault(); } catch (final IOException ioe) { throw new RuntimeException(ioe); } renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); // renderer = RegionRenderer.create(rs, null, null); gl.setSwapInterval(1); gl.glEnable(GL.GL_DEPTH_TEST); gl.glEnable(GL.GL_BLEND); renderer.init(gl, renderModes); initTexts(); sceneUIController.setRenderer(renderer); final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight(); jogampLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFixed, jogamp); jogampLabel.addMouseListener(dragZoomRotateListener); sceneUIController.addShape(jogampLabel); jogampLabel.setEnabled(enableOthers); final float pixelSize10Pt = font.getPixelSize(fontSizePt, dpiH); System.err.println("10Pt PixelSize: Display "+dpiH+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixel-size"); truePtSizeLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSize10Pt, truePtSize); sceneUIController.addShape(truePtSizeLabel); truePtSizeLabel.setEnabled(enableOthers); truePtSizeLabel.translate(0, - 1.5f * jogampLabel.getLineHeight(), 0f); truePtSizeLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f); /** * * [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 = fontSizeFpsPVP * drawable.getSurfaceHeight(); fpsLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFPS, "Nothing there yet"); fpsLabel.addMouseListener(dragZoomRotateListener); sceneUIController.addShape(fpsLabel); fpsLabel.setEnabled(enableOthers); fpsLabel.setColor(0.3f, 0.3f, 0.3f, 1.0f); crossHairCtr = new CrossHair(renderer.getRenderState().getVertexFactory(), 0, 100f, 100f, 2f); crossHairCtr.addMouseListener(dragZoomRotateListener); sceneUIController.addShape(crossHairCtr); crossHairCtr.setEnabled(true); crossHairCtr.translate(0f, 0f, -1f); initButtons(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), renderer); for(int i=0; i<buttons.size(); i++) { sceneUIController.addShape(buttons.get(i)); } sceneUIController.init(drawable); final GLAnimatorControl a = drawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); } } @Override public void dispose(final GLAutoDrawable drawable) { if(drawable instanceof GLWindow) { System.err.println("GPUUISceneGLListener0A: dispose (1)"); final GLWindow glw = (GLWindow) drawable; detachInputListenerFrom(glw); } else { System.err.println("GPUUISceneGLListener0A: dispose (0)"); } sceneUIController.dispose(drawable); // disposes all registered UIShapes final GL2ES2 gl = drawable.getGL().getGL2ES2(); renderer.destroy(gl); screenshot.dispose(gl); } private int shotCount = 0; public void printScreen(final GL gl) { final String modeS = Region.getRenderModeString(jogampLabel.getRenderModes()); final String filename = String.format("GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png", shotCount++, renderer.getWidth(), renderer.getHeight(), modeS, sceneUIController.getSampleCount()); gl.glFinish(); // just make sure rendering finished .. if(screenshot.readPixels(gl, false)) { screenshot.write(new File(filename)); System.err.println("Wrote: "+filename); } } @Override public void display(final GLAutoDrawable drawable) { // System.err.println("GPUUISceneGLListener0A: display"); final GL2ES2 gl = drawable.getGL().getGL2ES2(); if(null == labels[currentText]) { final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight(); final float dyTop = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight(); final float dxMiddle = drawable.getSurfaceWidth() * relMiddle; labels[currentText] = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFixed, strings[currentText]); labels[currentText].setColor(0.1f, 0.1f, 0.1f, 1.0f); labels[currentText].setEnabled(enableOthers); labels[currentText].translate(dxMiddle, dyTop - 1.5f * jogampLabel.getLineHeight() - 1.5f * truePtSizeLabel.getLineHeight(), 0f); labels[currentText].addMouseListener(dragZoomRotateListener); sceneUIController.addShape(labels[currentText]); System.err.println("Label["+currentText+"] CTOR: "+labels[currentText]); System.err.println("Label["+currentText+"] CTOR: "+Arrays.toString(labels[currentText].getTranslate())); } if( fpsLabel.isEnabled() ) { final float lfps, tfps, td; final GLAnimatorControl animator = drawable.getAnimator(); if( null != animator ) { lfps = animator.getLastFPS(); tfps = animator.getTotalFPS(); td = animator.getTotalFPSDuration()/1000f; } else { lfps = 0f; tfps = 0f; td = 0f; } final String modeS = Region.getRenderModeString(renderModes); final String text; if( null == actionText ) { final String timePrec = gl.isGLES() ? "4.0" : "4.1"; 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", lfps, tfps, gl.getSwapInterval(), dpiH, fontSizeFixedPVP, modeS, sceneUIController.getSampleCount(), fpsLabel.getQuality(), td, renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED), drawable.getChosenGLCapabilities().getAlphaBits(), drawable.getChosenGLCapabilities().getNumSamples()); } else { text = String.format("%03.1f/%03.1f fps, v-sync %d, fontSize %.1f, %s", lfps, tfps, gl.getSwapInterval(), fontSizeFixedPVP, actionText); } fpsLabel.setText(text); } sceneUIController.display(drawable); } float lastWidth = 0f, lastHeight = 0f; @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { System.err.println("GPUUISceneGLListener0A: reshape"); // // Layout all shapes: Relational move regarding window coordinates // final float dw = width - lastWidth; final float dh = height - lastHeight; final float dz = 0f; final float dyTop = dh * relTop; final float dxLeft = dw * relLeft; final float dxRight = dw; for(int i=0; i<buttons.size() && i<buttonsLeftCount; i++) { buttons.get(i).translate(dxLeft, dyTop, dz); } for(int i=buttonsLeftCount; i<buttons.size(); i++) { buttons.get(i).translate(dxRight, dyTop, dz); } final float dxMiddleAbs = width * relMiddle; final float dyTopLabelAbs = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight(); jogampLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs, dz); truePtSizeLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs, dz); truePtSizeLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight(), 0f); fpsLabel.translate(0f, 0f, 0f); if( null != labels[currentText] ) { labels[currentText].setTranslate(dxMiddleAbs, dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight() - 1.5f * truePtSizeLabel.getLineHeight(), 0f); System.err.println("Label["+currentText+"] MOVE: "+labels[currentText]); System.err.println("Label["+currentText+"] MOVE: "+Arrays.toString(labels[currentText].getTranslate())); } crossHairCtr.translate(dw/2f, dh/2f, 0f); sceneUIController.reshape(drawable, x, y, width, height); lastWidth = width; lastHeight = height; } public void attachInputListenerTo(final GLWindow window) { if ( !ioAttached ) { ioAttached = true; sceneUIController.attachInputListenerTo(window); } } public void detachInputListenerFrom(final GLWindow window) { if ( ioAttached ) { ioAttached = false; sceneUIController.detachInputListenerFrom(window); } } /** * We can share this instance w/ all UI elements, * since only mouse action / gesture is complete for a single one (press, drag, released and click). */ private final UIShape.MouseGestureAdapter dragZoomRotateListener = new UIShape.MouseGestureAdapter() { float dragFirstX=-1f, dragFirstY=-1f; boolean dragFirst = false; @Override public void mousePressed(final MouseEvent e) { dragFirst = true; } @Override public void mouseReleased(final MouseEvent e) { dragFirst = false; actionText = null; } @Override public void mouseDragged(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; if( e.getPointerCount() == 1 ) { // 1 pointer drag if(dragFirst) { dragFirstX = shapeEvent.objPos[0]; // e.getX(); dragFirstY = shapeEvent.objPos[1]; // e.getY(); dragFirst=false; return; } final float nx = shapeEvent.objPos[0]; // e.getX(); final float ny = shapeEvent.objPos[1]; // e.getY(); final float dx = nx - dragFirstX; final float dy = ny - dragFirstY; // final float dy = -(ny - dragLastY); shapeEvent.shape.translate(dx, dy, 0f); final float[] tx = shapeEvent.shape.getTranslate(); actionText = String.format("Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]); } } } @Override public void mouseWheelMoved(final MouseEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass(); if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) { // offscreen vertical mouse wheel zoom final float tz = 8f*e.getRotation()[1]; // vertical: wheel System.err.println("Rotate.Zoom.W: "+tz); shapeEvent.shape.translate(0f, 0f, tz); } else if( isOnscreen || e.isControlDown() ) { final float[] rot = VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f); if( isOnscreen ) { System.err.println("XXX: "+e); // swap axis for onscreen rotation matching natural feel final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp; VectorUtil.scaleVec3(rot, rot, 2f); } shapeEvent.shape.getRotation().rotateByEuler( rot ); } } } @Override public void gestureDetected(final GestureEvent e) { final Object attachment = e.getAttachment(); if( attachment instanceof UIShape.PointerEventInfo ) { final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment; if( e instanceof PinchToZoomGesture.ZoomEvent ) { final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e; final float tz = ze.getDelta() * ze.getScale(); System.err.println("Rotate.Zoom.G: "+tz); shapeEvent.shape.translate(0f, 0f, tz); } } } }; }