uiDrawManager/uiDrawManager.cpp
 
 
 
uiDrawManager/uiDrawManager.cpp
//-
// ==========================================================================
// Copyright 2012 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+

// Plugin: uiDrawManager.cpp

// This plugin demonstrates the use of MUIDrawManager.
//
// It provides the 'uiDrawManager' node which uses MUIDrawManager to display 3D (world coordinates) 
// or 2D (screen coordinates) primitives such as text, lines, spheres, etc, based on values set 
// on its attributes.
//
// For example, to draw a 2D, 15x30 pixel rectangle in the viewport, centered on pixel position 
// (50, 20) and tilted at a 45 degree angle, you would do the following:
// createNode -n testo uiDrawManager;
// setAttr testo.draw2D true;
// setAttr testo.rectScale -type double 2 15 30;
// setAttr testo.position -type double 3 50 20 0;
// setAttr testo.rectUp -type double3 1 1 0;

#include <maya/MPxLocatorNode.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnStringData.h>
#include <maya/MFnPointArrayData.h>
#include <maya/MPointArray.h>
#include <maya/MUintArray.h>

// Viewport 2.0 includes
#include <maya/MDrawRegistry.h>
#include <maya/MPxDrawOverride.h>
#include <maya/MUserData.h>

using namespace MHWRender;

class uiDrawManager : public MPxLocatorNode
{
public:
        enum EuiType {
                kText,
                kLine,
                kPoint,
                kRect,
                kQuad,
                kSphere,
                kCircle,                
                kArc,           
        };

public:
        uiDrawManager();
        virtual ~uiDrawManager();

        static void*                    creator();
        static MStatus                  initialize();

        // ui type attribute
        static MObject                  aUIType;

        // color
        static MObject                  aPrimitiveColor;
        static MObject                  aPrimitiveTransparency;

        // line width and line style attributes 
        static MObject                  aLineWidth;
        static MObject                  aLineStyle;

        // fill attribute
        static MObject                  aIsFilled;

        // radius attribute
        static MObject                  aRadius;

        // 2D attributes
        static MObject                  aDraw2D;
        static MObject                  aPosition;

        // Text attributes
        static MObject                  aTextAlignment;
        static MObject                  aTextBoxSize;
        static MObject                  aText;  
        static MObject                  aTextBoxColor;
        static MObject                  aTextBoxTransparency;
        static MObject                  aTextFontSize;

        // point attributes
        static MObject                  aPointSize;

        // line attributes
        static MObject                  aLineStartPoint;
        static MObject                  aLineEndPoint;

        // rect attributes
        static MObject                  aRectUp;
        static MObject                  aRectNormal;
        static MObject                  aRectScale;

        // quad attributes
        static MObject                  aQuadVertex[4];

        // circle attributes
        static MObject                  aCircleNormal;

        // arc attributes
        static MObject                  aArcStart;
        static MObject                  aArcEnd;
        static MObject                  aArcNormal;
public:
        static  MTypeId         id;
        static  MString         drawDbClassification;
        static  MString         drawRegistrantId;
};

MObject uiDrawManager::aUIType;

MObject uiDrawManager::aPrimitiveColor;
MObject uiDrawManager::aPrimitiveTransparency;

MObject uiDrawManager::aLineWidth;
MObject uiDrawManager::aLineStyle;

MObject uiDrawManager::aIsFilled;

MObject uiDrawManager::aRadius;

MObject uiDrawManager::aDraw2D;
MObject uiDrawManager::aPosition;

MObject uiDrawManager::aTextAlignment;
MObject uiDrawManager::aTextBoxSize;
MObject uiDrawManager::aText;
MObject uiDrawManager::aTextBoxColor;
MObject uiDrawManager::aTextBoxTransparency;
MObject uiDrawManager::aTextFontSize;

MObject uiDrawManager::aPointSize;

MObject uiDrawManager::aLineStartPoint;
MObject uiDrawManager::aLineEndPoint;

MObject uiDrawManager::aRectUp;
MObject uiDrawManager::aRectNormal;
MObject uiDrawManager::aRectScale;

MObject uiDrawManager::aQuadVertex[4];

MObject uiDrawManager::aCircleNormal;

