* Initial commit for light-weight jME3 AWT panels

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8323 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
sha..rd 13 years ago
parent 5d5e0082a7
commit a28d0d8baf
  1. 27
      engine/src/desktop/com/jme3/input/awt/AwtKeyInput.java
  2. 50
      engine/src/desktop/com/jme3/input/awt/AwtMouseInput.java
  3. 218
      engine/src/desktop/com/jme3/system/awt/AwtPanel.java
  4. 176
      engine/src/desktop/com/jme3/system/awt/AwtPanelsContext.java
  5. 26
      engine/src/desktop/com/jme3/util/Screenshots.java
  6. 86
      engine/src/test/jme3test/awt/TestAwtPanels.java
  7. 8
      engine/src/test/jme3test/batching/TestCubeCluster.java

@ -53,19 +53,25 @@ public class AwtKeyInput implements KeyInput, KeyListener {
private static final Logger logger = Logger.getLogger(AwtKeyInput.class.getName()); private static final Logger logger = Logger.getLogger(AwtKeyInput.class.getName());
private RawInputListener listener; private RawInputListener listener;
private boolean inited = false;
private List<KeyInputEvent> eventQueue = new LinkedList<KeyInputEvent>(); private List<KeyInputEvent> eventQueue = new LinkedList<KeyInputEvent>();
private Component component; private Component component;
public AwtKeyInput(Component comp){ public AwtKeyInput(){
this.component = comp;
} }
public void initialize() { public void initialize() {
inited = true; }
component.addKeyListener(this);
logger.info("Key input initialized."); public void destroy() {
}
public void setInputSource(Component comp){
if (component != null){
component.removeKeyListener(this);
eventQueue.clear();
}
component = comp;
component.addKeyListener(this);
} }
public long getInputTimeNanos() { public long getInputTimeNanos() {
@ -84,15 +90,8 @@ public class AwtKeyInput implements KeyInput, KeyListener {
eventQueue.clear(); eventQueue.clear();
} }
public void destroy() {
inited = false;
component.removeKeyListener(this);
logger.info("Key input destroyed.");
}
public boolean isInitialized() { public boolean isInitialized() {
return inited; return true;
} }
public void setInputListener(RawInputListener listener) { public void setInputListener(RawInputListener listener) {

@ -68,8 +68,6 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
private static final Logger logger = Logger.getLogger(AwtMouseInput.class.getName()); private static final Logger logger = Logger.getLogger(AwtMouseInput.class.getName());
private boolean inited = false;
private boolean visible = true; private boolean visible = true;
private RawInputListener listener; private RawInputListener listener;
@ -92,8 +90,7 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
private boolean isRecentering; private boolean isRecentering;
private int eventsSinceRecenter; private int eventsSinceRecenter;
public AwtMouseInput(Component comp) { public AwtMouseInput() {
this.component = comp;
location = new Point(); location = new Point();
centerLocation = new Point(); centerLocation = new Point();
centerLocationOnScreen = new Point(); centerLocationOnScreen = new Point();
@ -106,27 +103,38 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
} }
} }
public void initialize() { public void setInputSource(Component comp){
inited = true; if (component != null){
component.removeMouseListener(this);
component.removeMouseMotionListener(this);
component.removeMouseWheelListener(this);
wheelPos = 0;
isRecentering = false;
eventsSinceRecenter = 0;
lastEventX = 0;
lastEventY = 0;
lastEventWheel = 0;
location = new Point();
centerLocation = new Point();
centerLocationOnScreen = new Point();
lastKnownLocation = new Point();
}
component = comp;
component.addMouseListener(this); component.addMouseListener(this);
component.addMouseMotionListener(this); component.addMouseMotionListener(this);
component.addMouseWheelListener(this); component.addMouseWheelListener(this);
}
logger.info("Mouse input initialized."); public void initialize() {
} }
public void destroy() { public void destroy() {
inited = false;
robot = null;
component.removeMouseListener(this);
component.removeMouseMotionListener(this);
component.removeMouseWheelListener(this);
logger.info("Mouse input destroyed.");
} }
public boolean isInitialized() { public boolean isInitialized() {
return inited; return true;
} }
public void setInputListener(RawInputListener listener){ public void setInputListener(RawInputListener listener){
@ -139,10 +147,16 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
public void setCursorVisible(boolean visible){ public void setCursorVisible(boolean visible){
if (this.visible != visible){ if (this.visible != visible){
component.setCursor(visible ? null : getTransparentCursor());
this.visible = visible; this.visible = visible;
if (!visible) final boolean newVisible = visible;
recenterMouse(component); SwingUtilities.invokeLater(new Runnable() {
public void run() {
component.setCursor(newVisible ? null : getTransparentCursor());
if (!newVisible)
recenterMouse(component);
}
});
} }
} }

@ -0,0 +1,218 @@
package com.jme3.system.awt;
import com.jme3.post.SceneProcessor;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image.Format;
import com.jme3.util.BufferUtils;
import com.jme3.util.Screenshots;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
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 {
private BufferedImage img;
private FrameBuffer fb;
private ByteBuffer byteBuf;
private boolean activeUpdates = true;
private RenderManager rm;
private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
// 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 AtomicBoolean reshapeNeeded = new AtomicBoolean(false);
public AwtPanel(boolean activeUpdates){
this.activeUpdates = activeUpdates;
setIgnoreRepaint(true);
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();
}
}
});
}
@Override
public void addNotify(){
super.addNotify();
try {
createBufferStrategy(2);
strategy = getBufferStrategy();
visible.set(true);
visibleBarrier.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (BrokenBarrierException ex) {
ex.printStackTrace();
}
requestFocusInWindow();
}
@Override
public void removeNotify(){
try {
visible.set(false);
visibleBarrier.await();
strategy = null;
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (BrokenBarrierException ex) {
ex.printStackTrace();
}
super.removeNotify();
}
private void checkVisibility(){
if (visible.get() != glVisible){
try {
glVisible = visible.get();
visibleBarrier.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (BrokenBarrierException ex) {
ex.printStackTrace();
}
}
}
public void drawFrame(){
checkVisibility();
if (!glVisible)
return;
if (strategy.contentsLost()){
strategy.dispose();
createBufferStrategy(2);
strategy = getBufferStrategy();
System.out.println("BufferStrategy lost!");
}
Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
g2d.drawImage(img, transformOp, 0, 0);
g2d.dispose();
strategy.show();
}
public boolean isActiveUpdates() {
return activeUpdates;
}
public void setActiveUpdates(boolean activeUpdates) {
this.activeUpdates = activeUpdates;
}
public void attachTo(ViewPort ... vps){
if (viewPorts.size() > 0){
for (ViewPort vp : viewPorts){
vp.setOutputFrameBuffer(null);
}
viewPorts.get(viewPorts.size()-1).removeProcessor(this);
}
viewPorts.addAll(Arrays.asList(vps));
viewPorts.get(viewPorts.size()-1).addProcessor(this);
}
public void initialize(RenderManager rm, ViewPort vp) {
if (this.rm == null){
// First time called in OGL thread
this.rm = rm;
reshapeInThread(1, 1);
}
}
private void reshapeInThread(int width, int height) {
byteBuf = BufferUtils.ensureLargeEnough(byteBuf, width * height * 4);
fb = new FrameBuffer(width, height, 1);
fb.setDepthBuffer(Format.Depth);
fb.setColorBuffer(Format.RGB8);
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -img.getHeight());
transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
for (ViewPort vp : viewPorts){
vp.setOutputFrameBuffer(fb);
vp.getCamera().resize(width, height, true);
}
}
public boolean isInitialized() {
return fb != null;
}
public void preFrame(float tpf) {
}
public void postQueue(RenderQueue rq) {
}
public void postFrame(FrameBuffer out) {
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();
}
}
public void reshape(ViewPort vp, int w, int h) {
}
public void cleanup() {
}
}

@ -0,0 +1,176 @@
package com.jme3.system.awt;
import com.jme3.input.JoyInput;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.TouchInput;
import com.jme3.input.awt.AwtKeyInput;
import com.jme3.input.awt.AwtMouseInput;
import com.jme3.renderer.Renderer;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeSystem;
import com.jme3.system.SystemListener;
import com.jme3.system.Timer;
import java.util.ArrayList;
public class AwtPanelsContext implements JmeContext {
protected JmeContext actualContext;
protected AppSettings settings = new AppSettings(true);
protected SystemListener listener;
protected ArrayList<AwtPanel> panels = new ArrayList<AwtPanel>();
protected AwtPanel inputSource;
protected AwtMouseInput mouseInput = new AwtMouseInput();
protected AwtKeyInput keyInput = new AwtKeyInput();
private class AwtPanelsListener implements SystemListener {
public void initialize() {
initInThread();
}
public void reshape(int width, int height) {
throw new IllegalStateException();
}
public void update() {
updateInThread();
}
public void requestClose(boolean esc) {
// shouldn't happen
throw new IllegalStateException();
}
public void gainFocus() {
// shouldn't happen
throw new IllegalStateException();
}
public void loseFocus() {
// shouldn't happen
throw new IllegalStateException();
}
public void handleError(String errorMsg, Throwable t) {
listener.handleError(errorMsg, t);
}
public void destroy() {
destroyInThread();
}
}
public void setInputSource(AwtPanel panel){
if (!panels.contains(panel))
throw new IllegalArgumentException();
inputSource = panel;
mouseInput.setInputSource(panel);
keyInput.setInputSource(panel);
}
public Type getType() {
return Type.OffscreenSurface;
}
public void setSystemListener(SystemListener listener) {
this.listener = listener;
}
public AppSettings getSettings() {
return settings;
}
public Renderer getRenderer() {
return actualContext.getRenderer();
}
public MouseInput getMouseInput() {
return mouseInput;
}
public KeyInput getKeyInput() {
return keyInput;
}
public JoyInput getJoyInput() {
return null;
}
public TouchInput getTouchInput() {
return null;
}
public Timer getTimer() {
return actualContext.getTimer();
}
public boolean isCreated() {
return actualContext != null && actualContext.isCreated();
}
public boolean isRenderable() {
return actualContext != null && actualContext.isRenderable();
}
public AwtPanelsContext(){
}
public AwtPanel createPanel(boolean activeUpdates){
AwtPanel panel = new AwtPanel(activeUpdates);
panels.add(panel);
return panel;
}
private void initInThread(){
listener.initialize();
}
private void updateInThread(){
listener.update();
}
private void destroyInThread(){
listener.destroy();
}
public void setSettings(AppSettings settings) {
settings.copyFrom(settings);
if (actualContext != null){
actualContext.setSettings(settings);
}
}
public void create(boolean waitFor) {
if (actualContext != null)
throw new IllegalStateException("Already created");
actualContext = JmeSystem.newContext(settings, Type.OffscreenSurface);
actualContext.setSystemListener(new AwtPanelsListener());
actualContext.create(waitFor);
}
public void destroy(boolean waitFor) {
if (actualContext == null)
throw new IllegalStateException("Not created");
// destroy parent context
actualContext.destroy(waitFor);
}
public void setTitle(String title) {
// not relevant, ignore
}
public void setAutoFlushFrames(boolean enabled) {
// not relevant, ignore
}
public void restart() {
// only relevant if changing pixel format.
}
}

@ -2,10 +2,36 @@ package com.jme3.util;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte; import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.WritableRaster; import java.awt.image.WritableRaster;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
public final class Screenshots { public final class Screenshots {
public static void convertScreenShot2(ByteBuffer bgraBuf, BufferedImage out){
WritableRaster wr = out.getRaster();
DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
int[] cpuArray = db.getData();
bgraBuf.clear();
bgraBuf.asIntBuffer().get(cpuArray);
// int width = wr.getWidth();
// int height = wr.getHeight();
//
// // flip the components the way AWT likes them
// for (int y = 0; y < height / 2; y++){
// for (int x = 0; x < width; x++){
// int inPtr = (y * width + x);
// int outPtr = ((height-y-1) * width + x);
// int pixel = cpuArray[inPtr];
// cpuArray[inPtr] = cpuArray[outPtr];
// cpuArray[outPtr] = pixel;
// }
// }
}
public static void convertScreenShot(ByteBuffer bgraBuf, BufferedImage out){ public static void convertScreenShot(ByteBuffer bgraBuf, BufferedImage out){
WritableRaster wr = out.getRaster(); WritableRaster wr = out.getRaster();
DataBufferByte db = (DataBufferByte) wr.getDataBuffer(); DataBufferByte db = (DataBufferByte) wr.getDataBuffer();

@ -0,0 +1,86 @@
package jme3test.awt;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.system.awt.AwtPanel;
import com.jme3.system.awt.AwtPanelsContext;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class TestAwtPanels extends SimpleApplication {
private static TestAwtPanels app;
private static AwtPanel panel, panel2;
private static int panelsClosed = 0;
private static void createWindowForPanel(AwtPanel panel, int location){
JFrame frame = new JFrame("Render Display " + location);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
if (++panelsClosed == 2){
app.stop();
}
}
});
frame.pack();
frame.setLocation(location, Toolkit.getDefaultToolkit().getScreenSize().height - 400);
frame.setVisible(true);
}
public static void main(String[] args){
Logger.getLogger("com.jme3").setLevel(Level.WARNING);
app = new TestAwtPanels();
app.setShowSettings(false);
AppSettings settings = new AppSettings(true);
settings.setCustomRenderer(AwtPanelsContext.class);
app.setSettings(settings);
app.start();
SwingUtilities.invokeLater(new Runnable(){
public void run(){
final AwtPanelsContext ctx = (AwtPanelsContext) app.getContext();
panel = ctx.createPanel(true);
panel.setPreferredSize(new Dimension(400, 300));
ctx.setInputSource(panel);
panel2 = ctx.createPanel(true);
panel2.setPreferredSize(new Dimension(400, 300));
createWindowForPanel(panel, 300);
createWindowForPanel(panel2, 700);
}
});
}
@Override
public void simpleInitApp() {
flyCam.setDragToRotate(true);
Box b = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
geom.setMaterial(mat);
rootNode.attachChild(geom);
panel.attachTo(viewPort);
guiViewPort.setClearFlags(true, true, true);
panel2.attachTo(guiViewPort);
}
}

@ -11,30 +11,22 @@ import com.jme3.input.controls.ActionListener;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box; import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.input.controls.KeyTrigger; import com.jme3.input.controls.KeyTrigger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random; import java.util.Random;
import com.jme3.light.DirectionalLight;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.post.FilterPostProcessor; import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter; import com.jme3.post.filters.BloomFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.scene.BatchedGeometry; import com.jme3.scene.BatchedGeometry;
import com.jme3.scene.GeometryBatch; import com.jme3.scene.GeometryBatch;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.scene.debug.Arrow; import com.jme3.scene.debug.Arrow;
import java.util.List; import java.util.List;
import jme3test.post.SSAOUI;
public class TestCubeCluster extends SimpleApplication { public class TestCubeCluster extends SimpleApplication {

Loading…
Cancel
Save