======
Styles
======

A style is a collection of attributes that is applied to a segment as a set. In complex segment trees, you may have segments that are not related hierarchically, but nonetheless share common attributes. You *could* set attributes for each segment individually. However, that is not only inefficient, but also inconvenient, especially when the modifications involve a large number of segments. Instead, defining and using a style provides a convenient way to take a set of attributes and apply them to many segments. Any attribute that can be set on a segment can also be set in a style.


.. _named_styles:

Named Styles
============

The recommended way to create a style is by creating and using a ``HPS::NamedStyleDefinition``. Named styles are those which are referenced by a name you assign to them. Attributes are set on the style object itself. In this example, a green wireframe style is applied to the style definition:

.. tabs::

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

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_create_named_style.cs
		   :start-after: //! [create_named_style]
		   :end-before: //! [create_named_style]
		   
		   
.. _style_segments:
		   
Style Segments
==============

A style can also be defined by setting attributes on a *style segment*. A style segment is a segment with attributes that are used as the source of the style. The segment does not have to be part of the scene hierarchy. If you have many styles, you may want to consider creating a style library. A style library is an informal collection of segments which hold no geometry and are used only as a source of styles.

Code for creating and using a style is shown below. The concept is the same as using a named style, but instead of setting attributes on the style definition object, you style the segment directly:

.. tabs::

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

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

Each segment has an associated style stack which allows a segment to have more than one style applied to it. In this case, the style settings at the top of the stack overrides any conflicting style information that may be present below. You can unset  a style by using one of the following:

.. tabs::

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

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

.. _conditional_styles:

Using Conditional Styles
========================

A conditional style is a style that is automatically applied to a segment when a set of conditions are met. The "condition" is merely a set of flags that is set on on a segment. The flags themselves are strings.

.. tabs::

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

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

While the basic example above is too simple to warrant setting up the condition mechanism, the benefit of using conditions becomes more apparent when applied to multiple segments. For instance, imagine you have a model with many different parts, some of which are supposed to become invisible when the scene is rotated in a certain way. Since conditions inherit down the tree like other attributes, this means you need only set the condition at the root segment for all subsegments with that conditional style to be made invisible.


.. _complex_conditional_styles:

Complex Conditional Styles
==========================

Segments can be marked with more than one condition at a time.

.. tabs::

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

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

|HPSNOW| can also interpret basic conditional operators using ``HPS::OR`` and ``HPS::AND``. To create one of these complex conditions, they must be combined into a single condition. For example, if you want a condition of ``("c1" OR "c2") AND "c3"``, you could construct it as demonstrated below:

.. tabs::

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

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

|HPSNOW| also supports ``XOR`` and ``NOT`` operators. Up to 10 conditions are supported for a single conditional operator. However, you can construct an arbitrarily large conditions [the presence of ``AND`` and ``OR`` constructors which take multiple arguments is to make it more convenient to do things like ``AND(c1, c2, c3)`` instead of having to do ``AND(AND(c1, c2), c3)``].


.. _style_stack:

Using Multiple Styles With the Style Stack
==========================================

|HPSNOW| uses a stack to manage styles. Each segment either has its own stack or inherits one from a parent. Anytime you set a style, you are implicitly using the style stack. If you are using only one style per segment, the style stack is transparent because you are only working with the top element. However, to enable multiple styles on the same segment, instead of *setting* the style, you must *push* the style onto the segment's style stack. To do this, simply call ``PushStyle``:

.. tabs::

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

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_style_stack.cs
		   :start-after: //! [push_style]
		   :end-before: //! [push_style]
		   
When rendering, |HPSNOW| will examine the style stack and apply the styles individually. In the case that styles have overlapping attributes, the attributes of the most recently pushed style will take precedence over styles further down in the stack.

It is possible to edit the style stack by getting an array of the current styles and then modifying that array. So, for example, to remove a style from the middle of a stack of three styles:

.. tabs::

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

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