* Ogre3D mesh.xml loader is now more resilient to certain models exported using blender2ogre
* Ogre3D dotScene loader can now load spot lights * Added some better debugging to FBO errors * Fix weird explosion in TestWalkingChar * Added additional "canvas torture methods" in TestCanvas * Several fixes to canvas: - Issue when size becomes 0, 0 - Freeze if no framerate limit is imposed and canvas is closed git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8210 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
120a3d1e4f
commit
6d728615a3
@ -102,12 +102,11 @@ public final class SAXUtil {
|
||||
public static boolean parseBool(String bool, boolean def) throws SAXException{
|
||||
if (bool == null || bool.equals(""))
|
||||
return def;
|
||||
else if (bool.equals("false"))
|
||||
return false;
|
||||
else if (bool.equals("true"))
|
||||
return true;
|
||||
else
|
||||
throw new SAXException("Expected a boolean, got'"+bool+"'");
|
||||
return Boolean.valueOf(bool);
|
||||
//else
|
||||
//else
|
||||
// throw new SAXException("Expected a boolean, got'"+bool+"'");
|
||||
}
|
||||
|
||||
public static String parseString(String str, String def){
|
||||
|
@ -90,6 +90,7 @@ import jme3tools.converters.MipMapGenerator;
|
||||
import org.lwjgl.opengl.ARBDrawBuffers;
|
||||
//import org.lwjgl.opengl.ARBDrawInstanced;
|
||||
import org.lwjgl.opengl.ARBDrawInstanced;
|
||||
import org.lwjgl.opengl.ARBFramebufferObject;
|
||||
import org.lwjgl.opengl.ARBMultisample;
|
||||
import org.lwjgl.opengl.ContextCapabilities;
|
||||
import org.lwjgl.opengl.EXTTextureArray;
|
||||
@ -427,14 +428,17 @@ public class LwjglRenderer implements Renderer {
|
||||
}
|
||||
|
||||
public void resetGLObjects() {
|
||||
logger.log(Level.INFO, "Reseting objects and invalidating state");
|
||||
objManager.resetObjects();
|
||||
statistics.clearMemory();
|
||||
invalidateState();
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
logger.log(Level.INFO, "Deleting objects and invalidating state");
|
||||
objManager.deleteAllObjects(this);
|
||||
statistics.clearMemory();
|
||||
invalidateState();
|
||||
}
|
||||
|
||||
private void checkCap(Caps cap) {
|
||||
@ -537,8 +541,8 @@ public class LwjglRenderer implements Renderer {
|
||||
|
||||
if (state.isPointSprite() && !context.pointSprite) {
|
||||
// Only enable/disable sprite
|
||||
if (context.boundTextures[0] != null) {
|
||||
if (context.boundTextureUnit != 0) {
|
||||
if (context.boundTextures[0] != null){
|
||||
if (context.boundTextureUnit != 0){
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
context.boundTextureUnit = 0;
|
||||
}
|
||||
@ -547,8 +551,8 @@ public class LwjglRenderer implements Renderer {
|
||||
}
|
||||
context.pointSprite = true;
|
||||
} else if (!state.isPointSprite() && context.pointSprite) {
|
||||
if (context.boundTextures[0] != null) {
|
||||
if (context.boundTextureUnit != 0) {
|
||||
if (context.boundTextures[0] != null){
|
||||
if (context.boundTextureUnit != 0){
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
context.boundTextureUnit = 0;
|
||||
}
|
||||
@ -960,7 +964,7 @@ public class LwjglRenderer implements Renderer {
|
||||
}
|
||||
|
||||
source.setId(id);
|
||||
} else {
|
||||
}else{
|
||||
throw new RendererException("Cannot recompile shader source");
|
||||
}
|
||||
|
||||
@ -1278,6 +1282,85 @@ public class LwjglRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
private String getTargetBufferName(int buffer){
|
||||
switch (buffer){
|
||||
case GL_NONE: return "NONE";
|
||||
case GL_FRONT: return "GL_FRONT";
|
||||
case GL_BACK: return "GL_BACK";
|
||||
default:
|
||||
if ( buffer >= GL_COLOR_ATTACHMENT0_EXT
|
||||
&& buffer <= GL_COLOR_ATTACHMENT15_EXT){
|
||||
return "GL_COLOR_ATTACHMENT" +
|
||||
(buffer - GL_COLOR_ATTACHMENT0_EXT);
|
||||
}else{
|
||||
return "UNKNOWN? " + buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name){
|
||||
System.out.println("== Renderbuffer " + name + " ==");
|
||||
System.out.println("RB ID: " + rb.getId());
|
||||
System.out.println("Is proper? " + glIsRenderbufferEXT(rb.getId()));
|
||||
|
||||
int attachment = convertAttachmentSlot(rb.getSlot());
|
||||
|
||||
int type = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT,
|
||||
attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT);
|
||||
|
||||
int rbName = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT,
|
||||
attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT);
|
||||
|
||||
switch (type){
|
||||
case GL_NONE:
|
||||
System.out.println("Type: None");
|
||||
return; // note: return from method as other queries will be invalid
|
||||
case GL_TEXTURE:
|
||||
System.out.println("Type: Texture");
|
||||
break;
|
||||
case GL_RENDERBUFFER_EXT:
|
||||
System.out.println("Type: Buffer");
|
||||
System.out.println("RB ID: " + rbName);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void printRealFrameBufferInfo(FrameBuffer fb) {
|
||||
boolean doubleBuffer = glGetBoolean(GL_DOUBLEBUFFER);
|
||||
String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER));
|
||||
String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
|
||||
|
||||
int fbId = fb.getId();
|
||||
int curDrawBinding = glGetInteger(ARBFramebufferObject.GL_DRAW_FRAMEBUFFER_BINDING);
|
||||
int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING);
|
||||
|
||||
System.out.println("=== OpenGL FBO State ===");
|
||||
System.out.println("Context doublebuffered? " + doubleBuffer);
|
||||
System.out.println("FBO ID: " + fbId);
|
||||
System.out.println("Is proper? " + glIsFramebufferEXT(fbId));
|
||||
System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
|
||||
System.out.println("Is bound to read? " + (fbId == curReadBinding));
|
||||
System.out.println("Draw buffer: " + drawBuf);
|
||||
System.out.println("Read buffer: " + readBuf);
|
||||
|
||||
if (context.boundFBO != fbId){
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbId);
|
||||
context.boundFBO = fbId;
|
||||
}
|
||||
|
||||
if (fb.getDepthBuffer() != null){
|
||||
printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
|
||||
}
|
||||
for (int i = 0; i < fb.getNumColorBuffers(); i++){
|
||||
printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFrameBufferError() {
|
||||
int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch (status) {
|
||||
@ -1290,7 +1373,7 @@ public class LwjglRenderer implements Renderer {
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
throw new IllegalStateException("Framebuffer has erronous attachment.");
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
throw new IllegalStateException("Framebuffer is missing required attachment.");
|
||||
throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached.");
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
@ -1487,6 +1570,11 @@ public class LwjglRenderer implements Renderer {
|
||||
|
||||
lastFb = null;
|
||||
} else {
|
||||
if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null){
|
||||
throw new IllegalArgumentException("The framebuffer: " + fb +
|
||||
"\nDoesn't have any color/depth buffers");
|
||||
}
|
||||
|
||||
if (fb.isUpdateNeeded()) {
|
||||
updateFrameBuffer(fb);
|
||||
}
|
||||
@ -1544,13 +1632,14 @@ public class LwjglRenderer implements Renderer {
|
||||
assert fb.getId() >= 0;
|
||||
assert context.boundFBO == fb.getId();
|
||||
lastFb = fb;
|
||||
}
|
||||
|
||||
try {
|
||||
checkFrameBufferError();
|
||||
} catch (IllegalStateException ex) {
|
||||
logger.log(Level.SEVERE, "Problem FBO:\n{0}", fb);
|
||||
throw ex;
|
||||
}
|
||||
try {
|
||||
checkFrameBufferError();
|
||||
} catch (IllegalStateException ex) {
|
||||
logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
|
||||
printRealFrameBufferInfo(fb);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1964,7 +2053,7 @@ public class LwjglRenderer implements Renderer {
|
||||
glBindBuffer(target, bufId);
|
||||
context.boundElementArrayVBO = bufId;
|
||||
//statistics.onVertexBufferUse(vb, true);
|
||||
} else {
|
||||
}else{
|
||||
//statistics.onVertexBufferUse(vb, false);
|
||||
}
|
||||
} else {
|
||||
@ -1973,7 +2062,7 @@ public class LwjglRenderer implements Renderer {
|
||||
glBindBuffer(target, bufId);
|
||||
context.boundArrayVBO = bufId;
|
||||
//statistics.onVertexBufferUse(vb, true);
|
||||
} else {
|
||||
}else{
|
||||
//statistics.onVertexBufferUse(vb, false);
|
||||
}
|
||||
}
|
||||
@ -2142,7 +2231,7 @@ public class LwjglRenderer implements Renderer {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bufId);
|
||||
context.boundArrayVBO = bufId;
|
||||
//statistics.onVertexBufferUse(vb, true);
|
||||
} else {
|
||||
}else{
|
||||
//statistics.onVertexBufferUse(vb, false);
|
||||
}
|
||||
|
||||
@ -2189,7 +2278,7 @@ public class LwjglRenderer implements Renderer {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufId);
|
||||
context.boundElementArrayVBO = bufId;
|
||||
//statistics.onVertexBufferUse(indexBuf, true);
|
||||
} else {
|
||||
}else{
|
||||
//statistics.onVertexBufferUse(indexBuf, true);
|
||||
}
|
||||
|
||||
@ -2314,9 +2403,9 @@ public class LwjglRenderer implements Renderer {
|
||||
}
|
||||
|
||||
private void renderMeshVertexArray(Mesh mesh, int lod, int count) {
|
||||
if (mesh.getId() == -1) {
|
||||
if (mesh.getId() == -1){
|
||||
updateVertexArray(mesh);
|
||||
} else {
|
||||
}else{
|
||||
// TODO: Check if it was updated
|
||||
}
|
||||
|
||||
@ -2359,7 +2448,7 @@ public class LwjglRenderer implements Renderer {
|
||||
}
|
||||
//for (Entry<VertexBuffer> entry : buffers) {
|
||||
// VertexBuffer vb = entry.getValue();
|
||||
for (int i = 0; i < buffersList.size(); i++) {
|
||||
for (int i = 0; i < buffersList.size(); i++){
|
||||
VertexBuffer vb = buffersList.get(i);
|
||||
|
||||
if (vb.getBufferType() == Type.InterleavedData
|
||||
@ -2391,10 +2480,10 @@ public class LwjglRenderer implements Renderer {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.pointSprite && mesh.getMode() != Mode.Points) {
|
||||
if (context.pointSprite && mesh.getMode() != Mode.Points){
|
||||
// XXX: Hack, disable point sprite mode if mesh not in point mode
|
||||
if (context.boundTextures[0] != null) {
|
||||
if (context.boundTextureUnit != 0) {
|
||||
if (context.boundTextures[0] != null){
|
||||
if (context.boundTextureUnit != 0){
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
context.boundTextureUnit = 0;
|
||||
}
|
||||
@ -2417,7 +2506,7 @@ public class LwjglRenderer implements Renderer {
|
||||
// if (GLContext.getCapabilities().GL_ARB_vertex_array_object){
|
||||
// renderMeshVertexArray(mesh, lod, count);
|
||||
// }else{
|
||||
renderMeshDefault(mesh, lod, count);
|
||||
renderMeshDefault(mesh, lod, count);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -38,13 +38,11 @@ import com.jme3.system.JmeContext.Type;
|
||||
import com.jme3.system.JmeSystem;
|
||||
import com.jme3.system.JmeSystem.Platform;
|
||||
import java.awt.Canvas;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
@ -53,14 +51,23 @@ import org.lwjgl.opengl.PixelFormat;
|
||||
|
||||
public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContext {
|
||||
|
||||
protected static final int TASK_NOTHING = 0,
|
||||
TASK_DESTROY_DISPLAY = 1,
|
||||
TASK_CREATE_DISPLAY = 2,
|
||||
TASK_COMPLETE = 3;
|
||||
|
||||
// protected static final boolean USE_SHARED_CONTEXT =
|
||||
// Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true"));
|
||||
|
||||
protected static final boolean USE_SHARED_CONTEXT = false;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(LwjglDisplay.class.getName());
|
||||
private Canvas canvas;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
private final AtomicBoolean needRestoreCanvas = new AtomicBoolean(false);
|
||||
private final AtomicBoolean needDestroyCanvas = new AtomicBoolean(false);
|
||||
private final CyclicBarrier actionRequiredBarrier = new CyclicBarrier(2);
|
||||
private final Object taskLock = new Object();
|
||||
private int desiredTask = TASK_NOTHING;
|
||||
|
||||
private Thread renderThread;
|
||||
private boolean runningFirstTime = true;
|
||||
@ -95,11 +102,19 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, "EDT: Notifying OGL that canvas is visible..");
|
||||
needRestoreCanvas.set(true);
|
||||
|
||||
// NOTE: no need to wait for OGL to initialize the canvas,
|
||||
// it can happen at any time.
|
||||
logger.log(Level.INFO, "EDT: Telling OGL to create display ..");
|
||||
synchronized (taskLock){
|
||||
desiredTask = TASK_CREATE_DISPLAY;
|
||||
// while (desiredTask != TASK_COMPLETE){
|
||||
// try {
|
||||
// taskLock.wait();
|
||||
// } catch (InterruptedException ex) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// desiredTask = TASK_NOTHING;
|
||||
}
|
||||
// logger.log(Level.INFO, "EDT: OGL has created the display");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -112,19 +127,20 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
|
||||
// We must tell GL context to shutdown and wait for it to
|
||||
// shutdown, otherwise, issues will occur.
|
||||
logger.log(Level.INFO, "EDT: Notifying OGL that canvas is about to become invisible..");
|
||||
needDestroyCanvas.set(true);
|
||||
try {
|
||||
actionRequiredBarrier.await();
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, "EDT: Interrupted! ", ex);
|
||||
} catch (BrokenBarrierException ex){
|
||||
logger.log(Level.SEVERE, "EDT: Broken barrier! ", ex);
|
||||
logger.log(Level.INFO, "EDT: Telling OGL to destroy display ..");
|
||||
synchronized (taskLock){
|
||||
desiredTask = TASK_DESTROY_DISPLAY;
|
||||
while (desiredTask != TASK_COMPLETE){
|
||||
try {
|
||||
taskLock.wait();
|
||||
} catch (InterruptedException ex){
|
||||
super.removeNotify();
|
||||
return;
|
||||
}
|
||||
}
|
||||
desiredTask = TASK_NOTHING;
|
||||
}
|
||||
|
||||
// Reset barrier for future use
|
||||
actionRequiredBarrier.reset();
|
||||
|
||||
logger.log(Level.INFO, "EDT: Acknowledged receipt of canvas death");
|
||||
// GL context is dead at this point
|
||||
|
||||
@ -171,34 +187,42 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
|
||||
@Override
|
||||
protected void runLoop(){
|
||||
if (needDestroyCanvas.getAndSet(false)){
|
||||
// Destroy canvas
|
||||
logger.log(Level.INFO, "OGL: Received destroy request! Complying..");
|
||||
try {
|
||||
listener.loseFocus();
|
||||
pauseCanvas();
|
||||
} finally {
|
||||
try {
|
||||
// Required to avoid deadlock if an exception occurs
|
||||
actionRequiredBarrier.await();
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
|
||||
} catch (BrokenBarrierException ex) {
|
||||
logger.log(Level.SEVERE, "OGL: Broken barrier! ", ex);
|
||||
if (desiredTask != TASK_NOTHING){
|
||||
synchronized (taskLock){
|
||||
switch (desiredTask){
|
||||
case TASK_CREATE_DISPLAY:
|
||||
logger.log(Level.INFO, "OGL: Creating display ..");
|
||||
restoreCanvas();
|
||||
listener.gainFocus();
|
||||
desiredTask = TASK_NOTHING;
|
||||
break;
|
||||
case TASK_DESTROY_DISPLAY:
|
||||
logger.log(Level.INFO, "OGL: Destroying display ..");
|
||||
listener.loseFocus();
|
||||
pauseCanvas();
|
||||
break;
|
||||
}
|
||||
desiredTask = TASK_COMPLETE;
|
||||
taskLock.notifyAll();
|
||||
}
|
||||
}else if (needRestoreCanvas.getAndSet(false)){
|
||||
// Put canvas back online
|
||||
logger.log(Level.INFO, "OGL: Canvas is now visible! Re-initializing..");
|
||||
restoreCanvas();
|
||||
listener.gainFocus();
|
||||
}
|
||||
|
||||
if (width != canvas.getWidth() || height != canvas.getHeight()){
|
||||
width = canvas.getWidth();
|
||||
height = canvas.getHeight();
|
||||
if (listener != null)
|
||||
listener.reshape(width, height);
|
||||
if (renderable.get()){
|
||||
int newWidth = Math.max(canvas.getWidth(), 1);
|
||||
int newHeight = Math.max(canvas.getHeight(), 1);
|
||||
if (width != newWidth || height != newHeight){
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
if (listener != null){
|
||||
listener.reshape(width, height);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (frameRate <= 0){
|
||||
// NOTE: MUST be done otherwise
|
||||
// Windows OS will freeze
|
||||
Display.sync(30);
|
||||
}
|
||||
}
|
||||
|
||||
super.runLoop();
|
||||
@ -218,8 +242,6 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
Keyboard.destroy();
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, "OGL: Canvas will become invisible! Destroying ..");
|
||||
|
||||
renderable.set(false);
|
||||
destroyContext();
|
||||
}
|
||||
@ -237,7 +259,7 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
}
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, "OGL: Creating display..");
|
||||
logger.log(Level.INFO, "OGL: Creating display context ..");
|
||||
|
||||
// Set renderable to true, since canvas is now displayable.
|
||||
renderable.set(true);
|
||||
@ -306,7 +328,27 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
|
||||
if (pbuffer == null) {
|
||||
pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null);
|
||||
pbuffer.makeCurrent();
|
||||
logger.log(Level.INFO, "OGL: Pbuffer has been created");
|
||||
|
||||
// Any created objects are no longer valid
|
||||
if (!runningFirstTime){
|
||||
renderer.resetGLObjects();
|
||||
}
|
||||
}
|
||||
|
||||
pbuffer.makeCurrent();
|
||||
if (!pbuffer.isCurrent()){
|
||||
throw new LWJGLException("Pbuffer cannot be made current");
|
||||
}
|
||||
}
|
||||
|
||||
protected void destroyPbuffer(){
|
||||
if (pbuffer != null){
|
||||
if (!pbuffer.isBufferLost()){
|
||||
pbuffer.destroy();
|
||||
}
|
||||
pbuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,25 +359,9 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
*/
|
||||
protected void destroyContext(){
|
||||
try {
|
||||
// The canvas is no longer visible,
|
||||
// but the context thread is still running.
|
||||
if (!needClose.get()){
|
||||
// MUST make sure there's still a context current here ..
|
||||
// Display is dead, make pbuffer available to the system
|
||||
makePbufferAvailable();
|
||||
|
||||
// pbuffer is now available, make it current
|
||||
pbuffer.makeCurrent();
|
||||
|
||||
// invalidate the state so renderer can resume operation
|
||||
renderer.invalidateState();
|
||||
}else{
|
||||
// The context thread is no longer running.
|
||||
// Destroy pbuffer.
|
||||
if (pbuffer != null && !pbuffer.isBufferLost()){
|
||||
pbuffer.destroy();
|
||||
pbuffer = null;
|
||||
}
|
||||
// invalidate the state so renderer can resume operation
|
||||
if (!USE_SHARED_CONTEXT){
|
||||
renderer.cleanup();
|
||||
}
|
||||
|
||||
if (Display.isCreated()){
|
||||
@ -353,21 +379,35 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
Keyboard.destroy();
|
||||
}
|
||||
|
||||
try {
|
||||
//try {
|
||||
// NOTE: On Windows XP, not calling setParent(null)
|
||||
// freezes the application.
|
||||
// On Mac it freezes the application.
|
||||
// On Linux it fixes a crash with X Window System.
|
||||
if (JmeSystem.getPlatform() == Platform.Windows32
|
||||
|| JmeSystem.getPlatform() == Platform.Windows64){
|
||||
Display.setParent(null);
|
||||
//Display.setParent(null);
|
||||
}
|
||||
} catch (LWJGLException ex) {
|
||||
logger.log(Level.SEVERE, "Encountered exception when setting parent to null", ex);
|
||||
}
|
||||
//} catch (LWJGLException ex) {
|
||||
// logger.log(Level.SEVERE, "Encountered exception when setting parent to null", ex);
|
||||
//}
|
||||
|
||||
Display.destroy();
|
||||
}
|
||||
|
||||
// The canvas is no longer visible,
|
||||
// but the context thread is still running.
|
||||
if (!needClose.get()){
|
||||
// MUST make sure there's still a context current here ..
|
||||
// Display is dead, make pbuffer available to the system
|
||||
makePbufferAvailable();
|
||||
|
||||
renderer.invalidateState();
|
||||
}else{
|
||||
// The context thread is no longer running.
|
||||
// Destroy pbuffer.
|
||||
destroyPbuffer();
|
||||
}
|
||||
} catch (LWJGLException ex) {
|
||||
listener.handleError("Failed make pbuffer available", ex);
|
||||
}
|
||||
@ -385,28 +425,44 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
||||
frameRate = settings.getFrameRate();
|
||||
|
||||
try {
|
||||
// First create the pbuffer, if it is needed.
|
||||
makePbufferAvailable();
|
||||
|
||||
if (renderable.get()){
|
||||
if (!runningFirstTime){
|
||||
// because the display is a different opengl context
|
||||
// must reset the context state.
|
||||
if (!USE_SHARED_CONTEXT){
|
||||
renderer.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
// if the pbuffer is currently active,
|
||||
// make sure to deactivate it
|
||||
if (pbuffer.isCurrent()){
|
||||
pbuffer.releaseContext();
|
||||
destroyPbuffer();
|
||||
|
||||
if (Keyboard.isCreated()){
|
||||
Keyboard.destroy();
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
|
||||
Display.setVSyncEnabled(settings.isVSync());
|
||||
Display.setParent(canvas);
|
||||
Display.create(acquirePixelFormat(false), pbuffer);
|
||||
|
||||
// because the display is a different opengl context
|
||||
// must reset the context state.
|
||||
if (USE_SHARED_CONTEXT){
|
||||
Display.create(acquirePixelFormat(false), pbuffer);
|
||||
}else{
|
||||
Display.create(acquirePixelFormat(false));
|
||||
}
|
||||
|
||||
renderer.invalidateState();
|
||||
}else{
|
||||
pbuffer.makeCurrent();
|
||||
// First create the pbuffer, if it is needed.
|
||||
makePbufferAvailable();
|
||||
}
|
||||
// At this point, the OpenGL context is active.
|
||||
|
||||
// At this point, the OpenGL context is active.
|
||||
if (runningFirstTime){
|
||||
// THIS is the part that creates the renderer.
|
||||
// It must always be called, now that we have the pbuffer workaround.
|
||||
|
@ -41,6 +41,8 @@ import com.jme3.asset.AssetNotFoundException;
|
||||
import com.jme3.light.DirectionalLight;
|
||||
import com.jme3.light.Light;
|
||||
import com.jme3.light.PointLight;
|
||||
import com.jme3.light.SpotLight;
|
||||
import com.jme3.math.FastMath;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Node;
|
||||
@ -104,16 +106,22 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
light = null;
|
||||
}
|
||||
|
||||
private void checkTopNode(String topNode) throws SAXException{
|
||||
if (!elementStack.peek().equals(topNode)){
|
||||
throw new SAXException("dotScene parse error: Expected parent node to be " + topNode);
|
||||
}
|
||||
}
|
||||
|
||||
private Quaternion parseQuat(Attributes attribs) throws SAXException{
|
||||
if (attribs.getValue("x") != null){
|
||||
// defined as quaternion
|
||||
// qx, qy, qz, qw defined
|
||||
float x = parseFloat(attribs.getValue("x"));
|
||||
float y = parseFloat(attribs.getValue("y"));
|
||||
float z = parseFloat(attribs.getValue("z"));
|
||||
float w = parseFloat(attribs.getValue("w"));
|
||||
return new Quaternion(x,y,z,w);
|
||||
}else if (attribs.getValue("qx") != null){
|
||||
// defined as quaternion with prefix "q"
|
||||
float x = parseFloat(attribs.getValue("qx"));
|
||||
float y = parseFloat(attribs.getValue("qy"));
|
||||
float z = parseFloat(attribs.getValue("qz"));
|
||||
@ -129,6 +137,7 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
q.fromAngleAxis(angle, new Vector3f(axisX, axisY, axisZ));
|
||||
return q;
|
||||
}else{
|
||||
// defines as 3 angles along XYZ axes
|
||||
float angleX = parseFloat(attribs.getValue("angleX"));
|
||||
float angleY = parseFloat(attribs.getValue("angleY"));
|
||||
float angleZ = parseFloat(attribs.getValue("angleZ"));
|
||||
@ -139,19 +148,22 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
}
|
||||
|
||||
private void parseLightNormal(Attributes attribs) throws SAXException {
|
||||
assert elementStack.peek().equals("light");
|
||||
checkTopNode("light");
|
||||
|
||||
// SpotLight will be supporting a direction-normal, too.
|
||||
if (light instanceof DirectionalLight)
|
||||
((DirectionalLight) light).setDirection(parseVector3(attribs));
|
||||
else if (light instanceof SpotLight){
|
||||
((SpotLight) light).setDirection(parseVector3(attribs));
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLightAttenuation(Attributes attribs) throws SAXException {
|
||||
// NOTE: Only radius is supported atm ( for pointlights only, since there are no spotlights, yet).
|
||||
assert elementStack.peek().equals("light");
|
||||
// NOTE: Derives range based on "linear" if it is used solely
|
||||
// for the attenuation. Otherwise derives it from "range"
|
||||
checkTopNode("light");
|
||||
|
||||
// SpotLight will be supporting a direction-normal, too.
|
||||
if (light instanceof PointLight){
|
||||
if (light instanceof PointLight || light instanceof SpotLight){
|
||||
float range = parseFloat(attribs.getValue("range"));
|
||||
float constant = parseFloat(attribs.getValue("constant"));
|
||||
float linear = parseFloat(attribs.getValue("linear"));
|
||||
@ -165,15 +177,36 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
if (constant == 1 && quadratic == 0 && linear > 0){
|
||||
range = 1f / linear;
|
||||
}
|
||||
((PointLight) light).setRadius(range);
|
||||
|
||||
if (light instanceof PointLight){
|
||||
((PointLight) light).setRadius(range);
|
||||
}else{
|
||||
((SpotLight)light).setSpotRange(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLightSpotLightRange(Attributes attribs) throws SAXException{
|
||||
checkTopNode("light");
|
||||
|
||||
float outer = SAXUtil.parseFloat(attribs.getValue("outer"));
|
||||
float inner = SAXUtil.parseFloat(attribs.getValue("inner"));
|
||||
|
||||
if (!(light instanceof SpotLight)){
|
||||
throw new SAXException("dotScene parse error: spotLightRange "
|
||||
+ "can only appear under 'spot' light elements");
|
||||
}
|
||||
|
||||
SpotLight sl = (SpotLight) light;
|
||||
sl.setSpotInnerAngle(inner * 0.5f);
|
||||
sl.setSpotOuterAngle(outer * 0.5f);
|
||||
}
|
||||
|
||||
private void parseLight(Attributes attribs) throws SAXException {
|
||||
assert node != null;
|
||||
assert node.getParent() != null;
|
||||
assert elementStack.peek().equals("node");
|
||||
if (node == null || node.getParent() == null)
|
||||
throw new SAXException("dotScene parse error: light can only appear under a node");
|
||||
|
||||
checkTopNode("node");
|
||||
|
||||
String lightType = parseString(attribs.getValue("type"), "point");
|
||||
if(lightType.equals("point")) {
|
||||
@ -182,10 +215,8 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
light = new DirectionalLight();
|
||||
// Assuming "normal" property is not provided
|
||||
((DirectionalLight)light).setDirection(Vector3f.UNIT_Z);
|
||||
} else if(lightType.equals("spotLight")) {
|
||||
// TODO: SpotLight class.
|
||||
logger.warning("No SpotLight class atm, using Pointlight instead.");
|
||||
light = new PointLight();
|
||||
} else if(lightType.equals("spotLight") || lightType.equals("spot")) {
|
||||
light = new SpotLight();
|
||||
} else {
|
||||
logger.log(Level.WARNING, "No matching jME3 LightType found for OGRE LightType: {0}", lightType);
|
||||
}
|
||||
@ -203,14 +234,19 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attribs) throws SAXException{
|
||||
if (qName.equals("scene")){
|
||||
assert elementStack.size() == 0;
|
||||
if (elementStack.size() != 0){
|
||||
throw new SAXException("dotScene parse error: 'scene' element must be the root XML element");
|
||||
}
|
||||
|
||||
String version = attribs.getValue("formatVersion");
|
||||
if (version == null || !version.equals("1.0.0"))
|
||||
if (version == null && !version.equals("1.0.0") && !version.equals("1.0.1"))
|
||||
logger.log(Level.WARNING, "Unrecognized version number"
|
||||
+ " in dotScene file: {0}", version);
|
||||
|
||||
}else if (qName.equals("nodes")){
|
||||
assert root == null;
|
||||
if (root != null){
|
||||
throw new SAXException("dotScene parse error: nodes element was specified twice");
|
||||
}
|
||||
if (sceneName == null)
|
||||
root = new Node("OgreDotScene"+(++sceneIdx));
|
||||
else
|
||||
@ -218,22 +254,31 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
|
||||
node = root;
|
||||
}else if (qName.equals("externals")){
|
||||
assert elementStack.peek().equals("scene");
|
||||
|
||||
checkTopNode("scene");
|
||||
// Not loaded currently
|
||||
}else if (qName.equals("item")){
|
||||
assert elementStack.peek().equals("externals");
|
||||
checkTopNode("externals");
|
||||
}else if (qName.equals("file")){
|
||||
assert elementStack.peek().equals("item");
|
||||
String matFile = folderName+attribs.getValue("name");
|
||||
try {
|
||||
materialList = (MaterialList) assetManager.loadAsset(new OgreMaterialKey(matFile));
|
||||
} catch (AssetNotFoundException ex){
|
||||
materialList = null;
|
||||
logger.log(Level.WARNING, "Cannot locate material file: {0}", matFile);
|
||||
}
|
||||
checkTopNode("item");
|
||||
|
||||
// XXX: Currently material file name is based
|
||||
// on the scene's filename. THIS IS NOT CORRECT.
|
||||
// To solve, port SceneLoader to use DOM instead of SAX
|
||||
|
||||
//String matFile = folderName+attribs.getValue("name");
|
||||
//try {
|
||||
// materialList = (MaterialList) assetManager.loadAsset(new OgreMaterialKey(matFile));
|
||||
//} catch (AssetNotFoundException ex){
|
||||
// materialList = null;
|
||||
// logger.log(Level.WARNING, "Cannot locate material file: {0}", matFile);
|
||||
//}
|
||||
}else if (qName.equals("node")){
|
||||
String curElement = elementStack.peek();
|
||||
assert curElement.equals("nodes") || curElement.equals("node");
|
||||
if (!curElement.equals("node") && !curElement.equals("nodes")){
|
||||
throw new SAXException("dotScene parse error: "
|
||||
+ "node element can only appear under 'node' or 'nodes'");
|
||||
}
|
||||
|
||||
String name = attribs.getValue("name");
|
||||
if (name == null)
|
||||
name = "OgreNode-" + (++nodeIdx);
|
||||
@ -259,7 +304,8 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
}
|
||||
}
|
||||
}else if (qName.equals("entity")){
|
||||
assert elementStack.peek().equals("node");
|
||||
checkTopNode("node");
|
||||
|
||||
String name = attribs.getValue("name");
|
||||
if (name == null)
|
||||
name = "OgreEntity-" + (++nodeIdx);
|
||||
@ -267,32 +313,31 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
name += "-entity";
|
||||
|
||||
String meshFile = attribs.getValue("meshFile");
|
||||
if (meshFile == null)
|
||||
if (meshFile == null) {
|
||||
throw new SAXException("Required attribute 'meshFile' missing for 'entity' node");
|
||||
}
|
||||
|
||||
// TODO: Not currently used
|
||||
String materialName = attribs.getValue("materialName");
|
||||
|
||||
// NOTE: append "xml" since its assumed mesh filse are binary in dotScene
|
||||
if (folderName != null)
|
||||
if (folderName != null) {
|
||||
meshFile = folderName + meshFile;
|
||||
}
|
||||
|
||||
// NOTE: append "xml" since its assumed mesh files are binary in dotScene
|
||||
meshFile += ".xml";
|
||||
|
||||
entityNode = new Node(name);
|
||||
OgreMeshKey key = new OgreMeshKey(meshFile, materialList);
|
||||
Spatial ogreMesh =
|
||||
(Spatial) assetManager.loadAsset(key);
|
||||
//TODO:workaround for meshxml / mesh.xml
|
||||
if(ogreMesh==null){
|
||||
meshFile = folderName + attribs.getValue("meshFile") + "xml";
|
||||
key = new OgreMeshKey(meshFile, materialList);
|
||||
ogreMesh = (Spatial) assetManager.loadAsset(key);
|
||||
}
|
||||
Spatial ogreMesh = assetManager.loadModel(key);
|
||||
|
||||
entityNode.attachChild(ogreMesh);
|
||||
node.attachChild(entityNode);
|
||||
node = null;
|
||||
}else if (qName.equals("position")){
|
||||
node.setLocalTranslation(SAXUtil.parseVector3(attribs));
|
||||
if (elementStack.peek().equals("node")){
|
||||
node.setLocalTranslation(SAXUtil.parseVector3(attribs));
|
||||
}
|
||||
}else if (qName.equals("quaternion") || qName.equals("rotation")){
|
||||
node.setLocalRotation(parseQuat(attribs));
|
||||
}else if (qName.equals("scale")){
|
||||
@ -305,19 +350,22 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
light.setColor(parseColor(attribs));
|
||||
}
|
||||
}else{
|
||||
assert elementStack.peek().equals("environment");
|
||||
checkTopNode("environment");
|
||||
}
|
||||
} else if (qName.equals("normal")) {
|
||||
} else if (qName.equals("normal") || qName.equals("direction")) {
|
||||
checkTopNode("light");
|
||||
parseLightNormal(attribs);
|
||||
} else if (qName.equals("lightAttenuation")) {
|
||||
parseLightAttenuation(attribs);
|
||||
} else if (qName.equals("spotLightRange") || qName.equals("lightRange")) {
|
||||
parseLightSpotLightRange(attribs);
|
||||
}
|
||||
|
||||
elementStack.push(qName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
public void endElement(String uri, String name, String qName) throws SAXException {
|
||||
if (qName.equals("node")){
|
||||
node = node.getParent();
|
||||
}else if (qName.equals("nodes")){
|
||||
@ -339,11 +387,21 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
|
||||
PointLight pl = (PointLight) light;
|
||||
Vector3f pos = node.getWorldTranslation();
|
||||
pl.setPosition(pos);
|
||||
}else if (light instanceof SpotLight){
|
||||
SpotLight sl = (SpotLight) light;
|
||||
|
||||
Vector3f pos = node.getWorldTranslation();
|
||||
sl.setPosition(pos);
|
||||
|
||||
Quaternion q = node.getWorldRotation();
|
||||
Vector3f dir = sl.getDirection();
|
||||
q.multLocal(dir);
|
||||
sl.setDirection(dir);
|
||||
}
|
||||
}
|
||||
light = null;
|
||||
}
|
||||
assert elementStack.peek().equals(qName);
|
||||
checkTopNode(qName);
|
||||
elementStack.pop();
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ public class TestBareBonesApp extends Application {
|
||||
boxGeom.updateGeometricState();
|
||||
|
||||
// render the viewports
|
||||
renderManager.render(tpf, true);
|
||||
renderManager.render(tpf, context.isRenderable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,7 +88,7 @@ public class TestAppStates extends Application {
|
||||
stateManager.render(renderManager);
|
||||
|
||||
// render the viewports
|
||||
renderManager.render(tpf, true);
|
||||
renderManager.render(tpf, context.isRenderable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,7 +37,10 @@ import com.jme3.app.SimpleApplication;
|
||||
import com.jme3.system.AppSettings;
|
||||
import com.jme3.system.JmeCanvasContext;
|
||||
import com.jme3.util.JmeFormatter;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@ -50,8 +53,11 @@ import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
public class TestCanvas {
|
||||
|
||||
@ -59,7 +65,130 @@ public class TestCanvas {
|
||||
private static Canvas canvas;
|
||||
private static Application app;
|
||||
private static JFrame frame;
|
||||
private static final String appClass = "jme3test.post.TestMultiplesFilters";
|
||||
private static Container canvasPanel1, canvasPanel2;
|
||||
private static Container currentPanel;
|
||||
private static JTabbedPane tabbedPane;
|
||||
private static final String appClass = "jme3test.post.TestRenderToTexture";
|
||||
|
||||
private static void createTabs(){
|
||||
tabbedPane = new JTabbedPane();
|
||||
|
||||
canvasPanel1 = new JPanel();
|
||||
canvasPanel1.setLayout(new BorderLayout());
|
||||
tabbedPane.addTab("jME3 Canvas 1", canvasPanel1);
|
||||
|
||||
canvasPanel2 = new JPanel();
|
||||
canvasPanel2.setLayout(new BorderLayout());
|
||||
tabbedPane.addTab("jME3 Canvas 2", canvasPanel2);
|
||||
|
||||
frame.getContentPane().add(tabbedPane);
|
||||
|
||||
currentPanel = canvasPanel1;
|
||||
}
|
||||
|
||||
private static void createMenu(){
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
frame.setJMenuBar(menuBar);
|
||||
|
||||
JMenu menuTortureMethods = new JMenu("Canvas Torture Methods");
|
||||
menuBar.add(menuTortureMethods);
|
||||
|
||||
final JMenuItem itemRemoveCanvas = new JMenuItem("Remove Canvas");
|
||||
menuTortureMethods.add(itemRemoveCanvas);
|
||||
itemRemoveCanvas.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (itemRemoveCanvas.getText().equals("Remove Canvas")){
|
||||
currentPanel.remove(canvas);
|
||||
|
||||
itemRemoveCanvas.setText("Add Canvas");
|
||||
}else if (itemRemoveCanvas.getText().equals("Add Canvas")){
|
||||
currentPanel.add(canvas, BorderLayout.CENTER);
|
||||
|
||||
itemRemoveCanvas.setText("Remove Canvas");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final JMenuItem itemHideCanvas = new JMenuItem("Hide Canvas");
|
||||
menuTortureMethods.add(itemHideCanvas);
|
||||
itemHideCanvas.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (itemHideCanvas.getText().equals("Hide Canvas")){
|
||||
canvas.setVisible(false);
|
||||
itemHideCanvas.setText("Show Canvas");
|
||||
}else if (itemHideCanvas.getText().equals("Show Canvas")){
|
||||
canvas.setVisible(true);
|
||||
itemHideCanvas.setText("Hide Canvas");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final JMenuItem itemSwitchTab = new JMenuItem("Switch to tab #2");
|
||||
menuTortureMethods.add(itemSwitchTab);
|
||||
itemSwitchTab.addActionListener(new ActionListener(){
|
||||
public void actionPerformed(ActionEvent e){
|
||||
if (itemSwitchTab.getText().equals("Switch to tab #2")){
|
||||
canvasPanel1.remove(canvas);
|
||||
canvasPanel2.add(canvas, BorderLayout.CENTER);
|
||||
currentPanel = canvasPanel2;
|
||||
itemSwitchTab.setText("Switch to tab #1");
|
||||
}else if (itemSwitchTab.getText().equals("Switch to tab #1")){
|
||||
canvasPanel2.remove(canvas);
|
||||
canvasPanel1.add(canvas, BorderLayout.CENTER);
|
||||
currentPanel = canvasPanel1;
|
||||
itemSwitchTab.setText("Switch to tab #2");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem itemSwitchLaf = new JMenuItem("Switch Look and Feel");
|
||||
menuTortureMethods.add(itemSwitchLaf);
|
||||
itemSwitchLaf.addActionListener(new ActionListener(){
|
||||
public void actionPerformed(ActionEvent e){
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Throwable t){
|
||||
t.printStackTrace();
|
||||
}
|
||||
SwingUtilities.updateComponentTreeUI(frame);
|
||||
frame.pack();
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem itemSmallSize = new JMenuItem("Set size to (0, 0)");
|
||||
menuTortureMethods.add(itemSmallSize);
|
||||
itemSmallSize.addActionListener(new ActionListener(){
|
||||
public void actionPerformed(ActionEvent e){
|
||||
Dimension preferred = frame.getPreferredSize();
|
||||
frame.setPreferredSize(new Dimension(0, 0));
|
||||
frame.pack();
|
||||
frame.setPreferredSize(preferred);
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem itemKillCanvas = new JMenuItem("Stop/Start Canvas");
|
||||
menuTortureMethods.add(itemKillCanvas);
|
||||
itemKillCanvas.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
currentPanel.remove(canvas);
|
||||
app.stop(true);
|
||||
|
||||
createCanvas(appClass);
|
||||
currentPanel.add(canvas, BorderLayout.CENTER);
|
||||
frame.pack();
|
||||
startApp();
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem itemExit = new JMenuItem("Exit");
|
||||
menuTortureMethods.add(itemExit);
|
||||
itemExit.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
frame.dispose();
|
||||
app.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void createFrame(){
|
||||
frame = new JFrame("Test");
|
||||
@ -71,75 +200,14 @@ public class TestCanvas {
|
||||
}
|
||||
});
|
||||
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
frame.setJMenuBar(menuBar);
|
||||
|
||||
JMenu menuFile = new JMenu("File");
|
||||
menuBar.add(menuFile);
|
||||
|
||||
final JMenuItem itemRemoveCanvas = new JMenuItem("Remove Canvas");
|
||||
menuFile.add(itemRemoveCanvas);
|
||||
itemRemoveCanvas.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (itemRemoveCanvas.getText().equals("Remove Canvas")){
|
||||
frame.getContentPane().remove(canvas);
|
||||
|
||||
// force OS to repaint over canvas ..
|
||||
// this is needed since AWT does not handle
|
||||
// that when a heavy-weight component is removed.
|
||||
frame.setVisible(false);
|
||||
frame.setVisible(true);
|
||||
frame.requestFocus();
|
||||
|
||||
itemRemoveCanvas.setText("Add Canvas");
|
||||
}else if (itemRemoveCanvas.getText().equals("Add Canvas")){
|
||||
frame.getContentPane().add(canvas);
|
||||
itemRemoveCanvas.setText("Remove Canvas");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem itemKillCanvas = new JMenuItem("Stop/Start Canvas");
|
||||
menuFile.add(itemKillCanvas);
|
||||
itemKillCanvas.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
frame.getContentPane().remove(canvas);
|
||||
app.stop(true);
|
||||
|
||||
createCanvas(appClass);
|
||||
frame.getContentPane().add(canvas);
|
||||
frame.pack();
|
||||
startApp();
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem itemExit = new JMenuItem("Exit");
|
||||
menuFile.add(itemExit);
|
||||
itemExit.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
frame.dispose();
|
||||
app.stop();
|
||||
}
|
||||
});
|
||||
|
||||
JMenu menuEdit = new JMenu("Edit");
|
||||
menuBar.add(menuEdit);
|
||||
JMenuItem itemDelete = new JMenuItem("Delete");
|
||||
menuEdit.add(itemDelete);
|
||||
|
||||
JMenu menuView = new JMenu("View");
|
||||
menuBar.add(menuView);
|
||||
JMenuItem itemSetting = new JMenuItem("Settings");
|
||||
menuView.add(itemSetting);
|
||||
|
||||
JMenu menuHelp = new JMenu("Help");
|
||||
menuBar.add(menuHelp);
|
||||
createTabs();
|
||||
createMenu();
|
||||
}
|
||||
|
||||
public static void createCanvas(String appClass){
|
||||
AppSettings settings = new AppSettings(true);
|
||||
settings.setWidth( Math.max(640, frame.getContentPane().getWidth()) );
|
||||
settings.setHeight( Math.max(480, frame.getContentPane().getHeight()) );
|
||||
settings.setWidth(640);
|
||||
settings.setHeight(480);
|
||||
|
||||
try{
|
||||
Class<? extends Application> clazz = (Class<? extends Application>) Class.forName(appClass);
|
||||
@ -155,6 +223,7 @@ public class TestCanvas {
|
||||
app.setPauseOnLostFocus(false);
|
||||
app.setSettings(settings);
|
||||
app.createCanvas();
|
||||
app.startCanvas();
|
||||
|
||||
context = (JmeCanvasContext) app.getContext();
|
||||
canvas = context.getCanvas();
|
||||
@ -184,14 +253,20 @@ public class TestCanvas {
|
||||
Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]);
|
||||
Logger.getLogger("").addHandler(consoleHandler);
|
||||
|
||||
createCanvas(appClass);
|
||||
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
public void run(){
|
||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||
|
||||
createFrame();
|
||||
createCanvas(appClass);
|
||||
|
||||
frame.getContentPane().add(canvas);
|
||||
currentPanel.add(canvas, BorderLayout.CENTER);
|
||||
frame.pack();
|
||||
startApp();
|
||||
frame.setLocationRelativeTo(null);
|
||||
|
@ -225,7 +225,7 @@ public class TestWalkingChar extends SimpleApplication implements ActionListener
|
||||
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
|
||||
mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
|
||||
effect.setMaterial(mat);
|
||||
effect.setLocalScale(100);
|
||||
// effect.setLocalScale(100);
|
||||
rootNode.attachChild(effect);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user