MObject uiDrawManager::aArcStart;
MObject uiDrawManager::aArcEnd;
MObject uiDrawManager::aArcNormal;

MTypeId uiDrawManager::id(0x0008002A);
MString uiDrawManager::drawDbClassification("drawdb/geometry/uiDrawManager");
MString uiDrawManager::drawRegistrantId("uiDrawManagerPlugin");

uiDrawManager::uiDrawManager() {}

uiDrawManager::~uiDrawManager() {}

void* uiDrawManager::creator()
{
        return new uiDrawManager();
}


//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Viewport 2.0 override implementation
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class uiDrawManagerData : public MUserData 
{
public:
        uiDrawManagerData();
        virtual ~uiDrawManagerData() {};

        uiDrawManager::EuiType fUIType;

        MColor fColor;  

        float fLineWidth;
        MUIDrawManager::LineStyle fLineStyle;

        bool fIsFilled;

        double fRadius;

        bool fDraw2D;

        MPoint fPosition;

        // text
        MString fText;
        MUIDrawManager::FontSize fTextFontSize;
        MUIDrawManager::TextAlignment fTextAlignment;   
        int fTextBoxWidth;
        int fTextBoxHeight;     
        MColor fTextBoxColor;

        // point
        float fPointSize;

        // line
        MPoint fLineStartPoint;
        MPoint fLineEndPoint;

        // rect
        MVector fRectUp;
        MVector fRectNormal;
        double fRectScaleX;
        double fRectScaleY;

        // quad
        MPoint fQuadVertex[4];

        // circle
        MVector fCircleNormal;

        // arc
        MVector fArcStart;
        MVector fArcEnd;
        MVector fArcNormal;
};

uiDrawManagerData::uiDrawManagerData() : MUserData(false) 
        , fUIType(uiDrawManager::kText)
        , fColor(1.0f, 0.0f, 0.0f, 1.0f)        
        , fLineWidth(2.0f)
        , fLineStyle(MUIDrawManager::kSolid)    
        , fIsFilled(false)
        , fRadius(1.0)
        , fDraw2D(false)
        , fPosition(0.0, 0.0, 0.001)
        // text
        , fText("uiDrawManager-Text")
        , fTextFontSize(MUIDrawManager::kDefaultFontSize)
        , fTextAlignment(MUIDrawManager::kLeft)
        , fTextBoxWidth(200)
        , fTextBoxHeight(40)
        , fTextBoxColor(0.0f, 1.0f, 1.0f, 1.0f) 
        // point
        , fPointSize(2.0f)
        // line
        , fLineStartPoint(0.0, 0.0, 0.0)
        , fLineEndPoint(1.0, 1.0, 1.0)
        // rect
        , fRectUp(0.0, 1.0, 0.0)
        , fRectNormal(0.0, 0.0, 1.0)
        , fRectScaleX(1.0)
        , fRectScaleY(1.0)      
        // circle
        , fCircleNormal(0.0, 0.0, 1.0)
        // arc
        , fArcStart(1.0, 0.0, 0.0)
        , fArcEnd(0.0, 1.0, 0.0)
        , fArcNormal(0.0, 0.0, 1.0)
{
        // quad
        fQuadVertex[0] = MPoint(0.0, 0.0, 0.0);
        fQuadVertex[1] = MPoint(1.0, 0.0, 0.0);
        fQuadVertex[2] = MPoint(1.0, 1.0, 0.0);
        fQuadVertex[3] = MPoint(0.0, 1.0, 0.0);

}

class uiDrawManagerDrawOverride : public MPxDrawOverride
{
public:
        static MPxDrawOverride* Creator(const MObject& obj)
        {
                return new uiDrawManagerDrawOverride(obj);
        }

        virtual ~uiDrawManagerDrawOverride();

        virtual DrawAPI supportedDrawAPIs() const;

        virtual bool isBounded(
                const MDagPath& objPath,
                const MDagPath& cameraPath) const;

        virtual MBoundingBox boundingBox(
                const MDagPath& objPath,
                const MDagPath& cameraPath) const;

        virtual MUserData* prepareForDraw(
                const MDagPath& objPath,
                const MDagPath& cameraPath,
                const MFrameContext& frameContext,
                MUserData* oldData);

        virtual bool hasUIDrawables() const { return true; }

