#####################
Database Fundamentals
#####################

**NOTE:** This programming guide introduces the HOOPS Visualize API. For a high-level overview of what HOOPS Visualize is, as well as a discussion of its major components, see the :doc:`Technical Overview </general/technical_overview>`.


The foundation of HOOPS Visualize is the Visualize graphics *database*. The database is where all scene information is stored and organized.

Your application will probably integrate many different libraries to provide all of its functionality. To your application, Visualize simply appears as another library containing functions which can be called to insert and delete objects from the graphics database, to initiate and control rendering, and to receive input events. The general order in which these operations occur is described below:

#. Your application code makes changes to the graphics database.
#. When it is finished making changes to the graphics database, your application tells Visualize to update the display (either by explicitly calling Update() or by waiting for input).
#. Visualize walks the database and sends the primitives to be drawn to the renderer.
#. The renderer draws the scene and sends it to some output device.
#. The user sees the new picture, thinks for a while, and then generates input through the user interface.
#. Your application code receives this input and makes further changes to the Visualize database.

Although called a 'database', the Visualize database does not use a relational model like a SQL database. Instead, information is organized in a tree-like scene graph composed of nodes. Nodes have a parent/child relationship where one parent can have many children but each child only has one parent. In the Visualize database, **a node is called a segment**. Segments are the building blocks of the scene graph - they contain all geometry and attributes and are used to organize your scene hierarchically.

Describing a scene graph as a data structure is beyond the scope of this document, but understanding how the HOOPS Visualize database works is **critical** in order to work with Visualize efficiently.

.. image:: images/scene_graph.png
	:align: center

.. rst-class:: center

	*Structure of a scene graph*

The database and all objects within it depend on a ``HPS::World`` object. You can think of ``HPS::World`` as the context within which Visualize is able to manage your scene and to execute all its internal commands. You must create a ``HPS::World`` before using HOOPS Visualize.

The ``HPS::World`` object requires one parameter, your license key. The Tech Soft 3D Developer Zone provides this in the form of a header file, *hoops_license.h*. The license key is inside that file.

.. tabs::

	.. group-tab:: C++
		
		.. code-block:: cpp
	
			HPS::World world("[my license key]");
		   
	.. group-tab:: C#
		
		.. code-block:: c#

			HPS.World world = new HPS.World("[my license key]");

