git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8323 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
5d5e0082a7
commit
a28d0d8baf
@ -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.
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue