1 package com.jme3.system.awt;
3 import com.jme3.post.SceneProcessor;
4 import com.jme3.renderer.RenderManager;
5 import com.jme3.renderer.ViewPort;
6 import com.jme3.renderer.queue.RenderQueue;
7 import com.jme3.texture.FrameBuffer;
8 import com.jme3.texture.Image.Format;
9 import com.jme3.util.BufferUtils;
10 import com.jme3.util.Screenshots;
11 import java.awt.AWTException;
12 import java.awt.BufferCapabilities;
13 import java.awt.Canvas;
14 import java.awt.Graphics;
15 import java.awt.Graphics2D;
16 import java.awt.ImageCapabilities;
17 import java.awt.RenderingHints;
18 import java.awt.event.ComponentAdapter;
19 import java.awt.event.ComponentEvent;
20 import java.awt.geom.AffineTransform;
21 import java.awt.image.AffineTransformOp;
22 import java.awt.image.BufferStrategy;
23 import java.awt.image.BufferedImage;
24 import java.nio.ByteBuffer;
25 import java.nio.IntBuffer;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.concurrent.atomic.AtomicBoolean;
30 public class AwtPanel extends Canvas implements SceneProcessor {
32 private boolean attachAsMain = false;
34 private BufferedImage img;
35 private FrameBuffer fb;
36 private ByteBuffer byteBuf;
37 private IntBuffer intBuf;
38 private RenderManager rm;
39 private PaintMode paintMode;
40 private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
42 // Visibility/drawing vars
43 private BufferStrategy strategy;
44 private AffineTransformOp transformOp;
45 private AtomicBoolean hasNativePeer = new AtomicBoolean(false);
46 private AtomicBoolean showing = new AtomicBoolean(false);
47 private AtomicBoolean repaintRequest = new AtomicBoolean(false);
50 private int newWidth = 1;
51 private int newHeight = 1;
52 private AtomicBoolean reshapeNeeded = new AtomicBoolean(false);
53 private final Object lock = new Object();
55 public AwtPanel(PaintMode paintMode){
56 this.paintMode = paintMode;
58 if (paintMode == PaintMode.Accelerated){
59 setIgnoreRepaint(true);
62 addComponentListener(new ComponentAdapter(){
64 public void componentResized(ComponentEvent e) {
66 int newWidth2 = Math.max(getWidth(), 1);
67 int newHeight2 = Math.max(getHeight(), 1);
68 if (newWidth != newWidth2 || newHeight != newHeight2){
70 newHeight = newHeight2;
71 reshapeNeeded.set(true);
72 System.out.println("EDT: componentResized " + newWidth + ", " + newHeight);
80 public void addNotify(){
84 hasNativePeer.set(true);
85 System.out.println("EDT: addNotify");
88 requestFocusInWindow();
92 public void removeNotify(){
94 hasNativePeer.set(false);
95 System.out.println("EDT: removeNotify");
102 public void paint(Graphics g){
103 Graphics2D g2d = (Graphics2D) g;
105 g2d.drawImage(img, transformOp, 0, 0);
109 public boolean checkVisibilityState(){
110 if (!hasNativePeer.get()){
111 if (strategy != null){
114 System.out.println("OGL: Not visible. Destroy strategy.");
119 boolean currentShowing = isShowing();
120 if (showing.getAndSet(currentShowing) != currentShowing){
122 System.out.println("OGL: Enter showing state.");
124 System.out.println("OGL: Exit showing state.");
127 return currentShowing;
130 public void repaintInThread(){
131 // Convert screenshot.
133 rm.getRenderer().readFrameBuffer(fb, byteBuf);
136 // All operations on img must be synchronized
137 // as it is accessed from EDT.
138 Screenshots.convertScreenShot2(intBuf, img);
143 public void drawFrameInThread(){
144 // Convert screenshot.
146 rm.getRenderer().readFrameBuffer(fb, byteBuf);
147 Screenshots.convertScreenShot2(intBuf, img);
150 // All operations on strategy should be synchronized (?)
151 if (strategy == null){
153 createBufferStrategy(1,
154 new BufferCapabilities(
155 new ImageCapabilities(true),
156 new ImageCapabilities(true),
157 BufferCapabilities.FlipContents.UNDEFINED)
159 } catch (AWTException ex) {
160 ex.printStackTrace();
162 strategy = getBufferStrategy();
163 System.out.println("OGL: Visible. Create strategy.");
169 Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
171 System.out.println("OGL: DrawGraphics was null.");
175 g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
176 RenderingHints.VALUE_RENDER_SPEED);
178 g2d.drawImage(img, transformOp, 0, 0);
181 } while (strategy.contentsRestored());
182 } while (strategy.contentsLost());
186 public boolean isActiveDrawing(){
187 return paintMode != PaintMode.OnRequest && showing.get();
190 public void attachTo(boolean overrideMainFramebuffer, ViewPort ... vps){
191 if (viewPorts.size() > 0){
192 for (ViewPort vp : viewPorts){
193 vp.setOutputFrameBuffer(null);
195 viewPorts.get(viewPorts.size()-1).removeProcessor(this);
198 viewPorts.addAll(Arrays.asList(vps));
199 viewPorts.get(viewPorts.size()-1).addProcessor(this);
201 this.attachAsMain = overrideMainFramebuffer;
204 public void initialize(RenderManager rm, ViewPort vp) {
205 if (this.rm == null){
206 // First time called in OGL thread
208 reshapeInThread(1, 1);
212 private void reshapeInThread(int width, int height) {
213 byteBuf = BufferUtils.ensureLargeEnough(byteBuf, width * height * 4);
214 intBuf = byteBuf.asIntBuffer();
216 fb = new FrameBuffer(width, height, 1);
217 fb.setDepthBuffer(Format.Depth);
218 fb.setColorBuffer(Format.RGB8);
221 rm.getRenderer().setMainFrameBufferOverride(fb);
225 img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
228 // synchronized (lock){
229 // img = (BufferedImage) getGraphicsConfiguration().createCompatibleImage(width, height);
232 AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
233 tx.translate(0, -img.getHeight());
234 transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
236 for (ViewPort vp : viewPorts){
238 vp.setOutputFrameBuffer(fb);
240 vp.getCamera().resize(width, height, true);
242 // NOTE: Hack alert. This is done ONLY for custom framebuffers.
243 // Main framebuffer should use RenderManager.notifyReshape().
244 for (SceneProcessor sp : vp.getProcessors()){
245 sp.reshape(vp, width, height);
250 public boolean isInitialized() {
254 public void preFrame(float tpf) {
257 public void postQueue(RenderQueue rq) {
261 public void invalidate(){
262 // For "PaintMode.OnDemand" only.
263 repaintRequest.set(true);
266 public void postFrame(FrameBuffer out) {
267 if (!attachAsMain && out != fb){
268 throw new IllegalStateException("Why did you change the output framebuffer?");
271 if (reshapeNeeded.getAndSet(false)){
272 reshapeInThread(newWidth, newHeight);
274 if (!checkVisibilityState()){
286 if (repaintRequest.getAndSet(false)){
294 public void reshape(ViewPort vp, int w, int h) {
297 public void cleanup() {