C++ users may forgo setting the license key in the ``HPS::World`` constructor and instead simply use the macro ``HOOPS_LICENSE``, which is defined in *hoops_license.h*. In order to make this work, you have to generate your own *hoops_license.h* from the Tech Soft 3D Developer Zone and copy it to *<VISUALIZE_INSTALL_DIR>/include/*.

There are a number of different ways to connect HOOPS Visualize to a window. The simplest way uses a stand-alone window:

.. tabs::

	.. group-tab:: C++
	
		.. code-block:: cpp
	
			#include "hps.h"
	 
			using namespace HPS;
			 
			int main(int argc, char* argv[])
			{
				HPS::World world("[my license key]");
				HPS::StandAloneWindowKey sawk = HPS::Database::CreateStandAloneWindow();
				sawk.Update();
				return 0;
			}
   
	.. group-tab:: C#
	
		.. code-block:: c#

			namespace HPS_020612_3
			{
				class Program
				{
					// it is important to have a static reference to avoid garbage collector
					static HPS.World world = new HPS.World("[my license key]"); 
					
					static void Main(string[] args)
					{
						HPS.StandAloneWindowKey sawk = HPS.Database.CreateStandAloneWindow();
						sawk.Update();
					}
				}
			}
		
Despite its brevity, the code in the snippet above is all that is needed to get HOOPS Visualize running in an empty window. For further information on the other ways to connect HOOPS Visualize to your application window, see :ref:`this section <prog_guide/0101_database:Connecting Visualize to a window>`.


.. _segments:

Segments
========

When you instantiate a ``HPS::World`` object, Visualize initializes the graphical database. To begin building your scene graph, you must utilize at least one root segment. There are two ways to do this. You may use a window segment as a root segment, or you can create one independently using ``HPS::Database::CreateRootSegment`` and then associate it with a window segment using an :ref:`include link <prog_guide/0101_database:Include segments>`. Any number of root segments can be created this way. This method is useful, for example, when you have multiple geometries or assemblies you would like to swap in and out of the scene.

Regardless of which method you choose, it is important to understand that *only those segments that have a window segment ancestor will be drawn at render-time*. With a root segment, you can set attributes, insert geometry and create subsegments. A window segment is similar to a root segment but has slightly different behavior and attributes. For example, every window segment is associated with a Visualize rendering context while a plain root segment is not (a plain root segment may not even be attached to the scene hierarchy). Another difference is that window segments are the only place to set window-level rendering directives such as anti-aliasing. It is important to understand these differences to determine which one to use and when to use it.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_database.cpp
		   :start-after: //! [database]
		   :end-before: //! [database]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_database.cs
		   :start-after: //! [database]
		   :end-before: //! [database]

If a root segment does not need to be attached to the main scene graph, then what is its purpose? A root segment may be used to organize a group of related segments into a model subassembly to which attributes such as visibility or modelling matrix may be applied. For example, to temporarily make a subassembly invisible, you could detach the corresponding branch from the scene tree. The root of the branch is now a root segment. Another example would be to create a new root segment using ``Database::CreateRootSegment``, fill its branches with model data, and attach it to the main tree when it is ready to be rendered.

In the sample code above, both a generic root segment and a window segment are created using static methods in ``HPS::Database``. Both creation methods return a ``HPS::SegmentKey`` or subclass thereof. Note that a ``HPS::SegmentKey`` is *not* actually a segment but a handle that lets you interact with a specific instance of a segment in the database.  A ``HPS::SegmentKey`` provides access to the attributes and geometry within a segment and allows you to perform actions upon the segment. It also lets you traverse the segment tree allowing you to access and manipulate child segments.

In summary, all segments are inherently part of the database - they do not exist in isolation. All segments have a parent except root segments which exhibit slightly different behavioral relationships. Each segment has a handle called a *key*. The key allows you to locate the segment, find its type, and find its relationship to other segments like its parent and children. The following code snippet demonstrates some examples of these interactions:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_show_subsegments.cpp
		   :start-after: //! [show_subsegments]
		   :end-before: //! [show_subsegments]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_show_subsegments.cs
		   :start-after: //! [show_subsegments]
		   :end-before: //! [show_subsegments]

A segment contains data and also has data attached to it. The way you :ref:`structure your scene graph <prog_guide/0703_performance_considerations:Segment organization>` is very important, because a segment always inherits a set of attributes from its parent segment. Isolated root segments do not contain initialized attributes, but they will inherit attributes from a parent when attached. In Visualize, attaching is called :ref:`inclusion <prog_guide/0101_database:Include segments>`. In addition to inserting geometry into a segment and creating child segments, it is possible to attach or detach existing segments. However, since normal segments cannot exist in an orphaned state, when detaching segments, they must be either deleted or moved to another segment (this restriction does not apply to root segments or include segments).

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_manipulate_segment.cpp
		   :start-after: //! [manipulate_segment]
		   :end-before: //! [manipulate_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_manipulate_segment.cs
		   :start-after: //! [manipulate_segment]
		   :end-before: //! [manipulate_segment]
		   
.. image:: images/segment_structure_detail.png
	:align: center

*Segment Structure Detail*


Segment Attributes
------------------

One of the main purposes of segments is to group attributes at the segment level. For :doc:`performance reasons <0703_performance_considerations>`, segments are intended to be used to group items with similar attributes. Attributes are descriptors that tell Visualize how to render graphical information. Most (but not all) attributes exist at the *segment level*, which means they apply to all geometry in the segment. For any attribute set, there exists exactly one value for each attribute. If you do not explicitly specify the value for an attribute on a segment, the effective value will be inherited from the segment's parent (or ancestor, if the parent has no setting of its own). This also means that assigning a value to an attribute will cause all subsegments to inherit that value, unless they override it with a value of their own. Visualize determines a set of default values for all attributes and initializes each window segment with those defaults. Thus, due to the nature of inheritance, your attribute will receive the default value if you do not explicitly set a value for it in an ancestor segment.

A further discussion on attributes, as well as examples on setting attributes at the segment level, can be found in the :ref:`attributes section <prog_guide/0101_database:Attributes>`. Default values for all attributes can be found in the :doc:`appendix <appendix_default_attribute_values>`.


Geometry
--------

When a segment is created, it contains no geometry.  You can insert any type of geometry into a segment. When geometry is inserted into a segment, it becomes part of the database. Each *insert* function returns a key which is used as the geometry handle (see that :ref:`snippet <insert_geometry>` for a basic example of geometry insertion). Keys are reference counted smart pointers that do not delete the database object when they go out of scope. The key helps locate the geometry in the database letting us know its relationships to parent and children. Geometry is always part of a segment, but not all segments must contain geometry.


Subsegments
-----------

Segments can contain other segments, thus, child segments can have their own subsegments. This data model is designed to allow you to build a segment tree that logically describes your graphical scene. Common use of Visualize involves creating a segment hierarchy by attaching segments to other segments (see :doc:`Performance Considerations </prog_guide/0703_performance_considerations>` for information about recommended segment organization). To create a subsegment: 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_create_subsegment.cpp
		   :start-after: //! [create_subsegment]
		   :end-before: //! [create_subsegment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_create_subsegment.cs
		   :start-after: //! [create_subsegment]
		   :end-before: //! [create_subsegment]
		   

When calling ``Down`` or ``Subsegment``, you may supply a name for the segment. Any UTF-8 encoded name is legal. You can pass an empty string for an anonymous name, and in this case Visualize will guarantee a unique segment.


Include Segments
----------------

Graphical information inserted into a window segment ultimately goes into the rendering pipeline. However, sometimes it may be desirable to create and manipulate data without drawing immediately. For instance, imagine creating a scene graph for a turbine engine. Such a model would likely be very complex. You know that you will want to display your turbine engine in multiple windows at different times. Additionally, you might also want to export the information to a PDF file or print it to hardcopy. However, duplicating a scene graph is tedious, wastes memory, and is prone to errors. Additionally, if modifications are made to the scene, it must be made in multiple locations in order to maintain synchronicity with all scene graphs.

A more efficient way to manage the model data would be to build one scene graph which can be referenced by multiple segments. To begin constructing your scene graph, request a root segment from the Visualize database. With this root segment, you can build a segment tree that represents your model without associating it with any particular window.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_including.cpp
		   :start-after: //! [create_root_segment]
		   :end-before: //! [create_root_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_including.cs
		   :start-after: //! [create_root_segment]
		   :end-before: //! [create_root_segment]

When you request a root segment, Visualize creates a parentless segment and returns a ``HPS::SegmentKey``. You can then use the key to build your model's information hierarchy - setting attributes and inserting geometry. An isolated root segment and the information associated is never drawn unless it has a Visualize window as an ancestor. Therefore, to display your model, you must include your subtree into a window segment.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_including.cpp
		   :start-after: //! [include_segment]
		   :end-before: //! [include_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_including.cs
		   :start-after: //! [include_segment]
		   :end-before: //! [include_segment]

Once a segment is included by a window key, it will enter the rendering pipeline for that window. Multiple segments can include the model, thus, copies of the geometry can be drawn at multiple locations in a scene or in multiple windows. A change in the model will be reflected in all instances. You can also :doc:`export </prog_guide/0902_exporting_files>` your model information to a file or :ref:`print <prog_guide/0702_offscreen_rendering:Hardcopy>` to hardcopy.

.. image:: images/segment_include.png
	:align: center

*The segments representing a drawing context 'include' your model*

The ``HPS::WindowKey`` is not the only type of key that can include other segments. Any normal ``HPS::SegmentKey`` can as well.

This paradigm for creating and storing model information can also be used to organize and aggregate data. For instance, you can create multiple model segments and then use them to construct a master assembly that is itself a root segment. As an example, let's take the turbine engine. You may want to display the turbine engine by itself. However, you may also want to display it as part of the design for a whole aircraft. In each aircraft's scene graph, you can include the turbine engine using its ``HPS::SegmentKey``. Any changes in the turbine engine will be reflected in all models that include the turbine engine.

Judicious use of model segments in conjunction with window segments will help you efficiently manage and render your graphical data with minimal effort.

Filtering Include Links
-----------------------

When an include link is employed, all geometry and attributes from the target segment are included by the parent segment. It is possible to set a filter on the include key so that certain geometry or attributes can be excluded. 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_including.cpp
		   :start-after: //! [include_filter]
		   :end-before: //! [include_filter]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_including.cs
		   :start-after: //! [include_filter]
		   :end-before: //! [include_filter]

Deleting Include Links
----------------------

To sever the link between the parent key and its included segment, you must delete the include link key:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_including.cpp
		   :start-after: //! [delete_include]
		   :end-before: //! [delete_include]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_including.cs
		   :start-after: //! [delete_include]
		   :end-before: //! [delete_include]
		   

Conditional Include Links
-------------------------

Sometimes, it is useful to include a branch of a tree only when certain conditions are met. The *conditional include* mechanic provides this functionality. A *condition* is really just a flag that is set on a segment. When Visualize detects that the flag is set, the included segment is made part of the main tree and thus its geometry is rendered.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_advanced_including.cpp
		   :start-after: //! [conditional_include]
		   :end-before: //! [conditional_include]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_advanced_including.cs
		   :start-after: //! [conditional_include]
		   :end-before: //! [conditional_include]

While the code above is a trivial example of conditional include links, the real power of conditional includes becomes more apparent when many links need to be made at multiple locations in the tree. Conditions are inheritable attributes, and thus if set at the root segment, many links can be automatically included in one simple command if they all depend on the same condition.

Segment References
------------------

In some situations, you may find it necessary to instantiate geometric information at multiple places in a scene without having to worry about how the geometry is styled. Segment references enable you to do this. However, unlike include segments, segment references only import geometry - *attributes and subsegments are excluded*. A segment may be referenced any number of times.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_advanced_including.cpp
		   :start-after: //! [reference_segment]
		   :end-before: //! [reference_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_advanced_including.cs
		   :start-after: //! [reference_segment]
		   :end-before: //! [reference_segment]
		   

.. _keys:

Keys
====

In addition to segments, all other database objects in Visualize have an associated key. For example, a ``HPS::TextKey`` identifies a text string, and a ``HPS::SphereKey`` identifies a sphere. All Database modifications involve keys at some level. For example, to modify the font of a text string, you would use its key. In the code below, a simple segment is constructed. Note the relationships between the keys of the root segment, the sphere, the text, and the text font:

.. _insert_geometry:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_keys.cpp
		   :start-after: //! [keys]
		   :end-before: //! [keys]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_keys.cs
		   :start-after: //! [keys]
		   :end-before: //! [keys]

Behind the scenes, all Visualize keys are reference-counted smart pointers. You don't have to worry about initializing or deleting them. When a key goes out of scope, the object still exists in the Database.

You can use an object's key to set its fields. For example, you may use a ``HPS::CircleKey`` to set the radius and center point of a circle:

.. _geometry_keys:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_keys.cpp
		   :start-after: //! [geometry_keys]
		   :end-before: //! [geometry_keys]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_keys.cs
		   :start-after: //! [geometry_keys]
		   :end-before: //! [geometry_keys]

Note that setting attributes at the geometry level as shown in the snippet above will affect only the geometry represented by ``myCircleKey``. However, most attributes in Visualize are set at the segment level and use *attribute inheritance* to propagate values to geometry in child segments. An easy way to set attributes on a segment is to use an attribute control, as discussed in the following section.


Attributes
==========

An attribute is a setting that is used to style or alter how a segment's geometry is rendered. For each primitive, every applicable attribute must be known before the primitive can be drawn. For example, before a line can be drawn, the renderer must know the line's color, thickness, style, modelling transformation, how it is lit, and so on. A primitive can have dozens - or even hundreds - of attributes; specifying them all would be substantial work. The concept of attribute inheritance addresses this issue.

Attribute inheritance in Visualize works like inheritance in an object-oriented language. If an attribute value is not set locally on a segment, then it is inherited from a parent segment. When the database is rendered, it needs to know the attribute values for all the geometry in the database. If any required attributes have not been set on a segment, the value in the parent segment will be used. If the parent has no value, then Visualize looks at the parent's parent, and so on, until it finds a value for the attribute. The window segment of every scene graph always has a set of default attributes which will be used if no other value is set. Default values for all attributes can be found in the :doc:`appendix </prog_guide/appendix_default_attribute_values>`.

Some attributes, such as color and visibility, can be set at the segment level, geometry level, or subentity level. While this gives developers the maximum amount of flexibility in building a scene, setting attributes at the segment level is recommended for optimum performance. General performance guidelines are discussed in our section on :doc:`performance considerations <0703_performance_considerations>`.

**IMPORTANT:** Generally speaking, attribute inheritance only applies to segment-level attributes. Geometry attributes, such as the radius of a sphere, only apply to a single piece of geometry and do not inherit. If you can alter an attribute using an attribute control obtained from a ``HPS::SegmentKey``, you know this is a segment-level attribute. For example, :ref:`this snippet <edge_attribute_control_example>` shows *inheritable* line attributes being set using a ``HPS::LineAttributeControl``. :ref:`This code sample <geometry_keys>` shows *non-inheritable* geometry attributes being set on a circle using a ``HPS::CircleKey``.

Attribute controls are discussed in the following subsection.


Setting and Getting Attributes Using Attribute Controls
-------------------------------------------------------

Unlike ``HPS::CircleKey``, not every type of geometry key has its own set of attribute accessor functions. For these objects, attributes are specified using an *attribute control*. Attribute controls are available for all entities that are set at the segment level. When a segment-level attribute is set, all geometry within that segment and within all subsegments will inherit that setting. Of course, it is possible to override this by setting another attribute further down in the tree, or by using an :ref:`attribute lock <prog_guide/0101_database:Attribute locks>`.

In this example, the edge and camera controls are demonstrated, however, the other controls follow the same pattern. All of the controls are listed with the other classes in the Class Index. For an in-depth example on setting attributes and using inheritance, see :ref:`Tutorial 1 <guides/01_fundamentals:1.3 Setting attributes>`.


Example: Edge Attribute Control
-------------------------------

Edge attributes are controlled using the ``HPS::EdgeAttributeControl``. The attributes that can be modified are *edge weight* and *edge pattern*. Edge patterns and line patterns can be used interchangeably (line patterns are discussed in detail in the :doc:`line patterns page <0406_line_patterns>`). Continuing from the circle example, the results of the following code can be seen below:

.. _edge_attribute_control_example:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_controls_example.cpp
		   :start-after: //! [edge_attribute_control_example]
		   :end-before: //! [edge_attribute_control_example]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_controls_example.cs
		   :start-after: //! [edge_attribute_control_example]
		   :end-before: //! [edge_attribute_control_example]

.. image:: images/circle_pattern.png
	:align: center

*The circles drawn with the "dashdot" pattern and a heavy weight*


Example: Camera Attribute Control
---------------------------------

The ``HPS::CameraControl`` is another control that is commonly used for manipulating the scene view. The camera is complex inheritable attribute - see :ref:`this section <prog_guide/0303_cameras:Camera inheritance>` for details on camera inheritance.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_controls_example.cpp
		   :start-after: //! [camera_attribute_control_example]
		   :end-before: //! [camera_attribute_control_example]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_controls_example.cs
		   :start-after: //! [camera_attribute_control_example]
		   :end-before: //! [camera_attribute_control_example]
		   

Getting Attribute Values
------------------------

Note that you can also use attribute controls to get a segment's locally set attributes. For example, in the code snippet above, ``ShowProjection`` is used to get the camera projection. Getting attributes this way only works for attributes explicitly set on a segment. To find the value of inherited attributes, you need to use a ``HPS::KeyPath``. That procedure is documented :ref:`here <prog_guide/0102_api_conventions:Using a KeyPath>`.


.. _kits:

Using Kits to Instantiate Geometry
----------------------------------

Kits and geometry :ref:`keys <keys>` are related. They share the same settings. For most (but not all) types of keys, there is a corresponding kit type. Key objects always represent an object inside the Visualize database while kits exist entirely outside the database. You can think of a kit as a non-instanced key. Kits are useful because you can set all attributes for a future object in an independent way, without affecting the scene. Then, it can be inserted as a finished object into the database, which offers a modest performance benefit over building the same object piece-wise. Note that the kit and the resulting geometry are two separate objects. If you insert geometry using a kit, the geometry will take on the attributes of kit in the state it is in at the time of the insertion. If the kit is later changed, there will be no effect on the inserted object. Some other uses for kits include:

* inserting multiple identical or nearly-identical copies of an object into the database
* retrieving database information into one convenient object
* inserting a complex object into the database in a transactional way

The code sample below uses a ``HPS::CircleKit`` to insert two different circles using the same kit.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_using_kits.cpp
		   :start-after: //! [insert_circle]
		   :end-before: //! [insert_circle]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_using_kits.cs
		   :start-after: //! [insert_circle]
		   :end-before: //! [insert_circle]
		   
The result is show below. Note that face visibility has also been set to 'false' and a marker has been placed at the origin.

.. image:: images/coencentric_circles.png
	:align: center

*Two basic circles generated by the code above*

Attributes can also be set without the use of a kit. In that case, the *Set* functions would be called directly on the object itself. Note that this method incurs a performance penalty when compared to using a kit, as each attribute must be inserted into the database atomically instead of in a transactional way.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_using_kits.cpp
		   :start-after: //! [modify_circle]
		   :end-before: //! [modify_circle]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_using_kits.cs
		   :start-after: //! [modify_circle]
		   :end-before: //! [modify_circle]
		   

Attribute Locks
---------------

It is possible to temporarily override attributes by using an attribute lock. When a specific attribute is locked in a segment, that attribute will apply to all subsegments, even if they have a setting for the same attribute. Attribute locks may be useful when editing the attributes in a model. For example, you may display a model subassembly which already has its own attributes - but you want a 'parent' model object to have its attributes take precedence and override its children. Iterating through all the associated segments to change their attributes individually would be cumbersome - this problem is solved by attribute locks.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_using_kits.cpp
		   :start-after: //! [attribute_locks]
		   :end-before: //! [attribute_locks]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_using_kits.cs
		   :start-after: //! [attribute_locks]
		   :end-before: //! [attribute_locks]

Please note that an attribute lock is itself an attribute. So, to override a lock set by an ancestor segment, set an attribute lock on a subsegment. Additionally, when setting an attribute lock on a segment which also has an applied :doc:`style <0403_styles>`, the lock will be applied to the naturally inherited attributes - not the styled attributes.

	**IMPORTANT:** Attribute lock provides a feature for temporary rendering instances. We do not recommend that you use this feature in place of setting attributes in the normal way. When this feature is enabled, rendering performance can be impacted.

Interally, HOOPS Visualize stores attribute settings in related groups. For example, all backface diffuse settings (``BackFaceDiffuseColor``, ``BackFaceDiffuseTexture``, ``BackFaceDiffuseAlpha``) are assigned to the ``BackFaceDiffuse`` attribute lock group.

As a result, when you inspect which locks are currently set, the expected result is affected by which settings are active. If all settings of a lock group are active, HOOPS Visualize will return the group setting. Let's say you set locks for ````BackFaceDiffuseColor```` and ``BackFaceDiffuseAlpha``. If you use ``HPS::AttributeLockControl::ShowLock``, it will return those two locks as expected.

However, when showing active locks in a situation where ``BackFaceDiffuseColor``, ``BackFaceDiffuseTexture``, ``BackFaceDiffuseAlpha`` are all set, only ``BackFaceDiffuse`` would be returned. This is because in this context, BackFaceDiffuse = ``BackFaceDiffuseColor + BackFaceDiffuseTexture + BackFaceDiffuseAlpha``. The analogous situation is true for all types of material locks (``FrontFaceDiffuse``, ``CutFaceDiffuse``, etc).


.. _windows:

Connecting Visualize to a Window
================================

From a user perspective, the conventional concept of a window is a logical division of screen space controlled by one application. However, in Visualize, the term "window" is akin to a rendering context - the GUI part of the window you see on the screen is still handled by the native GUI framework. Behind the scenes, a Visualize window is represented by a segment in the scene graph. As such, each window has a unique key to identify it. Visualize offers three different types of windows, as discussed below. Regardless of the actual type of window, all window keys are derived from ``HPS::WindowKey``.

Window segments are the top-level node of a particular scene. The window segment is also where scene-level attributes, such as :doc:`anti-aliasing <0801_anti_alias>`, :doc:`bloom <0804_bloom>`, :doc:`depth of field <0808_depth_of_field>` (see ``HPS::WindowKey::SetPostProcessEffects``), and other rendering algorithms are set. Some options need to be set before window creation, and for that case, each window type has its own associated window options kit.

A window is always associated with a driver interface, through which all rendering is performed. For on-screen drivers, Visualize includes implementations of DirectX11 and OpenGL. While possible to create a multi-windowed Visualize application that uses different display drivers for each window, there can only be one driver per window. It is also not possible to change drivers after a window has been created.

While drivers can be manually specified, Visualize can also perform runtime query of the 3D capabilities of the operating system and GPU, and automatically choose the most appropriate display driver. Under Windows, preference will be given to DirectX API, followed by OpenGL. Under all other platforms, only the OpenGL API is supported. To use this capability, choose ``HPS::Window::Driver::Default3D`` when creating your window (window creation is covered below).


Application Window
------------------

The application window is the most common type of window used in a Visualize application. It is represented by ``HPS::ApplicationWindowKey``. For all but the simplest programs, this is the appropriate construct to use. For example, an application window can be hosted by a .NET UserControl, an MFC dialog, or even a plain Win32 window.

In fact, Visualize can render to any window for which you provide a handle. In Windows, the handle is the ``HWND`` parameter and is passed to the Database as shown below. Note the returned key from ``CreateApplicationWindow``, which is used to control the scene at a high level. For example, window keys are used to set selection options and trigger updates.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_application_window.cpp
		   :start-after: //! [create_application_window]
		   :end-before: //! [create_application_window]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_application_window.cs
		   :start-after: //! [application_window]
		   :end-before: //! [application_window]
		   

Off-Screen Window
-----------------

Although technically a window in Visualize, the offscreen window isn't visible to the user. This type of window is a memory buffer. However, it is still a completely functional Visualize rendering context. Offscreen windows are discussed in detail :doc:`here <0702_offscreen_rendering>`.


Stand-Alone Window
------------------

The standalone window is used when no host window is provided to host Visualize. In this situation, Visualize will create a default window and use it for rendering. The standalone window may be useful for quick prototyping, testing, or for very simple applications without GUI controls. The Visualize rendering context will use the entire window for rendering. The code below is a complete program that will result in a blank Visualize window:

.. tabs::

	.. group-tab:: C++
	
		.. code-block:: cpp
	
			#include "hps.h"

			using namespace HPS;

			int _tmain(int argc, _TCHAR* argv[])
			{
				World world();
				StandAloneWindowKey sawk = Database::CreateStandAloneWindow();
				sawk.Update();

				return 0;
			}
		   
	.. group-tab:: C#
	
		.. code-block:: c#

			using HPS;

			namespace HPS_020612_3
			{
				class Program
				{
					static World world = new World(); // it is important to have a static reference to avoid garbage collector
					
					static void Main(string[] args)
					{
						StandAloneWindowKey sawk = Database.CreateStandAloneWindow();
						sawk.Update();
					}
				}
			}
		   
To set the size of a standalone window, use the ``HPS::StandAloneWindowOptionsKit`` to set the subscreen:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_sawok.cpp
		   :start-after: //! [sawok]
		   :end-before: //! [sawok]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_sawok.cs
		   :start-after: //! [sawok]
		   :end-before: //! [sawok]
		   

.. _portfolios:
		   
Portfolios and definitions overview

In Visualize, a *definition* is an entity that encapsulates a type of styling. Unlike segments, they do not have parents, children or siblings. Instead, they belong to a *portfolio*. A portfolio is a named area where definitions are created and stored. An example of a definition is a texture, line pattern, or custom glyph. Organizing these resources into a portfolio makes reuse relatively simple.

Like all other database elements, every portfolio has a unique key associated with it called a ``HPS::PortfolioKey``. Portfolios can be shared among segments. Once the styles have been organized into different portfolios, they can be used in a scene graph. A single segment can use only one portfolio at a time, however, child segments inherit all definitions from their parents' portfolios and can augment or replace them by definitions in their own portfolio.

.. image:: images/portfolios.png
	:align: center

*Portfolios include the resources used to style a segment*

To learn more about portfolios and definitions, please see the 
:doc:`portfolios and definitions discussion <0401_portfolios_introduction>` beginning in section 4.


.. _traversal:

Database Traversal
==================

Using a ``HPS::SegmentKey``, it is possible to get the parent and children segments using the ``Up()`` and ``Down()`` methods. 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_traversal.cpp
		   :start-after: //! [traversal_1]
		   :end-before: //! [traversal_1]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_traversal.cs
		   :start-after: //! [traversal_1]
		   :end-before: //! [traversal_1]

Note that if ``Up()`` is called on a segment that has no parent, such as a root segment or a window key, the returned key will be invalid. If you try to use an invalid key an ``HPS::InvalidObjectException`` will be thrown. Therefore, if there is any doubt about the validity of a ``HPS::SegmentKey``, use the ``HPS::SegmentKey::Type()`` function:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_traversal.cpp
		   :start-after: //! [traversal_2]
		   :end-before: //! [traversal_2]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_traversal.cs
		   :start-after: //! [traversal_2]
		   :end-before: //! [traversal_2]

If you need a child ``HPS::SegmentKey`` but you don't explicitly know the name associated with it, you can use ``HPS::SegmentKey::ShowSubsegments`` to get an array of all children:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_traversal.cpp
		   :start-after: //! [traversal_3]
		   :end-before: //! [traversal_3]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_traversal.cs
		   :start-after: //! [traversal_3]
		   :end-before: //! [traversal_3]


.. _database_search:

Database Search
===============

Often, ``HPS::Database`` traversal is too limited or cumbersome to use when you already know what you're looking for, especially when the scene graph is extensive. In this case, a Database search is more appropriate. Searches are always done using the ``HPS::SegmentKey::Find`` function, and can be used to find objects within a segment, any subsegment, or all subsegments and included segments. The results are returned in a ``HPS::SearchResults`` object. Imagine you are using a Database search to find all circles in your scene. One way to do this would be the following:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_search.cpp
		   :start-after: //! [search]
		   :end-before: //! [search]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_search.cs
		   :start-after: //! [search]
		   :end-before: //! [search]

**IMPORTANT:** Using the ``Type()`` function has performance implications. Please see our section on :ref:`using keys <prog_guide/0102_api_conventions:Identifying keys>` for details.

Most types of geometry and attributes can be specified as a search parameter. To search for everything, use the search parameter ``HPS::Search::Type::Everything`` (or ``HPS.Search.Type.Everything`` in C#).

**IMPORTANT:** Attributes and user data set on geometry is *not* searched using the database search. If your application depends on the search feature, you should plan to set attributes at the segment level.


.. _search_behavior:

Search Behavior
---------------

An overload to ``HPS::SegmentKey::Find`` accepts a ``HPS::SearchOptionsKit``. In addition to the criteria and search space parameters offered by the example above, *behavior* is also an option when using the search options kit. The search behavior can be set to ``HPS::Search::Behavior::FirstMatch`` or ``HPS::Search::Behavior::Exhaustive``. ``Exhaustive`` will return all matches in the subtree you specify whereas ``FirstMatch`` only returns the first item that matches your search criteria. 

A third option, ``ExhaustivePaths``, will instruct the system to record the paths to objects and return multiple copies if found. Normally, this is not the case - the search will only return one copy of instanced geometry. This option would most commonly would be used with the search space set to ``SubsegmentsAndIncludes`` and is particularly useful when you want each individual instance of an included object to be returned in the search results set (along with its path). While looking at the results of such a search, ``HPS::KeyPath HPS::SearchResultsIterator::GetPath() const;`` may be used to query the path associated with an item.


.. _user_data:

User Data
=========

Mapping scene graph data to application data can be useful in a variety of situations - especially when performing a query or responding to a selection. The HOOPS Visualize database allows you to associate your external data with segments or with individual pieces of geometry. Visualize calls this data *user data*. User data is optional, and is always supplied and interpreted by the developer.

All user data is stored in the Database as a byte array. Any ``HPS::GeometryKey`` or ``HPS::SegmentKey`` can have user data. User data does not conform to the a traditional attribute rules in that it does not inherit to child segments.

Any number of user data entries can be present on a particular segment or geometry key. When setting the data, you choose an index on which the data is placed. Indices do not have to be sequential, but must be unique within the segment (indices that are already in use will be overwritten). The code snippet below demonstrates how to set, retrieve, and unset user data.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_user_data.cpp
		   :start-after: //! [user_data]
		   :end-before: //! [user_data]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_user_data.cs
		   :start-after: //! [user_data]
		   :end-before: //! [user_data]

**NOTE:** When :doc:`loading an HSF file <0901_importing_files>`, any user options present in the file will be UTF8 encoded and stored as user data. 


