============
Highlighting
============

After a selection is performed, it is usually necessary to provide visual feedback to the user regarding what was selected. For example, the scene might contain a picture of an airplane wing which is represented by several pieces of geometry. However, HOOPS Visualize knows nothing about the airplane wing as a distinct concept. Therefore, if you wanted to highlight the entire wing after the user selects any part of it, you would need to figure out all the associated pieces of geometry and highlight them all. Depending on model complexity, this can be a non-trivial task.

This section will focus on some of the ways in which geometry can be highlighted as well as a strategy to manage highlighting easily. The details of how to represent highlighting are up to the developer. You could choose to modify the object's color, line weight, face pattern, visibility, shading mode, or any combination of these and other attributes. You must also choose the highlight algorithm, which is discussed :ref:`below <prog_guide/3dgs/04_4_user_interaction_highlighting:Choosing the highlight algorithm>`.
  

Defining a named style
======================

In HOOPS Visualize, a *style* is a collection of attributes that is applied to a segment as a set. Styles are applied to geometry to differentiate it within a scene. It is also the recommended way to apply highlighting effects. In complex segment trees, you may have segments that are not related hierarchically, but nonetheless share common attributes. One way to apply a style would be to set attributes individually for each segment as needed. 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.

The recommended way to create a style is by creating a new segment (perhaps in your style library) and setting attributes on that segment which define your style. You assign a name to the style segment. When you want to apply that style to highlighted geometry, you would call ``Define_Highlight``, referencing the name of the style segment. ``UnDefine_Highlight`` removes the style.
  

Highlighting a segment
======================

Highlighting at a segment level simply involves opening the segment and calling ``Define_Highlight`` with a previously named style. Note that this will affect the open segment, as well as any subsegments which do not have their own opinion about the attributes being modified. If you want all subsegments to have the same highlight attributes, regardless of local explicit settings, you can use the "attribute lock" rendering option:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0019.cpp
		   :start-after: //! [attribute_lock_color]
		   :end-before: //! [attribute_lock_color]

This is useful when you want to highlight an entire piece of the segment tree. For example, let's say the database was representing adrawing with multiple layers, with various systems such as HVAC, piping, andelectrical. If the GUI is in 'layer highlight' mode, you could  highlight a selected layer by setting the desired highlight attributes at a top-level layer parent segment, and then setting attribute lock in that segment. 
  

Choosing the highlight algorithm
--------------------------------

The choice of highlight algorithm should be made based on how you want the highlight to appear. There are three modes to choose from: "InPlace", "Overlay", and "Spriting". The mode is set in the ``options`` "quick moves" parameter of ``Define_Highlight``.
  
*InPlace*

The "InPlace" highlighting option is used when you want to use a highlight style that is partially transparent. InPlace will cause Visualize to not draw the highlighted geometry itself, since doing so would cause the color of the geometry to blend with the color of the transparent highlight. Therefore, the geometry is not drawn at all - the highlight is drawn "in its place". One downside to using this method of highlighting is that when the geometry is eventually unhighlighted, the scene will have to be redrawn. This is in contrast to "overlay" or "spriting" highlighting options, which are able to unhighlight without redrawing the scene.

*Overlay*

Overlay highlights are drawn on top of all other geometry in the scene. This means if you highlight a piece of geometry that is partially obscured, overlay highlights will cause that geometry to "pop out" visually, ignoring z-values. Unhighlighting does not trigger a redraw.

*Spriting*

Spriting is the default highlight algorithm. In this highlight mode, z-values are preserved, so you won't get the pop-out effect of overlay highlighting. It is also fairly fast, although unlike "InPlace", it does require the geometry to be drawn twice - once for the geometry itself, and once for the highlight.

  
Fine-tuning highlight behavior
------------------------------

Various options are available to achieve the highlighting behavior that you require when using ``Define_Highlight``. For example, the "passive" option means that locked attributes won't be overridden. The "append" option will override any conflicting styles defined by previous highlights. See the API Reference Manual for more details on ``Define_Highlight``.


Example
-------

Below is an example of how a segment is highlighted. In order for your named style to be found, it must be defined in the segment where you will eventually be using the style, or an ancestor segment:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0028.cpp
		   :start-after: //! [setup_highlight_segment]
		   :end-before: //! [setup_highlight_segment]
		   
After the scene is set up, the actual highlighting is done this way:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0028.cpp
		   :start-after: //! [highlight_segment]
		   :end-before: //! [highlight_segment]

.. image:: images/highlighting.png

