- Improve FakeApplication, integrate into main application
- Add separate execution thread for user code
- Add error handling for failing AppStates
- Add error handling for failing Controls
- AppStateExplorer now works when opening it after the scene

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10079 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 12 years ago
parent 2c6e8cbb2a
commit 2d1af0f1f8
  1. 25
      sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.java
  2. 2
      sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java
  3. 9
      sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java
  4. 199
      sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java
  5. 37
      sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java
  6. 10
      sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java

@ -74,31 +74,27 @@ preferredID = "AppStateExplorerTopComponent")
public final class AppStateExplorerTopComponent extends TopComponent implements ExplorerManager.Provider {
private transient ExplorerManager explorerManager = new ExplorerManager();
private FakeApplication fakeApp;
private ProjectAssetManager mgr;
private SceneRequest currentRequest;
//TODO: move to global place
private SceneListener listener = new SceneListener() {
public void sceneOpened(SceneRequest request) {
currentRequest = request;
Spatial rootNode = request.getRootNode();
if (!(rootNode instanceof com.jme3.scene.Node)) {
return;
}
mgr = request.getManager();
AssetManager assetManager = request.getManager();
Camera cam = SceneApplication.getApplication().getCamera();
com.jme3.scene.Node guiNode = SceneApplication.getApplication().getGuiNode();
fakeApp = new FakeApplication((com.jme3.scene.Node) rootNode, guiNode, assetManager, cam);
//TODO: ermagherd, hackish
SceneApplication.getApplication().setFakeApp(fakeApp);
final AppStateManagerNode nod = new AppStateManagerNode(fakeApp.getStateManager());
final AppStateManagerNode nod = new AppStateManagerNode(request.getFakeApp().getStateManager());
jButton1.setEnabled(true);
explorerManager.setRootContext(nod);
setActivatedNodes(new Node[]{nod});
}
public void sceneClosed(SceneRequest request) {
currentRequest = null;
SceneApplication.getApplication().setFakeApp(null);
mgr = null;
fakeApp = null;
jButton1.setEnabled(false);
explorerManager.setRootContext(Node.EMPTY);
setActivatedNodes(new Node[]{Node.EMPTY});
@ -117,6 +113,11 @@ public final class AppStateExplorerTopComponent extends TopComponent implements
// map.put("moveup", new MoveUpAction());
// map.put("movedown", new MoveDownAction());
associateLookup(ExplorerUtils.createLookup(explorerManager, map));
//TODO: move to scene listener notify in scene?
SceneRequest request = SceneApplication.getApplication().getCurrentSceneRequest();
if (request != null) {
listener.sceneOpened(request);
}
SceneApplication.getApplication().addSceneListener(listener);
}
@ -165,9 +166,9 @@ public final class AppStateExplorerTopComponent extends TopComponent implements
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
ProjectAssetManager projectAssetManager = mgr;
FakeApplication fakeApp = this.fakeApp;
if (fakeApp != null && mgr != null) {
new NewAppStateWizardAction(projectAssetManager, fakeApp).showWizard();
SceneRequest currentRequest = this.currentRequest;
if (currentRequest != null && mgr != null && currentRequest.getFakeApp() != null) {
new NewAppStateWizardAction(projectAssetManager, currentRequest.getFakeApp()).showWizard();
}
}//GEN-LAST:event_jButton1ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables

@ -32,7 +32,7 @@
package com.jme3.gde.core.appstates;
import com.jme3.app.state.AppState;
import com.jme3.gde.core.appstates.FakeApplication.FakeAppStateManager;
import com.jme3.gde.core.scene.FakeApplication.FakeAppStateManager;
import java.util.LinkedList;
import java.util.List;
import org.openide.nodes.AbstractNode;

@ -48,17 +48,18 @@ public class ApplicationLogHandler extends Handler {
JmeFormatter formatter = new JmeFormatter();
public ApplicationLogHandler() {
io.setErrSeparated(true);
}
@Override
public void publish(LogRecord record) {
if (record.getLevel().equals(Level.SEVERE)) {
io.getErr().println(formatter.formatMessage(record));
}
else if (record.getLevel().equals(Level.WARNING)) {
} else if (record.getLevel().equals(Level.WARNING)) {
io.getErr().println(formatter.formatMessage(record));
}
else {
} else if (record.getLevel().equals(Level.INFO)) {
io.getOut().println(formatter.formatMessage(record));
} else {
io.getOut().println(formatter.formatMessage(record));
}
}

@ -29,7 +29,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.gde.core.appstates;
package com.jme3.gde.core.scene;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
@ -38,6 +38,7 @@ import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer;
import com.jme3.audio.Listener;
import com.jme3.gde.core.appstates.AppStateManagerNode;
import com.jme3.input.FlyByCamera;
import com.jme3.input.InputManager;
import com.jme3.renderer.Camera;
@ -45,6 +46,7 @@ import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.control.Control;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeContext.Type;
@ -54,9 +56,14 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.Exceptions;
@ -332,9 +339,60 @@ public class FakeApplication extends SimpleApplication {
//TODO: also nice messages
}
public static class FakeAppStateManager extends AppStateManager {
private AppStateManagerNode node;
ArrayList<AppState> states = new ArrayList<AppState>();
public FakeAppStateManager(Application app) {
super(app);
}
public List<AppState> getAddedStates() {
return states;
}
@Override
public boolean attach(AppState state) {
boolean ret = super.attach(state);
if (ret) {
states.add(state);
}
if (node != null) {
node.refresh();
}
return ret;
}
@Override
public boolean detach(AppState state) {
boolean ret = super.detach(state);
if (ret) {
states.remove(state);
}
if (node != null) {
node.refresh();
}
return ret;
}
public void setNode(AppStateManagerNode node) {
this.node = node;
}
}
/*
* Internal
*/
private ScheduledThreadPoolExecutor fakeAppThread;
public void startFakeApp() {
fakeAppThread = new ScheduledThreadPoolExecutor(1);
}
public void stopFakeApp() {
fakeAppThread.shutdown();
}
private void defaultFakeError() {
defaultFakeError(false);
}
@ -366,60 +424,129 @@ public class FakeApplication extends SimpleApplication {
NotifyDescriptor.WARNING_MESSAGE));
}
public void updateFake(float tpf) {
// System.out.println("UPDATE");
private void removeAllStates() {
for (Iterator<AppState> it = new ArrayList(appStateManager.getAddedStates()).iterator(); it.hasNext();) {
AppState appState = it.next();
appStateManager.detach(appState);
}
}
public boolean updateFake(final float tpf) {
Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
appStateManager.update(tpf);
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in AppState, all AppStates removed."));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Update loop was blocked for too long, all AppStates removed."));
return false;
}
return true;
}
public void renderFake() {
public boolean renderFake() {
Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
appStateManager.render(renderManager);
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in AppState, all AppStates removed."));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Render loop was blocked for too long, all AppStates removed."));
return false;
}
return true;
}
public static class FakeAppStateManager extends AppStateManager {
private AppStateManagerNode node;
ArrayList<AppState> states = new ArrayList<AppState>();
public FakeAppStateManager(Application app) {
super(app);
public boolean updateExternalLogicalState(final Node externalNode, final float tpf) {
Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
externalNode.updateLogicalState(tpf);
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in Control, scene content removed.\n" + ex.getMessage()));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Render loop was blocked for too long, scene content removed."));
return false;
}
return true;
}
public List<AppState> getAddedStates() {
return states;
public boolean updateExternalGeometricState(final Node externalNode) {
Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
externalNode.updateGeometricState();
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in Control, scene content removed.\n" + ex.getMessage()));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Render loop was blocked for too long, scene content removed."));
return false;
}
return true;
}
@Override
public boolean attach(AppState state) {
boolean ret = super.attach(state);
private void clearNode(final Node externalNode) {
while (!externalNode.getChildren().isEmpty()) {
try {
states.add(state);
externalNode.detachAllChildren();
} catch (Exception e) {
Exceptions.printStackTrace(e);
} catch (Error e) {
Exceptions.printStackTrace(e);
}
// DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(
// "attach state",
// NotifyDescriptor.WARNING_MESSAGE));
if (node != null) {
// DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(
// "refresh node",
// NotifyDescriptor.WARNING_MESSAGE));
node.refresh();
}
return ret;
}
@Override
public boolean detach(AppState state) {
Control control = externalNode.getControl(Control.class);
while (control != null) {
try {
states.remove(state);
externalNode.removeControl(control);
} catch (Exception e) {
Exceptions.printStackTrace(e);
} catch (Error e) {
Exceptions.printStackTrace(e);
}
return super.detach(state);
}
public void setNode(AppStateManagerNode node) {
this.node = node;
control = externalNode.getControl(Control.class);
}
}
}

@ -24,7 +24,6 @@
*/
package com.jme3.gde.core.scene;
import com.jme3.gde.core.appstates.FakeApplication;
import com.jme3.app.Application;
import com.jme3.app.StatsView;
import com.jme3.bullet.BulletAppState;
@ -171,7 +170,6 @@ public class SceneApplication extends Application implements LookupProvider {
private void attachPanel() {
enqueue(new Callable() {
public Object call() throws Exception {
panel.attachTo(true, viewPort, overlayView, guiViewPort);
return null;
@ -267,7 +265,7 @@ public class SceneApplication extends Application implements LookupProvider {
}
try {
super.update();
FakeApplication fakap=fakeApp;
FakeApplication fakap = fakeApp;
float tpf = timer.getTimePerFrame();
camLight.setPosition(cam.getLocation());
secondCounter += tpf;
@ -277,16 +275,21 @@ public class SceneApplication extends Application implements LookupProvider {
secondCounter = 0.0f;
}
getStateManager().update(tpf);
if(fakap!=null){
toolsNode.updateLogicalState(tpf);
if (fakap != null) {
fakap.updateFake(tpf);
}
fakap.updateExternalLogicalState(rootNode, tpf);
fakap.updateExternalLogicalState(guiNode, tpf);
fakap.updateExternalGeometricState(rootNode);
fakap.updateExternalGeometricState(guiNode);
} else {
rootNode.updateLogicalState(tpf);
guiNode.updateLogicalState(tpf);
toolsNode.updateLogicalState(tpf);
rootNode.updateGeometricState();
guiNode.updateGeometricState();
}
toolsNode.updateGeometricState();
if(fakap!=null){
if (fakap != null) {
fakap.renderFake();
}
getStateManager().render(renderManager);
@ -331,7 +334,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void notifyPreview(final PreviewRequest request) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
for (Iterator<SceneListener> it = listeners.iterator(); it.hasNext();) {
SceneListener sceneViewerListener = it.next();
@ -347,12 +349,12 @@ public class SceneApplication extends Application implements LookupProvider {
/**
* method to display the node tree of a plugin (threadsafe)
*
* @param request
*/
public void openScene(final SceneRequest request) {
closeScene(currentSceneRequest, request);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
if (request == null) {
return;
@ -370,8 +372,10 @@ public class SceneApplication extends Application implements LookupProvider {
} else {
camController.disable();
}
fakeApp = new FakeApplication(rootNode, guiNode, request.getManager(), cam);
fakeApp.startFakeApp();
request.setFakeApp(fakeApp);
enqueue(new Callable() {
public Object call() throws Exception {
if (request.getManager() != null) {
assetManager = request.getManager();
@ -396,6 +400,7 @@ public class SceneApplication extends Application implements LookupProvider {
/**
* method to close a scene displayed by a scene request (threadsafe)
*
* @param request
*/
public void closeScene(final SceneRequest request) {
@ -404,7 +409,6 @@ public class SceneApplication extends Application implements LookupProvider {
private void closeScene(final SceneRequest oldRequest, final SceneRequest newRequest) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
if (oldRequest == null) {
return;
@ -425,8 +429,11 @@ public class SceneApplication extends Application implements LookupProvider {
if (oldRequest.getRequester() instanceof SceneApplication) {
camController.disable();
}
if (fakeApp != null) {
fakeApp.stopFakeApp();
}
fakeApp = null;
enqueue(new Callable() {
public Object call() throws Exception {
if (physicsState != null) {
physicsState.getPhysicsSpace().removeAll(rootNode);
@ -465,7 +472,7 @@ public class SceneApplication extends Application implements LookupProvider {
req.setModified(false);
}
}
if ((request != null) && (request.getDataObject()instanceof AssetDataObject)){
if ((request != null) && (request.getDataObject() instanceof AssetDataObject)) {
AssetDataObject obj = (AssetDataObject) request.getDataObject();
obj.closeAsset();
}
@ -501,7 +508,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void enableCamLight(final boolean enabled) {
enqueue(new Callable() {
public Object call() throws Exception {
if (enabled) {
rootNode.removeLight(camLight);
@ -516,7 +522,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void enableStats(final boolean enabled) {
enqueue(new Callable() {
public Object call() throws Exception {
if (enabled) {
guiNode.attachChild(statsGuiNode);
@ -530,7 +535,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void enableWireFrame(final boolean selected) {
enqueue(new Callable() {
public Object call() throws Exception {
if (selected) {
viewPort.addProcessor(wireProcessor);
@ -544,7 +548,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void setPhysicsEnabled(final boolean enabled) {
enqueue(new Callable() {
public Object call() throws Exception {
if (enabled) {
if (physicsState == null) {

@ -54,6 +54,7 @@ public class SceneRequest {
private boolean displayed = false;
private DataObject dataObject;
private HelpCtx helpCtx;
private FakeApplication fakeApp;
public SceneRequest(Object requester, JmeNode rootNode, ProjectAssetManager manager) {
this.requester = requester;
@ -175,4 +176,13 @@ public class SceneRequest {
public void setHelpCtx(HelpCtx helpCtx) {
this.helpCtx = helpCtx;
}
public void setFakeApp(FakeApplication fakeApp) {
this.fakeApp = fakeApp;
}
public FakeApplication getFakeApp() {
return fakeApp;
}
}

Loading…
Cancel
Save