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

After a selection is performed, it is usually necessary to provide visual feedback to the user regarding what was selected. This section will focus on how to implement efficient highlighting. 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
======================

A *style* is a collection of attributes that is applied to a segment as a set. Any attribute that can be set on a segment can also be set in a style. In complex segment trees, you may have segments that are not related hierarchically, but nonetheless share common attributes. Using a style provides a convenient way to apply a set of attributes to many segments. You can apply styles using their segment key, or you can name a style with ``Define_Named_Style``, and then apply it using its name. 
  

Highlighting a Segment
======================

In HOOPS Visualize, highlighting is best achieved by first defining a named style, and then using ``Define_Highlight`` to apply the named style. This applies the named style in a temporary but efficient manner. This highlighting method has two important performance benefits over setting attributes directly in the scene:

It does not require a full update of the scene. Only the highlighted geometry needs to be redrawn. 

Since it does not modify the segment structure, static models do not need to be regenerated.

To remove the highlight, use ``UnDefine_Highlight``.

Highlight attributes take precedence over all other attributes in the scene, even child attributes and attribute locks. You can chose to respect attribute locks by using the "passive" option in ``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:

.. code-block:: c

    // creating the highlight style, in this case a root segment contains the highlight attributes which are simply yellow for all geometry
    HC_KEY styleKey = HC_Open_Segment("/style");
        HC_Set_Color("geometry=yellow");
    HC_Close_Segment();
    
    // inserting the shell and setting initial attributes
    HC_Open_Segment_By_Key(sceneKey);
        HC_Insert_Shell(pcount, pts, flist_count, faces);
        HC_Set_Color("faces=white, edges=black, windows=white");
        HC_Set_Visibility("edges=on");
        
        // here is where the style is defined
        HC_Define_Named_Style("myHighlightStyle", "/style");
    HC_Close_Segment();
    
After the scene is set up, the actual highlighting is done this way:

.. code-block:: c

    HC_Define_Highlight(1, &sceneKey, "myHighlightStyle", "quick moves=overlay");

.. image:: images/highlighting.png
    
    A piece of geometry before (left) and after overlay highlighting.
    

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

In the example above, note the option "quick moves=overlay" passed to the call to ``Define_Highlight``. The "quick moves" options parameter of ``Define_Highlight`` specifies the highlight algorithm. The highlight algorithm should be made based on how you want the highlight to appear, and has important performance implications for highlighting. There are three modes to choose from: "InPlace", "Overlay", and "Spriting". 
  
*InPlace*

The "InPlace" highlighting option is used when you want to use a highlight style that is partially transparent, changes visibility, or moves the geometry (with a modelling matrix). 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 automatically 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``.

  
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:: ../../../../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 erase 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:: ../../../../demo/common/sanity/0700_docs_0028.cpp
		   :start-after: //! [highlight_search]
		   :end-before: //! [highlight_search]


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

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``.


Legacy Highlighting Methods
============================

*Generation 1: Conditional Styles*

* Applies a style directly on the segment. Need to use attribute locks. 
* A condition is used to ensure that you're highlighting the correct instance (key path, include, etc). 
* Condition could be used as a toggle for common styles. 
* For entity level, you must copy geometry. 

Disadvantages: Heavy. Requires editing the tree which could complicate export. Full screen redraw. Incompatible with static model. Poor entity support. 

*Generation 2: Include into a style segment*

* Include the highlighted segment (or reference) in a special segment with highlighting attributes. Need to use attribute locks. 
* Need to collect net attributes to parent and apply that in tandem with highlight attributes. 
* Advantages: Plays well with static model. Not editing the (main) tree. 

Disadvantages: net attributes, poor sub-entity support

*Generation 3: Defines (current)*

* Plays well with static model
* Not modifying the tree. 
* No net-attribute accumulation. 
* No attribute locks
* Handle segment, entity, and sub-entity. 

We strongly recommend using the latest highlighting method described above when possible. Even if your application already uses older highlighting methods, the modern highlighting methods are advantageous enough to be worth rewriting legacy code. 

For the benefit of applications that were developed before the new highlighting methods were available, this section will describe the legacy highlighting methods. Remember, however, that this method carries the the disadvantage of requiring a full scene redraw to apply highlighting, and also requires static model regeneration if you that option. 