*A piece of geometry before (left) and after overlay highlighting*

  
Highlighting a single object
============================

A segment will commonly contain graphical primitives that represent discrete pieces of the model. Let's say we have an 'asteroid' segment which contains a shell for each asteroid. If the GUI is in 'single asteroid selection mode', then we need to highlight a single asteroid. Setting highlight attributes at the segment-level won't work since all the asteroids will be affected by that new attribute. So, we need to modify the database so that only the selected object will be drawn with the new highlight attributes. 

A brute force way to achieve this is to move the object (``Move_By_Key``) to a highlight segment, and move it back to the original segment to unhighlight. However, this has a major performance implication, since changing the contents of a segment segment will cause HOOPS to trigger a full screen redraw. To avoid such a full screen redraw and provide very fast highlighting/unhighlighting, an approach called 'quickmoves include/reference highlighting' should be used.
	
	
Quickmoves include/reference highlighting
-----------------------------------------

The :doc:`scene-interaction section </prog_guide/3dgs/04_5_interacting_with_scene>` reviews how only making changes to the contents of a quickmoves segment between updates will not cause HOOPS to perform a full update. Instead, HOOPS will only clear/redraw the graphical primitives in the segments that have the 'quickmoves' attribute. We can leverage this capability in conjunction with HOOPS 'include' and 'reference' capabilities, to perform fast highlighting/unhighlighting.

To prepare for highlighting, we would first create a 'highlight' segment that contains the 'quickmoves' setting and desired highlight attributes (color, line-pattern, etc...) When a segment, segment tree, or list of graphical primitives needs to be highlighted, either ``Include_Segment`` or ``Reference_Geometry`` can be called in the highlight segment. The documentation for :ref:`include segments <prog_guide/3dgs/01_3_database_dbase_structure:Include segments>` and :doc:`reference geometry </prog_guide/3dgs/02_18_geometry_reference>` will help you determine which one may be appropriate. But simply stated, Include_Segment would be used to highlight a whole segment tree, while ``Reference_Geometry`` would be used to highlight a single segment or set of graphical primitives.

Let's imagine we are modelling an airplane fuselage which has a few subcomponents. The fuselage is located in the airplane_fuselage segment and the subcomponents are in the subsegments fuse1, fuse2, and fuse3. You can control highlighting in the following way:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0028.cpp
		   :start-after: //! [quickmoves_include_reference_highlighting]
		   :end-before: //! [quickmoves_include_reference_highlighting]
		   
Because we have 'quickmoves' set in the highlight segment(s), making changes to those segments to effectively 'unhighlight' (such as deleting the Reference or Include by deleting the include_key and reference_key, respectively) will not cause HOOPS to redraw the entire scene.  HOOPS will simply 'undraw' the quickmoves geometry.

There is one caveat with the highlighting technique above.  We're highlighting by drawing a new instance (reference/include) of the geometry, and that instance would have the same position.  That means it will come out directly 'superimposed' on top of the original, unhighlighted geometry, resulting in geometry that 'bleeds' together. To address that, we can set the 'general displacement' value in the highlight-attributes segment to -8. This will 'pull' the highlighted copy forward a bit in the z-buffer, and avoid superimposition and thus any edge/face bleeding.


Highlight search
================

In certain circumstances, it may be useful to know if a segment is highlighted, or to know which highlight modes are currently in use. Visualize provides a few functions for this purpose. 

To determine if a segment is highlighted, call ``Determine_Highlight_Status`` with a key path to the segment you want to query. You may also specify a filter to further narrow results, such as which type of highlight you are interested in. This function will return a value which indicates specifics about how the highlighting is applied. See the API Reference for more details on ``Determine_Highlight_Status``.

``Find_Highlight`` is used to find which highlights are applied to the open segment, and works in a similar fashion to other scene graph searches with ``Begin`` and ``End`` guards:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0028.cpp
		   :start-after: //! [highlight_search]
		   :end-before: //! [highlight_search]


HOOPS/MVO Highlighting example
==============================

The HOOPS/MVO classes contain a class called ``HSelectionSet`` which provides higher level highlighting support. This class is intended to be used along with the other HOOPS/MVO classes, but its methods can be referred to for a reference implementation of segment and single object highlighting. The code handles other issues that were not mentioned above, such as dealing with include segments, and storing away a segment's original set of attributes (so that they can be restored later). It manages a selection array, and provides methods such as ``Select``, ``DeSelect``, ``DeSelectAll``, and ``IsSelected``.
