From b31594c4ab63b8e8675bcf2b4547cc92416db2b7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 2 Dec 2010 01:18:59 +0000 Subject: patch [#23212] Python api for Nodes from Dan Eicher (dna) This allows automated node tree creation and editing. developer note, made some changes to the patch. - removed incorrect use of container_of(), GCC only also, search for the scene instead. - commented socket min/max access, these are internal use only as far as I can tell. - commented group/ungroup functions, these use the selection context and are not really data level functions. - use remove() rather then delete() --- source/blender/makesrna/RNA_access.h | 3 + source/blender/makesrna/intern/rna_nodetree.c | 432 ++++++++++++++++++++++++-- 2 files changed, 401 insertions(+), 34 deletions(-) (limited to 'source') diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 08aee5cbf73..ac8c3229011 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -157,6 +157,7 @@ extern StructRNA RNA_CompositorNodeTexture; extern StructRNA RNA_CompositorNodeTime; extern StructRNA RNA_CompositorNodeTonemap; extern StructRNA RNA_CompositorNodeTranslate; +extern StructRNA RNA_CompositorNodeTree; extern StructRNA RNA_CompositorNodeValToRGB; extern StructRNA RNA_CompositorNodeValue; extern StructRNA RNA_CompositorNodeVecBlur; @@ -417,6 +418,7 @@ extern StructRNA RNA_ShaderNodeRGBToBW; extern StructRNA RNA_ShaderNodeSeparateRGB; extern StructRNA RNA_ShaderNodeSqueeze; extern StructRNA RNA_ShaderNodeTexture; +extern StructRNA RNA_ShaderNodeTree; extern StructRNA RNA_ShaderNodeValToRGB; extern StructRNA RNA_ShaderNodeValue; extern StructRNA RNA_ShaderNodeVectorCurve; @@ -496,6 +498,7 @@ extern StructRNA RNA_TextureNodeRotate; extern StructRNA RNA_TextureNodeScale; extern StructRNA RNA_TextureNodeTexture; extern StructRNA RNA_TextureNodeTranslate; +extern StructRNA RNA_TextureNodeTree; extern StructRNA RNA_TextureNodeValToNor; extern StructRNA RNA_TextureNodeValToRGB; extern StructRNA RNA_TextureNodeViewer; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 0d7aec4563d..6297a7897d9 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -48,10 +48,15 @@ #ifdef RNA_RUNTIME +#include "BLI_linklist.h" + #include "ED_node.h" #include "RE_pipeline.h" +#include "DNA_scene_types.h" +#include "WM_api.h" + static StructRNA *rna_Node_refine(struct PointerRNA *ptr) { bNode *node = (bNode*)ptr->data; @@ -89,6 +94,22 @@ static StructRNA *rna_NodeSocketType_refine(struct PointerRNA *ptr) } } +static StructRNA *rna_NodeTree_refine(struct PointerRNA *ptr) +{ + bNodeTree *ntree= (bNodeTree*)ptr->data; + + switch(ntree->type) { + case NTREE_SHADER: + return &RNA_ShaderNodeTree; + case NTREE_COMPOSIT: + return &RNA_CompositorNodeTree; + case NTREE_TEXTURE: + return &RNA_TextureNodeTree; + default: + return &RNA_UnknownType; + } +} + static char *rna_Node_path(PointerRNA *ptr) { bNode *node= (bNode*)ptr->data; @@ -157,6 +178,22 @@ static void rna_Image_end_frame_set(PointerRNA *ptr, int value) image->efra= value; } +static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value) +{ + 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 node_update(Main *bmain, Scene *scene, bNodeTree *ntree, bNode *node) { ED_node_generic_update(bmain, ntree, node); @@ -390,6 +427,117 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *C, PointerRNA *ptr, in return item; } +static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports, int type, bNodeTree *group) +{ + bNode *node= nodeAddNodeType(ntree, type, group, NULL); + + if (node == NULL) { + BKE_reportf(reports, RPT_ERROR, "Unable to create node"); + } + else { + nodeVerifyGroup(ntree); /* update group node socket links*/ + NodeTagChanged(ntree, node); + WM_event_add_notifier(C, NC_NODE|NA_EDITED, ntree); + } + + return node; +} + +static bNode *rna_NodeTree_node_composite_new(bNodeTree *ntree, bContext *C, ReportList *reports, int type, bNodeTree *group) +{ + /* raises error on failier */ + 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)); + ntreeSolveOrder(ntree); + } + + return node; +} + +static bNode *rna_NodeTree_node_texture_new(bNodeTree *ntree, bContext *C, ReportList *reports, int type, bNodeTree *group) +{ + /* raises error on failier */ + 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, bContext *C, ReportList *reports, bNode *node) +{ + if (BLI_findindex(&ntree->nodes, node) == -1) { + BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in nodetree", node->name); + } + else { + if (node->id) + id_us_min(node->id); + + nodeFreeNode(ntree, node); + nodeVerifyGroup(ntree); /* update group node socket links*/ + + WM_event_add_notifier(C, NC_NODE|NA_EDITED, ntree); + } +} + +static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, bContext *C, ReportList *reports, bNodeSocket *in, bNodeSocket *out) +{ + bNodeLink *ret; + bNode *fromnode, *tonode; + + if (!nodeFindNode(ntree, in, &fromnode, NULL)) { + BKE_reportf(reports, RPT_ERROR, "Unable to locate input socket's node in nodetree"); + return NULL; + } + + if (!nodeFindNode(ntree, out, &tonode, NULL)) { + BKE_reportf(reports, RPT_ERROR, "Unable to locate output socket's node in nodetree"); + return NULL; + } + + /* unlink node input socket */ + nodeRemSocketLinks(ntree, out); + + ret= nodeAddLink(ntree, fromnode, in, tonode, out); + + NodeTagChanged(ntree, tonode); + + ntreeSolveOrder(ntree); + + WM_event_add_notifier(C, NC_NODE|NA_EDITED, ntree); + + return ret; +} + +static void rna_NodeTree_link_remove(bNodeTree *ntree, bContext *C, ReportList *reports, bNodeLink *link) +{ + if (BLI_findindex(&ntree->links, link) == -1) { + BKE_reportf(reports, RPT_ERROR, "Unable to locate link in nodetree"); + } + else { + nodeRemLink(ntree, link); + ntreeSolveOrder(ntree); + nodeVerifyGroup(ntree); /* update group node socket links*/ + + WM_event_add_notifier(C, NC_NODE|NA_EDITED, ntree); + } +} #else @@ -1095,8 +1243,9 @@ static void def_cmp_render_layers(StructRNA *srna) prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL); RNA_def_property_struct_type(prop, "Scene"); - RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK); RNA_def_property_ui_text(prop, "Scene", ""); RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); @@ -2167,9 +2316,129 @@ static void rna_def_texture_node(BlenderRNA *brna) /* -------------------------------------------------------------------------- */ +static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *parm; + FunctionRNA *func; + + 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"); + + 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_CONTEXT|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); + + 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_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + +static void rna_def_composite_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *parm; + FunctionRNA *func; + + 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"); + + 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"); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= 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_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "node", "Node", "", "The node to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + +static void rna_def_shader_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *parm; + FunctionRNA *func; + + 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"); + + 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); + parm= 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_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "node", "Node", "", "The node to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + +static void rna_def_texture_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *parm; + FunctionRNA *func; + + 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); + parm= 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_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "node", "Node", "", "The node to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + static void rna_def_node_socket(BlenderRNA *brna) { StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem node_socket_type_items[] = { + {SOCK_VALUE, "VALUE", 0, "Value", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, + {0, NULL, 0, NULL, NULL}}; srna = RNA_def_struct(brna, "NodeSocket", NULL); RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node"); @@ -2178,24 +2447,43 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_PLUG); RNA_def_struct_path_func(srna, "rna_NodeSocket_path"); + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Name", "Socket name"); + RNA_def_struct_name_property(srna, prop); + + /* can add back if there is any use in reading them */ +#if 0 + prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ns.min"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Minimum Value", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeSocket_update"); + + prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ns.max"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Maximum Value", ""); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeSocket_update"); +#endif + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_enum_items(prop, node_socket_type_items); + RNA_def_property_ui_text(prop, "Type", "Node Socket type"); } static void rna_def_node_socket_value(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - srna = RNA_def_struct(brna, "ValueNodeSocket", NULL); + + srna = RNA_def_struct(brna, "ValueNodeSocket", "NodeSocket"); RNA_def_struct_ui_text(srna, "Value Node Socket", "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"); - - prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Name", "Socket name"); - RNA_def_struct_name_property(srna, prop); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ns.vec"); RNA_def_property_array(prop, 1); @@ -2208,18 +2496,13 @@ static void rna_def_node_socket_vector(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - srna = RNA_def_struct(brna, "VectorNodeSocket", NULL); + + srna = RNA_def_struct(brna, "VectorNodeSocket", "NodeSocket"); RNA_def_struct_ui_text(srna, "Vector Node Socket", "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"); - - prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Name", "Socket name"); - RNA_def_struct_name_property(srna, prop); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "ns.vec"); RNA_def_property_array(prop, 3); @@ -2232,18 +2515,13 @@ static void rna_def_node_socket_rgba(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - srna = RNA_def_struct(brna, "RGBANodeSocket", NULL); + + srna = RNA_def_struct(brna, "RGBANodeSocket", "NodeSocket"); RNA_def_struct_ui_text(srna, "RGBA Node Socket", "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"); - - prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Name", "Socket name"); - RNA_def_struct_name_property(srna, prop); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "ns.vec"); RNA_def_property_array(prop, 4); @@ -2323,33 +2601,117 @@ static void rna_def_nodetree(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + /* FunctionRNA *func; */ + /* PropertyRNA *parm; */ + + static EnumPropertyItem nodetree_type_items[] = { + {NTREE_SHADER, "SHADER", 0, "Shader", ""}, + {NTREE_COMPOSIT, "COMPOSITE", 0, "Composite", ""}, + {NTREE_TEXTURE, "TEXTURE", 0, "Texture", ""}, + {0, NULL, 0, NULL, NULL}}; srna = RNA_def_struct(brna, "NodeTree", "ID"); RNA_def_struct_ui_text(srna, "Node Tree", "Node tree consisting of linked nodes used for materials, textures and compositing"); RNA_def_struct_sdna(srna, "bNodeTree"); RNA_def_struct_ui_icon(srna, ICON_NODETREE); - + RNA_def_struct_refine_func(srna, "rna_NodeTree_refine"); + /* 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", ""); - /* NodeLinks Collection */ prop = RNA_def_property(srna, "links", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "links", NULL); RNA_def_property_struct_type(prop, "NodeLink"); RNA_def_property_ui_text(prop, "Links", ""); - + rna_def_nodetree_link_api(brna, prop); + /* Grease Pencil */ prop= RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gpd"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock"); + + /* these are too much like operators, better to have data level access + * ngroup = bpy.data.node_groups.new() + * ngroup.nodes.new(....) etc. */ +#if 0 + func= RNA_def_function(srna, "group_add", "nodeMakeGroupFromSelected"); + RNA_def_function_ui_description(func, "Make a group from the active nodes."); + /* return */ + parm= RNA_def_pointer(func, "group", "Node", "", "New group."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "ungroup", "nodeGroupUnGroup"); + RNA_def_function_ui_description(func, "Ungroup node group"); + parm= RNA_def_pointer(func, "group", "Node", "", "The group to ungroup."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_int(func, "bool", 0, 0, 1, "Bool", "", 0, 1); + RNA_def_function_return(func, parm); +#endif + + 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"); +} + +static void rna_def_composite_nodetree(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + 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); +} + +static void rna_def_shader_nodetree(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ShaderNodeTree", "NodeTree"); + RNA_def_struct_ui_text(srna, "Shader Node Tree", "Node tree consisting of linked nodes used for materials"); + 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_shader_nodetree_api(brna, prop); +} + +static void rna_def_texture_nodetree(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + 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_texture_nodetree_api(brna, prop); } static void define_specific_node(BlenderRNA *brna, int id, void (*func)(StructRNA*)) @@ -2373,7 +2735,9 @@ void RNA_def_nodetree(BlenderRNA *brna) rna_def_shader_node(brna); rna_def_compositor_node(brna); rna_def_texture_node(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); -- cgit v1.2.3