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