MPxDrawOverride Class Reference

MPxDrawOverride Class Referenceabstract
+ Related help topics:

#include <MPxDrawOverride.h>

Class Description

Base class for user defined drawing of nodes.

MPxDrawOverride allows the user to define custom draw code to be used to draw all instances of a specific DAG object type in Maya when using Viewport 2.0.

transform() should always return the world space transformation matrix for the object to be drawn in the custom draw code. The default implementation simply returns the transformation defined by the parent transform nodes.

isBounded() can return true or false to indicate whether the object is bounded or not respectively. If a false value is returned then camera frustum culling will not be performed against the bounding box. In this situation the boundingBox() method will not be called since the bounding box is not required.

boundingBox() should always return the object space bounding box for whatever is to be drawn in the custom draw code. If the bounding box is incorrect the node may be culled at the wrong time and the custom draw method might not be called.

When the object associated with the draw override changes, prepareForDraw() is called which allows the user to pull data from Maya to be used in the draw phase. It is invalid to query attribute values from Maya nodes during the draw callback and doing so may result in instability.

The method excludedFromPostEffects() allows for the plug-in to indicate whether to contribute to passes which are required for post effects. If so, the plug-in's draw() may be called multiple times, once for each pass. Note that even without overriding this method that the plug-in's draw can be called more than once (e.g. for a shadow map pass).

The method isTransparent() allows for the plug-in to indicate whether the object should be drawn as transparency. If so, the plug-in's draw() will be called two times, one for front-culling pass and one for back-culling pass. It will never be called into weighted average or depth peeling. Note that without overriding this method or make the method return false means the object will only be drawn once in opaque pass.

addUIDrawables() provides access to the MUIDrawManager, which can be used to queue up operations for drawing simple UI elements such as lines, circles and text. It is called just after prepareForDraw() and carries the same restrictions on the sorts of operations it can perform. To enable addUIDrawables(), override hasUIDrawables() and make it return true. UI elements are not affected by post effects, and hence are not affected by the excludedFromPostEffects() return value.

At draw time, the user defined callback will be invoked at which point any custom OpenGL drawing may occur. Data needed from the Maya dependency graph must have been cached in the prepareForDraw() stage as it is invalid to query such data during the draw callback.

Implementations of MPxDrawOverride must be registered with Maya through MDrawRegistry. If the registration contains "/includePostEffects" this will override the value returned from excludedFromPostEffects(). If the registration contains "/isTransparent" this will override the value returned from isTransparent(). For example, a classification starts with "/drawdb/geometry/testNode/includePostEffects/isTransparent" means testNode should contribute to passes required for post effect and it is a transparent object for draw.

When using the MHWRender::MRenderer::setGeometryDrawDirty() interface to mark a DAG object associated with an MPxDrawOverride object dirty, the optional topologyChanged parameter must be set to true.

+ Examples:

Public Types

typedef void(* GeometryDrawOverrideCb) (const MDrawContext &, const MUserData *)
 User draw callback definition, draw context and blind user data are parameters.
 

Public Member Functions

 MPxDrawOverride (const MObject &obj, GeometryDrawOverrideCb callback, bool isAlwaysDirty=true)
 Construct an MPxDrawOverride. More...
 
virtual ~MPxDrawOverride ()
 Destructor.
 
virtual ::MHWRender::DrawAPI supportedDrawAPIs () const
 Returns the draw API supported by this override. More...
 
virtual bool hasUIDrawables () const
 In order for any override for the addUIDrawables() method to be called this method must also be overridden to return true. More...
 
virtual MMatrix transform (const MDagPath &objPath, const MDagPath &cameraPath) const
 Called by Maya whenever the world space transform is needed for the object to be drawn by the draw callback. More...
 
virtual MBoundingBox boundingBox (const MDagPath &objPath, const MDagPath &cameraPath) const
 Called by Maya whenever the bounding box of the drawable object is needed. More...
 
virtual bool isBounded (const MDagPath &objPath, const MDagPath &cameraPath) const
 Called by Maya to determine if the drawable object is bounded or not. More...
 
virtual bool disableInternalBoundingBoxDraw () const
 Indicates whether to disable the automatic drawing of bounding boxes when the display mode has been set to bounding box display. More...
 
virtual bool excludedFromPostEffects () const
 Indicates whether or not the draw code should be called for any additional passes required to perform post effects. More...
 
