diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.form b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.form
new file mode 100644
index 000000000..6149cfda1
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.form
@@ -0,0 +1,66 @@
+
+
+
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
new file mode 100644
index 000000000..bc9f7cec6
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2003-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.asset.AssetManager;
+import com.jme3.gde.core.assets.ProjectAssetManager;
+import com.jme3.gde.core.scene.PreviewRequest;
+import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.gde.core.scene.SceneListener;
+import com.jme3.gde.core.scene.SceneRequest;
+import com.jme3.renderer.Camera;
+import com.jme3.scene.Spatial;
+import javax.swing.ActionMap;
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.ExplorerUtils;
+import org.openide.explorer.view.BeanTreeView;
+import org.openide.nodes.Node;
+import org.openide.windows.TopComponent;
+import org.openide.util.NbBundle.Messages;
+
+/**
+ * TODO: preliminary implementation 'til new scene system
+ */
+@ConvertAsProperties(
+ dtd = "-//com.jme3.gde.core.appstates//AppStateExplorer//EN",
+autostore = false)
+@TopComponent.Description(
+ preferredID = "AppStateExplorerTopComponent",
+//iconBase="SET/PATH/TO/ICON/HERE",
+persistenceType = TopComponent.PERSISTENCE_NEVER)
+@TopComponent.Registration(mode = "navigator", openAtStartup = true)
+@ActionID(category = "Window", id = "com.jme3.gde.core.appstates.AppStateExplorerTopComponent")
+@ActionReference(path = "Menu/Window" /*, position = 333 */)
+@TopComponent.OpenActionRegistration(
+ displayName = "#CTL_AppStateExplorerAction",
+preferredID = "AppStateExplorerTopComponent")
+@Messages({
+ "CTL_AppStateExplorerAction=AppStateExplorer",
+ "CTL_AppStateExplorerTopComponent=AppStateExplorer Window",
+ "HINT_AppStateExplorerTopComponent=This is a AppStateExplorer window"
+})
+public final class AppStateExplorerTopComponent extends TopComponent implements ExplorerManager.Provider {
+
+ private transient ExplorerManager explorerManager = new ExplorerManager();
+ private FakeApplication fakeApp;
+ private ProjectAssetManager mgr;
+ private SceneListener listener = new SceneListener() {
+ public void sceneOpened(SceneRequest 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());
+ jButton1.setEnabled(true);
+ explorerManager.setRootContext(nod);
+ setActivatedNodes(new Node[]{nod});
+ }
+
+ public void sceneClosed(SceneRequest request) {
+ SceneApplication.getApplication().setFakeApp(null);
+ mgr = null;
+ fakeApp = null;
+ jButton1.setEnabled(false);
+ explorerManager.setRootContext(Node.EMPTY);
+ setActivatedNodes(new Node[]{Node.EMPTY});
+ }
+
+ public void previewCreated(PreviewRequest request) {
+ }
+ };
+
+ public AppStateExplorerTopComponent() {
+ initComponents();
+ setName(Bundle.CTL_AppStateExplorerTopComponent());
+ setToolTipText(Bundle.HINT_AppStateExplorerTopComponent());
+ ActionMap map = getActionMap();
+ map.put("delete", ExplorerUtils.actionDelete(explorerManager, true));
+// map.put("moveup", new MoveUpAction());
+// map.put("movedown", new MoveDownAction());
+ associateLookup(ExplorerUtils.createLookup(explorerManager, map));
+ SceneApplication.getApplication().addSceneListener(listener);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane1 = new BeanTreeView();
+ jToolBar1 = new javax.swing.JToolBar();
+ jButton1 = new javax.swing.JButton();
+
+ jToolBar1.setFloatable(false);
+ jToolBar1.setRollover(true);
+
+ org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AppStateExplorerTopComponent.class, "AppStateExplorerTopComponent.jButton1.text")); // NOI18N
+ jButton1.setEnabled(false);
+ jButton1.setFocusable(false);
+ jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
+ jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton1ActionPerformed(evt);
+ }
+ });
+ jToolBar1.add(jButton1);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 259, Short.MAX_VALUE)
+ .addComponent(jScrollPane1)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 193, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ 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();
+ }
+ }//GEN-LAST:event_jButton1ActionPerformed
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton jButton1;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JToolBar jToolBar1;
+ // End of variables declaration//GEN-END:variables
+
+ @Override
+ public void componentOpened() {
+ }
+
+ @Override
+ public void componentClosed() {
+ }
+
+ void writeProperties(java.util.Properties p) {
+ // better to version settings since initial version as advocated at
+ // http://wiki.apidesign.org/wiki/PropertyFiles
+ p.setProperty("version", "1.0");
+ }
+
+ void readProperties(java.util.Properties p) {
+ String version = p.getProperty("version");
+ }
+
+ public ExplorerManager getExplorerManager() {
+ return explorerManager;
+ }
+}
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
new file mode 100644
index 000000000..4738624a7
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2003-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.app.state.AppState;
+import com.jme3.gde.core.appstates.FakeApplication.FakeAppStateManager;
+import java.util.LinkedList;
+import java.util.List;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class AppStateManagerNode extends AbstractNode {
+
+// private static Image smallImage =
+// ImageUtilities.loadImage("com/jme3/gde/core/filters/icons/eye.gif");
+
+ public AppStateManagerNode(FakeAppStateManager manager) {
+ super(new AppStateChildren(manager));
+ setName("Loaded App States");
+ manager.setNode(this);
+ }
+
+// @Override
+// public Image getIcon(int type) {
+// return smallImage;
+// }
+//
+// @Override
+// public Image getOpenedIcon(int type) {
+// return smallImage;
+// }
+
+ public void refresh() {
+ //TODO: external refresh
+ ((AppStateChildren) getChildren()).doRefresh();
+ }
+
+ public static class AppStateChildren extends Children.Keys {
+
+ private final FakeAppStateManager manager;
+
+ public AppStateChildren(FakeAppStateManager manager) {
+ this.manager = manager;
+ }
+
+ @Override
+ protected void addNotify() {
+ super.addNotify();
+ setKeys(createKeys());
+ }
+
+ protected void doRefresh() {
+ addNotify();
+ refresh();
+ }
+
+ protected void reorderNotify() {
+ setKeys(createKeys());
+ }
+
+ protected List createKeys() {
+ List keys = new LinkedList();
+ List states;
+ states = manager.getAddedStates();
+ keys.addAll(states);
+ return keys;
+ }
+
+ @Override
+ protected Node[] createNodes(Object t) {
+ AppStateNode node = new AppStateNode((AppState) t, manager);
+ return new Node[]{node};
+ }
+ }
+}
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateNode.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateNode.java
new file mode 100644
index 000000000..ad5f4e985
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateNode.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2003-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.app.state.AppState;
+import com.jme3.app.state.AppStateManager;
+import com.jme3.gde.core.properties.SceneExplorerProperty;
+import com.jme3.gde.core.properties.ScenePropertyChangeListener;
+import com.jme3.gde.core.util.PropertyUtils;
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node.Property;
+import org.openide.nodes.Sheet;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class AppStateNode extends AbstractNode implements ScenePropertyChangeListener {
+
+ protected AppState appState;
+ protected AppStateManager parent;
+// private static Image icon;
+// private static final String ICON_ENABLED = "com/jme3/gde/core/filters/icons/eye.gif";
+// private static final String ICON_DISABLED = "com/jme3/gde/core/filters/icons/crossedEye.gif";
+
+ public AppStateNode(AppState appState, AppStateManager parent) {
+ super(Children.LEAF);
+ this.parent = parent;
+ this.appState = appState;
+ setName(appState.getClass().getName());
+ setDisplayName(appState.getClass().getSimpleName());
+// icon = ImageUtilities.loadImage(ICON_ENABLED);
+// setIconBaseWithExtension(ICON_ENABLED);
+ }
+
+// @Override
+// public Image getIcon(int type) {
+// return icon;
+//
+// }
+//
+// @Override
+// public Image getOpenedIcon(int type) {
+// return icon;
+// }
+//
+// public void toggleIcon(boolean enabled) {
+// if (enabled) {
+// icon = ImageUtilities.loadImage(ICON_ENABLED);
+//
+// } else {
+// icon = ImageUtilities.loadImage(ICON_DISABLED);
+//
+// }
+// fireIconChange();
+// }
+// @Override
+// public Action[] getActions(boolean context) {
+// return new Action[]{
+// //Actions.alwaysEnabled(new EnableFiterAction(this), "Toggle enabled", "", false),
+// // SystemAction.get(MoveUpAction.class),
+// // SystemAction.get(MoveDownAction.class),
+// null, // SystemAction.get(DeleteAction.class),
+// };
+// }
+//
+// @Override
+// public Action getPreferredAction() {
+//// return Actions.alwaysEnabled(new EnableFiterAction(this), "Toggle enabled", "", false);
+// return null;
+// }
+ @Override
+ public boolean canDestroy() {
+ return true;
+ }
+
+ @Override
+ public void destroy() throws IOException {
+ super.destroy();
+ parent.detach(appState);
+ //TODO:hack
+ ((AppStateManagerNode) getParentNode()).refresh();
+ }
+
+ @Override
+ protected Sheet createSheet() {
+ Sheet sheet = super.createSheet();
+ Object obj = appState;
+ if (obj == null) {
+ DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(
+ "AppState unexpectedly null",
+ NotifyDescriptor.WARNING_MESSAGE));
+ return sheet;
+ }
+
+// Sheet.Set set2 = Sheet.createPropertiesSet();
+// set2.setDisplayName("AppStateMethods");
+// set2.setName(appState.getClass().getName() + ".hack");
+// createMethods(appState.getClass(), set2, obj);
+// sheet.put(set2);
+
+ Sheet.Set set = Sheet.createPropertiesSet();
+ set.setDisplayName("AppState");
+ set.setName(appState.getClass().getName());
+ createFields(appState.getClass(), set, obj);
+ sheet.put(set);
+
+ return sheet;
+ }
+
+ protected Property> makeProperty(Object obj, Class returntype, String method, String name) {
+ Property> prop = null;
+ try {
+ //getExplorerObjectClass().cast(obj)
+ prop = new SceneExplorerProperty(appState.getClass().cast(obj), returntype, method, null, this);
+ prop.setName(name);
+ } catch (NoSuchMethodException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return prop;
+ }
+
+ protected Property> makeProperty(Object obj, Class returntype, String method, String setter, String name) {
+ Property> prop = null;
+ try {
+ prop = new SceneExplorerProperty(appState.getClass().cast(obj), returntype, method, setter, this);
+ prop.setName(name);
+ } catch (NoSuchMethodException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return prop;
+ }
+
+ protected void createMethods(Class c, Sheet.Set set, Object obj) throws SecurityException {
+ for (Method method : c.getDeclaredMethods()) {
+ PropertyDescriptor prop = PropertyUtils.getPropertyDescriptor(c, method);
+ if (prop != null) {
+ set.put(makeProperty(obj, prop.getPropertyType(), prop.getReadMethod().getName(), prop.getWriteMethod().getName(), prop.getDisplayName()));
+ }
+ }
+ }
+
+ protected void createFields(Class c, Sheet.Set set, Object obj) throws SecurityException {
+ for (Field field : c.getDeclaredFields()) {
+ PropertyDescriptor prop = PropertyUtils.getPropertyDescriptor(c, field);
+ if (prop != null) {
+ set.put(makeProperty(obj, prop.getPropertyType(), prop.getReadMethod().getName(), prop.getWriteMethod().getName(), prop.getDisplayName()));
+ }
+ }
+ }
+
+ public void propertyChange(String property, Object oldValue, Object newValue) {
+ }
+}
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/appstates/Bundle.properties
new file mode 100644
index 000000000..2a7141b4a
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/Bundle.properties
@@ -0,0 +1,3 @@
+AppStateExplorerTopComponent.jButton1.text=attach..
+NewAppStateVisualPanel1.jLabel1.text=Select or enter AppState classname
+NewAppStateVisualPanel1.jTextField1.text=com.mycompany.MyAppState
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/FakeApplication.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/FakeApplication.java
new file mode 100644
index 000000000..1354c48cd
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/FakeApplication.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2003-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.app.Application;
+import com.jme3.app.SimpleApplication;
+import com.jme3.app.state.AppState;
+import com.jme3.app.state.AppStateManager;
+import com.jme3.asset.AssetManager;
+import com.jme3.audio.AudioRenderer;
+import com.jme3.audio.Listener;
+import com.jme3.input.FlyByCamera;
+import com.jme3.input.InputManager;
+import com.jme3.renderer.Camera;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.Renderer;
+import com.jme3.renderer.ViewPort;
+import com.jme3.scene.Node;
+import com.jme3.system.AppSettings;
+import com.jme3.system.JmeContext;
+import com.jme3.system.JmeContext.Type;
+import com.jme3.system.Timer;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.util.Exceptions;
+
+/**
+ * TODO: Temporary implementation before new scene system!
+ *
+ * @author normenhansen
+ */
+public class FakeApplication extends SimpleApplication {
+// private Lookup lookup;
+
+ private Node rootNode;
+ private Node guiNode;
+ private AssetManager assetManager;
+ private Camera cam;
+ private FakeAppStateManager appStateManager;
+ private FakeRenderManager renderManager;
+
+ public FakeApplication(Node rootNode, Node guiNode, AssetManager assetManager, Camera cam) {
+ this.rootNode = rootNode;
+ this.guiNode = guiNode;
+ this.assetManager = assetManager;
+ this.cam = cam;
+ this.appStateManager = new FakeAppStateManager(this);
+ }
+
+ @Override
+ public void createCanvas() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public void destroy() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ protected void destroyInput() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public Future enqueue(Callable callable) {
+ return super.enqueue(callable);
+ }
+
+ @Override
+ public void gainFocus() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public AssetManager getAssetManager() {
+ return assetManager;
+ }
+
+ @Override
+ public AudioRenderer getAudioRenderer() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public Camera getCamera() {
+ return cam;
+ }
+
+ @Override
+ public JmeContext getContext() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public ViewPort getGuiViewPort() {
+ //TODO
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public InputManager getInputManager() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public Listener getListener() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public RenderManager getRenderManager() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public Renderer getRenderer() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public FakeAppStateManager getStateManager() {
+ return appStateManager;
+ }
+
+ @Override
+ public Timer getTimer() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public ViewPort getViewPort() {
+ //TODO
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public boolean isPauseOnLostFocus() {
+ return true;
+ }
+
+ @Override
+ public void loseFocus() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public void initialize() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public void handleError(String errMsg, Throwable t) {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public void requestClose(boolean esc) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void reshape(int w, int h) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void restart() {
+ defaultFakeError();
+ }
+
+ @Override
+ public void setAssetManager(AssetManager assetManager) {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public void setSettings(AppSettings settings) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void setPauseOnLostFocus(boolean pauseOnLostFocus) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void start() {
+ defaultFakeError();
+ }
+
+ @Override
+ public void start(Type contextType) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void startCanvas() {
+ defaultFakeError();
+ }
+
+ @Override
+ public void startCanvas(boolean waitFor) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void stop() {
+ defaultFakeError();
+ }
+
+ @Override
+ public void stop(boolean waitFor) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void update() {
+ defaultFakeError(true);
+ }
+
+ /*
+ * SimpleApplication
+ */
+ @Override
+ public void simpleInitApp() {
+ defaultFakeError(true);
+ }
+
+ @Override
+ public FlyByCamera getFlyByCamera() {
+ defaultFakeError();
+ return null;
+ }
+
+ @Override
+ public Node getGuiNode() {
+ return guiNode;
+ }
+
+ @Override
+ public Node getRootNode() {
+ return rootNode;
+ }
+
+ @Override
+ public boolean isShowSettings() {
+ return true;
+ }
+
+ @Override
+ public void setDisplayFps(boolean show) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void setDisplayStatView(boolean show) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void setTimer(Timer timer) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void setShowSettings(boolean showSettings) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void simpleRender(RenderManager rm) {
+ defaultFakeError();
+ }
+
+ @Override
+ public void simpleUpdate(float tpf) {
+ defaultFakeError();
+ }
+
+ private class FakeRenderManager extends RenderManager {
+
+ public FakeRenderManager(Renderer renderer) {
+ super(null);
+ }
+ //TODO: also nice messages
+ }
+
+ /*
+ * Internal
+ */
+ private void defaultFakeError() {
+ defaultFakeError(false);
+ }
+
+ private void defaultFakeError(boolean severe) {
+ ByteArrayOutputStream str = new ByteArrayOutputStream();
+ new Throwable().printStackTrace(new PrintStream(new BufferedOutputStream(str)));
+ String trace = "No stack trace available.";
+ try {
+ trace = str.toString("UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ int idx = trace.indexOf("com.jme3.gde");
+ while (idx != -1) {
+ if (idx < 50) {
+ continue;
+ } else {
+ trace = trace.substring(0, idx);
+ break;
+ }
+ }
+ showError("Fake app is fake!" + (severe ? "And WTF are you trying to do anyway?\n" : "\n") + trace);
+ }
+
+ private void showError(String msg) {
+ DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(
+ msg,
+ NotifyDescriptor.WARNING_MESSAGE));
+ }
+
+ public void updateFake(float tpf) {
+// System.out.println("UPDATE");
+ appStateManager.update(tpf);
+ }
+
+ public void renderFake() {
+ appStateManager.render(renderManager);
+ }
+
+ 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);
+ try {
+ states.add(state);
+ } catch (Exception 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) {
+ try {
+ states.remove(state);
+ } catch (Exception e) {
+ Exceptions.printStackTrace(e);
+ }
+ return super.detach(state);
+ }
+
+ public void setNode(AppStateManagerNode node) {
+ this.node = node;
+ }
+ }
+}
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.form b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.form
new file mode 100644
index 000000000..9ae30e44b
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.form
@@ -0,0 +1,85 @@
+
+
+
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.java
new file mode 100644
index 000000000..e2f3726e9
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.gde.core.sceneexplorer.nodes.actions.impl.*;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.swing.JPanel;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.project.JavaProjectConstants;
+import org.netbeans.api.java.source.ClassIndex;
+import org.netbeans.api.java.source.ClassIndex.NameKind;
+import org.netbeans.api.java.source.ClassIndex.SearchScope;
+import org.netbeans.api.java.source.ClasspathInfo;
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.JavaSource.Phase;
+import org.netbeans.api.java.source.Task;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.api.project.Sources;
+import org.openide.util.Exceptions;
+
+public final class NewAppStateVisualPanel1 extends JPanel {
+
+ private Project proj;
+
+ /**
+ * Creates new form NewCustomControlVisualPanel1
+ */
+ public NewAppStateVisualPanel1() {
+ initComponents();
+ }
+
+ @Override
+ public String getName() {
+ return "Select AppState";
+ }
+
+ public String getClassName() {
+ return jTextField1.getText();
+ }
+
+ private void scanControls() {
+ List sources = getSources();
+ jList1.setListData(sources.toArray());
+ }
+
+ private List getSources() {
+ Sources sources = proj.getLookup().lookup(Sources.class);
+ final List list = new LinkedList();
+ if (sources != null) {
+ SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
+ if (groups != null) {
+ for (SourceGroup sourceGroup : groups) {
+ ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.BOOT),
+ ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.COMPILE),
+ ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.SOURCE));
+
+ HashSet set = new HashSet();
+ set.add(ClassIndex.SearchScope.SOURCE);
+ Set> types = cpInfo.getClassIndex().getDeclaredTypes("", NameKind.PREFIX, set);
+ for (Iterator> it = types.iterator(); it.hasNext();) {
+ final ElementHandle elementHandle = it.next();
+ JavaSource js = JavaSource.create(cpInfo);
+ try {
+ js.runUserActionTask(new Task() {
+ public void run(CompilationController control)
+ throws Exception {
+ control.toPhase(Phase.RESOLVED);
+ //TODO: check with proper casting check.. gotta get TypeMirror of Control interface..
+// TypeUtilities util = control.getTypeUtilities();//.isCastable(Types., null)
+// util.isCastable(null, null);
+ TypeElement elem = elementHandle.resolve(control);
+ if (elem != null) {
+ List extends TypeMirror> interfaces = elem.getInterfaces();
+ for (TypeMirror typeMirror : interfaces) {
+ String interfaceName = typeMirror.toString();
+ if ("com.jme3.app.state.AppState".equals(interfaceName)) {
+ list.add(elem.getQualifiedName().toString());
+ }
+ }
+ TypeMirror superClass = elem.getSuperclass();
+ String superClassName = superClass.toString();
+ if ("com.jme3.app.state.AbstractAppState".equals(superClassName)) {
+ list.add(elem.getQualifiedName().toString());
+ }
+ }
+ }
+ }, false);
+ } catch (Exception ioe) {
+ Exceptions.printStackTrace(ioe);
+ }
+ }
+
+ }
+ }
+ }
+ return list;
+ }
+
+ public void load(Project proj) {
+ this.proj = proj;
+ scanControls();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane1 = new javax.swing.JScrollPane();
+ jList1 = new javax.swing.JList();
+ jLabel1 = new javax.swing.JLabel();
+ jTextField1 = new javax.swing.JTextField();
+
+ jList1.setModel(new javax.swing.AbstractListModel() {
+ String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
+ public int getSize() { return strings.length; }
+ public Object getElementAt(int i) { return strings[i]; }
+ });
+ jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
+ public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
+ updateClassName(evt);
+ }
+ });
+ jScrollPane1.setViewportView(jList1);
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(NewAppStateVisualPanel1.class, "NewAppStateVisualPanel1.jLabel1.text")); // NOI18N
+
+ jTextField1.setText(org.openide.util.NbBundle.getMessage(NewAppStateVisualPanel1.class, "NewAppStateVisualPanel1.jTextField1.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 351, Short.MAX_VALUE)
+ .addComponent(jTextField1)
+ .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void updateClassName(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_updateClassName
+ Object obj = jList1.getSelectedValue();
+ if (obj != null) {
+ jTextField1.setText(obj + "");
+ }
+ }//GEN-LAST:event_updateClassName
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JList jList1;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JTextField jTextField1;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateWizardAction.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateWizardAction.java
new file mode 100644
index 000000000..bdb00abdf
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateWizardAction.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.app.Application;
+import com.jme3.app.state.AbstractAppState;
+import com.jme3.app.state.AppState;
+import com.jme3.gde.core.assets.ProjectAssetManager;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.MessageFormat;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.WizardDescriptor;
+import org.openide.util.Exceptions;
+
+// An example action demonstrating how the wizard could be called from within
+// your code. You can move the code below wherever you need, or register an action:
+// @ActionID(category="...", id="com.jme3.gde.core.sceneexplorer.nodes.actions.impl.NewCustomControlWizardAction")
+// @ActionRegistration(displayName="Open NewCustomControl Wizard")
+// @ActionReference(path="Menu/Tools", position=...)
+public final class NewAppStateWizardAction implements ActionListener {
+
+ private WizardDescriptor.Panel[] panels;
+ ProjectAssetManager mgr;
+ Application fakeApp;
+
+ public NewAppStateWizardAction(ProjectAssetManager mgr, Application fakeApp) {
+ this.mgr = mgr;
+ this.fakeApp = fakeApp;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ //TODO: actual action to open/close via keyboard etc?
+ }
+
+ protected void showWizard() {
+ WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
+ // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
+ wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
+ wizardDescriptor.setTitle("Add New AppState");
+ wizardDescriptor.putProperty("asset_manager", mgr);
+ wizardDescriptor.putProperty("fake_app", fakeApp);
+ wizardDescriptor.putProperty("project", mgr.getProject());
+ Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
+ dialog.setVisible(true);
+ dialog.toFront();
+ boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
+ if (!cancelled) {
+ AppState state = doCreateAppState(wizardDescriptor);
+ if (state != null) {
+ fakeApp.getStateManager().attach(state);
+ }
+ }
+ }
+
+ protected AppState doCreateAppState(WizardDescriptor configuration) {
+ if (configuration == null) {
+ return null;
+ }
+ WizardDescriptor wizardDescriptor = (WizardDescriptor) configuration;
+ ProjectAssetManager manager = (ProjectAssetManager) wizardDescriptor.getProperty("asset_manager");
+ List loaders = manager.getClassLoaders();
+
+ String className = (String) wizardDescriptor.getProperty("class_name");
+ Class clazz = null;
+ try {
+ clazz = getClass().getClassLoader().loadClass(className);
+ } catch (ClassNotFoundException ex) {
+ }
+ for (ClassLoader classLoader : loaders) {
+ if (clazz == null) {
+ try {
+ clazz = classLoader.loadClass(className);
+ } catch (ClassNotFoundException ex) {
+ }
+ }
+ }
+ if (clazz != null) {
+ try {
+ Object contr = clazz.newInstance();
+ //TODO: remove sillyness-test
+ if (contr instanceof AppState || contr instanceof AbstractAppState) {
+ return (AppState) contr;
+ } else {
+ DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("This is no AppState class!"));
+ }
+ } catch (InstantiationException ex) {
+ Exceptions.printStackTrace(ex);
+ DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Error instatiating class!"));
+ } catch (IllegalAccessException ex) {
+ Exceptions.printStackTrace(ex);
+ DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Error instatiating class!"));
+ }
+ } else {
+ DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Cannot find class: " + className + "\nMake sure the name is correct and the project is compiled,\nbest enable 'Save on Compile' in the project preferences."));
+ }
+ return null;
+ }
+
+ /**
+ * Initialize panels representing individual wizard's steps and sets various
+ * properties for them influencing wizard appearance.
+ */
+ private WizardDescriptor.Panel[] getPanels() {
+ if (panels == null) {
+ panels = new WizardDescriptor.Panel[]{
+ new NewAppStateWizardPanel1()
+ };
+ String[] steps = new String[panels.length];
+ for (int i = 0; i < panels.length; i++) {
+ Component c = panels[i].getComponent();
+ // Default step name to component name of panel. Mainly useful
+ // for getting the name of the target chooser to appear in the
+ // list of steps.
+ steps[i] = c.getName();
+ if (c instanceof JComponent) { // assume Swing components
+ JComponent jc = (JComponent) c;
+ // Sets step number of a component
+ // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*:
+ jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
+ // Sets steps names for a panel
+ jc.putClientProperty("WizardPanel_contentData", steps);
+ // Turn on subtitle creation on each step
+ jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE);
+ // Show steps on the left side with the image on the background
+ jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE);
+ // Turn on numbering of all steps
+ jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE);
+ }
+ }
+ }
+ return panels;
+ }
+}
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateWizardPanel1.java b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateWizardPanel1.java
new file mode 100644
index 000000000..d4798c83d
--- /dev/null
+++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/NewAppStateWizardPanel1.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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;
+
+import com.jme3.gde.core.sceneexplorer.nodes.actions.impl.*;
+import java.awt.Component;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.Project;
+import org.openide.WizardDescriptor;
+import org.openide.util.HelpCtx;
+
+public class NewAppStateWizardPanel1 implements WizardDescriptor.Panel {
+
+ /**
+ * The visual component that displays this panel. If you need to access the
+ * component from this class, just use getComponent().
+ */
+ private Component component;
+
+ // Get the visual component for the panel. In this template, the component
+ // is kept separate. This can be more efficient: if the wizard is created
+ // but never displayed, or not all panels are displayed, it is better to
+ // create only those which really need to be visible.
+ public Component getComponent() {
+ if (component == null) {
+ component = new NewAppStateVisualPanel1();
+ }
+ return component;
+ }
+
+ public HelpCtx getHelp() {
+ // Show no Help button for this panel:
+ return HelpCtx.DEFAULT_HELP;
+ // If you have context help:
+ // return new HelpCtx(SampleWizardPanel1.class);
+ }
+
+ public boolean isValid() {
+ // If it is always OK to press Next or Finish, then:
+ return true;
+ // If it depends on some condition (form filled out...), then:
+ // return someCondition();
+ // and when this condition changes (last form field filled in...) then:
+ // fireChangeEvent();
+ // and uncomment the complicated stuff below.
+ }
+
+ public final void addChangeListener(ChangeListener l) {
+ }
+
+ public final void removeChangeListener(ChangeListener l) {
+ }
+ /*
+ private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0
+ public final void addChangeListener(ChangeListener l) {
+ synchronized (listeners) {
+ listeners.add(l);
+ }
+ }
+ public final void removeChangeListener(ChangeListener l) {
+ synchronized (listeners) {
+ listeners.remove(l);
+ }
+ }
+ protected final void fireChangeEvent() {
+ Iterator it;
+ synchronized (listeners) {
+ it = new HashSet(listeners).iterator();
+ }
+ ChangeEvent ev = new ChangeEvent(this);
+ while (it.hasNext()) {
+ it.next().stateChanged(ev);
+ }
+ }
+ */
+
+ // You can use a settings object to keep track of state. Normally the
+ // settings object will be the WizardDescriptor, so you can use
+ // WizardDescriptor.getProperty & putProperty to store information entered
+ // by the user.
+ public void readSettings(Object settings) {
+ ((NewAppStateVisualPanel1) component).load((Project)((WizardDescriptor) settings).getProperty("project"));
+ }
+
+ public void storeSettings(Object settings) {
+ ((WizardDescriptor) settings).putProperty("class_name", ((NewAppStateVisualPanel1) component).getClassName());
+ }
+}
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 14734fd7e..015fa5228 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,6 +24,7 @@
*/
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;
@@ -116,6 +117,7 @@ public class SceneApplication extends Application implements LookupProvider {
boolean useCanvas = false;
private BulletAppState physicsState;
private Thread thread;
+ private FakeApplication fakeApp;
public SceneApplication() {
progressHandle.start(7);
@@ -265,6 +267,7 @@ public class SceneApplication extends Application implements LookupProvider {
}
try {
super.update();
+ FakeApplication fakap=fakeApp;
float tpf = timer.getTimePerFrame();
camLight.setPosition(cam.getLocation());
secondCounter += tpf;
@@ -274,12 +277,18 @@ public class SceneApplication extends Application implements LookupProvider {
secondCounter = 0.0f;
}
getStateManager().update(tpf);
+ if(fakap!=null){
+ fakap.updateFake(tpf);
+ }
rootNode.updateLogicalState(tpf);
guiNode.updateLogicalState(tpf);
toolsNode.updateLogicalState(tpf);
rootNode.updateGeometricState();
guiNode.updateGeometricState();
toolsNode.updateGeometricState();
+ if(fakap!=null){
+ fakap.renderFake();
+ }
getStateManager().render(renderManager);
renderManager.render(tpf, context.isRenderable());
getStateManager().postRender();
@@ -619,4 +628,12 @@ public class SceneApplication extends Application implements LookupProvider {
public boolean isAwt() {
return java.awt.EventQueue.isDispatchThread();
}
+
+ public FakeApplication getFakeApp() {
+ return fakeApp;
+ }
+
+ public void setFakeApp(FakeApplication fakeApp) {
+ this.fakeApp = fakeApp;
+ }
}
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/util/PropertyUtils.java b/sdk/jme3-core/src/com/jme3/gde/core/util/PropertyUtils.java
index 24b3ba6b1..fa6a434b2 100644
--- a/sdk/jme3-core/src/com/jme3/gde/core/util/PropertyUtils.java
+++ b/sdk/jme3-core/src/com/jme3/gde/core/util/PropertyUtils.java
@@ -34,6 +34,8 @@ package com.jme3.gde.core.util;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import org.openide.util.Exceptions;
/**
*
@@ -43,8 +45,18 @@ public class PropertyUtils {
public static PropertyDescriptor getPropertyDescriptor(Class c, Field field) {
try {
-
-
+ try {
+ try {
+ PropertyDescriptor p = (PropertyDescriptor)c.getClassLoader().loadClass("java.beans.PropertyDescriptor").newInstance();
+
+ } catch (InstantiationException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IllegalAccessException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ } catch (ClassNotFoundException ex) {
+ Exceptions.printStackTrace(ex);
+ }
PropertyDescriptor prop = new PropertyDescriptor(field.getName(), c);
prop.setDisplayName(splitCamelCase(field.getName()));
@@ -56,6 +68,29 @@ public class PropertyUtils {
}
}
+ public static PropertyDescriptor getPropertyDescriptor(Class c, Method meth) {
+ try {
+
+ String name = meth.getName();
+ if (name.startsWith("get") || name.startsWith("set")) {
+ name = name.substring(3);
+ if (name.length() > 0) {
+ name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
+ }
+ } else {
+ return null;
+ }
+ PropertyDescriptor prop = new PropertyDescriptor(name, c);
+
+ prop.setDisplayName(splitCamelCase(meth.getName()));
+
+ return prop;
+ } catch (IntrospectionException ex) {
+ //System.out.println(ex.getMessage());
+ return null;
+ }
+ }
+
static String splitCamelCase(String s) {
s = capitalizeString(s);
return s.replaceAll(