1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\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.Stack;
\r
21 import java.util.concurrent.ConcurrentLinkedQueue;
\r
23 import org.simantics.db.AbstractQuery;
\r
24 import org.simantics.db.Graph;
\r
25 import org.simantics.db.GraphRequestAdapter;
\r
26 import org.simantics.db.GraphRequestStatus;
\r
27 import org.simantics.db.Resource;
\r
28 import org.simantics.db.Session;
\r
29 import org.simantics.db.queries.IGraphQuery;
\r
30 import org.simantics.db.queries.IQuery;
\r
31 import org.simantics.db.queries.IQueryListener;
\r
32 import org.simantics.db.utils.transaction.MergingTransactionRunner;
\r
33 import org.simantics.layer0.utils.EntityFactory;
\r
34 import org.simantics.layer0.utils.IEntity;
\r
35 import org.simantics.layer0.utils.Property;
\r
36 import org.simantics.proconf.g3d.Resources;
\r
37 import org.simantics.proconf.g3d.scenegraph.IGeometryNode;
\r
38 import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;
\r
39 import org.simantics.proconf.g3d.scenegraph.RootGraphicsNode;
\r
40 import org.simantics.proconf.g3d.stubs.G3DNode;
\r
41 import org.simantics.utils.ui.ErrorLogger;
\r
42 import org.simantics.utils.datastructures.BijectionMap;
\r
44 import com.jme.scene.Node;
\r
48 * Scene-graph adapter :
\r
49 * 1. Adapts graph change events into changes in actual scene-graph nodes.
\r
50 * 2. Handles instantiating and disposing of Scene-graph nodes.
\r
53 * @author Marko Luukkainen
\r
56 public abstract class ScenegraphAdapterImpl implements ScenegraphAdapter {
\r
58 protected static boolean DEBUG = false;
\r
60 private RootGraphicsNode root;
\r
61 private HashMap<Resource,ScenegraphQuery> scenegraphQueries = new HashMap<Resource, ScenegraphQuery>();
\r
62 private HashMap<Resource,NodePropertyQuery> propertyQueries = new HashMap<Resource, NodePropertyQuery>();
\r
63 private HashMap<Resource,NodeTransformationQuery> transformationQueries = new HashMap<Resource, NodeTransformationQuery>();
\r
64 private HashMap<Resource, IGraphicsNode> abstractGraphicsNodes = new HashMap<Resource, IGraphicsNode>();
\r
65 protected Queue<IGeometryNode> geometryUpdates = new ConcurrentLinkedQueue<IGeometryNode>();
\r
67 private BijectionMap<Resource, String> nameMap = new BijectionMap<Resource, String>();
\r
69 protected JmeRenderingComponent component;
\r
71 protected boolean viewChanged = false;
\r
73 protected Session session;
\r
75 private MergingTransactionRunner transactionRunner;
\r
77 public ScenegraphAdapterImpl(Session session, JmeRenderingComponent component) {
\r
78 this.component = component;
\r
79 this.session = session;
\r
80 transactionRunner = new MergingTransactionRunner(session,true);
\r
85 public JmeRenderingComponent getRenderingComponent() {
\r
90 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#setRootNode(fi.vtt.simantics.g3d.stubs.G3DNode)
\r
92 public void setRootNode(G3DNode rootNode) {
\r
93 addSubnodeListener(rootNode);
\r
94 root = new RootGraphicsNode(component,rootNode.getResource());
\r
95 abstractGraphicsNodes.put(rootNode.getResource(),root);
\r
96 G3DTools.reloadCache(rootNode.getGraph(),root.getResource());
\r
97 addRootPropertyListener(rootNode.getGraph());
\r
101 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#needsUpdateGeometry()
\r
103 public boolean needsUpdateGeometry() {
\r
104 return geometryUpdates.size() > 0;
\r
108 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.g3d.scenegraph.IGeometryNode)
\r
110 public void updateGeometry(IGeometryNode node) {
\r
111 geometryUpdates.add(node);
\r
115 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.db.connection.Resource)
\r
117 public void updateGeometry(Resource nodeResource) {
\r
118 geometryUpdates.add((IGeometryNode)abstractGraphicsNodes.get(nodeResource));
\r
123 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.db.connection.Graph)
\r
125 public synchronized void updateGeometry(Graph graph) {
\r
126 if (geometryUpdates.size() > 0) {
\r
127 for (IGeometryNode n : geometryUpdates) {
\r
129 n.updateGeometry(graph);
\r
130 if (DEBUG) System.out.println("ScenegraphAdapterImpl: geometryUpdated " + n.getResource());
\r
131 } catch (Exception e) {
\r
132 ErrorLogger.defaultLogError("Failed to update geometry of node" + n.getResource(), e);
\r
135 geometryUpdates.clear();
\r
136 viewChanged = true;
\r
137 //if (DEBUG) System.out.println("ScenegraphAdapterImpl: geometryUpdated");
\r
142 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodes()
\r
144 public Collection<IGraphicsNode> getNodes() {
\r
145 return abstractGraphicsNodes.values();
\r
149 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNode(fi.vtt.simantics.db.connection.Resource)
\r
151 public IGraphicsNode getNode(Resource resource) {
\r
152 return abstractGraphicsNodes.get(resource);
\r
156 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRootNode()
\r
158 public IGraphicsNode getRootNode() {
\r
159 return getNode(getRootResource());
\r
163 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNode(fi.vtt.simantics.layer0.utils.IEntity)
\r
165 public IGraphicsNode getNode(IEntity IEntity) {
\r
166 return abstractGraphicsNodes.get(IEntity.getResource());
\r
170 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodeResource(java.lang.String)
\r
172 public Resource getNodeResource(String uid) {
\r
173 return nameMap.getLeft(uid);
\r
177 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodeUID(fi.vtt.simantics.db.connection.Resource)
\r
179 public String getNodeUID(Resource nodeResource) {
\r
180 String name = nameMap.getRight(nodeResource);
\r
181 if (name == null) {
\r
182 //name = UUID.randomUUID().toString();
\r
183 name = Long.toString(nodeResource.getResourceId());
\r
184 nameMap.map(nodeResource, name);
\r
190 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#hasNode(fi.vtt.simantics.db.connection.Resource)
\r
192 public boolean hasNode(Resource resource) {
\r
193 return abstractGraphicsNodes.containsKey(resource);
\r
197 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRootResource()
\r
199 public Resource getRootResource() {
\r
202 return root.getResource();
\r
206 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRoot()
\r
208 public Node getRoot() {
\r
209 return root.getGroup();
\r
213 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#dispose()
\r
215 public void dispose() {
\r
216 Set<Resource> shapes = new HashSet<Resource>(abstractGraphicsNodes.keySet());
\r
217 for (Resource r : shapes) {
\r
223 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#isChanged()
\r
225 public boolean isChanged() {
\r
226 return viewChanged;
\r
230 * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#setChanged(boolean)
\r
232 public void setChanged(boolean changed) {
\r
233 viewChanged = changed;
\r
238 * Instantiates Listener that listens hierarchy changes in the node (subnode
\r
239 * added and/or removed)
\r
244 protected abstract ScenegraphQuery newSubnodeListener(G3DNode node);
\r
246 protected void addSubnodeListener(G3DNode node) {
\r
247 if (DEBUG) System.out.println("ScenegraphAdapter.addSubnodeListener( " + node.getResource() + " )");
\r
248 ScenegraphQuery q = newSubnodeListener(node);
\r
249 node.getGraph().performQuery(q);
\r
250 scenegraphQueries.put(node.getResource(), q);
\r
254 * Returns propertyQuery for a single scene-graph node.
\r
258 protected abstract NodePropertyQuery newPropertyListener(G3DNode node);
\r
261 * Returns transformationQuery for a single scene-graph node
\r
265 protected abstract NodeTransformationQuery newTransformationListener(G3DNode node);
\r
268 * Returns propertyQuery for the root node.
\r
269 * May return null if root node has no interesting properties.
\r
271 * Potentially root node could contain lighting settings, and so on...
\r
276 protected abstract NodePropertyQuery newRootPropertyListener(G3DNode root);
\r
278 protected void addPropertyListener(G3DNode node) {
\r
279 if (DEBUG) System.out.println("ScenegraphAdapter.addPropertyListener( " + node.getResource() + " )");
\r
280 NodePropertyQuery q = newPropertyListener(node);
\r
281 node.getGraph().performQuery(q);
\r
282 propertyQueries.put(node.getResource(),q);
\r
286 protected void addTransformationListener(G3DNode node) {
\r
287 if (DEBUG) System.out.println("ScenegraphAdapter.addPropertyListener( " + node.getResource() + " )");
\r
288 NodeTransformationQuery q = newTransformationListener(node);
\r
289 node.getGraph().performQuery(q);
\r
290 transformationQueries.put(node.getResource(),q);
\r
293 protected void addRootPropertyListener(Graph g) {
\r
294 G3DNode node = root.getG3DNode(g);
\r
295 if (DEBUG) System.out.println("ScenegraphAdapter.addRootPropertyListener( " + node.getResource() + " )");
\r
296 NodePropertyQuery q = newRootPropertyListener(node);
\r
299 node.getGraph().performQuery(q);
\r
300 propertyQueries.put(node.getResource(),q);
\r
304 * Instantiates a new scene-graph node
\r
306 * @param parent the parent of the new node.
\r
307 * @param node the new node.
\r
310 protected abstract IGraphicsNode instantiateNode(IGraphicsNode parent, G3DNode node);
\r
314 * Adds node into scene-graph
\r
315 * @param parent the parent of the node
\r
316 * @param r resource of the node
\r
317 * @return created scene-graph node
\r
319 protected IGraphicsNode addNode(IEntity parent, IEntity r) {
\r
320 if (!r.isInstanceOf(Resources.g3dResource.G3DNode)) {
\r
321 ErrorLogger.defaultLogError("Trying to add node into scenegraph that is not instance of graphicsnode " + r,new Exception("ASSERT!"));
\r
324 if (parent.equals(r)) {
\r
325 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") adding node to itself?!");
\r
326 ErrorLogger.defaultLogError("Adding scnegraphnode " + r.getResource().getResourceId() + " to itself!", new Exception("ASSERT!"));
\r
327 return abstractGraphicsNodes.get(r);
\r
330 if (abstractGraphicsNodes.containsKey(r)) {
\r
332 IGraphicsNode inView = abstractGraphicsNodes.get(r);
\r
333 if (inView.getParent() == null) {
\r
334 //if graphicsNode has no parent it must be the root node
\r
335 ErrorLogger.defaultLogError("Trying to add rootnode into scenegraph " + r, null);
\r
338 if (parent.equals(inView.getParent().getResource())) {
\r
339 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") already in view");
\r
342 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") already in view, but has different parent, current parent is ("+inView.getParent().getResource()+") and node is added to ("+parent+") -> removing from old parent and inserting to new");
\r
343 removeNode(inView.getParent().getResource(),r.getResource());
\r
347 G3DNode node = new G3DNode(r);
\r
350 IGraphicsNode parentNode = abstractGraphicsNodes.get(parent);
\r
351 if (parentNode == null) {
\r
352 if (DEBUG) System.out.println("No graphicsnode for (" + parent.getResource().getResourceId() + ")");
\r
355 mo = instantiateNode(parentNode, node);
\r
357 ErrorLogger.defaultLogError("Could not instantiate scenegraph node for " + r.getResource().getResourceId(), null);
\r
360 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") added to parent (" + parent.getResource().getResourceId() + ") " + mo.getClass());
\r
362 addSubnodeListener(node);
\r
363 addPropertyListener(node);
\r
364 addTransformationListener(node);
\r
366 abstractGraphicsNodes.put(r.getResource(), mo);
\r
370 // FIXME : this is a hack to fix transformations of instantiated nodes
\r
371 // if (graph.getCurrentTransaction() != null) {
\r
373 // G3DTools.propagateWorldTransformChange(parentNode
\r
375 // graph.commitChanges(CommitMessage.CHANGE_MESSAGE);
\r
376 // // G3DNodeTools.transformationUpdate(graph, r.getId());
\r
377 // } catch (Exception e) {
\r
378 // ErrorLogger.defaultLogError(e);
\r
387 * This is used only when view is disposed!
\r
391 private void removeNode(Resource r) {
\r
392 NodeTransformationQuery tq = transformationQueries.get(r);
\r
393 //StructuralChangeMonitor monitor = monitors.getLeft(r);
\r
395 if (abstractGraphicsNodes.containsKey(r)) {
\r
396 // root node has no monitor (no transformation to monitor)
\r
397 //System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") node has no monitor, but has node in scenegraph");
\r
398 abstractGraphicsNodes.remove(r);
\r
399 if(scenegraphQueries.get(r) != null) {
\r
400 scenegraphQueries.get(r).dispose();
\r
401 scenegraphQueries.remove(r);
\r
404 //System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") not in view");
\r
408 // remove listeners
\r
409 propertyQueries.remove(r).dispose();
\r
410 transformationQueries.remove(r).dispose();
\r
411 scenegraphQueries.get(r);
\r
412 scenegraphQueries.remove(r).dispose();
\r
414 IGraphicsNode node = abstractGraphicsNodes.get(r);
\r
415 ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>(node.getChildren());
\r
416 for (IGraphicsNode n : children) {
\r
417 removeNode(n.getResource());
\r
420 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") removed");
\r
423 abstractGraphicsNodes.remove(r);
\r
428 * Removes a scene-graph node.
\r
429 * @param parent the parent of the node
\r
430 * @param r the node.
\r
432 protected void removeNode(Resource parent,Resource r) {
\r
433 NodePropertyQuery q = propertyQueries.get(r);
\r
435 assert(!abstractGraphicsNodes.containsKey(r));
\r
436 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") not in view");
\r
440 IGraphicsNode node = abstractGraphicsNodes.get(r);
\r
441 Resource rParent = node.getParent().getResource();
\r
442 if (!rParent.equals(parent)) {
\r
443 // this event may happen, depending of the order of events in transaction
\r
444 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") trying to remove from wrong parent current ("+rParent+") remove parentnode null("+parent+")");
\r
447 // removing listeners
\r
448 propertyQueries.remove(r).dispose();
\r
449 transformationQueries.remove(r).dispose();
\r
450 scenegraphQueries.remove(r).dispose();
\r
451 // remove node's children
\r
452 ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>(node.getChildren());
\r
453 for (IGraphicsNode n : children) {
\r
454 removeNode(r,n.getResource());
\r
456 if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") from ("+parent+")");
\r
459 abstractGraphicsNodes.remove(r);
\r
460 if (geometryUpdates.contains(node)) {
\r
461 geometryUpdates.remove(node);
\r
468 * Query that tracks changes in resources.
\r
470 * @author Marko Luukkainen
\r
473 public abstract class NodeQuery extends AbstractQuery<Object>{
\r
474 protected Resource nodeResource;
\r
475 private boolean disposed = false;
\r
476 private IQueryListener listener;
\r
477 //private OverridingTransactionRunner runner;
\r
480 public NodeQuery(Resource r) {
\r
481 this.nodeResource = r;
\r
482 //runner = new OverridingTransactionRunner(session,true);
\r
486 protected abstract Object compute2(Graph graph);
\r
489 public Object performQuery(Graph graph) {
\r
490 if (disposed) return null;
\r
491 return compute2(graph);
\r
496 * @param oldResult result of the query before the change.
\r
497 * @param newResult result of the query after the change.
\r
499 public abstract boolean updated(Graph graph, Object oldResult, Object newResult);
\r
502 public int getType() {
\r
503 return IQuery.SCHEDULED_UPDATE;
\r
507 public void resultChangedRaw(final Object oldResult, final Object newResult) {
\r
509 throw new RuntimeException("Updating disposed query"); //return;
\r
510 transactionRunner.run(new GraphRequestAdapter() {
\r
511 //session.asyncWrite(new GraphRequestAdapter() {
\r
513 public GraphRequestStatus perform(Graph g) throws Exception {
\r
515 if (oldResult == IQueryListener.NO_VALUE)
\r
516 updated(g, null, newResult);
\r
518 updated(g, oldResult, newResult);
\r
520 return GraphRequestStatus.transactionComplete();
\r
528 public boolean equalsQuery(IGraphQuery<Object> other) {
\r
529 return nodeResource.equals(((NodeQuery)other).nodeResource);
\r
533 final public int hash() {
\r
534 return nodeResource.hashCode();
\r
539 * Disposes the query
\r
541 public void dispose() {
\r
543 if (DEBUG) System.out.println("NodeQuery " + nodeResource + " disposed()" + " " + this.getClass());
\r
546 //public abstract NodeQuery instantiateQuery(Resource node);
\r
547 //public abstract void attach();
\r
550 public boolean isDisposed() {
\r
555 public IQueryListener getListener() {
\r
556 if (listener == null) {
\r
557 listener = new IQueryListener() {
\r
559 public boolean isDisposed() {
\r
560 return NodeQuery.this.disposed;
\r
564 public void resultChangedRaw(Object oldResult, Object newResult) {
\r
565 NodeQuery.this.resultChangedRaw(oldResult, newResult);
\r
576 * Query that tracks changes in scene-graph structure (parent/child relationships).
\r
578 * @author Marko Luukkainen
\r
581 public abstract class ScenegraphQuery extends NodeQuery {
\r
583 List<Resource> added = new ArrayList<Resource>();
\r
584 List<Resource> removed = new ArrayList<Resource>();
\r
586 private boolean initialized;
\r
588 public ScenegraphQuery(Resource nodeResource) {
\r
589 super(nodeResource);
\r
590 initialized = false;
\r
591 if(DEBUG)System.out.println("ScenegraphQuery created for " + nodeResource);
\r
595 public List<Resource> compute2(Graph g) {
\r
596 IEntity node = EntityFactory.create(g,nodeResource);
\r
597 Collection<IEntity> children = node.getRelatedObjects(Resources.g3dResource.HasChild);
\r
598 List<Resource> list = new ArrayList<Resource>();
\r
599 for (IEntity n: children)
\r
600 list.add(n.getResource());
\r
601 if (DEBUG) System.out.println("ScenegraphQuery " + nodeResource + " has " + list.size() + " children");
\r
605 @SuppressWarnings("unchecked")
\r
607 public boolean updated(Graph graph, Object oldResult, Object newResult) {
\r
608 List<Resource> oldChildren;
\r
609 if (oldResult != null)
\r
610 oldChildren = (List<Resource>)oldResult;
\r
612 oldChildren = new ArrayList<Resource>();
\r
613 List<Resource> newChildren = (List<Resource>)newResult;
\r
615 if (DEBUG) System.out.println("ScenegraphQuery " + nodeResource + " updated: had " + oldChildren.size() + " children, but now has " + newChildren.size() + " children");
\r
619 for (Resource r : oldChildren)
\r
620 if (!newChildren.contains(r))
\r
622 for (Resource r : newChildren)
\r
623 if (!oldChildren.contains(r))
\r
625 for (Resource r : removed) {
\r
627 System.out.println("ScenegraphQuery " + nodeResource
\r
628 + " removed " + r);
\r
629 removeNode(nodeResource, r);
\r
631 if (added.size() > 0) {
\r
632 G3DNode parent = new G3DNode(graph, nodeResource);
\r
636 * G3DTools.propagateTransformChange(parent); } catch
\r
637 * (Exception e) { ErrorLogger.defaultLogError(e); }
\r
639 for (Resource r : added) {
\r
640 IEntity e = EntityFactory.create(graph, r);
\r
641 G3DTools.propagateLocalTransformChange(parent, e);
\r
642 IGraphicsNode n = addNode(parent, e);
\r
643 shapeAdded(graph, n);
\r
646 return (added.size() > 0 || removed.size() > 0);
\r
648 // when query is run for the first time, we can assume that transformations are correct.
\r
649 initialized = true;
\r
650 for (Resource r : newChildren)
\r
652 if (added.size() > 0) {
\r
653 G3DNode parent = new G3DNode(graph, nodeResource);
\r
654 for (Resource r : added) {
\r
655 IEntity e = EntityFactory.create(graph, r);
\r
656 IGraphicsNode n = addNode(parent, e);
\r
657 shapeAdded(graph, n);
\r
668 * This method is run after a node is added to scene-graph.
\r
670 * @param graph Graph of the current transaction.
\r
671 * @param node the newly added scene-graph node
\r
673 public abstract void shapeAdded(Graph graph,IGraphicsNode node);
\r
676 // public void attach() {
\r
677 // scenegraphQueries.put(nodeResource, this);
\r
684 * Tracks changes in scene-graph nodes' properties
\r
686 * @author Marko Luukkainen
\r
689 public abstract class NodePropertyQuery extends NodeQuery {
\r
691 private boolean initialized;
\r
693 public NodePropertyQuery(Resource nodeResource) {
\r
694 super(nodeResource);
\r
695 initialized = false;
\r
696 if(DEBUG)System.out.println("NodePropertyQuery created for " + nodeResource);
\r
700 public List<Object> compute2(Graph g) {
\r
701 IEntity t = EntityFactory.create(g,nodeResource);
\r
703 Collection<Property> properties = t.getRelatedProperties(Resources.g3dResource.HasNonTransformation);
\r
704 List<Object> propertyValues = new ArrayList<Object>();
\r
705 p(properties,propertyValues);
\r
707 return propertyValues;
\r
710 private void p(Collection<Property> properties, List<Object> propertyValues) {
\r
711 for (Property p : properties) {
\r
712 Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);
\r
713 if (subProperties.size() != 0) {
\r
714 p(subProperties,propertyValues);
\r
717 propertyValues.add(p.getValue());
\r
723 public boolean updated(Graph graph, Object oldResult, Object newResult) {
\r
725 if (DEBUG) System.out.println("NodePropertyQuery changed " + nodeResource + " " + abstractGraphicsNodes.size());
\r
726 IGraphicsNode mo = abstractGraphicsNodes.get(nodeResource);
\r
728 if (DEBUG) System.out.println("NodePropertyQuery invalid change " + nodeResource + " " + abstractGraphicsNodes.size());
\r
729 ErrorLogger.defaultLogError("Got update from resource " + nodeResource + " but its not part of the scenegraph", null);
\r
733 shapeUpdated(graph,mo);
\r
736 initialized = true;
\r
743 * This method is run when a scene-graph node is changed.
\r
745 * @param shape the changed node
\r
747 public abstract void shapeUpdated(Graph graph,IGraphicsNode shape);
\r
750 // public void attach() {
\r
751 // propertyQueries.put(nodeResource, this);
\r
756 public abstract class NodeTransformationQuery extends NodeQuery {
\r
758 private boolean initialized;
\r
760 public NodeTransformationQuery(Resource nodeResource) {
\r
761 super(nodeResource);
\r
762 initialized = false;
\r
763 if(DEBUG)System.out.println("NodeTransformationQuery created for " + nodeResource);
\r
767 public List<Object> compute2(Graph g) {
\r
768 IEntity t = EntityFactory.create(g,nodeResource);
\r
770 Collection<Property> properties = t.getRelatedProperties(Resources.g3dResource.HasTransformation);
\r
772 List<Object> propertyValues = new ArrayList<Object>();
\r
773 p(properties,propertyValues);
\r
774 return propertyValues;
\r
778 private void p(Collection<Property> properties, List<Object> propertyValues) {
\r
779 for (Property p : properties) {
\r
780 Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);
\r
781 if (subProperties.size() != 0) {
\r
782 p(subProperties,propertyValues);
\r
785 propertyValues.add(p.getValue());
\r
791 public boolean updated(Graph graph,Object oldResult, Object newResult) {
\r
793 if (DEBUG) System.out.println("NodeTransformationQuery changed " + nodeResource + " " + abstractGraphicsNodes.size());
\r
795 G3DTools.transformationUpdate(graph, nodeResource);
\r
797 IGraphicsNode mo = abstractGraphicsNodes.get(nodeResource);
\r
799 if (DEBUG) System.out.println("NodeTransformationQuery invalid change " + nodeResource + " " + abstractGraphicsNodes.size());
\r
800 ErrorLogger.defaultLogError("Got update from resource " + nodeResource + " but its not part of the scenegraph", null);
\r
804 shapeUpdated(graph,mo);
\r
807 initialized = true;
\r
814 * This method is run when a scene-graph node is changed.
\r
816 * @param shape the changed node
\r
818 public abstract void shapeUpdated(Graph graph,IGraphicsNode shape);
\r
821 // public void attach() {
\r
822 // transformationQueries.put(nodeResource, this);
\r