virtual bool isTransparent () const
 Indicates whether or not the draw method should be called for each transparency pass(front-culling and back-culling). More...
 
virtual MUserDataprepareForDraw (const MDagPath &objPath, const MDagPath &cameraPath, const MFrameContext &frameContext, MUserData *oldData)=0
 Called by Maya whenever the object is dirty and needs to update for draw. More...
 
virtual void addUIDrawables (const MDagPath &objPath, MUIDrawManager &drawManager, const MFrameContext &frameContext, const MUserData *data)
 Provides access to the MUIDrawManager, which can be used to queue up operations to draw simple UI shapes like lines, circles, text, etc. More...
 
virtual bool refineSelectionPath (const MSelectionInfo &selectInfo, const MRenderItem &hitItem, MDagPath &path, MObject &geomComponents, MSelectionMask &objectMask)
 Maya calls this function during the selection interpretation phase of Viewport 2.0 selection and can be used to override the selected path, the selected components or simply reject the selection. More...
 
virtual void updateSelectionGranularity (const MDagPath &path, MSelectionContext &selectionContext)
 Maya calls this function during the pre-filtering phase of Viewport 2.0 selection and is used to setup the selection context of the given DAG object. More...
 
virtual bool traceCallSequence () const
 This method allows a way for a plug-in to examine the basic call sequence for a draw override. More...
 
virtual void handleTraceMessage (const MString &message) const
 When debug tracing is enabled via MPxDrawOverride::traceCallSequence(), this method will be called for each trace message. More...
 
virtual bool wantUserSelection () const
 This method is called during the hit test phase of Viewport 2.0 selection and is used to indicate whether or not the userSelect() method should be called to override the default hit test implementation for the associated DAG object. More...
 
virtual bool userSelect (const MSelectionInfo &selectInfo, const MDrawContext &context, const MDagPath &objPath, const MUserData *data, MSelectionList &selectionList, MPointArray &worldSpaceHitPts)
 This method is called during the hit test phase of Viewport 2.0 selection if wantUserSelection() returns true, in order to override the default hit test implementation for the associated DAG object. More...
 
virtual bool userSelect (MSelectionInfo &selectInfo, const MDrawContext &context, MPoint &hitPoint, const MUserData *data)
 This method is obsolete. More...
 

Static Public Member Functions

static const char * className ()
 Returns the name of this class. More...
 

Protected Member Functions

MStatus setGeometryForRenderItem (MRenderItem &renderItem, const MVertexBufferArray &vertexBuffers, const MIndexBuffer *indexBuffer, const MBoundingBox *objectBox) const
 Call this method to provide the geometry for a render item. More...
 

Static Protected Member Functions

static MStatus drawRenderItem (const MHWRender::MDrawContext &context, MRenderItem &item)
 Call this method to draw a render item constructed for the MPxDrawOverride. More...
 
static bool pointSnappingActive ()
 This utility function can be called by a draw override to query whether Viewport 2.0 selection has been launched to find points for snapping. More...
 

Constructor & Destructor Documentation

MPxDrawOverride ( const MObject obj,
GeometryDrawOverrideCb  callback,
bool  isAlwaysDirty = true 
)

Construct an MPxDrawOverride.

Parameters
[in]objThe Maya object this override draws
[in]callbackThe callback function to be invoked at draw time
[in]isAlwaysDirtyIf true, this override will always be updated (via prepareForDraw() or addUIDrawables()) without checking the dirty state of the Maya object. To avoid any unnecessary performance overhead due to the frequency of calling the update methods, the flag can be set to false. In this case the update methods will only be called when the Maya object is marked dirty via DG evaluation or dirty messages. To explicitly mark an object as being dirty the MRenderer::setGeometryDrawDirty() method can be used. Default is true.

Member Function Documentation

MHWRender::DrawAPI supportedDrawAPIs ( ) const

Returns the draw API supported by this override.

The returned value may be formed as the bitwise or of MHWRender::DrawAPI elements to indicate that the override supports multiple draw APIs. This method returns MHWRender::kOpenGL by default.

Returns
The draw API supported by this override
+ Examples:
bool hasUIDrawables ( ) const
virtual

In order for any override for the addUIDrawables() method to be called this method must also be overridden to return true.

This method should not be overridden if addUIDrawables() has not also been overridden as there may be associated wasted overhead.

