Dev:Source/Node Editor/IPOs
This document outlines my initial work on adding IPO support to nodes.
Patch
You can get the current patch at the tracker page.
How it works
Node IPOs are defined by special definition structures, called bNodeIpoChannel. They also get defined automatically by node input sockets. This section relates to exposing node parameters to the IPO system.
typedef struct bNodeIpoChannel {
char name[30];
short type;
int offset;
float min, max;
/*internal use only.*/
int datatype, sockindex, varindex;
char nodename[32];
} bNodeIpoChannel;
The fields are:
- name: The name of the ipo channel.
- type: The IPO data type (e.g. IPO_SHORT).
- offset: The offset in the node's .storage struct, can be hardcoded or calculated with a macro and a static global template struct.
- min, max: the minimum and maximum values allowed.
- datatype: set internally to 1, if this is an auto-generated node socket definition.
- sockindex, varindex: the index of a node's socket, and the index of the socket's ns.var float array to use.
- nodename: the name of the parent node.
An example would be:
static NodeBlurData blurtemplate;
static bNodeIpoChannel BlurIpoType[] = {
{"X Radius", IPO_SHORT, ((char*)&blurtemplate.sizex)-((char*)&blurtemplate), 0.0, 256.0, NIPO_USEDATA},
{"Y Radius", IPO_SHORT, ((char*)&blurtemplate.sizey)-((char*)&blurtemplate), 0.0, 256.0, NIPO_USEDATA},
{0, 0, 0}
};
static bNodeType cmp_node_blur= {
/* type code */ CMP_NODE_BLUR,
/* name */ "Blur",
/* width+range */ 120, 80, 200,
/* class+opts */ NODE_CLASS_OP_FILTER, NODE_OPTIONS,
/* input sock */ cmp_node_blur_in,
/* output sock */ cmp_node_blur_out,
/* storage */ "NodeBlurData",
/* execfunc */ node_composit_exec_blur,
/* Ipo type */ &BlurIpoType
};
Problems
Since nodes are not library block data (e.g. they don't inherit struct ID) I had to hack the IPO system to work with them. I'm not sure if this is really acceptable; what I'd really like to do would be to *make* nodes library block data, though I don't know how well that'd work.
(comment by ton) Nodes should not become Library data, that type is limited to data you allow to be re-used and freely linked internally by any other data block. The main problem is that the current Ipo system is far too weak... its original design (over 10 years old) has not proven to be very future proof.
Scene->actnode And Scene->acttree
To facilitate editing Ipos, I've added two members, actnode and acttree to Scene, to represent the active selected node and its parent nodetree. I decided not to use the internal nodetree's active node, since it seems to be in use for the material system. These members are in Scene, so you can have an active node/nodetree in each separate scene.
(comment by ton) I'll have to review this internal 'active node' then. Having multiple of these 'globals' should be avoided...