From BlenderWiki
New (as of 2.5) bare minimum
This section will be further documented once I find the time to further delve into the code and better explain why you do certain things. -Coen Spoor
Define node
We first need to define our new node in certain files, to make the compile process and Blender aware of it
source/blender/blenkernel/BKE_node.h
Assign a unique ID to the node(around line 660)
... #define CMP_NODE_MASK 268 #define CMP_NODE_KEYINGSCREEN 269 #define CMP_NODE_KEYING 270 #define CMP_NODE_YOURNODE 290 ...
source/blender/blenkernel/intern/node.c
Create the register function(line 1920)
... register_node_type_cmp_doubleedgemask(ttype); register_node_type_cmp_keyingscreen(ttype); register_node_type_cmp_keying(ttype); register_node_type_cmp_yournode(ttype); ...
source/blender/makesdna/DNA_node_types.h
around line 550
typedef struct NodeYourNode { /*variables you want access to*/ } NodeYourNode;
source/blender/makesrna/intern/rna_nodetree.c
static void def_cmp_yournode(StructRNA *srna) { /* to be documented*/ }
source/blender/makesrna/intern/rna_nodetree_types.h
DefNode( CompositorNode, CMP_NODE_YOURNODE, def_cmp_yournode, "YOURNODE", YourNode, "YourNode", "" )
source/blender/nodes/NOD_composite.h
void register_node_type_cmp_yournode(struct bNodeTreeType *ttype);
Create the node itself
source/blender/nodes/composite/nodes/node_composite_yournode.c
#include "node_composite_util.h" /* **************** yournode Tools ******************** */ static bNodeSocketTemplate cmp_node_yournode_in[]= { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("VAL"), 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f, PROP_UNSIGNED}, { -1, 0, "" } }; static bNodeSocketTemplate cmp_node_yournode_out[]= { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; static void do_yournode(bNode *UNUSED(node), float *out, float *in, float *fac) { int i=0; for (i=0; i<3; i++) { /* check for negative to avoid nan's */ out[i] = in[i]; } out[3] = in[3]; } static void node_composit_exec_yournode(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order in: Fac, Image */ /* stack order out: Image */ if (out[0]->hasoutput==0) return; /* input no image? then only color operation */ if (in[0]->data==NULL) { do_yournode(node, out[0]->vec, in[0]->vec, in[1]->vec); } else { /* make output size of input image */ CompBuf *cbuf= in[0]->data; CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs composit2_pixel_processor(node, stackbuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_yournode, CB_RGBA, CB_VAL); out[0]->data= stackbuf; } } void register_node_type_cmp_yournode(bNodeTreeType *ttype) { static bNodeType ntype; node_type_base(ttype, &ntype, CMP_NODE_YOURNODE, "YourNode", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_yournode_in, cmp_node_yournode_out); node_type_size(&ntype, 140, 100, 320); node_type_exec(&ntype, node_composit_exec_yournode); nodeRegisterType(ttype, &ntype); }
blender/nodes/CMakeLists.txt
composite/nodes/node_composite_yournode.c
New Compositor
Define and include our node/operation
blender/compositor/intern/COM_Converter.cpp
... #include "COM_YourNode.h" #include "COM_YourOperation.h" ... switch (b_node->type) { ... case CMP_NODE_YOURNODE: node = new YourNode(b_node); break;
Create the node
blender/compositor/nodes/COM_YourNode.h
#ifndef _COM_YourNode_h_ #define _COM_YourNode_h_ #include "COM_Node.h" /** * @brief YourNode * @ingroup Node */ class YourNode : public Node { public: YourNode(bNode *editorNode); void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; #endif
blender/compositor/nodes/COM_YourNode.cpp
#include "COM_YourNode.h" #include "DNA_scene_types.h" #include "COM_YourOperation.h" #include "COM_ExecutionSystem.h" YourNode::YourNode(bNode *editorNode) : Node(editorNode) { /* pass */ } void YourNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { YourOperation *operation = new YourOperation(); this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(operation); }
Create the logic that your node will execute
blender/compositor/operations/COM_YourOperation.h
#ifndef _COM_YourOperation_h #define _COM_YourOperation_h #include "COM_NodeOperation.h" class YourOperation : public NodeOperation { private: /** * Cached reference to the inputProgram */ SocketReader *m_inputProgram; SocketReader *m_inputYourProgram; public: YourOperation(); /** * the inner loop of this program */ void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer * inputBuffers[]); /** * Initialize the execution */ void initExecution(); /** * Deinitialize the execution */ void deinitExecution(); }; #endif
blender/compositor/operations/COM_YourOperation.cpp
#include "COM_YouraOperation.h" #include "BLI_math.h" /*you probably are going to do something math related*/ GammaOperation::YourOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); this->addOutputSocket(COM_DT_COLOR); this->m_inputProgram = NULL; this->m_inputYourProgram = NULL; } void YourOperation::initExecution() { this->m_inputProgram = this->getInputSocketReader(0); this->m_inputYourProgram = this->getInputSocketReader(1); } void YourOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) { /* Write logic here */ } void YourOperation::deinitExecution() { this->m_inputProgram = NULL; this->m_inputYourProgram = NULL; }