#include <maya/MPxSurfaceShape.h>
#include <maya/MPxSurfaceShapeUI.h>
#include <maya/MFnPlugin.h>
#include <maya/MPxGeometryOverride.h>
#include <maya/MDagPath.h>
#include <maya/MGeometryExtractor.h>
#include <maya/MDrawRegistry.h>
#include <maya/MFnData.h>
#include <maya/MItSelectionList.h>
#include <maya/MGlobal.h>
#include <maya/MPlugArray.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MShaderManager.h>
#include <maya/MFnNumericAttribute.h>
{
public:
    geometryReplicator();
    virtual ~geometryReplicator();
    virtual void postConstructor();
    virtual bool            isBounded() const;
    static  void *          creator();
    
public:
    static  MString     drawDbClassification;
 
};
MObject geometryReplicator::aShowCPV;
 
MObject geometryReplicator::aBaseMesh;
 
MTypeId geometryReplicator::id(0x00080029);
 
MString geometryReplicator::drawDbClassification(
"drawdb/geometry/geometryReplicator");
 
MString geometryReplicator::drawRegistrantId(
"geometryReplicatorPlugin");
 
geometryReplicator::geometryReplicator()
{
}
geometryReplicator::~geometryReplicator() {}
bool geometryReplicator::isBounded() const
{
    return true;
}
{
    MPoint corner1( -0.5, 0.0, -0.5 );
 
    MPoint corner2( 0.5, 0.0, 0.5 );
 
}
void* geometryReplicator::creator()
{
    return new geometryReplicator();
}
void geometryReplicator::postConstructor()
{
    setRenderable(true);
}
{
public:
    static void* creator();
    geometryReplicatorShapeUI();
    ~geometryReplicatorShapeUI();
private:
    
    geometryReplicatorShapeUI(const geometryReplicatorShapeUI& obj);
    const geometryReplicatorShapeUI& operator=(const geometryReplicatorShapeUI& obj);
};
void* geometryReplicatorShapeUI::creator()
{
    return new geometryReplicatorShapeUI;
}
geometryReplicatorShapeUI::geometryReplicatorShapeUI()
{}
geometryReplicatorShapeUI::~geometryReplicatorShapeUI()
{}
{
public:
    {
        return new geometryReplicatorGeometryOverride(obj);
    }
    virtual ~geometryReplicatorGeometryOverride();
    virtual DrawAPI supportedDrawAPIs() 
const;
 
    virtual bool hasUIDrawables() const;
    virtual void updateDG();
    virtual void updateRenderItems(
    virtual void addUIDrawables(
    virtual void populateGeometry(
    virtual void cleanUp();
protected:
    geometryReplicatorGeometryOverride(
const MObject& obj);
    bool isCPVShown();
    bool isBaseMesh();
};
geometryReplicatorGeometryOverride::geometryReplicatorGeometryOverride(
const MObject& obj)
    fThisNode(obj),
{
}
geometryReplicatorGeometryOverride::~geometryReplicatorGeometryOverride()
{
}
DrawAPI geometryReplicatorGeometryOverride::supportedDrawAPIs()
 const 
{
    
    return (kOpenGL | kDirectX11 | kOpenGLCoreProfile);
}
void geometryReplicatorGeometryOverride::updateDG()
{
    if (!fPath.isValid()) {
        MObject messageAttr = fnThisNode.attribute(
"message");
 
        MPlug messagePlug(fThisNode, messageAttr);
 
        if (messagePlug.connectedTo(connections, false, true)) {
            for (
unsigned int i = 0; i < connections.
length(); ++i) {
 
                MObject node = connections[i].node();
 
                {
                    fPath = path;
                    break;
                }
            }
        }
    }
}
bool geometryReplicatorGeometryOverride::isCPVShown()
{
    bool res = false;
    MPlug plug(fThisNode, geometryReplicator::aShowCPV);
 
    if (!plug.isNull())
    {
        {
            res = false;
        }
    }
    return res;
}
void geometryReplicatorGeometryOverride::updateRenderItems(
{
    if (!fPath.isValid())
        return;
    MRenderer* renderer = MRenderer::theRenderer();
 
    if (!renderer)
        return;
    if (!shaderManager)
        return;
    {
        
        int index = list.
indexOf(
"geometryReplicatorCurve");
 
        if (index < 0)
        {
            curveItem = MRenderItem::Create("geometryReplicatorCurve", MRenderItem::NonMaterialSceneItem, MGeometry::kLines);
            if (shader) {
                static const float theColor[] = {1.0f, 0.0f, 0.0f, 1.0f};
            }
        }
        else {
            curveItem = list.
itemAt(index);
        }
        if (curveItem) {
        }
    }
    {
        
        int index = list.
indexOf(
"geometryReplicatorWireframe");
 
        if (index < 0)
        {
            wireframeItem = MRenderItem::Create("geometryReplicatorWireframe", MRenderItem::DecorationItem, MGeometry::kLines);
            wireframeItem->
depthPriority(MRenderItem::sActiveWireDepthPriority);
            if (shader) {
                static const float theColor[] = {1.0f, 0.0f, 0.0f, 1.0f};
            }
        }
        else {
            wireframeItem = list.
itemAt(index);
        }
        if (wireframeItem) {
        }
        
        bool showCPV = isCPVShown();
        index = list.
indexOf(
"StandardShadedItem", MGeometry::kTriangles, MGeometry::kShaded);
        if (index >= 0) {
            if (shadedItem) {
            }
        }
        index = list.
indexOf(
"StandardShadedItem", MGeometry::kTriangles, MGeometry::kTextured);
        if (index >= 0) {
            if (shadedItem) {
            }
        }
        
        index = list.
indexOf(
"geometryReplicatorCPV");
        if (index >= 0) {
            if (cpvItem) {
            }
        }
        else {
            
            if (showCPV) {
                MRenderItem* cpvItem = MRenderItem::Create(
"geometryReplicatorCPV", MRenderItem::MaterialSceneItem, MGeometry::kTriangles);
 
                cpvItem->
setDrawMode((MGeometry::DrawMode)(MGeometry::kShaded|MGeometry::kTextured));
                if (shader) {
                    if (cpvItem) {
                    }
                }
            }
        }
    }
}
bool geometryReplicatorGeometryOverride::isBaseMesh()
{
    bool res = false;
    MPlug plug(fThisNode, geometryReplicator::aBaseMesh);
 
    if (!plug.isNull())
    {
        {
            res = false;
        }
    }
    return res;
}
void geometryReplicatorGeometryOverride::populateGeometry(
{
    if (!fPath.isValid())
        return;
    
    
    
    
    
    if( isBaseMesh() ) options = options|kPolyGeom_BaseMesh;
        return;
    
    for (
int reqNum = 0; reqNum < descList.
length(); ++reqNum)
 
    {
        {
            continue;
        }
        {
        case MGeometry::kPosition:
        case MGeometry::kNormal:
        case MGeometry::kTexture:
        case MGeometry::kTangent:
        case MGeometry::kBitangent:
        case MGeometry::kColor:
            {
                if (vertexBuffer) {
                    
                    
                    
                    
                    float* data = (
float*)vertexBuffer->
acquire(vertexCount, 
true );
 
                    if (data) {
                        status = extractor.populateVertexBuffer(data, vertexCount, desc);
                            return;
                    }
                }
            }
            break;
        default:
            
            break;
        }
    }
    
    for (
int i = 0; i < renderItems.
length(); ++i)
 
    {
        if (!item) continue;
        MIndexBuffer* indexBuffer = data.createIndexBuffer(MGeometry::kUnsignedInt32);
 
        if (!indexBuffer) continue;
        
        
        
        
        if (item->
primitive() == MGeometry::kTriangles)
 
        {
            unsigned int numTriangles = extractor.primitiveCount(triangleDesc);
            unsigned int* indices = (
unsigned int*)indexBuffer->
acquire(3 * numTriangles, 
true );
 
            status = extractor.populateIndexBuffer(indices, numTriangles, triangleDesc);
                return;
        }
        else if (item->
primitive() == MGeometry::kLines)
 
        {
            unsigned int numEdges = extractor.primitiveCount(edgeDesc);
            unsigned int* indices = (
unsigned int*)indexBuffer->
acquire(2 * numEdges, 
true );
 
            status = extractor.populateIndexBuffer(indices, numEdges, edgeDesc);
                return;
        }
    }
}
void geometryReplicatorGeometryOverride::cleanUp()
{
}
bool geometryReplicatorGeometryOverride::hasUIDrawables() const
{
    return true;
}
void geometryReplicatorGeometryOverride::addUIDrawables(
{
}
MStatus geometryReplicator::initialize()
 
{
    aShowCPV = nAttr.
create(
"showCPV", 
"sc",
    if (!status) {
        status.
perror(
"create attribute showCPV");
        return status;
    }
    if (!status) {
        status.
perror(
"addAttribute showCPV");
        return status;
    }
    aBaseMesh = nAttr.
create(
"isBaseMesh", 
"bm",
    if (!status) {
        status.
perror(
"create attribute baseMesh");
        return status;
    }
    if (!status) {
        status.
perror(
"addAttribute baseMesh");
        return status;
    }
}
{
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"3.0", 
"Any");
 
    status = plugin.registerShape(
        "geometryReplicator",
        geometryReplicator::id,
        &geometryReplicator::creator,
        &geometryReplicator::initialize,
        &geometryReplicatorShapeUI::creator,
        &geometryReplicator::drawDbClassification);
    if (!status) {
        status.
perror(
"registerNode");
        return status;
    }
    status = MDrawRegistry::registerGeometryOverrideCreator(
        geometryReplicator::drawDbClassification,
        geometryReplicator::drawRegistrantId,
        geometryReplicatorGeometryOverride::Creator);
    if (!status) {
        status.
perror(
"registerGeometryOverrideCreator");
        return status;
    }
    return status;
}
{
    status = MDrawRegistry::deregisterGeometryOverrideCreator(
        geometryReplicator::drawDbClassification,
        geometryReplicator::drawRegistrantId);
    if (!status) {
        status.
perror(
"deregisterGeometryOverrideCreator");
        return status;
    }
    status = plugin.deregisterNode( geometryReplicator::id );
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    return status;
}