Maya plugin factory

These are 2 utilities I mostly want to use in other projects myself and now they’re easier to find.

Utility to check the variable ‘stat’ and raise & return if something’s wrong. I always have 1 MStatus running through a function and it’s always named ‘stat’… The raised exception prints the file and line number as well!

utils.hpp

#ifndef UTILS_HPP


#define THROWSTAT if(stat != MS::kSuccess){ stat.perror(MString(__FILE__) + " line " + __LINE__); return stat; }
#define THROWSTATMSG(MSG) if(stat != MS::kSuccess){ stat.perror(MString(__FILE__) + " line " + __LINE__ + ": " + MSG); return stat; }


#define UTILS_HPP
#endif

This is the plugin factory. It registers the plugin with “Unknown” as author, you may wish to change that… There’s three interesting bits here.

First is the inclusion of MFnPlugin. Normally you can’t include this file twice because things get defined causing multiple defined objects and linking errors. With these defines the plugin will be safely included and all we get is access to the MFnPlugin class, which is all we need and great and safe!

Next there’s the initializePlugin function. Here you can use the macros to register nodes and commands.
> REGISTERNODE registers a node by the class name. Depending on whether you want maya nodes and functions with capital letters or not you’ll have to drop the common C++ style of classes start with a capital.

And the third interesting bit is, all the rest is automated. No uninitialize, no struggling with ids, all that stuff. The only bit you might want to change is the base value of __id. It is the first ID and any new node will increment the ID by 1. I don’t know much about where to find which ids are actually guaranteed to be free so this is just kind of random.

main.cpp

#include <vector>

#undef NT_PLUGIN
#define MNoVersionString
#include <maya/MFnPlugin.h>
#undef MNoVersionString
#define NT_PLUGIN


#include "utils.hpp"


int __id = 0x00208600;
std::vector<int> ids;
int id()
{
	ids.push_back(__id);
	return __id++;
}

std::vector<MString> cmds;


#define REGISTERNODE(NODE) stat = plugin.registerNode(#NODE, id(), NODE::sCreator, NODE::sInitialize); THROWSTATMSG("RegisterNode failed, is the TypeID already in use?")
#define REGISTERNODETYPE(NODE, TYPE) stat = plugin.registerNode(#NODE, id(), NODE::sCreator, NODE::sInitialize, TYPE); THROWSTAT
#define REGISTERCOMMAND(COMMAND) cmds.push_back(#COMMAND); stat = plugin.registerCommand(#COMMAND, COMMAND::sCreator, COMMAND::sNewSyntax); THROWSTAT


MStatus initializePlugin(MObject& pluginObj)
{
	MFnPlugin plugin(pluginObj, "Uknown", "1.0", "any");
	MStatus stat;
	
	REGISTERNODE(MyNode);
	REGISTERNODETYPE(MyShape, MPxNode::kLocatorNode);
	REGISTERCOMMAND(MyFunction);

	return stat;
}


MStatus uninitializePlugin(MObject& pluginObj)
{
	MFnPlugin plugin(pluginObj);
	MStatus stat;
	for(size_t i = ids.size() - 1; i >= 0; --i)
	{
		stat = plugin.deregisterNode(ids[i]); THROWSTAT
	}
	for(size_t i = cmds.size() - 1; i >= 0; --i)
	{
		stat = plugin.deregisterCommand(cmds[i]); THROWSTAT
	}
	return stat;
}

So yes, this may make your registering plugins life easier. Was messing about with automating other things as well, such as getting and setting plugs, but I feel that got a bit wonky in the end. May be continued…

Leave a Reply

Your email address will not be published. Required fields are marked *