Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Toenne <lukas.toenne@googlemail.com>2013-03-18 20:34:57 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2013-03-18 20:34:57 +0400
commit4638e5f99a9ba59ad0b8a1fd52b12e876480b9e8 (patch)
tree2444f12b4612440f44cf02835cdf5951b6564e92 /source/blender/blenkernel/BKE_node.h
parent7bfef29f2f2a1b262d28abdc6e30fcd9c1f1caad (diff)
Merge of the PyNodes branch (aka "custom nodes") into trunk.
PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
Diffstat (limited to 'source/blender/blenkernel/BKE_node.h')
-rw-r--r--source/blender/blenkernel/BKE_node.h489
1 files changed, 347 insertions, 142 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 80955729326..513851ce18f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -32,8 +32,21 @@
* \ingroup bke
*/
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
+
#include "DNA_listBase.h"
+/* for FOREACH_NODETREE */
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "RNA_types.h"
+
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
@@ -43,7 +56,10 @@ struct bNodeLink;
struct bNodeSocket;
struct bNodeStack;
struct bNodeTree;
+struct bNodeTreeType;
struct bNodeTreeExec;
+struct bNodeExecContext;
+struct bNodeExecData;
struct GPUMaterial;
struct GPUNode;
struct GPUNodeStack;
@@ -65,6 +81,7 @@ struct ARegion;
struct Object;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
+struct bNodeInstanceHash;
/* ************** NODE TYPE DEFINITIONS ***** */
@@ -72,9 +89,9 @@ struct ColorManagedDisplaySettings;
* Can be used to quickly define a list of static sockets for a node,
* which are added to each new node of that type.
*
- * \deprecated New nodes should add default sockets in the initialization
- * function instead. This struct is mostly kept for old nodes and should
- * be removed some time.
+ * \deprecated This struct is used by C nodes to define templates as simple
+ * static struct lists. These are converted to the new template collections
+ * in RNA types automatically.
*/
typedef struct bNodeSocketTemplate {
int type, limit;
@@ -86,38 +103,38 @@ typedef struct bNodeSocketTemplate {
/* after this line is used internal only */
struct bNodeSocket *sock; /* used to hold verified socket */
+ char identifier[64]; /* generated from name */
} bNodeSocketTemplate;
-typedef void (*NodeSocketButtonFunction)(const struct bContext *C, struct uiBlock *block,
- struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock,
- const char *name, int x, int y, int width);
-
/** Defines a socket type.
* Defines the appearance and behavior of a socket in the UI.
*/
typedef struct bNodeSocketType {
- int type;
- char ui_name[64]; /* MAX_NAME */
- char ui_description[128];
- int ui_icon;
- char ui_color[4];
+ char idname[64]; /* identifier name */
+
+ void (*draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr);
+ void (*draw_color)(struct bContext *C, struct PointerRNA *ptr, struct PointerRNA *node_ptr, float *r_color);
+
+ void (*interface_draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr);
+ void (*interface_draw_color)(struct bContext *C, struct PointerRNA *ptr, float *r_color);
+ void (*interface_register_properties)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct StructRNA *data_srna);
+ void (*interface_init_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock, const char *data_path);
+ void (*interface_from_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock);
- const char *value_structname;
- int value_structsize;
+ /* RNA integration */
+ ExtensionRNA ext_socket;
+ ExtensionRNA ext_interface;
- NodeSocketButtonFunction buttonfunc;
+ /* for standard socket types in C */
+ int type, subtype;
} bNodeSocketType;
-/** Template for creating a node.
- * Stored required parameters to make a new node of a specific type.
- */
-typedef struct bNodeTemplate {
- int type;
-
- struct Main *main;
- struct Scene *scene;
- struct bNodeTree *ngroup; /* group tree */
-} bNodeTemplate;
+typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr, int linked);
+
+typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
+typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata);
+typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out);
+typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat, struct bNode *node, struct bNodeExecData *execdata, struct GPUNodeStack *in, struct GPUNodeStack *out);
/** Defines a node type.
* Initial attributes and constants for a node as well as callback functions
@@ -127,8 +144,13 @@ typedef struct bNodeType {
void *next, *prev;
short needs_free; /* set for allocated types that need to be freed */
+ char idname[64]; /* identifier name */
int type;
- char name[64]; /* MAX_NAME */
+
+ char ui_name[64]; /* MAX_NAME */
+ char ui_description[256];
+ int ui_icon;
+
float width, minwidth, maxwidth;
float height, minheight, maxheight;
short nclass, flag, compatibility;
@@ -139,7 +161,8 @@ typedef struct bNodeType {
char storagename[64]; /* struct name for DNA */
/// Main draw function for the node.
- void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+ void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
/// Updates the node geometry attributes according to internal state before actual drawing.
void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
/// Draw the option buttons on the node.
@@ -150,8 +173,11 @@ typedef struct bNodeType {
void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
/// Draw a node socket. Default draws the input value button.
- NodeSocketButtonFunction drawinputfunc;
- NodeSocketButtonFunction drawoutputfunc;
+ /* XXX deprecated, only used for the OutputFile node,
+ * should be removed at some point.
+ */
+ NodeSocketDrawFunction drawinputfunc;
+ NodeSocketDrawFunction drawoutputfunc;
/// Optional custom label function for the node header.
const char *(*labelfunc)(struct bNode *);
@@ -168,45 +194,42 @@ typedef struct bNodeType {
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
/// Initialize a new node instance of this type after creation.
- void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp);
- /// Free the custom storage data.
- void (*freestoragefunc)(struct bNode *node);
- /// Make a copy of the custom storage data.
- void (*copystoragefunc)(struct bNode *node, struct bNode *target);
+ void (*initfunc)(struct bNodeTree *ntree, struct bNode *node);
+ /// Free the node instance.
+ void (*freefunc)(struct bNode *node);
+ /// Make a copy of the node instance.
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
- /// Create a template from an existing node.
- struct bNodeTemplate (*templatefunc)(struct bNode *);
- /** If a node can be made from the template in the given node tree.
- * \note Node groups can not be created inside their own node tree.
- */
- int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+ /* Registerable API callback versions, called in addition to C callbacks */
+ void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr);
+ void (*freefunc_api)(struct PointerRNA *ptr);
+ void (*copyfunc_api)(struct PointerRNA *ptr, struct bNode *src_node);
- /// Initialize a node tree associated to this node type.
- void (*inittreefunc)(struct bNodeTree *ntree);
- /// Update a node tree associated to this node type.
- void (*updatetreefunc)(struct bNodeTree *ntree);
-
- /* group edit callbacks for operators */
- /* XXX this is going to be changed as required by the UI */
- struct bNodeTree *(*group_edit_get)(struct bNode *node);
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit);
- void (*group_edit_clear)(struct bNode *node);
+ /* can this node type be added to a node tree */
+ int (*poll)(struct bNodeType *ntype, struct bNodeTree *nodetree);
+ /* can this node be added to a node tree */
+ int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree);
/* Update the internal links list, for muting and disconnect operators. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
/* **** execution callbacks **** */
- void *(*initexecfunc)(struct bNode *node);
- void (*freeexecfunc)(struct bNode *node, void *nodedata);
- void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
- /* XXX this alternative exec function has been added to avoid changing all node types.
- * when a final generic version of execution code is defined, this will be changed anyway
- */
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **);
+ NodeInitExecFunction initexecfunc;
+ NodeFreeExecFunction freeexecfunc;
+ NodeExecFunction execfunc;
/* gpu */
- int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
- /* extended gpu function */
- int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out);
+ NodeGPUExecFunction gpufunc;
+
+ /* Group type static info
+ *
+ * XXX This data is needed by group operators. If these operators could be implemented completely in Python,
+ * the static data could instead be stored in Python classes and would need no special treatment.
+ * Due to the way group operators move nodes between data blocks this is currently not possible.
+ */
+ char group_tree_idname[64]; /* tree type associated to the group node type */
+
+ /* RNA integration */
+ ExtensionRNA ext;
} bNodeType;
/* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -245,6 +268,7 @@ typedef struct bNodeType {
#define NODE_CLASS_TRANSFORM 30
#define NODE_CLASS_COMBINE 31
#define NODE_CLASS_SCRIPT 32
+#define NODE_CLASS_INTERFACE 33
#define NODE_CLASS_SHADER 40
#define NODE_CLASS_LAYOUT 100
@@ -258,10 +282,6 @@ typedef struct bNodeType {
#define NODE_RESIZE_RIGHT 4
#define NODE_RESIZE_LEFT 8
-/* enum values for input/output */
-#define SOCK_IN 1
-#define SOCK_OUT 2
-
typedef enum eNodeSizePreset {
NODE_SIZE_DEFAULT,
NODE_SIZE_SMALL,
@@ -270,19 +290,26 @@ typedef enum eNodeSizePreset {
struct bNodeTreeExec;
-typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name);
typedef struct bNodeTreeType {
int type; /* type identifier */
- char idname[64]; /* id name for RNA identification */
-
- ListBase node_types; /* type definitions */
+ char idname[64]; /* identifier name */
+
+ char ui_name[64];
+ char ui_description[256];
+ int ui_icon;
/* callbacks */
void (*free_cache)(struct bNodeTree *ntree);
void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node);
- void (*foreach_nodetree)(struct Main *main, void *calldata, bNodeTreeCallback func); /* iteration over all node trees */
void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
+ /* Add menu for this node tree. */
+ void (*draw_add_menu)(const struct bContext *C, struct uiLayout *layout, struct bNodeTree *ntree);
+ /* Check visibility in the node editor */
+ int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
+ /* Select a node tree from the context */
+ void (*get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype,
+ struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from);
/* calls allowing threaded composite */
void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
@@ -291,23 +318,37 @@ typedef struct bNodeTreeType {
/* Tree update. Overrides nodetype->updatetreefunc! */
void (*update)(struct bNodeTree *ntree);
- /* Node update. Overrides nodetype->updatefunc! */
- void (*update_node)(struct bNodeTree *ntree, struct bNode *node);
int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
-
- /* Default internal linking. */
- void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
+
+ /* RNA integration */
+ ExtensionRNA ext;
} bNodeTreeType;
+
/* ************** GENERIC API, TREES *************** */
-struct bNodeTreeType *ntreeGetType(int type);
-struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree);
-struct bNodeSocketType *ntreeGetSocketType(int type);
+struct bNodeTreeType *ntreeTypeFind(const char *idname);
+void ntreeTypeAdd(struct bNodeTreeType* nt);
+void ntreeTypeFreeLink(struct bNodeTreeType* nt);
+struct GHashIterator *ntreeTypeGetIterator(void);
+
+/* helper macros for iterating over tree types */
+#define NODE_TREE_TYPES_BEGIN(ntype) \
+{ \
+ GHashIterator *__node_tree_type_iter__ = ntreeTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_tree_type_iter__); BLI_ghashIterator_step(__node_tree_type_iter__)) { \
+ bNodeTreeType *ntype = BLI_ghashIterator_getValue(__node_tree_type_iter__);
-struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, int type, int nodetype);
-void ntreeInitTypes(struct bNodeTree *ntree);
+#define NODE_TREE_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_tree_type_iter__); \
+}
+
+void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
+int ntreeIsValid(struct bNodeTree *ntree);
+
+struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user);
@@ -337,8 +378,6 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode *
* new tree types have a per-output socket flag to indicate the final output to use explicitly.
*/
void ntreeSetOutput(struct bNodeTree *ntree);
-void ntreeInitPreview(struct bNodeTree *, int xsize, int ysize);
-void ntreeClearPreview(struct bNodeTree *ntree);
void ntreeFreeCache(struct bNodeTree *ntree);
@@ -348,29 +387,86 @@ struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
void ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree);
+/* ************** NODE TREE INTERFACE *************** */
+
+struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree, int in_out, const char *identifier);
+struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname, const char *name);
+struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname,
+ struct bNodeSocket *next_sock, const char *name);
+struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock);
+struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNodeSocket *next_sock,
+ struct bNode *from_node, struct bNodeSocket *from_sock);
+void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock);
+
+struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create);
+void ntreeInterfaceTypeFree(struct bNodeTree *ntree);
+void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
+
/* ************** GENERIC API, NODES *************** */
-struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *name, int type);
-struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, struct bNodeSocket *next_sock, const char *name, int type);
+struct bNodeType *nodeTypeFind(const char *idname);
+void nodeRegisterType(struct bNodeType* ntype);
+void nodeUnregisterType(struct bNodeType* ntype);
+struct GHashIterator *nodeTypeGetIterator(void);
+
+/* helper macros for iterating over node types */
+#define NODE_TYPES_BEGIN(ntype) \
+{ \
+ GHashIterator *__node_type_iter__ = nodeTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_type_iter__); BLI_ghashIterator_step(__node_type_iter__)) { \
+ bNodeType *ntype = BLI_ghashIterator_getValue(__node_type_iter__);
+
+#define NODE_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_type_iter__); \
+}
+
+struct bNodeSocketType *nodeSocketTypeFind(const char *idname);
+void nodeRegisterSocketType(struct bNodeSocketType* stype);
+void nodeUnregisterSocketType(struct bNodeSocketType* stype);
+struct GHashIterator *nodeSocketTypeGetIterator(void);
+const char * nodeStaticSocketType(int type, int subtype);
+const char * nodeStaticSocketInterfaceType(int type, int subtype);
+
+/* helper macros for iterating over node types */
+#define NODE_SOCKET_TYPES_BEGIN(stype) \
+{ \
+ GHashIterator *__node_socket_type_iter__ = nodeSocketTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_socket_type_iter__); BLI_ghashIterator_step(__node_socket_type_iter__)) { \
+ bNodeSocketType *stype = BLI_ghashIterator_getValue(__node_socket_type_iter__);
+
+#define NODE_SOCKET_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_socket_type_iter__); \
+}
+
+void nodeMakeDynamicType(struct bNode *node);
+int nodeDynamicUnlinkText(struct ID *txtid);
+
+struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier);
+struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
+ const char *identifier, const char *name);
+struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
+ struct bNodeSocket *next_sock, const char *identifier, const char *name);
+struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
+ const char *identifier, const char *name);
+struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
+ struct bNodeSocket *next_sock, const char *identifier, const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
-void nodeAddToPreview(struct bNode *node, const float col[4], int x, int y, int do_manage);
-
-struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
+struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
-void nodeRegisterType(struct bNodeTreeType *ttype, struct bNodeType *ntype);
-void nodeMakeDynamicType(struct bNode *node);
-int nodeDynamicUnlinkText(struct ID *txtid);
-
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
+int nodeLinkIsHidden(struct bNodeLink *link);
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node);
void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -380,11 +476,12 @@ void nodeAttachNode(struct bNode *node, struct bNode *parent);
void nodeDetachNode(struct bNode *node);
struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
-int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex, int *in_out);
+int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
+void nodeSetSelected(struct bNode *node, int select);
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeGetActive(struct bNodeTree *ntree);
struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
@@ -396,11 +493,9 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
void nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
int nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
-
-void nodeFreePreview(struct bNode *node);
+void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
int nodeSocketIsHidden(struct bNodeSocket *sock);
-void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
@@ -412,78 +507,189 @@ const struct ListBase *BKE_node_clipboard_get_nodes(void);
const struct ListBase *BKE_node_clipboard_get_links(void);
int BKE_node_clipboard_get_type(void);
+/* Node Instance Hash */
+typedef struct bNodeInstanceHash
+{
+ GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */
+} bNodeInstanceHash;
+
+typedef void (*bNodeInstanceValueFP)(void *value);
+
+extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE;
+
+bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, struct bNodeTree *ntree, struct bNode *node);
+
+bNodeInstanceHash * BKE_node_instance_hash_new(const char *info);
+void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value);
+void* BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp);
+void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+void* BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_size(bNodeInstanceHash *hash);
+
+void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash);
+void BKE_node_instance_hash_tag(bNodeInstanceHash *hash, void *value);
+int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key);
+void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+
+typedef GHashIterator bNodeInstanceHashIterator;
+
+BLI_INLINE bNodeInstanceHashIterator *BKE_node_instance_hash_iterator_new(bNodeInstanceHash *hash) { return BLI_ghashIterator_new(hash->ghash); }
+BLI_INLINE void BKE_node_instance_hash_iterator_init(bNodeInstanceHashIterator *iter, bNodeInstanceHash *hash) { BLI_ghashIterator_init(iter, hash->ghash); }
+BLI_INLINE void BKE_node_instance_hash_iterator_free(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_free(iter); }
+BLI_INLINE bNodeInstanceKey BKE_node_instance_hash_iterator_get_key(bNodeInstanceHashIterator *iter) { return *(bNodeInstanceKey *)BLI_ghashIterator_getKey(iter); }
+BLI_INLINE void* BKE_node_instance_hash_iterator_get_value(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_getValue(iter); }
+BLI_INLINE void BKE_node_instance_hash_iterator_step(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_step(iter); }
+BLI_INLINE bool BKE_node_instance_hash_iterator_not_done(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_notDone(iter); }
+
+#define NODE_INSTANCE_HASH_ITER(iter_, hash_) \
+ for (BKE_node_instance_hash_iterator_init(&iter_, hash_); \
+ BKE_node_instance_hash_iterator_not_done(&iter_); \
+ BKE_node_instance_hash_iterator_step(&iter_))
+
+
+/* Node Previews */
+
+int BKE_node_preview_used(struct bNode *node);
+bNodePreview* BKE_node_preview_verify(struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create);
+bNodePreview* BKE_node_preview_copy(struct bNodePreview *preview);
+void BKE_node_preview_free(struct bNodePreview *preview);
+void BKE_node_preview_init_tree(struct bNodeTree *ntree, int xsize, int ysize, int create_previews);
+void BKE_node_preview_free_tree(struct bNodeTree *ntree);
+void BKE_node_preview_remove_unused(struct bNodeTree *ntree);
+void BKE_node_preview_clear(struct bNodePreview *preview);
+void BKE_node_preview_clear_tree(struct bNodeTree *ntree);
+
+void BKE_node_preview_sync_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
+void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
+
+void BKE_node_preview_set_pixel(struct bNodePreview *preview, const float col[4], int x, int y, int do_manage);
+
+
/* ************** NODE TYPE ACCESS *************** */
-struct bNodeTemplate nodeMakeTemplate(struct bNode *node);
-int nodeValid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
const char *nodeLabel(struct bNode *node);
struct bNodeTree *nodeGroupEditGet(struct bNode *node);
struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit);
void nodeGroupEditClear(struct bNode *node);
+int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree);
+
/* Init a new node type struct with default values and callbacks */
-void node_type_base(struct bNodeTreeType *ttype, struct bNodeType *ntype, int type,
- const char *name, short nclass, short flag);
+void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+void node_type_base_custom(struct bNodeType *ntype, const char *idname, const char *name, short nclass, short flag);
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs);
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth);
void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size);
-void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp));
-void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp));
+void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node));
void node_type_storage(struct bNodeType *ntype,
const char *storagename,
- void (*freestoragefunc)(struct bNode *),
- void (*copystoragefunc)(struct bNode *, struct bNode *));
+ void (*freefunc)(struct bNode *node),
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node));
void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *));
-void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *));
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node),
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id));
-void node_type_tree(struct bNodeType *ntype,
- void (*inittreefunc)(struct bNodeTree *),
- void (*updatetreefunc)(struct bNodeTree *));
-void node_type_group_edit(struct bNodeType *ntype,
- struct bNodeTree *(*group_edit_get)(struct bNode *node),
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit),
- void (*group_edit_clear)(struct bNode *node));
-
-void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **,
- struct bNodeStack **));
-void node_type_exec_new(struct bNodeType *ntype,
- void *(*initexecfunc)(struct bNode *node),
- void (*freeexecfunc)(struct bNode *node, void *nodedata),
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata,
- struct bNodeStack **, struct bNodeStack **));
+
+void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc);
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc);
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
-void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node,
- struct GPUNodeStack *in, struct GPUNodeStack *out));
-void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node,
- void *nodedata, struct GPUNodeStack *in,
- struct GPUNodeStack *out));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
/* ************** COMMON NODES *************** */
+#define NODE_UNDEFINED -2 /* node type is not registered */
+#define NODE_CUSTOM -1 /* for dynamically registered custom types */
#define NODE_GROUP 2
-#define __NODE_FORLOOP 3 /* deprecated */
+#define __NODE_FORLOOP 3 /* deprecated */
#define __NODE_WHILELOOP 4 /* deprecated */
#define NODE_FRAME 5
#define NODE_REROUTE 6
+#define NODE_GROUP_INPUT 7
+#define NODE_GROUP_OUTPUT 8
-/* look up a socket on a group node by the internal group socket */
-struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock);
-struct bNodeSocket *node_group_find_output(struct bNode *gnode, struct bNodeSocket *gsock);
+void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
-struct bNodeSocket *node_group_add_socket(struct bNodeTree *ngroup, const char *name, int type, int in_out);
-struct bNodeSocket *node_group_expose_socket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out);
-void node_group_expose_all_sockets(struct bNodeTree *ngroup);
-void node_group_remove_socket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out);
-struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBase *lb, int in_out, struct bNodeSocket *gsock);
-
-/* in node_common.c */
-void register_node_type_frame(struct bNodeTreeType *ttype);
-void register_node_type_reroute(struct bNodeTreeType *ttype);
+/* Utility macro for visiting every node tree in the library data, including local bNodeTree blocks in other IDs.
+ * This avoids the need for callback functions and allows executing code in a single inner code block.
+ *
+ * Variables:
+ *
+ * nodetree: The actual bNodeTree data block.
+ * Check nodetree->idname or nodetree->typeinfo to use only specific types.
+ *
+ * id: The owner of the bNodeTree data block.
+ * Same as nodetree if it's a linkable node tree from the library.
+ *
+ * Examples:
+ *
+ * FOREACH_NODETREE(bmain, nodetree)
+ * if (id == nodetree)
+ * printf("This is a linkable node tree");
+ * FOREACH_NODETREE_END
+ *
+ * FOREACH_NODETREE(bmain, nodetree)
+ * if (nodetree->idname == "ShaderNodeTree")
+ * printf("This is a shader node tree);
+ * if (GS(id) == ID_MA)
+ * printf(" and it's owned by a material");
+ * FOREACH_NODETREE_END
+ */
-void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
+#define FOREACH_NODETREE(bmain, _nodetree, _id) \
+{ \
+ bNodeTree *_nodetree; \
+ ID *_id; \
+ bNodeTree *_ngroup = bmain->nodetree.first; \
+ Scene *_scene = bmain->scene.first; \
+ Material *_mat = bmain->mat.first; \
+ Tex *_tex = bmain->tex.first; \
+ Lamp *_lamp = bmain->lamp.first; \
+ World *_world = bmain->world.first; \
+ /* avoid compiler warning about unused variables */ \
+ (void)_id; \
+ (void)_nodetree; \
+ do { \
+ if (_ngroup) { \
+ _nodetree = _ngroup; \
+ _id = (ID *)_ngroup; \
+ _ngroup = _ngroup->id.next; \
+ } \
+ else if (_scene) { \
+ _nodetree = _scene->nodetree; \
+ _id = (ID *)_scene; \
+ _scene = _scene->id.next; \
+ } \
+ else if (_mat) { \
+ _nodetree = _mat->nodetree; \
+ _id = (ID *)_mat; \
+ _mat = _mat->id.next; \
+ } \
+ else if (_tex) { \
+ _nodetree = _tex->nodetree; \
+ _id = (ID *)_tex; \
+ _tex = _tex->id.next; \
+ } \
+ else if (_lamp) { \
+ _nodetree = _lamp->nodetree; \
+ _id = (ID *)_lamp; \
+ _lamp = _lamp->id.next; \
+ } \
+ else if (_world) { \
+ _nodetree = _world->nodetree; \
+ _id = (ID *)_world; \
+ _world = _world->id.next; \
+ } \
+ else \
+ break; \
+ if (_nodetree) {
+
+#define FOREACH_NODETREE_END \
+ } \
+ } while (TRUE); \
+}
/* ************** SHADER NODES *************** */
@@ -583,11 +789,10 @@ struct ShadeResult;
/* API */
-struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
+struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
+void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
-void nodeShaderSynchronizeID(struct bNode *node, int copyto);
/* switch material render loop */
extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
@@ -798,8 +1003,8 @@ struct TexResult;
int ntreeTexTagAnimated(struct bNodeTree *ntree);
void ntreeTexCheckCyclics(struct bNodeTree *ntree);
-struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
+struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
+void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
float coord[3], float dxt[3], float dyt[3], int osatex, const short thread,
struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);