diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.java index 1d5ef8ca1..c4986ecc5 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.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 diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java index 4738624a7..63d27b856 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java @@ -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; diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java index 40bcb8d2f..1a65e48d9 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java @@ -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)); } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/FakeApplication.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java similarity index 64% rename from sdk/jme3-core/src/com/jme3/gde/core/appstates/FakeApplication.java rename to sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java index 1354c48cd..e930fb8f2 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/appstates/FakeApplication.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java @@ -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 states = new ArrayList(); + + public FakeAppStateManager(Application app) { + super(app); + } + + public List 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"); - appStateManager.update(tpf); + private void removeAllStates() { + for (Iterator it = new ArrayList(appStateManager.getAddedStates()).iterator(); it.hasNext();) { + AppState appState = it.next(); + appStateManager.detach(appState); + } } - public void renderFake() { - appStateManager.render(renderManager); + public boolean updateFake(final float tpf) { + Future fut = fakeAppThread.submit(new Callable() { + 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 static class FakeAppStateManager extends AppStateManager { - - private AppStateManagerNode node; - ArrayList states = new ArrayList(); + public boolean renderFake() { + Future fut = fakeAppThread.submit(new Callable() { + 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 FakeAppStateManager(Application app) { - super(app); + public boolean updateExternalLogicalState(final Node externalNode, final float tpf) { + Future fut = fakeAppThread.submit(new Callable() { + 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 getAddedStates() { - return states; + public boolean updateExternalGeometricState(final Node externalNode) { + Future fut = fakeAppThread.submit(new Callable() { + 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); } } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java index 015fa5228..c6f63f1c2 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java @@ -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; @@ -77,7 +76,7 @@ import org.openide.util.NbPreferences; import org.openide.util.lookup.Lookups; /** - * + * * @author normenhansen */ @SuppressWarnings("unchecked") @@ -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); + rootNode.updateGeometricState(); + guiNode.updateGeometricState(); } - 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 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) { diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java index 6961fae97..7d86cf210 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java @@ -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; + } + }