#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();
~geometryReplicator() override;
void postConstructor() override;
bool isBounded() const override;
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() override;
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);
}
~geometryReplicatorGeometryOverride() override;
DrawAPI supportedDrawAPIs() const override;
bool hasUIDrawables() const override;
void updateDG() override;
void updateRenderItems(
void addUIDrawables(
void populateGeometry(
void cleanUp() override;
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);
if (shader) {
if (cpvItem) {
}
}
}
}
}
}
bool geometryReplicatorGeometryOverride::isBaseMesh()
{
bool res = false;
MPlug plug(fThisNode, geometryReplicator::aBaseMesh);
if (!plug.isNull())
{
{
res = false;
}
}
return res;
}
bool geometryReplicatorGeometryOverride::requiresUnsharedGeometricStreams(
{
for (
int reqNum = 0; reqNum < descList.
length(); ++reqNum)
{
{
if (semanticName == "vertexid" ||
semanticName == "faceid" ||
semanticName == "localuvcoord")
{
return true;
}
}
}
return false;
}
void geometryReplicatorGeometryOverride::populateGeometry(
{
if (!fPath.isValid())
return;
MPolyGeomOptions options = kPolyGeom_Normal;
if( isBaseMesh() ) options = options|kPolyGeom_BaseMesh;
if( requiresUnsharedGeometricStreams(requirements) ) options = options|kPolyGeom_NotSharing;
if (MS::kFailure == status)
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);
if (MS::kFailure == status)
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);
if (MS::kFailure == status)
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);
if (MS::kFailure == status)
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;
}