Returns
Whether addUIDrawables() will be called or not.
+ Examples:
MMatrix transform ( const MDagPath objPath,
const MDagPath cameraPath 
) const
virtual

Called by Maya whenever the world space transform is needed for the object to be drawn by the draw callback.

The default implementation simply returns the transformation defined by the parent transform nodes in Maya. Override to get custom behaviour.

Parameters
[in]objPathThe path to the object whose transform is needed
[in]cameraPathThe path to the camera that is being used to draw
Returns
The world space transformation matrix
MBoundingBox boundingBox ( const MDagPath objPath,
const MDagPath cameraPath 
) const
virtual

Called by Maya whenever the bounding box of the drawable object is needed.

This method should return the object space bounding box for the object to be drawn.

Note that this method will not be called if the isBounded() method returns a value of false.

Default implementation returns a huge bounding box which will never cull the object.

Parameters
[in]objPathThe path to the object being drawn
[in]cameraPathThe path to the camera that is being used to draw
Returns
The object space bounding box of object drawn in the draw callback
+ Examples:
bool isBounded ( const MDagPath objPath,
const MDagPath cameraPath 
) const
virtual

Called by Maya to determine if the drawable object is bounded or not.

If the object is not bounded then it will never be culled by the current camera frustum used for drawing.

The default implementation will always return true. This method can be overridden in derived classes to customize the behaviour.

Note that if this method returns false then the boundingBox() method will not be called as no bounds are required in this case.

Parameters
[in]objPathThe path to the object being drawn
[in]cameraPathThe path to the camera that is being used to draw
Returns
True if object is bounded
+ Examples:
bool disableInternalBoundingBoxDraw ( ) const
virtual

Indicates whether to disable the automatic drawing of bounding boxes when the display mode has been set to bounding box display.

Note that bounding box drawing is also disabled if the isBounded() method has been set to false. As noted the boundingBox() method is never called under this condition. As such with no bounding box information provided it is not possible to automatically draw due to insufficient information provided.

Returns
True to disable bounding box drawing. The default value is false.
+ Examples:
bool excludedFromPostEffects ( ) const
virtual

Indicates whether or not the draw code should be called for any additional passes required to perform post effects.

Note that the appropriate pass identifier and pass semantic can be queried at draw time via the MPassContext data structure. Also note that if the pass requires a shader override that it can be obtained from the MDrawContext data structure provided at draw time.

Returns
False to indicate inclusion in post effects. The default value is true.
+ Examples:
bool isTransparent ( ) const
virtual

Indicates whether or not the draw method should be called for each transparency pass(front-culling and back-culling).

Returns
True to indicate inclusion in transparency passes. The default value is false.
MUserData * prepareForDraw ( const MDagPath objPath,
const MDagPath cameraPath,
const MFrameContext frameContext,
MUserData oldData 
)
pure virtual

Called by Maya whenever the object is dirty and needs to update for draw.

Any data needed from the Maya dependency graph must be retrieved and cached in this stage. It is invalid to pull data from the Maya dependency graph in the draw callback method and Maya may become unstable if that is attempted.

Implementors may allow Maya to handle the data caching by returning a pointer to the data from this method. The pointer must be to a class derived from MUserData. This same pointer will be passed to the draw callback. On subsequent draws, the pointer will also be passed back into this method so that the data may be modified and reused instead of reallocated. If a different pointer is returned Maya will delete the old data. If the cache should not be maintained between draws, set the delete after use flag on the user data and Maya will delete it in a certain stage depending on whether the draw callback exists. If exists, the user data will be deleted after both addUIDrawables() and the draw callback are called; otherwise, the user data will be deleted immediately after addUIDrawables() is called. In all cases, the lifetime and ownership of the user data is handled by Maya and the user should not try to delete the data themselves. Data caching occurs per-instance of the associated DAG object. The lifetime of the user data can be longer than the associated node, instance or draw override. Due to internal caching, the user data can be deleted after an arbitrary long time. One should therefore be careful to not access stale objects from the user data destructor. If it is not desirable to allow Maya to handle data caching, simply return NULL in this method and ignore the user data parameter in the draw callback method.

Parameters
[in]objPathThe path to the object being drawn
[in]cameraPathThe path to the camera that is being used to draw
[in]frameContextFrame level context information
[in]oldDataData cached by the previous draw of the instance
Returns
Pointer to data to be passed to the draw callback method
+ Examples:
void addUIDrawables ( const MDagPath objPath,
MUIDrawManager drawManager,
const MFrameContext frameContext,
const MUserData data 
)
virtual

