package de.nameless.graphicEngine;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import com.sun.opengl.util.FPSAnimator;
import de.nameless.graphicEngine.lib.NECamera;
/**
* @author Pepijn Van Eeckhoudt
*/
public class GLDisplay {
private static final int DEFAULT_WIDTH = 1024;
private static final int DEFAULT_HEIGHT = 786;
private static final int DONT_CARE = -1;
private JFrame frame;
private GLCanvas glCanvas;
private FPSAnimator animator;
private static final boolean FULLSCREEN = false;
private int width;
private int height;
private GraphicsDevice usedDevice;
private NEabstractGraphicObject[] ObjectsUnderMouse;
private boolean mouseOnDisplay = false;
private int mouseX;
private int mouseY;
private MyHelpOverlayGLEventListener helpOverlayGLEventListener = new MyHelpOverlayGLEventListener();
private MyExceptionHandler exceptionHandler = new MyExceptionHandler();
public static GLDisplay createGLDisplay(String title, int width , int hight) {
GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
return new GLDisplay( title, width, hight);
}
private GLDisplay( String title, int width, int height) {
glCanvas = new GLCanvas(new GLCapabilities());
glCanvas.setSize( width-100, height-100 );
glCanvas.setIgnoreRepaint( true );
glCanvas.addGLEventListener( helpOverlayGLEventListener );
frame = new JFrame( title );
frame.getContentPane().setLayout( new BorderLayout() );
frame.getContentPane().add( glCanvas, BorderLayout.CENTER );
//frame.getContentPane().add( new JButton("test"), BorderLayout.EAST);
//addKeyListener( new MyKeyAdapter() );
this.width = width;
this.height = height;
animator = new FPSAnimator( glCanvas,1000);
animator.setRunAsFastAsPossible(true);
}
public void start() {
try {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setUndecorated( FULLSCREEN );
frame.addWindowListener( new MyWindowAdapter() );
if ( FULLSCREEN ) {
usedDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
usedDevice.setFullScreenWindow( frame );
usedDevice.setDisplayMode(
findDisplayMode(
usedDevice.getDisplayModes(),
width, height,
usedDevice.getDisplayMode().getBitDepth(),
usedDevice.getDisplayMode().getRefreshRate()
)
);
} else {
frame.setSize( frame.getContentPane().getPreferredSize() );
frame.setLocation(
( screenSize.width - frame.getWidth() ) / 2,
( screenSize.height - frame.getHeight() ) / 2
);
frame.setVisible( true );
}
glCanvas.requestFocus();
animator.start();
} catch ( Exception e ) {
exceptionHandler.handleException( e );
}
}
public void stop() {
try {
animator.stop();
if ( FULLSCREEN ) {
usedDevice.setFullScreenWindow( null );
usedDevice = null;
}
frame.dispose();
} catch ( Exception e ) {
exceptionHandler.handleException( e );
} finally {
System.exit( 0 );
}
}
private DisplayMode findDisplayMode( DisplayMode[] displayModes, int requestedWidth, int requestedHeight, int requestedDepth, int requestedRefreshRate ) {
// Try to find an exact match
DisplayMode displayMode = findDisplayModeInternal( displayModes, requestedWidth, requestedHeight, requestedDepth, requestedRefreshRate );
// Try again, ignoring the requested bit depth
if ( displayMode == null )
displayMode = findDisplayModeInternal( displayModes, requestedWidth, requestedHeight, DONT_CARE, DONT_CARE );
// Try again, and again ignoring the requested bit depth and height
if ( displayMode == null )
displayMode = findDisplayModeInternal( displayModes, requestedWidth, DONT_CARE, DONT_CARE, DONT_CARE );
// If all else fails try to get any display mode
if ( displayMode == null )
displayMode = findDisplayModeInternal( displayModes, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
return displayMode;
}
private DisplayMode findDisplayModeInternal( DisplayMode[] displayModes, int requestedWidth, int requestedHeight, int requestedDepth, int requestedRefreshRate ) {
DisplayMode displayModeToUse = null;
for ( int i = 0; i < displayModes.length; i++ ) {
DisplayMode displayMode = displayModes[i];
if ( ( requestedWidth == DONT_CARE || displayMode.getWidth() == requestedWidth ) &&
( requestedHeight == DONT_CARE || displayMode.getHeight() == requestedHeight ) &&
( requestedHeight == DONT_CARE || displayMode.getRefreshRate() == requestedRefreshRate ) &&
( requestedDepth == DONT_CARE || displayMode.getBitDepth() == requestedDepth ) )
displayModeToUse = displayMode;
}
return displayModeToUse;
}
public void addGLEventListener( GLEventListener glEventListener ) {
this.helpOverlayGLEventListener.addGLEventListener( glEventListener );
}
public void removeGLEventListener( GLEventListener glEventListener ) {
this.helpOverlayGLEventListener.removeGLEventListener( glEventListener );
}
public void addKeyListener( KeyListener l ) {
glCanvas.addKeyListener( l );
}
public void addMouseListener( MouseListener l ) {
glCanvas.addMouseListener( l );
}
public void addMouseMotionListener( MouseMotionListener l ) {
glCanvas.addMouseMotionListener( l );
}
public void removeKeyListener( KeyListener l ) {
glCanvas.removeKeyListener( l );
}
public void removeMouseListener( MouseListener l ) {
glCanvas.removeMouseListener( l );
}
public void removeMouseMotionListener( MouseMotionListener l ) {
glCanvas.removeMouseMotionListener( l );
}
/**
* @param arg0
* @see java.awt.Component#addMouseWheelListener(java.awt.event.MouseWheelListener)
*/
public void addMouseWheelListener(MouseWheelListener arg0) {
glCanvas.addMouseWheelListener(arg0);
}
public void registerKeyStrokeForHelp( KeyStroke keyStroke, String description ) {
helpOverlayGLEventListener.registerKeyStroke( keyStroke, description );
}
public void registerMouseEventForHelp( int id, int modifiers, String description ) {
helpOverlayGLEventListener.registerMouseEvent( id, modifiers, description );
}
public String getTitle() {
return frame.getTitle();
}
public void setTitle( String title ) {
frame.setTitle( title );
}
private class MyWindowAdapter extends WindowAdapter {
public void windowClosing( WindowEvent e ) {
stop();
}
}
private class MyExceptionHandler implements ExceptionHandler {
public void handleException( final Exception e ) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter( stringWriter );
e.printStackTrace( printWriter );
JOptionPane.showMessageDialog( frame, stringWriter.toString(), "Exception occurred", JOptionPane.ERROR_MESSAGE );
stop();
}
} );
}
}
private static class MyHelpOverlayGLEventListener implements GLEventListener {
private java.util.List<GLEventListener> eventListeners = new ArrayList<GLEventListener>();
private HelpOverlay helpOverlay = new HelpOverlay();
private boolean showHelp = false;
public void toggleHelp() {
showHelp = !showHelp;
}
public void registerKeyStroke( KeyStroke keyStroke, String description ) {
helpOverlay.registerKeyStroke( keyStroke, description );
}
public void registerMouseEvent(int id, int modifiers, String description){
helpOverlay.registerMouseEvent( id, modifiers, description );
}
public void addGLEventListener( GLEventListener glEventListener ) {
eventListeners.add( glEventListener );
}
public void removeGLEventListener( GLEventListener glEventListener ) {
eventListeners.remove( glEventListener );
}
public void display( GLAutoDrawable glDrawable ) {
for ( int i = 0; i < eventListeners.size(); i++ ) {
eventListeners.get( i ).display( glDrawable );
}
if ( showHelp )
helpOverlay.display( glDrawable );
}
public void displayChanged( GLAutoDrawable glDrawable, boolean b, boolean b1 ) {
for ( int i = 0; i < eventListeners.size(); i++ ) {
eventListeners.get( i ).displayChanged( glDrawable, b, b1 );
}
}
public void init( GLAutoDrawable glDrawable ) {
for ( int i = 0; i < eventListeners.size(); i++ ) {
eventListeners.get( i ).init( glDrawable );
}
}
public void reshape( GLAutoDrawable glDrawable, int i0, int i1, int i2, int i3 ) {
for ( int i = 0; i < eventListeners.size(); i++ ) {
eventListeners.get( i ).reshape( glDrawable, i0, i1, i2, i3 );
}
}
}
/**
* @return the width of the frame
*/
public int getWidth() {
return frame.getWidth();
}
/**
* @param width the width to set
*/
public void setSize(int hight ,int width) {
frame.setSize(hight, width) ;
}
/**
* @return the height of the frame
*/
public int getHeight() {
return frame.getHeight();
}
/**
* @return
*/
public int getX() {
return frame.getX();
}
/**
* @return
*/
public int getY() {
return frame.getY();
}
/**
* @param arg0
* @param arg1
*/
public void setLocation(int arg0, int arg1) {
frame.setLocation(arg0, arg1);
}
public void setMousePos(int x, int y){
this.mouseOnDisplay = true;
this.mouseX = x;
this.mouseY = y;
}
public void mouseExit(){
this.mouseOnDisplay = false;
}
/**
* liefert die Y position auf die der mauszeiger weist
* @param e ein Mausevent, dessen position berechnet weden soll
* @param c kamera in der Szene
* @return die position im Ogl fenster.
*/
public float glYPos(MouseEvent e, NECamera c){
float tanA = 0.414213562f;// new Float(Math.tan(45/2*(Math.PI/180)));
float result;
int y = e.getY();
int h = glCanvas.getHeight();
y = (y - h/2)*-1;
result = (float)y/(float)h*(tanA*c.z*2);
result += (float) c.y;
return result;
}
/**
* liefert die X position auf die der mauszeiger weist
* @param e ein Mausevent, dessen position berechnet weden soll
* @param c kamera in der Szene
* @return die position im Ogl fenster.
*/
public float glXPos(MouseEvent e, NECamera c){
float tanA = 0.414213562f; // = tan(42/2[RAD])
float result;
int x = e.getX();
int h = glCanvas.getHeight();
int w = glCanvas.getWidth();
float hw = (float)w/(float)h;
x = (x - w/2);
result = x/(float)w*tanA*2*c.z*hw;
result += c.x;
return result;
}
public boolean isMouseOnDisplay() {
return mouseOnDisplay;
}
public int getMouseX() {
return mouseX;
}
public int getMouseY() {
return mouseY;
}
public NEabstractGraphicObject[] getObjectsUnderMouse() {
return ObjectsUnderMouse;
}
public void setObjectsUnderMouse(NEabstractGraphicObject[] objectsUnderMouse) {
ObjectsUnderMouse = objectsUnderMouse;
}
}