######################
Assembly Tree Node IDs
######################

.. program:: converter

Basics
------

When authoring the assembly structure using the AssemblyTree API of libsc, each creation function returns an ID to identify the newly created object.

As an example:

.. literalinclude:: /../../applications/converter/docs/test_stream_cache.cpp
	   :start-after: //! [Assembly_Tree_Basic]
	   :end-before: //! [Assembly_Tree_Basic]

The parameter of ``CreateAssemblyTreeRoot`` (in this case, "root_node_id") is an out parameter. The id returned in "root_node_id" is needed as input for other functions:

.. literalinclude:: /../../applications/converter/docs/test_stream_cache.cpp
	   :start-after: //! [Assembly_Tree_Child]
	   :end-before: //! [Assembly_Tree_Child]

Every node (assembly, part, body instance, PMI, view, etc.) in the assembly tree will have an associated ID that is determined during authoring and will not change.

The IDs start at zero (which will usually be the assembly), and the IDs generated will increment by 1 meaning that the whole ID set will go from 0 to n.

When exporting to an XML file, the IDs will be the same in the XML as the ones you got when authoring. This is the same scenario when you use Converter with the command line option :option:`--output_xml_assemblytree`.

Also it's important to note that when the data is stored in the StreamCache, IDs will still stay the same, which means that the IDs created during authoring, the IDs in the XML, and the IDs returned in the web client will be the same.


Loading multiple files into the same viewing session
----------------------------------------------------

Assuming two assemblies: "A" and "B".
We generate a StreamCache file for both:

* For "A" the IDs range from 0 to 399.
* For "B" the IDs range from 0 to 499.

In the web client, we initially load "A" with the :ref:`WebViewer constructor <api_ref/viewing/classes/Communicator.WebViewer:constructor>` In addition, we load B into our ``Communicator.WebViewer`` object ("hwv" in this sample) using the :ref:`loadSubTreeFromModel <api_ref/viewing/classes/Communicator.Model:loadsubtreefrommodel>` function from the model object:

.. literalinclude:: /../../applications/client/docs/AssemblyTree.ts
	   :start-after: //! [Load_Multiple_Assemblies]
	   :end-before: //! [Load_Multiple_Assemblies]	

In this case, it isn't obvious how to reference a node in the "B" tree, since B's range of node IDs overlaps with A's. To make it possible to uniquely identify nodes, the IDs of B are automatically shifted to the lowest available ID of the existing scene. The function :ref:`getLowestAvailableNodeId <api_ref/viewing/classes/Communicator.Model:getlowestavailablenodeid>` should be called before loading another model into the scene -- in this case, right before loading B. It would return "400" as the lowest available ID. Then you can use that number internally to make your B assembly XML IDs match the IDs on the web client.

Here's a sample function call:

.. literalinclude:: /../../applications/client/docs/AssemblyTree.ts
	   :start-after: //! [Get_Lowest_Available_NodeID]
	   :end-before: //! [Get_Lowest_Available_NodeID]

In this scenario, since A has already reserved the IDs from 0 to 399, the range for B will be shifted from 0-499 to 400-899. It's up to the developer to correctly map those shifted IDs back to the original IDs in the XML of the model.