Provides access to the MUIDrawManager, which can be used to queue up operations to draw simple UI shapes like lines, circles, text, etc.

This method will only be called when this override is dirty and its hasUIDrawables() is overridden to return true. This method is called after prepareForDraw() and carries the same restrictions on the sorts of operations it can perform.

Parameters
[in]objPathThe path to the object being drawn
[in]drawManagerThe UI draw manager, it can be used to draw some simple geometry including text
[in]frameContextFrame level context information
[in]dataData cached by prepareForDraw()
+ Examples:
bool refineSelectionPath ( const MSelectionInfo selectInfo,
const MRenderItem hitItem,
MDagPath path,
MObject components,
MSelectionMask objectMask 
)
virtual

Maya calls this function during the selection interpretation phase of Viewport 2.0 selection and can be used to override the selected path, the selected components or simply reject the selection.

  • One can decide to change the selected path (ie: select the bottom-most transform instead of the proposed path).
  • One can decide to remove or add component to the proposed selected list.
  • One can decide to change the selection mask of the object (ie: override the selection mask returned by a component converter).
  • One can decide that the proposed selection (path or component) is not acceptable and discard it (ie: return false).

The default implementation does nothing and returns True (selection is accepted).

Parameters
[in]selectInfoThe selection info
[in]hitItemThe render item hit
[in,out]pathThe selected path
[in,out]componentsThe selected components
[in,out]objectMaskThe object selection mask
Returns
True the selection candidate is acceptable
void updateSelectionGranularity ( const MDagPath path,
MSelectionContext selectionContext 
)
virtual

Maya calls this function during the pre-filtering phase of Viewport 2.0 selection and is used to setup the selection context of the given DAG object.

This is useful to specify the selection level, which defines what can be selected on the object :

This is used to discard objects that are not selectable given the current selection mode (see MGlobal::selectionMode()).

The default implementation does nothing and the default selection level for a MPxDrawOverride is kObject.

Parameters
[in]pathThe path to the instance to update the selection context for
[out]selectionContextThe selection context
bool traceCallSequence ( ) const
virtual

This method allows a way for a plug-in to examine the basic call sequence for a draw override.

The default implementation returns false meaning no tracing will occur.

Returns
Whether to turn on call sequence tracing
+ Examples:
void handleTraceMessage ( const MString message) const
virtual

When debug tracing is enabled via MPxDrawOverride::traceCallSequence(), this method will be called for each trace message.

The default implementation will print the message to stderr.

Parameters
[in]messageA string which will provide feedback on either an internal or plug-in call location. To help distinguish which draw override a message is associated with, the full path name for the DAG object (associated with the draw override) may be included as part of the string.
+ Examples:
bool wantUserSelection ( ) const
virtual

This method is called during the hit test phase of Viewport 2.0 selection and is used to indicate whether or not the userSelect() method should be called to override the default hit test implementation for the associated DAG object.

This method returns false by default. In this case the draw callback method is invoked for the selection pass, with a special shader that encodes each entity with a different plain color, then the draw buffer is scanned and each color found inside the selection region is transformed into hit info that will be used by the later selection interpretation phase, including selected item and world-space hit point.

If a custom hit test implementation is required, this method must be overridden to return true in order for userSelect() to be called.

Returns
Whether userSelect() should be called
bool userSelect ( const MSelectionInfo selectInfo,
const MDrawContext context,
const MDagPath objPath,
const MUserData data,
MSelectionList selectionList,
MPointArray worldSpaceHitPts 
)
virtual

This method is called during the hit test phase of Viewport 2.0 selection if wantUserSelection() returns true, in order to override the default hit test implementation for the associated DAG object.

The selection info encapsulates the selection states such as the selection region. The draw context along with the user data cached by prepareForDraw() provides information the same as that being passed to the draw callback, thus makes it possible for a draw override to match its custom hit test with its custom drawing (a.k.a. WYSIWYG selection).

If the object is hit, the implementation should add the DAG path and if appropriate its component to selectionList. It is the responsibility of the implementation to add world-space coordinate of the intersection between the selected item and selection ray to worldSpaceHitPts.

