Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

349 lines
11 KiB
C++

//#include <maya/MIOStream.h>
//#include <stdio.h>
//#include <stdlib.h>
//
//#include <maya/MFn.h>
//#include <maya/MPxNode.h>
//#include <maya/MPxManipContainer.h>
//#include <maya/MPxSelectionContext.h>
//#include <maya/MPxContextCommand.h>
//#include <maya/MModelMessage.h>
//#include <maya/MFnPlugin.h>
#include <maya/MGlobal.h>
//#include <maya/MItSelectionList.h>
//#include <maya/MPoint.h>
#include <maya/MVector.h>
//#include <maya/MDagPath.h>
#include <maya/MManipData.h>
//#include <maya/MSelectionList.h>
#include <maya/MItMeshVertex.h>
#include <maya/MFnComponent.h>
//#include <maya/MStatus.h>
//#include <maya/MObject.h>
#include <maya/MPlug.h>
#include <maya/MFnMesh.h>
#include <maya/MFnNumericAttribute.h>
//
//Manipulators
#include <maya/MFnScaleManip.h>
#include <maya/MFnRotateManip.h>
//
//#include "rageHairContext.h"
#include "rageHairManip.h"
//#include "rageHairScaleCmd.h"
// #include "rageHairManip.h"
#define POINT_SIZE 20.0
#define BLIND_DATA_ID 60
void OutputError(const MString& obStrErrorMessage)
{
cout<<obStrErrorMessage<<endl;
MGlobal::displayError(obStrErrorMessage);
}
MStatus addArrayAttribute(MString strAttributeName, MObject obNode)
{
MFnDependencyNode obFnNode(obNode);
// Add an array atrribute to store all the hair vectors in
MStatus obStatus;
MPlug obPlug = obFnNode.findPlug(strAttributeName, &obStatus);
if (obPlug.isNull())
{
// Attribute does not exist, so create it
MFnNumericAttribute attributeFn;
MObject attr = attributeFn.create(strAttributeName, strAttributeName, MFnNumericData::k3Double);
attributeFn.setArray(true);
obFnNode.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
MPlug obPlug = obFnNode.findPlug(strAttributeName, &obStatus);
if (obPlug.isNull())
{
OutputError("Could not add "+ strAttributeName +" attribute.");
return MS::kFailure;
}
}
return MS::kSuccess;
}
rageHairManip::rageHairManip() :
m_aobInitialHairVectors(NULL),
m_abVertexIsSelected(NULL)
{
// The constructor must not call createChildren for user-defined
// manipulators.
m_astrBindDataLongNames.clear();
m_astrBindDataLongNames.append("rageHairBlindDataX");
m_astrBindDataLongNames.append("rageHairBlindDataY");
m_astrBindDataLongNames.append("rageHairBlindDataZ");
}
rageHairManip::~rageHairManip()
{
// m_aobInitialHairVectors should always be either NULL or an allocated array
// of MPoint.
//
delete [] m_aobInitialHairVectors;
delete [] m_abVertexIsSelected;
}
MStatus rageHairManip::initialize()
{
MStatus obStatus;
obStatus = MPxManipContainer::initialize();
return obStatus;
}
MStatus rageHairManip::connectToDependNode(const MObject &obMeshNode)
{
MStatus obStatus;
// Set up some stuff
delete [] m_aobInitialHairVectors;
delete [] m_abVertexIsSelected;
int iTotalNoOfVertsInMesh = MFnMesh(obMeshNode).numVertices();
// Fill in vector array
m_aobInitialHairVectors = new MVector[iTotalNoOfVertsInMesh];
for(int i=0; i<iTotalNoOfVertsInMesh; i++) m_aobInitialHairVectors[i] = MVector(1.0f, 2.0f, 3.0f);
// Fill in the bool array
m_abVertexIsSelected = new bool[iTotalNoOfVertsInMesh];
for(int i=0; i<iTotalNoOfVertsInMesh; i++) m_abVertexIsSelected[i] = false;
// I need to create a MFnMesh node, but if you create one from a MObject the blind data functions do not work
// So do some evil hacks to get a MDagPath to create it out of instead
MDagPath obDagPathMeshNode;
MDagPath::getAPathTo(obMeshNode, obDagPathMeshNode);
MFnMesh obFnMeshNode(obDagPathMeshNode);
// Throw on a dummy attribute, just so the manipulator has something to hang off
MPlug obDummyPlug = obFnMeshNode.findPlug( DUMMY_ATTRIBUTE_NAME, &obStatus );
if((!obStatus) || (obDummyPlug.isNull()))
{
// Unable to find dummy plug, so add it
MFnNumericAttribute obFnNumericAttribute;
MObject obAttr = obFnNumericAttribute.create(DUMMY_ATTRIBUTE_NAME, "rhd", MFnNumericData::kFloat , 0, &obStatus);
if(!obStatus)
{
OutputError(MString("Unable to create dummy attribute ")+ DUMMY_ATTRIBUTE_NAME);
return MS::kFailure;
}
obFnNumericAttribute.setHidden(true);
obStatus = obFnMeshNode.addAttribute(obAttr, MFnDependencyNode::kLocalDynamicAttr);
if(!obStatus)
{
OutputError(MString("Unable to add dummy attribute ")+ DUMMY_ATTRIBUTE_NAME +" to "+ obFnMeshNode.fullPathName());
return MS::kFailure;
}
}
// If mesh currently does not have blinddata, add it
// Create blind data type
MStringArray astrBindDataShortNames;
astrBindDataShortNames.append("rhx");
astrBindDataShortNames.append("rhy");
astrBindDataShortNames.append("rhz");
MStringArray formatNames;
formatNames.append("float");
formatNames.append("float");
formatNames.append("float");
// See if blinddata id already used in scene
if(!obFnMeshNode.isBlindDataTypeUsed(BLIND_DATA_ID,&obStatus))
{
// cout<<"Creating blind data"<<endl;
// Not already used so create
obStatus = obFnMeshNode.createBlindDataType(BLIND_DATA_ID, m_astrBindDataLongNames, astrBindDataShortNames, formatNames);
if(!obStatus)
{
OutputError("Error creating blind data");
return MS::kFailure;
}
}
// Iterate through the components, storing initial positions and find the
// m_obCentroidOfAllSelectedComponents. Add manipToPlug callbacks for each component.
//
m_obAISelectedComponentIndexes.clear();
MItMeshVertex iter(m_obMeshDagPath, GetSelectedComponents());
for (; !iter.isDone(); iter.next())
{
MString obStrVertNoAsString;
obStrVertNoAsString += iter.index();
m_obAISelectedComponentIndexes.append(iter.index());
m_abVertexIsSelected[iter.index()] = true;
m_obCentroidOfAllSelectedComponents += iter.position(MSpace::kWorld);
if(!obFnMeshNode.hasBlindData(iter.index(), MFn::kMeshVertComponent, BLIND_DATA_ID))
{
// I don't have a hair vector, so create one
MVector obVertexNormal;
iter.getNormal(obVertexNormal, MSpace::kWorld);
for(int iAxis=0; iAxis<3; iAxis++)
{
// Set value for the blind data
// polyBlindData -id 60 -associationType "vertex" -longDataName "bdFloat" -doubleData 234 pPlane1.vtx[0]
float fDataIn = 0.5f * (float)obVertexNormal[iAxis];
// cout<<"fDataIn = "<<fDataIn<<"\tobVertexNormal["<<iAxis<<"] = "<<obVertexNormal[iAxis]<<endl;
obStatus = obFnMeshNode.setFloatBlindData(iter.index(), MFn::kMeshVertComponent, BLIND_DATA_ID, m_astrBindDataLongNames[iAxis], fDataIn);
if (!obStatus)
{
OutputError("Could not set blind data "+ m_astrBindDataLongNames[iAxis] +" X for vert "+ obStrVertNoAsString +" on "+ obFnMeshNode.fullPathName());
return MS::kFailure;
}
}
}
// Store for future reference
double3 adHairVector;
for(int iAxis = 0; iAxis<3; iAxis++)
{
float fDataOut;
obStatus = obFnMeshNode.getFloatBlindData(iter.index(), MFn::kMeshVertComponent, BLIND_DATA_ID, m_astrBindDataLongNames[iAxis], fDataOut);
if (!obStatus)
{
OutputError("Could not get "+ m_astrBindDataLongNames[iAxis] +" for vert "+ obStrVertNoAsString +" on "+ obFnMeshNode.fullPathName());
return MS::kFailure;
}
adHairVector[iAxis] = fDataOut;
}
m_aobInitialHairVectors[iter.index()] = MVector( adHairVector[0], adHairVector[1], adHairVector[2] );
}
m_obCentroidOfAllSelectedComponents = m_obCentroidOfAllSelectedComponents * (1.0f/(float)iter.count());
MPxManipContainer::connectToDependNode(obMeshNode);
return obStatus;
}
void rageHairManip::draw(M3dView & view,
const MDagPath & path,
M3dView::DisplayStyle style,
M3dView::DisplayStatus obStatus)
{
MPxManipContainer::draw(view, path, style, obStatus);
// Draw the normals
view.beginGL();
// Query current obStatuse so it can be restored
//
bool lightingWasOn = glIsEnabled( GL_LIGHTING ) ? true : false;
if ( lightingWasOn )
{
glDisable( GL_LIGHTING );
}
float lastPointSize;
glGetFloatv( GL_POINT_SIZE, &lastPointSize );
// Set the point size of the vertices
glPointSize( POINT_SIZE );
// Get verts
// First the unselected one
glColor4f( 0.0f, 1.0f, 0.0f, 1.0f );
MFnMesh obFnMeshNode(m_obMeshDagPath.node());
for(MItMeshVertex iter(m_obMeshDagPath); !iter.isDone(); iter.next())
{
if(!m_abVertexIsSelected[iter.index()])
{
// Go through verts, drawing as I go
MPoint vertex = iter.position(MSpace::kWorld);
MVector obHair;
if(obFnMeshNode.hasBlindData(iter.index(), MFn::kMeshVertComponent, BLIND_DATA_ID))
{
for(int iAxis = 0; iAxis<3; iAxis++)
{
float fDataOut;
obFnMeshNode.getFloatBlindData(iter.index(), MFn::kMeshVertComponent, BLIND_DATA_ID, m_astrBindDataLongNames[iAxis], fDataOut);
obHair[iAxis] = fDataOut;
}
}
else
{
iter.getNormal(obHair, MSpace::kWorld);
obHair = obHair * 0.5f;
}
// obHair = obHair * 20.0f;
glBegin( GL_LINES );
glVertex3f( (float)vertex[0], (float)vertex[1], (float)vertex[2] );
glVertex3f( (float)obHair.x + (float)vertex[0], (float)obHair.y + (float)vertex[1], (float)obHair.z + (float)vertex[2] );
glEnd();
}
}
// Then the selected one
glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
for(MItMeshVertex iter(m_obMeshDagPath); !iter.isDone(); iter.next())
{
if(m_abVertexIsSelected[iter.index()])
{
// Go through verts, drawing as I go
MPoint vertex = iter.position(MSpace::kWorld);
double3 adHairVector;
for(int iAxis = 0; iAxis<3; iAxis++)
{
float fDataOut;
obFnMeshNode.getFloatBlindData (iter.index(), MFn::kMeshVertComponent, BLIND_DATA_ID, m_astrBindDataLongNames[iAxis], fDataOut);
adHairVector[iAxis] = fDataOut;
}
// Draw it
glBegin( GL_LINES );
glVertex3f( (float)vertex[0], (float)vertex[1], (float)vertex[2] );
glVertex3f( (float)adHairVector[0] + (float)vertex[0], (float)adHairVector[1] + (float)vertex[1], (float)adHairVector[2] + (float)vertex[2] );
glEnd();
}
}
// Restore the obStatuse
if ( lightingWasOn )
{
glEnable( GL_LIGHTING );
}
glPointSize( lastPointSize );
view.endGL();
}
MManipData rageHairManip::centerChangedCallback(unsigned index)
{
MObject obj = MObject::kNullObj;
// If we entered the callback with an invalid index, print an error and
// return. Since we registered the callback only for one index, all
// invocations of the callback should be for that index.
//
//MFnScaleManip scaleManip(m_obManipDagPath);
//if (index != scaleManip.scaleCenterIndex())
//{
// OutputError("Invalid index in center changed callback!");
// // For invalid indices, return vector of 0's
// MFnNumericData numericData;
// obj = numericData.create( MFnNumericData::k3Double );
// numericData.setData(0.0,0.0,0.0);
// return obj;
//}
// Set the center point for scaling to the m_obCentroidOfAllSelectedComponents of the CV's.
//
MFnNumericData numericData;
obj = numericData.create( MFnNumericData::k3Double );
numericData.setData(m_obCentroidOfAllSelectedComponents.x,m_obCentroidOfAllSelectedComponents.y,m_obCentroidOfAllSelectedComponents.z);
return MManipData(obj);
}