diff options
Diffstat (limited to 'source/blender/makesrna')
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 12 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_define.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_enum_types.h | 23 | ||||
-rw-r--r-- | source/blender/makesrna/intern/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 61 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_color.c | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_define.c | 72 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_lamp.c | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_main_api.c | 40 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_material.c | 10 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree.c | 4154 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree_types.h | 215 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 9 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_space.c | 168 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_texture.c | 20 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui_api.c | 16 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_userdef.c | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_world.c | 8 |
18 files changed, 3435 insertions, 1393 deletions
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index cde104710df..efa6f37648a 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -363,14 +363,13 @@ extern StructRNA RNA_NearSensor; extern StructRNA RNA_NlaStrip; extern StructRNA RNA_NlaTrack; extern StructRNA RNA_Node; -extern StructRNA RNA_NodeForLoop; -extern StructRNA RNA_NodeGroup; extern StructRNA RNA_NodeOutputFileSlotFile; extern StructRNA RNA_NodeOutputFileSlotLayer; +extern StructRNA RNA_NodeInstanceHash; extern StructRNA RNA_NodeLink; extern StructRNA RNA_NodeSocket; +extern StructRNA RNA_NodeSocketInterface; extern StructRNA RNA_NodeTree; -extern StructRNA RNA_NodeWhileLoop; extern StructRNA RNA_NoiseTexture; extern StructRNA RNA_NorController; extern StructRNA RNA_Object; @@ -655,7 +654,9 @@ StructRNA *RNA_struct_find(const char *identifier); const char *RNA_struct_identifier(StructRNA *type); const char *RNA_struct_ui_name(StructRNA *type); +const char *RNA_struct_ui_name_raw(StructRNA *type); const char *RNA_struct_ui_description(StructRNA *type); +const char *RNA_struct_ui_description_raw(StructRNA *type); const char *RNA_struct_translation_context(StructRNA *type); int RNA_struct_ui_icon(StructRNA *type); @@ -721,7 +722,9 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name); int RNA_property_string_maxlength(PropertyRNA *prop); const char *RNA_property_ui_name(PropertyRNA *prop); +const char *RNA_property_ui_name_raw(PropertyRNA *prop); const char *RNA_property_ui_description(PropertyRNA *prop); +const char *RNA_property_ui_description_raw(PropertyRNA *prop); const char *RNA_property_translation_context(PropertyRNA *prop); int RNA_property_ui_icon(PropertyRNA *prop); @@ -976,9 +979,11 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name); /* check if the idproperty exists, for operators */ bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost); bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop); +void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop); bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost); bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier); bool RNA_property_is_idprop(PropertyRNA *prop); +void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier); /* python compatible string representation of this property, (must be freed!) */ char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index); @@ -995,6 +1000,7 @@ char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func, Poi const char *RNA_function_identifier(FunctionRNA *func); const char *RNA_function_ui_description(FunctionRNA *func); +const char *RNA_function_ui_description_raw(FunctionRNA *func); int RNA_function_flag(FunctionRNA *func); int RNA_function_defined(FunctionRNA *func); diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 5ab37c6d97b..924fc505fda 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -223,6 +223,8 @@ const char *RNA_property_typename(PropertyType type); #define IS_DNATYPE_FLOAT_COMPAT(_str) (strcmp(_str, "float") == 0 || strcmp(_str, "double") == 0) #define IS_DNATYPE_INT_COMPAT(_str) (strcmp(_str, "int") == 0 || strcmp(_str, "short") == 0 || strcmp(_str, "char") == 0) +void RNA_identifier_sanitize(char *identifier, int property); + /* max size for dynamic defined type descriptors, * this value is arbitrary */ #define RNA_DYN_DESCR_MAX 240 diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index eabf0391c01..2719ae889d4 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -29,6 +29,10 @@ #include "RNA_types.h" +struct bNodeTreeType; +struct bNodeType; +struct bNodeSocketType; + /* Types */ extern EnumPropertyItem id_type_items[]; @@ -128,8 +132,23 @@ extern EnumPropertyItem gameproperty_type_items[]; extern EnumPropertyItem viewport_shade_items[]; -extern EnumPropertyItem nodetree_type_items[]; -extern EnumPropertyItem node_socket_type_items[]; +int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo); +int rna_node_tree_idname_to_enum(const char *idname); +struct bNodeTreeType *rna_node_tree_type_from_enum(int value); +EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, struct bNodeTreeType *), int *free); + +int rna_node_type_to_enum(struct bNodeType *typeinfo); +int rna_node_idname_to_enum(const char *idname); +struct bNodeType *rna_node_type_from_enum(int value); +EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, struct bNodeType*), int *free); + +int rna_node_socket_type_to_enum(struct bNodeSocketType *typeinfo); +int rna_node_socket_idname_to_enum(const char *idname); +struct bNodeSocketType *rna_node_socket_type_from_enum(int value); +EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, struct bNodeSocketType*), int *free); + +extern EnumPropertyItem node_socket_in_out_items[]; +extern EnumPropertyItem node_icon_items[]; extern EnumPropertyItem node_math_items[]; extern EnumPropertyItem node_vec_math_items[]; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 7621ebb70b3..a0ee5e05390 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -259,6 +259,7 @@ blender_include_dirs( ../../imbuf ../../ikplugin ../../makesdna + ../../nodes/ ../../windowmanager ../../editors/include ../../render/extern/include @@ -296,7 +297,6 @@ set(SRC ${SRC_RNA_INC} rna_internal.h rna_internal_types.h - rna_nodetree_types.h rna_mesh_utils.h ) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index f3efbd0d53e..92ce8122597 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -282,6 +282,20 @@ static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name) return NULL; } +static void rna_idproperty_free(PointerRNA *ptr, const char *name) +{ + IDProperty *group = RNA_struct_idprops(ptr, 0); + + if (group) { + IDProperty *idprop = IDP_GetPropertyFromGroup(group, name); + if (idprop) { + IDP_RemFromGroup(group, idprop); + IDP_FreeProperty(idprop); + MEM_freeN(idprop); + } + } +} + static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop) { if (prop->magic == RNA_MAGIC) { @@ -477,7 +491,7 @@ static const char *rna_ensure_property_description(PropertyRNA *prop) description = ((IDProperty *)prop)->name; /* XXX - not correct */ } - return TIP_(description); + return description; } static const char *rna_ensure_property_name(PropertyRNA *prop) @@ -489,7 +503,7 @@ static const char *rna_ensure_property_name(PropertyRNA *prop) else name = ((IDProperty *)prop)->name; - return CTX_IFACE_(prop->translation_context, name); + return name; } /* Structs */ @@ -515,6 +529,11 @@ const char *RNA_struct_ui_name(StructRNA *type) return CTX_IFACE_(type->translation_context, type->name); } +const char *RNA_struct_ui_name_raw(StructRNA *type) +{ + return type->name; +} + int RNA_struct_ui_icon(StructRNA *type) { if (type) @@ -528,6 +547,11 @@ const char *RNA_struct_ui_description(StructRNA *type) return TIP_(type->description); } +const char *RNA_struct_ui_description_raw(StructRNA *type) +{ + return type->description; +} + const char *RNA_struct_translation_context(StructRNA *type) { return type->translation_context ? type->translation_context : BLF_I18NCONTEXT_DEFAULT; @@ -778,7 +802,7 @@ const char *RNA_property_identifier(PropertyRNA *prop) const char *RNA_property_description(PropertyRNA *prop) { - return rna_ensure_property_description(prop); + return TIP_(rna_ensure_property_description(prop)); } PropertyType RNA_property_type(PropertyRNA *prop) @@ -1401,11 +1425,21 @@ int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, Property const char *RNA_property_ui_name(PropertyRNA *prop) { + return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop)); +} + +const char *RNA_property_ui_name_raw(PropertyRNA *prop) +{ return rna_ensure_property_name(prop); } const char *RNA_property_ui_description(PropertyRNA *prop) { + return TIP_(rna_ensure_property_description(prop)); +} + +const char *RNA_property_ui_description_raw(PropertyRNA *prop) +{ return rna_ensure_property_description(prop); } @@ -4797,6 +4831,13 @@ bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop) } } +void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop) +{ + if (prop->flag & PROP_IDPROPERTY) { + rna_idproperty_free(ptr, prop->identifier); + } +} + bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost) { PropertyRNA *prop = RNA_struct_find_property(ptr, identifier); @@ -4825,6 +4866,15 @@ bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier) } } +void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier) +{ + PropertyRNA *prop = RNA_struct_find_property(ptr, identifier); + + if (prop) { + RNA_property_unset(ptr, prop); + } +} + bool RNA_property_is_idprop(PropertyRNA *prop) { return (prop->magic != RNA_MAGIC); @@ -5190,6 +5240,11 @@ const char *RNA_function_identifier(FunctionRNA *func) const char *RNA_function_ui_description(FunctionRNA *func) { + return TIP_(func->description); +} + +const char *RNA_function_ui_description_raw(FunctionRNA *func) +{ return func->description; } diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 74d212fae57..49e1122bf18 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -298,7 +298,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * for (node = ntree->nodes.first; node; node = node->next) { if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { - ED_node_generic_update(bmain, ntree, node); + ED_node_tag_update_nodetree(bmain, ntree); } } } diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index c92777af8fd..61e67ad3298 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -458,6 +458,78 @@ static int rna_validate_identifier(const char *identifier, char *error, int prop return 1; } +void RNA_identifier_sanitize(char *identifier, int property) +{ + int a = 0; + + /* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */ + static const char *kwlist[] = { + /* "False", "None", "True", */ + "and", "as", "assert", "break", + "class", "continue", "def", "del", "elif", "else", "except", + "finally", "for", "from", "global", "if", "import", "in", + "is", "lambda", "nonlocal", "not", "or", "pass", "raise", + "return", "try", "while", "with", "yield", NULL + }; + + + if (!isalpha(identifier[0])) { + /* first character failed isalpha() check */ + identifier[0] = '_'; + } + + for (a = 0; identifier[a]; a++) { + if (DefRNA.preprocess && property) { + if (isalpha(identifier[a]) && isupper(identifier[a])) { + /* property names must contain lower case characters only */ + identifier[a] = tolower(identifier[a]); + } + } + + if (identifier[a] == '_') { + continue; + } + + if (identifier[a] == ' ') { + /* spaces are not okay in identifier names */ + identifier[a] = '_'; + } + + if (isalnum(identifier[a]) == 0) { + /* one of the characters failed an isalnum() check and is not an underscore */ + identifier[a] = '_'; + } + } + + for (a = 0; kwlist[a]; a++) { + if (strcmp(identifier, kwlist[a]) == 0) { + /* this keyword is reserved by python. + * just replace the last character by '_' to keep it readable. + */ + identifier[strlen(identifier)-1] = '_'; + break; + } + } + + if (property) { + static const char *kwlist_prop[] = { + /* not keywords but reserved all the same because py uses */ + "keys", "values", "items", "get", + NULL + }; + + for (a = 0; kwlist_prop[a]; a++) { + if (strcmp(identifier, kwlist_prop[a]) == 0) { + /* this keyword is reserved by python. + * just replace the last character by '_' to keep it readable. + */ + identifier[strlen(identifier)-1] = '_'; + break; + } + } + } +} + /* Blender Data Definition */ BlenderRNA *RNA_create(void) diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 912f4d914cb..7fee67cd569 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -42,6 +42,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_texture.h" @@ -169,14 +170,14 @@ static void rna_Lamp_spot_size_set(PointerRNA *ptr, float value) la->spotsize = RAD2DEGF(value); } -static void rna_Lamp_use_nodes_update(Main *blain, Scene *scene, PointerRNA *ptr) +static void rna_Lamp_use_nodes_update(bContext *C, PointerRNA *ptr) { Lamp *la = (Lamp *)ptr->data; if (la->use_nodes && la->nodetree == NULL) - ED_node_shader_default(scene, &la->id); + ED_node_shader_default(C, &la->id); - rna_Lamp_update(blain, scene, ptr); + rna_Lamp_update(CTX_data_main(C), CTX_data_scene(C), ptr); } #else @@ -414,6 +415,7 @@ static void rna_def_lamp(BlenderRNA *brna) prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the lamp"); RNA_def_property_update(prop, 0, "rna_Lamp_use_nodes_update"); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 4d5d4d4a7cd..a79fa1aaed4 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -235,23 +235,32 @@ static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerR } } -static bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type) +static EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) { - bNodeTree *tree = ntreeAddTree(bmain, name, type, NODE_GROUP); - - id_us_min(&tree->id); - return tree; + return rna_node_tree_type_itemf(NULL, NULL, free); +} +static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type) +{ + bNodeTreeType *typeinfo = rna_node_tree_type_from_enum(type); + if (typeinfo) { + bNodeTree *ntree = ntreeAddTree(bmain, name, typeinfo->idname); + + id_us_min(&ntree->id); + return ntree; + } + else + return NULL; } -static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *tree_ptr) +static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *ntree_ptr) { - bNodeTree *tree = tree_ptr->data; - if (ID_REAL_USERS(tree) <= 0) { - BKE_libblock_free(&bmain->nodetree, tree); - RNA_POINTER_INVALIDATE(tree_ptr); + bNodeTree *ntree = ntree_ptr->data; + if (ID_REAL_USERS(ntree) <= 0) { + BKE_libblock_free(&bmain->nodetree, ntree); + RNA_POINTER_INVALIDATE(ntree_ptr); } else { BKE_reportf(reports, RPT_ERROR, "Node tree '%s' must have zero users to be removed, found %d", - tree->id.name + 2, ID_REAL_USERS(tree)); + ntree->id.name + 2, ID_REAL_USERS(ntree)); } } @@ -1069,10 +1078,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop) PropertyRNA *parm; PropertyRNA *prop; - static EnumPropertyItem node_nodetree_items[] = { - {0, "SHADER", 0, "Shader", ""}, - {1, "COMPOSITE", 0, "Composite", ""}, - {2, "TEXTURE", 0, "Texture", ""}, + static EnumPropertyItem dummy_items[] = { + {0, "DUMMY", 0, "", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1085,7 +1092,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Add a new node tree to the main database"); parm = RNA_def_string(func, "name", "NodeGroup", 0, "", "New name for the datablock"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_enum(func, "type", node_nodetree_items, 0, "Type", "The type of node_group to add"); + parm = RNA_def_enum(func, "type", dummy_items, 0, "Type", "The type of node_group to add"); + RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_Main_nodetree_type_itemf"); RNA_def_property_flag(parm, PROP_REQUIRED); /* return type */ parm = RNA_def_pointer(func, "tree", "NodeTree", "", "New node tree datablock"); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index d1c81200e6a..57ae217cff6 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -82,6 +82,7 @@ EnumPropertyItem ramp_blend_items[] = { #include "DNA_node_types.h" #include "DNA_object_types.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_material.h" @@ -111,7 +112,7 @@ static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA * Material *ma = ptr->id.data; if (ma->nodetree) - ntreeClearPreview(ma->nodetree); + BKE_node_preview_clear_tree(ma->nodetree); WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma); } @@ -287,14 +288,14 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value) ma->ramp_spec = add_colorband(0); } -static void rna_Material_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Material_use_nodes_update(bContext *C, PointerRNA *ptr) { Material *ma = (Material *)ptr->data; if (ma->use_nodes && ma->nodetree == NULL) - ED_node_shader_default(scene, &ma->id); + ED_node_shader_default(C, &ma->id); - rna_Material_update(bmain, scene, ptr); + rna_Material_update(CTX_data_main(C), CTX_data_scene(C), ptr); } static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED(C), PointerRNA *ptr, @@ -2024,6 +2025,7 @@ void RNA_def_material(BlenderRNA *brna) prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the material"); RNA_def_property_update(prop, 0, "rna_Material_use_nodes_update"); 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", ©node); + 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 */ diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h deleted file mode 100644 index b7ec9235483..00000000000 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Robin Allen - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/makesrna/intern/rna_nodetree_types.h - * \ingroup RNA - */ - -/* intentionally no include guard */ - -/* Empty definitions for undefined macros to avoid warnings */ -#ifndef DefNode -#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) -#endif - -/* WARNING! If you edit those strings, please do the same in relevant nodes files (under blender/nodes/...)! */ - -/* Tree type Node ID RNA def function Enum name Struct name UI Name UI Description */ -DefNode( ShaderNode, SH_NODE_OUTPUT, 0, "OUTPUT", Output, "Output", "" ) -DefNode( ShaderNode, SH_NODE_MATERIAL, def_sh_material, "MATERIAL", Material, "Material", "" ) -DefNode( ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) -DefNode( ShaderNode, SH_NODE_VALUE, 0, "VALUE", Value, "Value", "" ) -DefNode( ShaderNode, SH_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "" ) -DefNode( ShaderNode, SH_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" ) -DefNode( ShaderNode, SH_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" ) -DefNode( ShaderNode, SH_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" ) -DefNode( ShaderNode, SH_NODE_NORMAL, 0, "NORMAL", Normal, "Normal", "" ) -DefNode( ShaderNode, SH_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" ) -DefNode( ShaderNode, SH_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright Contrast", "" ) -DefNode( ShaderNode, SH_NODE_GEOMETRY, def_sh_geometry, "GEOMETRY", Geometry, "Geometry", "" ) -DefNode( ShaderNode, SH_NODE_MAPPING, def_sh_mapping, "MAPPING", Mapping, "Mapping", "" ) -DefNode( ShaderNode, SH_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", VectorCurve, "Vector Curves", "" ) -DefNode( ShaderNode, SH_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", RGBCurve, "RGB Curves", "" ) -DefNode( ShaderNode, SH_NODE_CAMERA, 0, "CAMERA", CameraData, "Camera Data", "" ) -DefNode( ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" ) -DefNode( ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" ) -DefNode( ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" ) -DefNode( ShaderNode, SH_NODE_MATERIAL_EXT, def_sh_material, "MATERIAL_EXT", ExtendedMaterial, "Extended Material", "" ) -DefNode( ShaderNode, SH_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" ) -DefNode( ShaderNode, SH_NODE_SEPRGB, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" ) -DefNode( ShaderNode, SH_NODE_COMBRGB, 0, "COMBRGB", CombineRGB, "Combine RGB", "" ) -DefNode( ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" ) - -DefNode( ShaderNode, SH_NODE_OUTPUT_MATERIAL, 0, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" ) -DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, 0, "OUTPUT_LAMP", OutputLamp, "Lamp Output", "" ) -DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, 0, "OUTPUT_WORLD", OutputWorld, "World Output", "" ) -DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" ) -DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "LayerWeight", "" ) -DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" ) -DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" ) -DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" ) -DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" ) -DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" ) -DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" ) -DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume","" ) -DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" ) -DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" ) -DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" ) -DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" ) -DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) -DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) -DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) -DefNode( ShaderNode, SH_NODE_HAIR_INFO, 0, "HAIR_INFO", HairInfo, "Hair Info", "" ) -DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" ) -DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" ) -DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" ) -DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" ) -DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" ) -DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_GRADIENT, def_sh_tex_gradient, "TEX_GRADIENT", TexGradient, "Gradient Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_NOISE, def_sh_tex_noise, "TEX_NOISE", TexNoise, "Noise Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_MAGIC, def_sh_tex_magic, "TEX_MAGIC", TexMagic, "Magic Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TEX_WAVE", TexWave, "Wave Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" ) - -DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) -DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) -DefNode( CompositorNode, CMP_NODE_VALUE, 0, "VALUE", Value, "Value", "" ) -DefNode( CompositorNode, CMP_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "Mix", "" ) -DefNode( CompositorNode, CMP_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" ) -DefNode( CompositorNode, CMP_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" ) -DefNode( CompositorNode, CMP_NODE_NORMAL, 0, "NORMAL", Normal, "Normal", "" ) -DefNode( CompositorNode, CMP_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", CurveVec, "Vector Curves", "" ) -DefNode( CompositorNode, CMP_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curves", "" ) -DefNode( CompositorNode, CMP_NODE_ALPHAOVER, def_cmp_alpha_over, "ALPHAOVER", AlphaOver, "Alpha Over", "" ) -DefNode( CompositorNode, CMP_NODE_BLUR, def_cmp_blur, "BLUR", Blur, "Blur", "" ) -DefNode( CompositorNode, CMP_NODE_FILTER, def_cmp_filter, "FILTER", Filter, "Filter", "" ) -DefNode( CompositorNode, CMP_NODE_MAP_VALUE, def_cmp_map_value, "MAP_VALUE", MapValue, "Map Value", "" ) -DefNode( CompositorNode, CMP_NODE_MAP_RANGE, def_cmp_map_range, "MAP_RANGE", MapRange, "Map Range", "" ) -DefNode( CompositorNode, CMP_NODE_TIME, def_time, "TIME", Time, "Time", "" ) -DefNode( CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBLUR", VecBlur, "Vector Blur", "" ) -DefNode( CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" ) -DefNode( CompositorNode, CMP_NODE_SEPHSVA, 0, "SEPHSVA", SepHSVA, "Separate HSVA", "" ) -DefNode( CompositorNode, CMP_NODE_SETALPHA, 0, "SETALPHA", SetAlpha, "Set Alpha", "" ) -DefNode( CompositorNode, CMP_NODE_HUE_SAT, def_cmp_hue_saturation, "HUE_SAT", HueSat, "Hue Saturation Value","" ) -DefNode( CompositorNode, CMP_NODE_IMAGE, def_cmp_image, "IMAGE", Image, "Image", "" ) -DefNode( CompositorNode, CMP_NODE_R_LAYERS, def_cmp_render_layers, "R_LAYERS", RLayers, "Render Layers", "" ) -DefNode( CompositorNode, CMP_NODE_COMPOSITE, def_cmp_composite, "COMPOSITE", Composite, "Composite", "" ) -DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, def_cmp_output_file, "OUTPUT_FILE", OutputFile, "File Output", "" ) -DefNode( CompositorNode, CMP_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" ) -DefNode( CompositorNode, CMP_NODE_TRANSLATE, def_cmp_translate, "TRANSLATE", Translate, "Translate", "" ) -DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" ) -DefNode( CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" ) -DefNode( CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" ) -DefNode( CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAINT", Inpaint, "Inpaint", "" ) -DefNode( CompositorNode, CMP_NODE_DESPECKLE, def_cmp_despeckle, "DESPECKLE", Despeckle, "Despeckle", "" ) -DefNode( CompositorNode, CMP_NODE_ROTATE, def_cmp_rotate, "ROTATE", Rotate, "Rotate", "" ) -DefNode( CompositorNode, CMP_NODE_SCALE, def_cmp_scale, "SCALE", Scale, "Scale", "" ) -DefNode( CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCbCrA", "" ) -DefNode( CompositorNode, CMP_NODE_COMBYCCA, def_cmp_ycc, "COMBYCCA", CombYCCA, "Combine YCbCrA", "" ) -DefNode( CompositorNode, CMP_NODE_SEPYUVA, 0, "SEPYUVA", SepYUVA, "Separate YUVA", "" ) -DefNode( CompositorNode, CMP_NODE_COMBYUVA, 0, "COMBYUVA", CombYUVA, "Combine YUVA", "" ) -DefNode( CompositorNode, CMP_NODE_DIFF_MATTE, def_cmp_diff_matte, "DIFF_MATTE", DiffMatte, "Difference Key", "" ) -DefNode( CompositorNode, CMP_NODE_COLOR_SPILL, def_cmp_color_spill, "COLOR_SPILL", ColorSpill, "Color Spill", "" ) -DefNode( CompositorNode, CMP_NODE_CHROMA_MATTE, def_cmp_chroma_matte, "CHROMA_MATTE", ChromaMatte, "Chroma Key", "" ) -DefNode( CompositorNode, CMP_NODE_CHANNEL_MATTE, def_cmp_channel_matte, "CHANNEL_MATTE", ChannelMatte, "Channel Key", "" ) -DefNode( CompositorNode, CMP_NODE_FLIP, def_cmp_flip, "FLIP", Flip, "Flip", "" ) -DefNode( CompositorNode, CMP_NODE_SPLITVIEWER, def_cmp_splitviewer, "SPLITVIEWER", SplitViewer, "Split Viewer", "" ) -DefNode( CompositorNode, CMP_NODE_MAP_UV, def_cmp_map_uv, "MAP_UV", MapUV, "Map UV", "" ) -DefNode( CompositorNode, CMP_NODE_ID_MASK, def_cmp_id_mask, "ID_MASK", IDMask, "ID Mask", "" ) -DefNode( CompositorNode, CMP_NODE_DOUBLEEDGEMASK, def_cmp_double_edge_mask,"DOUBLEEDGEMASK", DoubleEdgeMask, "Double Edge Mask", "" ) -DefNode( CompositorNode, CMP_NODE_DEFOCUS, def_cmp_defocus, "DEFOCUS", Defocus, "Defocus", "" ) -DefNode( CompositorNode, CMP_NODE_DISPLACE, 0, "DISPLACE", Displace, "Displace", "" ) -DefNode( CompositorNode, CMP_NODE_COMBHSVA, 0, "COMBHSVA", CombHSVA, "Combine HSVA", "" ) -DefNode( CompositorNode, CMP_NODE_MATH, def_math, "MATH", Math, "Math", "" ) -DefNode( CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luminance Key", "" ) -DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" ) -DefNode( CompositorNode, CMP_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" ) -DefNode( CompositorNode, CMP_NODE_INVERT, def_cmp_invert, "INVERT", Invert, "Invert", "" ) -DefNode( CompositorNode, CMP_NODE_NORMALIZE, 0, "NORMALIZE", Normalize, "Normalize", "" ) -DefNode( CompositorNode, CMP_NODE_CROP, def_cmp_crop, "CROP", Crop, "Crop", "" ) -DefNode( CompositorNode, CMP_NODE_DBLUR, def_cmp_dblur, "DBLUR", DBlur, "Directional Blur", "" ) -DefNode( CompositorNode, CMP_NODE_BILATERALBLUR, def_cmp_bilateral_blur, "BILATERALBLUR", Bilateralblur, "Bilateral Blur", "" ) -DefNode( CompositorNode, CMP_NODE_PREMULKEY, def_cmp_premul_key, "PREMULKEY", PremulKey, "Alpha Convert", "" ) -DefNode( CompositorNode, CMP_NODE_GLARE, def_cmp_glare, "GLARE", Glare, "Glare", "" ) -DefNode( CompositorNode, CMP_NODE_TONEMAP, def_cmp_tonemap, "TONEMAP", Tonemap, "Tonemap", "" ) -DefNode( CompositorNode, CMP_NODE_LENSDIST, def_cmp_lensdist, "LENSDIST", Lensdist, "Lens Distortion", "" ) -DefNode( CompositorNode, CMP_NODE_VIEW_LEVELS, def_cmp_levels, "LEVELS", Levels, "Levels", "" ) -DefNode( CompositorNode, CMP_NODE_COLOR_MATTE, def_cmp_color_matte, "COLOR_MATTE", ColorMatte, "Color Key", "" ) -DefNode( CompositorNode, CMP_NODE_DIST_MATTE, def_cmp_distance_matte, "DISTANCE_MATTE", DistanceMatte, "Distance Key", "" ) -DefNode( CompositorNode, CMP_NODE_COLORBALANCE, def_cmp_colorbalance, "COLORBALANCE", ColorBalance, "Color Balance", "" ) -DefNode( CompositorNode, CMP_NODE_HUECORRECT, def_cmp_huecorrect, "HUECORRECT", HueCorrect, "Hue Correct", "" ) -DefNode( CompositorNode, CMP_NODE_MOVIECLIP, def_cmp_movieclip, "MOVIECLIP", MovieClip, "Movie Clip", "" ) -DefNode( CompositorNode, CMP_NODE_TRANSFORM, dev_cmd_transform, "TRANSFORM", Transform, "Transform", "" ) -DefNode( CompositorNode, CMP_NODE_STABILIZE2D, def_cmp_stabilize2d, "STABILIZE2D", Stabilize, "Stabilize 2D", "" ) -DefNode( CompositorNode, CMP_NODE_MOVIEDISTORTION,def_cmp_moviedistortion,"MOVIEDISTORTION",MovieDistortion, "Movie Distortion", "" ) -DefNode( CompositorNode, CMP_NODE_MASK_BOX, def_cmp_boxmask, "BOXMASK", BoxMask, "Box Mask", "" ) -DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIPSEMASK", EllipseMask, "Ellipse Mask", "" ) -DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE", BokehImage, "Bokeh Image", "" ) -DefNode( CompositorNode, CMP_NODE_BOKEHBLUR, def_cmp_bokehblur, "BOKEHBLUR", BokehBlur, "Bokeh Blur", "" ) -DefNode( CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH", Switch, "Switch", "" ) -DefNode( CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "Color Correction", "" ) -DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) -DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYINGSCREEN", KeyingScreen, "Keying Screen", "" ) -DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" ) -DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" ) -DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" ) - -DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) -DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) -DefNode( TextureNode, TEX_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" ) -DefNode( TextureNode, TEX_NODE_BRICKS, def_tex_bricks, "BRICKS", Bricks, "Bricks", "" ) -DefNode( TextureNode, TEX_NODE_MATH, def_math, "MATH", Math, "Math", "" ) -DefNode( TextureNode, TEX_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "Mix RGB", "" ) -DefNode( TextureNode, TEX_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" ) -DefNode( TextureNode, TEX_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" ) -DefNode( TextureNode, TEX_NODE_IMAGE, def_tex_image, "IMAGE", Image, "Image", "" ) -DefNode( TextureNode, TEX_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curves", "" ) -DefNode( TextureNode, TEX_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" ) -DefNode( TextureNode, TEX_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" ) -DefNode( TextureNode, TEX_NODE_CURVE_TIME, def_time, "CURVE_TIME", CurveTime, "Curve Time", "" ) -DefNode( TextureNode, TEX_NODE_ROTATE, 0, "ROTATE", Rotate, "Rotate", "" ) -DefNode( TextureNode, TEX_NODE_VIEWER, 0, "VIEWER", Viewer, "Viewer", "" ) -DefNode( TextureNode, TEX_NODE_TRANSLATE, 0, "TRANSLATE", Translate, "Translate", "" ) -DefNode( TextureNode, TEX_NODE_COORD, 0, "COORD", Coordinates, "Coordinates", "" ) -DefNode( TextureNode, TEX_NODE_DISTANCE, 0, "DISTANCE", Distance, "Distance", "" ) -DefNode( TextureNode, TEX_NODE_COMPOSE, 0, "COMPOSE", Compose, "Combine RGBA", "" ) -DefNode( TextureNode, TEX_NODE_DECOMPOSE, 0, "DECOMPOSE", Decompose, "Separate RGBA", "" ) -DefNode( TextureNode, TEX_NODE_VALTONOR, 0, "VALTONOR", ValToNor, "Value to Normal", "" ) -DefNode( TextureNode, TEX_NODE_SCALE, 0, "SCALE", Scale, "Scale", "" ) - - -/* undefine macros */ -#undef DefNode diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d556cc0dcdc..e03e7d222c6 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1173,13 +1173,12 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po rna_Scene_glsl_update(bmain, activescene, ptr); } -static void rna_Scene_use_nodes_set(PointerRNA *ptr, int value) +static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; - scene->use_nodes = value; if (scene->use_nodes && scene->nodetree == NULL) - ED_node_composit_default(scene); + ED_node_composit_default(C, scene); } static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -4533,9 +4532,9 @@ void RNA_def_scene(BlenderRNA *brna) prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1); - RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_use_nodes_set"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Enable the compositing node tree"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_nodes_update"); /* Sequencer */ prop = RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d88e8ed782a..f365352ca30 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -25,6 +25,7 @@ */ #include <stdlib.h> +#include <string.h> #include "MEM_guardedalloc.h" @@ -32,6 +33,7 @@ #include "BKE_key.h" #include "BKE_movieclip.h" +#include "BKE_node.h" #include "DNA_action_types.h" #include "DNA_key_types.h" @@ -1014,20 +1016,91 @@ static void rna_BackgroundImage_clear(View3D *v3d) /* Space Node Editor */ -static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, PointerRNA value) +static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr, const PointerRNA value) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + ED_node_tree_start(snode, (bNodeTree *)value.data, NULL, NULL); +} + +static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA value) { SpaceNode *snode = (SpaceNode *)ptr->data; bNodeTree *ntree = (bNodeTree *)value.data; - /* exclude group trees, only trees of the active type */ - return (ntree->nodetype == 0 && ntree->type == snode->treetype); + /* node tree type must match the selected type in node editor */ + return (strcmp(snode->tree_idname, ntree->idname) == 0); } -static void rna_SpaceNodeEditor_node_tree_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA *UNUSED(ptr)) { - SpaceNode *snode = (SpaceNode *)ptr->data; + ED_node_tree_update(C); +} + +static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr) +{ + SpaceNode *snode= (SpaceNode*)ptr->data; + return rna_node_tree_idname_to_enum(snode->tree_idname); +} +static void rna_SpaceNodeEditor_tree_type_set(PointerRNA *ptr, int value) +{ + SpaceNode *snode= (SpaceNode*)ptr->data; + ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value)); +} +static int rna_SpaceNodeEditor_tree_type_poll(void *Cv, bNodeTreeType *type) +{ + bContext *C = (bContext *)Cv; + if (type->poll) + return type->poll(C, type); + else + return TRUE; +} +static EnumPropertyItem *rna_SpaceNodeEditor_tree_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) +{ + return rna_node_tree_type_itemf(C, rna_SpaceNodeEditor_tree_type_poll, free); +} + +static void rna_SpaceNodeEditor_path_get(PointerRNA *ptr, char *value) +{ + SpaceNode *snode = ptr->data; + ED_node_tree_path_get(snode, value); +} + +static int rna_SpaceNodeEditor_path_length(PointerRNA *ptr) +{ + SpaceNode *snode = ptr->data; + return ED_node_tree_path_length(snode); +} + +void rna_SpaceNodeEditor_path_clear(SpaceNode *snode, bContext *C) +{ + ED_node_tree_start(snode, NULL, NULL, NULL); + ED_node_tree_update(C); +} + +void rna_SpaceNodeEditor_path_start(SpaceNode *snode, bContext *C, PointerRNA *node_tree) +{ + ED_node_tree_start(snode, (bNodeTree *)node_tree->data, NULL, NULL); + ED_node_tree_update(C); +} + +void rna_SpaceNodeEditor_path_push(SpaceNode *snode, bContext *C, ReportList *reports, PointerRNA *node) +{ + PointerRNA tree_ptr; + + tree_ptr = RNA_pointer_get(node, "node_tree"); + if (!tree_ptr.data) { + BKE_reportf(reports, RPT_WARNING, "Missing node group tree in node %s", ((bNode *)node->data)->name); + return; + } - ED_node_tree_update(snode, scene); + ED_node_tree_push(snode, (bNodeTree *)tree_ptr.data, (bNode *)node->data); + ED_node_tree_update(C); +} + +void rna_SpaceNodeEditor_path_pop(SpaceNode *snode, bContext *C) +{ + ED_node_tree_pop(snode); + ED_node_tree_update(C); } static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, PointerRNA *UNUSED(ptr), @@ -3077,6 +3150,58 @@ static void rna_def_space_userpref(BlenderRNA *brna) } +static void rna_def_node_tree_path(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "NodeTreePath", NULL); + RNA_def_struct_sdna(srna, "bNodeTreePath"); + RNA_def_struct_ui_text(srna, "Node Tree Path", "Element of the node space tree path"); + + prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context"); +} + +static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop, *parm; + FunctionRNA *func; + + RNA_def_property_srna(cprop, "SpaceNodeEditorPath"); + srna = RNA_def_struct(brna, "SpaceNodeEditorPath", NULL); + RNA_def_struct_sdna(srna, "SpaceNode"); + RNA_def_struct_ui_text(srna, "Space Node Editor Path", "History of node trees in the editor"); + + prop = RNA_def_property(srna, "to_string", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_SpaceNodeEditor_path_get", "rna_SpaceNodeEditor_path_length", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_ui_text(srna, "Path", "Get the node tree path as a string"); + + func = RNA_def_function(srna, "clear", "rna_SpaceNodeEditor_path_clear"); + RNA_def_function_ui_description(func, "Reset the node tree path"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + + func = RNA_def_function(srna, "start", "rna_SpaceNodeEditor_path_start"); + RNA_def_function_ui_description(func, "Set the root node tree"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", ""); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR); + + func = RNA_def_function(srna, "push", "rna_SpaceNodeEditor_path_push"); + RNA_def_function_ui_description(func, "Append a node group tree to the path"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "node", "NodeGroup", "Node", "Group node"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR); + + func = RNA_def_function(srna, "pop", "rna_SpaceNodeEditor_path_pop"); + RNA_def_function_ui_description(func, "Remove the last node tree from the path"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); +} + static void rna_def_space_node(BlenderRNA *brna) { StructRNA *srna; @@ -3106,13 +3231,17 @@ static void rna_def_space_node(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem dummy_items[] = { + {0, "DUMMY", 0, "", ""}, + {0, NULL, 0, NULL, NULL}}; + srna = RNA_def_struct(brna, "SpaceNodeEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceNode"); RNA_def_struct_ui_text(srna, "Space Node Editor", "Node editor space data"); prop = RNA_def_property(srna, "tree_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "treetype"); - RNA_def_property_enum_items(prop, nodetree_type_items); + RNA_def_property_enum_items(prop, dummy_items); + RNA_def_property_enum_funcs(prop, "rna_SpaceNodeEditor_tree_type_get", "rna_SpaceNodeEditor_tree_type_set", "rna_SpaceNodeEditor_tree_type_itemf"); RNA_def_property_ui_text(prop, "Tree Type", "Node tree type to display and edit"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL); @@ -3137,17 +3266,29 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "ID From", "Datablock from which the edited datablock is linked"); + prop= RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL); + RNA_def_property_struct_type(prop, "NodeTreePath"); + RNA_def_property_ui_text(prop, "Node Tree Path", "Path from the data block to the currently edited node tree"); + rna_def_space_node_path_api(brna, prop); + prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceNodeEditor_node_tree_set", NULL, "rna_SpaceNodeEditor_node_tree_poll"); RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); - RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_SpaceNodeEditor_node_tree_poll"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Node Tree", "Node tree being displayed"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE); + RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, "rna_SpaceNodeEditor_node_tree_update"); - prop = RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE); + prop= RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "edittree"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Edit Tree", "Edited node tree"); + RNA_def_property_ui_text(prop, "Edit Tree", "Node tree being displayed and edited"); + + prop= RNA_def_property(srna, "pin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_PIN); + RNA_def_property_ui_text(prop, "Pinned", "Use the pinned node tree"); + RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NODE, NULL); prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_BACKDRAW); @@ -3544,6 +3685,7 @@ void RNA_def_space(BlenderRNA *brna) rna_def_console_line(brna); rna_def_space_info(brna); rna_def_space_userpref(brna); + rna_def_node_tree_path(brna); rna_def_space_node(brna); rna_def_space_logic(brna); rna_def_space_clip(brna); diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index d86e5fd0d9c..009823555f0 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -107,6 +107,7 @@ EnumPropertyItem blend_type_items[] = { #include "RNA_access.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_image.h" #include "BKE_texture.h" @@ -167,7 +168,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt } else if (GS(id->name) == ID_NT) { bNodeTree *ntree = ptr->id.data; - ED_node_generic_update(bmain, ntree, NULL); + ED_node_tag_update_nodetree(bmain, ntree); } } @@ -384,15 +385,18 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value) tex->coba = add_colorband(0); } -static void rna_Texture_use_nodes_set(PointerRNA *ptr, int v) +static void rna_Texture_use_nodes_update(bContext *C, PointerRNA *ptr) { Tex *tex = (Tex *)ptr->data; - tex->use_nodes = v; - tex->type = 0; + if (tex->use_nodes) { + tex->type = 0; + + if (tex->nodetree == NULL) + ED_node_texture_default(C, tex); + } - if (v && tex->nodetree == NULL) - ED_node_texture_default(tex); + rna_Texture_nodes_update(CTX_data_main(C), CTX_data_scene(C), ptr); } static void rna_ImageTexture_mipmap_set(PointerRNA *ptr, int value) @@ -2021,9 +2025,9 @@ static void rna_def_texture(BlenderRNA *brna) /* nodetree */ prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1); - RNA_def_property_boolean_funcs(prop, NULL, "rna_Texture_use_nodes_set"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Make this a node-based texture"); - RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + RNA_def_property_update(prop, 0, "rna_Texture_use_nodes_update"); prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 0204fa5367b..41d1411d35c 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -419,6 +419,8 @@ void RNA_api_ui_layout(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; + static float node_socket_color_default[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + /* simple layout specifiers */ func = RNA_def_function(srna, "row", "uiLayoutRow"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); @@ -829,6 +831,14 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_pointer(func, "item", "KeyMapItem", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); + func = RNA_def_function(srna, "template_component_menu", "uiTemplateComponentMenu"); + RNA_def_function_ui_description(func, "Item. Display expanded property in a popup menu"); + parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property"); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data"); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_string(func, "name", "", 0, "", ""); + func = RNA_def_function(srna, "introspect", "uiLayoutIntrospect"); parm = RNA_def_string(func, "string", "", 1024 * 1024, "Descr", "DESCR"); RNA_def_function_return(func, parm); @@ -843,6 +853,12 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); /* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */ + + /* node socket icon */ + func = RNA_def_function(srna, "template_node_socket", "uiTemplateNodeSocket"); + RNA_def_function_ui_description(func, "Node Socket Icon"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_float_array(func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f); } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 3824ee28956..12fac82fb75 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1884,6 +1884,12 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Group Node", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop= RNA_def_property(srna, "group_socket_node", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "console_output"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Group Socket Node", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "frame_node", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "movie"); RNA_def_property_array(prop, 4); diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 02a04d36c23..b689a82c231 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -42,6 +42,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_texture.h" @@ -121,14 +122,14 @@ static void rna_World_stars_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po WM_main_add_notifier(NC_WORLD | ND_WORLD_STARS, wo); } -static void rna_World_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr) { World *wrld = (World *)ptr->data; if (wrld->use_nodes && wrld->nodetree == NULL) - ED_node_shader_default(scene, &wrld->id); + ED_node_shader_default(C, &wrld->id); - rna_World_update(bmain, scene, ptr); + rna_World_update(CTX_data_main(C), CTX_data_scene(C), ptr); } #else @@ -581,6 +582,7 @@ void RNA_def_world(BlenderRNA *brna) prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the world"); RNA_def_property_update(prop, 0, "rna_World_use_nodes_update"); |