        virtual void addUIDrawables(
                const MDagPath& objPath,
                MHWRender::MUIDrawManager& drawManager,
                const MHWRender::MFrameContext& frameContext,
                const MUserData* data);

        static void draw(const MHWRender::MDrawContext& context, const MUserData* data);

protected:

private:
        uiDrawManagerDrawOverride(const MObject& obj);
};

uiDrawManagerDrawOverride::uiDrawManagerDrawOverride(const MObject& obj)
        : MPxDrawOverride(obj, uiDrawManagerDrawOverride::draw)
{
}

uiDrawManagerDrawOverride::~uiDrawManagerDrawOverride()
{
}

DrawAPI uiDrawManagerDrawOverride::supportedDrawAPIs() const
{
        // this plugin supports both GL and DX
        return (kOpenGL | kDirectX11);
}

bool uiDrawManagerDrawOverride::isBounded(const MDagPath& /*objPath*/,
        const MDagPath& /*cameraPath*/) const
{
        return false;
}

MBoundingBox uiDrawManagerDrawOverride::boundingBox(
        const MDagPath& objPath,
        const MDagPath& cameraPath) const
{
        return MBoundingBox();
}

MUserData* uiDrawManagerDrawOverride::prepareForDraw(
        const MDagPath& objPath,
        const MDagPath& cameraPath,
        const MHWRender::MFrameContext& frameContext,
        MUserData* oldData)
{
        uiDrawManagerData* data = dynamic_cast<uiDrawManagerData*>(oldData);
        if (!data) {
                data = new uiDrawManagerData();
        }

        MStatus status;
        MObject uiDrawManagerNode = objPath.node(&status);
        if (status) {
                // retrieve uiType
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aUIType);
                        data->fUIType = (uiDrawManager::EuiType)plug.asShort();
                }

                // common attributes
                // retrieve color
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aPrimitiveColor);
                        MObject o = plug.asMObject();
                        MFnNumericData nData(o);
                        nData.getData(data->fColor.r, data->fColor.g, data->fColor.b);                  
                }

                // retrieve transparency
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aPrimitiveTransparency);
                        data->fColor.a = 1.0f - plug.asFloat();
                }
                
                // retrieve line width
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aLineWidth);
                        data->fLineWidth = plug.asFloat();
                }

                // retrieve line style
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aLineStyle);
                        data->fLineStyle = (MUIDrawManager::LineStyle)plug.asShort();
                }
                
                // retrieve filled flag         
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aIsFilled);
                        data->fIsFilled = plug.asBool();
                }

                // retrieve radius
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aRadius);
                        data->fRadius = plug.asDouble();
                }

                // retrieve 2D flag
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aDraw2D);
                        data->fDraw2D = plug.asBool();
                }

                // retrieve screen position
                {
                        MPlug plug(uiDrawManagerNode, uiDrawManager::aPosition);
                        MObject o = plug.asMObject();
                        MFnNumericData nData(o);                                
                        nData.getData(data->fPosition.x, data->fPosition.y, data->fPosition.z);
                        data->fPosition.w = 1.0f;
                }

                switch (data->fUIType) 
                {
                case uiDrawManager::kText:
                        // retrieve text
                        {               
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aText);
                                data->fText = plug.asString();
                        }       

                        // retrieve text font size
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aTextFontSize);
                                data->fTextFontSize = (MUIDrawManager::FontSize)plug.asShort();                 
                        }               

                        // retrieve text alignment
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aTextAlignment);
                                data->fTextAlignment = (MUIDrawManager::TextAlignment)plug.asShort();
                        }               

                        // retrieve text box size
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aTextBoxSize);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                        
                                nData.getData(data->fTextBoxWidth, data->fTextBoxHeight);                       
                        }               

                        // retrieve text box color
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aTextBoxColor);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);
                                nData.getData(data->fTextBoxColor.r, data->fTextBoxColor.g, data->fTextBoxColor.b);                             
                        }

                        // retrieve text box transparency
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aTextBoxTransparency);
                                data->fTextBoxColor.a = 1.0f - plug.asFloat();
                        }
                        break;                  

                case uiDrawManager::kPoint:
                        // retrieve point size
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aPointSize);
                                data->fPointSize = plug.asFloat();
                        }

                        break;

                case uiDrawManager::kLine:
                        // retrieve line start point
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aLineStartPoint);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fLineStartPoint.x, data->fLineStartPoint.y, data->fLineStartPoint.z);
                                data->fLineStartPoint.w = 1.0f;
                        }

                        // retrieve line end point
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aLineEndPoint);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fLineEndPoint.x, data->fLineEndPoint.y, data->fLineEndPoint.z);
                                data->fLineEndPoint.w = 1.0f;
                        }

                        break;

                case uiDrawManager::kRect:
                        // retrieve rect up vector
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aRectUp);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fRectUp.x, data->fRectUp.y, data->fRectUp.z);                               
                        }

                        // retrieve rect normal vector
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aRectNormal);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fRectNormal.x, data->fRectNormal.y, data->fRectNormal.z);           
                        }

                        // retrieve rect scale
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aRectScale);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fRectScaleX, data->fRectScaleY);
                        }

                        break;

                case uiDrawManager::kQuad:
                        // retrieve quad vertices
                        {
                                for (int i = 0; i < 4; ++i)
                                {
                                        MPlug plug(uiDrawManagerNode, uiDrawManager::aQuadVertex[i]);
                                        MObject o = plug.asMObject();
                                        MFnNumericData nData(o);
                                        nData.getData(data->fQuadVertex[i].x, data->fQuadVertex[i].y, data->fQuadVertex[i].z);
                                }
                        }

                        break;

                case uiDrawManager::kCircle:
                        // retrieve circle normal
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aCircleNormal);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fCircleNormal.x, data->fCircleNormal.y, data->fCircleNormal.z);     
                        }

                        break;

                case uiDrawManager::kArc:
                        // retrieve arc start vector
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aArcStart);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fArcStart.x, data->fArcStart.y, data->fArcStart.z);
                        }

                        // retrieve arc end vector
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aArcEnd);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fArcEnd.x, data->fArcEnd.y, data->fArcEnd.z);       
                        }

                        // retrieve arc normal
                        {
                                MPlug plug(uiDrawManagerNode, uiDrawManager::aArcNormal);
                                MObject o = plug.asMObject();
                                MFnNumericData nData(o);                                
                                nData.getData(data->fArcNormal.x, data->fArcNormal.y, data->fArcNormal.z);      
                        }

                        break;

                case uiDrawManager::kSphere:
                        break;

                default:
                        perror("unhandled ui type.");
                        break;
                }                       
        }

        return data;
}

