利用者:Sobotka/Minimal Node Code
目次
- 1 New Compositor HelloWorld Example
- 1.1 Register the Unique Node ID Value in source/blender/blenkernel/BKE_node.h
- 1.2 Register the new node in source/blender/blenkernel/intern/node.c
- 1.3 Add the DNA that describes the data in source/blender/makesdna/DNA_node_types.h
- 1.4 Register the Python RNA in source/blender/makesrna/intern/rna_nodetree.c
- 1.5 Register the node in Python RNA in /source/blender/nodes/NOD_static_types.h
- 1.6 Register the node in source/blender/nodes/NOD_composite.h
- 1.7 Create a new file that defines node inputs and output in source/blender/nodes/composite/nodes/node_composite_helloworld.c
- 1.8 Make sure it is compiled by adding it to source/blender/nodes/CMakeLists.txt
- 1.9 Create the header file for the node in source/blender/compositor/nodes/COM_HelloWorldNode.h
- 1.10 Create the main node file in source/blender/compositor/nodes/COM_HelloWorldNode.cpp
- 1.11 Write the header file for the operation in source/blender/compositor/operations/COM_HelloWorldOperation.h
- 1.12 Create the code that does the work in source/blender/compositor/operations/COM_HelloWorldOperation.cpp
- 1.13 Add the node to the converter code listing in source/blender/compositor/intern/COM_Converter.cpp
- 1.14 Make sure it will get compiled via cmake in source/blender/compositor/CMakeLists.txt
- 1.15 OPTIONAL: Write the code that would handle drawing in the node to source/blender/editors/space_node/drawnode.c, set the function and pointer, and set the flag in composite/nodes/nodename.c
New Compositor HelloWorld Example
Sit back, buckle up, and get ready to edit a hundred files before you see your new HelloWorld node!
TODO: Must touch COM_Converter.cpp in order to register the node too. *sigh*.
Register the Unique Node ID Value in source/blender/blenkernel/BKE_node.h
Example:
[...]
#define CMP_NODE_COLOR_MATTE 259
#define CMP_NODE_COLORBALANCE 260
#define CMP_NODE_HUECORRECT 261
#define CMP_NODE_HELLOWORLD 262 /* Add a Unique ID for our new node. */
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302
[...]
Register the new node in source/blender/blenkernel/intern/node.c
Example:
[...]
register_node_type_cmp_bokehblur(ttype);
register_node_type_cmp_switch(ttype);
register_node_type_cmp_mask(ttype);
register_node_type_cmp_trackpos(ttype);
register_node_type_cmp_helloworld(ttype);
[...]
Add the DNA that describes the data in source/blender/makesdna/DNA_node_types.h
WARNING
All DNA must be padded. This means that your data must be padded to an alignment that matches the data length. For more information, see the DNA section on the wiki. If you fail to do so, you will get an odd looking and nondescript error from makesdna.c.
|
Example:
[...]
float uspillr, uspillg, uspillb;
}NodeColorspill;
typedef struct NodeHelloWorld {
double helloDouble; /* Our Hello World data. */
} NodeHelloWorld;
/* TEX_output */
typedef struct TexNodeOutput {
char name[32];
[...]
Register the Python RNA in source/blender/makesrna/intern/rna_nodetree.c
Example:
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
}
static void def_cmp_helloworld(StructRNA *srna)
{
/* Register elements we want exposed to Python access. */
}
static void def_cmp_zcombine(StructRNA *srna)
{
PropertyRNA *prop;
Register the node in Python RNA in /source/blender/nodes/NOD_static_types.h
Example:
[...]
DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" )
DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" )
DefNode( CompositorNode, CMP_NODE_HELLOWORLD, def_cmp_helloworld, "HELLOWORLD", HelloWorld, "Hello World", "" )
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
[...]
Register the node in source/blender/nodes/NOD_composite.h
Example:
[...]
void register_node_type_cmp_bokehblur(struct bNodeTreeType *ttype);
void register_node_type_cmp_switch(struct bNodeTreeType *ttype);
void register_node_type_cmp_trackpos(struct bNodeTreeType *ttype);
void register_node_type_cmp_helloworld(struct bNodeTreeType *ttype);
#endif
Create a new file that defines node inputs and output in source/blender/nodes/composite/nodes/node_composite_helloworld.c
It should be noted that NODE_CLASS_CONVERTER determines where the node will appear in the Add menu.
Example:
#include "node_composite_util.h"
/* **************** Hello World Tool ******************** */
static bNodeSocketTemplate cmp_node_helloworld_in[]= {
{ SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Variable"), 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f, PROP_UNSIGNED},
{ -1, 0, "" }
};
static bNodeSocketTemplate cmp_node_helloworld_out[]= {
{ SOCK_RGBA, 0, N_("Image")},
{ -1, 0, "" }
};
void register_node_type_cmp_helloworld(void)
{
static bNodeType ntype;
node_type_base(&ntype, CMP_NODE_HELLOWORLD, "Hello World", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_helloworld_in, cmp_node_helloworld_out);
node_type_size(&ntype, 140, 100, 320);
nodeRegisterType(&ntype);
}
Make sure it is compiled by adding it to source/blender/nodes/CMakeLists.txt
[...]
composite/nodes/node_composite_bokehimage.c
composite/nodes/node_composite_boxmask.c
composite/nodes/node_composite_ellipsemask.c
composite/nodes/node_composite_switch.c
composite/nodes/node_composite_colorcorrection.c
composite/nodes/node_composite_helloworld.c
composite/node_composite_tree.c
composite/node_composite_util.c
[...]
Create the header file for the node in source/blender/compositor/nodes/COM_HelloWorldNode.h
#ifndef _COM_HelloWorldNode_h_
#define _COM_HelloWorldNode_h_
#include "COM_Node.h"
/**
* @brief HelloWorldNode
* @ingroup Node
*/
class HelloWorldNode : public Node {
public:
HelloWorldNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
};
#endif
Create the main node file in source/blender/compositor/nodes/COM_HelloWorldNode.cpp
#include "COM_HelloWorldNode.h"
#include "COM_HelloWorldOperation.h"
#include "COM_ExecutionSystem.h"
HelloWorldNode::HelloWorldNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
}
void HelloWorldNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
HelloWorldOperation *operation = new HelloWorldOperation();
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);
}
Write the header file for the operation in source/blender/compositor/operations/COM_HelloWorldOperation.h
#ifndef _COM_HelloWorldOperation_h
#define _COM_HelloWorldOperation_h
#include "COM_NodeOperation.h"
class HelloWorldOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
*/
SocketReader *m_inputProgram;
SocketReader *m_inputHelloWorldProgram;
public:
HelloWorldOperation();
/**
* the inner loop of this program
*/
void executePixel(float output[4], float x, float y, PixelSampler sampler);
/**
* Initialize the execution
*/
void initExecution();
/**
* Deinitialize the execution
*/
void deinitExecution();
};
#endif
Create the code that does the work in source/blender/compositor/operations/COM_HelloWorldOperation.cpp
#include "COM_HelloWorldOperation.h"
#include "BLI_math.h"
HelloWorldOperation::HelloWorldOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR);
this->addInputSocket(COM_DT_VALUE);
this->addOutputSocket(COM_DT_COLOR);
this->m_inputProgram = NULL;
this->m_inputHelloWorldProgram = NULL;
}
void HelloWorldOperation::initExecution()
{
this->m_inputProgram = this->getInputSocketReader(0);
this->m_inputHelloWorldProgram = this->getInputSocketReader(1);
}
void HelloWorldOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
float inputValue[4];
float inputHelloWorld[4];
this->m_inputProgram->read(inputValue, x, y, sampler);
this->m_inputHelloWorldProgram->read(inputHelloWorld, x, y, sampler);
const float helloworld = inputHelloWorld[0];
/* check for negative to avoid nan's */
output[0] = inputValue[0] > 0.0f ? powf(inputValue[0], helloworld) : inputValue[0];
output[1] = inputValue[1] > 0.0f ? powf(inputValue[1], helloworld) : inputValue[1];
output[2] = inputValue[2] > 0.0f ? powf(inputValue[2], helloworld) : inputValue[2];
output[3] = inputValue[3];
}
void HelloWorldOperation::deinitExecution()
{
this->m_inputProgram = NULL;
this->m_inputHelloWorldProgram = NULL;
}
Add the node to the converter code listing in source/blender/compositor/intern/COM_Converter.cpp
[...]
#include "COM_ViewerNode.h"
#include "COM_ZCombineNode.h"
#include "COM_HelloWorldNode.h"
Node *Converter::convert(bNode *b_node, bool fast)
{
Node *node;
[...]
case CMP_NODE_TRACKPOS:
node = new TrackPositionNode(b_node);
break;
case CMP_NODE_HELLOWORLD:
node = new HelloWorldNode(b_node);
break;
/* not inplemented yet */
default:
node = new MuteNode(b_node);
break;
}
return node;
}
[...]
Make sure it will get compiled via cmake in source/blender/compositor/CMakeLists.txt
Example:
[...]
operations/COM_SetAlphaOperation.cpp
operations/COM_SetAlphaOperation.h
operations/COM_MapValueOperation.cpp
operations/COM_MapValueOperation.h
# HelloWorld Nodes
nodes/COM_HelloWorldNode.cpp
nodes/COM_HelloWorldNode.h
operations/COM_HelloWorldOperation.h
operations/COM_HelloWorldOperation.cpp
# Distort operation
operations/COM_TranslateOperation.h
operations/COM_TranslateOperation.cpp
[...]
And finally add it to release/scripts/startup/nodeitems_builtins.py so it will show up in the UI
[...]
CompositorNodeCategory("CMP_CONVERTOR", "Converter", items=[
NodeItem("CompositorNodeMath"),
NodeItem("CompositorNodeHelloWorld"),
[...]
OPTIONAL: Write the code that would handle drawing in the node to source/blender/editors/space_node/drawnode.c, set the function and pointer, and set the flag in composite/nodes/nodename.c
This may need to be updated and expanded. There be dragons...
void register_node_type_cmp_composite(ListBase *lb)
{
[...]
node_type_base(&ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_PREVIEW);
// OR NODE_PREVIEW with NODE_OPTIONS!
[...]
}