/* * Moonlight|3D Copyright (C) 2005 The Moonlight|3D team * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Created on Jan 5, 2005 */ package ml.backend.og; /** * \package ml.backend.og * * This is the operator graph base. This packages contains all * the base classes for the the operator graph of Moonlight|3D. * * This package is part of the core program. */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import ml.backend.document.Document; import ml.backend.selection.PathElement; import ml.backend.selection.RootPathElement; import ml.core.exceptions.Exception; import ml.core.helper.NamePool; import ml.core.helper.Observed; /** * This is the operator graph manager class, through which the operator graph * is built and accessed * * @author gregor */ public class Manager extends Observed implements RootPathElement { private static ArrayList factories; static { factories=new ArrayList(); } /** * Register a node factory for a certain kind of operator graph nodes. * Nodes will solely be constructed through the registered factory. * * @param factory new operator graph node factory */ public static void registerNodeFactory(ml.core.helper.Factory factory) { factories.add(factory); } /** * Unregister a node factory for a certain kind of operator graph nodes. * Once this happens, no new nodes of this kind will be created. * * @param name the name of the operator graph node factory * @throws ml.core.exceptions.Exception if factory was not found */ public static void unregisterNodeFactory(String name) throws ml.core.exceptions.Exception { for(int i=0;i nodes; protected HashMap nodeMap; protected ArrayList links; protected NamePool names; protected ArrayList listeners; protected Document document; public Manager(Document document) { super(); this.document=document; nodes=new ArrayList(); nodeMap=new HashMap(); links=new ArrayList(); names=new NamePool(); listeners=new ArrayList(); } /** * Register an operator graph listener. From that point onwards it will be called * whenever a noteworthy change is made in the operator graph. * * @param listener the listener to register */ public void registerOperatorGraphListener(OperatorGraphListener listener) { listeners.add(listener); } /** * Unregister an operator graph listener. From that point onwards, the listener * will no longer be notified of any changes. * * @param listener the listener to remove */ public void unregisterOperatorGraphListener(OperatorGraphListener listener) { listeners.remove(listener); } /** * Clear operator graph. Used to start out with an fresh, empty scene. * Please note that clearing the operator graph may not be sufficient * for generating a consistent state in the backend. See the frontend * tools on details. * */ public void clear() { names.clear(); nodes.clear(); nodeMap.clear(); links.clear(); for(OperatorGraphListener listener : listeners) { listener.graphCleared(); } } /** * Create a node of the given kind, e.g. "MoveObject" and insert it * into the operator graph. You will still have to linke that node's * slots afterwards to define the it's input and output. * * @param name * @return * @throws Exception */ public Node createNodeByName(String name) throws Exception { for(int i=0;i getNodeList() { return (ArrayList)nodes.clone(); } public Node getNodeByName(String name) throws Exception { Node node=nodeMap.get(name); if(node!=null) { return node; } throw new Exception("unable to find node with given name"); } /** * adds a link to the node graph * @throws Exception */ public Link addLink(Slot output, Slot input) throws Exception { try { Link link=new Link(); link.setInput(output); link.setOutput(input); links.add(link); for(OperatorGraphListener listener : listeners) { listener.linkInserted(link); } return link; } catch (Exception e) { throw new ml.core.exceptions.Exception("unable to add link to operator graph",e); } } /** * removes a link from the node graph */ public void removeLink(Link link) { for(int i=0;i getLinkList() { return (ArrayList)links.clone(); } /** * Helper function for inserting new nodes into the scene graph. This function * will insert the node with the two slots newInput and newOutput after the * the slot oldOutput of an existing node. If oldOutput was connected to Slot * oldInput before the operation, then oldOutput will be connected to newInput * and newOutput will be connected to oldInput afterwards. * * @param oldOutput output slot of a valid OG node * @param newInput input slot of a new OG node * @param newOutput output slot of a new OG node * @throws Exception */ public void insertNodeAfter(Slot oldOutput, Slot newInput, Slot newOutput) throws Exception { if (oldOutput.getCurrentLink() == null) { addLink(oldOutput, newInput); } else { Slot oldInput = oldOutput.getCurrentLink().getOutput(); removeLink(oldOutput.getCurrentLink()); addLink(oldOutput, newInput); addLink(newOutput, oldInput); } } /** * recursively update the whole tree * * @throws Exception */ public void update() throws Exception { // long startTime=System.currentTimeMillis(); /* only start recursive updating of the whole tree * at nodes which are known to be pure sources */ try { for(int i=0;i