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 index ad5f4e985..bbcc37acf 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateNode.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateNode.java @@ -113,10 +113,13 @@ public class AppStateNode extends AbstractNode implements ScenePropertyChangeLis @Override public void destroy() throws IOException { + AppStateManagerNode parentNode = (AppStateManagerNode) getParentNode(); super.destroy(); parent.detach(appState); //TODO:hack - ((AppStateManagerNode) getParentNode()).refresh(); + if (parentNode != null) { + parentNode.refresh(); + } } @Override @@ -130,12 +133,6 @@ public class AppStateNode extends AbstractNode implements ScenePropertyChangeLis 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()); @@ -148,7 +145,6 @@ public class AppStateNode extends AbstractNode implements ScenePropertyChangeLis 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) { @@ -186,6 +182,13 @@ public class AppStateNode extends AbstractNode implements ScenePropertyChangeLis } } - public void propertyChange(String property, Object oldValue, Object newValue) { + public void propertyChange(final String type, final String name, final Object before, final Object after) { + if (SceneExplorerProperty.PROP_USER_CHANGE.equals(type)) { + firePropertyChange(name, before, after); + } else if (SceneExplorerProperty.PROP_SCENE_CHANGE.equals(type)) { + firePropertyChange(name, before, after); + } else if (SceneExplorerProperty.PROP_INIT_CHANGE.equals(type)) { + firePropertyChange(name, before, after); + } } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/filters/actions/EnableFiterAction.java b/sdk/jme3-core/src/com/jme3/gde/core/filters/actions/EnableFiterAction.java index 61d48b99d..59a152a2f 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/filters/actions/EnableFiterAction.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/filters/actions/EnableFiterAction.java @@ -59,7 +59,7 @@ public class EnableFiterAction implements ActionListener { Filter filter=context.getFilter(); filter.setEnabled(!filter.isEnabled()); Logger.getLogger(EnableFiterAction.class.getName()).info( (filter.isEnabled()?"Enabled":"Disabled")+" "+filter.getName()); - context.propertyChange("Enabled", !filter.isEnabled(), filter.isEnabled()); + context.propertyChange("PROP_USER_CHANGE", "Enabled", !filter.isEnabled(), filter.isEnabled()); return null; } 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 deleted file mode 100644 index 647778efb..000000000 --- a/sdk/jme3-core/src/com/jme3/gde/core/navigator/DataScanner.java +++ /dev/null @@ -1,18 +0,0 @@ -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/SceneChangeListener.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneChangeListener.java deleted file mode 100644 index 04dd6f547..000000000 --- a/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneChangeListener.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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/SceneProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneProperty.java deleted file mode 100644 index 5f0776d00..000000000 --- a/sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneProperty.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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); - } - -} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/AudioTrackProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/AudioTrackProperty.java index 1b5707a19..73128acda 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/AudioTrackProperty.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/AudioTrackProperty.java @@ -85,7 +85,7 @@ public class AudioTrackProperty extends PropertySupport.ReadWrite { private void notifyListeners(Object before, Object after) { for (Iterator it = listeners.iterator(); it.hasNext();) { ScenePropertyChangeListener propertyChangeListener = it.next(); - propertyChangeListener.propertyChange(getName(), before, after); + propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after); } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/EffectTrackEmitterProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/EffectTrackEmitterProperty.java index 6b44d5ca3..cf0ae3813 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/EffectTrackEmitterProperty.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/EffectTrackEmitterProperty.java @@ -85,7 +85,7 @@ public class EffectTrackEmitterProperty extends PropertySupport.ReadWrite it = listeners.iterator(); it.hasNext();) { ScenePropertyChangeListener propertyChangeListener = it.next(); - propertyChangeListener.propertyChange(getName(), before, after); + propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after); } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/ParticleInfluencerProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/ParticleInfluencerProperty.java index 72a86438a..54761137a 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/ParticleInfluencerProperty.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/ParticleInfluencerProperty.java @@ -88,7 +88,7 @@ public class ParticleInfluencerProperty extends PropertySupport.ReadWrite it = listeners.iterator(); it.hasNext();) { ScenePropertyChangeListener propertyChangeListener = it.next(); - propertyChangeListener.propertyChange(getName(), before, after); + propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after); } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/SceneExplorerProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/SceneExplorerProperty.java index e6e3e4cc8..4fb87b4e6 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/SceneExplorerProperty.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/SceneExplorerProperty.java @@ -41,16 +41,18 @@ import com.jme3.math.Matrix3f; import com.jme3.math.Quaternion; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Iterator; import java.util.LinkedList; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import org.openide.nodes.PropertySupport; import org.openide.util.Exceptions; import org.openide.util.Lookup; +import org.openide.util.Mutex; /** * @@ -59,6 +61,16 @@ import org.openide.util.Lookup; @SuppressWarnings("unchecked") public class SceneExplorerProperty extends PropertySupport.Reflection { + public static final String PROP_SCENE_CHANGE = "PROP_SCENE_CHANGE"; + public static final String PROP_USER_CHANGE = "PROP_USER_CHANGE"; + public static final String PROP_INIT_CHANGE = "PROP_INIT_CHANGE"; + private T objectLocal; + private final boolean cloneable; + private final boolean instantiable; + private final boolean primitive; + private final Mutex mutex = new Mutex(); + private boolean inited = false; + private final boolean editable; protected LinkedList listeners = new LinkedList(); public SceneExplorerProperty(T instance, Class valueType, String getter, String setter) throws NoSuchMethodException { @@ -67,7 +79,14 @@ public class SceneExplorerProperty extends PropertySupport.Reflection { public SceneExplorerProperty(T instance, Class valueType, String getter, String setter, ScenePropertyChangeListener listener) throws NoSuchMethodException { super(instance, valueType, getter, setter); - addPropertyChangeListener(listener); + primitive = isPrimitive(instance, getter); + if (!primitive) { + cloneable = canClone(instance, getter); + instantiable = canRecreate(instance, getter); + } else { + cloneable = false; + instantiable = false; + } if (valueType == Vector3f.class) { setPropertyEditorClass(Vector3fPropertyEditor.class); } else if (valueType == Quaternion.class) { @@ -87,70 +106,171 @@ public class SceneExplorerProperty extends PropertySupport.Reflection { for (SceneExplorerPropertyEditor di : Lookup.getDefault().lookupAll(SceneExplorerPropertyEditor.class)) { di.setEditor(valueType, this); } + //TODO: instantiates editor? + editable = getPropertyEditor() != null; + addPropertyChangeListener(listener); + } + + /** + * synchronizes the local and scene value + */ + public void syncValue() { + if (!editable) { + return; + } + mutex.postWriteRequest(new Runnable() { + public void run() { + T realValue = getSuperValue(); + if (objectLocal == null && !inited) { + inited = true; + objectLocal = duplicateObject(realValue); + notifyListeners(PROP_INIT_CHANGE, null, objectLocal); + } else if (objectLocal != null && !objectLocal.equals(realValue)) { + T oldObject = objectLocal; + T newObject = duplicateObject(realValue); + notifyListeners(PROP_SCENE_CHANGE, oldObject, newObject); + objectLocal = newObject; + } + } + }); } @Override public T getValue() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return super.getValue(); -// try { -// return SceneApplication.getApplication().enqueue(new Callable() { -// -// public T call() throws Exception { -// return getSuperValue(); -// } -// }).get(); -// } catch (InterruptedException ex) { -// Exceptions.printStackTrace(ex); -// } catch (ExecutionException ex) { -// Exceptions.printStackTrace(ex); -// } -// return null; + return objectLocal; } - private T getSuperValue() { + @Override + public void setValue(final T val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + mutex.postWriteRequest(new Runnable() { + public void run() { + final T oldObject = (T) objectLocal; + objectLocal = val; + final T sceneObject = (T) duplicateObject(val); + notifyListeners(PROP_USER_CHANGE, oldObject, objectLocal); + SceneApplication.getApplication().enqueue(new Callable() { + public Void call() throws Exception { + setSuperValue(sceneObject); + return null; + } + }); + } + }); + } + + private boolean isPrimitive(Object obj, String getter) { try { - return super.getValue(); - } catch (IllegalAccessException ex) { - Exceptions.printStackTrace(ex); - } catch (IllegalArgumentException ex) { - Exceptions.printStackTrace(ex); - } catch (InvocationTargetException ex) { + Class objClass = obj.getClass().getMethod(getter).getReturnType(); + if (objClass.isPrimitive()) { + return true; + } + } catch (NoSuchMethodException ex) { + } catch (SecurityException ex) { Exceptions.printStackTrace(ex); } - return null; + return false; } - @Override - public void setValue(final T val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + private boolean canClone(Object obj, String getter) { try { - notifyListeners(getSuperValue(), val); - SceneApplication.getApplication().enqueue(new Callable() { + Class objClass = obj.getClass().getMethod(getter).getReturnType(); + if (Enum.class.isAssignableFrom(objClass)) { + return false; + } + Method meth = objClass.getMethod("clone"); + if (meth != null) { + if (meth.getParameterTypes().length == 0 + && meth.getReturnType().equals(obj.getClass())) { + return true; + } + } + } catch (NoSuchMethodException ex) { + } catch (SecurityException ex) { + Exceptions.printStackTrace(ex); + } + return false; + } - public Void call() throws Exception { - setSuperValue(val); - return null; + private boolean canRecreate(Object obj, String getter) { + try { + Class objClass = obj.getClass().getMethod(getter).getReturnType(); + if (Enum.class.isAssignableFrom(objClass)) { + return false; + } + Constructor[] constructors = objClass.getConstructors(); + for (Constructor constructor : constructors) { + Class[] types = constructor.getParameterTypes(); + if (types.length == 1 && types[0].equals(obj.getClass())) { + return true; } - }).get(); - } catch (InterruptedException ex) { + } + } catch (NoSuchMethodException ex) { + Exceptions.printStackTrace(ex); + } catch (SecurityException ex) { + Exceptions.printStackTrace(ex); + } + return false; + } + + private T duplicateObject(T a) { + T obj = a; + if (primitive) { + return obj; + } else if (cloneable) { + try { + obj = (T) a.getClass().getMethod("clone").invoke(a); + } catch (IllegalAccessException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } catch (InvocationTargetException ex) { + Exceptions.printStackTrace(ex); + } catch (NoSuchMethodException ex) { + Exceptions.printStackTrace(ex); + } catch (SecurityException ex) { + Exceptions.printStackTrace(ex); + } + } else if (instantiable) { + try { + obj = (T) a.getClass().getConstructor(a.getClass()).newInstance(a); + } catch (InstantiationException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalAccessException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } catch (InvocationTargetException ex) { + Exceptions.printStackTrace(ex); + } catch (NoSuchMethodException ex) { + Exceptions.printStackTrace(ex); + } catch (SecurityException ex) { + Exceptions.printStackTrace(ex); + } + } + return obj; + } + + private void setSuperValue(T val) { + setSuperValue(val, true); + } + + private T getSuperValue() { + try { + return super.getValue(); + } catch (IllegalAccessException ex) { Exceptions.printStackTrace(ex); - } catch (ExecutionException ex) { + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } catch (InvocationTargetException ex) { Exceptions.printStackTrace(ex); } + return null; } private void setSuperValue(T val, boolean undo) { try { if (undo) { - try { - Object oldValue = getSuperValue(); - if (oldValue.getClass().getMethod("clone") != null) { - addUndo(oldValue.getClass().getMethod("clone").invoke(oldValue), val); - Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.INFO, "Add cloned undo {0}", oldValue.getClass().getMethod("clone").invoke(oldValue)); - } - } catch (Exception e) { - addUndo(getSuperValue(), val); - Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.INFO, "Add undo {0}", getSuperValue()); - } + addUndo(duplicateObject(getSuperValue()), val); } super.setValue(val); } catch (IllegalAccessException ex) { @@ -162,10 +282,6 @@ public class SceneExplorerProperty extends PropertySupport.Reflection { } } - private void setSuperValue(T val) { - setSuperValue(val, true); - } - protected void addUndo(final Object before, final Object after) { SceneUndoRedoManager undoRedo = Lookup.getDefault().lookup(SceneUndoRedoManager.class); if (undoRedo == null) { @@ -173,15 +289,17 @@ public class SceneExplorerProperty extends PropertySupport.Reflection { return; } undoRedo.addEdit(this, new AbstractUndoableSceneEdit() { - @Override public void sceneUndo() { - Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.INFO, "Do undo {0}", before); + Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.FINE, "Do undo {0}", before); + notifyListeners(PROP_USER_CHANGE, after, before); setSuperValue((T) before, false); } @Override public void sceneRedo() { + Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.FINE, "Do redo {0}", before); + notifyListeners(PROP_USER_CHANGE, before, after); setSuperValue((T) after, false); } @@ -196,17 +314,25 @@ public class SceneExplorerProperty extends PropertySupport.Reflection { } public void addPropertyChangeListener(ScenePropertyChangeListener listener) { - listeners.add(listener); + if (listener != null) { + listeners.add(listener); + } } public void removePropertyChangeListener(ScenePropertyChangeListener listener) { - listeners.remove(listener); + if (listener != null) { + listeners.remove(listener); + } } - private void notifyListeners(Object before, Object after) { - for (Iterator it = listeners.iterator(); it.hasNext();) { - ScenePropertyChangeListener propertyChangeListener = it.next(); - propertyChangeListener.propertyChange(getName(), before, after); - } + private void notifyListeners(final String type, final Object before, final Object after) { + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + for (Iterator it = listeners.iterator(); it.hasNext();) { + ScenePropertyChangeListener propertyChangeListener = it.next(); + propertyChangeListener.propertyChange(type, getName(), before, after); + } + } + }); } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/ScenePropertyChangeListener.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/ScenePropertyChangeListener.java index 385ca15dd..5b0c55770 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/ScenePropertyChangeListener.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/ScenePropertyChangeListener.java @@ -37,5 +37,5 @@ package com.jme3.gde.core.properties; * @author normenhansen */ public interface ScenePropertyChangeListener { - public void propertyChange(String property, Object oldValue, Object newValue); + public void propertyChange(String type, String name, Object oldValue, Object newValue); } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java index 7918ae1d0..b73739f50 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java @@ -159,7 +159,7 @@ public class UserDataProperty extends PropertySupport.ReadWrite { private void notifyListeners(Object before, Object after) { for (Iterator it = listeners.iterator(); it.hasNext();) { ScenePropertyChangeListener propertyChangeListener = it.next(); - propertyChangeListener.propertyChange(getName(), before, after); + propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after); } } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java index b2d0915fb..2cfc89b53 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java @@ -83,6 +83,13 @@ public class FakeApplication extends SimpleApplication { private FakeAppStateManager appStateManager; private FakeRenderManager renderManager; + public FakeApplication(Node guiNode, AssetManager assetManager, Camera cam) { + this.guiNode = guiNode; + this.assetManager = assetManager; + this.cam = cam; + this.appStateManager = new FakeAppStateManager(this); + } + public FakeApplication(Node rootNode, Node guiNode, AssetManager assetManager, Camera cam) { this.rootNode = rootNode; this.guiNode = guiNode; @@ -385,6 +392,10 @@ public class FakeApplication extends SimpleApplication { */ private ScheduledThreadPoolExecutor fakeAppThread = new ScheduledThreadPoolExecutor(1); + public void setRootNode(Node rootNode) { + this.rootNode = rootNode; + } + public void stopFakeApp() { fakeAppThread.shutdown(); } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/NodeSyncAppState.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/NodeSyncAppState.java new file mode 100644 index 000000000..8200409bf --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/NodeSyncAppState.java @@ -0,0 +1,125 @@ +/* + * 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.scene; + +import com.jme3.app.Application; +import com.jme3.app.state.AbstractAppState; +import com.jme3.app.state.AppStateManager; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; + +/** + * + * @author normenhansen + */ +public class NodeSyncAppState extends AbstractAppState implements LookupListener { + + private final List newNodes = Collections.synchronizedList(new LinkedList()); + private final List oldNodes = Collections.synchronizedList(new LinkedList()); + private final Result nodeSelectionResult; + private AbstractSceneExplorerNode node; + private float timeStep = 1; + private float timer = 0; + + public NodeSyncAppState() { + nodeSelectionResult = Utilities.actionsGlobalContext().lookupResult(AbstractSceneExplorerNode.class); + } + + @Override + public void initialize(AppStateManager stateManager, Application app) { + super.initialize(stateManager, app); + nodeSelectionResult.addLookupListener(this); + } + + @Override + public void update(float tpf) { + super.update(tpf); + synchronized (newNodes) { + for (Iterator it = newNodes.iterator(); it.hasNext();) { + AbstractSceneExplorerNode abstractSceneExplorerNode = it.next(); + abstractSceneExplorerNode.syncSceneData(); + it.remove(); + } + } + timer += tpf; + if (timer > timeStep) { + timer = 0; + AbstractSceneExplorerNode node = this.node; + if (initialized && node != null) { + node.syncSceneData(); + } + } + synchronized (oldNodes) { + for (Iterator it = oldNodes.iterator(); it.hasNext();) { + AbstractSceneExplorerNode abstractSceneExplorerNode = it.next(); + abstractSceneExplorerNode.syncSceneData(); + it.remove(); + } + } + } + + public void resultChanged(LookupEvent ev) { + Collection collection = nodeSelectionResult.allInstances(); + AbstractSceneExplorerNode newNode = null; + for (Iterator it = collection.iterator(); it.hasNext();) { + Object object = it.next(); + if (object instanceof AbstractSceneExplorerNode) { + if (object != null) { + synchronized (newNodes) { + newNodes.add((AbstractSceneExplorerNode) object); + } + } + newNode = (AbstractSceneExplorerNode) object; + } + } + if (node != null) { + synchronized (oldNodes) { + oldNodes.add(node); + } + } + node = newNode; + } + + @Override + public void cleanup() { + nodeSelectionResult.removeLookupListener(this); + super.cleanup(); + } +} 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 b81903098..201559f34 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 @@ -116,6 +116,7 @@ public class SceneApplication extends Application implements LookupProvider { boolean useCanvas = false; private BulletAppState physicsState; private Thread thread; + private NodeSyncAppState nodeSync; private FakeApplication fakeApp; public SceneApplication() { @@ -140,6 +141,8 @@ public class SceneApplication extends Application implements LookupProvider { createCanvas(); startCanvas(true); } + nodeSync = new NodeSyncAppState(); + stateManager.attach(nodeSync); progressHandle.progress("initialize Base Application", 1); } catch (Exception e) { getProgressHandle().finish(); @@ -375,6 +378,7 @@ public class SceneApplication extends Application implements LookupProvider { } else { camController.disable(); } + //TODO: reuse fakeapp fakeApp = new FakeApplication(rootNode, guiNode, request.getManager(), cam); request.setFakeApp(fakeApp); enqueue(new Callable() { @@ -387,6 +391,13 @@ public class SceneApplication extends Application implements LookupProvider { StatusDisplayer.getDefault().setStatusText("could not load Spatial from request: " + getCurrentSceneRequest().getWindowTitle()); return null; } + //TODO: bit dangerous, setting rootNode late + // still it should only be accessed from the + // update loop and be set until then. + + if (model instanceof Node) { + fakeApp.setRootNode((Node) model); + } rootNode.attachChild(model); if (request.getToolNode() != null) { toolsNode.attachChild(request.getToolNode()); diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form index 2801b7a9e..a465d44e8 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form @@ -1,4 +1,4 @@ - +
@@ -40,6 +40,7 @@ + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java index 2b4dceb97..5d0d90834 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java @@ -118,6 +118,7 @@ public final class SceneExplorerTopComponent extends TopComponent implements Exp 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(SceneExplorerTopComponent.class, "SceneExplorerTopComponent.jButton1.text")); // NOI18N diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java index 952eae669..61b450213 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java @@ -31,18 +31,19 @@ */ package com.jme3.gde.core.sceneexplorer.nodes; -import com.jme3.gde.core.util.DynamicLookup; import com.jme3.gde.core.properties.SceneExplorerProperty; import com.jme3.gde.core.properties.ScenePropertyChangeListener; +import com.jme3.gde.core.util.DynamicLookup; import com.jme3.gde.core.util.PropertyUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import org.openide.loaders.DataObject; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.nodes.NodeAdapter; -import org.openide.nodes.NodeListener; import org.openide.nodes.Sheet; import org.openide.util.Exceptions; import org.openide.util.Lookup; @@ -60,6 +61,7 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements protected final InstanceContent lookupContents; protected boolean readOnly = false; protected DataObject dataObject; + private final List sceneProperties = Collections.synchronizedList(new LinkedList()); public AbstractSceneExplorerNode() { super(Children.LEAF, new DynamicLookup(new InstanceContent())); @@ -69,7 +71,7 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements public AbstractSceneExplorerNode(Children children, DataObject dataObject) { super(children, new ProxyLookup(dataObject.getLookup(), new DynamicLookup(new InstanceContent()))); this.dataObject = dataObject; - lookupContents = getLookup().lookup(DynamicLookup.class).getInstanceContent(); + lookupContents = getLookup().lookup(DynamicLookup.class).getInstanceContent(); } public AbstractSceneExplorerNode(DataObject dataObject) { @@ -106,9 +108,9 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements dataObject.setModified(true); } } - + /** - * returns the PropertySet with the given name (mostly Class.name) + * returns the PropertySet with the given name * @param name * @return The PropertySet or null if no PropertySet by that name exists */ @@ -167,8 +169,8 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements } return prop; } - - protected Property makeEmbedProperty(Object obj,Class objectClass, Class returntype, String method, String setter, String name) { + + protected Property makeEmbedProperty(Object obj, Class objectClass, Class returntype, String method, String setter, String name) { Property prop = null; try { if (readOnly) { @@ -184,7 +186,6 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements return prop; } - protected void createFields(Class c, Sheet.Set set, Object obj) throws SecurityException { for (Field field : c.getDeclaredFields()) { PropertyDescriptor prop = PropertyUtils.getPropertyDescriptor(c, field); @@ -194,9 +195,32 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements } } - public void propertyChange(final String name, final Object before, final Object after) { - fireSave(true); - firePropertyChange(name, before, after); + @Override + protected Sheet createSheet() { + return Sheet.createDefault(); + } + + public void syncSceneData() { + //TODO: precache structure to avoid locks? + for (PropertySet propertySet : getPropertySets()) { + for (Property property : propertySet.getProperties()) { + if(property instanceof SceneExplorerProperty){ + SceneExplorerProperty prop = (SceneExplorerProperty)property; + prop.syncValue(); + } + } + } + } + + public void propertyChange(final String type, final String name, final Object before, final Object after) { + if (SceneExplorerProperty.PROP_USER_CHANGE.equals(type)) { + fireSave(true); + firePropertyChange(name, before, after); + } else if (SceneExplorerProperty.PROP_SCENE_CHANGE.equals(type)) { + firePropertyChange(name, before, after); + } else if (SceneExplorerProperty.PROP_INIT_CHANGE.equals(type)) { + firePropertyChange(name, before, after); + } } public Class getExplorerNodeClass() { @@ -208,5 +232,4 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements public Node[] createNodes(Object key, DataObject dataObject, boolean readOnly) { return new Node[]{Node.EMPTY}; } - } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java index ac23e9e06..985c5f0d6 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java @@ -130,7 +130,6 @@ public class JmeGenericControl extends AbstractNode implements ScenePropertyChan final Spatial spat = getParentNode().getLookup().lookup(Spatial.class); try { SceneApplication.getApplication().enqueue(new Callable() { - public Void call() throws Exception { spat.removeControl(control); return null; @@ -161,7 +160,7 @@ public class JmeGenericControl extends AbstractNode implements ScenePropertyChan // if (readOnly) { // prop = new SceneExplorerProperty(control.getClass().cast(obj), returntype, method, null); // } else { - prop = new SceneExplorerProperty(control.getClass().cast(obj), returntype, method, setter, this); + prop = new SceneExplorerProperty(control.getClass().cast(obj), returntype, method, setter, this); // } prop.setName(name); @@ -180,8 +179,10 @@ public class JmeGenericControl extends AbstractNode implements ScenePropertyChan } } - public void propertyChange(String property, Object oldValue, Object newValue) { - dobject.setModified(true); + public void propertyChange(String type, String name, Object oldValue, Object newValue) { + if (type.equals("PROP_USER_CHANGE")) { + dobject.setModified(true); + } // throw new UnsupportedOperationException("Not supported yet."); } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java index bc64cb5ae..3a38a8155 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java @@ -41,7 +41,6 @@ import java.awt.Image; import java.io.IOException; import java.util.concurrent.Callable; import org.openide.loaders.DataObject; -import org.openide.nodes.AbstractNode; import org.openide.nodes.Sheet; import org.openide.util.ImageUtilities; @@ -144,8 +143,8 @@ public class JmeGeometry extends JmeSpatial implements MaterialChangeListener { } @Override - public void propertyChange(String name, final Object before, final Object after) { - super.propertyChange(name, before, after); + public void propertyChange(String type, String name, final Object before, final Object after) { + super.propertyChange(type, name, before, after); if (name.equals("Material")) { java.awt.EventQueue.invokeLater(new Runnable() { diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java index fdb482a1e..c91fd43bd 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java @@ -154,8 +154,8 @@ public class JmeParticleEmitter extends JmeGeometry { } @Override - public void propertyChange(String name, Object before, Object after) { - super.propertyChange(name, before, after); + public void propertyChange(String type, String name, Object before, Object after) { + super.propertyChange(type, name, before, after); if (!name.equals("Emit all particles")) { fireSave(true); firePropertyChange(name, before, after); diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java index b132b7dbf..a2b920677 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java @@ -294,7 +294,7 @@ public class JmeSpatial extends AbstractSceneExplorerNode { @Override protected Sheet createSheet() { - Sheet sheet = Sheet.createDefault(); + Sheet sheet = super.createSheet(); //TODO: multithreading.. but we only read Collection dataKeys = spatial.getUserDataKeys(); diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTrack.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTrack.java index a3c36645f..8836dbd53 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTrack.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTrack.java @@ -253,8 +253,8 @@ public class JmeTrack extends AbstractSceneExplorerNode { } @Override - public void propertyChange(String name, Object before, Object after) { - super.propertyChange(name, before, after); + public void propertyChange(String type, String name, Object before, Object after) { + super.propertyChange(type, name, before, after); setName(); } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form index 5ca6d5389..8101ad25a 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form @@ -1,4 +1,4 @@ - + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java index 419306d13..ce77d449e 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java @@ -37,11 +37,9 @@ */ package com.jme3.gde.core.sceneexplorer.nodes.actions; -import com.jme3.effect.influencers.ParticleInfluencer; import com.jme3.export.Savable; import com.jme3.gde.core.assets.ProjectAssetManager; import com.jme3.gde.core.properties.SceneExplorerProperty; -import com.jme3.gde.core.properties.ScenePropertyChangeListener; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.core.util.PropertyUtils; @@ -65,7 +63,7 @@ import org.openide.util.Exceptions; * * @author normenhansen */ -public class UserDataDialog extends javax.swing.JDialog implements ScenePropertyChangeListener { +public class UserDataDialog extends javax.swing.JDialog { JmeSpatial spat; boolean initialized = false; @@ -134,15 +132,11 @@ public class UserDataDialog extends javax.swing.JDialog implements SceneProperty } - public void propertyChange(String property, Object oldValue, Object newValue) { - //System.out.println(property + " changed"); - } - protected Property makeProperty(Object obj, Class returntype, String method, String setter, String name) { Property prop = null; try { - prop = new SceneExplorerProperty(obj.getClass().cast(obj), returntype, method, setter, this); + prop = new SceneExplorerProperty(obj.getClass().cast(obj), returntype, method, setter); prop.setName(name); @@ -408,4 +402,5 @@ private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FI private javax.swing.JTextField jTextField1; private javax.swing.JTextField jTextField2; // End of variables declaration//GEN-END:variables + } 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 fa6a434b2..99df5767d 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 @@ -35,7 +35,6 @@ import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import org.openide.util.Exceptions; /** * @@ -45,18 +44,6 @@ 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()));