- MAJOR overhaul of the SceneExplorer node updates, updates are no longer blocking or reading from another thread
- Some issues with enums still
- simplified, improved and more versatile SceneExplorerProperty class


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10083 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 12 years ago
parent f77b953fff
commit 81a08d6c49
  1. 21
      sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateNode.java
  2. 2
      sdk/jme3-core/src/com/jme3/gde/core/filters/actions/EnableFiterAction.java
  3. 18
      sdk/jme3-core/src/com/jme3/gde/core/navigator/DataScanner.java
  4. 43
      sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneChangeListener.java
  5. 52
      sdk/jme3-core/src/com/jme3/gde/core/navigator/SceneProperty.java
  6. 2
      sdk/jme3-core/src/com/jme3/gde/core/properties/AudioTrackProperty.java
  7. 2
      sdk/jme3-core/src/com/jme3/gde/core/properties/EffectTrackEmitterProperty.java
  8. 2
      sdk/jme3-core/src/com/jme3/gde/core/properties/ParticleInfluencerProperty.java
  9. 224
      sdk/jme3-core/src/com/jme3/gde/core/properties/SceneExplorerProperty.java
  10. 2
      sdk/jme3-core/src/com/jme3/gde/core/properties/ScenePropertyChangeListener.java
  11. 2
      sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java
  12. 11
      sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java
  13. 125
      sdk/jme3-core/src/com/jme3/gde/core/scene/NodeSyncAppState.java
  14. 11
      sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java
  15. 3
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form
  16. 1
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java
  17. 39
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java
  18. 5
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java
  19. 5
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java
  20. 4
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java
  21. 2
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java
  22. 4
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTrack.java
  23. 2
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form
  24. 11
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java
  25. 13
      sdk/jme3-core/src/com/jme3/gde/core/util/PropertyUtils.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);
}
}
}

@ -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;
}

@ -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);
}
}

@ -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);
}

@ -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<T> extends PropertySupport.Reflection<T> {
Lookup lookup;
Object _originalValue;
public SceneProperty(Lookup lookup, Object instance, Class<T> valueType, String property) throws NoSuchMethodException {
super(instance, valueType, property);
DataScanner scanner = lookup.lookup(DataScanner.class);
}
}

@ -85,7 +85,7 @@ public class AudioTrackProperty extends PropertySupport.ReadWrite<AudioNode> {
private void notifyListeners(Object before, Object after) {
for (Iterator<ScenePropertyChangeListener> it = listeners.iterator(); it.hasNext();) {
ScenePropertyChangeListener propertyChangeListener = it.next();
propertyChangeListener.propertyChange(getName(), before, after);
propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after);
}
}

@ -85,7 +85,7 @@ public class EffectTrackEmitterProperty extends PropertySupport.ReadWrite<Partic
private void notifyListeners(Object before, Object after) {
for (Iterator<ScenePropertyChangeListener> it = listeners.iterator(); it.hasNext();) {
ScenePropertyChangeListener propertyChangeListener = it.next();
propertyChangeListener.propertyChange(getName(), before, after);
propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after);
}
}

@ -88,7 +88,7 @@ public class ParticleInfluencerProperty extends PropertySupport.ReadWrite<Partic
private void notifyListeners(Object before, Object after) {
for (Iterator<ScenePropertyChangeListener> it = listeners.iterator(); it.hasNext();) {
ScenePropertyChangeListener propertyChangeListener = it.next();
propertyChangeListener.propertyChange(getName(), before, after);
propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after);
}
}

