package com.marginallyclever.makelangelo; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.event.MouseInputListener; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.awt.GLJPanel; import com.jogamp.opengl.glu.GLU; import com.marginallyclever.makelangeloRobot.MakelangeloRobot; // Custom drawing panel written as an inner class to access the instance variables. public class DrawPanel extends GLJPanel implements MouseListener, MouseInputListener, GLEventListener { static final long serialVersionUID=2; // Use debug pipeline? private static final boolean DEBUG_GL_ON=false; private static final boolean TRACE_GL_ON=false; // motion control //private boolean mouseIn=false; private int buttonPressed=MouseEvent.NOBUTTON; private int mouseOldX, mouseOldY; // scale + position private double cameraOffsetX = 0.0d; private double cameraOffsetY = 0.0d; private double cameraZoom = 1.0d; private int windowWidth=0; private int windowHeight=0; protected MakelangeloRobot robot; public DrawPanel(GLCapabilities caps) { super(caps); addMouseMotionListener(this); addMouseListener(this); addGLEventListener(this); } void setRobot(MakelangeloRobot r) { robot = r; } /** * set up the correct projection so the image appears in the right location and aspect ratio. */ @Override public void reshape(GLAutoDrawable glautodrawable, int x, int y, int width, int height) { GL2 gl2 = glautodrawable.getGL().getGL2(); gl2.setSwapInterval(1); windowWidth = width; windowHeight = height; //window_aspect_ratio = window_width / window_height; gl2.glMatrixMode(GL2.GL_PROJECTION); gl2.glLoadIdentity(); //gl2.glOrtho(-windowWidth / 2.0d, windowWidth / 2.0d, -windowHeight / 2.0d, windowHeight / 2.0d, 0.01d, 100.0d); GLU glu = new GLU(); glu.gluPerspective(60, (float)windowWidth/(float)windowHeight, 1.0f, 1000.0f); } /** * turn on debug pipeline(s) if needed. */ @Override public void init(GLAutoDrawable drawable) { if (DEBUG_GL_ON) { try { // Debug .. GL gl = drawable.getGL(); gl = gl.getContext().setGL(GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null)); } catch (Exception e) { e.printStackTrace(); } } if (TRACE_GL_ON) { try { // Trace .. GL gl = drawable.getGL(); gl = gl.getContext().setGL(GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[]{System.err})); } catch (Exception e) { e.printStackTrace(); } } } @Override public void dispose(GLAutoDrawable glautodrawable) {} /** * refresh the image in the view */ @Override public void display(GLAutoDrawable glautodrawable) { //long now_time = System.currentTimeMillis(); //float dt = (now_time - last_time)*0.001f; //last_time = now_time; //System.out.println(dt); GL2 gl2 = glautodrawable.getGL().getGL2(); //gl2.glEnable(GL2.GL_LINE_SMOOTH); //gl2.glEnable(GL2.GL_POLYGON_SMOOTH); //gl2.glHint(GL2.GL_POLYGON_SMOOTH_HINT, GL2.GL_NICEST); // draw the world render(gl2); } /** * scale the picture of the robot to fake a zoom. */ public void zoomToFitPaper() { double widthOfPaper = robot.getSettings().getPaperWidth(); double heightOfPaper = robot.getSettings().getPaperHeight(); double drawPanelWidthZoom = widthOfPaper; double drawPanelHeightZoom = heightOfPaper; if( windowWidth < windowHeight ) { cameraZoom = (drawPanelWidthZoom > drawPanelHeightZoom ? drawPanelWidthZoom : drawPanelHeightZoom ); } else { cameraZoom = (drawPanelWidthZoom < drawPanelHeightZoom ? drawPanelWidthZoom : drawPanelHeightZoom ); } cameraOffsetX = 0; cameraOffsetY = 0; } public void mousePressed(MouseEvent e) { buttonPressed=e.getButton(); mouseOldX=e.getX(); mouseOldY=e.getY(); } public void mouseReleased(MouseEvent e) { buttonPressed=MouseEvent.NOBUTTON; } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseDragged(MouseEvent e) { int x=e.getX(); int y=e.getY(); int dx = x - mouseOldX; int dy = y - mouseOldY; if(buttonPressed==MouseEvent.BUTTON1) moveCamera(-dx,-dy); if(buttonPressed==MouseEvent.BUTTON3) zoomCamera(dy); mouseOldX=x; mouseOldY=y; } public void mouseMoved(MouseEvent e) {} /** * position the camera in from of the robot * * @param dx change horizontally * @param dy change vertically */ private void moveCamera(int dx, int dy) { cameraOffsetX += (float)dx * cameraZoom / windowWidth; cameraOffsetY += (float)dy * cameraZoom / windowHeight; } /** * scale the picture of the robot to fake a zoom. * * @param y */ private void zoomCamera(int dy) { double zoomAmount = (double)dy * 0.25; cameraZoom += zoomAmount; if (cameraZoom < 0.1) cameraZoom = 0.1; } /** * scale the picture of the robot to fake a zoom. */ public void zoomIn() { cameraZoom *= 3.0d / 4.0d; } /** * scale the picture of the robot to fake a zoom. */ public void zoomOut() { cameraZoom *= 4.0d / 3.0d; } /** * set up the correct modelview so the robot appears where it hsould. * * @param gl2 */ private void paintCamera(GL2 gl2) { gl2.glMatrixMode(GL2.GL_MODELVIEW); gl2.glLoadIdentity(); gl2.glTranslated(-cameraOffsetX, cameraOffsetY, -cameraZoom); } /** * clear the panel * * @param gl2 */ private void paintBackground(GL2 gl2) { // Clear The Screen And The Depth Buffer gl2.glClearColor(212.0f/255.0f, 233.0f/255.0f, 255.0f/255.0f, 0.0f); // Special handling for the case where the GLJPanel is translucent // and wants to be composited with other Java 2D content if (GLProfile.isAWTAvailable() && (this instanceof com.jogamp.opengl.awt.GLJPanel) && !((com.jogamp.opengl.awt.GLJPanel) this).isOpaque() && ((com.jogamp.opengl.awt.GLJPanel) this).shouldPreserveColorBufferIfTranslucent()) { gl2.glClear(GL2.GL_DEPTH_BUFFER_BIT); } else { gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); } } public void render(GL2 gl2) { paintBackground(gl2); paintCamera(gl2); gl2.glPushMatrix(); if(robot!=null) { robot.render(gl2); } gl2.glPopMatrix(); } } /** * This file is part of Makelangelo. * <p> * Makelangelo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * <p> * Makelangelo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * <p> * You should have received a copy of the GNU General Public License * along with Makelangelo. If not, see <http://www.gnu.org/licenses/>. */