Maya插件(五): 自定义Dependency Node

前言

       在插件(三)中,我们使用了自定义的Locator结点,它也是个DG Node,本文目的是学习和理解Mplug && Attribute。

MyDGNode是我们自定义的结点, 有输入、输出Attribute,下图是一个用法:

       将时间结点time1的输出-->MyDGNode1-->sphere1(Transform结点).

      

 

 

MyDGNode的实现

       从MPxNode继承。MyDGNode.h

#ifndef __MYDGNODE_H__ #define __MYDGNODE_H__ #ifdef WIN32 #ifdef NT_PLUGIN #define NT_PLUGIN #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include /// MyDGNode class MyDGNode : public MPxNode { public: MyDGNode(); virtual ~MyDGNode(); /// /brief /// to calculate the value of a specific output attribute. virtual MStatus compute(const MPlug &outPlug, MDataBlock &dataBlock); /// /brief /// create this-self static void *creator(); /// /brief /// initialize the node, to append the addtional attributes. static MStatus initialize(); public: const static MTypeId m_typeId; const static MString m_typeName; private: static MObject m_inTime; /// attribute inTime for in static MObject m_outValue; /// attribute outValue to out }; #endif /// __MYDGNODE_H__

1. virtual MStatus compute(const MPlug &outPlug, MDataBlock &dataBlock);

    当DG网络出现脏数据时,该函数将被调用,用于更新数据.

2. static MStatus initialize();

    初始化该结点,创建Attributes(相当于动态添加类成员变量).

3. static MObject m_inTime;  static MObject m_outValue;

    新的Attribute标识符(句柄).

实现代码MyDGNode.cpp

#include "MyDGNode.h" #include #include const MTypeId MyDGNode::m_typeId = 0x10001; const MString MyDGNode::m_typeName = "MyDGNode"; MObject MyDGNode::m_inTime; MObject MyDGNode::m_outValue; /// construction && destruction MyDGNode::MyDGNode() { std::cout << "MyDGNode()" << std::endl; } MyDGNode::~MyDGNode() { std::cout << "~MyDGNode()" << std::endl; } void *MyDGNode::creator() { std::cout << "MyDGNode::creator()" << std::endl; return new MyDGNode(); } MStatus MyDGNode::initialize() { /// attribute "time" 将连接到全局时间结点的attribute上 MFnUnitAttribute uAttr; m_inTime = uAttr.create("time", "t", MFnUnitAttribute::kTime); uAttr.setStorable(false); uAttr.setKeyable(false); MFnNumericAttribute nAttr; m_outValue = nAttr.create("output", "o", MFnNumericData::kFloat, 0.0f); nAttr.setReadable(true); nAttr.setKeyable(false); // 必须为false,否则compute将不会被调用,不明白. addAttribute(m_inTime); addAttribute(m_outValue); /// 设置依赖 attributeAffects(m_inTime, m_outValue); return MS::kSuccess; } MStatus MyDGNode::compute(const MPlug &plug, MDataBlock &data) { std::cout << "MyDGNode::compute() begin " << std::endl; if (plug != m_outValue) return MS::kUnknownParameter; /// 获取inTime MDataHandle timeData = data.inputValue(m_inTime); MDataHandle outData = data.outputValue(m_outValue); MTime time = timeData.asTime(); std::cout << "time.as(MTime::kSeconds): " << time.as(MTime::kSeconds) << std::endl; outData.set((float)sin(time.as(MTime::kSeconds))); data.setClean(plug); return MS::kSuccess; }

注册MyDGNode, pluginMain.cpp

#include #include #include "MyDGNode.h" #ifdef WIN32 #define MLL_EXPORT __declspec(dllexport) #else #define MLL_EXPORT #endif MLL_EXPORT MStatus initializePlugin(MObject obj) { std::cout << "initializePlugin" << std::endl; MStatus status; MFnPlugin plugin(obj, "Jett Huang", "1.0", "Any"); status = plugin.registerNode(MyDGNode::m_typeName, MyDGNode::m_typeId, MyDGNode::creator, MyDGNode::initialize, MPxNode::kDependNode); return status; } MLL_EXPORT MStatus uninitializePlugin(MObject obj) { std::cout << "uninitializePlugin" << std::endl; MStatus status; MFnPlugin plugin(obj); status = plugin.deregisterNode(MyDGNode::m_typeId); return status; }

Attribute Editor模板MEL

/// /brief /// Attribute Editor Template. /// /// /// global proc AEMyDGNodeTemplate ( string $nodeName ) { print("DEBUG: AEMyDGNodeTemplate is Invokded: " + $nodeName); editorTemplate -beginScrollLayout; // 加入我们的属性编辑控件 editorTemplate -beginLayout "MyDGNode Input" -collapse 0; editorTemplate -addControl "time"; editorTemplate -endLayout; AEdependNodeTemplate $nodeName; // This will add the standard UI controls for the node editorTemplate -addExtraControls; editorTemplate -endScrollLayout; }

放在Maya用户目录的Scripts下面。

编译工程.....

加载插件后,在MEL窗口中执行如下脚本

// run this MEL to test the MyDGNode

{
     $myNode = `createNode "MyDGNode"`;
    
     // create a polygon sphere
     string $psphere[] = `polySphere -r 1 -sx 20 -sy 20 -ax 0 1 0 -tx 1 -ch 1`;

 

     // connect the output of the node to the x-scale of the ploy sphere
     string $plugName = `connectAttr ($myNode + ".output") ($psphere[0] + ".sx")`;
     print $plugName;
     print("/n");
    
     // connect the time1 output to the "time" of myNode
     $plugName = `connectAttr "time1.outTime" ($myNode + ".time")`;
     print $plugName;
     print("/n");
}

然后开启时间滑块,你会发现球体的缩放动画。

 

做个实验

       在MEL命令中继续输入如下命令:

connectAttr "time1.outTime"  "MyDGNode1.output";

 

直接将time1连接到MyDGNode1的ouput, 发现对显示无影响,看看连接图如下:

 

如果输入的命令是:

connectAttr "pSphere1.sy"  "MyDGNode1.time";

将出现错误, Error: line 1: 'MyDGNode1.time' already has an incoming connection from 'time1.outTime'.

说明incoming的来源只能是一个!

你可能感兴趣的:(Maya,Develope,output,construction,attributes,string,float,input)