利用者:Coenspoor/Minimal node tutorial(2.5)

提供: wiki
移動先: 案内検索

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;
}

blender/compositor/CMakeLists.txt