@ -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<T> extends PropertySupport.Reflection<T> {
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<ScenePropertyChangeListener> listeners = new LinkedList<ScenePropertyChangeListener>();
public SceneExplorerProperty(T instance, Class valueType, String getter, String setter) throws NoSuchMethodException {
@ -67,7 +79,14 @@ public class SceneExplorerProperty<T> extends PropertySupport.Reflection<T> {
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<T> extends PropertySupport.Reflection<T> {
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<T>() {
//
// 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<Void>() {
public Void call() throws Exception {
setSuperValue(sceneObject);
return null;
}
});
}
});
}
private boolean isPrimitive(Object obj, String getter) {
try {
return super.getValue();
Class objClass = obj.getClass().getMethod(getter).getReturnType();
if (objClass.isPrimitive()) {
return true;
}
} catch (NoSuchMethodException ex) {
} catch (SecurityException ex) {
Exceptions.printStackTrace(ex);
}
return false;
}
private boolean canClone(Object obj, String getter) {
try {
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;
}
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;
}
}
} 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);
}
return null;
}
@Override
public void setValue(final T val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
} else if (instantiable) {
try {
notifyListeners(getSuperValue(), val);
SceneApplication.getApplication().enqueue(new Callable<Void>() {
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;
}
public Void call() throws Exception {
setSuperValue(val);
return null;
private void setSuperValue(T val) {
setSuperValue(val, true);
}
}).get();
} catch (InterruptedException ex) {
private T getSuperValue() {
try {
return super.getValue();
} catch (IllegalAccessException ex) {
Exceptions.printStackTrace(ex);
} catch (IllegalArgumentException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException 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<T> extends PropertySupport.Reflection<T> {
}
}
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<T> extends PropertySupport.Reflection<T> {
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<T> extends PropertySupport.Reflection<T> {
}
public void addPropertyChangeListener(ScenePropertyChangeListener listener) {
if (listener != null) {
listeners.add(listener);
}
}
public void removePropertyChangeListener(ScenePropertyChangeListener listener) {
if (listener != null) {
listeners.remove(listener);
}
}
private void notifyListeners(Object before, Object after) {
private void notifyListeners(final String type, final Object before, final Object after) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
for (Iterator<ScenePropertyChangeListener> it = listeners.iterator(); it.hasNext();) {
ScenePropertyChangeListener propertyChangeListener = it.next();
propertyChangeListener.propertyChange(getName(), before, after);
propertyChangeListener.propertyChange(type, getName(), before, after);
}
}
});
}
}

@ -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);
}

@ -159,7 +159,7 @@ public class UserDataProperty extends PropertySupport.ReadWrite<String> {
private void notifyListeners(Object before, Object after) {
for (Iterator<ScenePropertyChangeListener> it = listeners.iterator(); it.hasNext();) {
ScenePropertyChangeListener propertyChangeListener = it.next();
propertyChangeListener.propertyChange(getName(), before, after);
propertyChangeListener.propertyChange("PROP_USER_CHANGE", getName(), before, after);
}
}
}

@ -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();
}

@ -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<AbstractSceneExplorerNode> newNodes = Collections.synchronizedList(new LinkedList<AbstractSceneExplorerNode>());
private final List<AbstractSceneExplorerNode> oldNodes = Collections.synchronizedList(new LinkedList<AbstractSceneExplorerNode>());
private final Result<AbstractSceneExplorerNode> 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<AbstractSceneExplorerNode> 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<AbstractSceneExplorerNode> 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();
}
}

@ -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());

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
@ -40,6 +40,7 @@
</Container>
<Container class="javax.swing.JToolBar" name="jToolBar1">
<Properties>
<Property name="floatable" type="boolean" value="false"/>
<Property name="rollover" type="boolean" value="true"/>
</Properties>

@ -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

@ -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<Property> sceneProperties = Collections.synchronizedList(new LinkedList<Property>());
public AbstractSceneExplorerNode() {
super(Children.LEAF, new DynamicLookup(new InstanceContent()));
@ -108,7 +110,7 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
}
/**
* 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
*/
@ -168,7 +170,7 @@ 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) {
@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};
}
}

@ -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<Void>() {
public Void call() throws Exception {
spat.removeControl(control);
return null;
@ -180,8 +179,10 @@ public class JmeGenericControl extends AbstractNode implements ScenePropertyChan
}
}
public void propertyChange(String property, Object oldValue, Object newValue) {
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.");
}
}

@ -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() {

@ -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);

@ -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<String> dataKeys = spatial.getUserDataKeys();

@ -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();
}

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<NonVisualComponents>

@ -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
}

@ -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()));

Loading…
Cancel
Save