UI draw manager

The MUIDrawManager class provides a straight forward way for API users to draw basic UI elements such as: lines, circles, arcs, icons, and text.

While previous APIs allowed for what is commonly called immediate mode drawing, MUIDrawManager exposes a different type of interaction closer to retained mode drawing. The logic consists of queuing items to draw “drawables” into a “drawable” list.

Actual retained mode drawing is associated with MRenderItem usage. You should use interfaces that use MRenderItems when more complex geometry or shading is required, and MUIDrawManager for additional drawables.

The decision as to whether to use MUIDrawManager is mostly based on a choice between simplicity versus flexibility. A basic breakdown of the pros and cons of using MUIDrawManager is provided in the following table:

Strengths Caveats
Suitable for simple UI, where simple means a small amount of UI, or a when a small number of objects are drawing the UI. May not scale well since drawables are not persistent, though MPxSubSceneOverride allows for reuse.
Easier to port legacy draw code as it looks more like immediate mode drawing. Avoids the complexity of using MRenderItems. Provides a fixed set of shading options, and single texture drawing. The geometry attributes that can be specified are fixed.
Supports 2D drawing without having to worry about the matrix transformations required. Cannot take advantage of consolidation (since they are not persistent).
Supports text, icons, lines, face styles, depth priority, basic 2D and 3D primitives, and arbitrary meshes. Has no inherent concept of participating based on viewport display modes.
Available for all main interfaces including being the only interface for manipulator and tool contexts for 3d viewports and the UV Texture Editor. Will not participate in post effects and advanced transparency options (as MRenderItems can).
One set of code that can be reused across all supported hardware drawing APIs. Fixed draw order based on provided properties.

Each drawable automatically uses the appropriate shader instance and geometry based on the type of draw item. For example, text has an appropriate “text shader”. This knowledge is hidden from the user for simplicity.

The manager checks each drawable and places the drawables into lists which are drawn at different times within the render pipeline. Currently, control over list placement is not exposed in MUIDrawManager. Users of MUIDrawManager should be aware that there are explicit properties depending on the list that the drawable is drawn from, and that the interface from which the MUIDrawManager is used generally determines list placement. For example, queuing drawables from the manager provided via the manipulator interface means that drawables are not depth tested nor written to depth.

MUIDrawManager is not designed for accessing at arbitrary time or at arbitrary places. Access to the interface is thus restricted to a few methods on various API interfaces. Any data and context information management is prepared by the manager and passed to the caller as appropriate. Examples of information that may be passed back to the caller include: DAG path, pass information, and view information. For example, some drawables like heads-up-display elements may need to scale with respect to the viewport rectangle.

The MUIDrawManager is owned by the renderer and cannot be explicitly constructed.

The following interfaces currently support MUIDrawManager:

MPxDrawOverride, MPxGeometryOverride and MPxSubSceneOverride have common methods with signatures that can be overridden to use MUIDrawManager.

The virtual functions are:

The method hasUIDrawables() can be overridden to return true to indicate that the user wishes to add drawables via the addUIDrawables() method. A false value means to skip calling addUIDrawables().

The method addUIDrawables() is the main method which allows access to MUIDrawManager. Drawables that are queued here can be thought of as additional render items that can be filtered or bucketed into the appropriate render item list in the pipeline.

Drawables are transient in nature, and as such there is an inherent cost to recreate them each refresh. MPxSubSceneOverride has an additional virtual method:

MPxSubSceneOverride::areUIDrawablesDirty()

which can be overridden to indicate that drawables are persistent between draw calls.

For manipulators MPxManipContainer and MPxManipulatorNode, two override methods provide interaction with MUIDrawManager:

These methods are only called when the current renderer is Viewport 2.0.

preDrawUI() is always called before drawUI(). preDrawUI() allows the user to perform draw data preparation. Then, drawUI() uses the passed in MUIDrawManager to draw with the draw data. The drawables queued are rendered after a draw of scene DAG objects, and before the drawing of the HUD (heads-up-display).

For tool contexts, MPxContext has the following methods available:

These methods are only called when the current renderer is Viewport 2.0.

They can be thought of as the Viewport 2.0 version of doPress/doRelease/doDrag/doHold/doEnterRegion and doPtrMoved. Plug-ins can override these functions to implement the equivalent behavior to that of the default viewport.

MUIDrawManager can also be used for render overrides. For MUserRenderOperation and MHUDRender, two methods may be used:

For MSceneRender, three functions may be used:

Override these functions to define the drawables to be drawn during the user, HUD, pre-scene, or post-scene render operations.

As mentioned, MUIDrawManager can be thought of having retained mode drawing. As such, certain states can be set which are applied to the drawables queued after a given state is set.

To control line display attributes, possible line state controls include setting the width and line style.

For example:

For controlling primitive paint style, setPaintStyle() can be used to allow flat-shaded, stippled, or shaded drawing to be applied. Shaded drawing uses an internal fixed material.

For controlling text, size can be set as a retained mode state (setFontSize()).

MUIDrawManager supports both 3D and 2D drawable interfaces, and 2D interfaces are generally denoted with "2d" appended to the name of the method. For example line() is for 3D drawable, and line2d() is for a 2D drawable.

It should be noted that for 2D drawables, only x and y components of a 3d position or vector are used, and the unit for drawing is in screen pixels.

Examples: