-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCore.h
249 lines (222 loc) · 11.4 KB
/
Core.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#pragma once
#pragma comment(lib, "Foundation.lib")
#pragma comment(lib, "OpenMaya.lib")
#pragma comment(lib, "OpenMayaAnim.lib")
#include <vector>
#include <maya/MFnPlugin.h>
#include <maya/MPxNode.h>
#include <maya/MString.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MArrayDataBuilder.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MDistance.h>
#include <maya/MAngle.h>
#include <maya/MTime.h>
#include <maya/MFloatVector.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MColor.h>
#include <maya/MMatrix.h>
#include <maya/MFloatMatrix.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MQuaternion.h>
#include <maya/MFnMessageAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MPxDeformerNode.h>
#include <maya/MFnMesh.h>
#include <maya/MItMeshVertex.h>
#include <maya/MPointArray.h>
#include <maya/MItGeometry.h>
#include <maya/MGlobal.h>
#include <maya/MEulerRotation.h>
#define DECL_MFN_MOBJECT(N) struct N { MObject obj; N(MObject obj) : obj(obj) {} operator MObject() { return obj; } operator const MObject&() const { return obj; } };
#include "MFnHelpers.inc"
struct Meta {
MObject node;
MDataBlock& data;
unsigned int deformerMultiIndex;
Meta(MObject node, MDataBlock& data, unsigned int deformerMultiIndex = 0) : node(node), data(data), deformerMultiIndex(deformerMultiIndex) {}
operator MDataBlock& () { return data; }
};
template<typename T>
class TMPxNode : public MPxNode {
public:
static void* creator() { return new T; }
protected:
virtual void compute(Meta b) = 0;
virtual bool isInputPlug(const MPlug& p) = 0;
private:
MStatus compute(const MPlug& p, MDataBlock& b) override { if (!isInputPlug(p)) return MS::kUnknownParameter; compute({ thisMObject(), b }); return MS::kSuccess; }
};
template<typename T>
class TMPxDeformer : public MPxDeformerNode {
public:
static void* creator() { return new T; }
protected:
static void makePaintable(const char* nodeName) {
MGlobal::executeCommand(MString("makePaintable -attrType multiFloat -sm deformer ") + nodeName + " weights", true);
}
virtual MStatus deform(Meta b, MItGeometry& outputGeometry, const MMatrix& worldMatrix) = 0;
private:
MStatus deform(MDataBlock& b, MItGeometry& outputGeometry, const MMatrix& worldMatrix, unsigned int multiIndex) override { return deform(Meta(thisMObject(), b, multiIndex), outputGeometry, worldMatrix); }
};
template<typename T, MFn::Type G>
class TTypedMPxDeformer : public TMPxDeformer<T> {
protected:
MObject inputGeometry(const Meta& b) {
// MItGeometry is a copy of the input that will be written to the output. Therefore we can't write to the output directly, but only to to MItGeometry.
// TODO: Verify that MItGeometry can't just be ignored if we get a handle to the output plug
// MItGeometry is geometry-agnostic so we can't use it for polygon-specific deformers. Therefore we will get the input geometry as the right type.
MStatus status;
MArrayDataHandle inputGeometryArray = b.data.inputArrayValue(T::input, &status); CHECK_MSTATUS_AND_RETURN(status, MObject::kNullObj);
status = inputGeometryArray.jumpToElement(b.deformerMultiIndex); CHECK_MSTATUS_AND_RETURN(status, MObject::kNullObj);
MDataHandle inputGeometryArrayElement = inputGeometryArray.inputValue(&status); CHECK_MSTATUS_AND_RETURN(status, MObject::kNullObj);
MObject inputShape = inputGeometryArrayElement.child(T::inputGeom).asMesh();
if (inputShape == MObject::kNullObj || !inputShape.hasFn(G)) {
MGlobal::displayError("This deformer only works on specific geometry data, input is wrong type of shape.");
status = MS::kFailure;
return MObject::kNullObj;
}
return inputShape;
}
};
MStatus enumInitialize(MObject& dst, const MString& enumName, const std::vector<MString>& fieldNames, const std::vector<short> fieldIndices) {
MFnEnumAttribute fn;
MStatus status;
dst = fn.create(enumName, enumName, fieldIndices[0], &status); CHECK_MSTATUS_AND_RETURN_IT(status);
for (unsigned int i = 0; i < fieldNames.size(); ++i) {
status = fn.addField(fieldNames[i], fieldIndices[i]);
CHECK_MSTATUS_AND_RETURN_IT(status);
}
return status;
}
unsigned int arraySize(Meta b, const MObject& o);
MDataHandle arrayInputElement(Meta b, const MObject& o, unsigned int index, MStatus& status);
template<typename T> T get(MDataHandle& element);
template<typename T> T get(MDataHandle& element, const MObject* compoundChildren);
template<typename T> void set(MDataHandle& element, const T& value);
template<typename T> void set(MDataHandle& element, const MObject* compoundChildren, const T& value);
template<typename T> std::vector<T> get(MArrayDataHandle& element) {
std::vector<T> result;
result.reserve(element.elementCount());
for (unsigned int i = 0; i < element.elementCount(); ++i) {
element.jumpToArrayElement(i);
MDataHandle elementHandle = element.inputValue();
result.push_back(get<T>(elementHandle));
}
return result;
}
template<typename T> T get(MArrayDataHandle& element, const MObject* compoundChildren) {
std::vector<T> result;
result.reserve(element.elementCount());
for (unsigned int i = 0; i < element.elementCount(); ++i) {
element.jumpToArrayElement(i);
MDataHandle elementHandle = element.inputValue();
result.push_back(get<T>(elementHandle, compoundChildren));
}
return result;
}
template<typename T> void set(MArrayDataHandle& element, const std::vector<T>& value) {
MStatus status;
MArrayDataBuilder builder = element.builder(&status); CHECK_MSTATUS(status); if (MStatus::kSuccess != status) return;
for (unsigned int index = 0; index < (unsigned int)value.size(); ++index) {
MDataHandle child = builder.addElement(index, &status); CHECK_MSTATUS(status); if (MStatus::kSuccess != status) return;
set<T>(child, value[index]);
}
element.set(builder);
}
template<typename T> void set(MArrayDataHandle& element, const MObject* compoundChildren, const T& value) {
MStatus status;
MArrayDataBuilder builder = element.builder(&status); CHECK_MSTATUS(status); if (MStatus::kSuccess != status) return;
for (unsigned int index = 0; index < (unsigned int)value.size(); ++index) {
MDataHandle child = builder.addElement(index, &status); CHECK_MSTATUS(status); if (MStatus::kSuccess != status) return;
set<T>(child, compoundChildren, value[index]);
}
element.set(builder);
}
template<typename T> T fallback() { return T(); } // fallback value in case of errors
template<typename T> T getAttr(Meta b, const MObject& o) { MDataHandle h = b.data.inputValue(o); return get<T>(h); }
template<typename T> T getAttr(Meta b, const MObject& o, const std::vector<MObject>& compoundChildren) { MDataHandle h = b.data.inputValue(o); return get<T>(h, &compoundChildren[0]); }
template<typename T> T getArray(Meta b, const MObject& o, int index) {
MStatus status;
MDataHandle element = arrayInputElement(b, o, index, status);
if (status != MS::kSuccess) // element is not valid
return fallback<T>();
return get<T>(element);
}
template<typename T> T getArray(Meta b, const MObject& o, const std::vector<MObject>& compoundChildren, int index) {
MStatus status;
MDataHandle element = arrayInputElement(b, o, index, status);
if (status != MS::kSuccess) // element is not valid
return fallback<T>();
return get<T>(element, &compoundChildren[0]);
}
template<typename T> MStatus setAttr(Meta b, const MObject& o, const T& value) {
MStatus status;
MDataHandle element = b.data.outputValue(o, &status); CHECK_MSTATUS_AND_RETURN_IT(status);
set<T>(element, value);
return status;
}
template<typename T> MStatus setAttr(Meta b, const MObject& o, const std::vector<MObject>& compoundChildren, const T& value) {
MStatus status;
MDataHandle element = b.data.outputValue(o, &status); CHECK_MSTATUS_AND_RETURN_IT(status);
set<T>(element, &compoundChildren[0], value);
return status;
}
template<typename T> MStatus setArray(Meta b, const MObject& o, const std::vector<T>& value) {
MStatus status;
MDataHandle element;
MArrayDataHandle handle = b.data.outputArrayValue(o, &status); CHECK_MSTATUS_AND_RETURN_IT(status);
MArrayDataBuilder builder = handle.builder(&status); CHECK_MSTATUS_AND_RETURN_IT(status);
for (unsigned int index = 0; index < (unsigned int)value.size(); ++index) {
element = builder.addElement(index, &status); CHECK_MSTATUS_AND_RETURN_IT(status);
set<T>(element, value[index]);
}
handle.set(builder);
return status;
}
template<typename T> MStatus setArray(Meta b, const MObject& o, const std::vector<MObject>& compoundChildren, const std::vector<T>& value) {
MStatus status;
MDataHandle element;
MArrayDataHandle handle = b.data.outputArrayValue(o, &status); CHECK_MSTATUS_AND_RETURN_IT(status);
MArrayDataBuilder builder = handle.builder(&status); CHECK_MSTATUS_AND_RETURN_IT(status);
for (unsigned int index = 0; index < (unsigned int)value.size(); ++index) {
element = builder.addElement(index, &status); CHECK_MSTATUS_AND_RETURN_IT(status);
set<T>(element, &compoundChildren[0], value[index]);
}
handle.set(builder);
return status;
}
template<typename T> MStatus initialize(MObject& dst, const char* name);
template<typename T> MStatus initialize(MObject& dst, const char* name, std::vector<MObject>& dstChildren);
#define TYPED_DEFORMER_BEGIN(N, TYPE) class N : public TTypedMPxDeformer<N, MFn::k##TYPE> { public: static MStatus initialize(); virtual MStatus deform(Meta b, MItGeometry& outputGeometry, const MMatrix& worldMatrix) override
#define DEFORMER_BEGIN(N) class N : public TMPxDeformer<N> { public: static MStatus initialize(); virtual MStatus deform(Meta b, MItGeometry& outputGeometry, const MMatrix& worldMatrix) override
#define DEFORMER_END };
#define NODE_BEGIN(N) class N : public TMPxNode<N> { public: static MStatus initialize(); protected: virtual bool isInputPlug(const MPlug& p) override; virtual void compute(Meta b) override
#define NODE_END };
#define INPUT(T, N) static MObject N##Attr; T N(Meta dataBlock);
#define OUTPUT(T, N) static MObject N##Attr; void N##Set(Meta dataBlock, const T& value);
#define INOUT(T, N) static MObject N##Attr; T N(Meta dataBlock); void N##Set(Meta dataBlock, const T& value);
#define INPUT_ARRAY(T, N) static MObject N##Attr; int N##Size(Meta dataBlock); T N(Meta dataBlock, int index);
#define OUTPUT_ARRAY(T, N) static MObject N##Attr; int N##Size(Meta dataBlock); void N##Set(Meta dataBlock, const std::vector<T>& value);
#define INOUT_ARRAY(T, N) static MObject N##Attr; int N##Size(Meta dataBlock); T N(Meta dataBlock, int index); void N##Set(Meta dataBlock, const std::vector<T>& value);
#define ENUM_BEGIN(N) enum class N {
#define ENUM(N) N,
#define ENUM_VALUE(N, V) N = V,
#define ENUM_END };
#define COMPOUND_BEGIN(N) struct N {
#define COMPOUND_VALUE(T, N) T N;
#define COMPOUND_ARRAY(T, N) std::vector<T> N;
#define COMPOUND_END };
struct SVec2 { short x = 0; short y = 0; SVec2(); SVec2(const short2& i); };
struct IVec2 { int x = 0; int y = 0; IVec2(); IVec2(const int2& i); };
struct FVec2 { float x = 0; float y = 0; FVec2(); FVec2(const float2& i); };
struct DVec2 { double x = 0; double y = 0; DVec2(); DVec2(const double2& i); };
struct SVec3 { short x = 0; short y = 0; short z = 0; SVec3(); SVec3(const short3& i); };
struct IVec3 { int x = 0; int y = 0; int z = 0; IVec3(); IVec3(const int3& i); };
struct FVec3 { float x = 0; float y = 0; float z = 0; FVec3(); FVec3(const float3& i); };
struct DVec3 { double x = 0; double y = 0; double z = 0; DVec3(); DVec3(const double3& i); };
struct DVec4 { double x = 0; double y = 0; double z = 0; double w = 0; DVec4(); DVec4(const double4& i); };