Skip to content
Zach Kinstner edited this page Nov 2, 2016 · 4 revisions

Renderers provide size, shape, and graphics for a target element (like an item or cursor). Each renderer creates a visual representation of their element, allows significant customization of its own behavior and appearance, and constantly updates (based on the element's interaction state) to display dynamic visual feedback for users.

A renderer is typically packaged as a Unity prefab, and applied to an element as a complete unit. Each renderer prefab contains a hierarchy of objects, which are primarily controlled by standardized components, and sometimes adjusted or extended using renderer module components.

The renderer itself does not have a direct reference to its target element. Instead, the element is responsible for passing its data and state information into the renderer. The element does not need to know any details about the renderer; all element-specific renderers (like a cursor renderer) share a particular interface, allowing elements to swap between different renderer styles (regardless of appearance or internal structure).

Overview

Updaters

Each renderer type (currently: item, cursor, and idle) has an "updater" component. This component is responsible for instantiating the renderer (via prefab) and continually passing information from the element into its renderer. The component attaches to the element itself (not the renderer).

For example, each item object uses the HoverItemRendererUpdater component to pass item-related information into the renderer.

Programming Interface

Each renderer prefab has a HoverRenderer-based component (like HoverRendererButton) attached to its root object. This component is responsible for providing a consistent programming interface for querying and updating the renderer. There are currently four of these components: Button (for non-slider-type items), Slider, Cursor, and Idle.

Indicators

Renderers use the HoverIndicator component to pass highlight and selection progress through their object hierarchy. Each component within the renderer can use this information to adjust its appearance. For example, an item renderer typically shows visual effects for both highlight and selection progress, growing or changing based upon the information provided by the indicator component.

The interactions in Hover UI Kit depend on visual indicators to make interactive items more discoverable to users, to clearly communicate cursor proximity, to help orient the user in 3D space, and to show when the item's selection event will occur. See the Themes page for more details.

Shapes

Renderers use HoverShape-based components to define the size and shape of their graphics, to become discoverable for layouts, and to calculate proximity-to-cursor values. Shape components automatically pass information to child shape components, and are typically present throughout the renderer's object hierarchy.

There are currently two main shape types. "Rect" shapes use the HoverShapeRect component, which provides properties for the width and height of the rectangle. "Arc" shapes use the HoverShapeArc component, which provides properties for the inner radius, outer radius, and total degrees of the radial segment.

Meshes

Renderers use HoverMesh-based components to create meshes for drawing the renderer's graphics. These components modify their meshes procedurally (via code) based on various factors, including changes to the "shape" information, "indicator" information, colors, or other mesh-related properties.

Each mesh component is based on a specific shape component (like "Rect" or "Arc"). There may be several different mesh components for any one shape component. For example, one "Rect" shaped mesh type may build a standard rectangular mesh, while another may build one with rounded corners, and another may build one with a small "tab" triangle pointing out of it. Some mesh components may even be built to interlock seamlessly with, or to wrap around, other meshes of the same type.

Most mesh components can react to a HoverIndicator component's values, and provide properties for selecting a particular type of reaction. For example, an increasing "highlight" value could optionally cause the inner radius of the "Arc" mesh to grow smaller. This allows renderers to easily use meshes for drawing dynamic visual indicators (like cursor proximity and item selection).

Most mesh components provide properties to control the way its UV values are calculated. This allows a renderer to dynamically adjust the texturing of each mesh. In addition, some form of "Auto UV" property is typically available. The exact "auto" behavior may vary, but it often automatically compensates for changes to the mesh size to avoid unwanted texture stretching. For example, a progress meter (built with an "Auto UV" mesh) might continually adjust the texture to "become revealed" as the meter grows toward 100%.

Fills

Renderers use a "fill" component to manage the meshes that draw the renderer's shape. These meshes form "layers" (overlapping or not) that should move and resize in a coordinated manner. A typical list includes background, highlight, and selection layers.

The HoverFill base component provides standardized methods for obtaining the fill's mesh and shape components. Subclasses (like HoverFillButton) provide semantic access to the meshes, and sometimes provide additional properties needed for its specific usage scenarios.

Proximity

An item's size and shape is determined by its renderer, so the renderer must calculate proximity-to-cursor information for the item. The HoverItemRendererUpdatercomponent (attached to the item object, not the renderer) implements the IProximityProvider interface, allowing the item to request proximity calculations based on a cursor's position or a cursor's raycast.

Internally, the renderer typically passes the proximity calculations into its "shape" component. The result of an item's proximity request varies based upon the cursor behavior:

  • For standard cursors, the result is the nearest point (relative to the cursor position) on the "surface" of the renderer. For example, an "arc" shape would find a point on the arc's 3D plane, constrained within the arc's angles and radii.
  • For raycast cursors, the result is the nearest point (relative to the cursor's ray) on the "surface" of the renderer. The ray will not always intersect the renderer's "surface", so additional information (like the "is hit" state, the nearest position in the vicinity of the renderer, etc.) is included in the result.
Clone this wiki locally