diff --git a/engine/src/desktop/com/jme3/input/awt/AwtKeyInput.java b/engine/src/desktop/com/jme3/input/awt/AwtKeyInput.java index 546a416ef..8667074ad 100644 --- a/engine/src/desktop/com/jme3/input/awt/AwtKeyInput.java +++ b/engine/src/desktop/com/jme3/input/awt/AwtKeyInput.java @@ -38,8 +38,7 @@ import com.jme3.input.event.KeyInputEvent; import java.awt.Component; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; -import java.util.LinkedList; -import java.util.List; +import java.util.ArrayList; import java.util.logging.Logger; /** @@ -52,8 +51,9 @@ import java.util.logging.Logger; public class AwtKeyInput implements KeyInput, KeyListener { private static final Logger logger = Logger.getLogger(AwtKeyInput.class.getName()); + + private final ArrayList eventQueue = new ArrayList(); private RawInputListener listener; - private List eventQueue = new LinkedList(); private Component component; public AwtKeyInput(){ @@ -66,12 +66,14 @@ public class AwtKeyInput implements KeyInput, KeyListener { } public void setInputSource(Component comp){ - if (component != null){ - component.removeKeyListener(this); - eventQueue.clear(); + synchronized (eventQueue){ + if (component != null){ + component.removeKeyListener(this); + eventQueue.clear(); + } + component = comp; + component.addKeyListener(this); } - component = comp; - component.addKeyListener(this); } public long getInputTimeNanos() { @@ -83,11 +85,13 @@ public class AwtKeyInput implements KeyInput, KeyListener { } public void update() { - // flush events to listener - for (int i = 0; i < eventQueue.size(); i++){ - listener.onKeyEvent(eventQueue.get(i)); + synchronized (eventQueue){ + // flush events to listener + for (int i = 0; i < eventQueue.size(); i++){ + listener.onKeyEvent(eventQueue.get(i)); + } + eventQueue.clear(); } - eventQueue.clear(); } public boolean isInitialized() { @@ -100,25 +104,30 @@ public class AwtKeyInput implements KeyInput, KeyListener { public void keyTyped(KeyEvent evt) { // key code is zero for typed events - int code = 0; - //int code = convertAwtKey(evt.getKeyCode()); - KeyInputEvent keyEvent = new KeyInputEvent(code, evt.getKeyChar(), false, true); - keyEvent.setTime(evt.getWhen()); - eventQueue.add(keyEvent); +// int code = 0; +// KeyInputEvent keyEvent = new KeyInputEvent(code, evt.getKeyChar(), false, true); +// keyEvent.setTime(evt.getWhen()); +// synchronized (eventQueue){ +// eventQueue.add(keyEvent); +// } } public void keyPressed(KeyEvent evt) { int code = convertAwtKey(evt.getKeyCode()); KeyInputEvent keyEvent = new KeyInputEvent(code, evt.getKeyChar(), true, false); keyEvent.setTime(evt.getWhen()); - eventQueue.add(keyEvent); + synchronized (eventQueue){ + eventQueue.add(keyEvent); + } } public void keyReleased(KeyEvent evt) { int code = convertAwtKey(evt.getKeyCode()); KeyInputEvent keyEvent = new KeyInputEvent(code, evt.getKeyChar(), false, false); keyEvent.setTime(evt.getWhen()); - eventQueue.add(keyEvent); + synchronized (eventQueue){ + eventQueue.add(keyEvent); + } } /** diff --git a/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java b/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java index 3b2900ac5..d047d814f 100644 --- a/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java +++ b/engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java @@ -88,6 +88,7 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe private Point centerLocationOnScreen; private Point lastKnownLocation; private boolean isRecentering; + private boolean cursorMoved; private int eventsSinceRecenter; public AwtMouseInput() { @@ -161,29 +162,33 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe } public void update() { - int newX = location.x; - int newY = location.y; - int newWheel = wheelPos; - - // invert DY - MouseMotionEvent evt = new MouseMotionEvent(newX, newY, - newX - lastEventX, - lastEventY - newY, - wheelPos, lastEventWheel - wheelPos); - listener.onMouseMotionEvent(evt); + if (cursorMoved){ + int newX = location.x; + int newY = location.y; + int newWheel = wheelPos; + + // invert DY + MouseMotionEvent evt = new MouseMotionEvent(newX, newY, + newX - lastEventX, + lastEventY - newY, + wheelPos, lastEventWheel - wheelPos); + listener.onMouseMotionEvent(evt); + + lastEventX = newX; + lastEventY = newY; + lastEventWheel = newWheel; + + cursorMoved = false; + } int size = eventQueue.size(); for (int i = 0; i < size; i++){ listener.onMouseButtonEvent(eventQueue.get(i)); } eventQueue.clear(); - - lastEventX = newX; - lastEventY = newY; - lastEventWheel = newWheel; } - private final Cursor getTransparentCursor() { + private Cursor getTransparentCursor() { if (transparentCursor == null){ BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); cursorImage.setRGB(0, 0, 0); @@ -191,10 +196,7 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe } return transparentCursor; } -// -// public boolean isCursorVisible() { -// return( isCursorVisible ); -// } + // public void setHardwareCursor(URL file, int xHotspot, int yHotspot) { // //Create the image from the provided url // java.awt.Image cursorImage = new ImageIcon( file ).getImage( ); @@ -239,6 +241,7 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe public void mouseWheelMoved(MouseWheelEvent arg0) { int dwheel = arg0.getUnitsToScroll(); wheelPos -= dwheel; + cursorMoved = true; } public void mouseDragged(MouseEvent arg0) { @@ -267,16 +270,8 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe } lastKnownLocation.x = arg0.getX(); lastKnownLocation.y = arg0.getY(); -// MHenze (cylab) Fix Issue 35: all accesses to the swingEvents list have to be synchronized for StandardGame to work... - // TODO MHenze (cylab): Cleanup. this members seem obsolete by the newly introduced above. -// absPoint.setLocation(location); -// if (lastPoint.x == Integer.MIN_VALUE) { -// lastPoint.setLocation(absPoint.x, absPoint.y); -// } -// lastPoint.setLocation(arg0.getPoint()); -// currentDeltaPoint.x = absPoint.x - lastPoint.x; -// currentDeltaPoint.y = -(absPoint.y - lastPoint.y); -// lastPoint.setLocation(location); + + cursorMoved = true; } } @@ -285,14 +280,10 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe if (robot != null) { eventsSinceRecenter = 0; isRecentering = true; -// SwingUtilities.invokeLater(new Runnable() { -// public void run() { centerLocation.setLocation(component.getWidth()/2, component.getHeight()/2); centerLocationOnScreen.setLocation(centerLocation); SwingUtilities.convertPointToScreen(centerLocationOnScreen, component); robot.mouseMove(centerLocationOnScreen.x, centerLocationOnScreen.y); -// } -// }); } } @@ -301,13 +292,13 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe switch (arg0.getButton()) { default: case MouseEvent.BUTTON1: //left - index = 0; + index = MouseInput.BUTTON_LEFT; break; case MouseEvent.BUTTON2: //middle - index = 2; + index = MouseInput.BUTTON_MIDDLE; break; case MouseEvent.BUTTON3: //right - index = 1; + index = MouseInput.BUTTON_RIGHT; break; } return index; diff --git a/engine/src/desktop/com/jme3/system/awt/AwtPanel.java b/engine/src/desktop/com/jme3/system/awt/AwtPanel.java index 1cfd6d840..b25f3f378 100644 --- a/engine/src/desktop/com/jme3/system/awt/AwtPanel.java +++ b/engine/src/desktop/com/jme3/system/awt/AwtPanel.java @@ -8,9 +8,12 @@ import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image.Format; import com.jme3.util.BufferUtils; import com.jme3.util.Screenshots; +import java.awt.AWTException; +import java.awt.BufferCapabilities; import java.awt.Canvas; -import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.ImageCapabilities; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.geom.AffineTransform; @@ -18,10 +21,9 @@ import java.awt.image.AffineTransformOp; import java.awt.image.BufferStrategy; import java.awt.image.BufferedImage; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.ArrayList; import java.util.Arrays; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicBoolean; public class AwtPanel extends Canvas implements SceneProcessor { @@ -29,6 +31,7 @@ public class AwtPanel extends Canvas implements SceneProcessor { private BufferedImage img; private FrameBuffer fb; private ByteBuffer byteBuf; + private IntBuffer intBuf; private boolean activeUpdates = true; private RenderManager rm; private ArrayList viewPorts = new ArrayList(); @@ -36,15 +39,13 @@ public class AwtPanel extends Canvas implements SceneProcessor { // Visibility/drawing vars private BufferStrategy strategy; private AffineTransformOp transformOp; - private CyclicBarrier visibleBarrier = new CyclicBarrier(2); private AtomicBoolean visible = new AtomicBoolean(false); - private boolean glVisible = false; // Reshape vars - private int newWidth = 0; - private int newHeight = 0; - private CyclicBarrier reshapeBarrier = new CyclicBarrier(2); + private int newWidth = 1; + private int newHeight = 1; private AtomicBoolean reshapeNeeded = new AtomicBoolean(false); + private final Object lock = new Object(); public AwtPanel(boolean activeUpdates){ this.activeUpdates = activeUpdates; @@ -53,16 +54,15 @@ public class AwtPanel extends Canvas implements SceneProcessor { addComponentListener(new ComponentAdapter(){ @Override public void componentResized(ComponentEvent e) { - newWidth = Math.max(getWidth(), 1); - newHeight = Math.max(getHeight(), 1); - reshapeNeeded.set(true); - - try { - reshapeBarrier.await(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } catch (BrokenBarrierException ex) { - ex.printStackTrace(); + synchronized (lock){ + int newWidth2 = Math.max(getWidth(), 1); + int newHeight2 = Math.max(getHeight(), 1); + if (newWidth != newWidth2 || newHeight != newHeight2){ + newWidth = newWidth2; + newHeight = newHeight2; + reshapeNeeded.set(true); + System.out.println("EDT: componentResized " + newWidth + ", " + newHeight); + } } } }); @@ -72,15 +72,9 @@ public class AwtPanel extends Canvas implements SceneProcessor { public void addNotify(){ super.addNotify(); - try { - createBufferStrategy(2); - strategy = getBufferStrategy(); + synchronized (lock){ visible.set(true); - visibleBarrier.await(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } catch (BrokenBarrierException ex) { - ex.printStackTrace(); + System.out.println("EDT: addNotify"); } requestFocusInWindow(); @@ -88,48 +82,47 @@ public class AwtPanel extends Canvas implements SceneProcessor { @Override public void removeNotify(){ - try { + synchronized (lock){ visible.set(false); - visibleBarrier.await(); - strategy = null; - } catch (InterruptedException ex) { - ex.printStackTrace(); - } catch (BrokenBarrierException ex) { - ex.printStackTrace(); +// strategy.dispose(); +// strategy = null; + System.out.println("EDT: removeNotify"); } super.removeNotify(); } - private void checkVisibility(){ - if (visible.get() != glVisible){ + public void drawFrameInThread(){ + if (!visible.get()){ + if (strategy != null){ + strategy.dispose(); + strategy = null; + } + return; + } + + if (strategy == null || strategy.contentsLost()){ + if (strategy != null){ + strategy.dispose(); + } try { - glVisible = visible.get(); - visibleBarrier.await(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } catch (BrokenBarrierException ex) { + createBufferStrategy(1, new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), BufferCapabilities.FlipContents.UNDEFINED)); + } catch (AWTException ex) { ex.printStackTrace(); } + strategy = getBufferStrategy(); + System.out.println("OGL: BufferStrategy lost!"); } - } - - public void drawFrame(){ - checkVisibility(); - if (!glVisible) - return; + + Graphics2D g2d; - if (strategy.contentsLost()){ - strategy.dispose(); - createBufferStrategy(2); - strategy = getBufferStrategy(); - System.out.println("BufferStrategy lost!"); + synchronized (lock){ + g2d = (Graphics2D) strategy.getDrawGraphics(); } - Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics(); g2d.drawImage(img, transformOp, 0, 0); g2d.dispose(); - strategy.show(); + strategy.show(); } public boolean isActiveUpdates() { @@ -137,7 +130,9 @@ public class AwtPanel extends Canvas implements SceneProcessor { } public void setActiveUpdates(boolean activeUpdates) { - this.activeUpdates = activeUpdates; + synchronized (lock){ + this.activeUpdates = activeUpdates; + } } public void attachTo(ViewPort ... vps){ @@ -162,11 +157,15 @@ public class AwtPanel extends Canvas implements SceneProcessor { private void reshapeInThread(int width, int height) { byteBuf = BufferUtils.ensureLargeEnough(byteBuf, width * height * 4); + intBuf = byteBuf.asIntBuffer(); fb = new FrameBuffer(width, height, 1); fb.setDepthBuffer(Format.Depth); fb.setColorBuffer(Format.RGB8); img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// synchronized (lock){ +// img = (BufferedImage) getGraphicsConfiguration().createCompatibleImage(width, height); +// } AffineTransform tx = AffineTransform.getScaleInstance(1, -1); tx.translate(0, -img.getHeight()); transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); @@ -188,26 +187,19 @@ public class AwtPanel extends Canvas implements SceneProcessor { } public void postFrame(FrameBuffer out) { - if (out != fb) + if (out != fb){ throw new IllegalStateException("Why did you change the output framebuffer?"); + } if (reshapeNeeded.getAndSet(false)){ reshapeInThread(newWidth, newHeight); - try { - reshapeBarrier.await(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } catch (BrokenBarrierException ex) { - ex.printStackTrace(); - } }else if (activeUpdates){ byteBuf.clear(); rm.getRenderer().readFrameBuffer(fb, byteBuf); - Screenshots.convertScreenShot2(byteBuf, img); - drawFrame(); - }else{ - checkVisibility(); + Screenshots.convertScreenShot2(intBuf, img); + drawFrameInThread(); } + } public void reshape(ViewPort vp, int w, int h) { diff --git a/engine/src/desktop/com/jme3/system/awt/AwtPanelsContext.java b/engine/src/desktop/com/jme3/system/awt/AwtPanelsContext.java index 5fa0c8cd9..75f91ef65 100644 --- a/engine/src/desktop/com/jme3/system/awt/AwtPanelsContext.java +++ b/engine/src/desktop/com/jme3/system/awt/AwtPanelsContext.java @@ -138,7 +138,8 @@ public class AwtPanelsContext implements JmeContext { } public void setSettings(AppSettings settings) { - settings.copyFrom(settings); + this.settings.copyFrom(settings); + this.settings.setRenderer(AppSettings.LWJGL_OPENGL2); if (actualContext != null){ actualContext.setSettings(settings); } diff --git a/engine/src/desktop/com/jme3/util/Screenshots.java b/engine/src/desktop/com/jme3/util/Screenshots.java index f2412e5fd..bbb69669c 100644 --- a/engine/src/desktop/com/jme3/util/Screenshots.java +++ b/engine/src/desktop/com/jme3/util/Screenshots.java @@ -5,17 +5,18 @@ import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.WritableRaster; import java.nio.ByteBuffer; +import java.nio.IntBuffer; public final class Screenshots { - public static void convertScreenShot2(ByteBuffer bgraBuf, BufferedImage out){ + public static void convertScreenShot2(IntBuffer bgraBuf, BufferedImage out){ WritableRaster wr = out.getRaster(); DataBufferInt db = (DataBufferInt) wr.getDataBuffer(); int[] cpuArray = db.getData(); bgraBuf.clear(); - bgraBuf.asIntBuffer().get(cpuArray); + bgraBuf.get(cpuArray); // int width = wr.getWidth(); // int height = wr.getHeight(); diff --git a/engine/src/test/jme3test/awt/TestAwtPanels.java b/engine/src/test/jme3test/awt/TestAwtPanels.java index 115754c47..8eac2073d 100644 --- a/engine/src/test/jme3test/awt/TestAwtPanels.java +++ b/engine/src/test/jme3test/awt/TestAwtPanels.java @@ -49,6 +49,7 @@ public class TestAwtPanels extends SimpleApplication { app.setShowSettings(false); AppSettings settings = new AppSettings(true); settings.setCustomRenderer(AwtPanelsContext.class); + settings.setFrameRate(60); app.setSettings(settings); app.start();