X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.g3d.jme%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fjme%2Fcommon%2FAbstractJMENodeMap.java;fp=org.simantics.g3d.jme%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fjme%2Fcommon%2FAbstractJMENodeMap.java;h=162fbb3bfc41f7bab2ac2736fbe56622a4b228d0;hb=5b4454ce3dac8d0cf04caaaa696f300c16be99a0;hp=0000000000000000000000000000000000000000;hpb=2e9c37990c979fe7a877a6a9d0de65ee27f3b56f;p=simantics%2F3d.git diff --git a/org.simantics.g3d.jme/src/org/simantics/g3d/jme/common/AbstractJMENodeMap.java b/org.simantics.g3d.jme/src/org/simantics/g3d/jme/common/AbstractJMENodeMap.java new file mode 100644 index 00000000..162fbb3b --- /dev/null +++ b/org.simantics.g3d.jme/src/org/simantics/g3d/jme/common/AbstractJMENodeMap.java @@ -0,0 +1,415 @@ +package org.simantics.g3d.jme.common; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.g3d.ontology.G3D; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.g3d.scenegraph.RenderListener; +import org.simantics.g3d.scenegraph.base.INode; +import org.simantics.g3d.scenegraph.base.NodeListener; +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.objmap.graph.IMapping; +import org.simantics.objmap.graph.IMappingListener; +import org.simantics.utils.datastructures.MapList; +import org.simantics.utils.datastructures.MapSet; +import org.simantics.utils.datastructures.Pair; + +import com.jme3.app.Application; +import com.jme3.scene.Spatial; + +public abstract class AbstractJMENodeMap implements JMENodeMap, IMappingListener, NodeListener, RenderListener { + + protected Session session; + protected IMapping mapping; + protected Application app; +// protected InteractiveVtkPanel panel; + + protected MapList nodeToActor = new MapList(); + protected Map actorToNode = new HashMap(); + + protected ParentNode rootNode; + + public AbstractJMENodeMap(Session session, IMapping mapping, Application app, ParentNode rootNode) { + this.session = session; + this.mapping = mapping; + this.rootNode = rootNode; + this.app = app; +// this.panel = panel; +// panel.addListener(this); + mapping.addMappingListener(this); + rootNode.addListener(this); + } + + protected abstract void addActor(E node); + protected abstract void removeActor(E node); + protected abstract void updateActor(E node,Set ids); + + + public void repaint() { + + } + + public void populate() { + for (E node : rootNode.getNodes()) { + receiveAdd(node, node.getParentRel(),true); + } + repaint(); + } + + @Override + public IG3DNode getNode(Spatial prop) { + return actorToNode.get(prop); + } + + @SuppressWarnings("unchecked") + @Override + public Collection getRenderObjects(IG3DNode node) { + return nodeToActor.getValues((E)node); + } + + @SuppressWarnings("unchecked") + @Override + public ParentNode getRootNode() { + return (ParentNode)rootNode; + } + + @Override + public void commit() { + session.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + synchronized(syncMutex) { + graphUpdates = true; + mapping.updateDomain(graph); + graphUpdates = false; + } + } + }); + } + + @Override + public boolean isChangeTracking() { + return changeTracking; + } + + @Override + public void setChangeTracking(boolean enabled) { + changeTracking = enabled; + } + + private boolean changeTracking = true; + + private Object syncMutex = new Object(); + + + private List> added = new ArrayList>(); + private List> removed = new ArrayList>(); + //private List> updated = new ArrayList>(); + private MapSet updated = new MapSet();//new MapSet.Hash(); + + + @SuppressWarnings("unchecked") + @Override + public void updateRenderObjectsFor(IG3DNode node) { + List toDelete = new ArrayList(); + for (Spatial prop : nodeToActor.getValues((E)node)) { +// if (prop.GetVTKId() != 0) { +// panel.GetRenderer().RemoveActor(prop); +// //prop.Delete(); +// toDelete.add(prop); +// } + prop.removeFromParent(); + actorToNode.remove(prop); + } + nodeToActor.remove((E)node); + Collection coll = getActors((E)node); + if (coll == null) + return; + for (Spatial prop : coll) { + nodeToActor.add((E)node,prop); + actorToNode.put(prop, (E)node); + toDelete.remove(prop); + } + for (Spatial p : toDelete) { + //p.Delete(); + } + } + + protected abstract Collection getActors(E node); + + @SuppressWarnings("unchecked") + private void receiveAdd(E node, String id, boolean db) { + synchronized (syncMutex) { + for (Pair n : added) { + if (n.first.equals(node)) + return; + } + if (changeTracking) { + mapping.rangeModified(node.getParent()); + } + added.add(new Pair(node, id)); + } + repaint(); + } + + @SuppressWarnings("unchecked") + private void receiveRemove(E node, String id, boolean db) { + synchronized (syncMutex) { + for (Pair n : removed) { + if (n.first.equals(node)) + return; + } + if (changeTracking && !db) + mapping.rangeModified(node.getParent()); + removed.add(new Pair(node, id)); + } + repaint(); + } + + @SuppressWarnings("unchecked") + private void receiveUpdate(E node, String id, boolean db) { + synchronized (syncMutex) { +// for (Pair n : updated) { +// if (n.first.equals(node)) +// return; +// } + if (changeTracking && !db) + mapping.rangeModified(node); + //updated.add(new Pair(node, id)); + updated.add(node, id); + } + repaint(); + } + + private boolean graphUpdates = false; + private Set graphModified = new HashSet(); + + @Override + public void domainModified() { + if (graphUpdates) + return; + //System.out.println("domainModified"); + session.asyncRequest(new ReadRequest() { + + @SuppressWarnings("unchecked") + @Override + public void run(ReadGraph graph) throws DatabaseException { + graphUpdates = true; + for (Object domainObject : mapping.getDomainModified()) { + Object rangeObject = mapping.get(domainObject); + if (rangeObject != null) + graphModified.add(rangeObject); + } + mapping.updateRange(graph); + graphModified.clear(); + graphUpdates = false; + if (mapping.isRangeModified()) + commit(); + } + }); + + } + + @Override + public void rangeModified() { + //System.out.println("rangeModified"); + + } + + @Override + public void postRender() { + + } + + List> rem = new ArrayList>(); + List> add = new ArrayList>(); + MapSet mod = new MapSet();//new MapSet.Hash(); + Set propagation = new HashSet(); + Stack stack = new Stack(); + + @SuppressWarnings("unchecked") + @Override + public synchronized void preRender() { + rem.clear(); + add.clear(); + mod.clear(); + propagation.clear(); + + synchronized (syncMutex) { + rem.addAll(removed); + add.addAll(added); + //mod.addAll(updated); + for (E e : updated.getKeys()) { + for (String s : updated.getValues(e)) + mod.add(e, s); + } + + removed.clear(); + added.clear(); + updated.clear(); + } + + for (Pair n : rem) { + stopListening(n.first); + removeActor(n.first); + + } + + for (Pair n : add) { + addActor(n.first); + listen(n.first); + } + + for (E e : mod.getKeys()) { + Set ids = mod.getValues(e); + if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation)) { + if (!propagation.contains(e)) + propagation.add(e); + } + } + + if (propagation.size() > 0) { + stack.clear(); + stack.addAll(propagation); + propagation.clear(); + while (!stack.isEmpty()) { + E node = stack.pop(); + if (propagation.contains(node)) + continue; + propagation.add(node); + for (NodeListener l : node.getListeners()) { + if (l == this) { + //changeTracking = false; + //l.propertyChanged(node, G3D.URIs.hasPosition); + //changeTracking = true; + } else { + l.propertyChanged(node, G3D.URIs.hasPosition); + } + } + if (node instanceof ParentNode) { + stack.addAll(((ParentNode)node).getNodes()); + } + } + } + + for (E e : mod.getKeys()) { + Set ids = mod.getValues(e); + updateActor(e,ids); + } + + for (Pair n : rem) { + for (NodeListener l : nodeListeners) + l.nodeRemoved(null, n.first, n.second); + } + for (Pair n : add) { + for (NodeListener l : nodeListeners) + l.nodeAdded(n.first.getParent(), n.first, n.second); + } +// for (Pair n : mod) { +// for (NodeListener l : nodeListeners) +// l.propertyChanged(n.first, n.second); +// } + for (E e : mod.getKeys()) { + for (NodeListener l : nodeListeners) + for (String s : mod.getValues(e)) + l.propertyChanged(e, s); + } + } + + @SuppressWarnings("unchecked") + private void listen(INode node) { + node.addListener(this); + if (node instanceof ParentNode) { + ParentNode parentNode = (ParentNode)node; + for (INode n : parentNode.getNodes()) + listen(n); + } + } + + private void stopListening(INode node) { + node.removeListener(this); + if (node instanceof ParentNode) { + @SuppressWarnings("unchecked") + ParentNode parentNode = (ParentNode)node; + for (INode n : parentNode.getNodes()) + stopListening(n); + } + } + + @SuppressWarnings("unchecked") + @Override + public void propertyChanged(INode node, String id) { + //receiveUpdate((E)node, id, graphUpdates); + receiveUpdate((E)node, id, graphModified.contains(node)); + + } + + @SuppressWarnings("unchecked") + @Override + public void nodeAdded(ParentNode node, INode child, + String rel) { + //receiveAdd((E)child, rel ,graphUpdates); + receiveAdd((E)child, rel ,graphModified.contains(node)); + + } + + @SuppressWarnings("unchecked") + @Override + public void nodeRemoved(ParentNode node, INode child, + String rel) { + //receiveRemove((E)child, rel, graphUpdates); + receiveRemove((E)child, rel, graphModified.contains(node)); + } + + @Override + public void delete() { + changeTracking = false; + //panel.removeListener(this); + mapping.removeMappingListener(this); + + List nodes = new ArrayList(nodeToActor.getKeySize()); + nodes.addAll(nodeToActor.getKeys()); + for (E node : nodes) { + node.removeListener(this); + removeActor(node); + node.cleanup(); + } + for (Spatial prop : actorToNode.keySet()) { + prop.removeFromParent(); + //if (prop.GetVTKId() != 0) + // prop.Delete(); + } + actorToNode.clear(); + nodeToActor.clear(); + + } + + + private List nodeListeners = new ArrayList(); + @Override + public void addListener(NodeListener listener) { + nodeListeners.add(listener); + + } + + @Override + public void removeListener(NodeListener listener) { + nodeListeners.remove(listener); + + } + +}