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/makesrna/intern/rna_nodetree.c
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/makesrna/intern/rna_nodetree.c')
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c4154
1 files changed, 3038 insertions, 1116 deletions
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e7c030d5cdf..99b4f5a794d 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -61,11 +62,22 @@
#include "MEM_guardedalloc.h"
-EnumPropertyItem nodetree_type_items[] = {
- {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
- {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
- {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
- {0, NULL, 0, NULL, NULL}
+EnumPropertyItem node_socket_in_out_items[] = {
+ { SOCK_IN, "IN", 0, "Input", "" },
+ { SOCK_OUT, "OUT", 0, "Output", "" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+EnumPropertyItem node_socket_type_items[] = {
+ {SOCK_CUSTOM, "CUSTOM", 0, "Custom", ""},
+ {SOCK_FLOAT, "VALUE", 0, "Value", ""},
+ {SOCK_INT, "INT", 0, "Int", ""},
+ {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_STRING, "STRING", 0, "String", ""},
+ {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
+ {SOCK_SHADER, "SHADER", 0, "Shader", ""},
+ {0, NULL, 0, NULL, NULL}
};
EnumPropertyItem node_quality_items[] = {
@@ -85,17 +97,15 @@ EnumPropertyItem node_chunksize_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem node_socket_type_items[] = {
- {SOCK_FLOAT, "VALUE", 0, "Value", ""},
- {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
- {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
- {SOCK_SHADER, "SHADER", 0, "Shader", ""},
- {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
- {SOCK_MESH, "MESH", 0, "Mesh", ""},
- {SOCK_INT, "INT", 0, "Int", ""},
- {SOCK_STRING, "STRING", 0, "String", ""},
- {0, NULL, 0, NULL, NULL}
-};
+#define DEF_ICON_BLANK_SKIP
+#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
+#define DEF_VICO(name)
+EnumPropertyItem node_icon_items[] = {
+#include "UI_icons.h"
+ {0, NULL, 0, NULL, NULL}};
+#undef DEF_ICON_BLANK_SKIP
+#undef DEF_ICON
+#undef DEF_VICO
EnumPropertyItem node_math_items[] = {
{ 0, "ADD", 0, "Add", ""},
@@ -174,52 +184,20 @@ EnumPropertyItem prop_wave_items[] = {
};
#endif
-/* Add any new socket value subtype here.
- * When adding a new subtype here, make sure you also add it
- * to the subtype definitions in DNA_node_types.h.
- * This macro is used by the RNA and the internal converter functions
- * to define all socket subtypes. The SUBTYPE macro must be defined
- * before using this macro, and undefined afterwards.
- */
-#define NODE_DEFINE_SUBTYPES_INT \
- SUBTYPE(INT, Int, NONE, None) \
- SUBTYPE(INT, Int, UNSIGNED, Unsigned)
-
-#define NODE_DEFINE_SUBTYPES_FLOAT \
- SUBTYPE(FLOAT, Float, NONE, None) \
- SUBTYPE(FLOAT, Float, UNSIGNED, Unsigned) \
- SUBTYPE(FLOAT, Float, PERCENTAGE, Percentage) \
- SUBTYPE(FLOAT, Float, FACTOR, Factor) \
- SUBTYPE(FLOAT, Float, ANGLE, Angle) \
- SUBTYPE(FLOAT, Float, TIME, Time) \
- SUBTYPE(FLOAT, Float, DISTANCE, Distance)
-
-#define NODE_DEFINE_SUBTYPES_STRING \
- SUBTYPE(STRING, String, NONE, None) \
- SUBTYPE(STRING, String, FILEPATH, Filepath)
-
-#define NODE_DEFINE_SUBTYPES_VECTOR \
- SUBTYPE(VECTOR, Vector, NONE, None) \
- SUBTYPE(VECTOR, Vector, TRANSLATION, Translation) \
- SUBTYPE(VECTOR, Vector, DIRECTION, Direction) \
- SUBTYPE(VECTOR, Vector, VELOCITY, Velocity) \
- SUBTYPE(VECTOR, Vector, ACCELERATION, Acceleration) \
- SUBTYPE(VECTOR, Vector, EULER, Euler) \
- SUBTYPE(VECTOR, Vector, XYZ, XYZ)
-
-#define NODE_DEFINE_SUBTYPES \
- NODE_DEFINE_SUBTYPES_INT \
- NODE_DEFINE_SUBTYPES_FLOAT \
- NODE_DEFINE_SUBTYPES_STRING \
- NODE_DEFINE_SUBTYPES_VECTOR \
-
#ifdef RNA_RUNTIME
#include "BLI_linklist.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_idprop.h"
#include "BKE_global.h"
#include "ED_node.h"
+#include "ED_render.h"
+
+#include "NOD_socket.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -227,66 +205,1334 @@ EnumPropertyItem prop_wave_items[] = {
#include "DNA_scene_types.h"
#include "WM_api.h"
-static StructRNA *rna_Node_refine(struct PointerRNA *ptr)
+
+int rna_node_tree_type_to_enum(bNodeTreeType *typeinfo)
{
- bNode *node = (bNode *)ptr->data;
+ int i=0, result=-1;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (nt == typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
+
+int rna_node_tree_idname_to_enum(const char *idname)
+{
+ int i=0, result=-1;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (strcmp(nt->idname, idname)==0) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
- switch (node->type) {
+bNodeTreeType *rna_node_tree_type_from_enum(int value)
+{
+ int i=0;
+ bNodeTreeType *result=NULL;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (i == value) {
+ result = nt;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, bNodeTreeType *), int *free)
+{
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ int totitem=0, i=0;
+
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (poll && !poll(data, nt)) {
+ ++i;
+ continue;
+ }
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- case ID: return &RNA_##Category##StructName;
-
- #include "rna_nodetree_types.h"
+ tmp.value = i;
+ tmp.identifier = nt->idname;
+ tmp.icon = nt->ui_icon;
+ tmp.name = nt->ui_name;
+ tmp.description = nt->ui_description;
- case NODE_GROUP:
- return &RNA_NodeGroup;
- case NODE_FRAME:
- return &RNA_NodeFrame;
- case NODE_REROUTE:
- return &RNA_NodeReroute;
- default:
- return &RNA_Node;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_TREE_TYPES_END
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+int rna_node_type_to_enum(bNodeType *typeinfo)
+{
+ int i=0, result=-1;
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype==typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+int rna_node_idname_to_enum(const char *idname)
+{
+ int i=0, result=-1;
+ NODE_TYPES_BEGIN(ntype)
+ if (strcmp(ntype->idname, idname)==0) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+bNodeType *rna_node_type_from_enum(int value)
+{
+ int i=0;
+ bNodeType *result=NULL;
+ NODE_TYPES_BEGIN(ntype)
+ if (i==value) {
+ result = ntype;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, bNodeType *), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem=0, i=0;
+
+ NODE_TYPES_BEGIN(ntype)
+ if (poll && !poll(data, ntype)) {
+ ++i;
+ continue;
+ }
+
+ tmp.value = i;
+ tmp.identifier = ntype->idname;
+ tmp.icon = ntype->ui_icon;
+ tmp.name = ntype->ui_name;
+ tmp.description = ntype->ui_description;
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_TYPES_END
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+int rna_node_socket_type_to_enum(bNodeSocketType *typeinfo)
+{
+ int i=0, result=-1;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (stype==typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+int rna_node_socket_idname_to_enum(const char *idname)
+{
+ int i=0, result=-1;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (strcmp(stype->idname, idname)==0) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+bNodeSocketType *rna_node_socket_type_from_enum(int value)
+{
+ int i=0;
+ bNodeSocketType *result=NULL;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (i==value) {
+ result = stype;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, bNodeSocketType *), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem=0, i=0;
+ StructRNA *srna;
+
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (poll && !poll(data, stype)) {
+ ++i;
+ continue;
+ }
+
+ srna = stype->ext_socket.srna;
+ tmp.value = i;
+ tmp.identifier = stype->idname;
+ tmp.icon = RNA_struct_ui_icon(srna);
+ tmp.name = RNA_struct_ui_name(srna);
+ tmp.description = RNA_struct_ui_description(srna);
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_SOCKET_TYPES_END
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp;
+ int totitem=0;
+
+ /* hack, don't want to add include path to RNA just for this, since in the future RNA types
+ * for nodes should be defined locally at runtime anyway ...
+ */
+
+ tmp.value = NODE_CUSTOM;
+ tmp.identifier = "CUSTOM";
+ tmp.name = "Custom";
+ tmp.description = "Custom Node";
+ tmp.icon = ICON_NONE;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ tmp.value = NODE_UNDEFINED;
+ tmp.identifier = "UNDEFINED";
+ tmp.name = "UNDEFINED";
+ tmp.description = "";
+ tmp.icon = ICON_NONE;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "Node")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+
+ if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "ShaderNode")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+ }
+
+ if (RNA_struct_is_a(ptr->type, &RNA_CompositorNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "CompositorNode")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+ }
+
+ if (RNA_struct_is_a(ptr->type, &RNA_TextureNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "TextureNode")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
}
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
}
+/* ******** Node Tree ******** */
+
static StructRNA *rna_NodeTree_refine(struct PointerRNA *ptr)
{
+ bNodeTree *ntree= (bNodeTree*)ptr->data;
+
+ if (ntree->typeinfo && ntree->typeinfo->ext.srna)
+ return ntree->typeinfo->ext.srna;
+ else
+ return &RNA_NodeTree;
+}
+
+static int rna_NodeTree_poll(const bContext *C, bNodeTreeType *ntreetype)
+{
+ extern FunctionRNA rna_NodeTree_poll_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, ntreetype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_NodeTree_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ ntreetype->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int*)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static void rna_NodeTree_draw_add_menu(const bContext *C, struct uiLayout *layout, bNodeTree *ntree)
+{
+ extern FunctionRNA rna_NodeTree_draw_add_menu_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!ntreeIsValid(ntree))
+ return;
+
+ RNA_id_pointer_create(&ntree->id, &ptr);
+ func = &rna_NodeTree_draw_add_menu_func; /* RNA_struct_find_function(&ptr, "draw_add_menu"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ ntree->typeinfo->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeTree_get_from_context(const bContext *C, bNodeTreeType *ntreetype,
+ bNodeTree **r_ntree, ID **r_id, ID **r_from)
+{
+ extern FunctionRNA rna_NodeTree_get_from_context_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret1, *ret2, *ret3;
+
+ RNA_pointer_create(NULL, ntreetype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_NodeTree_get_from_context_func; /* RNA_struct_find_function(&ptr, "get_from_context"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ ntreetype->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "result_1", &ret1);
+ RNA_parameter_get_lookup(&list, "result_2", &ret2);
+ RNA_parameter_get_lookup(&list, "result_3", &ret3);
+ *r_ntree = *(bNodeTree **)ret1;
+ *r_id = *(ID **)ret2;
+ *r_from = *(ID **)ret3;
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeTree_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeTreeType *nt= RNA_struct_blender_type_get(type);
+
+ if(!nt)
+ return;
+
+ RNA_struct_free_extension(type, &nt->ext);
+
+ ntreeTypeFreeLink(nt);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeTree_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeTreeType *nt, dummynt;
+ bNodeTree dummyntree;
+ PointerRNA dummyptr;
+ int have_function[3];
+
+ /* setup dummy tree & tree type to store static properties in */
+ memset(&dummynt, 0, sizeof(bNodeTreeType));
+ memset(&dummyntree, 0, sizeof(bNodeTree));
+ dummyntree.typeinfo= &dummynt;
+ RNA_pointer_create(NULL, &RNA_NodeTree, &dummyntree, &dummyptr);
+
+ /* validate the python class */
+ if(validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if(strlen(identifier) >= sizeof(dummynt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "registering node tree class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummynt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this tree type before, and remove it */
+ nt= ntreeTypeFind(dummynt.idname);
+ if(nt)
+ rna_NodeTree_unregister(bmain, nt->ext.srna);
+
+ /* create a new node tree type */
+ nt= MEM_callocN(sizeof(bNodeTreeType), "node tree type");
+ memcpy(nt, &dummynt, sizeof(dummynt));
+
+ nt->type = NTREE_CUSTOM;
+
+ nt->ext.srna= RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, &RNA_NodeTree);
+ nt->ext.data= data;
+ nt->ext.call= call;
+ nt->ext.free= free;
+ RNA_struct_blender_type_set(nt->ext.srna, nt);
+
+ RNA_def_struct_ui_text(nt->ext.srna, nt->ui_name, nt->ui_description);
+ RNA_def_struct_ui_icon(nt->ext.srna, nt->ui_icon);
+
+ nt->poll = (have_function[0]) ? rna_NodeTree_poll : NULL;
+ nt->draw_add_menu = (have_function[1]) ? rna_NodeTree_draw_add_menu : NULL;
+ nt->get_from_context = (have_function[2]) ? rna_NodeTree_get_from_context : NULL;
+
+ ntreeTypeAdd(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+
+ /* when using border, make it so no old data from outside of
+ * border is hanging around
+ * ideally shouldn't be in RNA callback, but how to teach
+ * compo to only clear frame when border usage is actually
+ * toggling
+ */
+ if (ntree->flag & NTREE_VIEWER_BORDER) {
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ if (ibuf->rect)
+ memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
+
+ if (ibuf->rect_float)
+ memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports, const char *type)
+{
+ bNodeType *ntype;
+ bNode *node;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ ntype = nodeTypeFind(type);
+ if (!ntype) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s undefined", type);
+ return NULL;
+ }
+
+ if (ntype->poll && !ntype->poll(ntype, ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Cannot add node of type %s to node tree '%s'", type, ntree->id.name+2);
+ return NULL;
+ }
+
+ node = nodeAddNode(C, ntree, type);
+ BLI_assert(node && node->typeinfo);
+
+ /* XXX ugly stuff, should be done with specialized operators (after actual node creation)! */
+ if (ntree->type==NTREE_COMPOSIT) {
+ if(ELEM4(node->type, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE, CMP_NODE_R_LAYERS)) {
+ /* annoying, find the node tree we are in, scene can be NULL */
+ Scene *scene;
+ for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next) {
+ if(scene->nodetree == ntree) {
+ break;
+ }
+ }
+ node->id= (ID *)scene;
+ id_us_plus(node->id);
+ }
+
+ ntreeCompositForceHidden(ntree, CTX_data_scene(C));
+ }
+ else if (ntree->type==NTREE_TEXTURE) {
+ ntreeTexCheckCyclics(ntree);
+ }
+
+ ntreeUpdateTree(ntree);
+ nodeUpdate(ntree, node);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+
+ return node;
+}
+
+static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr)
+{
+ bNode *node = node_ptr->data;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ if (BLI_findindex(&ntree->nodes, node) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name);
+ return;
+ }
+
+ id_us_min(node->id);
+ nodeFreeNode(ntree, node);
+ RNA_POINTER_INVALIDATE(node_ptr);
+
+ ntreeUpdateTree(ntree); /* update group node socket links */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNode *node = ntree->nodes.first;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ while (node) {
+ bNode *next_node = node->next;
+
+ if (node->id)
+ id_us_min(node->id);
+
+ nodeFreeNode(ntree, node);
+
+ node = next_node;
+ }
+
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
+{
bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNode *node = nodeGetActive(ntree);
+ return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
+}
- switch (ntree->type) {
- case NTREE_SHADER:
- return &RNA_ShaderNodeTree;
- case NTREE_COMPOSIT:
- return &RNA_CompositorNodeTree;
- case NTREE_TEXTURE:
- return &RNA_TextureNodeTree;
- default:
- return &RNA_NodeTree;
+static void rna_NodeTree_active_node_set(PointerRNA *ptr, const PointerRNA value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNode *node = (bNode *)value.data;
+
+ /* activating node might require valid typeinfo */
+ if (!ntreeIsValid(ntree))
+ return;
+
+ if (node && BLI_findindex(&ntree->nodes, node) != -1)
+ nodeSetActive(ntree, node);
+ else
+ nodeClearActive(ntree);
+}
+
+static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
+ bNodeSocket *fromsock, bNodeSocket *tosock,
+ int verify_limits)
+{
+ bNodeLink *ret;
+ bNode *fromnode = NULL, *tonode = NULL;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ nodeFindNode(ntree, fromsock, &fromnode, NULL);
+ nodeFindNode(ntree, tosock, &tonode, NULL);
+
+ if (&fromsock->in_out == &tosock->in_out) {
+ BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
+ return NULL;
+ }
+
+ if (verify_limits) {
+ /* remove other socket links if limit is exceeded */
+ if (nodeCountSocketLinks(ntree, fromsock) > fromsock->limit)
+ nodeRemSocketLinks(ntree, fromsock);
+ if (nodeCountSocketLinks(ntree, tosock) > tosock->limit)
+ nodeRemSocketLinks(ntree, tosock);
+ }
+
+ ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
+
+ if (ret) {
+ if (tonode)
+ nodeUpdate(ntree, tonode);
+
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
+ return ret;
}
-static char *rna_Node_path(PointerRNA *ptr)
+static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr)
+{
+ bNodeLink *link = link_ptr->data;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ if (BLI_findindex(&ntree->links, link) == -1) {
+ BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree");
+ return;
+ }
+
+ nodeRemLink(ntree, link);
+ RNA_POINTER_INVALIDATE(link_ptr);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeLink *link = ntree->links.first;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ while (link) {
+ bNodeLink *next_link = link->next;
+
+ nodeRemLink(ntree, link);
+
+ link = next_link;
+ }
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static int rna_NodeTree_active_input_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index)
+ if (gsock->flag & SELECT)
+ return index;
+ return -1;
+}
+
+static void rna_NodeTree_active_input_set(PointerRNA *ptr, int value)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index) {
+ if (index == value)
+ gsock->flag |= SELECT;
+ else
+ gsock->flag &= ~SELECT;
+ }
+ for (gsock = ntree->outputs.first; gsock; gsock = gsock->next) {
+ gsock->flag &= ~SELECT;
+ }
+}
+
+static int rna_NodeTree_active_output_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->outputs.first, index = 0; gsock; gsock = gsock->next, ++index)
+ if (gsock->flag & SELECT)
+ return index;
+ return -1;
+}
+
+static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first; gsock; gsock = gsock->next) {
+ gsock->flag &= ~SELECT;
+ }
+ for (gsock = ntree->outputs.first, index = 0; gsock; gsock = gsock->next, ++index) {
+ if (index == value)
+ gsock->flag |= SELECT;
+ else
+ gsock->flag &= ~SELECT;
+ }
+}
+
+static int rna_NodeTree_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_IN, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static int rna_NodeTree_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_OUT, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
+{
+ bNodeSocket *sock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+
+ return sock;
+}
+
+static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
+{
+ bNodeSocket *sock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+
+ return sock;
+}
+
+static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock)
+{
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ if (BLI_findindex(&ntree->inputs, sock) == -1 && BLI_findindex(&ntree->outputs, sock) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier);
+ }
+ else {
+ ntreeRemoveSocketInterface(ntree, sock);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+}
+
+static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeSocket *sock, *nextsock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ for (sock = ntree->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ ntreeRemoveSocketInterface(ntree, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeSocket *sock, *nextsock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ for (sock = ntree->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ ntreeRemoveSocketInterface(ntree, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C)
+{
+ if (!ntreeIsValid(ntree))
+ return;
+
+ ntree->update |= NTREE_UPDATE_GROUP;
+ ntreeUpdateTree(ntree);
+
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
+}
+
+static void rna_NodeTree_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_idname_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_NodeTree_bl_label_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->ui_name);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_label_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->ui_name);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_NodeTree_bl_description_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->ui_description);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_description_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->ui_description);
+ else
+ return strlen("UNDEFINED");
+}
+
+static int rna_NodeTree_bl_icon_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return ntree->typeinfo->ui_icon;
+ else
+ return ICON_NONE;
+}
+
+
+/* ******** NodeLink ******** */
+
+static int rna_NodeLink_is_hidden_get(PointerRNA *ptr)
+{
+ bNodeLink *link = ptr->data;
+ return nodeLinkIsHidden(link);
+}
+
+
+/* ******** Node ******** */
+
+static StructRNA *rna_Node_refine(struct PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
+
+ if (node->typeinfo && node->typeinfo->ext.srna)
+ return node->typeinfo->ext.srna;
+ else
+ return ptr->type;
+}
+
+static char *rna_Node_path(PointerRNA *ptr)
+{
+ bNode *node = (bNode*)ptr->data;
return BLI_sprintfN("nodes[\"%s\"]", node->name);
}
-static const char *rna_Node_get_node_type(StructRNA *type)
+static int rna_Node_poll(bNodeType *ntype, bNodeTree *ntree)
{
- bNodeType *nodetype = RNA_struct_blender_type_get(type);
- if (nodetype) {
- /* XXX hack: with customnodes branch, nodes will use an identifier string instead of integer ID.
- * Then this can be returned directly instead of doing this ugly include thingy ...
- */
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- if (ID == nodetype->type) { \
- return EnumName; \
- }
-
- #include "rna_nodetree_types.h"
+ extern FunctionRNA rna_Node_poll_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, ntype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_Node_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node_tree", &ntree);
+ ntype->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int*)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static int rna_Node_poll_instance(bNode *node, bNodeTree *ntree)
+{
+ extern FunctionRNA rna_Node_poll_instance_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ if (!node->typeinfo)
+ return FALSE;
+
+ RNA_pointer_create(NULL, node->typeinfo->ext.srna, node, &ptr); /* dummy */
+ func = &rna_Node_poll_instance_func; /* RNA_struct_find_function(&ptr, "poll_instance"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node_tree", &ntree);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int*)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static int rna_Node_poll_instance_default(bNode *node, bNodeTree *ntree)
+{
+ if (!node->typeinfo)
+ return FALSE;
+
+ /* use the basic poll function */
+ return rna_Node_poll(node->typeinfo, ntree);
+}
+
+static void rna_Node_update_reg(bNodeTree *ntree, bNode *node)
+{
+ extern FunctionRNA rna_Node_update_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, node->typeinfo->ext.srna, node, &ptr);
+ func = &rna_Node_update_func; /* RNA_struct_find_function(&ptr, "update"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_init(const bContext *C, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_init_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_init_func; /* RNA_struct_find_function(&ptr, "init"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ node->typeinfo->ext.call((bContext *)C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_copy(PointerRNA *ptr, struct bNode *copynode)
+{
+ extern FunctionRNA rna_Node_copy_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_copy_func; /* RNA_struct_find_function(&ptr, "copy"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &copynode);
+ node->typeinfo->ext.call(NULL, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_free(PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_free_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_free_func; /* RNA_struct_find_function(&ptr, "free"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ node->typeinfo->ext.call(NULL, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_draw_buttons(struct uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_draw_buttons_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_draw_buttons_func; /* RNA_struct_find_function(&ptr, "draw_buttons"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ node->typeinfo->ext.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_draw_buttons_ext(struct uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_draw_buttons_ext_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_draw_buttons_ext_func; /* RNA_struct_find_function(&ptr, "draw_buttons_ext"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ node->typeinfo->ext.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static int rna_Node_is_registered_node_type(StructRNA *type)
+{
+ return (RNA_struct_blender_type_get(type) != NULL);
+}
+
+static void rna_Node_is_registered_node_type_runtime(bContext *UNUSED(C), ReportList *UNUSED(reports), PointerRNA *ptr, ParameterList *parms)
+{
+ int result = (RNA_struct_blender_type_get(ptr->type) != NULL);
+ RNA_parameter_set_lookup(parms, "result", &result);
+}
+
+static void rna_Node_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeType *nt= RNA_struct_blender_type_get(type);
+
+ if(!nt)
+ return;
+
+ RNA_struct_free_extension(type, &nt->ext);
+
+ /* this also frees the allocated nt pointer, no MEM_free call needed! */
+ nodeUnregisterType(nt);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
+
+/* Generic internal registration function.
+ * Can be used to implement callbacks for registerable RNA node subtypes.
+ */
+static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, StructRNA *basetype,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt, dummynt;
+ bNode dummynode;
+ PointerRNA dummyptr;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ int have_function[8];
+
+ /* setup dummy node & node type to store static properties in */
+ memset(&dummynt, 0, sizeof(bNodeType));
+ /* this does some additional initialization of default values */
+ node_type_base_custom(&dummynt, identifier, "", 0, 0);
+
+ memset(&dummynode, 0, sizeof(bNode));
+ dummynode.typeinfo= &dummynt;
+ RNA_pointer_create(NULL, basetype, &dummynode, &dummyptr);
+
+ /* validate the python class */
+ if(validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if(strlen(identifier) >= sizeof(dummynt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "registering node class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummynt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this node type before, and remove it */
+ nt= nodeTypeFind(dummynt.idname);
+ if(nt)
+ rna_Node_unregister(bmain, nt->ext.srna);
+
+ /* create a new node type */
+ nt= MEM_callocN(sizeof(bNodeType), "node type");
+ memcpy(nt, &dummynt, sizeof(dummynt));
+ /* make sure the node type struct is freed on unregister */
+ nt->needs_free = 1;
+
+ nt->ext.srna= RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, basetype);
+ nt->ext.data= data;
+ nt->ext.call= call;
+ nt->ext.free= free;
+ RNA_struct_blender_type_set(nt->ext.srna, nt);
+
+ RNA_def_struct_ui_text(nt->ext.srna, nt->ui_name, nt->ui_description);
+ RNA_def_struct_ui_icon(nt->ext.srna, nt->ui_icon);
+
+ func = RNA_def_function_runtime(nt->ext.srna, "is_registered_node_type", rna_Node_is_registered_node_type_runtime);
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
+ /* XXX bad level call! needed to initialize the basic draw functions ... */
+ ED_init_custom_node_type(nt);
+
+ nt->poll = (have_function[0]) ? rna_Node_poll : NULL;
+ nt->poll_instance = (have_function[1]) ? rna_Node_poll_instance : rna_Node_poll_instance_default;
+ nt->updatefunc = (have_function[2]) ? rna_Node_update_reg : NULL;
+ nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL;
+ nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL;
+ nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL;
+ nt->uifunc = (have_function[6]) ? rna_Node_draw_buttons : NULL;
+ nt->uifuncbut = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
+ /* node buttons are only drawn if the options flag is set */
+ if (nt->uifunc || nt->uifuncbut)
+ nt->flag |= NODE_OPTIONS;
+
+ return nt;
+}
+
+static StructRNA *rna_Node_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_Node, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_NodeGroup_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_NodeGroup, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_ShaderNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_ShaderNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_CompositorNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_CompositorNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_TextureNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_TextureNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
+{
+ bNode *node = ptr->data;
+
+ if (create && !node->prop) {
+ IDPropertyTemplate val = {0};
+ node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties");
}
- return "";
+
+ return node->prop;
}
static void rna_Node_parent_set(PointerRNA *ptr, PointerRNA value)
@@ -330,47 +1576,388 @@ static int rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value)
return TRUE;
}
-static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
+static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void rna_Node_socket_value_update(ID *id, bNode *UNUSED(node), bContext *C)
+{
+ ED_node_tag_update_nodetree(CTX_data_main(C), (bNodeTree *)id);
+}
+
+static void rna_Node_select_set(PointerRNA *ptr, int value)
+{
+ bNode *node= (bNode*)ptr->data;
+ nodeSetSelected(node, value);
+}
+
+static void rna_Node_name_set(PointerRNA *ptr, const char *value)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ bNode *node = (bNode*)ptr->data;
+ char oldname[sizeof(node->name)];
- if (sock->default_value) {
- /* This returns the refined socket type with the full definition
- * of the default input value with type and subtype.
- */
-
- #define SUBTYPE(socktype, stypename, id, idname) \
- { \
- bNodeSocketValue##stypename *value = (bNodeSocketValue##stypename *)sock->default_value; \
- if (value->subtype == PROP_##id) \
- return &RNA_NodeSocket##stypename##idname; \
- }
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, node->name, sizeof(node->name));
+ /* set new name */
+ BLI_strncpy_utf8(node->name, value, sizeof(node->name));
+
+ nodeUniqueName(ntree, node);
+
+ /* fix all the animation data which may link to this */
+ BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
+}
+
+static int rna_Node_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static int rna_Node_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_OUT, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, SOCK_IN, type, identifier, name);
+
+ if (sock == NULL) {
+ BKE_report(reports, RPT_ERROR, "Unable to create socket");
+ }
+ else {
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+
+ return sock;
+}
+
+static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, SOCK_OUT, type, identifier, name);
+
+ if (sock == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to create socket");
+ }
+ else {
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+
+ return sock;
+}
+
+static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNodeSocket *sock)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ if (BLI_findindex(&node->inputs, sock) == -1 && BLI_findindex(&node->outputs, sock) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier);
+ }
+ else {
+ nodeRemoveSocket(ntree, node, sock);
- switch (sock->type) {
- case SOCK_FLOAT:
- NODE_DEFINE_SUBTYPES_FLOAT
- break;
- case SOCK_INT:
- NODE_DEFINE_SUBTYPES_INT
- break;
- case SOCK_BOOLEAN:
- return &RNA_NodeSocketBoolean;
- case SOCK_VECTOR:
- NODE_DEFINE_SUBTYPES_VECTOR
- break;
- case SOCK_STRING:
- NODE_DEFINE_SUBTYPES_STRING
- break;
- case SOCK_RGBA:
- return &RNA_NodeSocketRGBA;
- case SOCK_SHADER:
- return &RNA_NodeSocketShader;
- }
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+}
+
+static void rna_Node_inputs_clear(ID *id, bNode *node, ReportList *reports)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock, *nextsock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ for (sock = node->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_Node_outputs_clear(ID *id, bNode *node, ReportList *reports)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock, *nextsock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ for (sock = node->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_Node_width_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo) {
+ *min = *softmin = node->typeinfo->minwidth;
+ *max = *softmax = node->typeinfo->maxwidth;
+ }
+ else {
+ *min = *softmin = 0.0f;
+ *max = *softmax = 0.0f;
+ }
+}
+
+static void rna_Node_height_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo) {
+ *min = *softmin = node->typeinfo->minheight;
+ *max = *softmax = node->typeinfo->maxheight;
+ }
+ else {
+ *min = *softmin = 0.0f;
+ *max = *softmax = 0.0f;
+ }
+}
+
+static void rna_Node_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNode *node= ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_Node_bl_idname_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_Node_bl_label_get(PointerRNA *ptr, char *value)
+{
+ bNode *node= ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->ui_name);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_Node_bl_label_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->ui_name);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_Node_bl_description_get(PointerRNA *ptr, char *value)
+{
+ bNode *node= ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->ui_description);
+ else
+ strcpy(value, "");
+}
+static int rna_Node_bl_description_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->ui_description);
+ else
+ return strlen("");
+}
+
+static int rna_Node_bl_icon_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return node->typeinfo->ui_icon;
+ else
+ return ICON_NONE;
+}
+
+static int rna_Node_bl_static_type_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return node->typeinfo->type;
+ else
+ return NODE_UNDEFINED;
+}
+
+
+/* ******** Node Socket ******** */
+
+static void rna_NodeSocket_draw(bContext *C, struct uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
+{
+ extern FunctionRNA rna_NodeSocket_draw_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocket_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ RNA_parameter_set_lookup(&list, "node", node_ptr);
+ sock->typeinfo->ext_socket.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocket_draw_color(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color)
+{
+ extern FunctionRNA rna_NodeSocket_draw_color_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocket_draw_color_func; /* RNA_struct_find_function(&ptr, "draw_color"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "node", node_ptr);
+ sock->typeinfo->ext_socket.call(C, ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "color", &ret);
+ copy_v4_v4(r_color, (float *)ret);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeSocketType *st= RNA_struct_blender_type_get(type);
+ if(!st)
+ return;
+
+ RNA_struct_free_extension(type, &st->ext_socket);
+
+ nodeUnregisterSocketType(st);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeSocket_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeSocketType *st, dummyst;
+ bNodeSocket dummysock;
+ PointerRNA dummyptr;
+ int have_function[2];
+
+ /* setup dummy socket & socket type to store static properties in */
+ memset(&dummyst, 0, sizeof(bNodeSocketType));
+
+ memset(&dummysock, 0, sizeof(bNodeSocket));
+ dummysock.typeinfo= &dummyst;
+ RNA_pointer_create(NULL, &RNA_NodeSocket, &dummysock, &dummyptr);
+
+ /* validate the python class */
+ if(validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if(strlen(identifier) >= sizeof(dummyst.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "registering node socket class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyst.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this socket type before */
+ st= nodeSocketTypeFind(dummyst.idname);
+ if (!st) {
+ /* create a new node socket type */
+ st= MEM_callocN(sizeof(bNodeSocketType), "node socket type");
+ memcpy(st, &dummyst, sizeof(dummyst));
- #undef SUBTYPE
+ nodeRegisterSocketType(st);
+ }
+
+ /* if RNA type is already registered, unregister first */
+ if (st->ext_socket.srna) {
+ StructRNA *srna = st->ext_socket.srna;
+ RNA_struct_free_extension(srna, &st->ext_socket);
+ RNA_struct_free(&BLENDER_RNA, srna);
}
+ st->ext_socket.srna= RNA_def_struct_ptr(&BLENDER_RNA, st->idname, &RNA_NodeSocket);
+ st->ext_socket.data= data;
+ st->ext_socket.call= call;
+ st->ext_socket.free= free;
+ RNA_struct_blender_type_set(st->ext_socket.srna, st);
- return &RNA_NodeSocket;
+ /* XXX bad level call! needed to initialize the basic draw functions ... */
+ ED_init_custom_node_socket_type(st);
+
+ st->draw = (have_function[0]) ? rna_NodeSocket_draw : NULL;
+ st->draw_color = (have_function[1]) ? rna_NodeSocket_draw_color : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return st->ext_socket.srna;
+}
+
+static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
+{
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+
+ if (sock->typeinfo && sock->typeinfo->ext_socket.srna)
+ return sock->typeinfo->ext_socket.srna;
+ else
+ return &RNA_NodeSocket;
}
static char *rna_NodeSocket_path(PointerRNA *ptr)
@@ -380,29 +1967,65 @@ static char *rna_NodeSocket_path(PointerRNA *ptr)
bNode *node;
int socketindex;
- /* group sockets */
- socketindex = BLI_findindex(&ntree->inputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("inputs[%d]", socketindex);
-
- socketindex = BLI_findindex(&ntree->outputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("outputs[%d]", socketindex);
-
- /* node sockets */
- if (!nodeFindNode(ntree, sock, &node, NULL, NULL)) return NULL;
+ if (!nodeFindNode(ntree, sock, &node, &socketindex))
+ return NULL;
- socketindex = BLI_findindex(&node->inputs, sock);
- if (socketindex != -1)
+ if (sock->in_out == SOCK_IN)
return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", node->name, socketindex);
-
- socketindex = BLI_findindex(&node->outputs, sock);
- if (socketindex != -1)
+ else
return BLI_sprintfN("nodes[\"%s\"].outputs[%d]", node->name, socketindex);
return NULL;
}
+static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create)
+{
+ bNodeSocket *sock = ptr->data;
+
+ if (create && !sock->prop) {
+ IDPropertyTemplate val = {0};
+ sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties");
+ }
+
+ return sock->prop;
+}
+
+static void rna_NodeSocket_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNodeSocket *sock = ptr->data;
+ if (sock->typeinfo)
+ strcpy(value, sock->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeSocket_bl_idname_length(PointerRNA *ptr)
+{
+ bNodeSocket *sock = ptr->data;
+ if (sock->typeinfo)
+ return strlen(sock->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ bNode *node;
+ PointerRNA r_ptr;
+
+ nodeFindNode(ntree, sock, &node, NULL);
+
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &r_ptr);
+ return r_ptr;
+}
+
+static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value)
{
bNodeSocket *sock = (bNodeSocket *)ptr->data;
@@ -417,151 +2040,334 @@ static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value)
sock->flag &= ~SOCK_HIDDEN;
}
-/* Button Set Funcs for Matte Nodes */
-static void rna_Matte_t1_set(PointerRNA *ptr, float value)
+
+static void rna_NodeSocketInterface_draw(bContext *C, struct uiLayout *layout, PointerRNA *ptr)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
-
- chroma->t1 = value;
-
- if (value < chroma->t2)
- chroma->t2 = value;
+ extern FunctionRNA rna_NodeSocketInterface_draw_func;
+
+ bNodeSocket *stemp = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ func = &rna_NodeSocketInterface_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ stemp->typeinfo->ext_interface.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_Matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_draw_color(bContext *C, PointerRNA *ptr, float *r_color)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
-
- if (value > chroma->t1)
- value = chroma->t1;
-
- chroma->t2 = value;
+ extern FunctionRNA rna_NodeSocketInterface_draw_color_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocketInterface_draw_color_func; /* RNA_struct_find_function(&ptr, "draw_color"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ sock->typeinfo->ext_interface.call(C, ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "color", &ret);
+ copy_v4_v4(r_color, (float *)ret);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_distance_matte_t1_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_register_properties(bNodeTree *ntree, bNodeSocket *stemp, StructRNA *data_srna)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ extern FunctionRNA rna_NodeSocketInterface_register_properties_func;
- chroma->t1 = value;
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ func = &rna_NodeSocketInterface_register_properties_func; /* RNA_struct_find_function(&ptr, "register_properties"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "data_rna_type", &data_srna);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_distance_matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_init_socket(bNodeTree *ntree, bNodeSocket *stemp, bNode *node, bNodeSocket *sock, const char *data_path)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ extern FunctionRNA rna_NodeSocketInterface_init_socket_func;
- chroma->t2 = value;
+ PointerRNA ptr, node_ptr, sock_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
+ func = &rna_NodeSocketInterface_init_socket_func; /* RNA_struct_find_function(&ptr, "init_socket"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &node_ptr);
+ RNA_parameter_set_lookup(&list, "socket", &sock_ptr);
+ RNA_parameter_set_lookup(&list, "data_path", &data_path);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_difference_matte_t1_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_from_socket(bNodeTree *ntree, bNodeSocket *stemp, bNode *node, bNodeSocket *sock)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ extern FunctionRNA rna_NodeSocketInterface_from_socket_func;
- chroma->t1 = value;
+ PointerRNA ptr, node_ptr, sock_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
+ func = &rna_NodeSocketInterface_from_socket_func; /* RNA_struct_find_function(&ptr, "from_socket"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &node_ptr);
+ RNA_parameter_set_lookup(&list, "socket", &sock_ptr);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_difference_matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_unregister(Main *UNUSED(bmain), StructRNA *type)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ bNodeSocketType *st= RNA_struct_blender_type_get(type);
+ if(!st)
+ return;
+
+ RNA_struct_free_extension(type, &st->ext_interface);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
- chroma->t2 = value;
+static StructRNA *rna_NodeSocketInterface_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeSocketType *st, dummyst;
+ bNodeSocket dummysock;
+ PointerRNA dummyptr;
+ int have_function[5];
+
+ /* setup dummy socket & socket type to store static properties in */
+ memset(&dummyst, 0, sizeof(bNodeSocketType));
+
+ memset(&dummysock, 0, sizeof(bNodeSocket));
+ dummysock.typeinfo= &dummyst;
+ RNA_pointer_create(NULL, &RNA_NodeSocketInterface, &dummysock, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ /* check if we have registered this socket type before */
+ st= nodeSocketTypeFind(dummyst.idname);
+ if (st) {
+ /* basic socket type registered by a socket class before. */
+ }
+ else {
+ /* create a new node socket type */
+ st= MEM_callocN(sizeof(bNodeSocketType), "node socket type");
+ memcpy(st, &dummyst, sizeof(dummyst));
+
+ nodeRegisterSocketType(st);
+ }
+
+ /* if RNA type is already registered, unregister first */
+ if (st->ext_interface.srna) {
+ StructRNA *srna = st->ext_interface.srna;
+ RNA_struct_free_extension(srna, &st->ext_interface);
+ RNA_struct_free(&BLENDER_RNA, srna);
+ }
+ st->ext_interface.srna= RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_NodeSocketInterface);
+ st->ext_interface.data= data;
+ st->ext_interface.call= call;
+ st->ext_interface.free= free;
+ RNA_struct_blender_type_set(st->ext_interface.srna, st);
+
+ st->interface_draw = (have_function[0]) ? rna_NodeSocketInterface_draw : NULL;
+ st->interface_draw_color = (have_function[1]) ? rna_NodeSocketInterface_draw_color : NULL;
+ st->interface_register_properties = (have_function[2]) ? rna_NodeSocketInterface_register_properties : NULL;
+ st->interface_init_socket = (have_function[3]) ? rna_NodeSocketInterface_init_socket : NULL;
+ st->interface_from_socket = (have_function[4]) ? rna_NodeSocketInterface_from_socket : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return st->ext_interface.srna;
}
+static StructRNA *rna_NodeSocketInterface_refine(PointerRNA *ptr)
+{
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+
+ if (sock->typeinfo && sock->typeinfo->ext_interface.srna)
+ return sock->typeinfo->ext_interface.srna;
+ else
+ return &RNA_NodeSocketInterface;
+}
-static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
+static char *rna_NodeSocketInterface_path(PointerRNA *ptr)
{
- bNode *node = (bNode *)ptr->data;
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ int socketindex;
+
+ socketindex = BLI_findindex(&ntree->inputs, sock);
+ if (socketindex != -1)
+ return BLI_sprintfN("inputs[%d]", socketindex);
+
+ socketindex = BLI_findindex(&ntree->outputs, sock);
+ if (socketindex != -1)
+ return BLI_sprintfN("outputs[%d]", socketindex);
+
+ return NULL;
+}
- if (node->id) {
- id_us_min(node->id);
- node->id = NULL;
+static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create)
+{
+ bNodeSocket *sock = ptr->data;
+
+ if (create && !sock->prop) {
+ IDPropertyTemplate val = {0};
+ sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties");
}
+
+ return sock->prop;
+}
- node->id = value.data;
-
- id_us_plus(node->id);
+static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *stemp = ptr->data;
+
+ if (!stemp->typeinfo)
+ return;
+
+ ntree->update |= NTREE_UPDATE_GROUP;
+ ntreeUpdateTree(ntree);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
}
+/* ******** Standard Node Socket Base Types ******** */
-static void node_update(Main *bmain, Scene *UNUSED(scene), bNodeTree *ntree, bNode *node)
+static void rna_NodeSocketStandard_draw(ID *id, bNodeSocket *sock, struct bContext *C, struct uiLayout *layout, PointerRNA *nodeptr)
{
- ED_node_generic_update(bmain, ntree, node);
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->draw(C, layout, &ptr, nodeptr);
}
-static void rna_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeSocketStandard_draw_color(ID *id, bNodeSocket *sock, struct bContext *C, PointerRNA *nodeptr, float *r_color)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
-
- node_update(bmain, scene, ntree, node);
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->draw_color(C, &ptr, nodeptr, r_color);
}
-static void rna_Node_tex_image_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeSocketInterfaceStandard_draw(ID *id, bNodeSocket *sock, struct bContext *C, struct uiLayout *layout)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->interface_draw(C, layout, &ptr);
+}
- node_update(bmain, scene, ntree, node);
- WM_main_add_notifier(NC_IMAGE, NULL);
+static void rna_NodeSocketInterfaceStandard_draw_color(ID *id, bNodeSocket *sock, struct bContext *C, float *r_color)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->interface_draw_color(C, &ptr, r_color);
}
-static void rna_Node_material_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+/* using a context update function here, to avoid searching the node if possible */
+static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
+ bNode *node;
+
+ /* default update */
+ rna_NodeSocket_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+
+ /* try to use node from context, faster */
+ node = CTX_data_pointer_get(C, "node").data;
+ if (!node) {
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+
+ /* fall back to searching node in the tree */
+ nodeFindNode(ntree, sock, &node, NULL);
+ }
+
+ if (node)
+ nodeSynchronizeID(node, true);
+}
- if (node->id)
- nodeSetActive(ntree, node);
- node_update(bmain, scene, ntree, node);
+/* ******** Node Types ******** */
+
+static void rna_CompositorNode_tag_need_exec(bNode *node)
+{
+ node->need_exec = TRUE;
}
-static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- /* when using border, make it so no old data from outside of
- * border is hanging around
- * ideally shouldn't be in RNA callback, but how to teach
- * compo to only clear frame when border usage is actually
- * toggling
- */
- if (ntree->flag & NTREE_VIEWER_BORDER) {
- Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
- void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
-
- if (ibuf) {
- if (ibuf->rect)
- memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
-
- if (ibuf->rect_float)
- memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
+ ED_node_tag_update_nodetree(bmain, ntree);
+ WM_main_add_notifier(NC_IMAGE, NULL);
+}
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- }
+static void rna_Node_material_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
- BKE_image_release_ibuf(ima, ibuf, lock);
- }
+ if (node->id)
+ nodeSetActive(ntree, node);
- WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
- WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
-static void rna_NodeGroup_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNode *node = (bNode *)ptr->data;
- ntreeUpdateTree((bNodeTree *)node->id);
+ if (node->id)
+ ntreeUpdateTree((bNodeTree *)node->id);
- node_update(bmain, scene, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
@@ -573,91 +2379,99 @@ static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
return (ngroup->type == ntree->type);
}
-static void rna_Node_name_set(PointerRNA *ptr, const char *value)
+
+static StructRNA *rna_NodeGroup_interface_typef(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
- char oldname[sizeof(node->name)];
-
- /* make a copy of the old name first */
- BLI_strncpy(oldname, node->name, sizeof(node->name));
- /* set new name */
- BLI_strncpy_utf8(node->name, value, sizeof(node->name));
-
- nodeUniqueName(ntree, node);
-
- /* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
+ bNode *node = ptr->data;
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+
+ if (ngroup) {
+ StructRNA *srna = ntreeInterfaceTypeGet(ngroup, TRUE);
+ if (srna)
+ return srna;
+ }
+ return &RNA_PropertyGroup;
}
-static void rna_Node_width_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static StructRNA *rna_NodeGroupInputOutput_interface_typef(PointerRNA *ptr)
{
- bNode *node = ptr->data;
- *min = *softmin = node->typeinfo->minwidth;
- *max = *softmax = node->typeinfo->maxwidth;
+ bNodeTree *ntree = ptr->id.data;
+
+ if (ntree) {
+ StructRNA *srna = ntreeInterfaceTypeGet(ntree, TRUE);
+ if (srna)
+ return srna;
+ }
+ return &RNA_PropertyGroup;
}
-static void rna_Node_height_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_distance_matte_t1_set(PointerRNA *ptr, float value)
{
- bNode *node = ptr->data;
- *min = *softmin = node->typeinfo->minheight;
- *max = *softmax = node->typeinfo->maxheight;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
}
-static void rna_NodeSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_distance_matte_t2_set(PointerRNA *ptr, float value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNode *node;
-
- if (nodeFindNode(ntree, sock, &node, NULL, NULL))
- node_update(bmain, scene, ntree, node);
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t2 = value;
}
-static void rna_NodeGroupSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_difference_matte_t1_set(PointerRNA *ptr, float value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNode *node;
-
- ntreeUpdateTree(ntree);
-
- if (nodeFindNode(ntree, sock, &node, NULL, NULL))
- node_update(bmain, scene, ntree, node);
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
}
-#if 0 /* UNUSED */
-static void rna_NodeLink_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_difference_matte_t2_set(PointerRNA *ptr, float value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
- ntree->update |= NTREE_UPDATE_LINKS;
- ntreeUpdateTree(ntree);
+ chroma->t2 = value;
}
-#endif
-static void rna_NodeSocketInt_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+/* Button Set Funcs for Matte Nodes */
+static void rna_Matte_t1_set(PointerRNA *ptr, float value)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueInt *val = (bNodeSocketValueInt *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
+
+ if (value < chroma->t2)
+ chroma->t2 = value;
}
-static void rna_NodeSocketFloat_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_Matte_t2_set(PointerRNA *ptr, float value)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ if (value > chroma->t1)
+ value = chroma->t1;
+
+ chroma->t2 = value;
}
-static void rna_NodeSocketVector_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueVector *val = (bNodeSocketValueVector *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ bNode *node = (bNode *)ptr->data;
+
+ if (node->id) {
+ id_us_min(node->id);
+ node->id = NULL;
+ }
+
+ node->id = value.data;
+
+ id_us_plus(node->id);
}
static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -741,35 +2555,35 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
switch (node->custom1) {
case CMP_NODE_CHANNEL_MATTE_CS_RGB:
- tmp.identifier = "R"; tmp.name = "R"; tmp.value = 1;
+ tmp.identifier = "R"; tmp.name= "R"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "G"; tmp.name = "G"; tmp.value = 2;
+ tmp.identifier = "G"; tmp.name= "G"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "B"; tmp.name = "B"; tmp.value = 3;
+ tmp.identifier = "B"; tmp.name= "B"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
case CMP_NODE_CHANNEL_MATTE_CS_HSV:
- tmp.identifier = "H"; tmp.name = "H"; tmp.value = 1;
+ tmp.identifier = "H"; tmp.name= "H"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "S"; tmp.name = "S"; tmp.value = 2;
+ tmp.identifier = "S"; tmp.name= "S"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "V"; tmp.name = "V"; tmp.value = 3;
+ tmp.identifier = "V"; tmp.name= "V"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
case CMP_NODE_CHANNEL_MATTE_CS_YUV:
- tmp.identifier = "Y"; tmp.name = "Y"; tmp.value = 1;
+ tmp.identifier = "Y"; tmp.name= "Y"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "G"; tmp.name = "U"; tmp.value = 2;
+ tmp.identifier = "G"; tmp.name= "U"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "V"; tmp.name = "V"; tmp.value = 3;
+ tmp.identifier = "V"; tmp.name= "V"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
case CMP_NODE_CHANNEL_MATTE_CS_YCC:
- tmp.identifier = "Y"; tmp.name = "Y"; tmp.value = 1;
+ tmp.identifier = "Y"; tmp.name= "Y"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "CB"; tmp.name = "Cr"; tmp.value = 2;
+ tmp.identifier = "CB"; tmp.name= "Cr"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "CR"; tmp.name = "Cb"; tmp.value = 3;
+ tmp.identifier = "CR"; tmp.name= "Cb"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
default:
@@ -782,274 +2596,13 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
return item;
}
-static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNode *node = nodeGetActive(ntree);
- return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
-}
-
-static void rna_NodeTree_active_node_set(PointerRNA *ptr, PointerRNA value)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNode *node = (bNode *)value.data;
- if (node && BLI_findindex(&ntree->nodes, node) != -1)
- nodeSetActive(ntree, node);
- else
- nodeClearActive(ntree);
-}
-
-static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- bNode *node;
- bNodeTemplate ntemp;
-
- if (type == NODE_GROUP && group == NULL) {
- BKE_report(reports, RPT_ERROR, "Node type 'GROUP' missing group argument");
- return NULL;
- }
-
- ntemp.type = type;
- ntemp.ngroup = group;
- ntemp.scene = CTX_data_scene(C);
- ntemp.main = CTX_data_main(C);
- node = nodeAddNode(ntree, &ntemp);
-
- if (node == NULL) {
- BKE_report(reports, RPT_ERROR, "Unable to create node");
- }
- else {
- ntreeUpdateTree(ntree); /* update group node socket links*/
- nodeUpdate(ntree, node);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-
- if (group)
- id_us_plus(&group->id);
- }
-
- return node;
-}
-
-static bNode *rna_NodeTree_node_composite_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- /* raises error on failure */
- bNode *node = rna_NodeTree_node_new(ntree, C, reports, type, group);
-
- if (node) {
- if (ELEM4(node->type, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE, CMP_NODE_R_LAYERS)) {
- /* annoying, find the node tree we are in, scene can be NULL */
- Scene *scene;
- for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) {
- if (scene->nodetree == ntree) {
- break;
- }
- }
- node->id = (ID *)scene;
- id_us_plus(node->id);
- }
-
- ntreeCompositForceHidden(ntree, CTX_data_scene(C));
- ntreeUpdateTree(ntree);
- }
-
- return node;
-}
-
-static bNode *rna_NodeTree_node_texture_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- /* raises error on failure */
- bNode *node = rna_NodeTree_node_new(ntree, C, reports, type, group);
-
- if (node) {
- ntreeTexCheckCyclics(ntree);
- }
-
- return node;
-}
-
-static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr)
-{
- bNode *node = node_ptr->data;
- if (BLI_findindex(&ntree->nodes, node) == -1) {
- BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name);
- return;
- }
-
- id_us_min(node->id);
- nodeFreeNode(ntree, node);
- RNA_POINTER_INVALIDATE(node_ptr);
-
- ntreeUpdateTree(ntree); /* update group node socket links */
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static void rna_NodeTree_node_clear(bNodeTree *ntree)
-{
- bNode *node = ntree->nodes.first;
-
- while (node) {
- bNode *next_node = node->next;
-
- if (node->id)
- id_us_min(node->id);
-
- nodeFreeNode(ntree, node);
-
- node = next_node;
- }
-
- ntreeUpdateTree(ntree); /* update group node socket links*/
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
- bNodeSocket *fromsock, bNodeSocket *tosock)
-{
- bNodeLink *ret;
- bNode *fromnode = NULL, *tonode = NULL;
- int from_in_out, to_in_out;
-
- nodeFindNode(ntree, fromsock, &fromnode, NULL, &from_in_out);
- nodeFindNode(ntree, tosock, &tonode, NULL, &to_in_out);
-
- if (&from_in_out == &to_in_out) {
- BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
- return NULL;
- }
-
- /* unlink node input socket */
- if (to_in_out == SOCK_IN)
- nodeRemSocketLinks(ntree, tosock);
- else
- nodeRemSocketLinks(ntree, fromsock);
-
- ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
-
- if (ret) {
- if (tonode)
- nodeUpdate(ntree, tonode);
-
- ntreeUpdateTree(ntree);
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- }
-
- return ret;
-}
-
-static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr)
-{
- bNodeLink *link = link_ptr->data;
- if (BLI_findindex(&ntree->links, link) == -1) {
- BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree");
- return;
- }
-
- nodeRemLink(ntree, link);
- RNA_POINTER_INVALIDATE(link_ptr);
-
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static void rna_NodeTree_link_clear(bNodeTree *ntree)
-{
- bNodeLink *link = ntree->links.first;
-
- while (link) {
- bNodeLink *next_link = link->next;
-
- nodeRemLink(ntree, link);
-
- link = next_link;
- }
- ntreeUpdateTree(ntree);
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static bNodeSocket *rna_NodeTree_input_new(bNodeTree *ntree, ReportList *UNUSED(reports), const char *name, int type)
-{
- /* XXX should check if tree is a group here! no good way to do this currently. */
- bNodeSocket *gsock = node_group_add_socket(ntree, name, type, SOCK_IN);
-
- ntree->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
-}
-
-static bNodeSocket *rna_NodeTree_output_new(bNodeTree *ntree, ReportList *UNUSED(reports), const char *name, int type)
-{
- /* XXX should check if tree is a group here! no good way to do this currently. */
- bNodeSocket *gsock = node_group_add_socket(ntree, name, type, SOCK_OUT);
-
- ntree->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
-}
-
-static bNodeSocket *rna_NodeTree_input_expose(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock, int add_link)
-{
- bNode *node;
- bNodeSocket *gsock;
- int index, in_out;
-
- if (!nodeFindNode(ntree, sock, &node, &index, &in_out))
- BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree");
- else if (in_out != SOCK_IN)
- BKE_report(reports, RPT_ERROR, "Socket is not an input");
- else {
- /* XXX should check if tree is a group here! no good way to do this currently. */
- gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_IN);
- if (add_link)
- nodeAddLink(ntree, NULL, gsock, node, sock);
-
- ntree->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
- }
- return NULL;
-}
-
-static bNodeSocket *rna_NodeTree_output_expose(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock, int add_link)
-{
- bNode *node;
- bNodeSocket *gsock;
- int index, in_out;
-
- if (!nodeFindNode(ntree, sock, &node, &index, &in_out))
- BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree");
- else if (in_out != SOCK_OUT)
- BKE_report(reports, RPT_ERROR, "Socket is not an output");
- else {
- /* XXX should check if tree is a group here! no good way to do this currently. */
- gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_OUT);
- if (add_link)
- nodeAddLink(ntree, node, sock, NULL, gsock);
-
- ntree->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
- }
- return NULL;
-}
-
-static void rna_Image_Node_update_id(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNode *node = (bNode *)ptr->data;
node->update |= NODE_UPDATE_ID;
- node_update(bmain, scene, ntree, node);
- node->update &= ~NODE_UPDATE_ID;
+ nodeUpdate(ntree, node); /* to update image node sockets */
}
static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -1073,6 +2626,8 @@ static PointerRNA rna_NodeOutputFile_slot_file_get(CollectionPropertyIterator *i
return ptr;
}
+/* ******** Node Socket Types ******** */
+
static PointerRNA rna_NodeOutputFile_slot_layer_get(CollectionPropertyIterator *iter)
{
PointerRNA ptr;
@@ -1126,53 +2681,6 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va
}
}
-static bNodeSocket *rna_ShaderNodeScript_find_socket(bNode *node, const char *name, int is_output)
-{
- bNodeSocket *sock;
-
- if (is_output) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, name) == 0) {
- return sock;
- }
- }
- }
- else {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, name) == 0) {
- return sock;
- }
- }
- }
-
- return NULL;
-}
-
-static void rna_ShaderNodeScript_remove_socket(ID *id, bNode *node, bNodeSocket *sock)
-{
- bNodeTree *ntree = (bNodeTree *)id;
-
- nodeRemoveSocket(ntree, node, sock);
-
- ED_node_generic_update(G.main, ntree, node);
-}
-
-static bNodeSocket *rna_ShaderNodeScript_add_socket(ID *id, bNode *node, const char *name, int type, int is_output)
-{
- bNodeTree *ntree = (bNodeTree *)id;
- bNodeSocket *sock;
-
- /* replace existing socket with the same name, to keep it unique */
- sock = rna_ShaderNodeScript_find_socket(node, name, is_output);
- if (sock)
- nodeRemoveSocket(ntree, node, sock);
- sock = nodeAddSocket(ntree, node, (is_output ? SOCK_OUT : SOCK_IN), name, type);
-
- ED_node_generic_update(G.main, ntree, node);
-
- return sock;
-}
-
static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
{
bNode *node = (bNode *)ptr->data;
@@ -1236,19 +2744,6 @@ static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value
nss->bytecode = NULL;
}
-static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, bool create)
-{
- bNode *node = (bNode *)ptr->data;
- NodeShaderScript *nss = node->storage;
-
- if (create && !nss->prop) {
- IDPropertyTemplate val = {0};
- nss->prop = IDP_New(IDP_GROUP, &val, "RNA_ShaderNodeScript ID properties");
- }
-
- return nss->prop;
-}
-
static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -1262,7 +2757,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
RE_engine_free(engine);
}
- node_update(bmain, scene, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
#else
@@ -1311,139 +2806,36 @@ static EnumPropertyItem node_script_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
-#define MaxNodes 50000
-
-enum
-{
- Category_GroupNode,
- Category_LayoutNode,
- Category_ShaderNode,
- Category_CompositorNode,
- Category_TextureNode,
-};
-
-typedef struct NodeInfo {
- int defined;
- int category;
- const char *enum_name;
- const char *struct_name;
- const char *base_name;
- int icon;
- const char *ui_name;
- const char *ui_desc;
-} NodeInfo;
-
-static NodeInfo nodes[MaxNodes];
-
-static void reg_node(int ID, int category, const char *enum_name, const char *struct_name,
- const char *base_name, const char *ui_name, const char *ui_desc)
-{
- NodeInfo *ni = nodes + ID;
-
- ni->defined = 1;
- ni->category = category;
- ni->enum_name = enum_name;
- ni->struct_name = struct_name;
- ni->base_name = base_name;
- ni->ui_name = ui_name;
- ni->ui_desc = ui_desc;
-}
-
-static void init(void)
-{
- memset(nodes, 0, sizeof(nodes));
-
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- reg_node(ID, Category_##Category, EnumName, STRINGIFY_ARG(Category##StructName), #Category, UIName, UIDesc);
-
- #include "rna_nodetree_types.h"
-
- reg_node(NODE_GROUP, Category_GroupNode, "GROUP", "NodeGroup", "SpecialNode", "Group", "");
- reg_node(NODE_FRAME, Category_LayoutNode, "FRAME", "NodeFrame", "SpecialNode", "Frame", "");
- reg_node(NODE_REROUTE, Category_LayoutNode, "REROUTE", "NodeReroute", "SpecialNode", "Reroute", "");
-}
+/* -- Common nodes ---------------------------------------------------------- */
-static StructRNA *def_node(BlenderRNA *brna, int node_id)
+static void def_group_input(StructRNA *srna)
{
- StructRNA *srna;
- FunctionRNA *func;
- PropertyRNA *parm;
- NodeInfo *node = nodes + node_id;
-
- srna = RNA_def_struct(brna, node->struct_name, node->base_name);
- RNA_def_struct_ui_text(srna, node->ui_name, node->ui_desc);
- RNA_def_struct_sdna(srna, "bNode");
-
- func = RNA_def_function(srna, "get_node_type", "rna_Node_get_node_type");
- RNA_def_function_ui_description(func, "Get the identifier of the node type");
- RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
- parm = RNA_def_string(func, "result", "", 0, "Result", "");
- RNA_def_function_return(func, parm);
+ PropertyRNA *prop;
- return srna;
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
}
-static void alloc_node_type_items(EnumPropertyItem *items, int category)
+static void def_group_output(StructRNA *srna)
{
- int i;
- int count = 4;
- EnumPropertyItem *item = items;
-
- for (i = 0; i < MaxNodes; i++)
- if (nodes[i].defined && nodes[i].category == category)
- count++;
-
- /*item = items = MEM_callocN(count * sizeof(EnumPropertyItem), "alloc_node_type_items");*/
-
- for (i = 0; i < MaxNodes; i++) {
- NodeInfo *node = nodes + i;
- if (node->defined && node->category == category) {
- item->value = i;
- item->identifier = node->enum_name;
- item->icon = node->icon;
- item->name = node->ui_name;
- item->description = node->ui_desc;
-
- item++;
- }
- }
-
- item->value = NODE_GROUP;
- item->identifier = "GROUP";
- item->icon = 0;
- item->name = "Group";
- item->description = "";
-
- item++;
-
- item->value = NODE_REROUTE;
- item->identifier = "REROUTE";
- item->icon = 0;
- item->name = "Reroute";
- item->description = "";
-
- item++;
-
- item->value = NODE_FRAME;
- item->identifier = "FRAME";
- item->icon = 0;
- item->name = "Frame";
- item->description = "";
-
- item++;
-
- /* NOTE!, increase 'count' when adding items here */
+ PropertyRNA *prop;
- memset(item, 0, sizeof(EnumPropertyItem));
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
}
-
-/* -- Common nodes ---------------------------------------------------------- */
-
static void def_group(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_def_struct_register_funcs(srna, "rna_NodeGroup_register", "rna_Node_unregister", NULL);
+
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "NodeTree");
@@ -1451,6 +2843,18 @@ static void def_group(StructRNA *srna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Node Tree", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update");
+
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroup_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_group_tree_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->group_tree_idname");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "Group Tree Type", "");
}
static void def_frame(StructRNA *srna)
@@ -2062,8 +3466,7 @@ static void def_sh_tangent(StructRNA *srna)
static void def_sh_script(StructRNA *srna)
{
- FunctionRNA *func;
- PropertyRNA *prop, *parm;
+ PropertyRNA *prop;
prop = RNA_def_property(srna, "script", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
@@ -2073,7 +3476,6 @@ static void def_sh_script(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update");
RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage");
- RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops");
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_ui_text(prop, "File Path", "Shader script path");
@@ -2104,7 +3506,8 @@ static void def_sh_script(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
/* API functions */
-
+
+#if 0 /* XXX TODO use general node api for this */
func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket");
RNA_def_function_ui_description(func, "Find a socket by name");
parm = RNA_def_string(func, "name", "", 0, "Socket name", "");
@@ -2129,6 +3532,7 @@ static void def_sh_script(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
parm = RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+#endif
}
/* -- Compositor Nodes ------------------------------------------------------ */
@@ -4382,390 +5786,571 @@ static void def_tex_bricks(StructRNA *srna)
/* -------------------------------------------------------------------------- */
-static EnumPropertyItem shader_node_type_items[MaxNodes];
static void rna_def_shader_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
- alloc_node_type_items(shader_node_type_items, Category_ShaderNode);
-
srna = RNA_def_struct(brna, "ShaderNode", "Node");
RNA_def_struct_ui_text(srna, "Shader Node", "Material shader node");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, shader_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_ShaderNode_register", "rna_Node_unregister", NULL);
}
-static EnumPropertyItem compositor_node_type_items[MaxNodes];
static void rna_def_compositor_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- alloc_node_type_items(compositor_node_type_items, Category_CompositorNode);
+ FunctionRNA *func;
srna = RNA_def_struct(brna, "CompositorNode", "Node");
RNA_def_struct_ui_text(srna, "Compositor Node", "");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, compositor_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_CompositorNode_register", "rna_Node_unregister", NULL);
+
+ /* compositor node need_exec flag */
+ func = RNA_def_function(srna, "tag_need_exec", "rna_CompositorNode_tag_need_exec");
+ RNA_def_function_ui_description(func, "Tag the node for compositor update");
}
-static EnumPropertyItem texture_node_type_items[MaxNodes];
static void rna_def_texture_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- alloc_node_type_items(texture_node_type_items, Category_TextureNode);
srna = RNA_def_struct(brna, "TextureNode", "Node");
RNA_def_struct_ui_text(srna, "Texture Node", "");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, texture_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_TextureNode_register", "rna_Node_unregister", NULL);
}
-static void rna_def_special_node(BlenderRNA *brna)
+/* -------------------------------------------------------------------------- */
+
+static void rna_def_node_socket(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocket", NULL);
+ RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
+ RNA_def_struct_ui_icon(srna, ICON_PLUG);
+ RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+ RNA_def_struct_register_funcs(srna, "rna_NodeSocket_register", "rna_NodeSocket_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_NodeSocket_idprops");
- static EnumPropertyItem specific_node_type_items[] = {
- {NODE_GROUP, "GROUP", ICON_NODE, "Group", ""},
- {NODE_FRAME, "FRAME", ICON_NODE, "Frame", ""},
- {NODE_REROUTE, "REROUTE", ICON_NODE, "Reroute", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "SpecialNode", "Node");
- RNA_def_struct_ui_text(srna, "Special Node", "");
- RNA_def_struct_sdna(srna, "bNode");
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "identifier");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, specific_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
-}
+ RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
-/* -------------------------------------------------------------------------- */
+ prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "in_out");
+ RNA_def_property_enum_items(prop, node_socket_in_out_items);
+ RNA_def_property_enum_default(prop, SOCK_IN);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
-static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *parm;
- FunctionRNA *func;
+ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_NodeSocket_hide_set");
+ RNA_def_property_ui_text(prop, "Hide", "Hide the socket");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- RNA_def_property_srna(cprop, "NodeLinks");
- srna = RNA_def_struct(brna, "NodeLinks", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Node Links", "Collection of Node Links");
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_UNAVAIL);
+ RNA_def_property_ui_text(prop, "Enabled", "Enable the socket");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- func = RNA_def_function(srna, "new", "rna_NodeTree_link_new");
- RNA_def_function_ui_description(func, "Add a node link to this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- /* return */
- parm = RNA_def_pointer(func, "link", "NodeLink", "", "New node link");
- RNA_def_function_return(func, parm);
+ prop = RNA_def_property(srna, "is_linked", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_IN_USE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
- func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove");
- RNA_def_function_ui_description(func, "remove a node link from the node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
+ RNA_def_property_ui_text(prop, "Expanded", "Socket links are expanded in the user interface");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear");
- RNA_def_function_ui_description(func, "remove all node links from the node tree");
-}
+ prop = RNA_def_property(srna, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, "rna_NodeSocket_node_get", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Node", "Node owning this socket");
-/* shared between all note tree types*/
-static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *UNUSED(cprop))
-{
- PropertyRNA *prop;
+ /* NB: the type property is used by standard sockets.
+ * Ideally should be defined only for the registered subclass,
+ * but to use the existing DNA is added in the base type here.
+ * Future socket types can ignore or override this if needed.
+ */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, node_socket_type_items);
+ RNA_def_property_enum_default(prop, SOCK_FLOAT);
+ RNA_def_property_ui_text(prop, "Type", "Data type");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeSocket_bl_idname_get", "rna_NodeSocket_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ /* draw socket */
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "Draw socket");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_pointer_funcs(prop, "rna_NodeTree_active_node_get", "rna_NodeTree_active_node_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
- RNA_def_property_ui_text(prop, "Active Node", "Active node in this tree");
- RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+ func = RNA_def_function(srna, "draw_color", NULL);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
}
-static void rna_def_composite_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_interface(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
PropertyRNA *parm;
FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocketInterface", NULL);
+ RNA_def_struct_ui_text(srna, "Node Socket Template", "Parameters to define node sockets");
+ /* XXX Using bNodeSocket DNA for templates is a compatibility hack.
+ * This allows to keep the inputs/outputs lists in bNodeTree working for earlier versions
+ * and at the same time use them for socket templates in groups.
+ */
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_refine_func(srna, "rna_NodeSocketInterface_refine");
+ RNA_def_struct_path_func(srna, "rna_NodeSocketInterface_path");
+ RNA_def_struct_idprops_func(srna, "rna_NodeSocketInterface_idprops");
+ RNA_def_struct_register_funcs(srna, "rna_NodeSocketInterface_register", "rna_NodeSocketInterface_unregister", NULL);
- RNA_def_property_srna(cprop, "CompositorNodes");
- srna = RNA_def_struct(brna, "CompositorNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Compositor Nodes", "Collection of Compositor Nodes");
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_composite_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", compositor_node_type_items, 0, "Type", "Type of node to add");
+ prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "identifier");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
+
+ prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "in_out");
+ RNA_def_property_enum_items(prop, node_socket_in_out_items);
+ RNA_def_property_enum_default(prop, SOCK_IN);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_socket_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeSocket_bl_idname_get", "rna_NodeSocket_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "Draw template settings");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "draw_color", NULL);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
+
+ func = RNA_def_function(srna, "register_properties", NULL);
+ RNA_def_function_ui_description(func, "Define RNA properties of a socket");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "data_rna_type", "Struct", "Data RNA Type", "RNA type for special socket properties");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ func = RNA_def_function(srna, "init_socket", NULL);
+ RNA_def_function_ui_description(func, "Initialize a node socket instance");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Node of the socket to initialize");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "Socket", "Socket to initialize");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_string(func, "data_path", "", 0, "Data Path", "Path to specialized socket data");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ func = RNA_def_function(srna, "from_socket", NULL);
+ RNA_def_function_ui_description(func, "Setup template parameters from an existing socket");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Node of the original socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "Socket", "Original socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+}
- rna_def_nodetree_active_api(srna, cprop);
+static void rna_def_node_socket_float(BlenderRNA *brna, const char *idname, const char *interface_idname, PropertySubType subtype)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, idname, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Float Node Socket", "Floating point number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Float Node Socket Interface", "Floating point number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
}
-static void rna_def_shader_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_int(BlenderRNA *brna, const char *identifier, const char *interface_idname, PropertySubType subtype)
{
StructRNA *srna;
- PropertyRNA *parm;
- FunctionRNA *func;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Integer Node Socket", "Integer number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_INT, subtype);
+ RNA_def_property_int_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Integer Node Socket Interface", "Integer number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- RNA_def_property_srna(cprop, "ShaderNodes");
- srna = RNA_def_struct(brna, "ShaderNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Shader Nodes", "Collection of Shader Nodes");
+static void rna_def_node_socket_bool(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Boolean Node Socket", "Boolean value socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "value", 1);
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Boolean Node Socket Interface", "Boolean value socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", shader_node_type_items, 0, "Type", "Type of node to add");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
+static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, const char *interface_idname, PropertySubType subtype)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Vector Node Socket", "3D vector socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Vector Node Socket Interface", "3D vector socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+static void rna_def_node_socket_color(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Color Node Socket", "RGBA color socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Color Node Socket Interface", "RGBA color socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+static void rna_def_node_socket_string(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "String Node Socket", "String socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "String Node Socket Interface", "String socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
+
+static void rna_def_node_socket_shader(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Shader Node Socket", "Shader socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Shader Node Socket Interface", "Shader socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- rna_def_nodetree_active_api(srna, cprop);
+static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Virtual Node Socket", "Virtual socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
}
-static void rna_def_texture_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_standard_types(BlenderRNA *brna)
{
+ /* XXX Workaround: Registered functions are not exposed in python by bpy,
+ * it expects them to be registered from python and use the native implementation.
+ * However, the standard socket types below are not registering these functions from python,
+ * so in order to call them in py scripts we need to overload and replace them with plain C callbacks.
+ * These types provide a usable basis for socket types defined in C.
+ */
+
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocketStandard", "NodeSocket");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ /* draw socket */
+ func = RNA_def_function(srna, "draw", "rna_NodeSocketStandard_draw");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Draw socket");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_srna(cprop, "TextureNodes");
- srna = RNA_def_struct(brna, "TextureNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Texture Nodes", "Collection of Texture Nodes");
-
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_texture_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", texture_node_type_items, 0, "Type", "Type of node to add");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ func = RNA_def_function(srna, "draw_color", "rna_NodeSocketStandard_draw_color");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
+
+
+ srna = RNA_def_struct(brna, "NodeSocketInterfaceStandard", "NodeSocketInterface");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ func = RNA_def_function(srna, "draw", "rna_NodeSocketInterfaceStandard_draw");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Draw template settings");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ func = RNA_def_function(srna, "draw_color", "rna_NodeSocketInterfaceStandard_draw_color");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
- rna_def_nodetree_active_api(srna, cprop);
-}
-static void rna_def_node_socket(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
+ /* XXX These types should eventually be registered at runtime.
+ * Then use the nodeStaticSocketType and nodeStaticSocketInterfaceType functions
+ * to get the idname strings from int type and subtype (see node_socket.c, register_standard_node_socket_types).
+ */
+
+ rna_def_node_socket_float(brna, "NodeSocketFloat", "NodeSocketInterfaceFloat", PROP_NONE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatUnsigned", "NodeSocketInterfaceFloatUnsigned", PROP_UNSIGNED);
+ rna_def_node_socket_float(brna, "NodeSocketFloatPercentage", "NodeSocketInterfaceFloatPercentage", PROP_PERCENTAGE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatFactor", "NodeSocketInterfaceFloatFactor", PROP_FACTOR);
+ rna_def_node_socket_float(brna, "NodeSocketFloatAngle", "NodeSocketInterfaceFloatAngle", PROP_ANGLE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatTime", "NodeSocketInterfaceFloatTime", PROP_TIME);
- srna = RNA_def_struct(brna, "NodeSocket", NULL);
- RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
- RNA_def_struct_sdna(srna, "bNodeSocket");
- RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
- RNA_def_struct_ui_icon(srna, ICON_PLUG);
- RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+ rna_def_node_socket_int(brna, "NodeSocketInt", "NodeSocketInterfaceInt", PROP_NONE);
+ rna_def_node_socket_int(brna, "NodeSocketIntUnsigned", "NodeSocketInterfaceIntUnsigned", PROP_UNSIGNED);
+ rna_def_node_socket_int(brna, "NodeSocketIntPercentage", "NodeSocketInterfaceIntPercentage", PROP_PERCENTAGE);
+ rna_def_node_socket_int(brna, "NodeSocketIntFactor", "NodeSocketInterfaceIntFactor", PROP_FACTOR);
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, node_socket_type_items);
- RNA_def_property_enum_default(prop, 0);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Type", "Node Socket type");
+ rna_def_node_socket_bool(brna, "NodeSocketBool", "NodeSocketInterfaceBool");
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- /* XXX must be editable for group sockets. if necessary use a special rna definition for these */
-/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
- RNA_def_property_ui_text(prop, "Name", "Socket name");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroupSocket_update");
+ rna_def_node_socket_vector(brna, "NodeSocketVector", "NodeSocketInterfaceVector", PROP_NONE);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorTranslation", "NodeSocketInterfaceVectorTranslation", PROP_TRANSLATION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorDirection", "NodeSocketInterfaceVectorDirection", PROP_DIRECTION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorVelocity", "NodeSocketInterfaceVectorVelocity", PROP_VELOCITY);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorAcceleration", "NodeSocketInterfaceVectorAcceleration", PROP_ACCELERATION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorEuler", "NodeSocketInterfaceVectorEuler", PROP_EULER);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorXYZ", "NodeSocketInterfaceVectorXYZ", PROP_XYZ);
- prop = RNA_def_property(srna, "group_socket", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "groupsock");
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Group Socket",
- "For group nodes, the group input or output socket this corresponds to");
+ rna_def_node_socket_color(brna, "NodeSocketColor", "NodeSocketInterfaceColor");
- prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_NodeSocket_hide_set");
- RNA_def_property_ui_text(prop, "Hide", "Hide the socket");
- RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
+ rna_def_node_socket_string(brna, "NodeSocketString", "NodeSocketInterfaceString");
- prop = RNA_def_property(srna, "is_linked", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_IN_USE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
+ rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader");
- prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
- RNA_def_property_ui_text(prop, "Expanded", "Socket links are expanded in the user interface");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
+ rna_def_node_socket_virtual(brna, "NodeSocketVirtual");
}
-static void rna_def_node_socket_subtype(BlenderRNA *brna, int type, int subtype, const char *name, const char *ui_name)
+static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
{
StructRNA *srna;
- PropertyRNA *prop = NULL;
- PropertySubType propsubtype = PROP_NONE;
-
- #define SUBTYPE(socktype, stypename, id, idname) { PROP_##id, #socktype "_" #id, 0, #idname, ""},
- static EnumPropertyItem subtype_items[] = {
- NODE_DEFINE_SUBTYPES
- {0, NULL, 0, NULL, NULL}
- };
- #undef SUBTYPE
+ PropertyRNA *parm;
+ FunctionRNA *func;
+ const char *structtype = (in_out == SOCK_IN ? "NodeInputs" : "NodeOutputs");
+ const char *uiname = (in_out == SOCK_IN ? "Node Inputs" : "Node Outputs");
+ const char *newfunc = (in_out == SOCK_IN ? "rna_Node_inputs_new" : "rna_Node_outputs_new");
+ const char *clearfunc = (in_out == SOCK_IN ? "rna_Node_inputs_clear" : "rna_Node_outputs_clear");
- #define SUBTYPE(socktype, stypename, id, idname) if (subtype == (PROP_##id)) propsubtype = PROP_##id;
- NODE_DEFINE_SUBTYPES
- #undef SUBTYPE
-
- srna = RNA_def_struct(brna, name, "NodeSocket");
- RNA_def_struct_ui_text(srna, ui_name, "Input or output socket of a node");
- RNA_def_struct_sdna(srna, "bNodeSocket");
- RNA_def_struct_ui_icon(srna, ICON_PLUG);
- RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
-
- switch (type) {
- case SOCK_INT:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_INT, propsubtype);
- RNA_def_property_int_sdna(prop, NULL, "value");
- RNA_def_property_int_funcs(prop, NULL, NULL, "rna_NodeSocketInt_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_FLOAT:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, propsubtype);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketFloat_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_BOOLEAN:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value");
-
- prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "value", 1);
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_VECTOR:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, propsubtype);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketVector_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_RGBA:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value");
+ RNA_def_property_srna(cprop, structtype);
+ srna= RNA_def_struct(brna, structtype, NULL);
+ RNA_def_struct_sdna(srna, "bNode");
+ RNA_def_struct_ui_text(srna, uiname, "Collection of Node Sockets");
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_STRING:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- }
-
- /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
- RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+ func= RNA_def_function(srna, "new", newfunc);
+ RNA_def_function_ui_description(func, "Add a socket to this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm= RNA_def_string(func, "type", "", MAX_NAME, "Type", "Data type");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_string(func, "identifier", "", MAX_NAME, "Identifier", "Unique socket identifier");
+ /* return value */
+ parm= RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_Node_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a socket from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm= RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func= RNA_def_function(srna, "clear", clearfunc);
+ RNA_def_function_ui_description(func, "Remove all sockets from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
}
static void rna_def_node(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ static EnumPropertyItem dummy_static_type_items[] = {
+ {NODE_CUSTOM, "CUSTOM", 0, "Custom", "Custom Node"},
+ {0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "Node", NULL);
RNA_def_struct_ui_text(srna, "Node", "Node in a node tree");
@@ -4773,6 +6358,16 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_NODE);
RNA_def_struct_refine_func(srna, "rna_Node_refine");
RNA_def_struct_path_func(srna, "rna_Node_path");
+ RNA_def_struct_register_funcs(srna, "rna_Node_register", "rna_Node_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_Node_idprops");
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, dummy_static_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_node_static_type_itemf");
+ RNA_def_property_enum_default(prop, NODE_CUSTOM);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Type", "Node type (deprecated, use bl_static_type or bl_idname for the actual identifier string)");
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "locx");
@@ -4812,13 +6407,24 @@ static void rna_def_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_Node_inputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Inputs", "");
+ rna_def_node_sockets_api(brna, prop, SOCK_IN);
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_Node_outputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Outputs", "");
+ rna_def_node_sockets_api(brna, prop, SOCK_OUT);
+
+ prop = RNA_def_property(srna, "internal_links", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "internal_links", NULL);
+ RNA_def_property_struct_type(prop, "NodeLink");
+ RNA_def_property_ui_text(prop, "Internal Links", "Internal input-to-output connections for muting");
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "parent");
@@ -4840,8 +6446,9 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SELECT);
- RNA_def_property_ui_text(prop, "Select", "");
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Node_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Node selection state");
RNA_def_property_update(prop, NC_NODE | NA_SELECTED, NULL);
prop = RNA_def_property(srna, "show_options", PROP_BOOLEAN, PROP_NONE);
@@ -4868,6 +6475,115 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_TEXTURE);
RNA_def_property_ui_text(prop, "Show Texture", "Draw node in viewport textured draw mode");
RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ /* generic property update function */
+ func = RNA_def_function(srna, "socket_value_update", "rna_Node_socket_value_update");
+ RNA_def_function_ui_description(func, "Update after property changes");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "is_registered_node_type", "rna_Node_is_registered_node_type");
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_idname_get", "rna_Node_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER|PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_name");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_label_get", "rna_Node_bl_label_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Label", "The node label");
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_description_get", "rna_Node_bl_description_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon");
+ RNA_def_property_enum_funcs(prop, "rna_Node_bl_icon_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, node_icon_items);
+ RNA_def_property_enum_default(prop, ICON_NODE);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Icon", "The node icon");
+
+ prop = RNA_def_property(srna, "bl_static_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->type");
+ RNA_def_property_enum_funcs(prop, "rna_Node_bl_static_type_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, dummy_static_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_node_static_type_itemf");
+ RNA_def_property_enum_default(prop, NODE_CUSTOM);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Static Type", "Node type (deprecated, use with care)");
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "If non-null output is returned, the node type can be added to the tree");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "poll_instance", NULL);
+ RNA_def_function_ui_description(func, "If non-null output is returned, the node can be added to the tree");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ /* update */
+ func = RNA_def_function(srna, "update", NULL);
+ RNA_def_function_ui_description(func, "Update on editor changes");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* init */
+ func = RNA_def_function(srna, "init", NULL);
+ RNA_def_function_ui_description(func, "Initialize a new instance of this node");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* copy */
+ func = RNA_def_function(srna, "copy", NULL);
+ RNA_def_function_ui_description(func, "Initialize a new instance of this node from an existing node");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Existing node to copy");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* free */
+ func = RNA_def_function(srna, "free", NULL);
+ RNA_def_function_ui_description(func, "Clean up node on removal");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* draw buttons */
+ func = RNA_def_function(srna, "draw_buttons", NULL);
+ RNA_def_function_ui_description(func, "Draw node buttons");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+
+ /* draw buttons extended */
+ func = RNA_def_function(srna, "draw_buttons_ext", NULL);
+ RNA_def_function_ui_description(func, "Draw node buttons in the sidebar");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
}
static void rna_def_node_link(BlenderRNA *brna)
@@ -4880,63 +6596,165 @@ static void rna_def_node_link(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bNodeLink");
RNA_def_struct_ui_icon(srna, ICON_NODE);
+ prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_LINK_VALID);
+ RNA_def_struct_ui_text(srna, "Valid", "Link is valid");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
+
prop = RNA_def_property(srna, "from_node", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fromnode");
RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "From node", "");
prop = RNA_def_property(srna, "to_node", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tonode");
RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "To node", "");
prop = RNA_def_property(srna, "from_socket", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fromsock");
RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "From socket", "");
prop = RNA_def_property(srna, "to_socket", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tosock");
RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "To socket", "");
+
+ prop = RNA_def_property(srna, "is_hidden", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_NodeLink_is_hidden_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Hidden", "Link is hidden due to invisible sockets");
}
-static void rna_def_group_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
+static void rna_def_nodetree_nodes_api(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *parm, *prop;
+ FunctionRNA *func;
+
+ RNA_def_property_srna(cprop, "Nodes");
+ srna= RNA_def_struct(brna, "Nodes", NULL);
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_text(srna, "Nodes", "Collection of Nodes");
+
+ func= RNA_def_function(srna, "new", "rna_NodeTree_node_new");
+ RNA_def_function_ui_description(func, "Add a node to this node tree");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm= RNA_def_string(func, "type", "", MAX_NAME, "Type", "Type of node to add");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return value */
+ parm= RNA_def_pointer(func, "node", "Node", "", "New node");
+ RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
+ RNA_def_function_ui_description(func, "Remove a node from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm= RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func= RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
+ RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_pointer_funcs(prop, "rna_NodeTree_active_node_get", "rna_NodeTree_active_node_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Node", "Active node in this tree");
+ RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+}
+
+static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
- RNA_def_property_srna(cprop, (in_out == SOCK_IN ? "GroupInputs" : "GroupOutputs"));
- srna = RNA_def_struct(brna, (in_out == SOCK_IN ? "GroupInputs" : "GroupOutputs"), NULL);
+ RNA_def_property_srna(cprop, "NodeLinks");
+ srna = RNA_def_struct(brna, "NodeLinks", NULL);
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Group Sockets", "Collection of group sockets");
+ RNA_def_struct_ui_text(srna, "Node Links", "Collection of Node Links");
- func = RNA_def_function(srna, "new", (in_out == SOCK_IN ? "rna_NodeTree_input_new" : "rna_NodeTree_output_new"));
- RNA_def_function_ui_description(func, "Add a socket to the group tree");
+ func = RNA_def_function(srna, "new", "rna_NodeTree_link_new");
+ RNA_def_function_ui_description(func, "Add a node link to this node tree");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_string(func, "name", "Socket", MAX_NAME, "Name", "Name of the socket");
- RNA_def_enum(func, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of socket");
- /* return value */
- parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "verify_limits", TRUE, "Verify Limits", "Remove existing links if connection limit is exceeded");
+ /* return */
+ parm = RNA_def_pointer(func, "link", "NodeLink", "", "New node link");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "expose",
- (in_out == SOCK_IN ? "rna_NodeTree_input_expose" : "rna_NodeTree_output_expose"));
- RNA_def_function_ui_description(func, "Expose an internal socket in the group tree");
+ func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove");
+ RNA_def_function_ui_description(func, "remove a node link from the node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear");
+ RNA_def_function_ui_description(func, "remove all node links from the node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+}
+
+static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
+{
+ StructRNA *srna;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+ const char *structtype = (in_out == SOCK_IN ? "NodeTreeInputs" : "NodeTreeOutputs");
+ const char *uiname = (in_out == SOCK_IN ? "Node Tree Inputs" : "Node Tree Outputs");
+ const char *newfunc = (in_out == SOCK_IN ? "rna_NodeTree_inputs_new" : "rna_NodeTree_outputs_new");
+ const char *clearfunc = (in_out == SOCK_IN ? "rna_NodeTree_inputs_clear" : "rna_NodeTree_outputs_clear");
+
+ RNA_def_property_srna(cprop, structtype);
+ srna= RNA_def_struct(brna, structtype, NULL);
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_text(srna, uiname, "Collection of Node Tree Sockets");
+
+ func= RNA_def_function(srna, "new", newfunc);
+ RNA_def_function_ui_description(func, "Add a socket to this node tree");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "Internal node socket to expose");
+ parm= RNA_def_string(func, "type", "", MAX_NAME, "Type", "Data type");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "add_link", TRUE, "Add Link", "If TRUE, adds a link to the internal socket");
/* return value */
- parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ parm= RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "New socket");
RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_NodeTree_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a socket from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm= RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func= RNA_def_function(srna, "clear", clearfunc);
+ RNA_def_function_ui_description(func, "Remove all sockets from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
}
static void rna_def_nodetree(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ static EnumPropertyItem static_type_items[] = {
+ {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
+ {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
+ {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "NodeTree", "ID");
RNA_def_struct_ui_text(srna, "Node Tree",
@@ -4944,10 +6762,18 @@ static void rna_def_nodetree(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bNodeTree");
RNA_def_struct_ui_icon(srna, ICON_NODETREE);
RNA_def_struct_refine_func(srna, "rna_NodeTree_refine");
+ RNA_def_struct_register_funcs(srna, "rna_NodeTree_register", "rna_NodeTree_unregister", NULL);
/* AnimData */
rna_def_animdata_common(srna);
-
+
+ /* Nodes Collection */
+ prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_ui_text(prop, "Nodes", "");
+ rna_def_nodetree_nodes_api(brna, prop);
+
/* NodeLinks Collection */
prop = RNA_def_property(srna, "links", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "links", NULL);
@@ -4965,21 +6791,100 @@ static void rna_def_nodetree(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, nodetree_type_items);
- RNA_def_property_ui_text(prop, "Type", "Node Tree type");
+ RNA_def_property_enum_items(prop, static_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Node Tree type (deprecated, bl_idname is the actual node tree type identifier)");
- /* group sockets */
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Inputs", "");
- rna_def_group_sockets_api(brna, prop, SOCK_IN);
-
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_NodeTree_inputs_lookupstring", NULL);
+ RNA_def_property_struct_type(prop, "NodeSocketInterface");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Inputs", "Node tree inputs");
+ rna_def_node_tree_sockets_api(brna, prop, SOCK_IN);
+
+ prop = RNA_def_property(srna, "active_input", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_NodeTree_active_input_get", "rna_NodeTree_active_input_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Input", "Index of the active input");
+ RNA_def_property_update(prop, NC_NODE, NULL);
+
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Outputs", "");
- rna_def_group_sockets_api(brna, prop, SOCK_OUT);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_NodeTree_outputs_lookupstring", NULL);
+ RNA_def_property_struct_type(prop, "NodeSocketInterface");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Outputs", "Node tree outputs");
+ rna_def_node_tree_sockets_api(brna, prop, SOCK_OUT);
+
+ prop = RNA_def_property(srna, "active_output", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_NodeTree_active_output_get", "rna_NodeTree_active_output_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Output", "Index of the active output");
+ RNA_def_property_update(prop, NC_NODE, NULL);
+
+ /* exposed as a function for runtime interface type properties */
+ func = RNA_def_function(srna, "interface_update", "rna_NodeTree_interface_update");
+ RNA_def_function_ui_description(func, "Updated node group interface");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_idname_get", "rna_NodeTree_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER|PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_name");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_label_get", "rna_NodeTree_bl_label_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Label", "The node tree label");
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_description_get", "rna_NodeTree_bl_description_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon");
+ RNA_def_property_enum_funcs(prop, "rna_NodeTree_bl_icon_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, node_icon_items);
+ RNA_def_property_enum_default(prop, ICON_NODETREE);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Icon", "The node tree icon");
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "Check visibility in the editor");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+
+ /* draw add menu */
+ func = RNA_def_function(srna, "draw_add_menu", NULL);
+ RNA_def_function_ui_description(func, "Draw the menu for adding nodes");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Menu layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+
+ /* get a node tree from context */
+ func = RNA_def_function(srna, "get_from_context", NULL);
+ RNA_def_function_ui_description(func, "Get a node tree from the context");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_pointer(func, "result_1", "NodeTree", "Node Tree", "Active node tree from context");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "result_2", "ID", "Owner ID", "ID data block that owns the node tree");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "result_3", "ID", "From ID", "Original ID data block selected from the context");
+ RNA_def_function_output(func, parm);
}
static void rna_def_composite_nodetree(BlenderRNA *brna)
@@ -4990,15 +6895,7 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
srna = RNA_def_struct(brna, "CompositorNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Compositor Node Tree", "Node tree consisting of linked nodes used for compositing");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
-
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
-
- rna_def_composite_nodetree_api(brna, prop);
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
prop = RNA_def_property(srna, "render_quality", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "render_quality");
@@ -5029,6 +6926,11 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, "
"second pass calculate all nodes");
+ prop = RNA_def_property(srna, "is_local_tree", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Local Scene Tree", "Local scene node tree, eligible for special node types");
+
prop = RNA_def_property(srna, "use_viewer_border", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_VIEWER_BORDER);
RNA_def_property_ui_text(prop, "Viewer Border", "Use boundaries for viewer nodes and composite backdrop");
@@ -5044,15 +6946,12 @@ static void rna_def_shader_nodetree(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Shader Node Tree",
"Node tree consisting of linked nodes used for materials (and other shading datablocks)");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
+ RNA_def_struct_ui_icon(srna, ICON_MATERIAL);
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
-
- rna_def_shader_nodetree_api(brna, prop);
+ prop = RNA_def_property(srna, "is_local_tree", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Local Material Tree", "Local material node tree, eligible for special node types");
}
static void rna_def_texture_nodetree(BlenderRNA *brna)
@@ -5063,64 +6962,87 @@ static void rna_def_texture_nodetree(BlenderRNA *brna)
srna = RNA_def_struct(brna, "TextureNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Texture Node Tree", "Node tree consisting of linked nodes used for textures");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
-
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
+ RNA_def_struct_ui_icon(srna, ICON_TEXTURE);
- rna_def_texture_nodetree_api(brna, prop);
+ prop = RNA_def_property(srna, "is_local_tree", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Local Texture Tree", "Local texture node tree, eligible for special node types");
}
-static void define_specific_node(BlenderRNA *brna, int id, void (*def_func)(StructRNA *))
+static void define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name,
+ const char *ui_name, const char *ui_desc, void (*def_func)(StructRNA *))
{
- StructRNA *srna = def_node(brna, id);
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ srna = RNA_def_struct(brna, struct_name, base_name);
+ RNA_def_struct_ui_text(srna, ui_name, ui_desc);
+ RNA_def_struct_sdna(srna, "bNode");
+
+ func = RNA_def_function(srna, "is_registered_node_type", "rna_Node_is_registered_node_type");
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
if (def_func)
def_func(srna);
}
+static void rna_def_node_instance_hash(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "NodeInstanceHash", NULL);
+ RNA_def_struct_ui_text(srna, "Node Instance Hash", "Hash table containing node instance data");
+
+ /* XXX This type is a stub for now, only used to store instance hash in the context.
+ * Eventually could use a StructRNA pointer to define a specific data type
+ * and expose lookup functions.
+ */
+}
+
void RNA_def_nodetree(BlenderRNA *brna)
{
- init();
- rna_def_nodetree(brna);
-
rna_def_node_socket(brna);
-
- /* Generate RNA definitions for all socket subtypes */
- #define SUBTYPE(socktype, stypename, id, idname) \
- rna_def_node_socket_subtype(brna, SOCK_##socktype, PROP_##id, "NodeSocket"#stypename#idname, \
- #idname" "#stypename" Node Socket");
- NODE_DEFINE_SUBTYPES
- #undef SUBTYPE
- rna_def_node_socket_subtype(brna, SOCK_BOOLEAN, 0, "NodeSocketBoolean", "Boolean Node Socket");
- rna_def_node_socket_subtype(brna, SOCK_RGBA, 0, "NodeSocketRGBA", "RGBA Node Socket");
- rna_def_node_socket_subtype(brna, SOCK_SHADER, 0, "NodeSocketShader", "Shader Closure Node Socket");
+ rna_def_node_socket_interface(brna);
rna_def_node(brna);
rna_def_node_link(brna);
rna_def_shader_node(brna);
rna_def_compositor_node(brna);
rna_def_texture_node(brna);
- rna_def_special_node(brna);
+
+ rna_def_nodetree(brna);
+
+ rna_def_node_socket_standard_types(brna);
rna_def_composite_nodetree(brna);
rna_def_shader_nodetree(brna);
rna_def_texture_nodetree(brna);
+
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- define_specific_node(brna, ID, DefFunc);
-
- #include "rna_nodetree_types.h"
+ define_specific_node(brna, #Category #StructName, #Category, UIName, UIDesc, DefFunc);
- define_specific_node(brna, NODE_GROUP, def_group);
- define_specific_node(brna, NODE_FRAME, def_frame);
- define_specific_node(brna, NODE_REROUTE, 0);
+ /* hack, don't want to add include path to RNA just for this, since in the future RNA types
+ * for nodes should be defined locally at runtime anyway ...
+ */
+ #include "../../nodes/NOD_static_types.h"
+
+ /* Node group types need to be defined for shader, compositor, texture nodes individually.
+ * Cannot use the static types header for this, since they share the same int id.
+ */
+ define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group);
+ define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group);
+ define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group);
/* special socket types */
rna_def_cmp_output_file_slot_file(brna);
rna_def_cmp_output_file_slot_layer(brna);
+
+ rna_def_node_instance_hash(brna);
}
/* clean up macro definition */