diff --git a/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneApplication.java b/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneApplication.java new file mode 100644 index 000000000..a38a1b8bc --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneApplication.java @@ -0,0 +1,66 @@ +package com.jme3.gde.core.editor; + +import com.jme3.app.SimpleApplication; +import com.jme3.app.StatsAppState; +import com.jme3.gde.core.Installer; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.Node; +import com.jme3.system.AppSettings; +import com.jme3.system.awt.AwtPanel; +import com.jme3.system.awt.AwtPanelsContext; +import com.jme3.system.awt.PaintMode; +import java.util.concurrent.Callable; +import org.openide.util.NbPreferences; + +/** + * + * @author normenhansen + */ +public class SceneApplication extends SimpleApplication { + + private AwtPanel panel; + private ViewPort overlayView; + + public SceneApplication() { + super(new StatsAppState()); + AppSettings newSetting = new AppSettings(true); + newSetting.setFrameRate(30); + if ("true".equals(NbPreferences.forModule(Installer.class).get("use_opengl_1", "false"))) { + newSetting.setRenderer(AppSettings.LWJGL_OPENGL1); + } + newSetting.setCustomRenderer(AwtPanelsContext.class); + setSettings(newSetting); + setPauseOnLostFocus(false); + setShowSettings(false); + } + + public AwtPanel getPanel() { + if (panel == null) { + panel = ((AwtPanelsContext) getContext()).createPanel(PaintMode.Accelerated); + ((AwtPanelsContext) getContext()).setInputSource(panel); + attachPanel(); + } + return panel; + } + + private void attachPanel() { + enqueue(new Callable() { + public Object call() throws Exception { + panel.attachTo(true, viewPort, /*overlayView, */guiViewPort); + return null; + } + }); + } + + @Override + public Node getRootNode() { + return super.getRootNode(); + } + + @Override + public void simpleInitApp() { + overlayView = getRenderManager().createMainView("Overlay", cam); + overlayView.setClearFlags(false, true, false); + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.form b/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.form new file mode 100644 index 000000000..1d73df479 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.form @@ -0,0 +1,25 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.java b/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.java new file mode 100644 index 000000000..8b6dc707a --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.java @@ -0,0 +1,131 @@ +package com.jme3.gde.core.editor; + +import java.io.IOException; +import javax.swing.JPanel; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataObject; +import org.openide.loaders.OpenSupport; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.windows.TopComponent; +import org.openide.util.NbBundle.Messages; +import org.openide.windows.CloneableTopComponent; + +/** + * Top component which displays something. + */ +@ConvertAsProperties( + dtd = "-//com.jme3.gde.core.editor//SceneEditor//EN", +autostore = false) +@TopComponent.Description( + preferredID = "SceneEditorTopComponent", +//iconBase="SET/PATH/TO/ICON/HERE", +persistenceType = TopComponent.PERSISTENCE_ALWAYS) +@TopComponent.Registration(mode = "editor", openAtStartup = false) +@ActionID(category = "Window", id = "com.jme3.gde.core.editor.SceneEditorTopComponent") +@ActionReference(path = "Menu/Window" /*, position = 333 */) +@TopComponent.OpenActionRegistration( + displayName = "#CTL_SceneEditorAction", +preferredID = "SceneEditorTopComponent") +@Messages({ + "CTL_SceneEditorAction=SceneEditor", + "CTL_SceneEditorTopComponent=SceneEditor Window", + "HINT_SceneEditorTopComponent=This is a SceneEditor window" +}) +public final class SceneEditorTopComponent extends CloneableTopComponent { + + DataObject obj; + + public SceneEditorTopComponent() { + initComponents(); + setToolTipText(Bundle.HINT_SceneEditorTopComponent()); + } + + public void setDataObject(DataObject scene) { + obj = scene; + if (scene == null) { + return; + } + setName(scene.getName()); + setActivatedNodes(new Node[]{scene.getNodeDelegate()}); + } + + public JPanel getScenePanel() { + return scenePanel; + } + + /** + * 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() { + + scenePanel = new javax.swing.JPanel(); + + setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.PAGE_AXIS)); + + scenePanel.setLayout(new javax.swing.BoxLayout(scenePanel, javax.swing.BoxLayout.LINE_AXIS)); + add(scenePanel); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel scenePanel; + // End of variables declaration//GEN-END:variables + + @Override + public boolean canClose() { + if (obj != null && obj.isModified()) { + NotifyDescriptor.Confirmation mesg = new NotifyDescriptor.Confirmation("Scene has not been saved,\ndo you want to save it?", + "Not Saved", + NotifyDescriptor.YES_NO_CANCEL_OPTION); + DialogDisplayer.getDefault().notify(mesg); + if (mesg.getValue() == NotifyDescriptor.Confirmation.YES_OPTION) { + try { + obj.getCookie(SaveCookie.class).save(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } else if (mesg.getValue() == NotifyDescriptor.Confirmation.CANCEL_OPTION) { + return false; + } else if (mesg.getValue() == NotifyDescriptor.Confirmation.NO_OPTION) { + obj.setModified(false); + return true; + } + } + return true; + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + if (obj != null) { + OpenSupport closer = obj.getLookup().lookup(OpenSupport.class); + if (closer != null) { + closer.close(); + } + } + } + + 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"); + // TODO store your settings + } + + void readProperties(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/editor/SpatialAssetOpenSupport.java b/sdk/jme3-core/src/com/jme3/gde/core/editor/SpatialAssetOpenSupport.java new file mode 100644 index 000000000..039185be0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/editor/SpatialAssetOpenSupport.java @@ -0,0 +1,105 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.core.editor; + +import com.jme3.gde.core.assets.AssetData; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import com.jme3.light.DirectionalLight; +import com.jme3.scene.Spatial; +import com.jme3.system.awt.AwtPanel; +import java.util.concurrent.Callable; +import org.openide.cookies.CloseCookie; +import org.openide.cookies.OpenCookie; +import org.openide.loaders.Environment; +import org.openide.loaders.OpenSupport; +import org.openide.windows.CloneableTopComponent; + +/** + * + * @author normenhansen + */ +public class SpatialAssetOpenSupport extends OpenSupport implements OpenCookie, CloseCookie { + + SpatialAssetDataObject dataObject; + SceneApplication app; + SceneEditorTopComponent tc; + + public SpatialAssetOpenSupport(SpatialAssetDataObject dataObject) { + super(dataObject.getPrimaryEntry()); + this.dataObject = dataObject; + } + + protected CloneableTopComponent createCloneableTopComponent() { + if (tc == null) { + tc = new SceneEditorTopComponent(); + } + return tc; + } + + @Override + public void open() { + super.open(); + if (app == null) { + app = new SceneApplication(); + tc.setDataObject(dataObject); +// dataObject.setModified(true); +// final ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening Scene.."); +// progressHandle.start(); + //runs new thread, needed? + System.out.println("Judge Thread: " + Thread.currentThread().getName()); + Thread t = new Thread(new Runnable() { + public void run() { + app.start(); + //enqueue to wait until started + app.enqueue(new Callable() { + public Void call() throws Exception { + //run on EDT + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + AwtPanel panel = app.getPanel(); + tc.getScenePanel().add(panel); + tc.repaint(); + } + }); + Spatial spat = (Spatial) dataObject.getLookup().lookup(AssetData.class).loadAsset(); + if (spat != null) { + app.getRootNode().attachChild(spat); + app.getRootNode().addLight(new DirectionalLight()); + } + dataObject.getLookupContents().add(app); +// progressHandle.finish(); + return null; + } + }); + } + }); + t.start(); + } + } + + @Override + public boolean close() { + System.out.println("CLOSING"); + boolean close = super.close(); + if (close && app != null) { + app.stop(); + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + tc.getScenePanel().removeAll(); + } + }); + dataObject.getLookupContents().remove(app); + app = null; + } + return close; + } + + @Override + protected boolean canClose() { + System.out.println("CANCLOSE"); + return super.canClose(); + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/navigator/DataScanner.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/DataScanner.java new file mode 100644 index 000000000..647778efb --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/navigator/DataScanner.java @@ -0,0 +1,18 @@ +package com.jme3.gde.core.navigator; + +import com.jme3.app.state.AbstractAppState; + +/** + * + * @author normenhansen + */ + + +public class DataScanner extends AbstractAppState{ + + @Override + public void update(float tpf) { + super.update(tpf); + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/navigator/NavigatorNode.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/NavigatorNode.java new file mode 100644 index 000000000..d0a15f0a7 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/navigator/NavigatorNode.java @@ -0,0 +1,32 @@ + package com.jme3.gde.core.navigator; + +import java.io.IOException; +import org.openide.loaders.DataObject; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ + + +public class NavigatorNode extends AbstractNode{ + + public static NavigatorNode createNode(DataObject obj){ + return null; + } + + public NavigatorNode(Children children, Lookup lookup) { + super(children, lookup); + } + + @Override + public void destroy() throws IOException { + System.out.println("call destroy"); + super.destroy(); + } + + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/navigator/NavigatorNodeChildren.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/NavigatorNodeChildren.java new file mode 100644 index 000000000..e49698f00 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/navigator/NavigatorNodeChildren.java @@ -0,0 +1,34 @@ +package com.jme3.gde.core.navigator; + +import com.jme3.gde.core.editor.SceneApplication; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Node; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public class NavigatorNodeChildren extends ChildFactory { + + private Lookup lookup; + + @Override + protected boolean createKeys(List toPopulate) { + SceneApplication app = lookup.lookup(SceneApplication.class); + if (app == null) { + Logger.getLogger(NavigatorNodeChildren.class.getName()).log(Level.WARNING, "Could not access SceneApplication"); + return true; + } + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Node[] createNodesForKey(Object key) { + return super.createNodesForKey(key); + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneChangeListener.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneChangeListener.java new file mode 100644 index 000000000..04dd6f547 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneChangeListener.java @@ -0,0 +1,43 @@ +/* + * 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.navigator; + +import com.jme3.gde.core.properties.*; + +/** + * + * @author normenhansen + */ +public interface SceneChangeListener { + public void propertyChange(String property, Object oldValue, Object newValue); +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneNavigatorPanel.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneNavigatorPanel.java new file mode 100644 index 000000000..bd09093b8 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneNavigatorPanel.java @@ -0,0 +1,131 @@ +package com.jme3.gde.core.navigator; + +import com.jme3.gde.core.editor.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; +import java.util.Collection; +import java.util.Iterator; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.text.DefaultEditorKit; +import org.netbeans.spi.navigator.NavigatorPanel; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.explorer.view.BeanTreeView; +import org.openide.nodes.Node; +import org.openide.util.Lookup; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; + +/** + * + * @author normenhansen + */ +@NavigatorPanel.Registration(displayName = "SceneExplorer", mimeType = "application/jme3model") +public class SceneNavigatorPanel extends JPanel implements NavigatorPanel, LookupListener, ExplorerManager.Provider { + + private final BeanTreeView beanTreeView = new BeanTreeView(); + private final Lookup lookup; + private transient ExplorerManager explorerManager = new ExplorerManager(); + private Lookup.Result applicationResult; + private final Result nodeSelectionResult; + //ExplorerNode selection listener, does nothing + private LookupListener listener = new LookupListener() { + private Node selectedNode; + + public void resultChanged(LookupEvent ev) { + Collection collection = nodeSelectionResult.allInstances(); + for (Iterator it = collection.iterator(); it.hasNext();) { + Object obj = it.next(); + if (obj instanceof AbstractSceneExplorerNode) { + AbstractSceneExplorerNode node = (AbstractSceneExplorerNode) obj; + if (node != null) { + if (selectedNode != null) { + selectedNode = null; + } + selectedNode = node; + return; + } + } + } + if (selectedNode != null) { + selectedNode = null; + } + } + }; + + public SceneNavigatorPanel() { + ActionMap map = getActionMap(); + Action copyAction = ExplorerUtils.actionCopy(explorerManager); + map.put(DefaultEditorKit.copyAction, copyAction); + map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(explorerManager)); + map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(explorerManager)); + map.put("delete", ExplorerUtils.actionDelete(explorerManager, true)); // or false + + lookup = ExplorerUtils.createLookup(explorerManager, map); + + setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS)); + add(beanTreeView); + + nodeSelectionResult = Utilities.actionsGlobalContext().lookupResult(AbstractSceneExplorerNode.class); + } + + public Lookup getLookup() { + return lookup; + } + + public String getDisplayName() { + return "SceneExplorer"; + } + + public String getDisplayHint() { + return "Hint"; + } + + public JComponent getComponent() { + return this; + } + + public void panelActivated(Lookup lkp) { + ExplorerUtils.activateActions(explorerManager, true); + applicationResult = lkp.lookupResult(SceneApplication.class); + applicationResult.addLookupListener(this); + nodeSelectionResult.addLookupListener(listener); + } + + public void panelDeactivated() { + ExplorerUtils.activateActions(explorerManager, false); + applicationResult.removeLookupListener(this); + nodeSelectionResult.removeLookupListener(listener); + explorerManager.setRootContext(Node.EMPTY); + } + + /** + * result listener for application start + */ + public void resultChanged(LookupEvent ev) { +// System.out.println("Select Thread: " + Thread.currentThread().getName()); + Collection collection = applicationResult.allInstances(); + for (Iterator it = collection.iterator(); it.hasNext();) { + Object obj = it.next(); + if (obj instanceof SceneApplication) { + SceneApplication app = (SceneApplication) obj; + if (app != null) { + Node node = NodeUtility.createNode(((SceneApplication) app).getRootNode()); + explorerManager.setRootContext(node); + explorerManager.getRootContext().setDisplayName(node.getName()); + return; + } + } + } + explorerManager.setRootContext(Node.EMPTY); + } + + public ExplorerManager getExplorerManager() { + return explorerManager; + } +} \ No newline at end of file diff --git a/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneProperty.java new file mode 100644 index 000000000..5f0776d00 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneProperty.java @@ -0,0 +1,52 @@ +/* + * 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.navigator; + +import org.openide.nodes.PropertySupport; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +@SuppressWarnings("unchecked") +public class SceneProperty extends PropertySupport.Reflection { + + Lookup lookup; + Object _originalValue; + + public SceneProperty(Lookup lookup, Object instance, Class valueType, String property) throws NoSuchMethodException { + super(instance, valueType, property); + DataScanner scanner = lookup.lookup(DataScanner.class); + } + +}