1 /*******************************************************************************
\r
2 * Copyright (c) 2007- VTT Technical Research Centre of Finland.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.proconf.g3d.base;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Collection;
\r
15 import java.util.HashMap;
\r
16 import java.util.HashSet;
\r
17 import java.util.List;
\r
18 import java.util.Queue;
\r
19 import java.util.Set;
\r
20 import java.util.concurrent.ConcurrentLinkedQueue;
\r
22 import org.simantics.db.AbstractQuery;
\r
23 import org.simantics.db.Graph;
\r
24 import org.simantics.db.GraphRequestAdapter;
\r
25 import org.simantics.db.GraphRequestStatus;
\r
26 import org.simantics.db.Resource;
\r
27 import org.simantics.db.Session;
\r
28 import org.simantics.db.queries.IGraphQuery;
\r
29 import org.simantics.db.queries.IQuery;
\r
30 import org.simantics.db.queries.IQueryListener;
\r
31 import org.simantics.db.utils.transaction.MergingTransactionRunner;
\r
32 import org.simantics.layer0.utils.EntityFactory;
\r
33 import org.simantics.layer0.utils.IEntity;
\r
34 import org.simantics.layer0.utils.Property;
\r
35 import org.simantics.proconf.g3d.Resources;
\r
36 import org.simantics.proconf.g3d.scenegraph.IGeometryNode;
\r
37 import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;
\r
38 import org.simantics.proconf.g3d.scenegraph.RootGraphicsNode;
\r
39 import org.simantics.proconf.g3d.stubs.G3DNode;
\r
40 import org.simantics.utils.ui.ErrorLogger;
\r
41 import org.simantics.utils.datastructures.BijectionMap;
\r
43 import com.jme.scene.Node;
\r
47 * Scene-graph adapter :
\r
48 * 1. Adapts graph change events into changes in actual scene-graph nodes.
\r
49 * 2. Handles instantiating and disposing of Scene-graph nodes.
\r
52 * @author Marko Luukkainen
\r
55 public abstract class ScenegraphAdapterImpl implements ScenegraphAdapter {
\r
57 protected static boolean DEBUG = false;
\r
59 private RootGraphicsNode root;
\r
60 private HashMap<Resource,ScenegraphQuery> scenegraphQueries = new HashMap<Resource, ScenegraphQuery>();
\r
61 private HashMap<Resource,NodePropertyQuery> propertyQueries = new HashMap<Resource, NodePropertyQuery>();
\r
62 private HashMap<Resource,NodeTransformationQuery> transformationQueries = new HashMap<Resource, NodeTransformationQuery>();
\r
63 private HashMap<Resource, IGraphicsNode> abstractGraphicsNodes = new HashMap<Resource, IGraphicsNode>();
\r
64 protected Queue<IGeometryNode> geometryUpdates = new ConcurrentLinkedQueue<IGeometryNode>();
\r
66 private BijectionMap<Resource, String> nameMap = new BijectionMap<Resource, String>();
\r
68 protected JmeRenderingComponent component;
\r
70 protected boolean viewChanged = false;
\r
72 protected Session session;
\r
74 private MergingTransactionRunner transactionRunner;
\r
76 public ScenegraphAdapterImpl(Session session, JmeRenderingComponent component) {
\r
77 this.component = component;
\r
78 this.session = session;
\r
79 transactionRunner = new MergingTransactionRunner(session,true);
\r
84 public JmeRenderingComponent getRenderingComponent() {
\r
89 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#setRootNode(fi.vtt.simantics.g3d.stubs.G3DNode)
\r
91 public void setRootNode(G3DNode rootNode) {
\r
92 addSubnodeListener(rootNode);
\r
93 root = new RootGraphicsNode(component,rootNode.getResource());
\r
94 abstractGraphicsNodes.put(rootNode.getResource(),root);
\r
95 G3DTools.reloadCache(rootNode.getGraph(),root.getResource());
\r
96 addRootPropertyListener(rootNode.getGraph());
\r
100 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#needsUpdateGeometry()
\r
102 public boolean needsUpdateGeometry() {
\r
103 return geometryUpdates.size() > 0;
\r
107 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.g3d.scenegraph.IGeometryNode)
\r
109 public void updateGeometry(IGeometryNode node) {
\r
110 geometryUpdates.add(node);
\r
114 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.db.connection.Resource)
\r
116 public void updateGeometry(Resource nodeResource) {
\r
117 geometryUpdates.add((IGeometryNode)abstractGraphicsNodes.get(nodeResource));
\r
122 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.db.connection.Graph)
\r
124 public synchronized void updateGeometry(Graph graph) {
\r
125 if (geometryUpdates.size() > 0) {
\r
126 for (IGeometryNode n : geometryUpdates) {
\r
128 n.updateGeometry(graph);
\r
129 if (DEBUG) System.out.println("ScenegraphAdapterImpl: geometryUpdated " + n.getResource());
\r
130 } catch (Exception e) {
\r
131 ErrorLogger.defaultLogError("Failed to update geometry of node" + n.getResource(), e);
\r
134 geometryUpdates.clear();
\r
135 viewChanged = true;
\r
136 //if (DEBUG) System.out.println("ScenegraphAdapterImpl: geometryUpdated");
\r
141 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodes()
\r
143 public Collection<IGraphicsNode> getNodes() {
\r
144 return abstractGraphicsNodes.values();
\r
148 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNode(fi.vtt.simantics.db.connection.Resource)
\r
150 public IGraphicsNode getNode(Resource resource) {
\r
151 return abstractGraphicsNodes.get(resource);
\r
155 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRootNode()
\r
157 public IGraphicsNode getRootNode() {
\r
158 return getNode(getRootResource());
\r
162 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNode(fi.vtt.simantics.layer0.utils.IEntity)
\r
164 public IGraphicsNode getNode(IEntity IEntity) {
\r
165 return abstractGraphicsNodes.get(IEntity.getResource());
\r
169 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodeResource(java.lang.String)
\r
171 public Resource getNodeResource(String uid) {
\r
172 return nameMap.getLeft(uid);
\r
176 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodeUID(fi.vtt.simantics.db.connection.Resource)
\r
178 public String getNodeUID(Resource nodeResource) {
\r
179 String name = nameMap.getRight(nodeResource);
\r
180 if (name == null) {
\r
181 //name = UUID.randomUUID().toString();
\r
182 name = Long.toString(nodeResource.getResourceId());
\r
183 nameMap.map(nodeResource, name);
\r
189 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#hasNode(fi.vtt.simantics.db.connection.Resource)
\r
191 public boolean hasNode(Resource resource) {
\r
192 return abstractGraphicsNodes.containsKey(resource);
\r
196 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRootResource()
\r
198 public Resource getRootResource() {
\r
201 return root.getResource();
\r
205 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRoot()
\r
207 public Node getRoot() {
\r
208 return root.getGroup();
\r
212 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#dispose()
\r
214 public void dispose() {
\r
215 Set<Resource> shapes = new HashSet<Resource>(abstractGraphicsNodes.keySet());
\r
216 for (Resource r : shapes) {
\r
222 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#isChanged()
\r
224 public boolean isChanged() {
\r
225 return viewChanged;
\r
229 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#setChanged(boolean)
\r
231 public void setChanged(boolean changed) {
\r
232 viewChanged = changed;
\r
237 * Instantiates Listener that listens hierarchy changes in the node (subnode
\r
238 * added and/or removed)
\r
243 protected abstract ScenegraphQuery newSubnodeListener(G3DNode node);
\r
245 protected void addSubnodeListener(G3DNode node) {
\r
246 if (DEBUG) System.out.println("ScenegraphAdapter.addSubnodeListener( " + node.getResource() + " )");
\r
247 ScenegraphQuery q = newSubnodeListener(node);
\r
248 node.getGraph().performQuery(q);
\r
249 scenegraphQueries.put(node.getResource(), q);
\r
253 * Returns propertyQuery for a single scene-graph node.
\r
257 protected abstract NodePropertyQuery newPropertyListener(G3DNode node);
\r
260 * Returns transformationQuery for a single scene-graph node
\r
264 protected abstract NodeTransformationQuery newTransformationListener(G3DNode node);
\r
267 * Returns propertyQuery for the root node.
\r
268 * May return null if root node has no interesting properties.
\r
270 * Potentially root node could contain lighting settings, and so on...
\r
275 protected abstract NodePropertyQuery newRootPropertyListener(G3DNode root);
\r
277 protected void addPropertyListener(G3DNode node) {
\r
278 if (DEBUG) System.out.println("ScenegraphAdapter.addPropertyListener( " + node.getResource() + " )");
\r
279 NodePropertyQuery q = newPropertyListener(node);
\r
280 node.getGraph().performQuery(q);
\r
281 propertyQueries.put(node.getResource(),q);
\r
285 protected void addTransformationListener(G3DNode node) {
\r
286 if (DEBUG) System.out.println("ScenegraphAdapter.addPropertyListener( " + node.getResource() + " )");
\r
287 NodeTransformationQuery q = newTransformationListener(node);
\r
288 node.getGraph().performQuery(q);
\r
289 transformationQueries.put(node.getResource(),q);
\r
292 protected void addRootPropertyListener(Graph g) {
\r
293 G3DNode node = root.getG3DNode(g);
\r
294 if (DEBUG) System.out.println("ScenegraphAdapter.addRootPropertyListener( " + node.getResource() + " )");
\r
295 NodePropertyQuery q = newRootPropertyListener(node);
\r
298 node.getGraph().performQuery(q);
\r
299 propertyQueries.put(node.getResource(),q);
\r
303 * Instantiates a new scene-graph node
\r
305 * @param parent the parent of the new node.
\r
306 * @param node the new node.
\r
309 protected abstract IGraphicsNode instantiateNode(IGraphicsNode parent, G3DNode node);
\r
313 * Adds node into scene-graph
\r
314 * @param parent the parent of the node
\r
315 * @param r resource of the node
\r
316 * @return created scene-graph node
\r
318 protected IGraphicsNode addNode(IEntity parent, IEntity r) {
\r
319 if (!r.isInstanceOf(Resources.g3dResource.G3DNode)) {
\r
320 ErrorLogger.defaultLogError("Trying to add node into scenegraph that is not instance of G3DNode " + r,new Exception("ASSERT!"));
\r
323 if (parent.equals(r)) {
\r
324 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") adding node to itself?!");
\r
325 ErrorLogger.defaultLogError("Adding scnegraphnode " + r.getResource().getResourceId() + " to itself!", new Exception("ASSERT!"));
\r
326 return abstractGraphicsNodes.get(r);
\r
329 if (abstractGraphicsNodes.containsKey(r)) {
\r
331 IGraphicsNode inView = abstractGraphicsNodes.get(r);
\r
332 if (inView.getParent() == null) {
\r
333 //if graphicsNode has no parent it must be the root node
\r
334 ErrorLogger.defaultLogError("Trying to add rootnode into scenegraph " + r, null);
\r
337 if (parent.equals(inView.getParent().getResource())) {
\r
338 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") already in view");
\r
341 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") already in view, but has different parent, current parent is ("+inView.getParent().getResource().getResourceId()+") and node is added to ("+parent+") -> removing from old parent and inserting to new");
\r
342 removeNode(inView.getParent().getResource(),r.getResource());
\r
346 G3DNode node = new G3DNode(r);
\r
349 IGraphicsNode parentNode = abstractGraphicsNodes.get(parent);
\r
350 if (parentNode == null) {
\r
351 if (DEBUG) System.out.println("No graphicsnode for (" + parent.getResource().getResourceId() + ")");
\r
354 mo = instantiateNode(parentNode, node);
\r
356 ErrorLogger.defaultLogError("Could not instantiate scenegraph node for " + r.getResource().getResourceId(), null);
\r
359 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") added to parent (" + parent.getResource().getResourceId() + ") " + mo.getClass());
\r
361 addSubnodeListener(node);
\r
362 addPropertyListener(node);
\r
363 addTransformationListener(node);
\r
365 abstractGraphicsNodes.put(r.getResource(), mo);
\r
369 // FIXME : this is a hack to fix transformations of instantiated nodes
\r
370 // if (graph.getCurrentTransaction() != null) {
\r
372 // G3DTools.propagateWorldTransformChange(parentNode
\r
374 // graph.commitChanges(CommitMessage.CHANGE_MESSAGE);
\r
375 // // G3DNodeTools.transformationUpdate(graph, r.getId());
\r
376 // } catch (Exception e) {
\r
377 // ErrorLogger.defaultLogError(e);
\r
386 * This is used only when view is disposed!
\r
390 private void removeNode(Resource r) {
\r
391 NodeTransformationQuery tq = transformationQueries.get(r);
\r
392 //StructuralChangeMonitor monitor = monitors.getLeft(r);
\r
394 if (abstractGraphicsNodes.containsKey(r)) {
\r
395 // root node has no monitor (no transformation to monitor)
\r
396 //System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") node has no monitor, but has node in scenegraph");
\r
397 abstractGraphicsNodes.remove(r);
\r
398 if(scenegraphQueries.get(r) != null) {
\r
399 scenegraphQueries.get(r).dispose();
\r
400 scenegraphQueries.remove(r);
\r
403 //System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") not in view");
\r
407 // remove listeners
\r
408 propertyQueries.remove(r).dispose();
\r
409 transformationQueries.remove(r).dispose();
\r
410 scenegraphQueries.get(r);
\r
411 scenegraphQueries.remove(r).dispose();
\r
413 IGraphicsNode node = abstractGraphicsNodes.get(r);
\r
414 ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>(node.getChildren());
\r
415 for (IGraphicsNode n : children) {
\r
416 removeNode(n.getResource());
\r
419 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") removed");
\r
422 abstractGraphicsNodes.remove(r);
\r
427 * Removes a scene-graph node.
\r
428 * @param parent the parent of the node
\r
429 * @param r the node.
\r
431 protected void removeNode(Resource parent,Resource r) {
\r
432 NodePropertyQuery q = propertyQueries.get(r);
\r
434 assert(!abstractGraphicsNodes.containsKey(r));
\r
435 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") not in view");
\r
439 IGraphicsNode node = abstractGraphicsNodes.get(r);
\r
440 Resource rParent = node.getParent().getResource();
\r
441 if (!rParent.equals(parent)) {
\r
442 // this event may happen, depending of the order of events in transaction
\r
443 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") trying to remove from wrong parent current ("+rParent+") remove parentnode null("+parent+")");
\r
446 // removing listeners
\r
447 propertyQueries.remove(r).dispose();
\r
448 transformationQueries.remove(r).dispose();
\r
449 scenegraphQueries.remove(r).dispose();
\r
450 // remove node's children
\r
451 ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>(node.getChildren());
\r
452 for (IGraphicsNode n : children) {
\r
453 removeNode(r,n.getResource());
\r
455 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") from ("+parent+")");
\r
458 abstractGraphicsNodes.remove(r);
\r
459 if (geometryUpdates.contains(node)) {
\r
460 geometryUpdates.remove(node);
\r
467 * Query that tracks changes in resources.
\r
469 * @author Marko Luukkainen
\r
472 public abstract class NodeQuery extends AbstractQuery<Object>{
\r
473 protected Resource nodeResource;
\r
474 private boolean disposed = false;
\r
476 private IQueryListener listener = null;
\r
478 public NodeQuery(Resource r) {
\r
479 this.nodeResource = r;
\r
482 protected abstract Object compute2(Graph graph);
\r
485 public Object performQuery(Graph graph) {
\r
486 if (disposed) return null;
\r
487 return compute2(graph);
\r
492 * @param oldResult result of the query before the change.
\r
493 * @param newResult result of the query after the change.
\r
495 public abstract boolean updated(Graph graph, Object oldResult, Object newResult);
\r
498 public int getType() {
\r
499 return IQuery.SCHEDULED_UPDATE;
\r
503 public void resultChangedRaw(final Object oldResult, final Object newResult) {
\r
505 throw new RuntimeException("Updating disposed query"); //return;
\r
506 transactionRunner.run(new GraphRequestAdapter() {
\r
508 public GraphRequestStatus perform(Graph g) throws Exception {
\r
510 if (oldResult == IQueryListener.NO_VALUE)
\r
511 updated(g, null, newResult);
\r
513 updated(g, oldResult, newResult);
\r
515 return GraphRequestStatus.transactionComplete();
\r
523 public boolean equalsQuery(IGraphQuery<Object> other) {
\r
524 return nodeResource.equals(((NodeQuery)other).nodeResource);
\r
528 final public int hash() {
\r
529 return nodeResource.hashCode();
\r
534 * Disposes the query
\r
536 public void dispose() {
\r
538 if (DEBUG) System.out.println("NodeQuery " + nodeResource + " disposed()" + " " + this.getClass());
\r
542 public boolean isDisposed() {
\r
546 // without separate listener, this query would work only once
\r
548 public IQueryListener getListener() {
\r
549 if (listener == null) {
\r
550 listener = new IQueryListener() {
\r
552 public boolean isDisposed() {
\r
553 return NodeQuery.this.disposed;
\r
557 public void resultChangedRaw(Object oldResult, Object newResult) {
\r
558 NodeQuery.this.resultChangedRaw(oldResult, newResult);
\r
568 * Query that tracks changes in scene-graph structure (parent/child relationships).
\r
570 * @author Marko Luukkainen
\r
573 public abstract class ScenegraphQuery extends NodeQuery {
\r
575 List<Resource> added = new ArrayList<Resource>();
\r
576 List<Resource> removed = new ArrayList<Resource>();
\r
578 private boolean initialized;
\r
580 public ScenegraphQuery(Resource nodeResource) {
\r
581 super(nodeResource);
\r
582 initialized = false;
\r
583 if(DEBUG)System.out.println("ScenegraphQuery created for " + nodeResource);
\r
587 public List<Resource> compute2(Graph g) {
\r
588 IEntity node = EntityFactory.create(g,nodeResource);
\r
589 Collection<IEntity> children = node.getRelatedObjects(Resources.g3dResource.HasChild);
\r
590 List<Resource> list = new ArrayList<Resource>();
\r
591 for (IEntity n: children)
\r
592 list.add(n.getResource());
\r
593 if (DEBUG) System.out.println("ScenegraphQuery " + nodeResource + " has " + list.size() + " children");
\r
597 @SuppressWarnings("unchecked")
\r
599 public boolean updated(Graph graph, Object oldResult, Object newResult) {
\r
600 List<Resource> oldChildren;
\r
601 if (oldResult != null)
\r
602 oldChildren = (List<Resource>)oldResult;
\r
604 oldChildren = new ArrayList<Resource>();
\r
605 List<Resource> newChildren = (List<Resource>)newResult;
\r
607 if (DEBUG) System.out.println("ScenegraphQuery " + nodeResource + " updated: had " + oldChildren.size() + " children, but now has " + newChildren.size() + " children");
\r
611 for (Resource r : oldChildren)
\r
612 if (!newChildren.contains(r))
\r
614 for (Resource r : newChildren)
\r
615 if (!oldChildren.contains(r))
\r
617 for (Resource r : removed) {
\r
619 System.out.println("ScenegraphQuery " + nodeResource
\r
620 + " removed " + r);
\r
621 removeNode(nodeResource, r);
\r
623 if (added.size() > 0) {
\r
624 G3DNode parent = new G3DNode(graph, nodeResource);
\r
628 * G3DTools.propagateTransformChange(parent); } catch
\r
629 * (Exception e) { ErrorLogger.defaultLogError(e); }
\r
631 for (Resource r : added) {
\r
632 IEntity e = EntityFactory.create(graph, r);
\r
633 G3DTools.propagateLocalTransformChange(parent, e);
\r
634 IGraphicsNode n = addNode(parent, e);
\r
635 shapeAdded(graph, n);
\r
638 return (added.size() > 0 || removed.size() > 0);
\r
640 // when query is run for the first time, we can assume that transformations are correct.
\r
641 initialized = true;
\r
642 for (Resource r : newChildren)
\r
644 if (added.size() > 0) {
\r
645 G3DNode parent = new G3DNode(graph, nodeResource);
\r
646 for (Resource r : added) {
\r
647 IEntity e = EntityFactory.create(graph, r);
\r
648 IGraphicsNode n = addNode(parent, e);
\r
649 shapeAdded(graph, n);
\r
660 * This method is run after a node is added to scene-graph.
\r
662 * @param graph Graph of the current transaction.
\r
663 * @param node the newly added scene-graph node
\r
665 public abstract void shapeAdded(Graph graph,IGraphicsNode node);
\r
668 // public void attach() {
\r
669 // scenegraphQueries.put(nodeResource, this);
\r
676 * Tracks changes in scene-graph nodes' properties
\r
678 * @author Marko Luukkainen
\r
681 public abstract class NodePropertyQuery extends NodeQuery {
\r
683 private boolean initialized;
\r
685 public NodePropertyQuery(Resource nodeResource) {
\r
686 super(nodeResource);
\r
687 initialized = false;
\r
688 if(DEBUG)System.out.println("NodePropertyQuery created for " + nodeResource);
\r
692 public List<Object> compute2(Graph g) {
\r
693 IEntity t = EntityFactory.create(g,nodeResource);
\r
695 Collection<Property> properties = t.getRelatedProperties(Resources.g3dResource.HasNonTransformation);
\r
696 List<Object> propertyValues = new ArrayList<Object>();
\r
697 p(properties,propertyValues);
\r
699 return propertyValues;
\r
702 private void p(Collection<Property> properties, List<Object> propertyValues) {
\r
703 for (Property p : properties) {
\r
704 Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);
\r
705 if (subProperties.size() != 0) {
\r
706 p(subProperties,propertyValues);
\r
709 propertyValues.add(p.getValue());
\r
715 public boolean updated(Graph graph, Object oldResult, Object newResult) {
\r
717 if (DEBUG) System.out.println("NodePropertyQuery changed " + nodeResource + " " + abstractGraphicsNodes.size());
\r
718 IGraphicsNode mo = abstractGraphicsNodes.get(nodeResource);
\r
720 if (DEBUG) System.out.println("NodePropertyQuery invalid change " + nodeResource + " " + abstractGraphicsNodes.size());
\r
721 ErrorLogger.defaultLogError("Got update from resource " + nodeResource + " but its not part of the scenegraph", null);
\r
725 shapeUpdated(graph,mo);
\r
728 initialized = true;
\r
735 * This method is run when a scene-graph node is changed.
\r
737 * @param shape the changed node
\r
739 public abstract void shapeUpdated(Graph graph,IGraphicsNode shape);
\r
742 // public void attach() {
\r
743 // propertyQueries.put(nodeResource, this);
\r
748 public abstract class NodeTransformationQuery extends NodeQuery {
\r
750 private boolean initialized;
\r
752 public NodeTransformationQuery(Resource nodeResource) {
\r
753 super(nodeResource);
\r
754 initialized = false;
\r
755 if(DEBUG)System.out.println("NodeTransformationQuery created for " + nodeResource);
\r
759 public List<Object> compute2(Graph g) {
\r
760 IEntity t = EntityFactory.create(g,nodeResource);
\r
762 Collection<Property> properties = t.getRelatedProperties(Resources.g3dResource.HasTransformation);
\r
764 List<Object> propertyValues = new ArrayList<Object>();
\r
765 p(properties,propertyValues);
\r
766 return propertyValues;
\r
770 private void p(Collection<Property> properties, List<Object> propertyValues) {
\r
771 for (Property p : properties) {
\r
772 Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);
\r
773 if (subProperties.size() != 0) {
\r
774 p(subProperties,propertyValues);
\r
777 propertyValues.add(p.getValue());
\r
783 public boolean updated(Graph graph,Object oldResult, Object newResult) {
\r
785 if (DEBUG) System.out.println("NodeTransformationQuery changed " + nodeResource + " " + abstractGraphicsNodes.size());
\r
787 G3DTools.transformationUpdate(graph, nodeResource);
\r
789 IGraphicsNode mo = abstractGraphicsNodes.get(nodeResource);
\r
791 if (DEBUG) System.out.println("NodeTransformationQuery invalid change " + nodeResource + " " + abstractGraphicsNodes.size());
\r
792 ErrorLogger.defaultLogError("Got update from resource " + nodeResource + " but its not part of the scenegraph", null);
\r
796 shapeUpdated(graph,mo);
\r
799 initialized = true;
\r
806 * This method is run when a scene-graph node is changed.
\r
808 * @param shape the changed node
\r
810 public abstract void shapeUpdated(Graph graph,IGraphicsNode shape);
\r
813 // public void attach() {
\r
814 // transformationQueries.put(nodeResource, this);
\r