void uiDrawManagerDrawOverride::addUIDrawables(
        const MDagPath& objPath,
        MHWRender::MUIDrawManager& drawManager,
        const MHWRender::MFrameContext& frameContext,
        const MUserData* data)
{
        const uiDrawManagerData* thisdata = dynamic_cast<const uiDrawManagerData*>(data);
        if (!thisdata) {
                return;
        }

        switch (thisdata->fUIType) 
        {
        case uiDrawManager::kText: 
                {
                        // Draw a text "uiDrawManager"
                        // All drawing operations must take place between calls to beginDrawable()
                        // and endDrawable().
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setFontSize(thisdata->fTextFontSize);
                        int boxSize[] = { thisdata->fTextBoxWidth, thisdata->fTextBoxHeight };
                        if (thisdata->fDraw2D) {
                                // uiDrawManagerData::fPosition gives a screen space position 
                                // where 2D UI item is located.                         
                                drawManager.text2d(thisdata->fPosition, thisdata->fText, thisdata->fTextAlignment, 
                                        boxSize, &thisdata->fTextBoxColor, false);
                        }
                        else {
                                // for 3D items, place it at the origin of the world space.
                                drawManager.text(thisdata->fPosition, thisdata->fText, thisdata->fTextAlignment, 
                                        boxSize, &thisdata->fTextBoxColor, false);
                        }                       

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kLine:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setLineWidth(thisdata->fLineWidth);
                        drawManager.setLineStyle(thisdata->fLineStyle);
                        if (thisdata->fDraw2D) {
                                drawManager.line2d(thisdata->fLineStartPoint, thisdata->fLineEndPoint);
                        }
                        else {
                                drawManager.line(thisdata->fLineStartPoint, thisdata->fLineEndPoint);
                        }

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kPoint:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setPointSize(thisdata->fPointSize);
                        if (thisdata->fDraw2D) {
                                drawManager.point2d(thisdata->fPosition);
                        }
                        else {
                                drawManager.point(thisdata->fPosition);
                        }               

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kRect:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setLineWidth(thisdata->fLineWidth);
                        drawManager.setLineStyle(thisdata->fLineStyle);
                        if (thisdata->fDraw2D) {
                                // For 2d rectangle, an up vector in screen space is used to determine its X 
                                // and Y directions. In addition, "fRectScaleX" and "fRectScaleY"(in pixels)
                                // specify the half-lengths of the 2d rectangle.
                                drawManager.rect2d(thisdata->fPosition, thisdata->fRectUp,
                                        thisdata->fRectScaleX, thisdata->fRectScaleY, thisdata->fIsFilled);
                        }
                        else {
                                // For 3d rectangle, the up vector should not be parallel with the normal vector.
                                drawManager.rect(thisdata->fPosition, thisdata->fRectUp, thisdata->fRectNormal,
                                        thisdata->fRectScaleX, thisdata->fRectScaleY, thisdata->fIsFilled);
                        }

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kQuad:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setLineWidth(thisdata->fLineWidth);
                        drawManager.setLineStyle(thisdata->fLineStyle);

                        // prepare primitive type
                        MUIDrawManager::Primitive mode = 
                                thisdata->fIsFilled ? MUIDrawManager::kTriStrip : MUIDrawManager::kClosedLine;
                        // prepare position list
                        MPointArray position;
                        for (int i = 0; i < 4; ++i) {
                                position.append(thisdata->fQuadVertex[i]);
                        }
                        // prepare index
                        MUintArray index;
                        index.append(0);
                        index.append(1);
                        index.append(3);
                        index.append(2);                        

                        // draw mesh
                        if (thisdata->fDraw2D) {
                                drawManager.mesh2d(mode, position, NULL, thisdata->fIsFilled ? &index : NULL);
                        }
                        else {
                                drawManager.mesh(mode, position, NULL, NULL, thisdata->fIsFilled ? &index : NULL);
                        }

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kSphere:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setLineWidth(thisdata->fLineWidth);
                        drawManager.setLineStyle(thisdata->fLineStyle);
                        drawManager.sphere(thisdata->fPosition, thisdata->fRadius, thisdata->fIsFilled);

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kCircle:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setLineWidth(thisdata->fLineWidth);
                        drawManager.setLineStyle(thisdata->fLineStyle);
                        if (thisdata->fDraw2D) {
                                // The radius in specified as pixel unit for 2d items.
                                drawManager.circle2d(thisdata->fPosition, thisdata->fRadius, 
                                        thisdata->fIsFilled);
                        }
                        else {
                                drawManager.circle(thisdata->fPosition, thisdata->fCircleNormal, thisdata->fRadius, 
                                        thisdata->fIsFilled);
                        }

                        drawManager.endDrawable();
                }
                break;

        case uiDrawManager::kArc:
                {
                        drawManager.beginDrawable();

                        drawManager.setColor(thisdata->fColor);
                        drawManager.setLineWidth(thisdata->fLineWidth);
                        drawManager.setLineStyle(thisdata->fLineStyle);
                        if (thisdata->fDraw2D) {
                                // If 2d, the range of the arc is defined by the start and end vectors 
                                // specified in screen space.
                                drawManager.arc2d(thisdata->fPosition, thisdata->fArcStart, thisdata->fArcEnd, 
                                        thisdata->fRadius, thisdata->fIsFilled);
                        }
                        else {
                                // For 3d arc, the projections of the start and end vectors onto the arc plane(
                                // determined by the normal vector) determine the range of the arc.
                                drawManager.arc(thisdata->fPosition, thisdata->fArcStart, thisdata->fArcEnd, 
                                        thisdata->fArcNormal, thisdata->fRadius, thisdata->fIsFilled);
                        }

                        drawManager.endDrawable();
                }
                break;

        default:
                perror("unhandled ui types.");
                break;
        }
        
}