A custom hit test implementation can choose GPU-based approaches such as OpenGL selection mode, occlusion query etc., or CPU-based approaches which perform hit test for custom geometries. Note that a custom hit test implementation is an object-level override, thus the default hit test implementation can still work for other objects in the scene.

After a scene traversal in the hit test phase, Maya records a list of selected items and hit points. During the selection interpretation phase, the hit points will be sorted for certain cases such as single selection; only the winning hit point(s) will have the corresponding selected item(s) to call the refineSelectionPath() method for final selection result that is used to adjust the global active selection list. Thus, for these cases, Maya can only guarantee correct behavior if the implementation returns a valid hit point.

For cases such as marquee selection over multiple components, where hit points don't matter, instead of creating one component object for each selected component element, the implementation should create one component object for all selected component elements, to avoid any unnecessary performance overhead due to the frequency of calling refineSelectionPath().

For cases such as point snapping, where multiple hit points are required, each hit point should be stored with the same array index as its selected item (typically a vertex component object), in order for Maya to associate each pair of selected item and hit point.

Parameters
[in]selectInfoThe selection info
[in]contextThe draw context
[in]objPathThe path to the associated DAG object
[in]dataThe data cached by prepareForDraw()
[out]selectionListList of items selected by this method
[out]worldSpaceHitPtsList of hit points
Returns
True if at least one object was hit. The default value is false.
bool userSelect ( MSelectionInfo selectInfo,
const MDrawContext context,
MPoint hitPoint,
const MUserData data 
)
virtual

This method is obsolete.

This method is invoked when MPxDrawOverride::wantUserSelection() returns true.

[From Maya 2019]

Deprecated:
Use the other userSelect() method instead.

Return true from this function to indicate Maya the MPxDrawOverride with given MUserData instance is selected regarding current selection context.

Parameters
[in]selectInfoA reference to MSelectionInfo from which the selection region and other information can be queried.
[in]contextThe reference to MDrawContext that allows the derived class to implement drawing based selection method, or the plug-in can retrieve the world transform matrix for other purpose like performing hit testing on CPU.
[in,out]hitPointThe hit position that Maya will use for depth sorting of selected objects. Returning the correct hit position to result correct selection based on viewport visibility, especially in single selection mode. By default this parameter has been assigned to the local origin of current DAG path's transform. It is the responsibility of plug-ins to calculate the accurate hit position in world space.
[in]dataThis is the same user data that MPxDrawOverride::prepareForDraw() returns.
Returns
True the object is selected.
const char * className ( )
static

Returns the name of this class.

Returns
Name of this class.
MStatus setGeometryForRenderItem ( MRenderItem renderItem,
const MVertexBufferArray vertexBuffers,
const MIndexBuffer indexBuffer,
const MBoundingBox objectBox 
) const
protected

Call this method to provide the geometry for a render item.

Although the render item will add a reference to each buffer, ultimate ownership of the geometric data remains with the caller. This method may only be called on render items which have been generated by this override. Buffers may be shared among multiple render items. This method will replace any geometry currently associated with the render item with the newly provided geometry.

The bounding box parameter to this method is optional. If NULL, Maya will attempt to calculate the box automatically. Note that this may require a read-back of vertex data from the graphics card which can be a very slow operation. It is better to supply a correct bounding box whenever possible.

It is the responsibility of the caller to ensure that the buffers provided fulfill the geometry requirements of the shader for the render item. If the requirements are not met, the render item will not draw. If there is no shader assigned to the render item, this method will fail.

Parameters
[in]renderItemThe render item to provide geometry for
[in]vertexBuffersThe vertex buffers for the geometry
[in]indexBufferThe index buffer for the geometry. Can be NULL.
[in]objectBoxObject-space bounding box, may be NULL
Returns
Status code
Status Codes:
MStatus drawRenderItem ( const MHWRender::MDrawContext context,
MRenderItem item 
)
staticprotected

Call this method to draw a render item constructed for the MPxDrawOverride.

This method is only valid to call from a derived class's draw callback function.

Parameters
[in]contextThe draw context for the current draw pass.
[in]itemThe render item to draw.
Returns
Status code
Status Codes:
bool pointSnappingActive ( )
staticprotected

This utility function can be called by a draw override to query whether Viewport 2.0 selection has been launched to find points for snapping.

If so, in order for the associated DAG object to participate,

Returns
True if snapping to points is active.

The documentation for this class was generated from the following files:
  • MPxDrawOverride.h
  • MPxDrawOverride.cpp