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 MRenderItem
s 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
MPxSubSceneOverride
MPxManipContainer
MPxManipulatorNode
MPxContext
MUserRenderOperation
/MHUDRender
/MSceneRender
MPxDrawOverride
, MPxGeometryOverride
and MPxSubSceneOverride
have common methods with signatures that can be overridden to use MUIDrawManager
.
The virtual functions are:
virtual bool hasUIDrawables() const;
virtual void addUIDrawables(const MDagPath& objPath, MUIDrawManager& drawManager, const MFrameContext& frameContext, const MUserData* data);
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
:
virtual void preDrawUI(const M3dView &view);
virtual void drawUI(MHWRender::MUIDrawManager& drawManager, const MHWRender::MFrameContext& frameContext) const;
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:
virtual MStatus doPress (MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
virtual MStatus doRelease(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
virtual MStatus doDrag (MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
virtual MStatus doHold (MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
virtual MStatus doEnterRegion (MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
virtual MStatus doPtrMoved (MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
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:
virtual bool hasUIDrawables() const;
virtual void addUIDrawables(MUIDrawManager& drawManager, const MFrameContext& frameContext);
For MSceneRender
, three functions may be used:
virtual bool hasUIDrawables() const;
virtual void addPreUIDrawables(MUIDrawManager& drawManager, const MFrameContext& frameContext);
virtual void addPostUIDrawables(MUIDrawManager& drawManager, const MFrameContext& frameContext);
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:
void setLineWidth(float value);
sets line width state to a given value in pixels.
void setLineStyle(LineStyle style);
sets line style from a set of pre-defined line styles. These include solid, short dotted, short dashed, dashed, and dotted. For greater control, the method:
void setLineStyle(unsigned int factor, unsigned short pattern);
can be used,
where factor is a multiplier for each bit in the pattern;
where pattern is a bit-mask pattern that determines the fragments of a line to be drawn.
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:
MPxDrawOverride
examples:pyFootPrintNode.py
) and a C# implementation (footPrintNode.cs
) also exist.MUIDrawManager
.MPxGeometryOverride
examples:pyFootPrintNode_GeometryOverride.py
) version also exists.MRenderOverride
(render override) examples:MPxContext
(tool context) example:MPxSubSceneOverride
example: