Groups and LiveGroups
=====================

.. currentmodule:: NodegraphAPI

A :kat:node:`Group` node acts as a container for a sub-network of nodes. To add a Group node to a recipe
under the root node, then create a :kat:node:`PrimitiveCreate` node inside that group enter the following::

    # Create a Group node at root level
    groupNode = NodegraphAPI.CreateNode('Group', NodegraphAPI.GetRootNode())

Then, create a PrimitiveCreate node, as in :doc:`CreatingAndRetrievingNodes` but give the Group node as parent node,
rather than the root node as in the previous example::

    primNode = NodegraphAPI.CreateNode('PrimitiveCreate', groupNode)

Alternatively, create a Group node and a PrimitiveCreate node at the root level, then parent the PrimitiveCreate node
under the Group node::

    # Get the root node
    rootNode = NodegraphAPI.GetRootNode()

    # Create the Group node at root level
    groupNode = NodegraphAPI.CreateNode('Group', rootNode)

    # Create the PrimitiveCreate node at root level
    primNode = NodegraphAPI.CreateNode('PrimitiveCreate', rootNode)

    # Set the Group node as parent of the PrimitiveCreate node
    primNode.setParent(groupNode)

.. autofunction:: GetViewPortPosition
.. autofunction:: SetViewPortPosition


Send and Return Ports
---------------------

For :kat:node:`Group` nodes to be of any significant use, you need to be able to connect their internal structure to
the ports of external nodes. The quickest - in the short term - way of doing this is to directly connect a port on a
node inside the group to a port on a node outside the group. To do this however, you need to know the internal
structure of the Group node and be aware of the maintenance burden on the Python code that does the connecting. Any
change to the internal structure of the group can mean the port connecting code needs updating.

A more encapsulated approach is to connect the internal ports to corresponding *send* or *return ports* on the Group
node. If a Group node were a function in Python, the send ports would be the arguments and the return ports would the
return values.

.. note:: The send and return ports on a Group node only exist if the group has inputs and outputs created. Creating an
    input or output port on a group automatically creates a send or return port with the same name. See
    :doc:`ConnectingNodes` for more on creating, and connecting inputs and outputs.

Return Ports
''''''''''''

The advantage of send and return ports is that you can connect to them without any knowledge of the group’s internal
structure. For example, create a Group containing a :kat:node:`PrimitiveCreate` node and a :kat:node:`Merge` node.
Connect the output of the PrimitiveCreate node to the input of the Merge node, and connect the output of the Merge node
to the return port of the Group node::

    # Create the group at root level
    rootNode = NodegraphAPI.GetRootNode()
    groupNode = NodegraphAPI.CreateNode('Group', rootNode)
    groupNode.addOutputPort("out")

    # Create the PrimitiveCreate node at group level
    primNode = NodegraphAPI.CreateNode('PrimitiveCreate', groupNode)

    # Create a Merge nodes at group level
    mergeNode = NodegraphAPI.CreateNode('Merge', groupNode)

    # Connect PrimitiveCreate output to Merge input

    # Get the out port of the PrimitiveCreate node
    primOutPort = primNode.getOutputPort("out")
    mergeSphereInPort = mergeNode.addInputPort('sphere')
    primOutPort.connect(mergeSphereInPort)

    # Get the groups Return port
    # First create an output port on the group
    groupOutPort = groupNode.addOutputPort("goingOut")
    groupReturnPort = groupNode.getReturnPort("goingOut")

    # Get the output port on the Merge node
    mergeOutPort = mergeNode.getOutputPort("out")

    # Connect the Merge node's out to the Group node's Return
    mergeOutPort.connect(groupReturnPort)

Now you can connect the output of the Group node to external nodes without accessing its internal structure. For
example, take the example above, and connect the output of the Group node to a new Merge node::

    # Create a Merge node at root level
    outerMergeNode = NodegraphAPI.CreateNode('Merge', root)

    # Get the input port of the Merge node
    outerMergeInPort = outerMergeNode.getInputPort('input')

    # Connect the Group’s output to the Merge node's input
    outerMergeInPort.connect(groupReturn)


Send Ports
''''''''''

The Group node created above does not take any inputs. For a group to accept inputs, it must have an input port linked
to its send port. For example, create a group that merges geometry from a PrimitiveCreate node inside the group, with
geometry from a PrimitiveCreate node outside the group::

    # Create the group at root level
    rootNode = NodegraphAPI.GetRootNode()
    groupNode = NodegraphAPI.CreateNode('Group', rootNode)

    # Create input and output on the group
    groupNode.addInputPort("in")
    groupNode.addOutputPort("out")

    # Get the corresponding Send and Return ports
    groupReturnPort = groupNode.getReturnPort("out")
    groupSendPort = groupNode.getSendPort("in")

    # Create a PrimitiveCreate node at group level
    primNode = NodegraphAPI.CreateNode('PrimitiveCreate', groupNode)

    # Get the output port on the PrimitiveCreate
    primOutPort = primNode.getOutputPort("out")

    # Create a merge node at group level
    mergeNode = NodegraphAPI.CreateNode('Merge', groupNode)

    # Add two inputs and get the output ports
    mergeIn0Port = mergeNode.addInputPort("in0")
    mergeIn1Port = mergeNode.addInputPort("in1")
    mergeOutPort = mergeNode.getOutputPort("out")

    # Connect the PrimitiveCreate out to Merge in0
    mergeIn0Port.connect(primOutPort)

    # Connect the Merge node to the Group inputs and outputs
    mergeIn1Port.connect(groupSendPort)
    mergeOutPort.connect(groupReturnPort)

Anything connected to the input of the Group node is now merged with the output of the PrimitiveCreate node contained
in the group.


LiveGroups
----------

.. autofunction:: GetNodeModTime
.. autofunction:: SetNodeModTime
.. automodule:: NodegraphAPI.LiveGroup