void uiDrawManagerDrawOverride::draw(const MHWRender::MDrawContext& context, const MUserData* data)
{

}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Plugin Registration
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

MStatus uiDrawManager::initialize()
{
        MStatus status;

        MFnNumericAttribute nAttr;
        MFnEnumAttribute eAttr;
        MFnTypedAttribute typedAttr;

        // Add ui type attribute
        aUIType = eAttr.create("uiType", "ut", uiDrawManager::kText);
        eAttr.addField("text", uiDrawManager::kText);
        eAttr.addField("line", uiDrawManager::kLine);
        eAttr.addField("point", uiDrawManager::kPoint);
        eAttr.addField("rect", uiDrawManager::kRect);   
        eAttr.addField("quad", uiDrawManager::kQuad);
        eAttr.addField("sphere", uiDrawManager::kSphere);
        eAttr.addField("circle", uiDrawManager::kCircle);       
        eAttr.addField("arc", uiDrawManager::kArc);     
        MPxNode::addAttribute(aUIType);
        
        // Add color attribute
        aPrimitiveColor = nAttr.create("primitiveColor", "pc", MFnNumericData::k3Float);
        nAttr.setDefault(1.0f, 0.0f, 0.0f);
        nAttr.setUsedAsColor(true);
        MPxNode::addAttribute(aPrimitiveColor);

        // Add transparency attribute
        aPrimitiveTransparency = nAttr.create("primitiveTransparency", "pt", MFnNumericData::kFloat, 0.0);
        nAttr.setSoftMin(0.0);
        nAttr.setSoftMax(1.0);  
        MPxNode::addAttribute(aPrimitiveTransparency);

        // add line width and line style attributes
        aLineWidth = nAttr.create("lineWidth", "lw", MFnNumericData::kFloat, 2.0);
        MPxNode::addAttribute(aLineWidth);

        aLineStyle = eAttr.create("lineStyle", "ls", MUIDrawManager::kSolid);
        eAttr.addField("solid", MUIDrawManager::kSolid);
        eAttr.addField("shortdotted", MUIDrawManager::kShortDotted);
        eAttr.addField("shortdashed", MUIDrawManager::kShortDashed);
        eAttr.addField("dashed", MUIDrawManager::kDashed);
        eAttr.addField("dotted", MUIDrawManager::kDotted);
        MPxNode::addAttribute(aLineStyle);

        // Add filled attribute
        aIsFilled = nAttr.create("isFilled", "if", MFnNumericData::kBoolean, 0);        
        MPxNode::addAttribute(aIsFilled);

        // Add radius attribute
        aRadius = nAttr.create("radius", "ra", MFnNumericData::kDouble, 1.0);
        MPxNode::addAttribute(aRadius);

        // add 2D attributes
        aDraw2D = nAttr.create("draw2D", "d2", MFnNumericData::kBoolean, 0);
        MPxNode::addAttribute(aDraw2D);

        aPosition = nAttr.create("position", "pos", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 0.0, 0.001);
        MPxNode::addAttribute(aPosition);
        
        // Add text attributes.
        MFnStringData stringFn;
        MObject defaultText = stringFn.create("uiDrawManager-Text");
        aText = typedAttr.create("text", "t", MFnData::kString, defaultText);
        MPxNode::addAttribute(aText);   

        aTextFontSize = eAttr.create("textFontSize", "tfs", MUIDrawManager::kDefaultFontSize);
        eAttr.addField("default", MUIDrawManager::kDefaultFontSize);
        eAttr.addField("small", MUIDrawManager::kSmallFontSize);
        MPxNode::addAttribute(aTextFontSize);   

        aTextAlignment = eAttr.create("textAlignment", "ta", MUIDrawManager::kLeft);
        eAttr.addField("left", MUIDrawManager::kLeft);
        eAttr.addField("center", MUIDrawManager::kCenter);
        eAttr.addField("right", MUIDrawManager::kRight);
        MPxNode::addAttribute(aTextAlignment);  

        aTextBoxSize = nAttr.create("textBoxSize", "tbs", MFnNumericData::k2Int);
        nAttr.setDefault(200, 40);
        MPxNode::addAttribute(aTextBoxSize);

        aTextBoxColor = nAttr.create("textBoxColor", "tbc", MFnNumericData::k3Float);
        nAttr.setDefault(0.0f, 1.0f, 1.0f);
        nAttr.setUsedAsColor(true);
        MPxNode::addAttribute(aTextBoxColor);

        aTextBoxTransparency = nAttr.create("textBoxTransparency", "tbt", MFnNumericData::kFloat, 0.0);
        nAttr.setSoftMin(0.0);
        nAttr.setSoftMax(1.0);  
        MPxNode::addAttribute(aTextBoxTransparency);
        
        // add point attributes
        aPointSize = nAttr.create("pointSize", "ps", MFnNumericData::kFloat, 2.0);
        MPxNode::addAttribute(aPointSize);

        // add line attributes
        aLineStartPoint = nAttr.create("lineStartPoint", "lsp", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 0.0, 0.0);
        MPxNode::addAttribute(aLineStartPoint);

        aLineEndPoint = nAttr.create("lineEndPoint", "lep", MFnNumericData::k3Double);
        nAttr.setDefault(1.0, 1.0, 1.0);
        MPxNode::addAttribute(aLineEndPoint);
        
        // add rect attributes
        aRectUp = nAttr.create("rectUp", "ru", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 1.0, 0.0);
        MPxNode::addAttribute(aRectUp);

        aRectNormal = nAttr.create("rectNormal", "rn", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 0.0, 1.0);
        MPxNode::addAttribute(aRectNormal);

        aRectScale = nAttr.create("rectScale", "rs", MFnNumericData::k2Double);
        nAttr.setDefault(1.0, 1.0);
        MPxNode::addAttribute(aRectScale);

        // add quad attributes
        double defaultPosition[4][3] = 
        {
                {0.0, 0.0, 0.0},
                {1.0, 0.0, 0.0},
                {1.0, 1.0, 0.0},
                {0.0, 1.0, 0.0}
        };
        for (int i = 0; i < 4;  ++i)
        {
                MString fullName = "quadVertex";
                MString shortName = "qv";
                aQuadVertex[i] = nAttr.create(fullName + i, shortName + i, MFnNumericData::k3Double);
                nAttr.setDefault(defaultPosition[i][0], defaultPosition[i][1], defaultPosition[i][2]);
                MPxNode::addAttribute(aQuadVertex[i]);
        }
        
        // add circle attributes
        aCircleNormal = nAttr.create("circleNormal", "cn", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 0.0, 1.0);
        MPxNode::addAttribute(aCircleNormal);

        // add arc attributes
        aArcStart = nAttr.create("arcStartVector", "asv", MFnNumericData::k3Double);
        nAttr.setDefault(1.0, 0.0, 0.0);
        MPxNode::addAttribute(aArcStart);

        aArcEnd = nAttr.create("arcEndVector", "aev", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 1.0, 0.0);
        MPxNode::addAttribute(aArcEnd);

        aArcNormal = nAttr.create("arcNormal", "an", MFnNumericData::k3Double);
        nAttr.setDefault(0.0, 0.0, 1.0);
        MPxNode::addAttribute(aArcNormal);

        return MS::kSuccess;
}

MStatus initializePlugin( MObject obj )
{
        MStatus   status;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

        status = plugin.registerNode(
                "uiDrawManager",
                uiDrawManager::id,
                &uiDrawManager::creator,
                &uiDrawManager::initialize,
                MPxNode::kLocatorNode,
                &uiDrawManager::drawDbClassification);
        if (!status) {
                status.perror("registerNode");
                return status;
        }

        status = MHWRender::MDrawRegistry::registerDrawOverrideCreator(
                uiDrawManager::drawDbClassification,
                uiDrawManager::drawRegistrantId,
                uiDrawManagerDrawOverride::Creator);
        if (!status) {
                status.perror("registerDrawOverrideCreator");
                return status;
        }

        return status;
}

MStatus uninitializePlugin( MObject obj)
{
        MStatus   status;
        MFnPlugin plugin( obj );

        status = MDrawRegistry::deregisterGeometryOverrideCreator(
                uiDrawManager::drawDbClassification,
                uiDrawManager::drawRegistrantId);
        if (!status) {
                status.perror("deregisterGeometryOverrideCreator");
                return status;
        }

        status = plugin.deregisterNode( uiDrawManager::id );
        if (!status) {
                status.perror("deregisterNode");
                return status;
        }

        return status;
}