diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-03-19 02:37:04 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-03-19 02:37:04 +0400 |
commit | ae25aa22105b060294095357692f2aed4c650ce8 (patch) | |
tree | 06548276f86326f21943f8ec7ef92765a97b5ab5 | |
parent | 29b7b344fc48ed31b1e36818ab4767090691d6e2 (diff) | |
parent | 03762409cd4f812d152e42de9c4f9853df91be0b (diff) |
svn merge ^/trunk/blender -r55372:55392
314 files changed, 13573 insertions, 9037 deletions
diff --git a/doc/python_api/examples/bpy.types.NodeTree.py b/doc/python_api/examples/bpy.types.NodeTree.py new file mode 100644 index 00000000000..401b3a01ae0 --- /dev/null +++ b/doc/python_api/examples/bpy.types.NodeTree.py @@ -0,0 +1,23 @@ +""" +Poll Function ++++++++++++++++ +The :class:`NodeTree.poll` function determines if a node tree is visible +in the given context (similar to how :class:`Panel.poll` +and :class:`Menu.poll` define visibility). If it returns False, +the node tree type will not be selectable in the node editor. + +A typical condition for shader nodes would be to check the active render engine +of the scene and only show nodes of the renderer they are designed for. +""" +import bpy + + +class CyclesNodeTree(bpy.types.NodeTree): + """ This operator is only visible when Cycles is the selected render engine""" + bl_label = "Cycles Node Tree" + + @classmethod + def poll(cls, context): + return context.scene.render.engine == 'CYCLES' + +bpy.utils.register_class(CyclesNodeTree) diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index a10f3b63033..f7a05463f66 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -207,6 +207,7 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args) } #ifdef WITH_OSL + static PyObject *osl_update_node_func(PyObject *self, PyObject *args) { PyObject *pynodegroup, *pynode; @@ -248,17 +249,19 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) continue; /* determine socket type */ - BL::NodeSocket::type_enum socket_type; - float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + std::string socket_type; + BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE; + float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f); float default_float = 0.0f; int default_int = 0; std::string default_string = ""; if(param->isclosure) { - socket_type = BL::NodeSocket::type_SHADER; + socket_type = "NodeSocketShader"; } else if(param->type.vecsemantics == TypeDesc::COLOR) { - socket_type = BL::NodeSocket::type_RGBA; + socket_type = "NodeSocketColor"; + data_type = BL::NodeSocket::type_RGBA; if(param->validdefault) { default_float4[0] = param->fdefault[0]; @@ -269,7 +272,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) else if(param->type.vecsemantics == TypeDesc::POINT || param->type.vecsemantics == TypeDesc::VECTOR || param->type.vecsemantics == TypeDesc::NORMAL) { - socket_type = BL::NodeSocket::type_VECTOR; + socket_type = "NodeSocketVector"; + data_type = BL::NodeSocket::type_VECTOR; if(param->validdefault) { default_float4[0] = param->fdefault[0]; @@ -279,17 +283,20 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) } else if(param->type.aggregate == TypeDesc::SCALAR) { if(param->type.basetype == TypeDesc::INT) { - socket_type = BL::NodeSocket::type_INT; + socket_type = "NodeSocketInt"; + data_type = BL::NodeSocket::type_INT; if(param->validdefault) default_int = param->idefault[0]; } else if(param->type.basetype == TypeDesc::FLOAT) { - socket_type = BL::NodeSocket::type_VALUE; + socket_type = "NodeSocketFloat"; + data_type = BL::NodeSocket::type_VALUE; if(param->validdefault) default_float = param->fdefault[0]; } else if(param->type.basetype == TypeDesc::STRING) { - socket_type = BL::NodeSocket::type_STRING; + socket_type = "NodeSocketString"; + data_type = BL::NodeSocket::type_STRING; if(param->validdefault) default_string = param->sdefault[0]; } @@ -300,38 +307,52 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) continue; /* find socket socket */ - BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput); - - /* remove if type no longer matches */ - if(b_sock && b_sock.type() != socket_type) { - b_node.remove_socket(b_sock); - b_sock = BL::NodeSocket(PointerRNA_NULL); + BL::NodeSocket b_sock(PointerRNA_NULL); + if (param->isoutput) { + b_sock = b_node.outputs[param->name]; + + /* remove if type no longer matches */ + if(b_sock && b_sock.bl_idname() != socket_type) { + b_node.outputs.remove(b_sock); + b_sock = BL::NodeSocket(PointerRNA_NULL); + } + + if (!b_sock) { + /* create new socket */ + b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); + } + } + else { + b_sock = b_node.inputs[param->name]; + + /* remove if type no longer matches */ + if(b_sock && b_sock.bl_idname() != socket_type) { + b_node.inputs.remove(b_sock); + b_sock = BL::NodeSocket(PointerRNA_NULL); + } + + if (!b_sock) { + /* create new socket */ + b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); + } } - /* create new socket */ - if(!b_sock) { - b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput); - - /* set default value */ - if(socket_type == BL::NodeSocket::type_VALUE) { - BL::NodeSocketFloatNone b_float_sock(b_sock.ptr); - b_float_sock.default_value(default_float); + /* set default value */ + if(b_sock) { + if(data_type == BL::NodeSocket::type_VALUE) { + set_float(b_sock.ptr, "default_value", default_float); } - else if(socket_type == BL::NodeSocket::type_INT) { - BL::NodeSocketIntNone b_int_sock(b_sock.ptr); - b_int_sock.default_value(default_int); + else if(data_type == BL::NodeSocket::type_INT) { + set_int(b_sock.ptr, "default_value", default_int); } - else if(socket_type == BL::NodeSocket::type_RGBA) { - BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr); - b_rgba_sock.default_value(default_float4); + else if(data_type == BL::NodeSocket::type_RGBA) { + set_float4(b_sock.ptr, "default_value", default_float4); } - else if(socket_type == BL::NodeSocket::type_VECTOR) { - BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr); - b_vector_sock.default_value(default_float4); + else if(data_type == BL::NodeSocket::type_VECTOR) { + set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4)); } - else if(socket_type == BL::NodeSocket::type_STRING) { - BL::NodeSocketStringNone b_string_sock(b_sock.ptr); - b_string_sock.default_value(default_string); + else if(data_type == BL::NodeSocket::type_STRING) { + set_string(b_sock.ptr, "default_value", default_string); } } @@ -349,7 +370,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) { - b_node.remove_socket(*b_input); + b_node.inputs.remove(*b_input); removed = true; break; } @@ -357,7 +378,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) { - b_node.remove_socket(*b_output); + b_node.outputs.remove(*b_output); removed = true; break; } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 0f7dc15db19..45a97f1d530 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -31,9 +31,9 @@ CCL_NAMESPACE_BEGIN -typedef map<void*, ShaderNode*> PtrNodeMap; -typedef pair<ShaderNode*, std::string> SocketPair; -typedef map<void*, SocketPair> PtrSockMap; +typedef map<void*, ShaderInput*> PtrInputMap; +typedef map<void*, ShaderOutput*> PtrOutputMap; +typedef map<std::string, ProxyNode*> ProxyMap; /* Find */ @@ -55,83 +55,88 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default static BL::NodeSocket get_node_output(BL::Node b_node, const string& name) { BL::Node::outputs_iterator b_out; - + for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out) if(b_out->name() == name) return *b_out; - + assert(0); - + return *b_out; } static float3 get_node_output_rgba(BL::Node b_node, const string& name) { - BL::NodeSocketRGBA sock(get_node_output(b_node, name)); - return get_float3(sock.default_value()); + BL::NodeSocket b_sock = get_node_output(b_node, name); + float value[4]; + RNA_float_get_array(&b_sock.ptr, "default_value", value); + return make_float3(value[0], value[1], value[2]); } static float get_node_output_value(BL::Node b_node, const string& name) { - BL::NodeSocketFloatNone sock(get_node_output(b_node, name)); - return sock.default_value(); + BL::NodeSocket b_sock = get_node_output(b_node, name); + return RNA_float_get(&b_sock.ptr, "default_value"); } -static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) +static float3 get_node_output_vector(BL::Node b_node, const string& name) { - switch (b_type) { - case BL::NodeSocket::type_VALUE: - return SHADER_SOCKET_FLOAT; - case BL::NodeSocket::type_INT: - return SHADER_SOCKET_INT; - case BL::NodeSocket::type_VECTOR: - return SHADER_SOCKET_VECTOR; - case BL::NodeSocket::type_RGBA: - return SHADER_SOCKET_COLOR; - case BL::NodeSocket::type_SHADER: - return SHADER_SOCKET_CLOSURE; - case BL::NodeSocket::type_STRING: - return SHADER_SOCKET_STRING; - - case BL::NodeSocket::type_BOOLEAN: - case BL::NodeSocket::type_MESH: - default: - return SHADER_SOCKET_FLOAT; + BL::NodeSocket b_sock = get_node_output(b_node, name); + float value[3]; + RNA_float_get_array(&b_sock.ptr, "default_value", value); + return make_float3(value[0], value[1], value[2]); +} + +static ShaderSocketType convert_socket_type(BL::NodeSocket b_socket) +{ + switch (b_socket.type()) { + case BL::NodeSocket::type_VALUE: + return SHADER_SOCKET_FLOAT; + case BL::NodeSocket::type_INT: + return SHADER_SOCKET_INT; + case BL::NodeSocket::type_VECTOR: + return SHADER_SOCKET_VECTOR; + case BL::NodeSocket::type_RGBA: + return SHADER_SOCKET_COLOR; + case BL::NodeSocket::type_STRING: + return SHADER_SOCKET_STRING; + case BL::NodeSocket::type_SHADER: + return SHADER_SOCKET_CLOSURE; + + default: + return SHADER_SOCKET_UNDEFINED; } } -static void set_default_value(ShaderInput *input, BL::NodeSocket sock, BL::BlendData b_data, BL::ID b_id) +static void set_default_value(ShaderInput *input, BL::Node b_node, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id) { /* copy values for non linked inputs */ switch(input->type) { case SHADER_SOCKET_FLOAT: { - BL::NodeSocketFloatNone value_sock(sock); - input->set(value_sock.default_value()); + input->set(get_float(b_sock.ptr, "default_value")); break; } case SHADER_SOCKET_INT: { - BL::NodeSocketIntNone value_sock(sock); - input->set((float)value_sock.default_value()); + input->set((float)get_int(b_sock.ptr, "default_value")); break; } case SHADER_SOCKET_COLOR: { - BL::NodeSocketRGBA rgba_sock(sock); - input->set(get_float3(rgba_sock.default_value())); + input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value"))); break; } case SHADER_SOCKET_NORMAL: case SHADER_SOCKET_POINT: case SHADER_SOCKET_VECTOR: { - BL::NodeSocketVectorNone vec_sock(sock); - input->set(get_float3(vec_sock.default_value())); + input->set(get_float3(b_sock.ptr, "default_value")); break; } case SHADER_SOCKET_STRING: { - BL::NodeSocketStringNone string_sock(sock); - input->set((ustring)blender_absolute_path(b_data, b_id, string_sock.default_value())); + input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value"))); break; } + case SHADER_SOCKET_CLOSURE: + case SHADER_SOCKET_UNDEFINED: break; } } @@ -171,295 +176,226 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen { ShaderNode *node = NULL; - switch(b_node.type()) { - /* not supported */ - case BL::ShaderNode::type_GEOMETRY: break; - case BL::ShaderNode::type_MATERIAL: break; - case BL::ShaderNode::type_MATERIAL_EXT: break; - case BL::ShaderNode::type_OUTPUT: break; - case BL::ShaderNode::type_SQUEEZE: break; - case BL::ShaderNode::type_TEXTURE: break; - case BL::ShaderNode::type_FRAME: break; - /* handled outside this function */ - case BL::ShaderNode::type_GROUP: break; - /* existing blender nodes */ - case BL::ShaderNode::type_REROUTE: { - BL::Node::inputs_iterator b_input; - b_node.inputs.begin(b_input); - BL::Node::outputs_iterator b_output; - b_node.outputs.begin(b_output); - ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type())); - node = proxy; - break; - } - case BL::ShaderNode::type_CURVE_VEC: { - BL::ShaderNodeVectorCurve b_curve_node(b_node); - VectorCurvesNode *curves = new VectorCurvesNode(); - curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false); - node = curves; - break; - } - case BL::ShaderNode::type_CURVE_RGB: { - BL::ShaderNodeRGBCurve b_curve_node(b_node); - RGBCurvesNode *curves = new RGBCurvesNode(); - curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true); - node = curves; - break; - } - case BL::ShaderNode::type_VALTORGB: { - RGBRampNode *ramp = new RGBRampNode(); - BL::ShaderNodeValToRGB b_ramp_node(b_node); - colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE); - node = ramp; - break; - } - case BL::ShaderNode::type_RGB: { - ColorNode *color = new ColorNode(); - color->value = get_node_output_rgba(b_node, "Color"); - node = color; - break; - } - case BL::ShaderNode::type_VALUE: { - ValueNode *value = new ValueNode(); - value->value = get_node_output_value(b_node, "Value"); - node = value; - break; - } - case BL::ShaderNode::type_CAMERA: { - node = new CameraNode(); - break; - } - case BL::ShaderNode::type_INVERT: { - node = new InvertNode(); - break; - } - case BL::ShaderNode::type_GAMMA: { - node = new GammaNode(); - break; - } - case BL::ShaderNode::type_BRIGHTCONTRAST: { - node = new BrightContrastNode(); - break; - } - case BL::ShaderNode::type_MIX_RGB: { - BL::ShaderNodeMixRGB b_mix_node(b_node); - MixNode *mix = new MixNode(); - mix->type = MixNode::type_enum[b_mix_node.blend_type()]; + /* existing blender nodes */ + if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) { + BL::ShaderNodeRGBCurve b_curve_node(b_node); + RGBCurvesNode *curves = new RGBCurvesNode(); + curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true); + node = curves; + } + if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) { + BL::ShaderNodeVectorCurve b_curve_node(b_node); + VectorCurvesNode *curves = new VectorCurvesNode(); + curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false); + node = curves; + } + else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) { + RGBRampNode *ramp = new RGBRampNode(); + BL::ShaderNodeValToRGB b_ramp_node(b_node); + colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE); + node = ramp; + } + else if (b_node.is_a(&RNA_ShaderNodeRGB)) { + ColorNode *color = new ColorNode(); + color->value = get_node_output_rgba(b_node, "Color"); + node = color; + } + else if (b_node.is_a(&RNA_ShaderNodeValue)) { + ValueNode *value = new ValueNode(); + value->value = get_node_output_value(b_node, "Value"); + node = value; + } + else if (b_node.is_a(&RNA_ShaderNodeCameraData)) { + node = new CameraNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeInvert)) { + node = new InvertNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeGamma)) { + node = new GammaNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) { + node = new BrightContrastNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) { + BL::ShaderNodeMixRGB b_mix_node(b_node); + MixNode *mix = new MixNode(); + mix->type = MixNode::type_enum[b_mix_node.blend_type()]; mix->use_clamp = b_mix_node.use_clamp(); - node = mix; - break; - } - case BL::ShaderNode::type_SEPRGB: { - node = new SeparateRGBNode(); - break; - } - case BL::ShaderNode::type_COMBRGB: { - node = new CombineRGBNode(); - break; - } - case BL::ShaderNode::type_HUE_SAT: { - node = new HSVNode(); - break; - } - case BL::ShaderNode::type_RGBTOBW: { - node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT); - break; - } - case BL::ShaderNode::type_MATH: { - BL::ShaderNodeMath b_math_node(b_node); - MathNode *math = new MathNode(); - math->type = MathNode::type_enum[b_math_node.operation()]; + node = mix; + } + else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) { + node = new SeparateRGBNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) { + node = new CombineRGBNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) { + node = new HSVNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) { + node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT); + } + else if (b_node.is_a(&RNA_ShaderNodeMath)) { + BL::ShaderNodeMath b_math_node(b_node); + MathNode *math = new MathNode(); + math->type = MathNode::type_enum[b_math_node.operation()]; math->use_clamp = b_math_node.use_clamp(); - node = math; - break; - } - case BL::ShaderNode::type_VECT_MATH: { - BL::ShaderNodeVectorMath b_vector_math_node(b_node); - VectorMathNode *vmath = new VectorMathNode(); - vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()]; - node = vmath; - break; - } - case BL::ShaderNode::type_NORMAL: { - BL::Node::outputs_iterator out_it; - b_node.outputs.begin(out_it); - BL::NodeSocketVectorNone vec_sock(*out_it); - - NormalNode *norm = new NormalNode(); - norm->direction = get_float3(vec_sock.default_value()); - - node = norm; - break; - } - case BL::ShaderNode::type_MAPPING: { - BL::ShaderNodeMapping b_mapping_node(b_node); - MappingNode *mapping = new MappingNode(); - - get_tex_mapping(&mapping->tex_mapping, b_mapping_node); - - node = mapping; - break; - } - - /* new nodes */ - case BL::ShaderNode::type_OUTPUT_MATERIAL: - case BL::ShaderNode::type_OUTPUT_WORLD: - case BL::ShaderNode::type_OUTPUT_LAMP: { - node = graph->output(); - break; - } - case BL::ShaderNode::type_FRESNEL: { - node = new FresnelNode(); - break; - } - case BL::ShaderNode::type_LAYER_WEIGHT: { - node = new LayerWeightNode(); - break; - } - case BL::ShaderNode::type_ADD_SHADER: { - node = new AddClosureNode(); - break; - } - case BL::ShaderNode::type_MIX_SHADER: { - node = new MixClosureNode(); - break; - } - case BL::ShaderNode::type_ATTRIBUTE: { - BL::ShaderNodeAttribute b_attr_node(b_node); - AttributeNode *attr = new AttributeNode(); - attr->attribute = b_attr_node.attribute_name(); - node = attr; - break; - } - case BL::ShaderNode::type_BACKGROUND: { - node = new BackgroundNode(); - break; - } - case BL::ShaderNode::type_HOLDOUT: { - node = new HoldoutNode(); - break; - } - case BL::ShaderNode::type_BSDF_ANISOTROPIC: { - node = new WardBsdfNode(); - break; - } - case BL::ShaderNode::type_BSDF_DIFFUSE: { - node = new DiffuseBsdfNode(); - break; - } - case BL::ShaderNode::type_BSDF_GLOSSY: { - BL::ShaderNodeBsdfGlossy b_glossy_node(b_node); - GlossyBsdfNode *glossy = new GlossyBsdfNode(); - - switch(b_glossy_node.distribution()) { - case BL::ShaderNodeBsdfGlossy::distribution_SHARP: - glossy->distribution = ustring("Sharp"); - break; - case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN: - glossy->distribution = ustring("Beckmann"); - break; - case BL::ShaderNodeBsdfGlossy::distribution_GGX: - glossy->distribution = ustring("GGX"); - break; - } - node = glossy; - break; - } - case BL::ShaderNode::type_BSDF_GLASS: { - BL::ShaderNodeBsdfGlass b_glass_node(b_node); - GlassBsdfNode *glass = new GlassBsdfNode(); - switch(b_glass_node.distribution()) { - case BL::ShaderNodeBsdfGlass::distribution_SHARP: - glass->distribution = ustring("Sharp"); - break; - case BL::ShaderNodeBsdfGlass::distribution_BECKMANN: - glass->distribution = ustring("Beckmann"); - break; - case BL::ShaderNodeBsdfGlass::distribution_GGX: - glass->distribution = ustring("GGX"); - break; - } - node = glass; - break; - } - case BL::ShaderNode::type_BSDF_REFRACTION: { - BL::ShaderNodeBsdfRefraction b_refraction_node(b_node); - RefractionBsdfNode *refraction = new RefractionBsdfNode(); - switch(b_refraction_node.distribution()) { - case BL::ShaderNodeBsdfRefraction::distribution_SHARP: - refraction->distribution = ustring("Sharp"); - break; - case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN: - refraction->distribution = ustring("Beckmann"); - break; - case BL::ShaderNodeBsdfRefraction::distribution_GGX: - refraction->distribution = ustring("GGX"); - break; - } - node = refraction; - break; - } - case BL::ShaderNode::type_BSDF_TRANSLUCENT: { - node = new TranslucentBsdfNode(); - break; - } - case BL::ShaderNode::type_BSDF_TRANSPARENT: { - node = new TransparentBsdfNode(); - break; - } - case BL::ShaderNode::type_BSDF_VELVET: { - node = new VelvetBsdfNode(); - break; - } - case BL::ShaderNode::type_EMISSION: { - node = new EmissionNode(); - break; - } - case BL::ShaderNode::type_AMBIENT_OCCLUSION: { - node = new AmbientOcclusionNode(); - break; - } - case BL::ShaderNode::type_VOLUME_ISOTROPIC: { - node = new IsotropicVolumeNode(); - break; - } - case BL::ShaderNode::type_VOLUME_TRANSPARENT: { - node = new TransparentVolumeNode(); - break; - } - case BL::ShaderNode::type_NEW_GEOMETRY: { - node = new GeometryNode(); + node = math; + } + else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) { + BL::ShaderNodeVectorMath b_vector_math_node(b_node); + VectorMathNode *vmath = new VectorMathNode(); + vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()]; + node = vmath; + } + else if (b_node.is_a(&RNA_ShaderNodeNormal)) { + BL::Node::outputs_iterator out_it; + b_node.outputs.begin(out_it); + BL::NodeSocket vec_sock(*out_it); + + NormalNode *norm = new NormalNode(); + norm->direction = get_node_output_vector(b_node, "Normal"); + node = norm; + } + else if (b_node.is_a(&RNA_ShaderNodeMapping)) { + BL::ShaderNodeMapping b_mapping_node(b_node); + MappingNode *mapping = new MappingNode(); + + get_tex_mapping(&mapping->tex_mapping, b_mapping_node); + + node = mapping; + } + /* new nodes */ + else if (b_node.is_a(&RNA_ShaderNodeOutputMaterial) + || b_node.is_a(&RNA_ShaderNodeOutputWorld) + || b_node.is_a(&RNA_ShaderNodeOutputLamp)) { + node = graph->output(); + } + else if (b_node.is_a(&RNA_ShaderNodeFresnel)) { + node = new FresnelNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) { + node = new LayerWeightNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeAddShader)) { + node = new AddClosureNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeMixShader)) { + node = new MixClosureNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeAttribute)) { + BL::ShaderNodeAttribute b_attr_node(b_node); + AttributeNode *attr = new AttributeNode(); + attr->attribute = b_attr_node.attribute_name(); + node = attr; + } + else if (b_node.is_a(&RNA_ShaderNodeBackground)) { + node = new BackgroundNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeHoldout)) { + node = new HoldoutNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) { + node = new WardBsdfNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) { + node = new DiffuseBsdfNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) { + BL::ShaderNodeBsdfGlossy b_glossy_node(b_node); + GlossyBsdfNode *glossy = new GlossyBsdfNode(); + + switch(b_glossy_node.distribution()) { + case BL::ShaderNodeBsdfGlossy::distribution_SHARP: + glossy->distribution = ustring("Sharp"); break; - } - case BL::ShaderNode::type_LIGHT_PATH: { - node = new LightPathNode(); + case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN: + glossy->distribution = ustring("Beckmann"); break; - } - case BL::ShaderNode::type_LIGHT_FALLOFF: { - node = new LightFalloffNode(); + case BL::ShaderNodeBsdfGlossy::distribution_GGX: + glossy->distribution = ustring("GGX"); break; } - case BL::ShaderNode::type_OBJECT_INFO: { - node = new ObjectInfoNode(); + node = glossy; + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) { + BL::ShaderNodeBsdfGlass b_glass_node(b_node); + GlassBsdfNode *glass = new GlassBsdfNode(); + switch(b_glass_node.distribution()) { + case BL::ShaderNodeBsdfGlass::distribution_SHARP: + glass->distribution = ustring("Sharp"); break; - } - case BL::ShaderNode::type_PARTICLE_INFO: { - node = new ParticleInfoNode(); + case BL::ShaderNodeBsdfGlass::distribution_BECKMANN: + glass->distribution = ustring("Beckmann"); break; - } - case BL::ShaderNode::type_HAIR_INFO: { - node = new HairInfoNode(); + case BL::ShaderNodeBsdfGlass::distribution_GGX: + glass->distribution = ustring("GGX"); break; } - case BL::ShaderNode::type_BUMP: { - node = new BumpNode(); - break; + node = glass; + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) { + BL::ShaderNodeBsdfRefraction b_refraction_node(b_node); + RefractionBsdfNode *refraction = new RefractionBsdfNode(); + switch(b_refraction_node.distribution()) { + case BL::ShaderNodeBsdfRefraction::distribution_SHARP: + refraction->distribution = ustring("Sharp"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN: + refraction->distribution = ustring("Beckmann"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_GGX: + refraction->distribution = ustring("GGX"); + break; } - case BL::ShaderNode::type_SCRIPT: { + node = refraction; + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) { + node = new TranslucentBsdfNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) { + node = new TransparentBsdfNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) { + node = new VelvetBsdfNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeEmission)) { + node = new EmissionNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) { + node = new AmbientOcclusionNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeVolumeIsotropic)) { + node = new IsotropicVolumeNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeVolumeTransparent)) { + node = new TransparentVolumeNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) { + node = new GeometryNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeLightPath)) { + node = new LightPathNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) { + node = new LightFalloffNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) { + node = new ObjectInfoNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) { + node = new ParticleInfoNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) { + node = new HairInfoNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeBump)) { + node = new BumpNode(); + } + else if (b_node.is_a(&RNA_ShaderNodeScript)) { #ifdef WITH_OSL - if(!scene->shader_manager->use_osl()) - break; - + if(scene->shader_manager->use_osl()) { /* create script node */ BL::ShaderNodeScript b_script_node(b_node); OSLScriptNode *script_node = new OSLScriptNode(); @@ -472,29 +408,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen * Note 2: ShaderInput/ShaderOutput store shallow string copies only! * Socket names must be stored in the extra lists instead. */ BL::Node::inputs_iterator b_input; - + for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { script_node->input_names.push_back(ustring(b_input->name())); - ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type())); - set_default_value(input, *b_input, b_data, b_ntree); + ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), + convert_socket_type(*b_input)); + set_default_value(input, b_node, *b_input, b_data, b_ntree); } - + BL::Node::outputs_iterator b_output; - + for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) { script_node->output_names.push_back(ustring(b_output->name())); - script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(b_output->type())); + script_node->add_output(script_node->output_names.back().c_str(), + convert_socket_type(*b_output)); } - + /* load bytecode or filepath */ OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager; string bytecode_hash = b_script_node.bytecode_hash(); - + if(!bytecode_hash.empty()) { /* loaded bytecode if not already done */ if(!manager->shader_test_loaded(bytecode_hash)) manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode()); - + script_node->bytecode_hash = bytecode_hash; } else { @@ -503,173 +441,157 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = script_node; -#endif - - break; } - case BL::ShaderNode::type_TEX_IMAGE: { - BL::ShaderNodeTexImage b_image_node(b_node); - BL::Image b_image(b_image_node.image()); - ImageTextureNode *image = new ImageTextureNode(); - if(b_image) { - /* builtin images will use callback-based reading because - * they could only be loaded correct from blender side +#endif + } + else if (b_node.is_a(&RNA_ShaderNodeTexImage)) { + BL::ShaderNodeTexImage b_image_node(b_node); + BL::Image b_image(b_image_node.image()); + ImageTextureNode *image = new ImageTextureNode(); + if(b_image) { + /* builtin images will use callback-based reading because + * they could only be loaded correct from blender side + */ + bool is_builtin = b_image.packed_file() || + b_image.source() == BL::Image::source_GENERATED || + b_image.source() == BL::Image::source_MOVIE; + + if(is_builtin) { + /* for builtin images we're using image datablock name to find an image to + * read pixels from later + * + * also store frame number as well, so there's no differences in handling + * builtin names for packed images and movies */ - bool is_builtin = b_image.packed_file() || - b_image.source() == BL::Image::source_GENERATED || - b_image.source() == BL::Image::source_MOVIE; - - if(is_builtin) { - /* for builtin images we're using image datablock name to find an image to - * read pixels from later - * - * also store frame number as well, so there's no differences in handling - * builtin names for packed images and movies - */ - int scene_frame = b_scene.frame_current(); - int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame); - image->filename = b_image.name() + "@" + string_printf("%d", image_frame); - image->builtin_data = b_image.ptr.data; - } - else { - image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); - image->builtin_data = NULL; - } - - image->animated = b_image_node.image_user().use_auto_refresh(); + int scene_frame = b_scene.frame_current(); + int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame); + image->filename = b_image.name() + "@" + string_printf("%d", image_frame); + image->builtin_data = b_image.ptr.data; } - image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; - image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; - image->projection_blend = b_image_node.projection_blend(); - get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); - node = image; - break; - } - case BL::ShaderNode::type_TEX_ENVIRONMENT: { - BL::ShaderNodeTexEnvironment b_env_node(b_node); - BL::Image b_image(b_env_node.image()); - EnvironmentTextureNode *env = new EnvironmentTextureNode(); - if(b_image) { - bool is_builtin = b_image.packed_file() || - b_image.source() == BL::Image::source_GENERATED || - b_image.source() == BL::Image::source_MOVIE; - - if(is_builtin) { - int scene_frame = b_scene.frame_current(); - int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame); - env->filename = b_image.name() + "@" + string_printf("%d", image_frame); - env->builtin_data = b_image.ptr.data; - } - else { - env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); - env->animated = b_env_node.image_user().use_auto_refresh(); - env->builtin_data = NULL; - } + else { + image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); + image->builtin_data = NULL; } - env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; - env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; - get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); - node = env; - break; - } - case BL::ShaderNode::type_TEX_GRADIENT: { - BL::ShaderNodeTexGradient b_gradient_node(b_node); - GradientTextureNode *gradient = new GradientTextureNode(); - gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()]; - get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping()); - node = gradient; - break; - } - case BL::ShaderNode::type_TEX_VORONOI: { - BL::ShaderNodeTexVoronoi b_voronoi_node(b_node); - VoronoiTextureNode *voronoi = new VoronoiTextureNode(); - voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()]; - get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping()); - node = voronoi; - break; - } - case BL::ShaderNode::type_TEX_MAGIC: { - BL::ShaderNodeTexMagic b_magic_node(b_node); - MagicTextureNode *magic = new MagicTextureNode(); - magic->depth = b_magic_node.turbulence_depth(); - get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping()); - node = magic; - break; - } - case BL::ShaderNode::type_TEX_WAVE: { - BL::ShaderNodeTexWave b_wave_node(b_node); - WaveTextureNode *wave = new WaveTextureNode(); - wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()]; - get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping()); - node = wave; - break; - } - case BL::ShaderNode::type_TEX_CHECKER: { - BL::ShaderNodeTexChecker b_checker_node(b_node); - CheckerTextureNode *checker = new CheckerTextureNode(); - get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping()); - node = checker; - break; - } - case BL::ShaderNode::type_TEX_BRICK: { - BL::ShaderNodeTexBrick b_brick_node(b_node); - BrickTextureNode *brick = new BrickTextureNode(); - brick->offset = b_brick_node.offset(); - brick->offset_frequency = b_brick_node.offset_frequency(); - brick->squash = b_brick_node.squash(); - brick->squash_frequency = b_brick_node.squash_frequency(); - get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping()); - node = brick; - break; - } - case BL::ShaderNode::type_TEX_NOISE: { - BL::ShaderNodeTexNoise b_noise_node(b_node); - NoiseTextureNode *noise = new NoiseTextureNode(); - get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping()); - node = noise; - break; - } - case BL::ShaderNode::type_TEX_MUSGRAVE: { - BL::ShaderNodeTexMusgrave b_musgrave_node(b_node); - MusgraveTextureNode *musgrave = new MusgraveTextureNode(); - musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()]; - get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping()); - node = musgrave; - break; - } - case BL::ShaderNode::type_TEX_COORD: { - BL::ShaderNodeTexCoord b_tex_coord_node(b_node); - TextureCoordinateNode *tex_coord = new TextureCoordinateNode(); - tex_coord->from_dupli = b_tex_coord_node.from_dupli(); - node = tex_coord; - break; - } - case BL::ShaderNode::type_TEX_SKY: { - BL::ShaderNodeTexSky b_sky_node(b_node); - SkyTextureNode *sky = new SkyTextureNode(); - sky->sun_direction = get_float3(b_sky_node.sun_direction()); - sky->turbidity = b_sky_node.turbidity(); - get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping()); - node = sky; - break; - } - case BL::ShaderNode::type_NORMAL_MAP: { - BL::ShaderNodeNormalMap b_normal_map_node(b_node); - NormalMapNode *nmap = new NormalMapNode(); - nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()]; - nmap->attribute = b_normal_map_node.uv_map(); - node = nmap; - break; + + image->animated = b_image_node.image_user().use_auto_refresh(); } - case BL::ShaderNode::type_TANGENT: { - BL::ShaderNodeTangent b_tangent_node(b_node); - TangentNode *tangent = new TangentNode(); - tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()]; - tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()]; - tangent->attribute = b_tangent_node.uv_map(); - node = tangent; - break; + image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; + image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; + image->projection_blend = b_image_node.projection_blend(); + get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); + node = image; + } + else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) { + BL::ShaderNodeTexEnvironment b_env_node(b_node); + BL::Image b_image(b_env_node.image()); + EnvironmentTextureNode *env = new EnvironmentTextureNode(); + if(b_image) { + bool is_builtin = b_image.packed_file() || + b_image.source() == BL::Image::source_GENERATED || + b_image.source() == BL::Image::source_MOVIE; + + if(is_builtin) { + int scene_frame = b_scene.frame_current(); + int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame); + env->filename = b_image.name() + "@" + string_printf("%d", image_frame); + env->builtin_data = b_image.ptr.data; + } + else { + env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); + env->animated = b_env_node.image_user().use_auto_refresh(); + env->builtin_data = NULL; + } } + env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; + env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; + get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); + node = env; + } + else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) { + BL::ShaderNodeTexGradient b_gradient_node(b_node); + GradientTextureNode *gradient = new GradientTextureNode(); + gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()]; + get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping()); + node = gradient; + } + else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) { + BL::ShaderNodeTexVoronoi b_voronoi_node(b_node); + VoronoiTextureNode *voronoi = new VoronoiTextureNode(); + voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()]; + get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping()); + node = voronoi; + } + else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) { + BL::ShaderNodeTexMagic b_magic_node(b_node); + MagicTextureNode *magic = new MagicTextureNode(); + magic->depth = b_magic_node.turbulence_depth(); + get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping()); + node = magic; + } + else if (b_node.is_a(&RNA_ShaderNodeTexWave)) { + BL::ShaderNodeTexWave b_wave_node(b_node); + WaveTextureNode *wave = new WaveTextureNode(); + wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()]; + get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping()); + node = wave; + } + else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) { + BL::ShaderNodeTexChecker b_checker_node(b_node); + CheckerTextureNode *checker = new CheckerTextureNode(); + get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping()); + node = checker; + } + else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) { + BL::ShaderNodeTexBrick b_brick_node(b_node); + BrickTextureNode *brick = new BrickTextureNode(); + brick->offset = b_brick_node.offset(); + brick->offset_frequency = b_brick_node.offset_frequency(); + brick->squash = b_brick_node.squash(); + brick->squash_frequency = b_brick_node.squash_frequency(); + get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping()); + node = brick; + } + else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) { + BL::ShaderNodeTexNoise b_noise_node(b_node); + NoiseTextureNode *noise = new NoiseTextureNode(); + get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping()); + node = noise; + } + else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) { + BL::ShaderNodeTexMusgrave b_musgrave_node(b_node); + MusgraveTextureNode *musgrave = new MusgraveTextureNode(); + musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()]; + get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping()); + node = musgrave; + } + else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) { + BL::ShaderNodeTexCoord b_tex_coord_node(b_node); + TextureCoordinateNode *tex_coord = new TextureCoordinateNode(); + tex_coord->from_dupli = b_tex_coord_node.from_dupli(); + node = tex_coord; + } + else if (b_node.is_a(&RNA_ShaderNodeTexSky)) { + BL::ShaderNodeTexSky b_sky_node(b_node); + SkyTextureNode *sky = new SkyTextureNode(); + sky->sun_direction = get_float3(b_sky_node.sun_direction()); + sky->turbidity = b_sky_node.turbidity(); + get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping()); + node = sky; + } + else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) { + BL::ShaderNodeNormalMap b_normal_map_node(b_node); + NormalMapNode *nmap = new NormalMapNode(); + nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()]; + nmap->attribute = b_normal_map_node.uv_map(); + node = nmap; + } + else if (b_node.is_a(&RNA_ShaderNodeTangent)) { + BL::ShaderNodeTangent b_tangent_node(b_node); + TangentNode *tangent = new TangentNode(); + tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()]; + tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()]; + tangent->attribute = b_tangent_node.uv_map(); + node = tangent; } if(node && node != graph->output()) @@ -678,18 +600,16 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen return node; } -static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL::NodeSocket b_socket) +static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket) { BL::Node::inputs_iterator b_input; - BL::Node::outputs_iterator b_output; string name = b_socket.name(); bool found = false; int counter = 0, total = 0; - - /* find in inputs */ - for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { - if(b_input->name() == name) { - if(!found) + + for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { + if (b_input->name() == name) { + if (!found) counter++; total++; } @@ -697,128 +617,145 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL if(b_input->ptr.data == b_socket.ptr.data) found = true; } + + /* rename if needed */ + if (name == "Shader") + name = "Closure"; + + if (total > 1) + name = string_printf("%s%d", name.c_str(), counter); + + return node->input(name.c_str()); +} - if(!found) { - /* find in outputs */ - found = false; - counter = 0; - total = 0; - - for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { - if(b_output->name() == name) { - if(!found) - counter++; - total++; - } - - if(b_output->ptr.data == b_socket.ptr.data) - found = true; +static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket) +{ + BL::Node::outputs_iterator b_output; + string name = b_socket.name(); + bool found = false; + int counter = 0, total = 0; + + for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { + if (b_output->name() == name) { + if (!found) + counter++; + total++; } - } + if(b_output->ptr.data == b_socket.ptr.data) + found = true; + } + /* rename if needed */ - if(name == "Shader") + if (name == "Shader") name = "Closure"; - - if(total > 1) + + if (total > 1) name = string_printf("%s%d", name.c_str(), counter); - - return SocketPair(node_map[b_node.ptr.data], name); + + return node->output(name.c_str()); } -static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) +static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, ProxyMap &proxy_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; - PtrNodeMap node_map; - PtrSockMap proxy_map; + PtrInputMap input_map; + PtrOutputMap output_map; + + BL::Node::inputs_iterator b_input; + BL::Node::outputs_iterator b_output; for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if(b_node->mute()) { - BL::Node::inputs_iterator b_input; - BL::Node::outputs_iterator b_output; - bool found_match = false; - - /* this is slightly different than blender logic, we just connect a - * single pair for of input/output, but works ok for the node we have */ - for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - if(b_input->is_linked()) { - for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { - if(b_output->is_linked() && b_input->type() == b_output->type()) { - ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type())); - graph->add(proxy); - - proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); - proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); - found_match = true; - - break; - } - } - } - - if(found_match) - break; + if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) { + /* replace muted node with internal links */ + BL::Node::internal_links_iterator b_link; + for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) { + ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket())); + + input_map[b_link->from_socket().ptr.data] = proxy->inputs[0]; + output_map[b_link->to_socket().ptr.data] = proxy->outputs[0]; + + graph->add(proxy); } } - else if(b_node->is_a(&RNA_NodeGroup)) { - /* add proxy converter nodes for inputs and outputs */ + else if (b_node->is_a(&RNA_ShaderNodeGroup)) { BL::NodeGroup b_gnode(*b_node); BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); + ProxyMap group_proxy_map; + if (!b_group_ntree) continue; - - BL::Node::inputs_iterator b_input; - BL::Node::outputs_iterator b_output; - PtrSockMap group_sockmap; + add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_map); + /* map the outer socket to the internal proxy nodes */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - ShaderSocketType extern_type = convert_socket_type(b_input->type()); - ShaderSocketType intern_type = convert_socket_type(b_input->group_socket().type()); - ShaderNode *proxy = graph->add(new ProxyNode(extern_type, intern_type)); - /* map the external node socket to the proxy node socket */ - proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); - /* map the internal group socket to the proxy node socket */ - group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); + /* get internal proxy node from group proxy map */ + assert(group_proxy_map.find(b_input->identifier()) != group_proxy_map.end()); + assert(group_proxy_map[b_input->identifier()]->special_type == SHADER_SPECIAL_TYPE_PROXY); + ProxyNode *proxy = group_proxy_map[b_input->identifier()]; + + input_map[b_input->ptr.data] = proxy->inputs[0]; - /* default input values of the group node */ - set_default_value(proxy->inputs[0], *b_input, b_data, b_group_ntree); + /* input value for proxy inputs is defined by group node */ + set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); } + /* map the outer socket to the internal proxy nodes */ for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { - ShaderSocketType extern_type = convert_socket_type(b_output->type()); - ShaderSocketType intern_type = convert_socket_type(b_output->group_socket().type()); - ShaderNode *proxy = graph->add(new ProxyNode(intern_type, extern_type)); - /* map the external node socket to the proxy node socket */ - proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); - /* map the internal group socket to the proxy node socket */ - group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); + /* get internal proxy node from group node map */ + assert(group_proxy_map.find(b_output->identifier()) != group_proxy_map.end()); + assert(group_proxy_map[b_output->identifier()]->special_type == SHADER_SPECIAL_TYPE_PROXY); + ProxyNode *proxy = group_proxy_map[b_output->identifier()]; - /* default input values of internal, unlinked group outputs */ - set_default_value(proxy->inputs[0], b_output->group_socket(), b_data, b_group_ntree); + output_map[b_output->ptr.data] = proxy->outputs[0]; + } + } + else if (b_node->is_a(&RNA_NodeGroupInput)) { + /* add a proxy node for each socket */ + for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { + ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output)); + + output_map[b_output->ptr.data] = proxy->outputs[0]; + + /* register the proxy node for external binding */ + proxy_map[b_output->identifier()] = proxy; + + graph->add(proxy); + } + } + else if (b_node->is_a(&RNA_NodeGroupOutput)) { + /* add a proxy node for each socket */ + for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { + ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input)); + + input_map[b_input->ptr.data] = proxy->inputs[0]; + + set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); + + /* register the proxy node for external binding */ + proxy_map[b_input->identifier()] = proxy; + + graph->add(proxy); } - - add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap); } else { ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); if(node) { - BL::Node::inputs_iterator b_input; - - node_map[b_node->ptr.data] = node; - + /* map node sockets for linking */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input); - ShaderInput *input = pair.first->input(pair.second.c_str()); + ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input); + input_map[b_input->ptr.data] = input; - assert(input); - - /* copy values for non linked inputs */ - set_default_value(input, *b_input, b_data, b_ntree); + set_default_value(input, *b_node, *b_input, b_data, b_ntree); + } + for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { + ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output); + output_map[b_output->ptr.data] = output; } } } @@ -829,44 +766,23 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { /* get blender link data */ - BL::Node b_from_node = b_link->from_node(); - BL::Node b_to_node = b_link->to_node(); - BL::NodeSocket b_from_sock = b_link->from_socket(); BL::NodeSocket b_to_sock = b_link->to_socket(); - SocketPair from_pair, to_pair; - - /* links without a node pointer are connections to group inputs/outputs */ - - /* from sock */ - if(b_from_node) { - if (b_from_node.mute() || b_from_node.is_a(&RNA_NodeGroup)) - from_pair = proxy_map[b_from_sock.ptr.data]; - else - from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock); - } - else - from_pair = sockets_map[b_from_sock.ptr.data]; - - /* to sock */ - if(b_to_node) { - if (b_to_node.mute() || b_to_node.is_a(&RNA_NodeGroup)) - to_pair = proxy_map[b_to_sock.ptr.data]; - else - to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock); - } - else - to_pair = sockets_map[b_to_sock.ptr.data]; + ShaderOutput *output = 0; + ShaderInput *input = 0; + + PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data); + if (output_it != output_map.end()) + output = output_it->second; + PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data); + if (input_it != input_map.end()) + input = input_it->second; /* either node may be NULL when the node was not exported, typically * because the node type is not supported */ - if(from_pair.first && to_pair.first) { - ShaderOutput *output = from_pair.first->output(from_pair.second.c_str()); - ShaderInput *input = to_pair.first->input(to_pair.second.c_str()); - + if(output && input) graph->connect(output, input); - } } } @@ -891,10 +807,10 @@ void BlenderSync::sync_materials(bool update_all) /* create nodes */ if(b_mat->use_nodes() && b_mat->node_tree()) { - PtrSockMap sock_to_node; + ProxyMap proxy_map; BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map); } else { ShaderNode *closure, *out; @@ -932,10 +848,10 @@ void BlenderSync::sync_world(bool update_all) /* create nodes */ if(b_world && b_world.use_nodes() && b_world.node_tree()) { - PtrSockMap sock_to_node; + ProxyMap proxy_map; BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map); } else if(b_world) { ShaderNode *closure, *out; @@ -991,10 +907,10 @@ void BlenderSync::sync_lamps(bool update_all) if(b_lamp->use_nodes() && b_lamp->node_tree()) { shader->name = b_lamp->name().c_str(); - PtrSockMap sock_to_node; + ProxyMap proxy_map; BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map); } else { ShaderNode *closure, *out; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 976ed875211..bd4852d08e1 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -202,30 +202,60 @@ static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_a return layer; } -#if 0 static inline float3 get_float3(PointerRNA& ptr, const char *name) { float3 f; RNA_float_get_array(&ptr, name, &f.x); return f; } -#endif + +static inline void set_float3(PointerRNA& ptr, const char *name, float3 value) +{ + RNA_float_set_array(&ptr, name, &value.x); +} + +static inline float4 get_float4(PointerRNA& ptr, const char *name) +{ + float4 f; + RNA_float_get_array(&ptr, name, &f.x); + return f; +} + +static inline void set_float4(PointerRNA& ptr, const char *name, float4 value) +{ + RNA_float_set_array(&ptr, name, &value.x); +} static inline bool get_boolean(PointerRNA& ptr, const char *name) { return RNA_boolean_get(&ptr, name)? true: false; } +static inline void set_boolean(PointerRNA& ptr, const char *name, bool value) +{ + RNA_boolean_set(&ptr, name, (int)value); +} + static inline float get_float(PointerRNA& ptr, const char *name) { return RNA_float_get(&ptr, name); } +static inline void set_float(PointerRNA& ptr, const char *name, float value) +{ + RNA_float_set(&ptr, name, value); +} + static inline int get_int(PointerRNA& ptr, const char *name) { return RNA_int_get(&ptr, name); } +static inline void set_int(PointerRNA& ptr, const char *name, int value) +{ + RNA_int_set(&ptr, name, value); +} + static inline int get_enum(PointerRNA& ptr, const char *name) { return RNA_enum_get(&ptr, name); @@ -242,6 +272,32 @@ static inline string get_enum_identifier(PointerRNA& ptr, const char *name) return string(identifier); } +static inline void set_enum(PointerRNA& ptr, const char *name, int value) +{ + RNA_enum_set(&ptr, name, value); +} + +static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier) +{ + RNA_enum_set_identifier(&ptr, name, identifier.c_str()); +} + +static inline string get_string(PointerRNA& ptr, const char *name) +{ + char cstrbuf[1024]; + char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf)); + string str(cstr); + if (cstr != cstrbuf) + MEM_freeN(cstr); + + return str; +} + +static inline void set_string(PointerRNA& ptr, const char *name, const string &value) +{ + RNA_string_set(&ptr, name, value.c_str()); +} + /* Relative Paths */ static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path) diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 61b5bd83534..c6b9ae08508 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -43,6 +43,8 @@ class OSLCompiler; * Data type for inputs and outputs */ enum ShaderSocketType { + SHADER_SOCKET_UNDEFINED, + SHADER_SOCKET_FLOAT, SHADER_SOCKET_INT, SHADER_SOCKET_COLOR, diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 8ac12242e15..398b9f0a758 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1242,15 +1242,14 @@ void ConvertNode::compile(OSLCompiler& compiler) /* Proxy */ -ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_) +ProxyNode::ProxyNode(ShaderSocketType type_) : ShaderNode("proxy") { - from = from_; - to = to_; + type = type_; special_type = SHADER_SPECIAL_TYPE_PROXY; - add_input("Input", from); - add_output("Output", to); + add_input("Input", type); + add_output("Output", type); } void ProxyNode::compile(SVMCompiler& compiler) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 3609497e5ce..1efe4ae076d 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -190,10 +190,10 @@ public: class ProxyNode : public ShaderNode { public: - ProxyNode(ShaderSocketType from, ShaderSocketType to); + ProxyNode(ShaderSocketType type); SHADER_NODE_BASE_CLASS(ProxyNode) - ShaderSocketType from, to; + ShaderSocketType type; }; class BsdfNode : public ShaderNode { diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 56158278e29..f5585babf5c 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -468,6 +468,7 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) parameter(param_name.c_str(), input->value_string); break; case SHADER_SOCKET_CLOSURE: + case SHADER_SOCKET_UNDEFINED: break; } } diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp index 6011de0bddb..67f1ea29533 100644 --- a/intern/smoke/intern/smoke_API.cpp +++ b/intern/smoke/intern/smoke_API.cpp @@ -172,17 +172,25 @@ extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles) { *dens = fluid->_density; - *fuel = fluid->_fuel; - *react = fluid->_react; - *flame = fluid->_flame; - *heat = fluid->_heat; - *heatold = fluid->_heatOld; + if(fuel) + *fuel = fluid->_fuel; + if(react) + *react = fluid->_react; + if(flame) + *flame = fluid->_flame; + if(heat) + *heat = fluid->_heat; + if(heatold) + *heatold = fluid->_heatOld; *vx = fluid->_xVelocity; *vy = fluid->_yVelocity; *vz = fluid->_zVelocity; - *r = fluid->_color_r; - *g = fluid->_color_g; - *b = fluid->_color_b; + if(r) + *r = fluid->_color_r; + if(g) + *g = fluid->_color_g; + if(b) + *b = fluid->_color_b; *obstacles = fluid->_obstacles; *dt = fluid->_dt; *dx = fluid->_dx; @@ -195,12 +203,18 @@ extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **r return; *dens = wt->_densityBig; - *fuel = wt->_fuelBig; - *react = wt->_reactBig; - *flame = wt->_flameBig; - *r = wt->_color_rBig; - *g = wt->_color_gBig; - *b = wt->_color_bBig; + if(fuel) + *fuel = wt->_fuelBig; + if(react) + *react = wt->_reactBig; + if(flame) + *flame = wt->_flameBig; + if(r) + *r = wt->_color_rBig; + if(g) + *g = wt->_color_gBig; + if(b) + *b = wt->_color_bBig; *tcu = wt->_tcU; *tcv = wt->_tcV; *tcw = wt->_tcW; diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py index 2514873d137..925166a3d8b 100644 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py @@ -163,7 +163,7 @@ class SpellChecker(): "uncomment", "undeformed", "undistort", "undistortion", - "ungroup", + "ungroup", "ungrouped", "unhide", "unindent", "unkeyed", diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 4398b1721f7..f42fd8e3107 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -485,17 +485,6 @@ class Text(bpy_types.ID): ) -class NodeSocket(StructRNA): # , metaclass=RNAMeta - __slots__ = () - - @property - def links(self): - """List of node links from or to this socket""" - return tuple(link for link in self.id_data.links - if (link.from_socket == self or - link.to_socket == self)) - - # values are module: [(cls, path, line), ...] TypeMap = {} @@ -757,3 +746,147 @@ class Region(StructRNA): return None + +class NodeTree(bpy_types.ID, metaclass=RNAMetaPropGroup): + __slots__ = () + + +class NodeSocketTemplate(): + type = 'UNDEFINED' + + # Default implementation: + # Create a single property using the socket template's 'value_property' attribute + # value_property should be created in the __init__ function + # + # If necessary this function can be overloaded in subclasses, e.g. to create multiple value properties + def define_node_properties(self, node_type, prefix): + if hasattr(self, "value_property"): + setattr(node_type, prefix+"value", self.value_property) + + def init_socket(self, socket): + socket.type = self.type + if hasattr(self, "value_property"): + socket.value_property = self.value_property[1]['attr'] + + +def gen_valid_identifier(seq): + # get an iterator + itr = iter(seq) + # pull characters until we get a legal one for first in identifer + for ch in itr: + if ch == '_' or ch.isalpha(): + yield ch + break + # pull remaining characters and yield legal ones for identifier + for ch in itr: + if ch == '_' or ch.isalpha() or ch.isdigit(): + yield ch + +def sanitize_identifier(name): + return ''.join(gen_valid_identifier(name)) + +def unique_identifier(name, identifier_list): + # First some basic sanitation, to make a usable identifier string from the name + base = sanitize_identifier(name) + # Now make a unique identifier by appending an unused index + identifier = base + index = 0 + while identifier in identifier_list: + index += 1 + identifier = base + str(index) + return identifier + +class RNAMetaNode(RNAMetaPropGroup): + def __new__(cls, name, bases, classdict, **args): + # Wrapper for node.init, to add sockets from templates + + def create_sockets(self): + inputs = getattr(self, 'input_templates', None) + if inputs: + for temp in inputs: + socket = self.inputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier) + temp.init_socket(socket) + outputs = getattr(self, 'output_templates', None) + if outputs: + for temp in outputs: + socket = self.outputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier) + temp.init_socket(socket) + + init_base = classdict.get('init', None) + if init_base: + def init_node(self, context): + create_sockets(self) + init_base(self, context) + else: + def init_node(self, context): + create_sockets(self) + + classdict['init'] = init_node + + # Create the regular class + result = RNAMetaPropGroup.__new__(cls, name, bases, classdict) + + # Add properties from socket templates + inputs = classdict.get('input_templates', None) + if inputs: + for i, temp in enumerate(inputs): + temp.identifier = unique_identifier(temp.name, [t.identifier for t in inputs[0:i]]) + temp.define_node_properties(result, "input_"+temp.identifier+"_") + outputs = classdict.get('output_templates', None) + if outputs: + for i, temp in enumerate(outputs): + temp.identifier = unique_identifier(temp.name, [t.identifier for t in outputs[0:i]]) + temp.define_node_properties(result, "output_"+temp.identifier+"_") + + return result + + +class Node(StructRNA, metaclass=RNAMetaNode): + __slots__ = () + + @classmethod + def poll(cls, ntree): + return True + + +class NodeSocket(StructRNA, metaclass=RNAMetaPropGroup): + __slots__ = () + + @property + def links(self): + """List of node links from or to this socket""" + return tuple(link for link in self.id_data.links + if (link.from_socket == self or + link.to_socket == self)) + + +class NodeSocketInterface(StructRNA, metaclass=RNAMetaPropGroup): + __slots__ = () + + +# These are intermediate subclasses, need a bpy type too +class CompositorNode(Node): + __slots__ = () + + @classmethod + def poll(cls, ntree): + return ntree.bl_idname == 'CompositorNodeTree' + + def update(self): + self.tag_need_exec() + +class ShaderNode(Node): + __slots__ = () + + @classmethod + def poll(cls, ntree): + return ntree.bl_idname == 'ShaderNodeTree' + + +class TextureNode(Node): + __slots__ = () + + @classmethod + def poll(cls, ntree): + return ntree.bl_idname == 'TextureNodeTree' + diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py index bc0224db765..9839e0ee092 100644 --- a/release/scripts/startup/bl_operators/node.py +++ b/release/scripts/startup/bl_operators/node.py @@ -100,75 +100,55 @@ class NODE_OT_add_node(NodeAddOperator, Operator): return result -# XXX These node item lists should actually be generated by a callback at -# operator execution time (see node_type_items below), -# using the active node tree from the context. -# Due to a difficult bug in bpy this is not possible -# (item list memory gets freed too early), -# so for now just copy the static item lists to these global variables. -# -# In the custom_nodes branch, the static per-tree-type node items are replaced -# by a single independent type list anyway (with a poll function to limit node -# types to the respective trees). So this workaround is only temporary. - -# lazy init -node_type_items_dict = {} - -# Prefixes used to distinguish base node types and node groups -node_type_prefix = 'NODE_' -node_group_prefix = 'GROUP_' - - -# Generate a list of enum items for a given node class -# Copy existing type enum, adding a prefix to distinguish from node groups -# Skip the base node group type, -# node groups will be added below for all existing group trees -def node_type_items(node_class): - return [(node_type_prefix + item.identifier, item.name, item.description) - for item in node_class.bl_rna.properties['type'].enum_items - if item.identifier != 'GROUP'] - - -# Generate items for node group types -# Filter by the given tree_type -# Node group trees don't have a description property yet -# (could add this as a custom property though) -def node_group_items(tree_type): - return [(node_group_prefix + group.name, group.name, '') - for group in bpy.data.node_groups if group.type == tree_type] +def node_classes_iter(base=bpy.types.Node): + """ + Yields all true node classes by checking for the is_registered_node_type classmethod. + Node types can use specialized subtypes of bpy.types.Node, which are not usable + nodes themselves (e.g. CompositorNode). + """ + if base.is_registered_node_type(): + yield base + for subclass in base.__subclasses__(): + for node_class in node_classes_iter(subclass): + yield node_class + + +def node_class_items_iter(node_class, context): + identifier = node_class.bl_rna.identifier + # XXX Checking for explicit group node types is stupid. + # This should be replaced by a generic system of generating + # node items via callback. + # Group node_tree pointer should also use a poll function to filter the library list, + # but cannot do that without a node instance here. A node callback could just use the internal poll function. + if identifier in {'ShaderNodeGroup', 'CompositorNodeGroup', 'TextureNodeGroup'}: + tree_idname = context.space_data.edit_tree.bl_idname + for group in bpy.data.node_groups: + if group.bl_idname == tree_idname: + yield (group.name, "", {"node_tree":group}) # XXX empty string should be replaced by description from tree + else: + yield (node_class.bl_rna.name, node_class.bl_rna.description, {}) -# Returns the enum item list for the edited tree in the context -def node_type_items_cb(self, context): +def node_items_iter(context): snode = context.space_data if not snode: - return () + return tree = snode.edit_tree if not tree: - return () - - # Lists of basic node types for each - if not node_type_items_dict: - node_type_items_dict.update({ - 'SHADER': node_type_items(bpy.types.ShaderNode), - 'COMPOSITING': node_type_items(bpy.types.CompositorNode), - 'TEXTURE': node_type_items(bpy.types.TextureNode), - }) - - # XXX Does not work correctly, see comment above - ''' - return [(item.identifier, item.name, item.description, item.value) - for item in - tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items] - ''' - - if tree.type in node_type_items_dict: - return node_type_items_dict[tree.type] + node_group_items(tree.type) - else: - return () + return + + for node_class in node_classes_iter(): + if node_class.poll(tree): + for item in node_class_items_iter(node_class, context): + yield (node_class,) + item + + +# Create an enum list from node class items +def node_type_items_cb(self, context): + return [(str(index), item[1], item[2]) for index, item in enumerate(node_items_iter(context))] -class NODE_OT_add_search(Operator): +class NODE_OT_add_search(NodeAddOperator, Operator): '''Add a node to the active tree''' bl_idname = "node.add_search" bl_label = "Search and Add Node" @@ -182,55 +162,48 @@ class NODE_OT_add_search(Operator): items=node_type_items_cb, ) - _node_type_items_dict = None + def execute(self, context): + for index, item in enumerate(node_items_iter(context)): + if str(index) == self.type: + node = self.create_node(context, item[0].bl_rna.identifier) + for prop,value in item[3].items(): + setattr(node, prop, value) + break + return {'FINISHED'} - def create_node(self, context): - space = context.space_data - tree = space.edit_tree + def invoke(self, context, event): + self.store_mouse_cursor(context, event) + # Delayed execution in the search popup + context.window_manager.invoke_search_popup(self) + return {'CANCELLED'} - # Enum item identifier has an additional prefix to - # distinguish base node types from node groups - item = self.type - if item.startswith(node_type_prefix): - # item means base node type - node = tree.nodes.new(type=item[len(node_type_prefix):]) - elif item.startswith(node_group_prefix): - # item means node group type - node = tree.nodes.new( - type='GROUP', - group=bpy.data.node_groups[item[len(node_group_prefix):]]) - else: - return None - for n in tree.nodes: - if n == node: - node.select = True - tree.nodes.active = node - else: - node.select = False - node.location = space.cursor_location - return node +# Simple basic operator for adding a node without further initialization +class NODE_OT_add_node(NodeAddOperator, bpy.types.Operator): + '''Add a node to the active tree''' + bl_idname = "node.add_node" + bl_label = "Add Node" - @classmethod - def poll(cls, context): - space = context.space_data - # needs active node editor and a tree to add nodes to - return (space.type == 'NODE_EDITOR' and space.edit_tree) + type = StringProperty(name="Node Type", description="Node type") def execute(self, context): - self.create_node(context) + node = self.create_node(context, self.type) return {'FINISHED'} - def invoke(self, context, event): - space = context.space_data - v2d = context.region.view2d - # convert mouse position to the View2D for later node placement - space.cursor_location = v2d.region_to_view(event.mouse_region_x, - event.mouse_region_y) +class NODE_OT_add_group_node(NodeAddOperator, bpy.types.Operator): + '''Add a group node to the active tree''' + bl_idname = "node.add_group_node" + bl_label = "Add Group Node" - context.window_manager.invoke_search_popup(self) - return {'CANCELLED'} + type = StringProperty(name="Node Type", description="Node type") + grouptree = StringProperty(name="Group tree", description="Group node tree name") + + def execute(self, context): + node = self.create_node(context, self.type) + node.node_tree = bpy.data.node_groups[self.grouptree] + + return {'FINISHED'} class NODE_OT_collapse_hide_unused_toggle(Operator): @@ -261,3 +234,24 @@ class NODE_OT_collapse_hide_unused_toggle(Operator): socket.hide = hide return {'FINISHED'} + + +class NODE_OT_tree_path_parent(Operator): + '''Go to parent node tree''' + bl_idname = "node.tree_path_parent" + bl_label = "Parent Node Tree" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + space = context.space_data + # needs active node editor and a tree + return (space.type == 'NODE_EDITOR' and len(space.path) > 1) + + def execute(self, context): + space = context.space_data + + space.path.pop() + + return {'FINISHED'} + diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 1865b049a03..e739c5ea5d4 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -44,8 +44,8 @@ class NODE_HT_header(Header): row.menu("NODE_MT_node") layout.prop(snode, "tree_type", text="", expand=True) - - if snode.tree_type == 'SHADER': + + if snode.tree_type == 'ShaderNodeTree': if scene.render.use_shading_nodes: layout.prop(snode, "shader_type", text="", expand=True) @@ -65,7 +65,7 @@ class NODE_HT_header(Header): if snode_id: layout.prop(snode_id, "use_nodes") - elif snode.tree_type == 'TEXTURE': + elif snode.tree_type == 'TextureNodeTree': layout.prop(snode, "texture_type", text="", expand=True) if id_from: @@ -76,7 +76,7 @@ class NODE_HT_header(Header): if snode_id: layout.prop(snode_id, "use_nodes") - elif snode.tree_type == 'COMPOSITING': + elif snode.tree_type == 'CompositorNodeTree': layout.prop(snode_id, "use_nodes") layout.prop(snode_id.render, "use_free_unused_nodes", text="Free Unused") layout.prop(snode, "show_backdrop") @@ -84,6 +84,13 @@ class NODE_HT_header(Header): row = layout.row(align=True) row.prop(snode, "backdrop_channels", text="", expand=True) layout.prop(snode, "use_auto_render") + + else: + # Custom node tree is edited as independent ID block + layout.template_ID(snode, "node_tree", new="node.new_node_tree") + + layout.prop(snode, "pin", text="") + layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT') layout.separator() @@ -182,6 +189,7 @@ class NODE_MT_node(Menu): layout.operator("node.group_edit") layout.operator("node.group_ungroup") layout.operator("node.group_make") + layout.operator("node.group_insert") layout.separator() @@ -208,7 +216,7 @@ class NODE_PT_properties(Panel): @classmethod def poll(cls, context): snode = context.space_data - return snode.tree_type == 'COMPOSITING' + return snode.tree_type == 'CompositorNodeTree' def draw_header(self, context): snode = context.space_data @@ -237,7 +245,7 @@ class NODE_PT_quality(bpy.types.Panel): @classmethod def poll(cls, context): snode = context.space_data - return snode.tree_type == 'COMPOSITING' and snode.node_tree is not None + return snode.tree_type == 'CompositorNodeTree' and snode.node_tree is not None def draw(self, context): layout = self.layout @@ -276,5 +284,28 @@ class NODE_MT_node_color_specials(Menu): layout.operator("node.node_copy_color", icon='COPY_ID') +class NODE_UL_interface_sockets(bpy.types.UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + socket = item + color = socket.draw_color(context) + + if self.layout_type in {'DEFAULT', 'COMPACT'}: + row = layout.row(align=True) + + # inputs get icon on the left + if socket.in_out == 'IN': + row.template_node_socket(color) + + row.label(text=socket.name, icon_value=icon) + + # outputs get icon on the right + if socket.in_out == 'OUT': + row.template_node_socket(color) + + elif self.layout_type in {'GRID'}: + layout.alignment = 'CENTER' + layout.template_node_socket(color) + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py new file mode 100644 index 00000000000..485ee0ebe05 --- /dev/null +++ b/release/scripts/templates_py/custom_nodes.py @@ -0,0 +1,159 @@ +import bpy +# XXX these don't work yet ... +#from bpy_types import NodeTree, Node, NodeSocket + +# Implementation of custom nodes from Python + + +# Shortcut for node type menu +def add_nodetype(layout, type): + layout.operator("node.add_node", text=type.bl_label).type = type.bl_rna.identifier + +# Derived from the NodeTree base type, similar to Menu, Operator, Panel, etc. +class MyCustomTree(bpy.types.NodeTree): + # Description string + '''A custom node tree type that will show up in the node editor header''' + # Optional identifier string. If not explicitly defined, the python class name is used. + bl_idname = 'CustomTreeType' + # Label for nice name display + bl_label = 'Custom Node Tree' + # Icon identifier + # NOTE: If no icon is defined, the node tree will not show up in the editor header! + # This can be used to make additional tree types for groups and similar nodes (see below) + # Only one base tree class is needed in the editor for selecting the general category + bl_icon = 'NODETREE' + + def draw_add_menu(self, context, layout): + layout.label("Hello World!") + add_nodetype(layout, bpy.types.CustomNodeType) + add_nodetype(layout, bpy.types.MyCustomGroup) + + +# Custom socket type +class MyCustomSocket(bpy.types.NodeSocket): + # Description string + '''Custom node socket type''' + # Optional identifier string. If not explicitly defined, the python class name is used. + bl_idname = 'CustomSocketType' + # Label for nice name display + bl_label = 'Custom Node Socket' + # Socket color + bl_color = (1.0, 0.4, 0.216, 0.5) + + # Enum items list + my_items = [ + ("DOWN", "Down", "Where your feet are"), + ("UP", "Up", "Where your head should be"), + ("LEFT", "Left", "Not right"), + ("RIGHT", "Right", "Not left") + ] + + myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP') + + # Optional function for drawing the socket input value + def draw(self, context, layout, node): + layout.prop(self, "myEnumProperty", text=self.name) + + +# Base class for all custom nodes in this tree type. +# Defines a poll function to enable instantiation. +class MyCustomTreeNode : + @classmethod + def poll(cls, ntree): + return ntree.bl_idname == 'CustomTreeType' + +# Derived from the Node base type. +class MyCustomNode(bpy.types.Node, MyCustomTreeNode): + # === Basics === + # Description string + '''A custom node''' + # Optional identifier string. If not explicitly defined, the python class name is used. + bl_idname = 'CustomNodeType' + # Label for nice name display + bl_label = 'Custom Node' + # Icon identifier + bl_icon = 'SOUND' + + # === Custom Properties === + # These work just like custom properties in ID data blocks + # Extensive information can be found under + # http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties + myStringProperty = bpy.props.StringProperty() + myFloatProperty = bpy.props.FloatProperty(default=3.1415926) + + # === Optional Functions === + # Initialization function, called when a new node is created. + # This is the most common place to create the sockets for a node, as shown below. + # NOTE: this is not the same as the standard __init__ function in Python, which is + # a purely internal Python method and unknown to the node system! + def init(self, context): + self.inputs.new('CustomSocketType', "Hello") + self.inputs.new('NodeSocketFloat', "World") + self.inputs.new('NodeSocketVector', "!") + + self.outputs.new('NodeSocketColor', "How") + self.outputs.new('NodeSocketColor', "are") + self.outputs.new('NodeSocketFloat', "you") + + # Copy function to initialize a copied node from an existing one. + def copy(self, node): + print("Copying from node ", node) + + # Free function to clean up on removal. + def free(self): + print("Removing node ", self, ", Goodbye!") + + # Additional buttons displayed on the node. + def draw_buttons(self, context, layout): + layout.label("Node settings") + layout.prop(self, "myFloatProperty") + + # Detail buttons in the sidebar. + # If this function is not defined, the draw_buttons function is used instead + def draw_buttons_ext(self, context, layout): + layout.prop(self, "myFloatProperty") + # myStringProperty button will only be visible in the sidebar + layout.prop(self, "myStringProperty") + + +# A customized group-like node. +class MyCustomGroup(bpy.types.NodeGroup, MyCustomTreeNode): + # === Basics === + # Description string + '''A custom group node''' + # Label for nice name display + bl_label = 'Custom Group Node' + bl_group_tree_idname = 'CustomTreeType' + + orks = bpy.props.IntProperty(default=3) + dwarfs = bpy.props.IntProperty(default=12) + wizards = bpy.props.IntProperty(default=1) + + # Additional buttons displayed on the node. + def draw_buttons(self, context, layout): + col = layout.column(align=True) + col.prop(self, "orks") + col.prop(self, "dwarfs") + col.prop(self, "wizards") + + layout.label("The Node Tree:") + layout.prop(self, "node_tree", text="") + + +def register(): + bpy.utils.register_class(MyCustomTree) + bpy.utils.register_class(MyCustomSocket) + bpy.utils.register_class(MyCustomNode) + bpy.utils.register_class(MyCustomGroup) + + +def unregister(): + bpy.utils.unregister_class(MyCustomTree) + bpy.utils.unregister_class(MyCustomSocket) + bpy.utils.unregister_class(MyCustomNode) + bpy.utils.unregister_class(MyCustomGroup) + + +if __name__ == "__main__": + register() + diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index a53fc15714e..d03c631f7a1 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 266 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 80955729326..d9a311b7e13 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -32,8 +32,21 @@ * \ingroup bke */ +#include "BLI_ghash.h" +#include "BLI_utildefines.h" + #include "DNA_listBase.h" +/* for FOREACH_NODETREE */ +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" + +#include "RNA_types.h" + /* not very important, but the stack solver likes to know a maximum */ #define MAX_SOCKET 64 @@ -43,7 +56,10 @@ struct bNodeLink; struct bNodeSocket; struct bNodeStack; struct bNodeTree; +struct bNodeTreeType; struct bNodeTreeExec; +struct bNodeExecContext; +struct bNodeExecData; struct GPUMaterial; struct GPUNode; struct GPUNodeStack; @@ -65,6 +81,7 @@ struct ARegion; struct Object; struct ColorManagedViewSettings; struct ColorManagedDisplaySettings; +struct bNodeInstanceHash; /* ************** NODE TYPE DEFINITIONS ***** */ @@ -72,9 +89,9 @@ struct ColorManagedDisplaySettings; * Can be used to quickly define a list of static sockets for a node, * which are added to each new node of that type. * - * \deprecated New nodes should add default sockets in the initialization - * function instead. This struct is mostly kept for old nodes and should - * be removed some time. + * \deprecated This struct is used by C nodes to define templates as simple + * static struct lists. These are converted to the new template collections + * in RNA types automatically. */ typedef struct bNodeSocketTemplate { int type, limit; @@ -86,38 +103,38 @@ typedef struct bNodeSocketTemplate { /* after this line is used internal only */ struct bNodeSocket *sock; /* used to hold verified socket */ + char identifier[64]; /* generated from name */ } bNodeSocketTemplate; -typedef void (*NodeSocketButtonFunction)(const struct bContext *C, struct uiBlock *block, - struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, - const char *name, int x, int y, int width); - /** Defines a socket type. * Defines the appearance and behavior of a socket in the UI. */ typedef struct bNodeSocketType { - int type; - char ui_name[64]; /* MAX_NAME */ - char ui_description[128]; - int ui_icon; - char ui_color[4]; + char idname[64]; /* identifier name */ + + void (*draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr); + void (*draw_color)(struct bContext *C, struct PointerRNA *ptr, struct PointerRNA *node_ptr, float *r_color); + + void (*interface_draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr); + void (*interface_draw_color)(struct bContext *C, struct PointerRNA *ptr, float *r_color); + void (*interface_register_properties)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct StructRNA *data_srna); + void (*interface_init_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock, const char *data_path); + void (*interface_from_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock); - const char *value_structname; - int value_structsize; + /* RNA integration */ + ExtensionRNA ext_socket; + ExtensionRNA ext_interface; - NodeSocketButtonFunction buttonfunc; + /* for standard socket types in C */ + int type, subtype; } bNodeSocketType; -/** Template for creating a node. - * Stored required parameters to make a new node of a specific type. - */ -typedef struct bNodeTemplate { - int type; - - struct Main *main; - struct Scene *scene; - struct bNodeTree *ngroup; /* group tree */ -} bNodeTemplate; +typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr, int linked); + +typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key); +typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata); +typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out); +typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat, struct bNode *node, struct bNodeExecData *execdata, struct GPUNodeStack *in, struct GPUNodeStack *out); /** Defines a node type. * Initial attributes and constants for a node as well as callback functions @@ -127,8 +144,13 @@ typedef struct bNodeType { void *next, *prev; short needs_free; /* set for allocated types that need to be freed */ + char idname[64]; /* identifier name */ int type; - char name[64]; /* MAX_NAME */ + + char ui_name[64]; /* MAX_NAME */ + char ui_description[256]; + int ui_icon; + float width, minwidth, maxwidth; float height, minheight, maxheight; short nclass, flag, compatibility; @@ -139,7 +161,8 @@ typedef struct bNodeType { char storagename[64]; /* struct name for DNA */ /// Main draw function for the node. - void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node); + void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, + struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); /// Updates the node geometry attributes according to internal state before actual drawing. void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); /// Draw the option buttons on the node. @@ -150,8 +173,11 @@ typedef struct bNodeType { void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y); /// Draw a node socket. Default draws the input value button. - NodeSocketButtonFunction drawinputfunc; - NodeSocketButtonFunction drawoutputfunc; + /* XXX deprecated, only used for the OutputFile node, + * should be removed at some point. + */ + NodeSocketDrawFunction drawinputfunc; + NodeSocketDrawFunction drawoutputfunc; /// Optional custom label function for the node header. const char *(*labelfunc)(struct bNode *); @@ -168,45 +194,42 @@ typedef struct bNodeType { void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id); /// Initialize a new node instance of this type after creation. - void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp); - /// Free the custom storage data. - void (*freestoragefunc)(struct bNode *node); - /// Make a copy of the custom storage data. - void (*copystoragefunc)(struct bNode *node, struct bNode *target); + void (*initfunc)(struct bNodeTree *ntree, struct bNode *node); + /// Free the node instance. + void (*freefunc)(struct bNode *node); + /// Make a copy of the node instance. + void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node); - /// Create a template from an existing node. - struct bNodeTemplate (*templatefunc)(struct bNode *); - /** If a node can be made from the template in the given node tree. - * \note Node groups can not be created inside their own node tree. - */ - int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); + /* Registerable API callback versions, called in addition to C callbacks */ + void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr); + void (*freefunc_api)(struct PointerRNA *ptr); + void (*copyfunc_api)(struct PointerRNA *ptr, struct bNode *src_node); - /// Initialize a node tree associated to this node type. - void (*inittreefunc)(struct bNodeTree *ntree); - /// Update a node tree associated to this node type. - void (*updatetreefunc)(struct bNodeTree *ntree); - - /* group edit callbacks for operators */ - /* XXX this is going to be changed as required by the UI */ - struct bNodeTree *(*group_edit_get)(struct bNode *node); - struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit); - void (*group_edit_clear)(struct bNode *node); + /* can this node type be added to a node tree */ + int (*poll)(struct bNodeType *ntype, struct bNodeTree *nodetree); + /* can this node be added to a node tree */ + int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree); /* Update the internal links list, for muting and disconnect operators. */ void (*update_internal_links)(struct bNodeTree *, struct bNode *node); /* **** execution callbacks **** */ - void *(*initexecfunc)(struct bNode *node); - void (*freeexecfunc)(struct bNode *node, void *nodedata); - void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **); - /* XXX this alternative exec function has been added to avoid changing all node types. - * when a final generic version of execution code is defined, this will be changed anyway - */ - void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **); + NodeInitExecFunction initexecfunc; + NodeFreeExecFunction freeexecfunc; + NodeExecFunction execfunc; /* gpu */ - int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out); - /* extended gpu function */ - int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out); + NodeGPUExecFunction gpufunc; + + /* Group type static info + * + * XXX This data is needed by group operators. If these operators could be implemented completely in Python, + * the static data could instead be stored in Python classes and would need no special treatment. + * Due to the way group operators move nodes between data blocks this is currently not possible. + */ + char group_tree_idname[64]; /* tree type associated to the group node type */ + + /* RNA integration */ + ExtensionRNA ext; } bNodeType; /* node->exec, now in use for composites (#define for break is same as ready yes) */ @@ -245,6 +268,7 @@ typedef struct bNodeType { #define NODE_CLASS_TRANSFORM 30 #define NODE_CLASS_COMBINE 31 #define NODE_CLASS_SCRIPT 32 +#define NODE_CLASS_INTERFACE 33 #define NODE_CLASS_SHADER 40 #define NODE_CLASS_LAYOUT 100 @@ -258,10 +282,6 @@ typedef struct bNodeType { #define NODE_RESIZE_RIGHT 4 #define NODE_RESIZE_LEFT 8 -/* enum values for input/output */ -#define SOCK_IN 1 -#define SOCK_OUT 2 - typedef enum eNodeSizePreset { NODE_SIZE_DEFAULT, NODE_SIZE_SMALL, @@ -270,19 +290,26 @@ typedef enum eNodeSizePreset { struct bNodeTreeExec; -typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree); typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name); typedef struct bNodeTreeType { int type; /* type identifier */ - char idname[64]; /* id name for RNA identification */ - - ListBase node_types; /* type definitions */ + char idname[64]; /* identifier name */ + + char ui_name[64]; + char ui_description[256]; + int ui_icon; /* callbacks */ void (*free_cache)(struct bNodeTree *ntree); void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node); - void (*foreach_nodetree)(struct Main *main, void *calldata, bNodeTreeCallback func); /* iteration over all node trees */ void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */ + /* Add menu for this node tree. */ + void (*draw_add_menu)(const struct bContext *C, struct uiLayout *layout, struct bNodeTree *ntree); + /* Check visibility in the node editor */ + int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype); + /* Select a node tree from the context */ + void (*get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype, + struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from); /* calls allowing threaded composite */ void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree); @@ -291,23 +318,37 @@ typedef struct bNodeTreeType { /* Tree update. Overrides nodetype->updatetreefunc! */ void (*update)(struct bNodeTree *ntree); - /* Node update. Overrides nodetype->updatefunc! */ - void (*update_node)(struct bNodeTree *ntree, struct bNode *node); int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link); - - /* Default internal linking. */ - void (*update_internal_links)(struct bNodeTree *, struct bNode *node); + + /* RNA integration */ + ExtensionRNA ext; } bNodeTreeType; + /* ************** GENERIC API, TREES *************** */ -struct bNodeTreeType *ntreeGetType(int type); -struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree); -struct bNodeSocketType *ntreeGetSocketType(int type); +struct bNodeTreeType *ntreeTypeFind(const char *idname); +void ntreeTypeAdd(struct bNodeTreeType *nt); +void ntreeTypeFreeLink(struct bNodeTreeType *nt); +struct GHashIterator *ntreeTypeGetIterator(void); + +/* helper macros for iterating over tree types */ +#define NODE_TREE_TYPES_BEGIN(ntype) \ +{ \ + GHashIterator *__node_tree_type_iter__ = ntreeTypeGetIterator(); \ + for (; BLI_ghashIterator_notDone(__node_tree_type_iter__); BLI_ghashIterator_step(__node_tree_type_iter__)) { \ + bNodeTreeType *ntype = BLI_ghashIterator_getValue(__node_tree_type_iter__); -struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, int type, int nodetype); -void ntreeInitTypes(struct bNodeTree *ntree); +#define NODE_TREE_TYPES_END \ + } \ + BLI_ghashIterator_free(__node_tree_type_iter__); \ +} + +void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree); +int ntreeIsValid(struct bNodeTree *ntree); + +struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname); /* copy/free funcs, need to manage ID users */ void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user); @@ -337,8 +378,6 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode * * new tree types have a per-output socket flag to indicate the final output to use explicitly. */ void ntreeSetOutput(struct bNodeTree *ntree); -void ntreeInitPreview(struct bNodeTree *, int xsize, int ysize); -void ntreeClearPreview(struct bNodeTree *ntree); void ntreeFreeCache(struct bNodeTree *ntree); @@ -348,29 +387,86 @@ struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree); void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree); void ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree); +/* ************** NODE TREE INTERFACE *************** */ + +struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree, int in_out, const char *identifier); +struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname, const char *name); +struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname, + struct bNodeSocket *next_sock, const char *name); +struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock); +struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNodeSocket *next_sock, + struct bNode *from_node, struct bNodeSocket *from_sock); +void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock); + +struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create); +void ntreeInterfaceTypeFree(struct bNodeTree *ntree); +void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree); + /* ************** GENERIC API, NODES *************** */ -struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *name, int type); -struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, struct bNodeSocket *next_sock, const char *name, int type); +struct bNodeType *nodeTypeFind(const char *idname); +void nodeRegisterType(struct bNodeType *ntype); +void nodeUnregisterType(struct bNodeType *ntype); +struct GHashIterator *nodeTypeGetIterator(void); + +/* helper macros for iterating over node types */ +#define NODE_TYPES_BEGIN(ntype) \ +{ \ + GHashIterator *__node_type_iter__ = nodeTypeGetIterator(); \ + for (; BLI_ghashIterator_notDone(__node_type_iter__); BLI_ghashIterator_step(__node_type_iter__)) { \ + bNodeType *ntype = BLI_ghashIterator_getValue(__node_type_iter__); + +#define NODE_TYPES_END \ + } \ + BLI_ghashIterator_free(__node_type_iter__); \ +} + +struct bNodeSocketType *nodeSocketTypeFind(const char *idname); +void nodeRegisterSocketType(struct bNodeSocketType *stype); +void nodeUnregisterSocketType(struct bNodeSocketType *stype); +struct GHashIterator *nodeSocketTypeGetIterator(void); +const char * nodeStaticSocketType(int type, int subtype); +const char * nodeStaticSocketInterfaceType(int type, int subtype); + +/* helper macros for iterating over node types */ +#define NODE_SOCKET_TYPES_BEGIN(stype) \ +{ \ + GHashIterator *__node_socket_type_iter__ = nodeSocketTypeGetIterator(); \ + for (; BLI_ghashIterator_notDone(__node_socket_type_iter__); BLI_ghashIterator_step(__node_socket_type_iter__)) { \ + bNodeSocketType *stype = BLI_ghashIterator_getValue(__node_socket_type_iter__); + +#define NODE_SOCKET_TYPES_END \ + } \ + BLI_ghashIterator_free(__node_socket_type_iter__); \ +} + +void nodeMakeDynamicType(struct bNode *node); +int nodeDynamicUnlinkText(struct ID *txtid); + +struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier); +struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname, + const char *identifier, const char *name); +struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname, + struct bNodeSocket *next_sock, const char *identifier, const char *name); +struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype, + const char *identifier, const char *name); +struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype, + struct bNodeSocket *next_sock, const char *identifier, const char *name); void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock); void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node); -void nodeAddToPreview(struct bNode *node, const float col[4], int x, int y, int do_manage); - -struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); +struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname); +struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type); void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node); void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node); -void nodeRegisterType(struct bNodeTreeType *ttype, struct bNodeType *ntype); -void nodeMakeDynamicType(struct bNode *node); -int nodeDynamicUnlinkText(struct ID *txtid); - void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node); struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); +int nodeLinkIsHidden(struct bNodeLink *link); void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node); void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry); @@ -380,15 +476,16 @@ void nodeAttachNode(struct bNode *node, struct bNode *parent); void nodeDetachNode(struct bNode *node); struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name); -int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex, int *in_out); +int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to); int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); +void nodeSetSelected(struct bNode *node, int select); void nodeSetActive(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeGetActive(struct bNodeTree *ntree); struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype); -int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); +bool nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); void nodeClearActive(struct bNodeTree *ntree); void nodeClearActiveID(struct bNodeTree *ntree, short idtype); struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); @@ -396,11 +493,9 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); int nodeUpdateID(struct bNodeTree *ntree, struct ID *id); void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node); - -void nodeFreePreview(struct bNode *node); +void nodeSynchronizeID(struct bNode *node, bool copy_to_id); int nodeSocketIsHidden(struct bNodeSocket *sock); -void nodeSocketSetType(struct bNodeSocket *sock, int type); /* Node Clipboard */ void BKE_node_clipboard_init(struct bNodeTree *ntree); @@ -412,78 +507,189 @@ const struct ListBase *BKE_node_clipboard_get_nodes(void); const struct ListBase *BKE_node_clipboard_get_links(void); int BKE_node_clipboard_get_type(void); +/* Node Instance Hash */ +typedef struct bNodeInstanceHash +{ + GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */ +} bNodeInstanceHash; + +typedef void (*bNodeInstanceValueFP)(void *value); + +extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE; + +bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, struct bNodeTree *ntree, struct bNode *node); + +bNodeInstanceHash *BKE_node_instance_hash_new(const char *info); +void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp); +void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value); +void *BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key); +int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp); +void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp); +void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key); +int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key); +int BKE_node_instance_hash_size(bNodeInstanceHash *hash); + +void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash); +void BKE_node_instance_hash_tag(bNodeInstanceHash *hash, void *value); +int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key); +void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp); + +typedef GHashIterator bNodeInstanceHashIterator; + +BLI_INLINE bNodeInstanceHashIterator *BKE_node_instance_hash_iterator_new(bNodeInstanceHash *hash) { return BLI_ghashIterator_new(hash->ghash); } +BLI_INLINE void BKE_node_instance_hash_iterator_init(bNodeInstanceHashIterator *iter, bNodeInstanceHash *hash) { BLI_ghashIterator_init(iter, hash->ghash); } +BLI_INLINE void BKE_node_instance_hash_iterator_free(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_free(iter); } +BLI_INLINE bNodeInstanceKey BKE_node_instance_hash_iterator_get_key(bNodeInstanceHashIterator *iter) { return *(bNodeInstanceKey *)BLI_ghashIterator_getKey(iter); } +BLI_INLINE void *BKE_node_instance_hash_iterator_get_value(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_getValue(iter); } +BLI_INLINE void BKE_node_instance_hash_iterator_step(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_step(iter); } +BLI_INLINE bool BKE_node_instance_hash_iterator_not_done(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_notDone(iter); } + +#define NODE_INSTANCE_HASH_ITER(iter_, hash_) \ + for (BKE_node_instance_hash_iterator_init(&iter_, hash_); \ + BKE_node_instance_hash_iterator_not_done(&iter_); \ + BKE_node_instance_hash_iterator_step(&iter_)) + + +/* Node Previews */ + +int BKE_node_preview_used(struct bNode *node); +bNodePreview *BKE_node_preview_verify(struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create); +bNodePreview *BKE_node_preview_copy(struct bNodePreview *preview); +void BKE_node_preview_free(struct bNodePreview *preview); +void BKE_node_preview_init_tree(struct bNodeTree *ntree, int xsize, int ysize, int create_previews); +void BKE_node_preview_free_tree(struct bNodeTree *ntree); +void BKE_node_preview_remove_unused(struct bNodeTree *ntree); +void BKE_node_preview_clear(struct bNodePreview *preview); +void BKE_node_preview_clear_tree(struct bNodeTree *ntree); + +void BKE_node_preview_sync_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree); +void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree); + +void BKE_node_preview_set_pixel(struct bNodePreview *preview, const float col[4], int x, int y, int do_manage); + + /* ************** NODE TYPE ACCESS *************** */ -struct bNodeTemplate nodeMakeTemplate(struct bNode *node); -int nodeValid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); const char *nodeLabel(struct bNode *node); struct bNodeTree *nodeGroupEditGet(struct bNode *node); struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit); void nodeGroupEditClear(struct bNode *node); +int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree); + /* Init a new node type struct with default values and callbacks */ -void node_type_base(struct bNodeTreeType *ttype, struct bNodeType *ntype, int type, - const char *name, short nclass, short flag); +void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +void node_type_base_custom(struct bNodeType *ntype, const char *idname, const char *name, short nclass, short flag); void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs); void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth); void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size); -void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp)); -void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp)); +void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node)); void node_type_storage(struct bNodeType *ntype, const char *storagename, - void (*freestoragefunc)(struct bNode *), - void (*copystoragefunc)(struct bNode *, struct bNode *)); + void (*freefunc)(struct bNode *node), + void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node)); void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *)); -void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *)); void node_type_update(struct bNodeType *ntype, void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node), void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id)); -void node_type_tree(struct bNodeType *ntype, - void (*inittreefunc)(struct bNodeTree *), - void (*updatetreefunc)(struct bNodeTree *)); -void node_type_group_edit(struct bNodeType *ntype, - struct bNodeTree *(*group_edit_get)(struct bNode *node), - struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit), - void (*group_edit_clear)(struct bNode *node)); - -void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, - struct bNodeStack **)); -void node_type_exec_new(struct bNodeType *ntype, - void *(*initexecfunc)(struct bNode *node), - void (*freeexecfunc)(struct bNode *node, void *nodedata), - void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, - struct bNodeStack **, struct bNodeStack **)); + +void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc); +void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc); void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *)); -void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, - struct GPUNodeStack *in, struct GPUNodeStack *out)); -void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, - void *nodedata, struct GPUNodeStack *in, - struct GPUNodeStack *out)); void node_type_compatibility(struct bNodeType *ntype, short compatibility); /* ************** COMMON NODES *************** */ +#define NODE_UNDEFINED -2 /* node type is not registered */ +#define NODE_CUSTOM -1 /* for dynamically registered custom types */ #define NODE_GROUP 2 -#define __NODE_FORLOOP 3 /* deprecated */ +#define __NODE_FORLOOP 3 /* deprecated */ #define __NODE_WHILELOOP 4 /* deprecated */ #define NODE_FRAME 5 #define NODE_REROUTE 6 +#define NODE_GROUP_INPUT 7 +#define NODE_GROUP_OUTPUT 8 -/* look up a socket on a group node by the internal group socket */ -struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock); -struct bNodeSocket *node_group_find_output(struct bNode *gnode, struct bNodeSocket *gsock); +void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree); -struct bNodeSocket *node_group_add_socket(struct bNodeTree *ngroup, const char *name, int type, int in_out); -struct bNodeSocket *node_group_expose_socket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out); -void node_group_expose_all_sockets(struct bNodeTree *ngroup); -void node_group_remove_socket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out); -struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBase *lb, int in_out, struct bNodeSocket *gsock); - -/* in node_common.c */ -void register_node_type_frame(struct bNodeTreeType *ttype); -void register_node_type_reroute(struct bNodeTreeType *ttype); +/* Utility macro for visiting every node tree in the library data, including local bNodeTree blocks in other IDs. + * This avoids the need for callback functions and allows executing code in a single inner code block. + * + * Variables: + * + * nodetree: The actual bNodeTree data block. + * Check nodetree->idname or nodetree->typeinfo to use only specific types. + * + * id: The owner of the bNodeTree data block. + * Same as nodetree if it's a linkable node tree from the library. + * + * Examples: + * + * FOREACH_NODETREE(bmain, nodetree) + * if (id == nodetree) + * printf("This is a linkable node tree"); + * FOREACH_NODETREE_END + * + * FOREACH_NODETREE(bmain, nodetree) + * if (nodetree->idname == "ShaderNodeTree") + * printf("This is a shader node tree); + * if (GS(id) == ID_MA) + * printf(" and it's owned by a material"); + * FOREACH_NODETREE_END + */ -void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *owner_id, struct bNodeTree *ntree); +#define FOREACH_NODETREE(bmain, _nodetree, _id) \ +{ \ + bNodeTree *_nodetree; \ + ID *_id; \ + bNodeTree *_ngroup = bmain->nodetree.first; \ + Scene *_scene = bmain->scene.first; \ + Material *_mat = bmain->mat.first; \ + Tex *_tex = bmain->tex.first; \ + Lamp *_lamp = bmain->lamp.first; \ + World *_world = bmain->world.first; \ + /* avoid compiler warning about unused variables */ \ + (void)_id; \ + (void)_nodetree; \ + do { \ + if (_ngroup) { \ + _nodetree = _ngroup; \ + _id = (ID *)_ngroup; \ + _ngroup = _ngroup->id.next; \ + } \ + else if (_scene) { \ + _nodetree = _scene->nodetree; \ + _id = (ID *)_scene; \ + _scene = _scene->id.next; \ + } \ + else if (_mat) { \ + _nodetree = _mat->nodetree; \ + _id = (ID *)_mat; \ + _mat = _mat->id.next; \ + } \ + else if (_tex) { \ + _nodetree = _tex->nodetree; \ + _id = (ID *)_tex; \ + _tex = _tex->id.next; \ + } \ + else if (_lamp) { \ + _nodetree = _lamp->nodetree; \ + _id = (ID *)_lamp; \ + _lamp = _lamp->id.next; \ + } \ + else if (_world) { \ + _nodetree = _world->nodetree; \ + _id = (ID *)_world; \ + _world = _world->id.next; \ + } \ + else \ + break; \ + if (_nodetree) { + +#define FOREACH_NODETREE_END \ + } \ + } while (TRUE); \ +} /* ************** SHADER NODES *************** */ @@ -583,11 +789,10 @@ struct ShadeResult; /* API */ -struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data); -void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); +struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree); +void ntreeShaderEndExecTree(struct bNodeTreeExec *exec); bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode); -void nodeShaderSynchronizeID(struct bNode *node, int copyto); /* switch material render loop */ extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); @@ -798,8 +1003,8 @@ struct TexResult; int ntreeTexTagAnimated(struct bNodeTree *ntree); void ntreeTexCheckCyclics(struct bNodeTree *ntree); -struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data); -void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); +struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree); +void ntreeTexEndExecTree(struct bNodeTreeExec *exec); int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float coord[3], float dxt[3], float dyt[3], int osatex, const short thread, struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index f1796373367..621fc13af67 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -61,8 +61,8 @@ struct World; void BKE_texture_free(struct Tex *t); -void init_colorband(struct ColorBand *coba, int rangetype); -struct ColorBand *add_colorband(int rangetype); +void init_colorband(struct ColorBand *coba, bool rangetype); +struct ColorBand *add_colorband(bool rangetype); int do_colorband(const struct ColorBand *coba, float in, float out[4]); void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size); struct CBData *colorband_element_add(struct ColorBand *coba, float position); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 4b05f1c1050..24fb949481f 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1152,7 +1152,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru { CBData *ramp; - brush->paint_ramp = add_colorband(0); + brush->paint_ramp = add_colorband(false); if (!brush->paint_ramp) return 0; ramp = brush->paint_ramp->data; @@ -1168,7 +1168,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru { CBData *ramp; - brush->vel_ramp = add_colorband(0); + brush->vel_ramp = add_colorband(false); if (!brush->vel_ramp) return 0; ramp = brush->vel_ramp->data; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index c27f5e62520..4e79c086d4d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2171,7 +2171,7 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata, } else if (sa->spacetype == SPACE_NODE) { SpaceNode *snode = sa->spacedata.first; - if ((snode->treetype == NTREE_COMPOSIT) && (snode->nodetree)) { + if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) { bNode *node; for (node = snode->nodetree->nodes.first; node; node = node->next) { if (node->id && node->type == CMP_NODE_IMAGE) { diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 87802ab8ee6..a5241684e3a 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -57,6 +57,8 @@ #include "BKE_movieclip.h" #include "BKE_image.h" +#include "NOD_composite.h" + static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { if (point == &points_array[spline->tot_point - 1]) { @@ -966,10 +968,9 @@ void BKE_mask_free(Main *bmain, Mask *mask) } } - { - bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT); - treetype->foreach_nodetree(bmain, (void *)mask, &BKE_node_tree_unlink_id_cb); - } + FOREACH_NODETREE(bmain, ntree, id) { + BKE_node_tree_unlink_id((ID *)mask, ntree); + } FOREACH_NODETREE_END /* free mask data */ BKE_mask_layer_free_list(&mask->masklayers); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 6f6686150ae..a863d187a2c 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1015,7 +1015,7 @@ void init_render_material(Material *mat, int r_mode, float *amb) init_render_nodetree(mat->nodetree, mat, r_mode, amb); if (!mat->nodetree->execdata) - mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1); + mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree); } } @@ -1049,7 +1049,7 @@ void end_render_material(Material *mat) { if (mat && mat->nodetree && mat->use_nodes) { if (mat->nodetree->execdata) - ntreeShaderEndExecTree(mat->nodetree->execdata, 1); + ntreeShaderEndExecTree(mat->nodetree->execdata); } } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index e79754ca203..821c8fe3bda 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -86,6 +86,8 @@ #include "intern/openexr/openexr_multi.h" #endif +#include "NOD_composite.h" + /*********************** movieclip buffer loaders *************************/ static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen) @@ -1401,10 +1403,9 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip) } } - { - bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT); - treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb); - } + FOREACH_NODETREE(bmain, ntree, id) { + BKE_node_tree_unlink_id((ID *)clip, ntree); + } FOREACH_NODETREE_END clip->id.us = 0; } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 974a564b9da..757571b9cf6 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -58,133 +58,634 @@ #include "BKE_action.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BLI_ghash.h" #include "RNA_access.h" +#include "RNA_define.h" #include "NOD_socket.h" +#include "NOD_common.h" #include "NOD_composite.h" #include "NOD_shader.h" #include "NOD_texture.h" -bNodeTreeType *ntreeGetType(int type) +static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) +{ + bNodeSocketTemplate *sockdef; + /* bNodeSocket *sock; */ /* UNUSED */ + + if (ntype->inputs) { + sockdef = ntype->inputs; + while (sockdef->type != -1) { + /* sock = */ node_add_socket_from_template(ntree, node, sockdef, SOCK_IN); + + sockdef++; + } + } + if (ntype->outputs) { + sockdef = ntype->outputs; + while (sockdef->type != -1) { + /* sock = */ node_add_socket_from_template(ntree, node, sockdef, SOCK_OUT); + + sockdef++; + } + } +} + +/* Note: This function is called to initialize node data based on the type. + * The bNodeType may not be registered at creation time of the node, + * so this can be delayed until the node type gets registered. + * The node->typeinfo must not be used in that case until it is defined! + */ +static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node) { - static bNodeTreeType *types[NUM_NTREE_TYPES]; - static int types_init = 1; - if (types_init) { - types[NTREE_SHADER] = &ntreeType_Shader; - types[NTREE_COMPOSIT] = &ntreeType_Composite; - types[NTREE_TEXTURE] = &ntreeType_Texture; - types_init = 0; + bNodeType *ntype = node->typeinfo; + if (!ntype) + return; + + /* only do this once */ + if (node->flag & NODE_INIT) + return; + + node->flag = NODE_SELECT | ntype->flag; + node->width = ntype->width; + node->miniwidth = 42.0f; + node->height = ntype->height; + node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */ + + /* initialize the node name with the node label. + * note: do this after the initfunc so nodes get their data set which may be used in naming + * (node groups for example) */ + /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used + * in UI, *never* in data... + * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler + * than adding a "no translate" flag to this func (and labelfunc() as well). */ + BLI_strncpy(node->name, ntype->ui_name, NODE_MAXSTR); + nodeUniqueName(ntree, node); + + node_add_sockets_from_type(ntree, node, ntype); + + if (ntype->initfunc != NULL) + ntype->initfunc(ntree, node); + + /* extra init callback */ + if (ntype->initfunc_api) { + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr); + + /* XXX Warning: context can be NULL in case nodes are added in do_versions. + * Delayed init is not supported for nodes with context-based initfunc_api atm. + */ + BLI_assert(C != NULL); + ntype->initfunc_api(C, &ptr); } - if (type >= 0 && type < NUM_NTREE_TYPES) { - return types[type]; + node->flag |= NODE_INIT; +} + +static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo) +{ + ntree->typeinfo = typeinfo; + + if (typeinfo) { + /* deprecated integer type */ + ntree->type = typeinfo->type; } else { - return NULL; + ntree->init &= ~NTREE_TYPE_INIT; } } -static bNodeType *node_get_type(bNodeTree *ntree, int type) +static void node_set_typeinfo(const struct bContext *C, bNodeTree *ntree, bNode *node, bNodeType *typeinfo) { - bNodeType *ntype = ntreeGetType(ntree->type)->node_types.first; - for (; ntype; ntype = ntype->next) - if (ntype->type == type) - return ntype; + node->typeinfo = typeinfo; + if (typeinfo) { + /* deprecated integer type */ + node->type = typeinfo->type; + + /* initialize the node if necessary */ + node_init(C, ntree, node); + } + else { + ntree->init &= ~NTREE_TYPE_INIT; + } +} + +static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeSocketType *typeinfo) +{ + sock->typeinfo = typeinfo; + + if (typeinfo) { + if (sock->default_value == NULL) { + /* initialize the default_value pointer used by standard socket types */ + node_socket_init_default_value(sock); + } + } + else { + ntree->init &= ~NTREE_TYPE_INIT; + } +} + +/* Set specific typeinfo pointers in all node trees on register/unregister */ +static void update_typeinfo(Main *bmain, const struct bContext *C, bNodeTreeType *treetype, bNodeType *nodetype, bNodeSocketType *socktype, bool unregister) +{ + if (!bmain) + return; + + FOREACH_NODETREE(bmain, ntree, id) { + bNode *node; + bNodeSocket *sock; + + ntree->init |= NTREE_TYPE_INIT; + + if (treetype && STREQ(ntree->idname, treetype->idname)) + ntree_set_typeinfo(ntree, unregister ? NULL : treetype); + + /* initialize nodes */ + for (node = ntree->nodes.first; node; node = node->next) { + if (nodetype && STREQ(node->idname, nodetype->idname)) + node_set_typeinfo(C, ntree, node, unregister ? NULL : nodetype); + + /* initialize node sockets */ + for (sock = node->inputs.first; sock; sock = sock->next) + if (socktype && STREQ(sock->idname, socktype->idname)) + node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + for (sock = node->outputs.first; sock; sock = sock->next) + if (socktype && STREQ(sock->idname, socktype->idname)) + node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + } + + /* initialize tree sockets */ + for (sock = ntree->inputs.first; sock; sock = sock->next) + if (socktype && STREQ(sock->idname, socktype->idname)) + node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + for (sock = ntree->outputs.first; sock; sock = sock->next) + if (socktype && STREQ(sock->idname, socktype->idname)) + node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + } + FOREACH_NODETREE_END +} + +/* Try to initialize all typeinfo in a node tree. + * NB: In general undefined typeinfo is a perfectly valid case, the type may just be registered later. + * In that case the update_typeinfo function will set typeinfo on registration + * and do necessary updates. + */ +void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree) +{ + bNode *node; + bNodeSocket *sock; + + ntree->init |= NTREE_TYPE_INIT; + + ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname)); + + for (node = ntree->nodes.first; node; node = node->next) { + node_set_typeinfo(C, ntree, node, nodeTypeFind(node->idname)); + + for (sock = node->inputs.first; sock; sock = sock->next) + node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname)); + for (sock = node->outputs.first; sock; sock = sock->next) + node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname)); + } + + for (sock = ntree->inputs.first; sock; sock = sock->next) + node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname)); + for (sock = ntree->outputs.first; sock; sock = sock->next) + node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname)); +} + + +static GHash *nodetreetypes_hash = NULL; +static GHash *nodetypes_hash = NULL; +static GHash *nodesockettypes_hash = NULL; + +bNodeTreeType *ntreeTypeFind(const char *idname) +{ + bNodeTreeType *nt; + + if (idname[0]) { + nt = BLI_ghash_lookup(nodetreetypes_hash, idname); + if (nt) + return nt; + } + return NULL; } -bNodeType *ntreeGetNodeType(bNodeTree *ntree) +void ntreeTypeAdd(bNodeTreeType *nt) { - return node_get_type(ntree, ntree->nodetype); + BLI_ghash_insert(nodetreetypes_hash, (void *)nt->idname, nt); + /* XXX pass Main to register function? */ + update_typeinfo(G.main, NULL, nt, NULL, NULL, false); } -bNodeSocketType *ntreeGetSocketType(int type) +/* callback for hash value free function */ +static void ntree_free_type(void *treetype_v) { - static bNodeSocketType *types[NUM_SOCKET_TYPES] = {NULL}; - static int types_init = 1; + bNodeTreeType *treetype = treetype_v; + /* XXX pass Main to unregister function? */ + update_typeinfo(G.main, NULL, treetype, NULL, NULL, true); + MEM_freeN(treetype); +} - if (types_init) { - node_socket_type_init(types); - types_init = 0; +void ntreeTypeFreeLink(bNodeTreeType *nt) +{ + BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type); +} + +GHashIterator *ntreeTypeGetIterator(void) +{ + return BLI_ghashIterator_new(nodetreetypes_hash); +} + +int ntreeIsValid(bNodeTree *ntree) +{ + return (ntree && (ntree->init & NTREE_TYPE_INIT)); +} + +bNodeType *nodeTypeFind(const char *idname) +{ + bNodeType *nt; + + if (idname[0]) { + nt = BLI_ghash_lookup(nodetypes_hash, idname); + if (nt) + return nt; } - if (type < NUM_SOCKET_TYPES) { - return types[type]; + return NULL; +} + +static void free_dynamic_typeinfo(bNodeType *ntype) +{ + if (ntype->type == NODE_DYNAMIC) { + if (ntype->inputs) { + MEM_freeN(ntype->inputs); + } + if (ntype->outputs) { + MEM_freeN(ntype->outputs); + } + if (ntype->ui_name) { + MEM_freeN((void *)ntype->ui_name); + } } - else { - return NULL; +} + +/* callback for hash value free function */ +static void node_free_type(void *nodetype_v) +{ + bNodeType *nodetype = nodetype_v; + /* XXX pass Main to unregister function? */ + update_typeinfo(G.main, NULL, NULL, nodetype, NULL, true); + + /* XXX deprecated */ + if (nodetype->type == NODE_DYNAMIC) + free_dynamic_typeinfo(nodetype); + + if (nodetype->needs_free) + MEM_freeN(nodetype); +} + +void nodeRegisterType(bNodeType *nt) +{ + /* debug only: basic verification of registered types */ + BLI_assert(nt->idname[0] != '\0'); + BLI_assert(nt->poll != NULL); + + BLI_ghash_insert(nodetypes_hash, (void *)nt->idname, nt); + /* XXX pass Main to register function? */ + update_typeinfo(G.main, NULL, NULL, nt, NULL, false); +} + +void nodeUnregisterType(bNodeType *nt) +{ + BLI_ghash_remove(nodetypes_hash, nt->idname, NULL, node_free_type); +} + +GHashIterator *nodeTypeGetIterator(void) +{ + return BLI_ghashIterator_new(nodetypes_hash); +} + +bNodeSocketType *nodeSocketTypeFind(const char *idname) +{ + bNodeSocketType *st; + + if (idname[0]) { + st = BLI_ghash_lookup(nodesockettypes_hash, idname); + if (st) + return st; } + + return NULL; } -void ntreeInitTypes(bNodeTree *ntree) +/* callback for hash value free function */ +static void node_free_socket_type(void *socktype_v) { - bNode *node, *next; + bNodeSocketType *socktype = socktype_v; + /* XXX pass Main to unregister function? */ + update_typeinfo(G.main, NULL, NULL, NULL, socktype, true); - for (node = ntree->nodes.first; node; node = next) { - next = node->next; - - node->typeinfo = node_get_type(ntree, node->type); + MEM_freeN(socktype); +} - if (node->typeinfo == NULL) { - printf("Error: Node type %s doesn't exist anymore, removed\n", node->name); - nodeFreeNode(ntree, node); - } +void nodeRegisterSocketType(bNodeSocketType *st) +{ + BLI_ghash_insert(nodesockettypes_hash, (void *)st->idname, st); + /* XXX pass Main to register function? */ + update_typeinfo(G.main, NULL, NULL, NULL, st, false); +} + +void nodeUnregisterSocketType(bNodeSocketType *st) +{ + BLI_ghash_remove(nodesockettypes_hash, st->idname, NULL, node_free_socket_type); +} + +GHashIterator *nodeSocketTypeGetIterator(void) +{ + return BLI_ghashIterator_new(nodesockettypes_hash); +} + +void nodeMakeDynamicType(bNode *UNUSED(node)) +{ + #if 0 /* XXX deprecated */ + /* find SH_DYNAMIC_NODE ntype */ + bNodeType *ntype = ntreeType_Shader->node_types.first; + while (ntype) { + if (ntype->type == NODE_DYNAMIC) + break; + ntype = ntype->next; } - - ntree->init |= NTREE_TYPE_INIT; + + /* make own type struct to fill */ + if (ntype) { + /*node->typeinfo= MEM_dupallocN(ntype);*/ + bNodeType *newtype = MEM_callocN(sizeof(bNodeType), "dynamic bNodeType"); + *newtype = *ntype; + BLI_strncpy(newtype->name, ntype->name, sizeof(newtype->name)); + node->typeinfo = newtype; + } + #endif +} + +struct bNodeSocket *nodeFindSocket(bNode *node, int in_out, const char *identifier) +{ + bNodeSocket *sock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first); + for (; sock; sock = sock->next) { + if (STREQ(sock->identifier, identifier)) + return sock; + } + return NULL; } -static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type) +/* find unique socket identifier */ +static bool unique_identifier_check(void *arg, const char *identifier) { + struct ListBase *lb = arg; bNodeSocket *sock; + for (sock = lb->first; sock; sock = sock->next) { + if (STREQ(sock->identifier, identifier)) + return true; + } + return false; +} + +static bNodeSocket *make_socket(bNodeTree *ntree, bNode *UNUSED(node), int in_out, ListBase *lb, + const char *idname, const char *identifier, const char *name) +{ + bNodeSocket *sock; + char auto_identifier[MAX_NAME]; + + if (identifier && identifier[0] != '\0') { + /* use explicit identifier */ + BLI_strncpy(auto_identifier, identifier, sizeof(auto_identifier)); + } + else { + /* if no explicit identifier is given, assign a unique identifier based on the name */ + BLI_strncpy(auto_identifier, name, sizeof(auto_identifier)); + } + /* make the identifier unique */ + BLI_uniquename_cb(unique_identifier_check, lb, NULL, '.', auto_identifier, sizeof(auto_identifier)); sock = MEM_callocN(sizeof(bNodeSocket), "sock"); + sock->in_out = in_out; - BLI_strncpy(sock->name, name, NODE_MAXSTR); + BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR); sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF); - sock->type = type; + + BLI_strncpy(sock->name, name, NODE_MAXSTR); sock->storage = NULL; sock->flag |= SOCK_COLLAPSED; + sock->type = SOCK_CUSTOM; /* int type undefined by default */ - sock->default_value = node_socket_make_default_value(type); - node_socket_init_default_value(type, sock->default_value); + BLI_strncpy(sock->idname, idname, sizeof(sock->idname)); + node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname)); return sock; } -bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *name, int type) +bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname, + const char *identifier, const char *name) { - bNodeSocket *sock = make_socket(ntree, in_out, name, type); - if (in_out == SOCK_IN) - BLI_addtail(&node->inputs, sock); - else if (in_out == SOCK_OUT) - BLI_addtail(&node->outputs, sock); + ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs); + bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name); + + BLI_remlink(lb, sock); /* does nothing for new socket */ + BLI_addtail(lb, sock); node->update |= NODE_UPDATE; return sock; } -bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, bNodeSocket *next_sock, const char *name, int type) +bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname, + bNodeSocket *next_sock, const char *identifier, const char *name) { - bNodeSocket *sock = make_socket(ntree, in_out, name, type); - if (in_out == SOCK_IN) - BLI_insertlinkbefore(&node->inputs, next_sock, sock); - else if (in_out == SOCK_OUT) - BLI_insertlinkbefore(&node->outputs, next_sock, sock); + ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs); + bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name); + + BLI_remlink(lb, sock); /* does nothing for new socket */ + BLI_insertlinkbefore(lb, next_sock, sock); node->update |= NODE_UPDATE; return sock; } +const char *nodeStaticSocketType(int type, int subtype) +{ + switch (type) { + case SOCK_FLOAT: + switch (subtype) { + case PROP_UNSIGNED: + return "NodeSocketFloatUnsigned"; + case PROP_PERCENTAGE: + return "NodeSocketFloatPercentage"; + case PROP_FACTOR: + return "NodeSocketFloatFactor"; + case PROP_ANGLE: + return "NodeSocketFloatAngle"; + case PROP_TIME: + return "NodeSocketFloatTime"; + case PROP_NONE: + default: + return "NodeSocketFloat"; + } + case SOCK_INT: + switch (subtype) { + case PROP_UNSIGNED: + return "NodeSocketIntUnsigned"; + case PROP_PERCENTAGE: + return "NodeSocketIntPercentage"; + case PROP_FACTOR: + return "NodeSocketIntFactor"; + case PROP_NONE: + default: + return "NodeSocketInt"; + } + case SOCK_BOOLEAN: + return "NodeSocketBool"; + case SOCK_VECTOR: + switch (subtype) { + case PROP_TRANSLATION: + return "NodeSocketVectorTranslation"; + case PROP_DIRECTION: + return "NodeSocketVectorDirection"; + case PROP_VELOCITY: + return "NodeSocketVectorVelocity"; + case PROP_ACCELERATION: + return "NodeSocketVectorAcceleration"; + case PROP_EULER: + return "NodeSocketVectorEuler"; + case PROP_XYZ: + return "NodeSocketVectorXYZ"; + case PROP_NONE: + default: + return "NodeSocketVector"; + } + case SOCK_RGBA: + return "NodeSocketColor"; + case SOCK_STRING: + return "NodeSocketString"; + case SOCK_SHADER: + return "NodeSocketShader"; + } + return NULL; +} + +const char *nodeStaticSocketInterfaceType(int type, int subtype) +{ + switch (type) { + case SOCK_FLOAT: + switch (subtype) { + case PROP_UNSIGNED: + return "NodeSocketInterfaceFloatUnsigned"; + case PROP_PERCENTAGE: + return "NodeSocketInterfaceFloatPercentage"; + case PROP_FACTOR: + return "NodeSocketInterfaceFloatFactor"; + case PROP_ANGLE: + return "NodeSocketInterfaceFloatAngle"; + case PROP_TIME: + return "NodeSocketInterfaceFloatTime"; + case PROP_NONE: + default: + return "NodeSocketInterfaceFloat"; + } + case SOCK_INT: + switch (subtype) { + case PROP_UNSIGNED: + return "NodeSocketInterfaceIntUnsigned"; + case PROP_PERCENTAGE: + return "NodeSocketInterfaceIntPercentage"; + case PROP_FACTOR: + return "NodeSocketInterfaceIntFactor"; + case PROP_NONE: + default: + return "NodeSocketInterfaceInt"; + } + case SOCK_BOOLEAN: + return "NodeSocketInterfaceBool"; + case SOCK_VECTOR: + switch (subtype) { + case PROP_TRANSLATION: + return "NodeSocketInterfaceVectorTranslation"; + case PROP_DIRECTION: + return "NodeSocketInterfaceVectorDirection"; + case PROP_VELOCITY: + return "NodeSocketInterfaceVectorVelocity"; + case PROP_ACCELERATION: + return "NodeSocketInterfaceVectorAcceleration"; + case PROP_EULER: + return "NodeSocketInterfaceVectorEuler"; + case PROP_XYZ: + return "NodeSocketInterfaceVectorXYZ"; + case PROP_NONE: + default: + return "NodeSocketInterfaceVector"; + } + case SOCK_RGBA: + return "NodeSocketInterfaceColor"; + case SOCK_STRING: + return "NodeSocketInterfaceString"; + case SOCK_SHADER: + return "NodeSocketInterfaceShader"; + } + return NULL; +} + +bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree, bNode *node, int in_out, int type, int subtype, + const char *identifier, const char *name) +{ + const char *idname = nodeStaticSocketType(type, subtype); + bNodeSocket *sock; + + if (!idname) { + printf("Error: static node socket type %d undefined\n", type); + return NULL; + } + + sock = nodeAddSocket(ntree, node, in_out, idname, identifier, name); + sock->type = type; + return sock; +} + +bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree, bNode *node, int in_out, int type, int subtype, + bNodeSocket *next_sock, const char *identifier, const char *name) +{ + const char *idname = nodeStaticSocketType(type, subtype); + bNodeSocket *sock; + + if (!idname) { + printf("Error: static node socket type %d undefined\n", type); + return NULL; + } + + sock = nodeInsertSocket(ntree, node, in_out, idname, next_sock, identifier, name); + sock->type = type; + return sock; +} + +static void node_socket_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock, bNode *UNUSED(node)) +{ + if (sock->prop) { + IDP_FreeProperty(sock->prop); + MEM_freeN(sock->prop); + } + + if (sock->default_value) + MEM_freeN(sock->default_value); +} + void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock) { bNodeLink *link, *next; @@ -200,7 +701,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock) BLI_remlink(&node->inputs, sock); BLI_remlink(&node->outputs, sock); - node_socket_free_default_value(sock->type, sock->default_value); + node_socket_free(ntree, sock, node); MEM_freeN(sock); node->update |= NODE_UPDATE; @@ -208,7 +709,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock) void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) { - bNodeSocket *sock; + bNodeSocket *sock, *sock_next; bNodeLink *link, *next; for (link = ntree->links.first; link; link = next) { @@ -218,12 +719,16 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) } } - for (sock = node->inputs.first; sock; sock = sock->next) - node_socket_free_default_value(sock->type, sock->default_value); - BLI_freelistN(&node->inputs); - for (sock = node->outputs.first; sock; sock = sock->next) - node_socket_free_default_value(sock->type, sock->default_value); - BLI_freelistN(&node->outputs); + for (sock = node->inputs.first; sock; sock = sock_next) { + sock_next = sock->next; + node_socket_free(ntree, sock, node); + MEM_freeN(sock); + } + for (sock = node->outputs.first; sock; sock = sock_next) { + sock_next = sock->next; + node_socket_free(ntree, sock, node); + MEM_freeN(sock); + } node->update |= NODE_UPDATE; } @@ -235,26 +740,18 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) } /* finds a node based on given socket */ -int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out) +int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex) { + int in_out = sock->in_out; bNode *node; bNodeSocket *tsock; int index = 0; for (node = ntree->nodes.first; node; node = node->next) { - for (index = 0, tsock = node->inputs.first; tsock; tsock = tsock->next, index++) { - if (tsock == sock) { - if (in_out) *in_out = SOCK_IN; + tsock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first); + for (index = 0; tsock; tsock = tsock->next, index++) { + if (tsock == sock) break; - } - } - if (tsock) - break; - for (index = 0, tsock = node->outputs.first; tsock; tsock = tsock->next, index++) { - if (tsock == sock) { - if (in_out) *in_out = SOCK_OUT; - break; - } } if (tsock) break; @@ -271,28 +768,6 @@ int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockin } /* ************** Add stuff ********** */ -static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) -{ - bNodeSocketTemplate *sockdef; - /* bNodeSocket *sock; */ /* UNUSED */ - - if (ntype->inputs) { - sockdef = ntype->inputs; - while (sockdef->type != -1) { - /* sock = */ node_add_input_from_template(ntree, node, sockdef); - - sockdef++; - } - } - if (ntype->outputs) { - sockdef = ntype->outputs; - while (sockdef->type != -1) { - /* sock = */ node_add_output_from_template(ntree, node, sockdef); - - sockdef++; - } - } -} /* Find the first available, non-duplicate name for a given node */ void nodeUniqueName(bNodeTree *ntree, bNode *node) @@ -300,51 +775,55 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node) BLI_uniquename(&ntree->nodes, node, "Node", '.', offsetof(bNode, name), sizeof(node->name)); } -bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp) +bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname) { bNode *node; - bNodeType *ntype; - - ntype = node_get_type(ntree, ntemp->type); - if (ntype == NULL) { - printf("nodeAddNodeType() error: '%d' type invalid\n", ntemp->type); - return NULL; - } - /* validity check */ - if (!nodeValid(ntree, ntemp)) - return NULL; node = MEM_callocN(sizeof(bNode), "new node"); - node->type = ntype->type; - node->typeinfo = ntype; - node->flag = NODE_SELECT | ntype->flag; - node->width = ntype->width; - node->miniwidth = 42.0f; - node->height = ntype->height; - node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */ - - node_add_sockets_from_type(ntree, node, ntype); - BLI_addtail(&ntree->nodes, node); - if (ntype->initfunc != NULL) - ntype->initfunc(ntree, node, ntemp); - - /* initialize the node name with the node label. - * note: do this after the initfunc so nodes get their data set which may be used in naming - * (node groups for example) */ - /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used - * in UI, *never* in data... - * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler - * than adding a "no translate" flag to this func (and labelfunc() as well). */ - BLI_strncpy(node->name, node->typeinfo->name, NODE_MAXSTR); - nodeUniqueName(ntree, node); + BLI_strncpy(node->idname, idname, sizeof(node->idname)); + node_set_typeinfo(C, ntree, node, nodeTypeFind(idname)); ntree->update |= NTREE_UPDATE_NODES; return node; } +bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type) +{ + const char *idname = NULL; + + NODE_TYPES_BEGIN(ntype) + if (ntype->type == type) { + idname = ntype->idname; + break; + } + NODE_TYPES_END + if (!idname) { + printf("Error: static node type %d undefined\n", type); + return NULL; + } + return nodeAddNode(C, ntree, idname); +} + +static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src) +{ + src->new_sock = dst; + + if (src->prop) + dst->prop = IDP_CopyProperty(src->prop); + + if (src->default_value) + dst->default_value = MEM_dupallocN(src->default_value); + + dst->stack_index = 0; + /* XXX some compositor node (e.g. image, render layers) still store + * some persistent buffer data here, need to clear this to avoid dangling pointers. + */ + dst->cache = NULL; +} + /* keep socket listorder identical, for copying links */ /* ntree is the target tree */ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) @@ -363,33 +842,16 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) BLI_duplicatelist(&nnode->inputs, &node->inputs); oldsock = node->inputs.first; - for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) { - oldsock->new_sock = sock; - sock->stack_index = 0; - - sock->default_value = node_socket_make_default_value(oldsock->type); - node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value); - - /* XXX some compositor node (e.g. image, render layers) still store - * some persistent buffer data here, need to clear this to avoid dangling pointers. - */ - sock->cache = NULL; - } + for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) + node_socket_copy(sock, oldsock); BLI_duplicatelist(&nnode->outputs, &node->outputs); oldsock = node->outputs.first; - for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) { - oldsock->new_sock = sock; - sock->stack_index = 0; - - sock->default_value = node_socket_make_default_value(oldsock->type); - node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value); - - /* XXX some compositor node (e.g. image, render layers) still store - * some persistent buffer data here, need to clear this to avoid dangling pointers. - */ - sock->cache = NULL; - } + for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) + node_socket_copy(sock, oldsock); + + if (node->prop) + nnode->prop = IDP_CopyProperty(node->prop); BLI_duplicatelist(&nnode->internal_links, &node->internal_links); oldlink = node->internal_links.first; @@ -402,22 +864,17 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) /* don't increase node->id users, freenode doesn't decrement either */ - if (node->typeinfo->copystoragefunc) - node->typeinfo->copystoragefunc(node, nnode); + if (node->typeinfo->copyfunc) + node->typeinfo->copyfunc(ntree, nnode, node); node->new_node = nnode; nnode->new_node = NULL; - /* only shader nodes get pleasant preview updating this way, compo uses own system */ - if (node->preview) { - if (ntree && (ntree->type == NTREE_SHADER)) { - nnode->preview = MEM_dupallocN(node->preview); - if (node->preview->rect) - nnode->preview->rect = MEM_dupallocN(node->preview->rect); - } - else { - nnode->preview = NULL; - } + if (nnode->typeinfo->copyfunc_api) { + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, nnode, &ptr); + + nnode->typeinfo->copyfunc_api(&ptr, node); } if (ntree) @@ -429,71 +886,13 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) /* also used via rna api, so we check for proper input output direction */ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock) { - bNodeSocket *sock; bNodeLink *link = NULL; - int from = 0, to = 0; - if (fromnode) { - /* test valid input */ - for (sock = fromnode->outputs.first; sock; sock = sock->next) - if (sock == fromsock) - break; - if (sock) - from = 1; /* OK */ - else { - for (sock = fromnode->inputs.first; sock; sock = sock->next) - if (sock == fromsock) - break; - if (sock) - from = -1; /* OK but flip */ - } - } - else if (ntree) { - /* check tree sockets */ - for (sock = ntree->inputs.first; sock; sock = sock->next) - if (sock == fromsock) - break; - if (sock) - from = 1; /* OK */ - else { - for (sock = ntree->outputs.first; sock; sock = sock->next) - if (sock == fromsock) - break; - if (sock) - from = -1; /* OK but flip */ - } - } - if (tonode) { - for (sock = tonode->inputs.first; sock; sock = sock->next) - if (sock == tosock) - break; - if (sock) - to = 1; /* OK */ - else { - for (sock = tonode->outputs.first; sock; sock = sock->next) - if (sock == tosock) - break; - if (sock) - to = -1; /* OK but flip */ - } - } - else if (ntree) { - /* check tree sockets */ - for (sock = ntree->outputs.first; sock; sock = sock->next) - if (sock == tosock) - break; - if (sock) - to = 1; /* OK */ - else { - for (sock = ntree->inputs.first; sock; sock = sock->next) - if (sock == tosock) - break; - if (sock) - to = -1; /* OK but flip */ - } - } + /* test valid input */ + BLI_assert(fromnode); + BLI_assert(tonode); - if (from >= 0 && to >= 0) { + if (fromsock->in_out == SOCK_OUT && tosock->in_out == SOCK_IN) { link = MEM_callocN(sizeof(bNodeLink), "link"); if (ntree) BLI_addtail(&ntree->links, link); @@ -502,7 +901,8 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, link->tonode = tonode; link->tosock = tosock; } - else if (from <= 0 && to <= 0) { + else if (fromsock->in_out == SOCK_IN && tosock->in_out == SOCK_OUT) { + /* OK but flip */ link = MEM_callocN(sizeof(bNodeLink), "link"); if (ntree) BLI_addtail(&ntree->links, link); @@ -546,6 +946,11 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) ntree->update |= NTREE_UPDATE_LINKS; } +int nodeLinkIsHidden(bNodeLink *link) +{ + return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock); +} + void nodeInternalRelink(bNodeTree *ntree, bNode *node) { bNodeLink *link, *link_next; @@ -662,30 +1067,29 @@ void nodeDetachNode(struct bNode *node) } } -bNodeTree *ntreeAddTree(Main *bmain, const char *name, int type, int nodetype) +bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) { bNodeTree *ntree; - bNodeType *ntype; - /* trees are created as local trees if they of compositor, material or texture type, + /* trees are created as local trees for compositor, material or texture nodes, * node groups and other tree types are created as library data. */ - if (ELEM3(type, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE) && nodetype == 0) { + if (bmain) { + ntree = BKE_libblock_alloc(&bmain->nodetree, ID_NT, name); + } + else { ntree = MEM_callocN(sizeof(bNodeTree), "new node tree"); - *( (short *)ntree->id.name) = ID_NT; /* not "type", as that is ntree->type */ + *( (short *)ntree->id.name ) = ID_NT; BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name)); } - else - ntree = BKE_libblock_alloc(&bmain->nodetree, ID_NT, name); - ntree->type = type; - ntree->nodetype = nodetype; - - ntreeInitTypes(ntree); + /* Types are fully initialized at this point, + * if an undefined node is added later this will be reset. + */ + ntree->init |= NTREE_TYPE_INIT; - ntype = node_get_type(ntree, ntree->nodetype); - if (ntype && ntype->inittreefunc) - ntype->inittreefunc(ntree); + BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname)); + ntree_set_typeinfo(ntree, ntreeTypeFind(idname)); return ntree; } @@ -699,12 +1103,12 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, int type, int nodetype) * copying for internal use (threads for eg), where you wont want it to modify the * scene data. */ -static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern) +static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern, const short copy_previews) { bNodeTree *newtree; bNode *node /*, *nnode */ /* UNUSED */, *last; + bNodeSocket *sock, *oldsock; bNodeLink *link; - bNodeSocket *gsock, *oldgsock; if (ntree == NULL) return NULL; @@ -747,22 +1151,6 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use break; } - /* socket definition for group usage */ - BLI_duplicatelist(&newtree->inputs, &ntree->inputs); - for (gsock = newtree->inputs.first, oldgsock = ntree->inputs.first; gsock; gsock = gsock->next, oldgsock = oldgsock->next) { - oldgsock->new_sock = gsock; - gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); - gsock->default_value = node_socket_make_default_value(oldgsock->type); - node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value); - } - BLI_duplicatelist(&newtree->outputs, &ntree->outputs); - for (gsock = newtree->outputs.first, oldgsock = ntree->outputs.first; gsock; gsock = gsock->next, oldgsock = oldgsock->next) { - oldgsock->new_sock = gsock; - gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); - gsock->default_value = node_socket_make_default_value(oldgsock->type); - node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value); - } - /* copy links */ BLI_duplicatelist(&newtree->links, &ntree->links); for (link = newtree->links.first; link; link = link->next) { @@ -775,18 +1163,47 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use link->tosock->link = link; } + /* copy interface sockets */ + BLI_duplicatelist(&newtree->inputs, &ntree->inputs); + oldsock = ntree->inputs.first; + for (sock = newtree->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) + node_socket_copy(sock, oldsock); + + BLI_duplicatelist(&newtree->outputs, &ntree->outputs); + oldsock = ntree->outputs.first; + for (sock = newtree->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) + node_socket_copy(sock, oldsock); + + /* copy preview hash */ + if (ntree->previews && copy_previews) { + bNodeInstanceHashIterator iter; + + newtree->previews = BKE_node_instance_hash_new("node previews"); + + NODE_INSTANCE_HASH_ITER(iter, ntree->previews) { + bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); + bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + BKE_node_instance_hash_insert(newtree->previews, key, BKE_node_preview_copy(preview)); + } + } + else + newtree->previews = NULL; + /* update node->parent pointers */ for (node = newtree->nodes.first; node; node = node->next) { if (node->parent) node->parent = node->parent->new_node; } + /* node tree will generate its own interface type */ + ntree->interface_type = NULL; + return newtree; } bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user) { - return ntreeCopyTree_internal(ntree, do_id_user, TRUE); + return ntreeCopyTree_internal(ntree, do_id_user, TRUE, TRUE); } bNodeTree *ntreeCopyTree(bNodeTree *ntree) { @@ -835,62 +1252,225 @@ void ntreeUserDecrefID(bNodeTree *ntree) } } -/* *************** preview *********** */ -/* if node->preview, then we assume the rect to exist */ +/* *************** Node Preview *********** */ -void nodeFreePreview(bNode *node) +/* XXX this should be removed eventually ... + * Currently BKE functions are modelled closely on previous code, + * using BKE_node_preview_init_tree to set up previews for a whole node tree in advance. + * This should be left more to the individual node tree implementations. + */ +int BKE_node_preview_used(bNode *node) { - if (node->preview) { - if (node->preview->rect) - MEM_freeN(node->preview->rect); - MEM_freeN(node->preview); - node->preview = NULL; - } + /* XXX check for closed nodes? */ + return (node->typeinfo->flag & NODE_PREVIEW) != 0; } -static void node_init_preview(bNode *node, int xsize, int ysize) +bNodePreview *BKE_node_preview_verify(bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create) { + bNodePreview *preview; - if (node->preview == NULL) { - node->preview = MEM_callocN(sizeof(bNodePreview), "node preview"); - // printf("added preview %s\n", node->name); + preview = BKE_node_instance_hash_lookup(previews, key); + if (!preview) { + if (create) { + preview = MEM_callocN(sizeof(bNodePreview), "node preview"); + BKE_node_instance_hash_insert(previews, key, preview); + } + else + return NULL; } /* node previews can get added with variable size this way */ if (xsize == 0 || ysize == 0) - return; + return preview; /* sanity checks & initialize */ - if (node->preview->rect) { - if (node->preview->xsize != xsize && node->preview->ysize != ysize) { - MEM_freeN(node->preview->rect); - node->preview->rect = NULL; + if (preview->rect) { + if (preview->xsize != xsize || preview->ysize != ysize) { + MEM_freeN(preview->rect); + preview->rect = NULL; } } - if (node->preview->rect == NULL) { - node->preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char) * 4, "node preview rect"); - node->preview->xsize = xsize; - node->preview->ysize = ysize; + if (preview->rect == NULL) { + preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char) * 4, "node preview rect"); + preview->xsize = xsize; + preview->ysize = ysize; } /* no clear, makes nicer previews */ + + return preview; +} + +bNodePreview *BKE_node_preview_copy(bNodePreview *preview) +{ + bNodePreview *new_preview = MEM_dupallocN(preview); + if (preview->rect) + new_preview->rect = MEM_dupallocN(preview->rect); + return new_preview; +} + +void BKE_node_preview_free(bNodePreview *preview) +{ + if (preview->rect) + MEM_freeN(preview->rect); + MEM_freeN(preview); } -void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) +static void node_preview_init_tree_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key, int xsize, int ysize, int create) { bNode *node; - - if (ntree == NULL) + for (node = ntree->nodes.first; node; node = node->next) { + bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node); + + if (BKE_node_preview_used(node)) { + node->preview_xsize = xsize; + node->preview_ysize = ysize; + + BKE_node_preview_verify(previews, key, xsize, ysize, create); + } + + if (node->type == NODE_GROUP) + node_preview_init_tree_recursive(previews, (bNodeTree *)node->id, key, xsize, ysize, create); + } +} + +void BKE_node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize, int create_previews) +{ + if (!ntree) return; + if (!ntree->previews) + ntree->previews = BKE_node_instance_hash_new("node previews"); + + node_preview_init_tree_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE, xsize, ysize, create_previews); +} + +static void node_preview_tag_used_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key) +{ + bNode *node; for (node = ntree->nodes.first; node; node = node->next) { - if (node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */ - node_init_preview(node, xsize, ysize); - if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) - ntreeInitPreview((bNodeTree *)node->id, xsize, ysize); + bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node); + + if (BKE_node_preview_used(node)) + BKE_node_instance_hash_tag_key(previews, key); + + if (node->type == NODE_GROUP) + node_preview_tag_used_recursive(previews, (bNodeTree *)node->id, key); + } +} + +void BKE_node_preview_remove_unused(bNodeTree *ntree) +{ + if (!ntree || !ntree->previews) + return; + + /* use the instance hash functions for tagging and removing unused previews */ + BKE_node_instance_hash_clear_tags(ntree->previews); + node_preview_tag_used_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE); + + BKE_node_instance_hash_remove_untagged(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); +} + +void BKE_node_preview_free_tree(bNodeTree *ntree) +{ + if (!ntree) + return; + + if (ntree->previews) { + BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); + ntree->previews = NULL; + } +} + +void BKE_node_preview_clear(bNodePreview *preview) +{ + if (preview && preview->rect) + memset(preview->rect, 0, MEM_allocN_len(preview->rect)); +} + +void BKE_node_preview_clear_tree(bNodeTree *ntree) +{ + bNodeInstanceHashIterator iter; + + if (!ntree || !ntree->previews) + return; + + NODE_INSTANCE_HASH_ITER(iter, ntree->previews) { + bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + BKE_node_preview_clear(preview); + } +} + +static void node_preview_sync(bNodePreview *to, bNodePreview *from) +{ + /* sizes should have been initialized by BKE_node_preview_init_tree */ + BLI_assert(to->xsize == from->xsize && to->ysize == from->ysize); + + /* copy over contents of previews */ + if (to->rect && from->rect) { + int xsize = to->xsize; + int ysize = to->ysize; + memcpy(to->rect, from->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); } } +void BKE_node_preview_sync_tree(bNodeTree *to_ntree, bNodeTree *from_ntree) +{ + bNodeInstanceHash *from_previews = from_ntree->previews; + bNodeInstanceHash *to_previews = to_ntree->previews; + bNodeInstanceHashIterator iter; + + if (!from_previews || !to_previews) + return; + + NODE_INSTANCE_HASH_ITER(iter, from_previews) { + bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); + bNodePreview *from = BKE_node_instance_hash_iterator_get_value(&iter); + bNodePreview *to = BKE_node_instance_hash_lookup(to_previews, key); + + if (from && to) + node_preview_sync(to, from); + } +} + +void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree) +{ + /* free old previews */ + if (to_ntree->previews) + BKE_node_instance_hash_free(to_ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); + + /* transfer previews */ + to_ntree->previews = from_ntree->previews; + from_ntree->previews = NULL; + + /* clean up, in case any to_ntree nodes have been removed */ + BKE_node_preview_remove_unused(to_ntree); +} + +/* hack warning! this function is only used for shader previews, and + * since it gets called multiple times per pixel for Ztransp we only + * add the color once. Preview gets cleared before it starts render though */ +void BKE_node_preview_set_pixel(bNodePreview *preview, const float col[4], int x, int y, int do_manage) +{ + if (preview) { + if (x >= 0 && y >= 0) { + if (x < preview->xsize && y < preview->ysize) { + unsigned char *tar = preview->rect + 4 * ((preview->xsize * y) + x); + + if (do_manage) { + linearrgb_to_srgb_uchar4(tar, col); + } + else { + rgba_float_to_uchar(tar, col); + } + } + //else printf("prv out bound x y %d %d\n", x, y); + } + //else printf("prv out bound x y %d %d\n", x, y); + } +} + +#if 0 static void nodeClearPreview(bNode *node) { if (node->preview && node->preview->rect) @@ -908,7 +1488,7 @@ void ntreeClearPreview(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) { if (node->typeinfo->flag & NODE_PREVIEW) nodeClearPreview(node); - if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) + if (node->type == NODE_GROUP) ntreeClearPreview((bNodeTree *)node->id); } } @@ -936,6 +1516,7 @@ void nodeAddToPreview(bNode *node, const float col[4], int x, int y, int do_mana //else printf("prv out bound x y %d %d\n", x, y); } } +#endif /* ************** Free stuff ********** */ @@ -985,45 +1566,54 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) { bNodeSocket *sock, *nextsock; + /* extra free callback */ + if (node->typeinfo && node->typeinfo->freefunc_api) { + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr); + + node->typeinfo->freefunc_api(&ptr); + } + + /* since it is called while free database, node->id is undefined */ + /* can be called for nodes outside a node tree (e.g. clipboard) */ if (ntree) { - bNodeTreeType *treetype = ntreeGetType(ntree->type); - /* remove all references to this node */ nodeUnlinkNode(ntree, node); node_unlink_attached(ntree, node); - + BLI_remlink(&ntree->nodes, node); - - if (treetype->free_node_cache) - treetype->free_node_cache(ntree, node); + + if (ntree->typeinfo && ntree->typeinfo->free_node_cache) + ntree->typeinfo->free_node_cache(ntree, node); /* texture node has bad habit of keeping exec data around */ if (ntree->type == NTREE_TEXTURE && ntree->execdata) { - ntreeTexEndExecTree(ntree->execdata, 1); + ntreeTexEndExecTree(ntree->execdata); ntree->execdata = NULL; } + + if (node->typeinfo && node->typeinfo->freefunc) + node->typeinfo->freefunc(node); } - /* since it is called while free database, node->id is undefined */ - - if (node->typeinfo && node->typeinfo->freestoragefunc) - node->typeinfo->freestoragefunc(node); - for (sock = node->inputs.first; sock; sock = nextsock) { nextsock = sock->next; - node_socket_free_default_value(sock->type, sock->default_value); + node_socket_free(ntree, sock, node); MEM_freeN(sock); } for (sock = node->outputs.first; sock; sock = nextsock) { nextsock = sock->next; - node_socket_free_default_value(sock->type, sock->default_value); + node_socket_free(ntree, sock, node); MEM_freeN(sock); } BLI_freelistN(&node->internal_links); - nodeFreePreview(node); + if (node->prop) { + IDP_FreeProperty(node->prop); + MEM_freeN(node->prop); + } MEM_freeN(node); @@ -1031,12 +1621,24 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) ntree->update |= NTREE_UPDATE_NODES; } +static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock) +{ + if (sock->prop) { + IDP_FreeProperty(sock->prop); + MEM_freeN(sock->prop); + } + + /* can be left over from old files */ + if (sock->default_value) + MEM_freeN(sock->default_value); +} + /* do not free ntree itself here, BKE_libblock_free calls this function too */ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) { bNodeTree *tntree; bNode *node, *next; - bNodeSocket *sock; + bNodeSocket *sock, *nextsock; if (ntree == NULL) return; @@ -1048,15 +1650,18 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) if (ntree->execdata) { switch (ntree->type) { case NTREE_SHADER: - ntreeShaderEndExecTree(ntree->execdata, 1); + ntreeShaderEndExecTree(ntree->execdata); break; case NTREE_TEXTURE: - ntreeTexEndExecTree(ntree->execdata, 1); + ntreeTexEndExecTree(ntree->execdata); ntree->execdata = NULL; break; } } + /* unregister associated RNA types */ + ntreeInterfaceTypeFree(ntree); + BKE_free_animdata((ID *)ntree); id_us_min((ID *)ntree->gpd); @@ -1082,13 +1687,23 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) nodeFreeNode(ntree, node); } + + /* free interface sockets */ + for (sock = ntree->inputs.first; sock; sock = nextsock) { + nextsock = sock->next; + node_socket_interface_free(ntree, sock); + MEM_freeN(sock); + } + for (sock = ntree->outputs.first; sock; sock = nextsock) { + nextsock = sock->next; + node_socket_interface_free(ntree, sock); + MEM_freeN(sock); + } - for (sock = ntree->inputs.first; sock; sock = sock->next) - node_socket_free_default_value(sock->type, sock->default_value); - BLI_freelistN(&ntree->inputs); - for (sock = ntree->outputs.first; sock; sock = sock->next) - node_socket_free_default_value(sock->type, sock->default_value); - BLI_freelistN(&ntree->outputs); + /* free preview hash */ + if (ntree->previews) { + BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); + } /* if ntree is not part of library, free the libblock data explicitly */ for (tntree = G.main->nodetree.first; tntree; tntree = tntree->id.next) @@ -1106,13 +1721,10 @@ void ntreeFreeTree(bNodeTree *ntree) void ntreeFreeCache(bNodeTree *ntree) { - bNodeTreeType *treetype; - if (ntree == NULL) return; - treetype = ntreeGetType(ntree->type); - if (treetype->free_cache) - treetype->free_cache(ntree); + if (ntree->typeinfo->free_cache) + ntree->typeinfo->free_cache(ntree); } void ntreeSetOutput(bNodeTree *ntree) @@ -1162,6 +1774,24 @@ void ntreeSetOutput(bNodeTree *ntree) if (output == 0) node->flag |= NODE_DO_OUTPUT; } + + /* group node outputs use this flag too */ + if (node->type == NODE_GROUP_OUTPUT) { + bNode *tnode; + int output = 0; + + for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { + if (tnode->type == NODE_GROUP_OUTPUT) { + if (tnode->flag & NODE_DO_OUTPUT) { + output++; + if (output > 1) + tnode->flag &= ~NODE_DO_OUTPUT; + } + } + } + if (output == 0) + node->flag |= NODE_DO_OUTPUT; + } } /* here we could recursively set which nodes have to be done, @@ -1180,52 +1810,10 @@ bNodeTree *ntreeFromID(ID *id) } } -typedef struct MakeLocalCallData { - ID *group_id; - ID *new_id; - int lib, local; -} MakeLocalCallData; - -static void ntreeMakeLocal_CheckLocal(void *calldata, ID *owner_id, bNodeTree *ntree) -{ - MakeLocalCallData *cd = (MakeLocalCallData *)calldata; - bNode *node; - - /* find if group is in tree */ - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == cd->group_id) { - if (owner_id->lib) { - cd->lib = TRUE; - } - else { - cd->local = TRUE; - } - } - } -} - -static void ntreeMakeLocal_LinkNew(void *calldata, ID *owner_id, bNodeTree *ntree) -{ - MakeLocalCallData *cd = (MakeLocalCallData *)calldata; - bNode *node; - - /* find if group is in tree */ - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == cd->group_id) { - if (owner_id->lib == NULL) { - node->id = cd->new_id; - cd->new_id->us++; - cd->group_id->us--; - } - } - } -} - void ntreeMakeLocal(bNodeTree *ntree) { Main *bmain = G.main; - bNodeTreeType *treetype = ntreeGetType(ntree->type); - MakeLocalCallData cd; + int lib = FALSE, local = FALSE; /* - only lib users: do nothing * - only local users: set flag @@ -1239,26 +1827,42 @@ void ntreeMakeLocal(bNodeTree *ntree) } /* now check users of groups... again typedepending, callback... */ - cd.group_id = &ntree->id; - cd.new_id = NULL; - cd.local = 0; - cd.lib = 0; - - treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_CheckLocal); + FOREACH_NODETREE(G.main, tntree, owner_id) { + bNode *node; + /* find if group is in tree */ + for (node = tntree->nodes.first; node; node = node->next) { + if (node->id == (ID *)ntree) { + if (owner_id->lib) + lib = TRUE; + else + local = TRUE; + } + } + } FOREACH_NODETREE_END /* if all users are local, we simply make tree local */ - if (cd.local && cd.lib == 0) { + if (local && !lib) { id_clear_lib_data(bmain, (ID *)ntree); } - else if (cd.local && cd.lib) { + else if (local && lib) { /* this is the mixed case, we copy the tree and assign it to local users */ bNodeTree *newtree = ntreeCopyTree(ntree); newtree->id.us = 0; - - cd.new_id = &newtree->id; - treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_LinkNew); + FOREACH_NODETREE(G.main, tntree, owner_id) { + bNode *node; + /* find if group is in tree */ + for (node = tntree->nodes.first; node; node = node->next) { + if (node->id == (ID *)ntree) { + if (owner_id->lib == NULL) { + node->id = (ID *)newtree; + newtree->id.us++; + ntree->id.us--; + } + } + } + } FOREACH_NODETREE_END } } @@ -1283,90 +1887,337 @@ int ntreeOutputExists(bNode *node, bNodeSocket *testsock) /* returns localized tree for execution in threads */ bNodeTree *ntreeLocalize(bNodeTree *ntree) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); - - bNodeTree *ltree; - bNode *node; + if (ntreeIsValid(ntree)) { + bNodeTree *ltree; + bNode *node; + + bAction *action_backup = NULL, *tmpact_backup = NULL; + + /* Workaround for copying an action on each render! + * set action to NULL so animdata actions don't get copied */ + AnimData *adt = BKE_animdata_from_id(&ntree->id); - bAction *action_backup = NULL, *tmpact_backup = NULL; + if (adt) { + action_backup = adt->action; + tmpact_backup = adt->tmpact; - /* Workaround for copying an action on each render! - * set action to NULL so animdata actions don't get copied */ - AnimData *adt = BKE_animdata_from_id(&ntree->id); + adt->action = NULL; + adt->tmpact = NULL; + } + + /* Make full copy. + * Note: previews are not copied here. + */ + ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE, FALSE); + + if (adt) { + AnimData *ladt = BKE_animdata_from_id(<ree->id); + + adt->action = ladt->action = action_backup; + adt->tmpact = ladt->tmpact = tmpact_backup; + + if (action_backup) action_backup->id.us++; + if (tmpact_backup) tmpact_backup->id.us++; + + } + /* end animdata uglyness */ + + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); + + for (node = ntree->nodes.first; node; node = node->next) { + /* store new_node pointer to original */ + node->new_node->new_node = node; + } + + if (ntree->typeinfo->localize) + ntree->typeinfo->localize(ltree, ntree); + + return ltree; + } + else + return NULL; +} - if (adt) { - action_backup = adt->action; - tmpact_backup = adt->tmpact; +/* sync local composite with real tree */ +/* local tree is supposed to be running, be careful moving previews! */ +/* is called by jobs manager, outside threads, so it doesnt happen during draw */ +void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) +{ + if (localtree && ntreeIsValid(ntree)) { + /* XXX syncing was disabled for compositor nodes. + * It has to be ensured that there is no concurrent read/write access! + * Possibly needs a mutex lock or a flag to disable for certain tree types ... + */ + BKE_node_preview_sync_tree(ntree, localtree); + + if (ntree->typeinfo->local_sync) + ntree->typeinfo->local_sync(localtree, ntree); + } +} - adt->action = NULL; - adt->tmpact = NULL; +/* merge local tree results back, and free local tree */ +/* we have to assume the editor already changed completely */ +void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) +{ + if (localtree && ntreeIsValid(ntree)) { + BKE_node_preview_merge_tree(ntree, localtree); + + if (ntree->typeinfo->local_merge) + ntree->typeinfo->local_merge(localtree, ntree); + + ntreeFreeTree_ex(localtree, FALSE); + MEM_freeN(localtree); } +} - /* node copy func */ - ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE); - if (adt) { - AnimData *ladt = BKE_animdata_from_id(<ree->id); +/* ************ NODE TREE INTERFACE *************** */ - adt->action = ladt->action = action_backup; - adt->tmpact = ladt->tmpact = tmpact_backup; +static bNodeSocket *make_socket_template(bNodeTree *ntree, int in_out, + const char *idname, const char *name) +{ + bNodeSocketType *stype = nodeSocketTypeFind(idname); + bNodeSocket *sock; + int own_index = ntree->cur_index++; + + if (stype == NULL) { + printf("Error: node socket type '%s' undefined\n", idname); + return NULL; + } + + sock = MEM_callocN(sizeof(bNodeSocket), "socket template"); + sock->typeinfo = stype; + BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname)); + sock->in_out = in_out; + sock->type = SOCK_CUSTOM; /* int type undefined by default */ + + /* assign new unique index */ + own_index = ntree->cur_index++; + /* use the own_index as socket identifier */ + if (in_out == SOCK_IN) + BLI_snprintf(sock->identifier, MAX_NAME, "Input_%d", own_index); + else + BLI_snprintf(sock->identifier, MAX_NAME, "Output_%d", own_index); +#ifdef USE_NODE_COMPAT_CUSTOMNODES + /* XXX forward compatibility: + * own_index is deprecated, but needs to be set here. + * Node sockets generally use the identifier string instead now, + * but reconstructing own_index in writefile.c would require parsing the identifier string. + */ - if (action_backup) action_backup->id.us++; - if (tmpact_backup) tmpact_backup->id.us++; - +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + + sock->own_index = own_index; + +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) +# pragma GCC diagnostic pop +#endif + +#endif /* USE_NODE_COMPAT_CUSTOMNODES */ + + sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF); + + BLI_strncpy(sock->name, name, NODE_MAXSTR); + sock->storage = NULL; + sock->flag |= SOCK_COLLAPSED; + + return sock; +} + +bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *identifier) +{ + bNodeSocket *iosock = (in_out == SOCK_IN ? ntree->inputs.first : ntree->outputs.first); + for (; iosock; iosock = iosock->next) + if (STREQ(iosock->identifier, identifier)) + return iosock; + return NULL; +} + +bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree, int in_out, const char *idname, const char *name) +{ + bNodeSocket *iosock; + + iosock = make_socket_template(ntree, in_out, idname, name); + if (in_out == SOCK_IN) { + BLI_addtail(&ntree->inputs, iosock); + ntree->update |= NTREE_UPDATE_GROUP_IN; } - /* end animdata uglyness */ + else if (in_out == SOCK_OUT) { + BLI_addtail(&ntree->outputs, iosock); + ntree->update |= NTREE_UPDATE_GROUP_OUT; + } + + return iosock; +} - /* ensures only a single output node is enabled */ - ntreeSetOutput(ntree); +bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree, int in_out, const char *idname, + bNodeSocket *next_sock, const char *name) +{ + bNodeSocket *iosock; + + iosock = make_socket_template(ntree, in_out, idname, name); + if (in_out == SOCK_IN) { + BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock); + ntree->update |= NTREE_UPDATE_GROUP_IN; + } + else if (in_out == SOCK_OUT) { + BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock); + ntree->update |= NTREE_UPDATE_GROUP_OUT; + } + + return iosock; +} - for (node = ntree->nodes.first; node; node = node->next) { - /* store new_node pointer to original */ - node->new_node->new_node = node; +struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree, bNode *from_node, bNodeSocket *from_sock) +{ + bNodeSocket *iosock = ntreeAddSocketInterface(ntree, from_sock->in_out, from_sock->idname, from_sock->name); + if (iosock) { + if (iosock->typeinfo->interface_from_socket) + iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock); } + return iosock; +} - if (ntreetype->localize) - ntreetype->localize(ltree, ntree); +struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree, bNodeSocket *next_sock, bNode *from_node, bNodeSocket *from_sock) +{ + bNodeSocket *iosock = ntreeInsertSocketInterface(ntree, from_sock->in_out, from_sock->idname, next_sock, from_sock->name); + if (iosock) { + if (iosock->typeinfo->interface_from_socket) + iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock); + } + return iosock; +} - return ltree; +void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock) +{ + /* this is fast, this way we don't need an in_out argument */ + BLI_remlink(&ntree->inputs, sock); + BLI_remlink(&ntree->outputs, sock); + + node_socket_interface_free(ntree, sock); + MEM_freeN(sock); + + ntree->update |= NTREE_UPDATE_GROUP; } -/* sync local composite with real tree */ -/* local tree is supposed to be running, be careful moving previews! */ -/* is called by jobs manager, outside threads, so it doesnt happen during draw */ -void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) +/* generates a valid RNA identifier from the node tree name */ +static void ntree_interface_identifier_base(bNodeTree *ntree, char *base) +{ + /* generate a valid RNA identifier */ + sprintf(base, "NodeTreeInterface_%s", ntree->id.name + 2); + RNA_identifier_sanitize(base, FALSE); +} + +/* check if the identifier is already in use */ +static bool ntree_interface_unique_identifier_check(void *UNUSED(data), const char *identifier) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); + return (RNA_struct_find(identifier) != NULL); +} - if (ntreetype->local_sync) - ntreetype->local_sync(localtree, ntree); +/* generates the actual unique identifier and ui name and description */ +static void ntree_interface_identifier(bNodeTree *ntree, const char *base, char *identifier, int maxlen, char *name, char *description) +{ + /* There is a possibility that different node tree names get mapped to the same identifier + * after sanitization (e.g. "SomeGroup_A", "SomeGroup.A" both get sanitized to "SomeGroup_A"). + * On top of the sanitized id string add a number suffix if necessary to avoid duplicates. + */ + identifier[0] = '\0'; + BLI_uniquename_cb(ntree_interface_unique_identifier_check, NULL, base, '_', identifier, maxlen); + + sprintf(name, "Node Tree %s Interface", ntree->id.name + 2); + sprintf(description, "Interface properties of node group %s", ntree->id.name + 2); } -/* merge local tree results back, and free local tree */ -/* we have to assume the editor already changed completely */ -void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) +static void ntree_interface_type_create(bNodeTree *ntree) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); - bNode *lnode; + StructRNA *srna; + bNodeSocket *sock; + /* strings are generated from base string + ID name, sizes are sufficient */ + char base[MAX_ID_NAME + 64], identifier[MAX_ID_NAME + 64], name[MAX_ID_NAME + 64], description[MAX_ID_NAME + 64]; - /* move over the compbufs and previews */ - for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) { - if (ntreeNodeExists(ntree, lnode->new_node)) { - if (lnode->preview && lnode->preview->rect) { - nodeFreePreview(lnode->new_node); - lnode->new_node->preview = lnode->preview; - lnode->preview = NULL; - } + /* generate a valid RNA identifier */ + ntree_interface_identifier_base(ntree, base); + ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description); + + /* register a subtype of PropertyGroup */ + srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup); + RNA_def_struct_ui_text(srna, name, description); + RNA_def_struct_duplicate_pointers(srna); + + /* associate the RNA type with the node tree */ + ntree->interface_type = srna; + RNA_struct_blender_type_set(srna, ntree); + + /* add socket properties */ + for (sock = ntree->inputs.first; sock; sock = sock->next) { + bNodeSocketType *stype = sock->typeinfo; + if (stype && stype->interface_register_properties) + stype->interface_register_properties(ntree, sock, srna); + } + for (sock = ntree->outputs.first; sock; sock = sock->next) { + bNodeSocketType *stype = sock->typeinfo; + if (stype && stype->interface_register_properties) + stype->interface_register_properties(ntree, sock, srna); + } +} + +StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create) +{ + if (ntree->interface_type) { + /* strings are generated from base string + ID name, sizes are sufficient */ + char base[MAX_ID_NAME + 64], identifier[MAX_ID_NAME + 64], name[MAX_ID_NAME + 64], description[MAX_ID_NAME + 64]; + + /* A bit of a hack: when changing the ID name, update the RNA type identifier too, + * so that the names match. This is not strictly necessary to keep it working, + * but better for identifying associated NodeTree blocks and RNA types. + */ + StructRNA *srna = ntree->interface_type; + + ntree_interface_identifier_base(ntree, base); + + /* RNA identifier may have a number suffix, but should start with the idbase string */ + if (strncmp(RNA_struct_identifier(srna), base, sizeof(base)) != 0) { + /* generate new unique RNA identifier from the ID name */ + ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description); + + /* rename the RNA type */ + RNA_def_struct_free_pointers(srna); + RNA_def_struct_identifier(srna, identifier); + RNA_def_struct_ui_text(srna, name, description); + RNA_def_struct_duplicate_pointers(srna); } } + else if (create) { + ntree_interface_type_create(ntree); + } + + return ntree->interface_type; +} - if (ntreetype->local_merge) - ntreetype->local_merge(localtree, ntree); +void ntreeInterfaceTypeFree(bNodeTree *ntree) +{ + if (ntree->interface_type) { + RNA_struct_free(&BLENDER_RNA, ntree->interface_type); + ntree->interface_type = NULL; + } +} - ntreeFreeTree_ex(localtree, FALSE); - MEM_freeN(localtree); +void ntreeInterfaceTypeUpdate(bNodeTree *ntree) +{ + /* XXX it would be sufficient to just recreate all properties + * instead of re-registering the whole struct type, + * but there is currently no good way to do this in the RNA functions. + * Overhead should be negligible. + */ + ntreeInterfaceTypeFree(ntree); + ntree_interface_type_create(ntree); } + /* ************ find stuff *************** */ int ntreeHasType(bNodeTree *ntree, int type) @@ -1420,43 +2271,34 @@ bNode *nodeGetActive(bNodeTree *ntree) /* two active flags, ID nodes have special flag for buttons display */ bNode *nodeGetActiveID(bNodeTree *ntree, short idtype) { - bNode *node; + bNode *node, *tnode; if (ntree == NULL) return NULL; - /* check for group edit */ - for (node = ntree->nodes.first; node; node = node->next) - if (node->flag & NODE_GROUP_EDIT) - break; - - if (node) - ntree = (bNodeTree *)node->id; - - /* now find active node with this id */ for (node = ntree->nodes.first; node; node = node->next) if (node->id && GS(node->id->name) == idtype) if (node->flag & NODE_ACTIVE_ID) - break; - - return node; + return node; + + /* no node with active ID in this tree, look inside groups */ + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP) { + tnode = nodeGetActiveID((bNodeTree *)node->id, idtype); + if (tnode) + return tnode; + } + } + + return NULL; } -int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) +bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) { bNode *node; - int ok = FALSE; + bool ok = false; if (ntree == NULL) return ok; - /* check for group edit */ - for (node = ntree->nodes.first; node; node = node->next) - if (node->flag & NODE_GROUP_EDIT) - break; - - if (node) - ntree = (bNodeTree *)node->id; - - /* now find active node with this id */ for (node = ntree->nodes.first; node; node = node->next) { if (node->id && GS(node->id->name) == idtype) { if (id && ok == FALSE && node->id == id) { @@ -1469,6 +2311,15 @@ int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) } } + /* update all groups linked from here + * if active ID node has been found already, + * just pass NULL so other matching nodes are deactivated. + */ + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP) + ok |= nodeSetActiveID((bNodeTree *)node->id, idtype, (ok == false ? id : NULL)); + } + return ok; } @@ -1485,6 +2336,24 @@ void nodeClearActiveID(bNodeTree *ntree, short idtype) node->flag &= ~NODE_ACTIVE_ID; } +void nodeSetSelected(bNode *node, int select) +{ + if (select) { + node->flag |= NODE_SELECT; + } + else { + bNodeSocket *sock; + + node->flag &= ~NODE_SELECT; + + /* deselect sockets too */ + for (sock = node->inputs.first; sock; sock = sock->next) + sock->flag &= ~NODE_SELECT; + for (sock = node->outputs.first; sock; sock = sock->next) + sock->flag &= ~NODE_SELECT; + } +} + void nodeClearActive(bNodeTree *ntree) { bNode *node; @@ -1495,7 +2364,6 @@ void nodeClearActive(bNodeTree *ntree) node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_ID); } - /* two active flags, ID nodes have special flag for buttons display */ void nodeSetActive(bNodeTree *ntree, bNode *node) { @@ -1525,19 +2393,6 @@ int nodeSocketIsHidden(bNodeSocket *sock) return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0); } -void nodeSocketSetType(bNodeSocket *sock, int type) -{ - int old_type = sock->type; - void *old_default_value = sock->default_value; - - sock->type = type; - - sock->default_value = node_socket_make_default_value(sock->type); - node_socket_init_default_value(type, sock->default_value); - node_socket_convert_default_value(sock->type, sock->default_value, old_type, old_default_value); - node_socket_free_default_value(old_type, old_default_value); -} - /* ************** Node Clipboard *********** */ #define USE_NODE_CB_VALIDATE @@ -1692,6 +2547,163 @@ int BKE_node_clipboard_get_type(void) return node_clipboard.type; } + +/* Node Instance Hash */ + +/* magic number for initial hash key */ +const bNodeInstanceKey NODE_INSTANCE_KEY_BASE = {5381}; + +/* Generate a hash key from ntree and node names + * Uses the djb2 algorithm with xor by Bernstein: + * http://www.cse.yorku.ca/~oz/hash.html + */ +static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str) +{ + char c; + + while ((c = *str++)) + hash.value = ((hash.value << 5) + hash.value) ^ c; /* (hash * 33) ^ c */ + + /* separator '\0' character, to avoid ambiguity from concatenated strings */ + hash.value = (hash.value << 5) + hash.value; /* hash * 33 */ + + return hash; +} + +bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, bNodeTree *ntree, bNode *node) +{ + bNodeInstanceKey key; + + key = node_hash_int_str(parent_key, ntree->id.name + 2); + + if (node) + key = node_hash_int_str(key, node->name); + + return key; +} + +static unsigned int node_instance_hash_key(const void *key) +{ + return ((const bNodeInstanceKey *)key)->value; +} + +static int node_instance_hash_key_cmp(const void *a, const void *b) +{ + unsigned int value_a = ((const bNodeInstanceKey *)a)->value; + unsigned int value_b = ((const bNodeInstanceKey *)b)->value; + if (value_a == value_b) + return 0; + else if (value_a < value_b) + return -1; + else + return 1; +} + +bNodeInstanceHash *BKE_node_instance_hash_new(const char *info) +{ + bNodeInstanceHash *hash = MEM_mallocN(sizeof(bNodeInstanceHash), info); + hash->ghash = BLI_ghash_new(node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash"); + return hash; +} + +void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp) +{ + BLI_ghash_free(hash->ghash, NULL, (GHashValFreeFP)valfreefp); + MEM_freeN(hash); +} + +void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value) +{ + bNodeInstanceHashEntry *entry = value; + entry->key = key; + entry->tag = 0; + BLI_ghash_insert(hash->ghash, &entry->key, value); +} + +void *BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key) +{ + return BLI_ghash_lookup(hash->ghash, &key); +} + +int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp) +{ + return BLI_ghash_remove(hash->ghash, &key, NULL, (GHashValFreeFP)valfreefp); +} + +void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp) +{ + BLI_ghash_clear(hash->ghash, NULL, (GHashValFreeFP)valfreefp); +} + +void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key) +{ + return BLI_ghash_pop(hash->ghash, &key, NULL); +} + +int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key) +{ + return BLI_ghash_haskey(hash->ghash, &key); +} + +int BKE_node_instance_hash_size(bNodeInstanceHash *hash) +{ + return BLI_ghash_size(hash->ghash); +} + +void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash) +{ + bNodeInstanceHashIterator iter; + + NODE_INSTANCE_HASH_ITER(iter, hash) { + bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter); + + value->tag = 0; + } +} + +void BKE_node_instance_hash_tag(bNodeInstanceHash *UNUSED(hash), void *value) +{ + bNodeInstanceHashEntry *entry = value; + entry->tag = 1; +} + +int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key) +{ + bNodeInstanceHashEntry *entry = BKE_node_instance_hash_lookup(hash, key); + + if (entry) { + entry->tag = 1; + return TRUE; + } + else + return FALSE; +} + +void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp) +{ + /* NOTE: Hash must not be mutated during iterating! + * Store tagged entries in a separate list and remove items afterward. + */ + bNodeInstanceKey *untagged = MEM_mallocN(sizeof(bNodeInstanceKey) * BKE_node_instance_hash_size(hash), "temporary node instance key list"); + bNodeInstanceHashIterator iter; + int num_untagged, i; + + num_untagged = 0; + NODE_INSTANCE_HASH_ITER(iter, hash) { + bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter); + + if (!value->tag) + untagged[num_untagged++] = BKE_node_instance_hash_iterator_get_key(&iter); + } + + for (i = 0; i < num_untagged; ++i) { + BKE_node_instance_hash_remove(hash, untagged[i], valfreefp); + } + + MEM_freeN(untagged); +} + + /* ************** dependency stuff *********** */ /* node is guaranteed to be not checked before */ @@ -1707,12 +2719,10 @@ static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort for (link = ntree->links.first; link; link = link->next) { if (link->tonode == node) { fromnode = link->fromnode; - if (fromnode) { - if (fromnode->done == 0) - fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort); - if (fromnode->level <= level) - level = fromnode->level - 1; - } + if (fromnode->done == 0) + fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort); + if (fromnode->level <= level) + level = fromnode->level - 1; } } @@ -1792,13 +2802,6 @@ static void ntree_update_link_pointers(bNodeTree *ntree) sock->flag &= ~SOCK_IN_USE; } } - for (sock = ntree->inputs.first; sock; sock = sock->next) { - sock->flag &= ~SOCK_IN_USE; - } - for (sock = ntree->outputs.first; sock; sock = sock->next) { - sock->link = NULL; - sock->flag &= ~SOCK_IN_USE; - } for (link = ntree->links.first; link; link = link->next) { link->tosock->link = link; @@ -1810,144 +2813,133 @@ static void ntree_update_link_pointers(bNodeTree *ntree) static void ntree_validate_links(bNodeTree *ntree) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); bNodeLink *link; for (link = ntree->links.first; link; link = link->next) { link->flag |= NODE_LINK_VALID; if (link->fromnode && link->tonode && link->fromnode->level <= link->tonode->level) link->flag &= ~NODE_LINK_VALID; - else if (ntreetype->validate_link) { - if (!ntreetype->validate_link(ntree, link)) + else if (ntree->typeinfo->validate_link) { + if (!ntree->typeinfo->validate_link(ntree, link)) link->flag &= ~NODE_LINK_VALID; } } } -static void ntree_verify_nodes_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) -{ - ID *id = (ID *)calldata; - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) - if (node->typeinfo->verifyfunc) - node->typeinfo->verifyfunc(ntree, node, id); -} - void ntreeVerifyNodes(struct Main *main, struct ID *id) { - bNodeTreeType *ntreetype; - bNodeTree *ntree; - int n; - - for (n = 0; n < NUM_NTREE_TYPES; ++n) { - ntreetype = ntreeGetType(n); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, id, ntree_verify_nodes_cb); - } - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) - ntree_verify_nodes_cb(id, NULL, ntree); + FOREACH_NODETREE(main, ntree, owner_id) { + bNode *node; + + if (!ntreeIsValid(ntree)) + return; + + for (node = ntree->nodes.first; node; node = node->next) + if (node->typeinfo && node->typeinfo->verifyfunc) + node->typeinfo->verifyfunc(ntree, node, id); + } FOREACH_NODETREE_END } void ntreeUpdateTree(bNodeTree *ntree) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); bNode *node; + /* avoid reentrant updates, can be caused by RNA update callbacks */ + if (ntree->is_updating) + return; + ntree->is_updating = TRUE; + + /* only if types are initialized */ + if (!ntreeIsValid(ntree)) + return; + if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) { /* set the bNodeSocket->link pointers */ ntree_update_link_pointers(ntree); - - /* update the node level from link dependencies */ - ntree_update_node_level(ntree); } /* update individual nodes */ for (node = ntree->nodes.first; node; node = node->next) { /* node tree update tags override individual node update flags */ if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) { - if (ntreetype->update_node) - ntreetype->update_node(ntree, node); - else if (node->typeinfo->updatefunc) + if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); nodeUpdateInternalLinks(ntree, node); } } - /* check link validity */ - if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) - ntree_validate_links(ntree); - /* generic tree update callback */ - if (ntreetype->update) - ntreetype->update(ntree); - else { - /* Trees can be associated with a specific node type (i.e. group nodes), - * in that case a tree update function may be defined by that node type. - */ - bNodeType *ntype = node_get_type(ntree, ntree->nodetype); - if (ntype && ntype->updatetreefunc) - ntype->updatetreefunc(ntree); - } + if (ntree->typeinfo->update) + ntree->typeinfo->update(ntree); + /* XXX this should be moved into the tree type update callback for tree supporting node groups. + * Currently the node tree interface is still a generic feature of the base NodeTree type. + */ + if (ntree->update & NTREE_UPDATE_GROUP) + ntreeInterfaceTypeUpdate(ntree); /* XXX hack, should be done by depsgraph!! */ ntreeVerifyNodes(G.main, &ntree->id); + if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) { + /* node updates can change sockets or links, repeat link pointer update afterward */ + ntree_update_link_pointers(ntree); + + /* update the node level from link dependencies */ + ntree_update_node_level(ntree); + + /* check link validity */ + ntree_validate_links(ntree); + } + /* clear update flags */ for (node = ntree->nodes.first; node; node = node->next) { node->update = 0; } ntree->update = 0; + + ntree->is_updating = FALSE; } void nodeUpdate(bNodeTree *ntree, bNode *node) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); + /* avoid reentrant updates, can be caused by RNA update callbacks */ + if (ntree->is_updating) + return; + ntree->is_updating = TRUE; - if (ntreetype->update_node) - ntreetype->update_node(ntree, node); - else if (node->typeinfo->updatefunc) + if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); nodeUpdateInternalLinks(ntree, node); /* clear update flag */ node->update = 0; + + ntree->is_updating = FALSE; } int nodeUpdateID(bNodeTree *ntree, ID *id) { - bNodeTreeType *ntreetype; bNode *node; int change = FALSE; if (ELEM(NULL, id, ntree)) return change; - ntreetype = ntreeGetType(ntree->type); + /* avoid reentrant updates, can be caused by RNA update callbacks */ + if (ntree->is_updating) + return change; + ntree->is_updating = TRUE; - if (ntreetype->update_node) { - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == id) { - change = TRUE; - node->update |= NODE_UPDATE_ID; - ntreetype->update_node(ntree, node); - /* clear update flag */ - node->update = 0; - } - } - } - else { - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == id) { - change = TRUE; - node->update |= NODE_UPDATE_ID; - if (node->typeinfo->updatefunc) - node->typeinfo->updatefunc(ntree, node); - /* clear update flag */ - node->update = 0; - } + for (node = ntree->nodes.first; node; node = node->next) { + if (node->id == id) { + change = TRUE; + node->update |= NODE_UPDATE_ID; + if (node->typeinfo->updatefunc) + node->typeinfo->updatefunc(ntree, node); + /* clear update flag */ + node->update = 0; } } @@ -1955,6 +2947,7 @@ int nodeUpdateID(bNodeTree *ntree, ID *id) nodeUpdateInternalLinks(ntree, node); } + ntree->is_updating = FALSE; return change; } @@ -1967,21 +2960,75 @@ void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node) } -/* ************* node type access ********** */ - -int nodeValid(bNodeTree *ntree, bNodeTemplate *ntemp) +/* nodes that use ID data get synced with local data */ +void nodeSynchronizeID(bNode *node, bool copy_to_id) { - bNodeType *ntype = node_get_type(ntree, ntemp->type); - if (ntype) { - if (ntype->validfunc) - return ntype->validfunc(ntree, ntemp); - else - return 1; + if (node->id == NULL) return; + + if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) { + bNodeSocket *sock; + Material *ma = (Material *)node->id; + int a; + + /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */ + for (a = 0, sock = node->inputs.first; sock; sock = sock->next, a++) { + if (!nodeSocketIsHidden(sock)) { + if (copy_to_id) { + switch (a) { + case MAT_IN_COLOR: + copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; + case MAT_IN_SPEC: + copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; + case MAT_IN_REFL: + ma->ref = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + case MAT_IN_MIR: + copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; + case MAT_IN_AMB: + ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + case MAT_IN_EMIT: + ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + case MAT_IN_SPECTRA: + ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + case MAT_IN_RAY_MIRROR: + ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + case MAT_IN_ALPHA: + ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + case MAT_IN_TRANSLUCENCY: + ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break; + } + } + else { + switch (a) { + case MAT_IN_COLOR: + copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break; + case MAT_IN_SPEC: + copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break; + case MAT_IN_REFL: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ref; break; + case MAT_IN_MIR: + copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break; + case MAT_IN_AMB: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break; + case MAT_IN_EMIT: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break; + case MAT_IN_SPECTRA: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break; + case MAT_IN_RAY_MIRROR: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break; + case MAT_IN_ALPHA: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break; + case MAT_IN_TRANSLUCENCY: + ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break; + } + } + } + } } - else - return 0; } + +/* ************* node type access ********** */ + const char *nodeLabel(bNode *node) { if (node->label[0] != '\0') @@ -1989,81 +3036,136 @@ const char *nodeLabel(bNode *node) else if (node->typeinfo->labelfunc) return node->typeinfo->labelfunc(node); else - return IFACE_(node->typeinfo->name); + return IFACE_(node->typeinfo->ui_name); } -struct bNodeTree *nodeGroupEditGet(struct bNode *node) +static void node_type_base_defaults(bNodeType *ntype) { - if (node->typeinfo->group_edit_get) - return node->typeinfo->group_edit_get(node); - else - return NULL; + /* default size values */ + node_type_size_preset(ntype, NODE_SIZE_DEFAULT); + ntype->height = 100; + ntype->minheight = 30; + ntype->maxheight = FLT_MAX; } -struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit) +/* allow this node for any tree type */ +static int node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(ntree)) { - if (node->typeinfo->group_edit_set) - return node->typeinfo->group_edit_set(node, edit); - else if (node->typeinfo->group_edit_get) - return node->typeinfo->group_edit_get(node); - else - return NULL; + return TRUE; } -void nodeGroupEditClear(struct bNode *node) +/* use the basic poll function */ +static int node_poll_instance_default(bNode *node, bNodeTree *ntree) { - if (node->typeinfo->group_edit_clear) - node->typeinfo->group_edit_clear(node); + return node->typeinfo->poll(node->typeinfo, ntree); } -struct bNodeTemplate nodeMakeTemplate(struct bNode *node) +void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) { - bNodeTemplate ntemp; - if (node->typeinfo->templatefunc) - return node->typeinfo->templatefunc(node); - else { - ntemp.type = node->type; - return ntemp; + /* Use static type info header to map static int type to identifier string and RNA struct type. + * Associate the RNA struct type with the bNodeType. + * Dynamically registered nodes will create an RNA type at runtime + * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types + * created in makesrna, which can not be associated to a bNodeType immediately, + * since bNodeTypes are registered afterward ... + */ + #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ + case ID: \ + BLI_strncpy(ntype->idname, #Category #StructName, sizeof(ntype->idname)); \ + ntype->ext.srna = RNA_struct_find(#Category #StructName); \ + BLI_assert(ntype->ext.srna != NULL); \ + RNA_struct_blender_type_set(ntype->ext.srna, ntype); \ + break; + + switch (type) { + #include "NOD_static_types.h" } + + /* make sure we have a valid type (everything registered) */ + BLI_assert(ntype->idname[0] != '\0'); + + ntype->type = type; + BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name)); + ntype->nclass = nclass; + ntype->flag = flag; + + node_type_base_defaults(ntype); + + ntype->poll = node_poll_default; + ntype->poll_instance = node_poll_instance_default; } -void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char *name, short nclass, short flag) +void node_type_base_custom(bNodeType *ntype, const char *idname, const char *name, short nclass, short flag) { - memset(ntype, 0, sizeof(bNodeType)); - - ntype->type = type; - BLI_strncpy(ntype->name, name, sizeof(ntype->name)); + BLI_strncpy(ntype->idname, idname, sizeof(ntype->idname)); + ntype->type = NODE_CUSTOM; + BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name)); ntype->nclass = nclass; ntype->flag = flag; - /* Default muting stuff. */ - if (ttype) - ntype->update_internal_links = ttype->update_internal_links; + node_type_base_defaults(ntype); +} - /* default size values */ - node_type_size_preset(ntype, NODE_SIZE_DEFAULT); +static bool unique_socket_template_identifier_check(void *arg, const char *name) +{ + bNodeSocketTemplate *ntemp; + struct {bNodeSocketTemplate *list; bNodeSocketTemplate *ntemp;} *data = arg; - ntype->height = 100; - ntype->minheight = 30; - ntype->maxheight = FLT_MAX; + for (ntemp = data->list; ntemp->type >= 0; ++ntemp) { + if (ntemp != data->ntemp) { + if (STREQ(ntemp->identifier, name)) { + return true; + } + } + } + + return false; +} + +static void unique_socket_template_identifier(bNodeSocketTemplate *list, bNodeSocketTemplate *ntemp, const char defname[], char delim) +{ + struct {bNodeSocketTemplate *list; bNodeSocketTemplate *ntemp;} data; + data.list = list; + data.ntemp = ntemp; + + BLI_uniquename_cb(unique_socket_template_identifier_check, &data, defname, delim, ntemp->identifier, sizeof(ntemp->identifier)); } void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs) { + bNodeSocketTemplate *ntemp; + ntype->inputs = inputs; ntype->outputs = outputs; + + /* automatically generate unique identifiers */ + if (inputs) { + /* clear identifier strings (uninitialized memory) */ + for (ntemp = inputs; ntemp->type >= 0; ++ntemp) + ntemp->identifier[0] = '\0'; + + for (ntemp = inputs; ntemp->type >= 0; ++ntemp) { + BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier)); + unique_socket_template_identifier(inputs, ntemp, ntemp->identifier, '_'); + } + } + if (outputs) { + /* clear identifier strings (uninitialized memory) */ + for (ntemp = outputs; ntemp->type >= 0; ++ntemp) + ntemp->identifier[0] = '\0'; + + for (ntemp = outputs; ntemp->type >= 0; ++ntemp) { + BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier)); + unique_socket_template_identifier(outputs, ntemp, ntemp->identifier, '_'); + } + } } -void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp)) +void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node)) { ntype->initfunc = initfunc; } -void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp)) -{ - ntype->validfunc = validfunc; -} - void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth) { ntype->width = width; @@ -2089,14 +3191,17 @@ void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size) } } -void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *)) +void node_type_storage(bNodeType *ntype, + const char *storagename, + void (*freefunc)(struct bNode *node), + void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node)) { if (storagename) BLI_strncpy(ntype->storagename, storagename, sizeof(ntype->storagename)); else ntype->storagename[0] = '\0'; - ntype->copystoragefunc = copystoragefunc; - ntype->freestoragefunc = freestoragefunc; + ntype->copyfunc = copyfunc; + ntype->freefunc = freefunc; } void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *)) @@ -2104,11 +3209,6 @@ void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bN ntype->labelfunc = labelfunc; } -void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *)) -{ - ntype->templatefunc = templatefunc; -} - void node_type_update(struct bNodeType *ntype, void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node), void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id)) @@ -2117,50 +3217,21 @@ void node_type_update(struct bNodeType *ntype, ntype->verifyfunc = verifyfunc; } -void node_type_tree(struct bNodeType *ntype, void (*inittreefunc)(struct bNodeTree *), void (*updatetreefunc)(struct bNodeTree *)) -{ - ntype->inittreefunc = inittreefunc; - ntype->updatetreefunc = updatetreefunc; -} - -void node_type_group_edit(struct bNodeType *ntype, - struct bNodeTree *(*group_edit_get)(struct bNode *node), - struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit), - void (*group_edit_clear)(struct bNode *node)) -{ - ntype->group_edit_get = group_edit_get; - ntype->group_edit_set = group_edit_set; - ntype->group_edit_clear = group_edit_clear; -} - -void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **)) -{ - ntype->execfunc = execfunc; -} - -void node_type_exec_new(struct bNodeType *ntype, - void *(*initexecfunc)(struct bNode *node), - void (*freeexecfunc)(struct bNode *node, void *nodedata), - void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **)) +void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc) { ntype->initexecfunc = initexecfunc; ntype->freeexecfunc = freeexecfunc; - ntype->newexecfunc = newexecfunc; -} - -void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *)) -{ - ntype->update_internal_links = update_internal_links; + ntype->execfunc = execfunc; } -void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)) +void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc) { ntype->gpufunc = gpufunc; } -void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out)) +void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *)) { - ntype->gpuextfunc = gpuextfunc; + ntype->update_internal_links = update_internal_links; } void node_type_compatibility(struct bNodeType *ntype, short compatibility) @@ -2168,298 +3239,276 @@ void node_type_compatibility(struct bNodeType *ntype, short compatibility) ntype->compatibility = compatibility; } -static bNodeType *is_nodetype_registered(ListBase *typelist, int type) -{ - bNodeType *ntype = typelist->first; - - for (; ntype; ntype = ntype->next) - if (ntype->type == type) - return ntype; - - return NULL; -} - -void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype) -{ - ListBase *typelist = &(ttype->node_types); - bNodeType *found = is_nodetype_registered(typelist, ntype->type); - - if (found == NULL) - BLI_addtail(typelist, ntype); - - /* Associate the RNA struct type with the bNodeType. - * Dynamically registered nodes will create an RNA type at runtime - * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types - * created in makesrna, which can not be associated to a bNodeType immediately, - * since bNodeTypes are registered afterward ... - */ - #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ - if (ID == ntype->type) { \ - StructRNA *srna = RNA_struct_find(STRINGIFY_ARG(Category##StructName)); \ - BLI_assert(srna != NULL); \ - RNA_struct_blender_type_set(srna, ntype); \ - } - - /* XXX hack, this file will be moved to the nodes folder in customnodes branch, - * then this stupid include path is not needed any more. - */ - #include "intern/rna_nodetree_types.h" -} - -static void registerCompositNodes(bNodeTreeType *ttype) -{ - register_node_type_frame(ttype); - register_node_type_reroute(ttype); - - register_node_type_cmp_group(ttype); - - register_node_type_cmp_rlayers(ttype); - register_node_type_cmp_image(ttype); - register_node_type_cmp_texture(ttype); - register_node_type_cmp_value(ttype); - register_node_type_cmp_rgb(ttype); - register_node_type_cmp_curve_time(ttype); - register_node_type_cmp_movieclip(ttype); - - register_node_type_cmp_composite(ttype); - register_node_type_cmp_viewer(ttype); - register_node_type_cmp_splitviewer(ttype); - register_node_type_cmp_output_file(ttype); - register_node_type_cmp_view_levels(ttype); - - register_node_type_cmp_curve_rgb(ttype); - register_node_type_cmp_mix_rgb(ttype); - register_node_type_cmp_hue_sat(ttype); - register_node_type_cmp_brightcontrast(ttype); - register_node_type_cmp_gamma(ttype); - register_node_type_cmp_invert(ttype); - register_node_type_cmp_alphaover(ttype); - register_node_type_cmp_zcombine(ttype); - register_node_type_cmp_colorbalance(ttype); - register_node_type_cmp_huecorrect(ttype); - - register_node_type_cmp_normal(ttype); - register_node_type_cmp_curve_vec(ttype); - register_node_type_cmp_map_value(ttype); - register_node_type_cmp_map_range(ttype); - register_node_type_cmp_normalize(ttype); - - register_node_type_cmp_filter(ttype); - register_node_type_cmp_blur(ttype); - register_node_type_cmp_dblur(ttype); - register_node_type_cmp_bilateralblur(ttype); - register_node_type_cmp_vecblur(ttype); - register_node_type_cmp_dilateerode(ttype); - register_node_type_cmp_inpaint(ttype); - register_node_type_cmp_despeckle(ttype); - register_node_type_cmp_defocus(ttype); - - register_node_type_cmp_valtorgb(ttype); - register_node_type_cmp_rgbtobw(ttype); - register_node_type_cmp_setalpha(ttype); - register_node_type_cmp_idmask(ttype); - register_node_type_cmp_math(ttype); - register_node_type_cmp_seprgba(ttype); - register_node_type_cmp_combrgba(ttype); - register_node_type_cmp_sephsva(ttype); - register_node_type_cmp_combhsva(ttype); - register_node_type_cmp_sepyuva(ttype); - register_node_type_cmp_combyuva(ttype); - register_node_type_cmp_sepycca(ttype); - register_node_type_cmp_combycca(ttype); - register_node_type_cmp_premulkey(ttype); - - register_node_type_cmp_diff_matte(ttype); - register_node_type_cmp_distance_matte(ttype); - register_node_type_cmp_chroma_matte(ttype); - register_node_type_cmp_color_matte(ttype); - register_node_type_cmp_channel_matte(ttype); - register_node_type_cmp_color_spill(ttype); - register_node_type_cmp_luma_matte(ttype); - register_node_type_cmp_doubleedgemask(ttype); - register_node_type_cmp_keyingscreen(ttype); - register_node_type_cmp_keying(ttype); - - register_node_type_cmp_translate(ttype); - register_node_type_cmp_rotate(ttype); - register_node_type_cmp_scale(ttype); - register_node_type_cmp_flip(ttype); - register_node_type_cmp_crop(ttype); - register_node_type_cmp_displace(ttype); - register_node_type_cmp_mapuv(ttype); - register_node_type_cmp_glare(ttype); - register_node_type_cmp_tonemap(ttype); - register_node_type_cmp_lensdist(ttype); - register_node_type_cmp_transform(ttype); - register_node_type_cmp_stabilize2d(ttype); - register_node_type_cmp_moviedistortion(ttype); - - register_node_type_cmp_colorcorrection(ttype); - register_node_type_cmp_boxmask(ttype); - register_node_type_cmp_ellipsemask(ttype); - register_node_type_cmp_bokehimage(ttype); - register_node_type_cmp_bokehblur(ttype); - register_node_type_cmp_switch(ttype); - register_node_type_cmp_pixelate(ttype); - - register_node_type_cmp_mask(ttype); - register_node_type_cmp_trackpos(ttype); -} - -static void registerShaderNodes(bNodeTreeType *ttype) -{ - register_node_type_frame(ttype); - register_node_type_reroute(ttype); - - register_node_type_sh_group(ttype); - - register_node_type_sh_output(ttype); - register_node_type_sh_material(ttype); - register_node_type_sh_camera(ttype); - register_node_type_sh_gamma(ttype); - register_node_type_sh_brightcontrast(ttype); - register_node_type_sh_value(ttype); - register_node_type_sh_rgb(ttype); - register_node_type_sh_mix_rgb(ttype); - register_node_type_sh_valtorgb(ttype); - register_node_type_sh_rgbtobw(ttype); - register_node_type_sh_texture(ttype); - register_node_type_sh_normal(ttype); - register_node_type_sh_geom(ttype); - register_node_type_sh_mapping(ttype); - register_node_type_sh_curve_vec(ttype); - register_node_type_sh_curve_rgb(ttype); - register_node_type_sh_math(ttype); - register_node_type_sh_vect_math(ttype); - register_node_type_sh_squeeze(ttype); - register_node_type_sh_material_ext(ttype); - register_node_type_sh_invert(ttype); - register_node_type_sh_seprgb(ttype); - register_node_type_sh_combrgb(ttype); - register_node_type_sh_hue_sat(ttype); - - register_node_type_sh_attribute(ttype); - register_node_type_sh_geometry(ttype); - register_node_type_sh_light_path(ttype); - register_node_type_sh_light_falloff(ttype); - register_node_type_sh_object_info(ttype); - register_node_type_sh_fresnel(ttype); - register_node_type_sh_layer_weight(ttype); - register_node_type_sh_tex_coord(ttype); - register_node_type_sh_particle_info(ttype); - register_node_type_sh_hair_info(ttype); - register_node_type_sh_bump(ttype); - register_node_type_sh_script(ttype); - register_node_type_sh_tangent(ttype); - register_node_type_sh_normal_map(ttype); - - register_node_type_sh_background(ttype); - register_node_type_sh_bsdf_anisotropic(ttype); - register_node_type_sh_bsdf_diffuse(ttype); - register_node_type_sh_bsdf_glossy(ttype); - register_node_type_sh_bsdf_glass(ttype); - register_node_type_sh_bsdf_refraction(ttype); - register_node_type_sh_bsdf_translucent(ttype); - register_node_type_sh_bsdf_transparent(ttype); - register_node_type_sh_bsdf_velvet(ttype); - register_node_type_sh_emission(ttype); - register_node_type_sh_holdout(ttype); - register_node_type_sh_ambient_occlusion(ttype); - //register_node_type_sh_volume_transparent(ttype); - //register_node_type_sh_volume_isotropic(ttype); - register_node_type_sh_mix_shader(ttype); - register_node_type_sh_add_shader(ttype); - - register_node_type_sh_output_lamp(ttype); - register_node_type_sh_output_material(ttype); - register_node_type_sh_output_world(ttype); - - register_node_type_sh_tex_image(ttype); - register_node_type_sh_tex_environment(ttype); - register_node_type_sh_tex_sky(ttype); - register_node_type_sh_tex_noise(ttype); - register_node_type_sh_tex_wave(ttype); - register_node_type_sh_tex_voronoi(ttype); - register_node_type_sh_tex_musgrave(ttype); - register_node_type_sh_tex_gradient(ttype); - register_node_type_sh_tex_magic(ttype); - register_node_type_sh_tex_checker(ttype); - register_node_type_sh_tex_brick(ttype); -} - -static void registerTextureNodes(bNodeTreeType *ttype) -{ - register_node_type_frame(ttype); - register_node_type_reroute(ttype); - - register_node_type_tex_group(ttype); - - register_node_type_tex_math(ttype); - register_node_type_tex_mix_rgb(ttype); - register_node_type_tex_valtorgb(ttype); - register_node_type_tex_rgbtobw(ttype); - register_node_type_tex_valtonor(ttype); - register_node_type_tex_curve_rgb(ttype); - register_node_type_tex_curve_time(ttype); - register_node_type_tex_invert(ttype); - register_node_type_tex_hue_sat(ttype); - register_node_type_tex_coord(ttype); - register_node_type_tex_distance(ttype); - register_node_type_tex_compose(ttype); - register_node_type_tex_decompose(ttype); - - register_node_type_tex_output(ttype); - register_node_type_tex_viewer(ttype); - - register_node_type_tex_checker(ttype); - register_node_type_tex_texture(ttype); - register_node_type_tex_bricks(ttype); - register_node_type_tex_image(ttype); - - register_node_type_tex_rotate(ttype); - register_node_type_tex_translate(ttype); - register_node_type_tex_scale(ttype); - register_node_type_tex_at(ttype); - - register_node_type_tex_proc_voronoi(ttype); - register_node_type_tex_proc_blend(ttype); - register_node_type_tex_proc_magic(ttype); - register_node_type_tex_proc_marble(ttype); - register_node_type_tex_proc_clouds(ttype); - register_node_type_tex_proc_wood(ttype); - register_node_type_tex_proc_musgrave(ttype); - register_node_type_tex_proc_noise(ttype); - register_node_type_tex_proc_stucci(ttype); - register_node_type_tex_proc_distnoise(ttype); -} - -static void free_typeinfos(ListBase *list) -{ - bNodeType *ntype, *next; - for (ntype = list->first; ntype; ntype = next) { - next = ntype->next; - - if (ntype->needs_free) - MEM_freeN(ntype); - } +static void registerCompositNodes(void) +{ + register_node_type_cmp_group(); + + register_node_type_cmp_rlayers(); + register_node_type_cmp_image(); + register_node_type_cmp_texture(); + register_node_type_cmp_value(); + register_node_type_cmp_rgb(); + register_node_type_cmp_curve_time(); + register_node_type_cmp_movieclip(); + + register_node_type_cmp_composite(); + register_node_type_cmp_viewer(); + register_node_type_cmp_splitviewer(); + register_node_type_cmp_output_file(); + register_node_type_cmp_view_levels(); + + register_node_type_cmp_curve_rgb(); + register_node_type_cmp_mix_rgb(); + register_node_type_cmp_hue_sat(); + register_node_type_cmp_brightcontrast(); + register_node_type_cmp_gamma(); + register_node_type_cmp_invert(); + register_node_type_cmp_alphaover(); + register_node_type_cmp_zcombine(); + register_node_type_cmp_colorbalance(); + register_node_type_cmp_huecorrect(); + + register_node_type_cmp_normal(); + register_node_type_cmp_curve_vec(); + register_node_type_cmp_map_value(); + register_node_type_cmp_map_range(); + register_node_type_cmp_normalize(); + + register_node_type_cmp_filter(); + register_node_type_cmp_blur(); + register_node_type_cmp_dblur(); + register_node_type_cmp_bilateralblur(); + register_node_type_cmp_vecblur(); + register_node_type_cmp_dilateerode(); + register_node_type_cmp_inpaint(); + register_node_type_cmp_despeckle(); + register_node_type_cmp_defocus(); + + register_node_type_cmp_valtorgb(); + register_node_type_cmp_rgbtobw(); + register_node_type_cmp_setalpha(); + register_node_type_cmp_idmask(); + register_node_type_cmp_math(); + register_node_type_cmp_seprgba(); + register_node_type_cmp_combrgba(); + register_node_type_cmp_sephsva(); + register_node_type_cmp_combhsva(); + register_node_type_cmp_sepyuva(); + register_node_type_cmp_combyuva(); + register_node_type_cmp_sepycca(); + register_node_type_cmp_combycca(); + register_node_type_cmp_premulkey(); + + register_node_type_cmp_diff_matte(); + register_node_type_cmp_distance_matte(); + register_node_type_cmp_chroma_matte(); + register_node_type_cmp_color_matte(); + register_node_type_cmp_channel_matte(); + register_node_type_cmp_color_spill(); + register_node_type_cmp_luma_matte(); + register_node_type_cmp_doubleedgemask(); + register_node_type_cmp_keyingscreen(); + register_node_type_cmp_keying(); + + register_node_type_cmp_translate(); + register_node_type_cmp_rotate(); + register_node_type_cmp_scale(); + register_node_type_cmp_flip(); + register_node_type_cmp_crop(); + register_node_type_cmp_displace(); + register_node_type_cmp_mapuv(); + register_node_type_cmp_glare(); + register_node_type_cmp_tonemap(); + register_node_type_cmp_lensdist(); + register_node_type_cmp_transform(); + register_node_type_cmp_stabilize2d(); + register_node_type_cmp_moviedistortion(); + + register_node_type_cmp_colorcorrection(); + register_node_type_cmp_boxmask(); + register_node_type_cmp_ellipsemask(); + register_node_type_cmp_bokehimage(); + register_node_type_cmp_bokehblur(); + register_node_type_cmp_switch(); + register_node_type_cmp_pixelate(); + + register_node_type_cmp_mask(); + register_node_type_cmp_trackpos(); +} + +static void registerShaderNodes(void) +{ + register_node_type_sh_group(); + + register_node_type_sh_output(); + register_node_type_sh_material(); + register_node_type_sh_camera(); + register_node_type_sh_gamma(); + register_node_type_sh_brightcontrast(); + register_node_type_sh_value(); + register_node_type_sh_rgb(); + register_node_type_sh_mix_rgb(); + register_node_type_sh_valtorgb(); + register_node_type_sh_rgbtobw(); + register_node_type_sh_texture(); + register_node_type_sh_normal(); + register_node_type_sh_geom(); + register_node_type_sh_mapping(); + register_node_type_sh_curve_vec(); + register_node_type_sh_curve_rgb(); + register_node_type_sh_math(); + register_node_type_sh_vect_math(); + register_node_type_sh_squeeze(); + register_node_type_sh_material_ext(); + register_node_type_sh_invert(); + register_node_type_sh_seprgb(); + register_node_type_sh_combrgb(); + register_node_type_sh_hue_sat(); + + register_node_type_sh_attribute(); + register_node_type_sh_geometry(); + register_node_type_sh_light_path(); + register_node_type_sh_light_falloff(); + register_node_type_sh_object_info(); + register_node_type_sh_fresnel(); + register_node_type_sh_layer_weight(); + register_node_type_sh_tex_coord(); + register_node_type_sh_particle_info(); + register_node_type_sh_bump(); + + register_node_type_sh_background(); + register_node_type_sh_bsdf_anisotropic(); + register_node_type_sh_bsdf_diffuse(); + register_node_type_sh_bsdf_glossy(); + register_node_type_sh_bsdf_glass(); + register_node_type_sh_bsdf_translucent(); + register_node_type_sh_bsdf_transparent(); + register_node_type_sh_bsdf_velvet(); + register_node_type_sh_emission(); + register_node_type_sh_holdout(); + //register_node_type_sh_volume_transparent(); + //register_node_type_sh_volume_isotropic(); + register_node_type_sh_mix_shader(); + register_node_type_sh_add_shader(); + + register_node_type_sh_output_lamp(); + register_node_type_sh_output_material(); + register_node_type_sh_output_world(); + + register_node_type_sh_tex_image(); + register_node_type_sh_tex_environment(); + register_node_type_sh_tex_sky(); + register_node_type_sh_tex_noise(); + register_node_type_sh_tex_wave(); + register_node_type_sh_tex_voronoi(); + register_node_type_sh_tex_musgrave(); + register_node_type_sh_tex_gradient(); + register_node_type_sh_tex_magic(); + register_node_type_sh_tex_checker(); + register_node_type_sh_tex_brick(); +} + +static void registerTextureNodes(void) +{ + register_node_type_tex_group(); + + + register_node_type_tex_math(); + register_node_type_tex_mix_rgb(); + register_node_type_tex_valtorgb(); + register_node_type_tex_rgbtobw(); + register_node_type_tex_valtonor(); + register_node_type_tex_curve_rgb(); + register_node_type_tex_curve_time(); + register_node_type_tex_invert(); + register_node_type_tex_hue_sat(); + register_node_type_tex_coord(); + register_node_type_tex_distance(); + register_node_type_tex_compose(); + register_node_type_tex_decompose(); + + register_node_type_tex_output(); + register_node_type_tex_viewer(); + register_node_type_sh_script(); + register_node_type_sh_tangent(); + register_node_type_sh_normal_map(); + register_node_type_sh_hair_info(); + + register_node_type_tex_checker(); + register_node_type_tex_texture(); + register_node_type_tex_bricks(); + register_node_type_tex_image(); + register_node_type_sh_bsdf_refraction(); + register_node_type_sh_ambient_occlusion(); + + register_node_type_tex_rotate(); + register_node_type_tex_translate(); + register_node_type_tex_scale(); + register_node_type_tex_at(); + + register_node_type_tex_proc_voronoi(); + register_node_type_tex_proc_blend(); + register_node_type_tex_proc_magic(); + register_node_type_tex_proc_marble(); + register_node_type_tex_proc_clouds(); + register_node_type_tex_proc_wood(); + register_node_type_tex_proc_musgrave(); + register_node_type_tex_proc_noise(); + register_node_type_tex_proc_stucci(); + register_node_type_tex_proc_distnoise(); } void init_nodesystem(void) { - /* init clipboard */ - node_clipboard.nodes.first = node_clipboard.nodes.last = NULL; - node_clipboard.links.first = node_clipboard.links.last = NULL; + nodetreetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetreetypes_hash gh"); + nodetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetypes_hash gh"); + nodesockettypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodesockettypes_hash gh"); + + register_standard_node_socket_types(); + + register_node_tree_type_cmp(); + register_node_tree_type_sh(); + register_node_tree_type_tex(); + + register_node_type_frame(); + register_node_type_reroute(); + register_node_type_group_input(); + register_node_type_group_output(); - registerCompositNodes(ntreeGetType(NTREE_COMPOSIT)); - registerShaderNodes(ntreeGetType(NTREE_SHADER)); - registerTextureNodes(ntreeGetType(NTREE_TEXTURE)); + registerCompositNodes(); + registerShaderNodes(); + registerTextureNodes(); } void free_nodesystem(void) { - free_typeinfos(&ntreeGetType(NTREE_COMPOSIT)->node_types); - free_typeinfos(&ntreeGetType(NTREE_SHADER)->node_types); - free_typeinfos(&ntreeGetType(NTREE_TEXTURE)->node_types); + NODE_TYPES_BEGIN(nt) + if (nt->ext.free) { + nt->ext.free(nt->ext.data); + } + NODE_TYPES_END + + NODE_SOCKET_TYPES_BEGIN(st) + if (st->ext_socket.free) + st->ext_socket.free(st->ext_socket.data); + if (st->ext_interface.free) + st->ext_interface.free(st->ext_interface.data); + NODE_SOCKET_TYPES_END + + NODE_TREE_TYPES_BEGIN(nt) + if (nt->ext.free) { + nt->ext.free(nt->ext.data); + } + NODE_TREE_TYPES_END + + BLI_ghash_free(nodetypes_hash, NULL, node_free_type); + nodetypes_hash = NULL; + + BLI_ghash_free(nodesockettypes_hash, NULL, node_free_socket_type); + nodesockettypes_hash = NULL; + + BLI_ghash_free(nodetreetypes_hash, NULL, ntree_free_type); + nodetreetypes_hash = NULL; } /* called from BKE_scene_unlink, when deleting a scene goes over all scenes diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index c900d08e4e9..8034c4d1de9 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -657,6 +657,85 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) return ret; } + +/* read old smoke cache from 2.64 */ +static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + + if (sds->fluid) { + size_t res = sds->res[0]*sds->res[1]*sds->res[2]; + float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz; + unsigned char *obstacles; + unsigned int out_len = (unsigned int)res * sizeof(float); + float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp"); + + int fluid_fields = smoke_get_data_flags(sds); + + /* Part part of the new cache header */ + sds->active_color[0] = 0.7f; + sds->active_color[1] = 0.7f; + sds->active_color[2] = 0.7f; + + smoke_export(sds->fluid, &dt, &dx, &dens, NULL, NULL, NULL, &heat, &heatold, &vx, &vy, &vz, NULL, NULL, NULL, &obstacles); + + ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len); + + if (fluid_fields & SM_ACTIVE_HEAT) + { + ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len); + } + else + { + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len); + } + ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res); + ptcache_file_read(pf, &dt, 1, sizeof(float)); + ptcache_file_read(pf, &dx, 1, sizeof(float)); + + MEM_freeN(tmp_array); + + if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) { + int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big, res_big_array[3]; + float *dens, *tcu, *tcv, *tcw; + unsigned int out_len = sizeof(float)*(unsigned int)res; + unsigned int out_len_big; + unsigned char *tmp_array_big; + + smoke_turbulence_get_res(sds->wt, res_big_array); + res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; + out_len_big = sizeof(float) * (unsigned int)res_big; + + tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp"); + + smoke_turbulence_export(sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw); + + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)tmp_array_big, out_len_big); + + ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len); + + MEM_freeN(tmp_array_big); + } + } + + return 1; +} + static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; @@ -671,7 +750,13 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) /* version header */ ptcache_file_read(pf, version, 4, sizeof(char)); - if (strncmp(version, SMOKE_CACHE_VERSION, 4)) return 0; + if (strncmp(version, SMOKE_CACHE_VERSION, 4)) + { + /* reset file pointer */ + fseek(pf->fp, -4, SEEK_CUR); + return ptcache_smoke_read_old(pf, smoke_v); + } + /* fluid info */ ptcache_file_read(pf, &cache_fields, 1, sizeof(int)); ptcache_file_read(pf, &active_fields, 1, sizeof(int)); @@ -1362,7 +1447,7 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p newname += len; } if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) { - idname = (pid->ob->id.name+2); + idname = (pid->ob->id.name + 2); /* convert chars to hex so they are always a valid filename */ while ('\0' != *idname) { BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++)); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index bdf2ce622de..2517324242b 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -148,7 +148,7 @@ void default_color_mapping(ColorMapping *colormap) { memset(colormap, 0, sizeof(ColorMapping)); - init_colorband(&colormap->coba, 1); + init_colorband(&colormap->coba, true); colormap->bright = 1.0; colormap->contrast = 1.0; @@ -163,7 +163,7 @@ void default_color_mapping(ColorMapping *colormap) /* ****************** COLORBAND ******************* */ -void init_colorband(ColorBand *coba, int rangetype) +void init_colorband(ColorBand *coba, bool rangetype) { int a; @@ -205,7 +205,7 @@ void init_colorband(ColorBand *coba, int rangetype) } -ColorBand *add_colorband(int rangetype) +ColorBand *add_colorband(bool rangetype) { ColorBand *coba; @@ -695,7 +695,7 @@ Tex *BKE_texture_copy(Tex *tex) if (tex->nodetree) { if (tex->nodetree->execdata) { - ntreeTexEndExecTree(tex->nodetree->execdata, 1); + ntreeTexEndExecTree(tex->nodetree->execdata); } texn->nodetree = ntreeCopyTree(tex->nodetree); } @@ -1285,7 +1285,7 @@ PointDensity *BKE_add_pointdensity(void) pd->noise_depth = 1; pd->noise_fac = 1.0f; pd->noise_influence = TEX_PD_NOISE_STATIC; - pd->coba = add_colorband(1); + pd->coba = add_colorband(true); pd->speed_scale = 1.0f; pd->totpoints = 0; pd->object = NULL; diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 97564ca5363..641aaa1f3fc 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -70,6 +70,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfre void BLI_ghash_insert(GHash *gh, void *key, void *val); void *BLI_ghash_lookup(GHash *gh, const void *key); bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); +void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); bool BLI_ghash_haskey(GHash *gh, const void *key); int BLI_ghash_size(GHash *gh); diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 9b3fca280c4..199174ae602 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -23,10 +23,13 @@ # # ***** END GPL LICENSE BLOCK ***** +# XXX allowing blenkernel and RNA includes in blenlib is a hack, +# but needed in a few places atm (bpath.c for instance) set(INC . # ../blenkernel # dont add this back! ../makesdna + ../makesrna ../../../intern/ghost ../../../intern/guardedalloc ../../../extern/wcwidth diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index ebc40ebc5e3..0887d646479 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -62,8 +62,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) gh->nentries = 0; gh->nbuckets = hashsizes[gh->cursize]; - gh->buckets = MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); - memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets)); + gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); return gh; } @@ -88,8 +87,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val) int i, nold = gh->nbuckets; gh->nbuckets = hashsizes[++gh->cursize]; - gh->buckets = (Entry **)MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); - memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets)); + gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); for (i = 0; i < nold; i++) { for (e = old[i]; e; ) { @@ -148,6 +146,32 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr return false; } +void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +{ + int i; + + if (keyfreefp || valfreefp) { + for (i = 0; i < gh->nbuckets; i++) { + Entry *e; + + for (e = gh->buckets[i]; e; ) { + Entry *n = e->next; + + if (keyfreefp) keyfreefp(e->key); + if (valfreefp) valfreefp(e->val); + + e = n; + } + } + } + + gh->cursize = 0; + gh->nentries = 0; + gh->nbuckets = hashsizes[gh->cursize]; + + gh->buckets = MEM_recallocN(gh->buckets, gh->nbuckets * sizeof(*gh->buckets)); +} + /* same as above but return the value, * no free value argument since it will be returned */ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5b746ac5ab1..0fa01b95bb2 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -130,6 +130,7 @@ #include "BKE_lattice.h" #include "BKE_library.h" // for which_libbase #include "BKE_idcode.h" +#include "BKE_idprop.h" #include "BKE_material.h" #include "BKE_main.h" // for Main #include "BKE_mesh.h" // for ME_ defines (patching) @@ -153,7 +154,11 @@ #include "IMB_imbuf.h" // for proxy / timecode versioning stuff +#include "NOD_common.h" #include "NOD_socket.h" +#include "NOD_composite.h" +#include "NOD_shader.h" +#include "NOD_texture.h" #include "BLO_readfile.h" #include "BLO_undofile.h" @@ -1316,10 +1321,12 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain) oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0); } for (; sce; sce = sce->id.next) { - if (sce->nodetree) { - bNode *node; - for (node = sce->nodetree->nodes.first; node; node = node->next) - oldnewmap_insert(fd->imamap, node->preview, node->preview, 0); + if (sce->nodetree && sce->nodetree->previews) { + bNodeInstanceHashIterator iter; + NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) { + bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + oldnewmap_insert(fd->imamap, preview, preview, 0); + } } } } @@ -1358,10 +1365,23 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain) ima->gputexture = newimaadr(fd, ima->gputexture); } for (; sce; sce = sce->id.next) { - if (sce->nodetree) { - bNode *node; - for (node = sce->nodetree->nodes.first; node; node = node->next) - node->preview = newimaadr(fd, node->preview); + if (sce->nodetree && sce->nodetree->previews) { + bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews"); + bNodeInstanceHashIterator iter; + + /* reconstruct the preview hash, only using remaining pointers */ + NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) { + bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + if (preview) { + bNodePreview *new_preview = newimaadr(fd, preview); + if (new_preview) { + bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); + BKE_node_instance_hash_insert(new_previews, key, new_preview); + } + } + } + BKE_node_instance_hash_free(sce->nodetree->previews, NULL); + sce->nodetree->previews = new_previews; } } } @@ -1384,7 +1404,7 @@ void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain) for (; sce; sce = sce->id.next) { if (sce->nodetree) { bNode *node; - for (node = sce->nodetree->nodes.first; node; node= node->next) + for (node = sce->nodetree->nodes.first; node; node = node->next) if (node->type == CMP_NODE_MOVIEDISTORTION) oldnewmap_insert(fd->movieclipmap, node->storage, node->storage, 0); } @@ -2289,17 +2309,42 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath) /* ************ READ NODE TREE *************** */ +static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock) +{ + /* Link ID Properties -- and copy this comment EXACTLY for easy finding + * of library blocks that implement this.*/ + if (sock->prop) + IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); +} + /* singe node tree (also used for material/scene trees), ntree is not NULL */ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) { bNode *node; + bNodeSocket *sock; if (ntree->adt) lib_link_animdata(fd, &ntree->id, ntree->adt); ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd); - for (node = ntree->nodes.first; node; node = node->next) - node->id = newlibadr_us(fd, id->lib, node->id); + for (node = ntree->nodes.first; node; node = node->next) { + /* Link ID Properties -- and copy this comment EXACTLY for easy finding + * of library blocks that implement this.*/ + if (node->prop) + IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + + node->id= newlibadr_us(fd, id->lib, node->id); + + for (sock = node->inputs.first; sock; sock = sock->next) + lib_link_node_socket(fd, id, sock); + for (sock = node->outputs.first; sock; sock = sock->next) + lib_link_node_socket(fd, id, sock); + } + + for (sock = ntree->inputs.first; sock; sock = sock->next) + lib_link_node_socket(fd, id, sock); + for (sock = ntree->outputs.first; sock; sock = sock->next) + lib_link_node_socket(fd, id, sock); } /* library ntree linking after fileread */ @@ -2316,131 +2361,49 @@ static void lib_link_nodetree(FileData *fd, Main *main) } } -static void do_versions_socket_default_value(bNodeSocket *sock) -{ - bNodeSocketValueFloat *valfloat; - bNodeSocketValueVector *valvector; - bNodeSocketValueRGBA *valrgba; - - if (sock->default_value) - return; - - switch (sock->type) { - case SOCK_FLOAT: - valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value"); - valfloat->value = sock->ns.vec[0]; - valfloat->min = sock->ns.min; - valfloat->max = sock->ns.max; - valfloat->subtype = PROP_NONE; - break; - case SOCK_VECTOR: - valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value"); - copy_v3_v3(valvector->value, sock->ns.vec); - valvector->min = sock->ns.min; - valvector->max = sock->ns.max; - valvector->subtype = PROP_NONE; - break; - case SOCK_RGBA: - valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value"); - copy_v4_v4(valrgba->value, sock->ns.vec); - break; - } -} - -void blo_do_versions_nodetree_default_value(bNodeTree *ntree) -{ - bNode *node; - bNodeSocket *sock; - for (node=ntree->nodes.first; node; node=node->next) { - for (sock=node->inputs.first; sock; sock=sock->next) - do_versions_socket_default_value(sock); - for (sock=node->outputs.first; sock; sock=sock->next) - do_versions_socket_default_value(sock); - } - for (sock=ntree->inputs.first; sock; sock=sock->next) - do_versions_socket_default_value(sock); - for (sock=ntree->outputs.first; sock; sock=sock->next) - do_versions_socket_default_value(sock); -} - -static void lib_nodetree_init_types_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - ntreeInitTypes(ntree); - - /* need to do this here instead of in do_versions, otherwise next function can crash */ - blo_do_versions_nodetree_default_value(ntree); - - /* XXX could be replaced by do_versions for new nodes */ - for (node=ntree->nodes.first; node; node=node->next) - node_verify_socket_templates(ntree, node); -} - -/* updates group node socket own_index so that +/* updates group node socket identifier so that * external links to/from the group node are preserved. */ static void lib_node_do_versions_group_indices(bNode *gnode) { bNodeTree *ngroup = (bNodeTree*)gnode->id; - bNode *intnode; - bNodeSocket *sock, *gsock, *intsock; - int found; + bNodeSocket *sock; + bNodeLink *link; - for (sock=gnode->outputs.first; sock; sock=sock->next) { + for (sock=gnode->outputs.first; sock; sock = sock->next) { int old_index = sock->to_index; - for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) { - if (gsock->link && gsock->link->fromsock->own_index == old_index) { - sock->own_index = gsock->own_index; - break; + + for (link = ngroup->links.first; link; link = link->next) { + if (link->tonode->type == NODE_GROUP_OUTPUT && link->fromsock->own_index == old_index) { + strcpy(sock->identifier, link->fromsock->identifier); + /* deprecated */ + sock->own_index = link->fromsock->own_index; + sock->to_index = 0; + sock->groupsock = NULL; } } } - for (sock=gnode->inputs.first; sock; sock=sock->next) { + for (sock=gnode->inputs.first; sock; sock = sock->next) { int old_index = sock->to_index; - /* can't use break in double loop */ - found = 0; - for (intnode=ngroup->nodes.first; intnode && !found; intnode=intnode->next) { - for (intsock=intnode->inputs.first; intsock; intsock=intsock->next) { - if (intsock->own_index == old_index && intsock->link) { - sock->own_index = intsock->link->fromsock->own_index; - found = 1; - break; - } + + for (link = ngroup->links.first; link; link = link->next) { + if (link->fromnode->type == NODE_GROUP_INPUT && link->tosock->own_index == old_index) { + strcpy(sock->identifier, link->tosock->identifier); + /* deprecated */ + sock->own_index = link->tosock->own_index; + sock->to_index = 0; + sock->groupsock = NULL; } } } } -/* updates external links for all group nodes in a tree */ -static void lib_nodetree_do_versions_group_indices_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == NODE_GROUP) { - bNodeTree *ngroup = (bNodeTree*)node->id; - if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE)) - lib_node_do_versions_group_indices(node); - } - } -} - -/* make an update call for the tree */ -static void lib_nodetree_do_versions_update_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - if (ntree->update) - ntreeUpdateTree(ntree); -} - /* verify types for nodes and groups, all data has to be read */ /* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic * typedefs */ static void lib_verify_nodetree(Main *main, int UNUSED(open)) { bNodeTree *ntree; - int i; - bNodeTreeType *ntreetype; /* this crashes blender on undo/redo */ #if 0 @@ -2450,41 +2413,138 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) #endif /* set node->typeinfo pointers */ - for (i = 0; i < NUM_NTREE_TYPES; ++i) { - ntreetype = ntreeGetType(i); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, lib_nodetree_init_types_cb); - } - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) - lib_nodetree_init_types_cb(NULL, NULL, ntree); + FOREACH_NODETREE(main, ntree, id) { + ntreeSetTypes(NULL, ntree); + } FOREACH_NODETREE_END + + /* verify static socket templates */ + FOREACH_NODETREE(main, ntree, id) { + bNode *node; + for (node=ntree->nodes.first; node; node=node->next) + node_verify_socket_templates(ntree, node); + } FOREACH_NODETREE_END { int has_old_groups = 0; /* XXX this should actually be part of do_versions, but since we need * finished library linking, it is not possible there. Instead in do_versions - * we have set the NTREE_DO_VERSIONS flag, so at this point we can do the + * we have set the NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 flag, so at this point we can do the * actual group node updates. */ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { - if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE) { - /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */ - node_group_expose_all_sockets(ntree); + if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2) has_old_groups = 1; - } } if (has_old_groups) { - for (i = 0; i < NUM_NTREE_TYPES; ++i) { - ntreetype = ntreeGetType(i); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_group_indices_cb); - } + FOREACH_NODETREE(main, ntree, id) { + /* updates external links for all group nodes in a tree */ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP) { + bNodeTree *ngroup = (bNodeTree*)node->id; + if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2)) + lib_node_do_versions_group_indices(node); + } + } + } FOREACH_NODETREE_END } for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) - ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE; + ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2; } + + { + /* Convert the previously used ntree->inputs/ntree->outputs lists to interface nodes. + * Pre 2.56.2 node trees automatically have all unlinked sockets exposed already + * (see NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2). + * + * XXX this should actually be part of do_versions, + * but needs valid typeinfo pointers to create interface nodes. + */ + for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { + if (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP) { + bNode *input_node = NULL, *output_node = NULL; + int num_inputs = 0, num_outputs = 0; + bNodeLink *link, *next_link; + /* Only create new interface nodes for actual older files. + * New file versions already have input/output nodes with duplicate links, + * in that case just remove the invalid links. + */ + int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE); + + float input_locx = 1000000.0f, input_locy = 0.0f; + float output_locx = -1000000.0f, output_locy = 0.0f; + /* rough guess, not nice but we don't have access to UI constants here ... */ + static const float offsetx = 42 + 3*20 + 20; + /*static const float offsety = 0.0f;*/ + + if (create_io_nodes) { + if (ntree->inputs.first) + input_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_INPUT); + + if (ntree->outputs.first) + output_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_OUTPUT); + } + + /* Redirect links from/to the node tree interface to input/output node. + * If the fromnode/tonode pointers are NULL, this means a link from/to + * the ntree interface sockets, which need to be redirected to new interface nodes. + */ + for (link = ntree->links.first; link; link = next_link) { + int free_link = FALSE; + next_link = link->next; + + if (link->fromnode == NULL) { + if (input_node) { + link->fromnode = input_node; + link->fromsock = node_group_input_find_socket(input_node, link->fromsock->identifier); + ++num_inputs; + + if (input_locx > link->tonode->locx - offsetx) + input_locx = link->tonode->locx - offsetx; + input_locy += link->tonode->locy; + } + else + free_link = TRUE; + } + + if (link->tonode == NULL) { + if (output_node) { + link->tonode = output_node; + link->tosock = node_group_output_find_socket(output_node, link->tosock->identifier); + ++num_outputs; + + if (output_locx < link->fromnode->locx + offsetx) + output_locx = link->fromnode->locx + offsetx; + output_locy += link->fromnode->locy; + } + else + free_link = TRUE; + } + + if (free_link) + nodeRemLink(ntree, link); + } + + if (num_inputs > 0) { + input_locy /= num_inputs; + input_node->locx = input_locx; + input_node->locy = input_locy; + } + if (num_outputs > 0) { + output_locy /= num_outputs; + output_node->locx = output_locx; + output_node->locy = output_locy; + } + + /* clear do_versions flags */ + ntree->flag &= ~(NTREE_DO_VERSIONS_CUSTOMNODES_GROUP | NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE); + } + } + } + /* verify all group user nodes */ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { ntreeVerifyNodes(main, &ntree->id); @@ -2492,21 +2552,22 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) /* make update calls where necessary */ { - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) + FOREACH_NODETREE(main, ntree, id) { + /* make an update call for the tree */ if (ntree->update) ntreeUpdateTree(ntree); - - for (i = 0; i < NUM_NTREE_TYPES; i++) { - ntreetype = ntreeGetType(i); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_update_cb); - } + } FOREACH_NODETREE_END } } static void direct_link_node_socket(FileData *fd, bNodeSocket *sock) { + sock->prop = newdataadr(fd, sock->prop); + if (sock->prop) + IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + sock->link = newdataadr(fd, sock->link); + sock->typeinfo = NULL; sock->storage = newdataadr(fd, sock->storage); sock->default_value = newdataadr(fd, sock->default_value); sock->cache = NULL; @@ -2521,6 +2582,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) bNodeLink *link; ntree->init = 0; /* to set callbacks and force setting types */ + ntree->is_updating = FALSE; + ntree->typeinfo= NULL; + ntree->interface_type = NULL; + ntree->progress = NULL; ntree->execdata = NULL; @@ -2536,6 +2601,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) link_list(fd, &node->inputs); link_list(fd, &node->outputs); + node->prop = newdataadr(fd, node->prop); + if (node->prop) + IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + link_list(fd, &node->internal_links); for (link = node->internal_links.first; link; link = link->next) { link->fromnode = newdataadr(fd, link->fromnode); @@ -2547,8 +2616,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) if (node->type == CMP_NODE_MOVIEDISTORTION) { node->storage = newmclipadr(fd, node->storage); } - else + else { node->storage = newdataadr(fd, node->storage); + } if (node->storage) { /* could be handlerized at some point */ @@ -2559,9 +2629,6 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) else if (node->type==SH_NODE_SCRIPT) { NodeShaderScript *nss = (NodeShaderScript *) node->storage; nss->bytecode = newdataadr(fd, nss->bytecode); - nss->prop = newdataadr(fd, nss->prop); - if (nss->prop) - IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } } else if (ntree->type==NTREE_COMPOSIT) { @@ -2580,14 +2647,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) } link_list(fd, &ntree->links); - /* external sockets */ - link_list(fd, &ntree->inputs); - link_list(fd, &ntree->outputs); - /* and we connect the rest */ for (node = ntree->nodes.first; node; node = node->next) { node->parent = newdataadr(fd, node->parent); - node->preview = newimaadr(fd, node->preview); node->lasty = 0; for (sock = node->inputs.first; sock; sock = sock->next) @@ -2595,6 +2657,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) for (sock = node->outputs.first; sock; sock = sock->next) direct_link_node_socket(fd, sock); } + + /* interface socket lists */ + link_list(fd, &ntree->inputs); + link_list(fd, &ntree->outputs); for (sock = ntree->inputs.first; sock; sock = sock->next) direct_link_node_socket(fd, sock); for (sock = ntree->outputs.first; sock; sock = sock->next) @@ -2607,6 +2673,29 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) link->tosock = newdataadr(fd, link->tosock); } +#if 0 + if (ntree->previews) { + bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews"); + bNodeInstanceHashIterator iter; + + NODE_INSTANCE_HASH_ITER(iter, ntree->previews) { + bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + if (preview) { + bNodePreview *new_preview = newimaadr(fd, preview); + if (new_preview) { + bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); + BKE_node_instance_hash_insert(new_previews, key, new_preview); + } + } + } + BKE_node_instance_hash_free(ntree->previews, NULL); + ntree->previews = new_previews; + } +#else + /* XXX TODO */ + ntree->previews = NULL; +#endif + /* type verification is in lib-link */ } @@ -4159,9 +4248,9 @@ static void lib_link_object(FileData *fd, Main *main) ob->proxy = NULL; if (ob->id.lib) - printf("Proxy lost from object %s lib %s\n", ob->id.name+2, ob->id.lib->name); + printf("Proxy lost from object %s lib %s\n", ob->id.name + 2, ob->id.lib->name); else - printf("Proxy lost from object %s lib <NONE>\n", ob->id.name+2); + printf("Proxy lost from object %s lib <NONE>\n", ob->id.name + 2); } else { /* this triggers object_update to always use a copy */ @@ -4175,9 +4264,9 @@ static void lib_link_object(FileData *fd, Main *main) if (ob->data==NULL && poin!=NULL) { if (ob->id.lib) - printf("Can't find obdata of %s lib %s\n", ob->id.name+2, ob->id.lib->name); + printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name); else - printf("Object %s lost data.\n", ob->id.name+2); + printf("Object %s lost data.\n", ob->id.name + 2); ob->type = OB_EMPTY; warn = 1; @@ -4898,7 +4987,7 @@ static void composite_patch(bNodeTree *ntree, Scene *scene) { bNode *node; - for (node= ntree->nodes.first; node; node= node->next) { + for (node = ntree->nodes.first; node; node = node->next) { if (node->id==NULL && ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) node->id = &scene->id; } @@ -5569,28 +5658,34 @@ static void lib_link_screen(FileData *fd, Main *main) } else if (sl->spacetype == SPACE_NODE) { SpaceNode *snode = (SpaceNode *)sl; + bNodeTreePath *path, *path_next; - snode->id = newlibadr(fd, sc->id.lib, snode->id); + for (path=snode->treepath.first; path; path=path->next) { + path->nodetree = newlibadr(fd, sc->id.lib, path->nodetree); + + if (!path->nodetree) + break; + } - if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) { - /* internal data, a bit patchy */ - snode->nodetree = NULL; - if (snode->id) { - if (GS(snode->id->name)==ID_MA) - snode->nodetree = ((Material *)snode->id)->nodetree; - else if (GS(snode->id->name)==ID_WO) - snode->nodetree = ((World *)snode->id)->nodetree; - else if (GS(snode->id->name)==ID_LA) - snode->nodetree = ((Lamp *)snode->id)->nodetree; - else if (GS(snode->id->name)==ID_SCE) - snode->nodetree = ((Scene *)snode->id)->nodetree; - else if (GS(snode->id->name)==ID_TE) - snode->nodetree = ((Tex *)snode->id)->nodetree; - } + /* remaining path entries are invalid, remove */ + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); } - else { - snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree); + + snode->nodetree = newlibadr(fd, sc->id.lib, snode->nodetree); + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = snode->treepath.last; + snode->edittree = path->nodetree; } + else + snode->edittree = NULL; + snode->id = newlibadr(fd, sc->id.lib, snode->id); + snode->from = newlibadr(fd, sc->id.lib, snode->from); } else if (sl->spacetype == SPACE_CLIP) { SpaceClip *sclip = (SpaceClip *)sl; @@ -5610,6 +5705,24 @@ static void lib_link_screen(FileData *fd, Main *main) } } +static bool restore_pointer(ID *id, ID *newid, int user) +{ + if (strcmp(newid->name + 2, id->name + 2) == 0) { + if (newid->lib == id->lib) { + if (user == 1) { + if (newid->us == 0) { + newid->us++; + } + } + else if (user == 2) { + id_us_ensure_real(newid); + } + return true; + } + } + return false; +} + /** * Only for undo files, or to restore a screen after reading without UI... * @@ -5621,30 +5734,33 @@ static void lib_link_screen(FileData *fd, Main *main) static void *restore_pointer_by_name(Main *mainp, ID *id, int user) { if (id) { - ListBase *lb = which_libbase(mainp, GS(id->name)); - - if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops) - ID *idn = lb->first; - char *name = id->name + 2; - - for (; idn; idn = idn->next) { - if (idn->name[2] == name[0] && strcmp(idn->name+2, name) == 0) { - if (idn->lib == id->lib) { - if (user == 1) { - if (idn->us == 0) { - idn->us++; - } - } - else if (user == 2) { - id_us_ensure_real(idn); - } - break; - } + /* node trees can be stored locally in other IDs, needs special handling ... */ + if (GS(id->name) == ID_NT) { + ID *idn = NULL; + + FOREACH_NODETREE(mainp, ntree, owner_id) { + if (restore_pointer(id, &ntree->id, user)) { + idn = &ntree->id; + break; } } + FOREACH_NODETREE_END return idn; } + else { + ListBase *lb = which_libbase(mainp, GS(id->name)); + if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops) + ID *idn = lb->first; + + for (; idn; idn = idn->next) { + if (restore_pointer(id, idn, user)) + break; + } + + return idn; + } + } } return NULL; } @@ -5874,24 +5990,34 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc } else if (sl->spacetype == SPACE_NODE) { SpaceNode *snode= (SpaceNode *)sl; + bNodeTreePath *path, *path_next; - snode->id = restore_pointer_by_name(newmain, snode->id, 1); - snode->edittree = NULL; + for (path=snode->treepath.first; path; path=path->next) { + path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, 0); + + if (!path->nodetree) + break; + } - if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) { - snode->nodetree = NULL; - if (snode->id) { - if (GS(snode->id->name)==ID_MA) - snode->nodetree = ((Material *)snode->id)->nodetree; - else if (GS(snode->id->name)==ID_SCE) - snode->nodetree = ((Scene *)snode->id)->nodetree; - else if (GS(snode->id->name)==ID_TE) - snode->nodetree = ((Tex *)snode->id)->nodetree; - } + /* remaining path entries are invalid, remove */ + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); } - else { - snode->nodetree= restore_pointer_by_name(newmain, &snode->nodetree->id, 1); + + snode->nodetree = restore_pointer_by_name(newmain, (ID*)snode->nodetree, 0); + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = snode->treepath.last; + snode->edittree = path->nodetree; } + else + snode->edittree = NULL; + snode->id = restore_pointer_by_name(newmain, snode->id, 1); + snode->from = restore_pointer_by_name(newmain, snode->from, 0); } else if (sl->spacetype == SPACE_CLIP) { SpaceClip *sclip = (SpaceClip *)sl; @@ -6142,6 +6268,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc) snode->gpd = newdataadr(fd, snode->gpd); direct_link_gpencil(fd, snode->gpd); } + + link_list(fd, &snode->treepath); snode->edittree = NULL; snode->linkdrag.first = snode->linkdrag.last = NULL; } @@ -7064,7 +7192,6 @@ static void link_global(FileData *fd, BlendFileData *bfd) } } -/* deprecated, only keep this for readfile.c */ void convert_tface_mt(FileData *fd, Main *main) { Main *gmain; @@ -7099,22 +7226,6 @@ static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree) } } -static void do_version_ntree_tex_mapping_260(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == SH_NODE_MAPPING) { - TexMapping *tex_mapping; - - tex_mapping= node->storage; - tex_mapping->projx= PROJ_X; - tex_mapping->projy= PROJ_Y; - tex_mapping->projz= PROJ_Z; - } - } -} - static void do_versions_nodetree_convert_angle(bNodeTree *ntree) { bNode *node; @@ -7336,7 +7447,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo nimf->format = sce->r.im_format; /* transfer render format toggle to node format toggle */ - for (sock=node->inputs.first; sock; sock=sock->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { NodeImageMultiFileSocket *simf = sock->storage; simf->use_node_format = simf->use_render_format; } @@ -7390,7 +7501,7 @@ static void do_versions_nodetree_file_output_layers_2_64_5(bNodeTree *ntree) for (node=ntree->nodes.first; node; node=node->next) { if (node->type == CMP_NODE_OUTPUT_FILE) { bNodeSocket *sock; - for (sock=node->inputs.first; sock; sock=sock->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { NodeImageMultiFileSocket *input = sock->storage; /* multilayer names are stored as separate strings now, @@ -7449,151 +7560,6 @@ static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree) } } -static void do_version_ntree_image_user_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) { - NodeTexImage *tex = node->storage; - - tex->iuser.frames= 1; - tex->iuser.sfra= 1; - tex->iuser.fie_ima= 2; - tex->iuser.ok= 1; - } - } -} - -static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_DILATEERODE) { - if (node->storage == NULL) { - NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__); - data->falloff = PROP_SMOOTH; - node->storage = data; - } - } - } -} - -static void do_version_ntree_defocus_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_DEFOCUS) { - NodeDefocus *data = node->storage; - if (data->maxblur == 0.0f) { - data->maxblur = 16.0f; - } - } - } -} - -static void do_version_ntree_mask_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_MASK) { - if (node->storage == NULL) { - NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__); - /* move settings into own struct */ - data->size_x = (int)node->custom3; - data->size_y = (int)node->custom4; - node->custom3 = 0.5f; /* default shutter */ - node->storage = data; - } - } - } -} - -static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_KEYING) { - NodeKeyingData *data = node->storage; - - if (data->despill_balance == 0.0f) { - data->despill_balance = 0.5f; - } - } - } -} - -static void do_version_ntree_tex_coord_from_dupli_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) - if (node->type == SH_NODE_TEX_COORD) - node->flag |= NODE_OPTIONS; -} - -static void do_version_node_cleanup_dynamic_sockets_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - bNodeSocket *sock; - - for (node = ntree->nodes.first; node; node = node->next) { - if (!ELEM(node->type, NODE_GROUP, CMP_NODE_IMAGE)) { - for (sock = node->inputs.first; sock; sock = sock->next) - sock->flag &= ~SOCK_DYNAMIC; - for (sock = node->outputs.first; sock; sock = sock->next) - sock->flag &= ~SOCK_DYNAMIC; - } - } -} - -static void do_version_node_fix_translate_wrapping(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) { - node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data"); - } - } -} - -static void do_version_node_straight_image_alpha_workaround(void *data, ID *UNUSED(id), bNodeTree *ntree) -{ - FileData *fd = (FileData *) data; - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_IMAGE) { - Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id); - - if (image) { - if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT) - node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT; - } - } - } -} - -static void do_version_node_fix_internal_links_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) -{ - bNode *node; - bNodeLink *link, *nextlink; - - for (node = ntree->nodes.first; node; node = node->next) { - for (link = node->internal_links.first; link; link = nextlink) { - nextlink = link->next; - if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) { - BLI_remlink(&node->internal_links, link); - } - } - } -} - static void do_version_logic_264(ListBase *regionbase) { ARegion *ar; @@ -7645,6 +7611,146 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track) } } + +static const char *node_get_static_idname(int type, int treetype) +{ + /* use static type info header to map static int type to identifier string */ + #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ + case ID: return #Category #StructName; + + /* XXX hack, group types share a single static integer identifier, but are registered as separate types */ + if (type == NODE_GROUP) { + switch (treetype) { + case NTREE_COMPOSIT: return "CompositorNodeGroup"; + case NTREE_SHADER: return "ShaderNodeGroup"; + case NTREE_TEXTURE: return "TextureNodeGroup"; + } + } + else { + switch (type) { + #include "NOD_static_types.h" + } + } + return ""; +} + +static const char *node_socket_get_static_idname(bNodeSocket *sock) +{ + switch (sock->type) { + case SOCK_FLOAT: { + bNodeSocketValueFloat *dval = sock->default_value; + return nodeStaticSocketType(SOCK_FLOAT, dval->subtype); + } + case SOCK_INT: { + bNodeSocketValueInt *dval = sock->default_value; + return nodeStaticSocketType(SOCK_INT, dval->subtype); + } + case SOCK_BOOLEAN: { + return nodeStaticSocketType(SOCK_BOOLEAN, PROP_NONE); + } + case SOCK_VECTOR: { + bNodeSocketValueVector *dval = sock->default_value; + return nodeStaticSocketType(SOCK_VECTOR, dval->subtype); + } + case SOCK_RGBA: { + return nodeStaticSocketType(SOCK_RGBA, PROP_NONE); + } + case SOCK_STRING: { + bNodeSocketValueString *dval = sock->default_value; + return nodeStaticSocketType(SOCK_STRING, dval->subtype); + } + case SOCK_SHADER: { + return nodeStaticSocketType(SOCK_SHADER, PROP_NONE); + } + } + return ""; +} + +static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_group)) +{ + /* initialize node tree type idname */ + { + bNode *node; + bNodeSocket *sock; + + ntree->typeinfo = NULL; + + /* tree type idname */ + switch (ntree->type) { + case NTREE_COMPOSIT: + strcpy(ntree->idname, "CompositorNodeTree"); + break; + case NTREE_SHADER: + strcpy(ntree->idname, "ShaderNodeTree"); + break; + case NTREE_TEXTURE: + strcpy(ntree->idname, "TextureNodeTree"); + break; + } + + /* node type idname */ + for (node=ntree->nodes.first; node; node=node->next) { + BLI_strncpy(node->idname, node_get_static_idname(node->type, ntree->type), sizeof(node->idname)); + + /* existing old nodes have been initialized already */ + node->flag |= NODE_INIT; + + /* sockets idname */ + for (sock = node->inputs.first; sock; sock = sock->next) + BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname)); + for (sock = node->outputs.first; sock; sock = sock->next) + BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname)); + } + /* tree sockets idname */ + for (sock = ntree->inputs.first; sock; sock = sock->next) + BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname)); + for (sock = ntree->outputs.first; sock; sock = sock->next) + BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname)); + } + + /* initialize socket in_out values */ + { + bNode *node; + bNodeSocket *sock; + + for (node=ntree->nodes.first; node; node=node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) + sock->in_out = SOCK_IN; + for (sock = node->outputs.first; sock; sock = sock->next) + sock->in_out = SOCK_OUT; + } + for (sock = ntree->inputs.first; sock; sock = sock->next) + sock->in_out = SOCK_IN; + for (sock = ntree->outputs.first; sock; sock = sock->next) + sock->in_out = SOCK_OUT; + } + + /* initialize socket identifier strings */ + { + bNode *node; + bNodeSocket *sock; + + for (node=ntree->nodes.first; node; node=node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { + BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier)); + BLI_uniquename(&node->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier)); + } + for (sock = node->outputs.first; sock; sock = sock->next) { + BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier)); + BLI_uniquename(&node->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier)); + } + } + for (sock = ntree->inputs.first; sock; sock = sock->next) { + BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier)); + BLI_uniquename(&ntree->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier)); + } + for (sock = ntree->outputs.first; sock; sock = sock->next) { + BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier)); + BLI_uniquename(&ntree->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier)); + } + } +} + /* initialize userdef with non-UI dependency stuff */ /* other initializers (such as theme color defaults) go to resources.c */ static void do_versions_userdef(FileData *fd, BlendFileData *bfd) @@ -7660,7 +7766,6 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd) user->image_gpubuffer_limit = 10; } } - static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -7726,10 +7831,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_mapping_260); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_SHADER) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_MAPPING) { + TexMapping *tex_mapping; + + tex_mapping= node->storage; + tex_mapping->projx= PROJ_X; + tex_mapping->projy= PROJ_Y; + tex_mapping->projz= PROJ_Z; + } + } + } + } FOREACH_NODETREE_END } if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) { @@ -8365,16 +8481,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_image_user_264); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_SHADER) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) { + NodeTexImage *tex = node->storage; + + tex->iuser.frames= 1; + tex->iuser.sfra= 1; + tex->iuser.fie_ima= 2; + tex->iuser.ok= 1; + } + } + } + } FOREACH_NODETREE_END } if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) { { Scene *scene; - bNodeTreeType *ntreetype; // composite redesign for (scene=main->scene.first; scene; scene=scene->id.next) { if (scene->nodetree) { @@ -8383,11 +8509,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } - ntreetype = ntreeGetType(NTREE_COMPOSIT); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_defocus_264); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_DEFOCUS) { + NodeDefocus *data = node->storage; + if (data->maxblur == 0.0f) { + data->maxblur = 16.0f; + } + } + } + } + } FOREACH_NODETREE_END } { @@ -8445,19 +8580,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 13)) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_dilateerode_264); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_DILATEERODE) { + if (node->storage == NULL) { + NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__); + data->falloff = PROP_SMOOTH; + node->storage = data; + } + } + } + } + } FOREACH_NODETREE_END } if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) { ParticleSettings *part; - bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_keying_despill_balance); - + + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_KEYING) { + NodeKeyingData *data = node->storage; + + if (data->despill_balance == 0.0f) { + data->despill_balance = 0.5f; + } + } + } + } + } FOREACH_NODETREE_END + /* keep compatibility for dupliobject particle size */ for (part=main->particle.first; part; part=part->id.next) if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) @@ -8466,12 +8622,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_mask_264); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_MASK) { + if (node->storage == NULL) { + NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__); + /* move settings into own struct */ + data->size_x = (int)node->custom3; + data->size_y = (int)node->custom4; + node->custom3 = 0.5f; /* default shutter */ + node->storage = data; + } + } + } + } + } FOREACH_NODETREE_END } - + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) { Scene *scene; @@ -8596,15 +8765,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); - bNodeTree *ntree; - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_coord_from_dupli_264); - - for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) - if (ntree->type==NTREE_SHADER) - do_version_ntree_tex_coord_from_dupli_264(NULL, NULL, ntree); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_SHADER) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) + if (node->type == SH_NODE_TEX_COORD) + node->flag |= NODE_OPTIONS; + } + } FOREACH_NODETREE_END } if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) { @@ -8690,28 +8858,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 4)) { - /* Fix for old node flags: Apparently the SOCK_DYNAMIC flag has been in use for other - * purposes before and then removed and later reused for SOCK_DYNAMIC. This socket should - * only be used by certain node types which don't use template lists, cleaning this up here. - */ - bNodeTreeType *ntreetype; - bNodeTree *ntree; - - ntreetype = ntreeGetType(NTREE_COMPOSIT); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264); - ntreetype = ntreeGetType(NTREE_SHADER); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264); - ntreetype = ntreeGetType(NTREE_TEXTURE); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264); - - for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) - do_version_node_cleanup_dynamic_sockets_264(NULL, NULL, ntree); - } - if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) { /* set a unwrapping margin and ABF by default */ Scene *scene; @@ -8728,22 +8874,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* Fix for bug #32982, internal_links list could get corrupted from r51630 onward. * Simply remove bad internal_links lists to avoid NULL pointers. */ - bNodeTreeType *ntreetype; - bNodeTree *ntree; - - ntreetype = ntreeGetType(NTREE_COMPOSIT); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264); - ntreetype = ntreeGetType(NTREE_SHADER); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264); - ntreetype = ntreeGetType(NTREE_TEXTURE); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264); - - for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) - do_version_node_fix_internal_links_264(NULL, NULL, ntree); - + FOREACH_NODETREE(main, ntree, id) + bNode *node; + bNodeLink *link, *nextlink; + + for (node = ntree->nodes.first; node; node = node->next) { + for (link = node->internal_links.first; link; link = nextlink) { + nextlink = link->next; + if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) { + BLI_remlink(&node->internal_links, link); + } + } + } + FOREACH_NODETREE_END } if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) { @@ -8887,8 +9030,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Scene *scene; Image *image; Tex *tex; - bNodeTreeType *ntreetype; - bNodeTree *ntree; for (scene = main->scene.first; scene; scene = scene->id.next) { Sequence *seq; @@ -8944,12 +9085,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - ntreetype = ntreeGetType(NTREE_COMPOSIT); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, fd, do_version_node_straight_image_alpha_workaround); + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_IMAGE) { + Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id); - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) - do_version_node_straight_image_alpha_workaround(fd, NULL, ntree); + if (image) { + if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT) + node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT; + } + } + } + } + } FOREACH_NODETREE_END } else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) { /* texture use alpha was removed for 2.66 but added back again for 2.66a, @@ -9014,15 +9164,76 @@ static void do_versions(FileData *fd, Library *lib, Main *main) // add storage for compositor translate nodes when not existing if (MAIN_VERSION_OLDER(main, 265, 11)) { - bNodeTreeType *ntreetype; - bNodeTree *ntree; + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) { + node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data"); + } + } + } + } FOREACH_NODETREE_END + } - ntreetype = ntreeGetType(NTREE_COMPOSIT); - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_translate_wrapping); + if (!MAIN_VERSION_ATLEAST(main, 266, 2)) { + FOREACH_NODETREE(main, ntree, id) { + do_versions_nodetree_customnodes(ntree, ((ID *)ntree == id)); + } FOREACH_NODETREE_END + } - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) - do_version_node_fix_translate_wrapping(NULL, NULL, ntree); + if (!MAIN_VERSION_ATLEAST(main, 266, 2)) { + bScreen *sc; + for (sc= main->screen.first; sc; sc= sc->id.next) { + ScrArea *sa; + for (sa= sc->areabase.first; sa; sa= sa->next) { + SpaceLink *sl; + for (sl= sa->spacedata.first; sl; sl= sl->next) { + if (sl->spacetype==SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + + /* reset pointers to force tree path update from context */ + snode->nodetree = NULL; + snode->edittree = NULL; + snode->id = NULL; + snode->from = NULL; + + /* convert deprecated treetype setting to tree_idname */ + switch (snode->treetype) { + case NTREE_COMPOSIT: + strcpy(snode->tree_idname, "CompositorNodeTree"); + break; + case NTREE_SHADER: + strcpy(snode->tree_idname, "ShaderNodeTree"); + break; + case NTREE_TEXTURE: + strcpy(snode->tree_idname, "TextureNodeTree"); + break; + } + } + } + } + } + } + + /* Set flag for delayed do_versions in lib_verify_nodetree. It needs valid typeinfo pointers ... */ + { + bNodeTree *ntree; + for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { + /* XXX This should be kept without version check for now! + * As long as USE_NODE_COMPAT_CUSTOMNODES is active, files will write links + * to tree interface sockets for forward compatibility. These links need to be removed again + * on file load in new versions. + * Once forward compatibility is not required any longer, make a subversion bump + * and only execute this for older versions. + */ + ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP; + + /* Only add interface nodes once. + * In old Blender versions they will be removed automatically due to undefined type */ + if (!MAIN_VERSION_ATLEAST(main, 266, 2)) + ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE; + } } if (main->versionfile < 267) { @@ -10470,7 +10681,7 @@ static void give_base_to_groups(Main *mainvar, Scene *scene) Base *base; /* BKE_object_add(...) messes with the selection */ - Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name+2); + Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); ob->type = OB_EMPTY; ob->lay = scene->lay; @@ -10484,7 +10695,7 @@ static void give_base_to_groups(Main *mainvar, Scene *scene) /* assign the group */ ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; - rename_id(&ob->id, group->id.name+2); + rename_id(&ob->id, group->id.name + 2); copy_v3_v3(ob->loc, scene->cursor); } } @@ -10872,7 +11083,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: %s: '%s' missing from '%s'"), BKE_idcode_to_name(GS(id->name)), - id->name+2, mainptr->curlib->filepath); + id->name + 2, mainptr->curlib->filepath); } change_idid_adr(mainlist, basefd, id, realid); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 46b95434e53..6d5fc056d89 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -152,7 +152,6 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr); struct PartEff *blo_do_version_give_parteff_245(struct Object *ob); void blo_do_version_old_trackto_to_constraints(struct Object *ob); void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions); -void blo_do_versions_nodetree_default_value(struct bNodeTree *ntree); void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *main); void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main); diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 36f3ea3654c..3827a31ae95 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -672,13 +672,90 @@ static void do_version_bone_roll_256(Bone *bone) do_version_bone_roll_256(child); } -static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree) +/* deprecated, only keep this for readfile.c */ +/* XXX Deprecated function to add a socket in ntree->inputs/ntree->outputs list + * (previously called node_group_add_socket). This function has been superseded + * by the implementation of proxy nodes. It is still necessary though + * for do_versions of pre-2.56.2 code (r35033), so later proxy nodes + * can be generated consistently from ntree socket lists. + */ +static bNodeSocket *do_versions_node_group_add_socket_2_56_2(bNodeTree *ngroup, const char *name, int type, int in_out) +{ +// bNodeSocketType *stype = ntreeGetSocketType(type); + bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket"); + + BLI_strncpy(gsock->name, name, sizeof(gsock->name)); + gsock->type = type; + + gsock->next = gsock->prev = NULL; + gsock->new_sock = NULL; + gsock->link = NULL; + /* assign new unique index */ + gsock->own_index = ngroup->cur_index++; + gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1); + +// if (stype->value_structsize > 0) +// gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value"); + + BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock); + + ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT); + + return gsock; +} + +/* Create default_value structs for node sockets from the internal bNodeStack value. + * These structs were used from 2.59.2 on, but are replaced in the subsequent do_versions for custom nodes + * by generic ID property values. This conversion happened _after_ do_versions originally due to messy type initialization + * for node sockets. Now created here intermediately for convenience and to keep do_versions consistent. + * + * Node compatibility code is gross ... + */ +static void do_versions_socket_default_value_259(bNodeSocket *sock) +{ + bNodeSocketValueFloat *valfloat; + bNodeSocketValueVector *valvector; + bNodeSocketValueRGBA *valrgba; + + if (sock->default_value) + return; + + switch (sock->type) { + case SOCK_FLOAT: + valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value"); + valfloat->value = sock->ns.vec[0]; + valfloat->min = sock->ns.min; + valfloat->max = sock->ns.max; + valfloat->subtype = PROP_NONE; + break; + case SOCK_VECTOR: + valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value"); + copy_v3_v3(valvector->value, sock->ns.vec); + valvector->min = sock->ns.min; + valvector->max = sock->ns.max; + valvector->subtype = PROP_NONE; + break; + case SOCK_RGBA: + valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value"); + copy_v4_v4(valrgba->value, sock->ns.vec); + break; + } +} + +static void do_versions_nodetree_default_value_259(bNodeTree *ntree) { + bNode *node; bNodeSocket *sock; + for (node=ntree->nodes.first; node; node=node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) + do_versions_socket_default_value_259(sock); + for (sock = node->outputs.first; sock; sock = sock->next) + do_versions_socket_default_value_259(sock); + } for (sock = ntree->inputs.first; sock; sock = sock->next) - sock->flag |= SOCK_DYNAMIC; + do_versions_socket_default_value_259(sock); for (sock = ntree->outputs.first; sock; sock = sock->next) - sock->flag |= SOCK_DYNAMIC; + do_versions_socket_default_value_259(sock); } void blo_do_versions_250(FileData *fd, Library *lib, Main *main) @@ -2289,16 +2366,79 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) { bNodeTree *ntree; - + bNode *node; + bNodeSocket *sock, *gsock; + bNodeLink *link; + /* node sockets are not exposed automatically any more, * this mimics the old behavior by adding all unlinked sockets to groups. */ - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { - /* XXX Only setting a flag here. Actual adding of group sockets - * is done in lib_verify_nodetree, because at this point the internal - * nodes may not be up-to-date! (missing lib-link) + for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) { + /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */ + + /* first make sure the own_index for new sockets is valid */ + for (node=ntree->nodes.first; node; node=node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) + if (sock->own_index >= ntree->cur_index) + ntree->cur_index = sock->own_index+1; + for (sock = node->outputs.first; sock; sock = sock->next) + if (sock->own_index >= ntree->cur_index) + ntree->cur_index = sock->own_index+1; + } + + /* add ntree->inputs/ntree->outputs sockets for all unlinked sockets in the group tree. */ + for (node=ntree->nodes.first; node; node=node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { + if (!sock->link && !nodeSocketIsHidden(sock)) { + + gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_IN); + + /* initialize the default socket value */ + copy_v4_v4(gsock->ns.vec, sock->ns.vec); + + /* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer, + * have to create these directly here. These links are updated again in subsequent do_version! + */ + link = MEM_callocN(sizeof(bNodeLink), "link"); + BLI_addtail(&ntree->links, link); + link->fromnode = NULL; + link->fromsock = gsock; + link->tonode = node; + link->tosock = sock; + ntree->update |= NTREE_UPDATE_LINKS; + + sock->link = link; + } + } + for (sock = node->outputs.first; sock; sock = sock->next) { + if (nodeCountSocketLinks(ntree, sock)==0 && !nodeSocketIsHidden(sock)) { + gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_OUT); + + /* initialize the default socket value */ + copy_v4_v4(gsock->ns.vec, sock->ns.vec); + + /* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer, + * have to create these directly here. These links are updated again in subsequent do_version! + */ + link = MEM_callocN(sizeof(bNodeLink), "link"); + BLI_addtail(&ntree->links, link); + link->fromnode = node; + link->fromsock = sock; + link->tonode = NULL; + link->tosock = gsock; + ntree->update |= NTREE_UPDATE_LINKS; + + gsock->link = link; + } + } + } + + /* XXX The external group node sockets needs to adjust their own_index to point at + * associated ntree inputs/outputs internal sockets. However, this can only happen + * after lib-linking (needs access to internal node group tree)! + * Setting a temporary flag here, actual do_versions happens in lib_verify_nodetree. */ - ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE; + ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2; } } @@ -2601,39 +2741,29 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) bNodeTree *ntree; for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { - blo_do_versions_nodetree_default_value(ntree); + do_versions_nodetree_default_value_259(ntree); ntree->update |= NTREE_UPDATE; } for (sce = main->scene.first; sce; sce = sce->id.next) if (sce->nodetree) { - blo_do_versions_nodetree_default_value(sce->nodetree); + do_versions_nodetree_default_value_259(sce->nodetree); sce->nodetree->update |= NTREE_UPDATE; } for (mat = main->mat.first; mat; mat = mat->id.next) if (mat->nodetree) { - blo_do_versions_nodetree_default_value(mat->nodetree); + do_versions_nodetree_default_value_259(mat->nodetree); mat->nodetree->update |= NTREE_UPDATE; } for (tex = main->tex.first; tex; tex = tex->id.next) if (tex->nodetree) { - blo_do_versions_nodetree_default_value(tex->nodetree); + do_versions_nodetree_default_value_259(tex->nodetree); tex->nodetree->update |= NTREE_UPDATE; } } - /* add SOCK_DYNAMIC flag to existing group sockets */ - { - bNodeTree *ntree; - /* only need to do this for trees in main, local trees are not used as groups */ - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { - do_versions_nodetree_dynamic_sockets(ntree); - ntree->update |= NTREE_UPDATE; - } - } - { /* Initialize group tree nodetypes. * These are used to distinguish tree types and diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 31410631ce0..c6856d8b71d 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -2306,7 +2306,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) Image *ima; for (ima = main->image.first; ima; ima = ima->id.next) if (strcmp(ima->name, "Compositor") == 0) { - strcpy(ima->id.name+2, "Viewer Node"); + strcpy(ima->id.name + 2, "Viewer Node"); strcpy(ima->name, "Viewer Node"); } } @@ -2495,11 +2495,11 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) ima->gen_x = 256; ima->gen_y = 256; ima->gen_type = 1; - if (0 == strncmp(ima->id.name+2, "Viewer Node", sizeof(ima->id.name) - 2)) { + if (0 == strncmp(ima->id.name + 2, "Viewer Node", sizeof(ima->id.name) - 2)) { ima->source = IMA_SRC_VIEWER; ima->type = IMA_TYPE_COMPOSITE; } - if (0 == strncmp(ima->id.name+2, "Render Result", sizeof(ima->id.name) - 2)) { + if (0 == strncmp(ima->id.name + 2, "Render Result", sizeof(ima->id.name) - 2)) { ima->source = IMA_SRC_VIEWER; ima->type = IMA_TYPE_R_RESULT; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ca97a084780..83899c3c3a0 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -74,6 +74,7 @@ #include <math.h> #include <fcntl.h> +#include <limits.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -154,6 +155,7 @@ #include "BKE_curve.h" #include "BKE_constraint.h" #include "BKE_global.h" // for G +#include "BKE_idprop.h" #include "BKE_library.h" // for set_listbasepointers #include "BKE_main.h" #include "BKE_node.h" @@ -165,6 +167,13 @@ #include "BKE_pointcache.h" #include "BKE_mesh.h" +#ifdef USE_NODE_COMPAT_CUSTOMNODES +#include "NOD_common.h" +#include "NOD_socket.h" /* for sock->default_value data */ +#endif + +#include "RNA_access.h" + #include "BLO_writefile.h" #include "BLO_readfile.h" #include "BLO_undofile.h" @@ -673,46 +682,54 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap) write_curvemapping_curves(wd, cumap); } -static void write_node_socket(WriteData *wd, bNodeSocket *sock) +static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock) { - bNodeSocketType *stype= ntreeGetSocketType(sock->type); - +#ifdef USE_NODE_COMPAT_CUSTOMNODES /* forward compatibility code, so older blenders still open */ sock->stack_type = 1; - if (sock->default_value) { - bNodeSocketValueFloat *valfloat; - bNodeSocketValueVector *valvector; - bNodeSocketValueRGBA *valrgba; - - switch (sock->type) { - case SOCK_FLOAT: - valfloat = sock->default_value; - sock->ns.vec[0] = valfloat->value; - sock->ns.min = valfloat->min; - sock->ns.max = valfloat->max; - break; - case SOCK_VECTOR: - valvector = sock->default_value; - copy_v3_v3(sock->ns.vec, valvector->value); - sock->ns.min = valvector->min; - sock->ns.max = valvector->max; - break; - case SOCK_RGBA: - valrgba = sock->default_value; - copy_v4_v4(sock->ns.vec, valrgba->value); - sock->ns.min = 0.0f; - sock->ns.max = 1.0f; - break; + if (node->type == NODE_GROUP) { + bNodeTree *ngroup = (bNodeTree *)node->id; + if (ngroup) { + /* for node groups: look up the deprecated groupsock pointer */ + sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier); + BLI_assert(sock->groupsock != NULL); + + /* node group sockets now use the generic identifier string to verify group nodes, + * old blender uses the own_index. + */ + sock->own_index = sock->groupsock->own_index; } } +#endif /* actual socket writing */ writestruct(wd, DATA, "bNodeSocket", 1, sock); + + if (sock->prop) + IDP_WriteProperty(sock->prop, wd); + if (sock->default_value) - writestruct(wd, DATA, stype->value_structname, 1, sock->default_value); + writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value); } +static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree), bNodeSocket *sock) +{ +#ifdef USE_NODE_COMPAT_CUSTOMNODES + /* forward compatibility code, so older blenders still open */ + sock->stack_type = 1; + + /* Reconstruct the deprecated default_value structs in socket interface DNA. */ + if (sock->default_value == NULL && sock->typeinfo) { + node_socket_init_default_value(sock); + } +#endif + + /* actual socket writing */ + writestruct(wd, DATA, "bNodeSocket", 1, sock); + if (sock->prop) + IDP_WriteProperty(sock->prop, wd); +} /* this is only direct data, tree itself should have been written */ static void write_nodetree(WriteData *wd, bNodeTree *ntree) { @@ -724,18 +741,19 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree) if (ntree->adt) write_animdata(wd, ntree->adt); - for (node= ntree->nodes.first; node; node= node->next) + for (node = ntree->nodes.first; node; node = node->next) { writestruct(wd, DATA, "bNode", 1, node); - for (node= ntree->nodes.first; node; node= node->next) { + if (node->prop) + IDP_WriteProperty(node->prop, wd); + for (sock= node->inputs.first; sock; sock= sock->next) - write_node_socket(wd, sock); + write_node_socket(wd, ntree, node, sock); for (sock= node->outputs.first; sock; sock= sock->next) - write_node_socket(wd, sock); + write_node_socket(wd, ntree, node, sock); for (link = node->internal_links.first; link; link = link->next) writestruct(wd, DATA, "bNodeLink", 1, link); - if (node->storage) { /* could be handlerized at some point, now only 1 exception still */ if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)) @@ -744,10 +762,6 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree) NodeShaderScript *nss = (NodeShaderScript *)node->storage; if (nss->bytecode) writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode); - /* Write ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ - if (nss->prop) - IDP_WriteProperty(nss->prop, wd); writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage); } else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) @@ -763,12 +777,12 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree) if (node->type==CMP_NODE_OUTPUT_FILE) { /* inputs have own storage data */ - for (sock=node->inputs.first; sock; sock=sock->next) + for (sock = node->inputs.first; sock; sock = sock->next) writestruct(wd, DATA, "NodeImageMultiFileSocket", 1, sock->storage); } if (node->type==CMP_NODE_IMAGE) { /* write extra socket info */ - for (sock=node->outputs.first; sock; sock=sock->next) + for (sock = node->outputs.first; sock; sock = sock->next) writestruct(wd, DATA, "NodeImageLayer", 1, sock->storage); } } @@ -776,11 +790,10 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree) for (link= ntree->links.first; link; link= link->next) writestruct(wd, DATA, "bNodeLink", 1, link); - /* external sockets */ - for (sock= ntree->inputs.first; sock; sock= sock->next) - write_node_socket(wd, sock); - for (sock= ntree->outputs.first; sock; sock= sock->next) - write_node_socket(wd, sock); + for (sock = ntree->inputs.first; sock; sock = sock->next) + write_node_socket_interface(wd, ntree, sock); + for (sock = ntree->outputs.first; sock; sock = sock->next) + write_node_socket_interface(wd, ntree, sock); } static void current_screen_compat(Main *mainvar, bScreen **screen) @@ -2538,7 +2551,12 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceTime", 1, sl); } else if (sl->spacetype==SPACE_NODE) { - writestruct(wd, DATA, "SpaceNode", 1, sl); + SpaceNode *snode = (SpaceNode *)sl; + bNodeTreePath *path; + writestruct(wd, DATA, "SpaceNode", 1, snode); + + for (path=snode->treepath.first; path; path=path->next) + writestruct(wd, DATA, "bNodeTreePath", 1, path); } else if (sl->spacetype==SPACE_LOGIC) { writestruct(wd, DATA, "SpaceLogic", 1, sl); @@ -2790,6 +2808,118 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase) } } +#ifdef USE_NODE_COMPAT_CUSTOMNODES +static void customnodes_add_deprecated_nodetree_data(bNodeTree *ntree) +{ + bNodeLink *link, *last_link = ntree->links.last; + /* Forward compatibility for group nodes: add links to node tree interface sockets. + * These links are invalid by new rules (missing node pointer)! + * They will be removed again in customnodes_free_deprecated_data, + * cannot do this directly lest bNodeLink pointer mapping becomes ambiguous. + * When loading files with such links in a new Blender version + * they will be removed as well. + */ + for (link = ntree->links.first; link; link = link->next) { + bNode *fromnode = link->fromnode, *tonode = link->tonode; + bNodeSocket *fromsock = link->fromsock, *tosock = link->tosock; + + /* check both sides of the link, to handle direct input-to-output links */ + if (fromnode->type == NODE_GROUP_INPUT) { + fromnode = NULL; + fromsock = ntreeFindSocketInterface(ntree, SOCK_IN, fromsock->identifier); + } + /* only the active output node defines links */ + if (tonode->type == NODE_GROUP_OUTPUT && (tonode->flag & NODE_DO_OUTPUT)) { + tonode = NULL; + tosock = ntreeFindSocketInterface(ntree, SOCK_OUT, tosock->identifier); + } + + if (!fromnode || !tonode) { + /* Note: not using nodeAddLink here, it asserts existing node pointers */ + bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "group node link"); + tlink->fromnode = fromnode; + tlink->fromsock = fromsock; + tlink->tonode = tonode; + tlink->tosock= tosock; + tosock->link = tlink; + tlink->flag |= NODE_LINK_VALID; + BLI_addtail(&ntree->links, tlink); + } + + /* don't check newly created compatibility links */ + if (link == last_link) + break; + } +} + +static void customnodes_add_deprecated_data(Main *mainvar) +{ + bNodeTree *ntree; + Scene *scene; + Material *mat; + World *world; + Lamp *lamp; + Tex *tex; + + for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next) + customnodes_add_deprecated_nodetree_data(ntree); + for (scene = mainvar->scene.first; scene; scene = scene->id.next) + if (scene->nodetree) + customnodes_add_deprecated_nodetree_data(scene->nodetree); + for (mat = mainvar->mat.first; mat; mat = mat->id.next) + if (mat->nodetree) + customnodes_add_deprecated_nodetree_data(mat->nodetree); + for (world = mainvar->world.first; world; world = world->id.next) + if (world->nodetree) + customnodes_add_deprecated_nodetree_data(world->nodetree); + for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next) + if (lamp->nodetree) + customnodes_add_deprecated_nodetree_data(lamp->nodetree); + for (tex = mainvar->tex.first; tex; tex = tex->id.next) + if (tex->nodetree) + customnodes_add_deprecated_nodetree_data(tex->nodetree); +} + +static void customnodes_free_deprecated_nodetree_data(bNodeTree *ntree) +{ + bNodeLink *link, *next_link; + + for (link = ntree->links.first; link; link = next_link) { + next_link = link->next; + if (link->fromnode == NULL || link->tonode == NULL) + nodeRemLink(ntree, link); + } +} + +static void customnodes_free_deprecated_data(Main *mainvar) +{ + bNodeTree *ntree; + Scene *scene; + Material *mat; + World *world; + Lamp *lamp; + Tex *tex; + + for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next) + customnodes_free_deprecated_nodetree_data(ntree); + for (scene = mainvar->scene.first; scene; scene = scene->id.next) + if (scene->nodetree) + customnodes_free_deprecated_nodetree_data(scene->nodetree); + for (mat = mainvar->mat.first; mat; mat = mat->id.next) + if (mat->nodetree) + customnodes_free_deprecated_nodetree_data(mat->nodetree); + for (world = mainvar->world.first; world; world = world->id.next) + if (world->nodetree) + customnodes_free_deprecated_nodetree_data(world->nodetree); + for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next) + if (lamp->nodetree) + customnodes_free_deprecated_nodetree_data(lamp->nodetree); + for (tex = mainvar->tex.first; tex; tex = tex->id.next) + if (tex->nodetree) + customnodes_free_deprecated_nodetree_data(tex->nodetree); +} +#endif + static void write_brushes(WriteData *wd, ListBase *idbase) { Brush *brush; @@ -3204,6 +3334,11 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0; #endif +#ifdef USE_NODE_COMPAT_CUSTOMNODES + /* deprecated forward compat data is freed again below */ + customnodes_add_deprecated_data(mainvar); +#endif + sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION); mywrite(wd, buf, 12); @@ -3252,6 +3387,14 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil /* dna as last, because (to be implemented) test for which structs are written */ writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data); +#ifdef USE_NODE_COMPAT_CUSTOMNODES + /* Ugly, forward compatibility code generates deprecated data during writing, + * this has to be freed again. Can not be done directly after writing, otherwise + * the data pointers could be reused and not be mapped correctly. + */ + customnodes_free_deprecated_data(mainvar); +#endif + /* end of file */ memset(&bhead, 0, sizeof(BHead)); bhead.code= ENDB; diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index b8c70871ea1..c3efac55fe7 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -353,7 +353,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) size_t prim_poly_count = mpvc->getFaceCount(); size_t prim_loop_count = 0; - for(int index=0; index < prim_poly_count; index++) { + for (int index=0; index < prim_poly_count; index++) { prim_loop_count += get_vertex_count(mpvc, index); } diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 89f8bb3226b..604e131b44b 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -178,7 +178,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) { GroupObject *go = NULL; Group *gr = ob->dup_group; - /* printf("group detected '%s'\n", gr->id.name+2); */ + /* printf("group detected '%s'\n", gr->id.name + 2); */ for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) { printf("\t%s\n", go->ob->id.name); } diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 66f7feb8928..84b81f4d332 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -143,7 +143,7 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh Mesh *tmpmesh; CustomDataMask mask = CD_MASK_MESH; DerivedMesh *dm = NULL; - if(apply_modifiers) { + if (apply_modifiers) { switch (export_mesh_type) { case BC_MESH_TYPE_VIEW: { dm = mesh_create_derived_view(scene, ob, mask); diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp index e1cc25d028a..6008a889205 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.cpp +++ b/source/blender/compositor/intern/COM_CompositorContext.cpp @@ -29,7 +29,6 @@ CompositorContext::CompositorContext() this->m_rd = NULL; this->m_quality = COM_QUALITY_HIGH; this->m_hasActiveOpenCLDevices = false; - this->m_activegNode = NULL; this->m_fastCalculation = false; this->m_viewSettings = NULL; this->m_displaySettings = NULL; diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h index 840a9e59584..3c7db703bf9 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.h +++ b/source/blender/compositor/intern/COM_CompositorContext.h @@ -64,11 +64,12 @@ private: * @see ExecutionSystem */ bNodeTree *m_bnodetree; - + /** - * @brief activegNode the group node that is currently being edited. + * @brief Preview image hash table + * This field is initialized in ExecutionSystem and must only be read from that point on. */ - bNode *m_activegNode; + bNodeInstanceHash *m_previews; /** * @brief does this system have active opencl devices? @@ -115,19 +116,19 @@ public: const bNodeTree *getbNodeTree() const { return this->m_bnodetree; } /** - * @brief set the active groupnode of the context + * @brief get the scene of the context */ - void setActivegNode(bNode *gnode) { this->m_activegNode = gnode; } + const RenderData *getRenderData() const { return this->m_rd; } /** - * @brief get the active groupnode of the context + * @brief set the preview image hash table */ - const bNode *getActivegNode() const { return this->m_activegNode; } + void setPreviewHash(bNodeInstanceHash *previews) { this->m_previews = previews; } /** - * @brief get the scene of the context + * @brief get the preview image hash table */ - const RenderData *getRenderData() const { return this->m_rd; } + bNodeInstanceHash *getPreviewHash() const { return this->m_previews; } /** * @brief set view settings of color color management diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 9c4a32f20c9..80f5b4fc149 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -124,7 +124,7 @@ Node *Converter::convert(bNode *b_node, bool fast) { - Node *node; + Node *node = NULL; if (b_node->flag & NODE_MUTED) { node = new MuteNode(b_node); @@ -226,6 +226,10 @@ Node *Converter::convert(bNode *b_node, bool fast) case NODE_GROUP: node = new GroupNode(b_node); break; + case NODE_GROUP_INPUT: + case NODE_GROUP_OUTPUT: + /* handled in GroupNode::ungroup */ + break; case CMP_NODE_NORMAL: node = new NormalNode(b_node); break; @@ -399,7 +403,6 @@ Node *Converter::convert(bNode *b_node, bool fast) node = new PixelateNode(b_node); break; default: - node = new MuteNode(b_node); break; } return node; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 2b2af73d0c8..2d87845d254 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -26,7 +26,9 @@ #include "PIL_time.h" #include "BLI_utildefines.h" +extern "C" { #include "BKE_node.h" +} #include "COM_Converter.h" #include "COM_NodeOperation.h" @@ -49,7 +51,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) { this->m_context.setbNodeTree(editingtree); + this->m_context.setPreviewHash(editingtree->previews); this->m_context.setFastCalculation(fastcalculation); +#if 0 /* XXX TODO find a better way to define visible output nodes from all editors */ bNode *gnode; for (gnode = (bNode *)editingtree->nodes.first; gnode; gnode = gnode->next) { if (gnode->type == NODE_GROUP && gnode->typeinfo->group_edit_get(gnode)) { @@ -57,6 +61,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re break; } } +#endif /* initialize the CompositorContext */ if (rendering) { @@ -68,7 +73,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re this->m_context.setRendering(rendering); this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() && (editingtree->flag & NTREE_COM_OPENCL)); - ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NULL); + ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NODE_INSTANCE_KEY_BASE); this->m_context.setRenderData(rd); this->m_context.setViewSettings(viewSettings); diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp index 506bd42ace3..ad396e053f2 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp @@ -26,7 +26,6 @@ #include <stdio.h> #include "PIL_time.h" -#include "BKE_node.h" #include "COM_Converter.h" #include "COM_NodeOperation.h" @@ -39,18 +38,25 @@ #include "COM_ReadBufferOperation.h" #include "COM_ViewerBaseOperation.h" -void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode) +extern "C" { +#include "BKE_node.h" +} + +void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key) { vector<Node *>& nodes = system.getNodes(); vector<SocketConnection *>& links = system.getConnections(); - const bNode *activeGroupNode = system.getContext().getActivegNode(); - bool isActiveGroup = activeGroupNode == groupnode; /* add all nodes of the tree to the node list */ bNode *node = (bNode *)tree->nodes.first; while (node != NULL) { + /* XXX TODO replace isActiveGroup by a more accurate check, all visible editors should do this! */ + bool isActiveGroup = true; Node *nnode = addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation()); - nnode->setbNodeGroup(groupnode); + if (nnode) { + nnode->setbNodeTree(tree); + nnode->setInstanceKey(BKE_node_instance_key(parent_key, tree, node)); + } node = node->next; } @@ -81,8 +87,10 @@ void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node) Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast) { Node *node = Converter::convert(b_node, fast); - node->setIsInActiveGroup(inActiveGroup); - addNode(nodes, node); + if (node) { + node->setIsInActiveGroup(inActiveGroup); + addNode(nodes, node); + } return node; } void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation) @@ -109,43 +117,21 @@ void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *re static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket) { - if (bnode != NULL) { - for (NodeIterator it = node_range.first; it != node_range.second; ++it) { - Node *node = *it; - if (node->getbNode() == bnode) - return node->findInputSocketBybNodeSocket(bsocket); - } - } - else { - for (NodeIterator it = node_range.first; it != node_range.second; ++it) { - Node *node = *it; - if (node->isProxyNode()) { - InputSocket *proxySocket = node->getInputSocket(0); - if (proxySocket->getbNodeSocket() == bsocket) - return proxySocket; - } - } + for (NodeIterator it = node_range.first; it != node_range.second; ++it) { + Node *node = *it; + InputSocket *input = node->findInputSocketBybNodeSocket(bsocket); + if (input) + return input; } return NULL; } static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket) { - if (bnode != NULL) { - for (NodeIterator it = node_range.first; it != node_range.second; ++it) { - Node *node = *it; - if (node->getbNode() == bnode) - return node->findOutputSocketBybNodeSocket(bsocket); - } - } - else { - for (NodeIterator it = node_range.first; it != node_range.second; ++it) { - Node *node = *it; - if (node->isProxyNode()) { - OutputSocket *proxySocket = node->getOutputSocket(0); - if (proxySocket->getbNodeSocket() == bsocket) - return proxySocket; - } - } + for (NodeIterator it = node_range.first; it != node_range.second; ++it) { + Node *node = *it; + OutputSocket *output = node->findOutputSocketBybNodeSocket(bsocket); + if (output) + return output; } return NULL; } @@ -190,7 +176,7 @@ void ExecutionSystemHelper::debugDump(ExecutionSystem *system) tot = system->getNodes().size(); for (int i = 0; i < tot; i++) { node = system->getNodes()[i]; - printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name); + printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name); } tot = system->getOperations().size(); for (int i = 0; i < tot; i++) { diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h index 307e082ea80..e05796b9127 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h +++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h @@ -48,7 +48,7 @@ public: * @param tree bNodeTree to add * @return Node representing the "Compositor node" of the maintree. or NULL when a subtree is added */ - static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode); + static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key); /** * @brief add an editor node to the system. diff --git a/source/blender/compositor/intern/COM_InputSocket.cpp b/source/blender/compositor/intern/COM_InputSocket.cpp index 2493d4e5a27..6868745d631 100644 --- a/source/blender/compositor/intern/COM_InputSocket.cpp +++ b/source/blender/compositor/intern/COM_InputSocket.cpp @@ -157,24 +157,3 @@ NodeOperation *InputSocket::getOperation() const return NULL; } } - -float *InputSocket::getStaticValues() -{ - /* XXX only works for socket types with actual float input values. - * currently all compositor socket types (value, rgba, vector) support this. - */ - bNodeSocket *b_socket = this->getbNodeSocket(); - static float default_null = 0.0f; - - switch (this->getDataType()) { - case COM_DT_VALUE: - return &((bNodeSocketValueFloat *)b_socket->default_value)->value; - case COM_DT_COLOR: - return ((bNodeSocketValueRGBA *)b_socket->default_value)->value; - case COM_DT_VECTOR: - return ((bNodeSocketValueVector *)b_socket->default_value)->value; - default: - /* XXX this should never happen, just added to please the compiler */ - return &default_null; - } -} diff --git a/source/blender/compositor/intern/COM_InputSocket.h b/source/blender/compositor/intern/COM_InputSocket.h index 5cd4cf3beb7..5a36fe3f33b 100644 --- a/source/blender/compositor/intern/COM_InputSocket.h +++ b/source/blender/compositor/intern/COM_InputSocket.h @@ -143,7 +143,6 @@ public: bool isStatic(); - float *getStaticValues(); SocketReader *getReader(); NodeOperation *getOperation() const; }; diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index d49bb5f96fb..f59580acb50 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -67,10 +67,9 @@ Node::Node(bNode *editorNode, bool create_sockets): NodeBase() void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex) { - bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex); + InputSocket *input = getInputSocket(editorNodeInputSocketIndex); SetValueOperation *operation = new SetValueOperation(); - bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)bSock->default_value; - operation->setValue(val->value); + operation->setValue(input->getEditorValueFloat()); this->addLink(graph, operation->getOutputSocket(), inputsocket); graph->addOperation(operation); } @@ -79,11 +78,13 @@ void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *conte { if (this->isInActiveGroup()) { if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes. - if (this->getbNode()->flag & NODE_PREVIEW) { + bNodeInstanceHash *previews = context->getPreviewHash(); + if (previews && (this->getbNode()->flag & NODE_PREVIEW)) { PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings()); system->addOperation(operation); operation->setbNode(this->getbNode()); operation->setbNodeTree(system->getContext().getbNodeTree()); + operation->verifyPreview(previews, this->getInstanceKey()); this->addLink(system, outputSocket, operation->getInputSocket(0)); } } @@ -114,25 +115,27 @@ SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSock void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex) { - bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex); + InputSocket *input = getInputSocket(editorNodeInputSocketIndex); SetColorOperation *operation = new SetColorOperation(); - bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)bSock->default_value; - operation->setChannel1(val->value[0]); - operation->setChannel2(val->value[1]); - operation->setChannel3(val->value[2]); - operation->setChannel4(val->value[3]); + float col[4]; + input->getEditorValueColor(col); + operation->setChannel1(col[0]); + operation->setChannel2(col[1]); + operation->setChannel3(col[2]); + operation->setChannel4(col[3]); this->addLink(graph, operation->getOutputSocket(), inputsocket); graph->addOperation(operation); } void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex) { - bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex); - bNodeSocketValueVector *val = (bNodeSocketValueVector *)bSock->default_value; + InputSocket *input = getInputSocket(editorNodeInputSocketIndex); SetVectorOperation *operation = new SetVectorOperation(); - operation->setX(val->value[0]); - operation->setY(val->value[1]); - operation->setZ(val->value[2]); + float vec[3]; + input->getEditorValueVector(vec); + operation->setX(vec[0]); + operation->setY(vec[1]); + operation->setZ(vec[2]); this->addLink(graph, operation->getOutputSocket(), inputsocket); graph->addOperation(operation); } diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index 5b0381f6443..fb5dfe2e9b7 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -53,12 +53,11 @@ private: * @brief Is this node part of the active group */ bool m_inActiveGroup; - + /** - * @brief The group node this node belongs to. - * @note: used to find the links in the current subtree for muting nodes + * @brief Instance key to identify the node in an instance hash table */ - bNode *m_bNodeGroup; + bNodeInstanceKey m_instanceKey; public: Node(bNode *editorNode, bool create_sockets = true); @@ -145,8 +144,9 @@ public: */ OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket); - inline void setbNodeGroup(bNode *group) {this->m_bNodeGroup = group;} - inline bNode *getbNodeGroup() {return this->m_bNodeGroup;} + void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; } + bNodeInstanceKey getInstanceKey() const { return m_instanceKey; } + protected: void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket); void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket); diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h index e386b5e08a0..41b6ab70bf9 100644 --- a/source/blender/compositor/intern/COM_NodeBase.h +++ b/source/blender/compositor/intern/COM_NodeBase.h @@ -59,6 +59,11 @@ private: */ bNode *m_editorNode; + /** + * @brief stores the reference to the SDNA bNode struct + */ + bNodeTree *m_editorNodeTree; + protected: /** * @brief get access to the vector of input sockets @@ -82,14 +87,25 @@ public: /** * @brief get the reference to the SDNA bNode struct */ - bNode *getbNode() {return m_editorNode;} + bNode *getbNode() const {return m_editorNode;} + + /** + * @brief get the reference to the SDNA bNodeTree struct + */ + bNodeTree *getbNodeTree() const {return m_editorNodeTree;} /** * @brief set the reference to the bNode * @note used in Node instances to receive the storage/settings and complex node for highlight during execution * @param bNode */ - void setbNode(bNode *bNode) {this->m_editorNode = bNode;} + void setbNode(bNode *node) {this->m_editorNode = node;} + + /** + * @brief set the reference to the bNodeTree + * @param bNodeTree + */ + void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;} /** * @brief is this node an operation? diff --git a/source/blender/compositor/intern/COM_Socket.cpp b/source/blender/compositor/intern/COM_Socket.cpp index 30f28f9dddb..3465fa6f56d 100644 --- a/source/blender/compositor/intern/COM_Socket.cpp +++ b/source/blender/compositor/intern/COM_Socket.cpp @@ -24,6 +24,10 @@ #include "COM_Node.h" #include "COM_SocketConnection.h" +extern "C" { +#include "RNA_access.h" +} + Socket::Socket(DataType datatype) { this->m_datatype = datatype; @@ -41,3 +45,24 @@ int Socket::isOutputSocket() const { return false; } const int Socket::isConnected() const { return false; } void Socket::setNode(NodeBase *node) { this->m_node = node; } NodeBase *Socket::getNode() const { return this->m_node; } + +float Socket::getEditorValueFloat() +{ + PointerRNA ptr; + RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr); + return RNA_float_get(&ptr, "default_value"); +} + +void Socket::getEditorValueColor(float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr); + return RNA_float_get_array(&ptr, "default_value", value); +} + +void Socket::getEditorValueVector(float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr); + return RNA_float_get_array(&ptr, "default_value", value); +} diff --git a/source/blender/compositor/intern/COM_Socket.h b/source/blender/compositor/intern/COM_Socket.h index bad112d20c7..6532864a4d9 100644 --- a/source/blender/compositor/intern/COM_Socket.h +++ b/source/blender/compositor/intern/COM_Socket.h @@ -36,6 +36,7 @@ using namespace std; class SocketConnection; class NodeBase; +struct PointerRNA; /** * @brief Base class for InputSocket and OutputSocket. @@ -86,6 +87,10 @@ public: void setEditorSocket(bNodeSocket *editorSocket) { this->m_editorSocket = editorSocket; } bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; } + float getEditorValueFloat(); + void getEditorValueColor(float *value); + void getEditorValueVector(float *value); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:Socket") #endif diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index 49ab9db5dd8..94a27e17b68 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -21,9 +21,9 @@ */ -#include "BKE_node.h" extern "C" { - #include "BLI_threads.h" +#include "BKE_node.h" +#include "BLI_threads.h" } #include "BKE_main.h" #include "BKE_global.h" @@ -63,6 +63,11 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering, return; } + /* Make sure node tree has previews. + * Don't create previews in advance, this is done when adding preview operations. + */ + BKE_node_preview_init_tree(editingtree, COM_PREVIEW_SIZE, COM_PREVIEW_SIZE, FALSE); + /* initialize workscheduler, will check if already done. TODO deinitialize somewhere */ bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL); WorkScheduler::initialize(use_opencl); @@ -85,7 +90,6 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering, } } - ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false, viewSettings, displaySettings); system->execute(); delete system; diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 6a4987c2075..b59a92710bc 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -45,8 +45,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co InputSocket *inputSizeSocket = this->getInputSocket(1); bool connectedSizeSocket = inputSizeSocket->isConnected(); - const bNodeSocket *sock = this->getInputSocket(1)->getbNodeSocket(); - const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value; + const float size = this->getInputSocket(1)->getEditorValueFloat(); CompositorQuality quality = context->getQuality(); NodeOperation *input_operation = NULL, *output_operation = NULL; diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp index 70f20e3235b..5725bc6cb32 100644 --- a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp @@ -60,21 +60,17 @@ void BokehBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContex else { BokehBlurOperation *operation = new BokehBlurOperation(); - const bNodeSocket *sock = this->getInputSocket(2)->getbNodeSocket(); - const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value; - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); this->getInputSocket(2)->relinkConnections(operation->getInputSocket(3), 2, graph); this->getInputSocket(3)->relinkConnections(operation->getInputSocket(2), 3, graph); - //operation->setSize(((bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value); operation->setQuality(context->getQuality()); operation->setbNode(this->getbNode()); graph->addOperation(operation); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); if (!connectedSizeSocket) { - operation->setSize(size); + operation->setSize(this->getInputSocket(2)->getEditorValueFloat()); } } } diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp index 93ff304afd8..103fbf26c7d 100644 --- a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp @@ -50,10 +50,11 @@ void ColorCurveNode::convertToOperations(ExecutionSystem *graph, CompositorConte this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); - bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)this->getInputSocket(2)->getbNodeSocket()->default_value; - operation->setBlackLevel(val->value); - val = (bNodeSocketValueRGBA *)this->getInputSocket(3)->getbNodeSocket()->default_value; - operation->setWhiteLevel(val->value); + float col[4]; + this->getInputSocket(2)->getEditorValueColor(col); + operation->setBlackLevel(col); + this->getInputSocket(3)->getEditorValueColor(col); + operation->setWhiteLevel(col); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); operation->setCurveMapping((CurveMapping *)this->getbNode()->storage); diff --git a/source/blender/compositor/nodes/COM_ColorNode.cpp b/source/blender/compositor/nodes/COM_ColorNode.cpp index 088f8bbb19d..fc2566e5a47 100644 --- a/source/blender/compositor/nodes/COM_ColorNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorNode.cpp @@ -32,9 +32,10 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode) void ColorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { SetColorOperation *operation = new SetColorOperation(); - bNodeSocket *socket = this->getEditorOutputSocket(0); - bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)socket->default_value; - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - operation->setChannels(dval->value); + OutputSocket *output = this->getOutputSocket(0); + output->relinkConnections(operation->getOutputSocket()); + float col[4]; + output->getEditorValueColor(col); + operation->setChannels(col); graph->addOperation(operation); } diff --git a/source/blender/compositor/nodes/COM_GroupNode.cpp b/source/blender/compositor/nodes/COM_GroupNode.cpp index 05c749345d5..09824a7b439 100644 --- a/source/blender/compositor/nodes/COM_GroupNode.cpp +++ b/source/blender/compositor/nodes/COM_GroupNode.cpp @@ -20,6 +20,8 @@ * Monique Dewanchand */ +#include "BKE_node.h" + #include "COM_GroupNode.h" #include "COM_SocketProxyNode.h" #include "COM_SetColorOperation.h" @@ -37,13 +39,38 @@ void GroupNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c } } +static int find_group_input(GroupNode *gnode, const char *identifier, InputSocket **r_sock) +{ + int index; + for (index = 0; index < gnode->getNumberOfInputSockets(); ++index) { + InputSocket *sock = gnode->getInputSocket(index); + if (STREQ(sock->getbNodeSocket()->identifier, identifier)) { + *r_sock = sock; + return index; + } + } + *r_sock = NULL; + return -1; +} + +static int find_group_output(GroupNode *gnode, const char *identifier, OutputSocket **r_sock) +{ + int index; + for (index = 0; index < gnode->getNumberOfOutputSockets(); ++index) { + OutputSocket *sock = gnode->getOutputSocket(index); + if (STREQ(sock->getbNodeSocket()->identifier, identifier)) { + *r_sock = sock; + return index; + } + } + *r_sock = NULL; + return -1; +} + void GroupNode::ungroup(ExecutionSystem &system) { bNode *bnode = this->getbNode(); bNodeTree *subtree = (bNodeTree *)bnode->id; - vector<InputSocket *> &inputsockets = this->getInputSockets(); - vector<OutputSocket *> &outputsockets = this->getOutputSockets(); - unsigned int index; /* get the node list size _before_ adding proxy nodes, so they are available for linking */ int nodes_start = system.getNodes().size(); @@ -54,26 +81,44 @@ void GroupNode::ungroup(ExecutionSystem &system) return; } - for (index = 0; index < inputsockets.size(); index++) { - InputSocket *inputSocket = inputsockets[index]; - bNodeSocket *editorInput = inputSocket->getbNodeSocket(); - if (editorInput->groupsock) { - SocketProxyNode *proxy = new SocketProxyNode(bnode, editorInput, editorInput->groupsock, false); - inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system); - ExecutionSystemHelper::addNode(system.getNodes(), proxy); - } - } - const bool groupnodeBuffering = system.getContext().isGroupnodeBufferEnabled(); - for (index = 0; index < outputsockets.size(); index++) { - OutputSocket *outputSocket = outputsockets[index]; - bNodeSocket *editorOutput = outputSocket->getbNodeSocket(); - if (editorOutput->groupsock) { - SocketProxyNode *proxy = new SocketProxyNode(bnode, editorOutput->groupsock, editorOutput, groupnodeBuffering); - outputSocket->relinkConnections(proxy->getOutputSocket(0)); - ExecutionSystemHelper::addNode(system.getNodes(), proxy); + + /* create proxy nodes for group input/output nodes */ + for (bNode *bionode = (bNode *)subtree->nodes.first; bionode; bionode = bionode->next) { + if (bionode->type == NODE_GROUP_INPUT) { + for (bNodeSocket *bsock = (bNodeSocket *)bionode->outputs.first; bsock; bsock = bsock->next) { + InputSocket *gsock; + int gsock_index = find_group_input(this, bsock->identifier, &gsock); + /* ignore virtual sockets */ + if (gsock) { + SocketProxyNode *proxy = new SocketProxyNode(bionode, gsock->getbNodeSocket(), bsock, false); + ExecutionSystemHelper::addNode(system.getNodes(), proxy); + + gsock->relinkConnectionsDuplicate(proxy->getInputSocket(0), gsock_index, &system); + } + } + } + + if (bionode->type == NODE_GROUP_OUTPUT && (bionode->flag & NODE_DO_OUTPUT)) { + for (bNodeSocket *bsock = (bNodeSocket *)bionode->inputs.first; bsock; bsock = bsock->next) { + OutputSocket *gsock; + find_group_output(this, bsock->identifier, &gsock); + /* ignore virtual sockets */ + if (gsock) { + SocketProxyNode *proxy = new SocketProxyNode(bionode, bsock, gsock->getbNodeSocket(), groupnodeBuffering); + ExecutionSystemHelper::addNode(system.getNodes(), proxy); + + gsock->relinkConnections(proxy->getOutputSocket(0)); + } + } } } - - ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, bnode); + + /* unlink the group node itself, input links have been duplicated */ + for (int index = 0; index < this->getNumberOfInputSockets(); ++index) { + InputSocket *sock = this->getInputSocket(index); + sock->unlinkConnections(&system); + } + + ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, this->getInstanceKey()); } diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp index 94c2fc885fb..f91744d88b6 100644 --- a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp +++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp @@ -51,8 +51,8 @@ void LensDistortionNode::convertToOperations(ExecutionSystem *graph, CompositorC operation->setData(data); if (!(this->getInputSocket(1)->isConnected() || this->getInputSocket(2)->isConnected())) { // no nodes connected to the distortion and dispersion. We can precalculate some values - float distortion = ((const bNodeSocketValueFloat *)this->getInputSocket(1)->getbNodeSocket()->default_value)->value; - float dispersion = ((const bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value; + float distortion = this->getInputSocket(1)->getEditorValueFloat(); + float dispersion = this->getInputSocket(2)->getEditorValueFloat(); operation->setDistortionAndDispersion(distortion, dispersion); } diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp index fbfff8386d0..41b91f61328 100644 --- a/source/blender/compositor/nodes/COM_NormalNode.cpp +++ b/source/blender/compositor/nodes/COM_NormalNode.cpp @@ -36,15 +36,13 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext * InputSocket *inputSocket = this->getInputSocket(0); OutputSocket *outputSocket = this->getOutputSocket(0); OutputSocket *outputSocketDotproduct = this->getOutputSocket(1); - bNode *editorNode = this->getbNode(); SetVectorOperation *operationSet = new SetVectorOperation(); - bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first; - bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value; float normal[3]; + outputSocket->getEditorValueVector(normal); /* animation can break normalization, this restores it */ - normalize_v3_v3(normal, dval->value); + normalize_v3(normal); operationSet->setX(normal[0]); operationSet->setY(normal[1]); diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp index ded6186ad77..c822d2107ec 100644 --- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp +++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp @@ -50,54 +50,54 @@ void SocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorCont { OutputSocket *outputsocket = this->getOutputSocket(0); InputSocket *inputsocket = this->getInputSocket(0); - if (outputsocket->isConnected()) { - if (inputsocket->isConnected()) { - SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType()); - inputsocket->relinkConnections(operation->getInputSocket(0)); - outputsocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - if (m_buffer) { - WriteBufferOperation *writeOperation = new WriteBufferOperation(); - ReadBufferOperation *readOperation = new ReadBufferOperation(); - readOperation->setMemoryProxy(writeOperation->getMemoryProxy()); - - operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket()); - addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0)); - - graph->addOperation(writeOperation); - graph->addOperation(readOperation); - } + if (inputsocket->isConnected()) { + SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType()); + inputsocket->relinkConnections(operation->getInputSocket(0)); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + + if (m_buffer) { + WriteBufferOperation *writeOperation = new WriteBufferOperation(); + ReadBufferOperation *readOperation = new ReadBufferOperation(); + readOperation->setMemoryProxy(writeOperation->getMemoryProxy()); + + operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket()); + addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0)); + + graph->addOperation(writeOperation); + graph->addOperation(readOperation); } - else { - /* If input is not connected, add a constant value operation instead */ - switch (outputsocket->getDataType()) { - case COM_DT_VALUE: - { - SetValueOperation *operation = new SetValueOperation(); - bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)inputsocket->getbNodeSocket()->default_value; - operation->setValue(dval->value); - outputsocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - break; - } - case COM_DT_COLOR: - { - SetColorOperation *operation = new SetColorOperation(); - bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)inputsocket->getbNodeSocket()->default_value; - operation->setChannels(dval->value); - outputsocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - break; - } - case COM_DT_VECTOR: - { - SetVectorOperation *operation = new SetVectorOperation(); - bNodeSocketValueVector *dval = (bNodeSocketValueVector *)inputsocket->getbNodeSocket()->default_value; - operation->setVector(dval->value); - outputsocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - break; - } + } + else if (outputsocket->isConnected()) { + /* If input is not connected, add a constant value operation instead */ + switch (outputsocket->getDataType()) { + case COM_DT_VALUE: + { + SetValueOperation *operation = new SetValueOperation(); + operation->setValue(inputsocket->getEditorValueFloat()); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + break; + } + case COM_DT_COLOR: + { + SetColorOperation *operation = new SetColorOperation(); + float col[4]; + inputsocket->getEditorValueColor(col); + operation->setChannels(col); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + break; + } + case COM_DT_VECTOR: + { + SetVectorOperation *operation = new SetVectorOperation(); + float vec[3]; + inputsocket->getEditorValueVector(vec); + operation->setVector(vec); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + break; } } } diff --git a/source/blender/compositor/nodes/COM_ValueNode.cpp b/source/blender/compositor/nodes/COM_ValueNode.cpp index 593d74952ee..ed4440aa099 100644 --- a/source/blender/compositor/nodes/COM_ValueNode.cpp +++ b/source/blender/compositor/nodes/COM_ValueNode.cpp @@ -32,9 +32,8 @@ ValueNode::ValueNode(bNode *editorNode) : Node(editorNode) void ValueNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { SetValueOperation *operation = new SetValueOperation(); - bNodeSocket *socket = this->getEditorOutputSocket(0); - bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)socket->default_value; - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - operation->setValue(dval->value); + OutputSocket *output = this->getOutputSocket(0); + output->relinkConnections(operation->getOutputSocket()); + operation->setValue(output->getEditorValueFloat()); graph->addOperation(operation); } diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index 6e58b277f66..ba158fb2509 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -36,42 +36,47 @@ extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_colormanagement.h" + #include "BKE_node.h" } PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->m_preview = NULL; this->m_outputBuffer = NULL; this->m_input = NULL; this->m_divider = 1.0f; - this->m_node = NULL; this->m_viewSettings = viewSettings; this->m_displaySettings = displaySettings; } +void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key) +{ + /* Size (0, 0) ensures the preview rect is not allocated in advance, + * this is set later in initExecution once the resolution is determined. + */ + this->m_preview = BKE_node_preview_verify(previews, key, 0, 0, TRUE); +} + void PreviewOperation::initExecution() { this->m_input = getInputSocketReader(0); - if (!this->m_node->preview) { - this->m_node->preview = (bNodePreview *)MEM_callocN(sizeof(bNodePreview), "node preview"); - } - else { - if (this->getWidth() == (unsigned int)this->m_node->preview->xsize && - this->getHeight() == (unsigned int)this->m_node->preview->ysize) - { - this->m_outputBuffer = this->m_node->preview->rect; - } + + if (this->getWidth() == (unsigned int)this->m_preview->xsize && + this->getHeight() == (unsigned int)this->m_preview->ysize) + { + this->m_outputBuffer = this->m_preview->rect; } if (this->m_outputBuffer == NULL) { this->m_outputBuffer = (unsigned char *)MEM_callocN(sizeof(unsigned char) * 4 * getWidth() * getHeight(), "PreviewOperation"); - if (this->m_node->preview->rect) { - MEM_freeN(this->m_node->preview->rect); + if (this->m_preview->rect) { + MEM_freeN(this->m_preview->rect); } - this->m_node->preview->xsize = getWidth(); - this->m_node->preview->ysize = getHeight(); - this->m_node->preview->rect = this->m_outputBuffer; + this->m_preview->xsize = getWidth(); + this->m_preview->ysize = getHeight(); + this->m_preview->rect = this->m_outputBuffer; } } diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h index 0da6b8e4e56..bb60dfa0420 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.h +++ b/source/blender/compositor/operations/COM_PreviewOperation.h @@ -35,7 +35,7 @@ protected: /** * @brief holds reference to the SDNA bNode, where this nodes will render the preview image for */ - bNode *m_node; + bNodePreview *m_preview; SocketReader *m_input; float m_divider; @@ -43,6 +43,8 @@ protected: const ColorManagedDisplaySettings *m_displaySettings; public: PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); + void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key); + bool isOutputOperation(bool rendering) const { return !G.background; } void initExecution(); void deinitExecution(); @@ -50,7 +52,6 @@ public: void executeRegion(rcti *rect, unsigned int tileNumber); void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void setbNode(bNode *node) { this->m_node = node; } bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); bool isPreviewOperation() { return true; } diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 32baa8883e1..448a15334c7 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -39,7 +39,10 @@ struct Tex; struct bContext; struct bNodeTree; struct bNode; +struct bNodeType; +struct bNodeSocketType; struct bNodeTree; +struct bNodeTreeType; struct ScrArea; struct Scene; struct View2D; @@ -51,15 +54,30 @@ typedef enum { NODE_RIGHT = 8 } NodeBorder; +/* space_node.c */ +int ED_node_tree_path_length(struct SpaceNode *snode); +void ED_node_tree_path_get(struct SpaceNode *snode, char *value); +void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length); + +void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from); +void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode); +void ED_node_tree_pop(struct SpaceNode *snode); +int ED_node_tree_depth(struct SpaceNode *snode); +struct bNodeTree *ED_node_tree_get(struct SpaceNode *snode, int level); + /* drawnode.c */ void ED_node_init_butfuncs(void); +void ED_init_custom_node_type(struct bNodeType *ntype); +void ED_init_custom_node_socket_type(struct bNodeSocketType *stype); +void ED_init_standard_node_socket_type(struct bNodeSocketType *stype); +void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype); void ED_node_sample_set(const float col[4]); void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border); /* node_draw.c */ -void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene); -void ED_node_changed_update(struct ID *id, struct bNode *node); -void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); +void ED_node_tree_update(const struct bContext *C); +void ED_node_tag_update_id(struct ID *id); +void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree); void ED_node_sort(struct bNodeTree *ntree); /* node_relationships.c */ @@ -67,9 +85,14 @@ void ED_node_link_intersect_test(struct ScrArea *sa, int test); void ED_node_link_insert(struct ScrArea *sa); /* node_edit.c */ -void ED_node_shader_default(struct Scene *scene, struct ID *id); -void ED_node_composit_default(struct Scene *sce); -void ED_node_texture_default(struct Tex *tex); +void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo); +int ED_node_is_compositor(struct SpaceNode *snode); +int ED_node_is_shader(struct SpaceNode *snode); +int ED_node_is_texture(struct SpaceNode *snode); + +void ED_node_shader_default(const struct bContext *C, struct ID *id); +void ED_node_composit_default(const struct bContext *C, struct Scene *scene); +void ED_node_texture_default(const struct bContext *C, struct Tex *tex); int ED_node_select_check(ListBase *lb); void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree); void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 3c8a9a87fbe..f805b199280 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -259,7 +259,8 @@ typedef enum { WAVEFORM = (49 << 9), VECTORSCOPE = (50 << 9), PROGRESSBAR = (51 << 9), - SEARCH_MENU_UNLINK = (52 << 9) + SEARCH_MENU_UNLINK = (52 << 9), + NODESOCKET = (53 << 9) } eButType; #define BUTTYPE (63 << 9) @@ -835,6 +836,8 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); +void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name); +void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); /* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */ #define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list" diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 2ac66fb1919..fb4e9d2aa6e 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -144,6 +144,7 @@ enum { TH_NODE, TH_NODE_IN_OUT, + TH_NODE_INTERFACE, TH_NODE_OPERATOR, TH_NODE_CONVERTOR, TH_NODE_GROUP, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 81a0f526049..3743539a9bd 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -167,7 +167,7 @@ View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int winx, int winy); void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag); void UI_view2d_constant_grid_draw(struct View2D *v2d); -void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels); +void UI_view2d_multi_grid_draw(struct View2D *v2d, int colorid, float step, int level_size, int totlevels); void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy); void UI_view2d_grid_free(View2DGrid *grid); @@ -200,6 +200,9 @@ struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C); void UI_view2d_getscale(struct View2D *v2d, float *x, float *y); void UI_view2d_getscale_inverse(struct View2D *v2d, float *x, float *y); +void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y); +void UI_view2d_setcenter(struct View2D *v2d, float x, float y); + short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y); /* cached text drawing in v2d, to allow pixel-aligned draw as post process */ diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 5486e12c6bf..7fc5c21f052 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -42,6 +42,7 @@ #include "BLI_utildefines.h" #include "BKE_colortools.h" +#include "BKE_node.h" #include "BKE_texture.h" #include "BKE_tracking.h" @@ -1685,6 +1686,71 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc glDisable(GL_BLEND); } +void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti) +{ + static const float size = 5.0f; + + /* 16 values of sin function */ + static float si[16] = { + 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f, + 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f, + -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f, + -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f + }; + /* 16 values of cos function */ + static float co[16] = { + 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f, + -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f, + -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f, + 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f, + }; + + unsigned char *col = but->col; + int a; + GLint scissor[4]; + rcti scissor_new; + float x, y; + + x = 0.5f * (recti->xmin + recti->xmax); + y = 0.5f * (recti->ymin + recti->ymax); + + /* need scissor test, can draw outside of boundary */ + glGetIntegerv(GL_VIEWPORT, scissor); + scissor_new.xmin = ar->winrct.xmin + recti->xmin; + scissor_new.ymin = ar->winrct.ymin + recti->ymin; + scissor_new.xmax = ar->winrct.xmin + recti->xmax; + scissor_new.ymax = ar->winrct.ymin + recti->ymax; + BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new); + glScissor(scissor_new.xmin, + scissor_new.ymin, + BLI_rcti_size_x(&scissor_new), + BLI_rcti_size_y(&scissor_new)); + + glColor4ubv(col); + + glEnable(GL_BLEND); + glBegin(GL_POLYGON); + for (a = 0; a < 16; a++) + glVertex2f(x + size * si[a], y + size * co[a]); + glEnd(); + glDisable(GL_BLEND); + + glColor4ub(0, 0, 0, 150); + + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + glBegin(GL_LINE_LOOP); + for (a = 0; a < 16; a++) + glVertex2f(x + size * si[a], y + size * co[a]); + glEnd(); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + glLineWidth(1.0f); + + /* restore scissortest */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); +} + /* ****************************************************** */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 39aef38fadb..54a173af603 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5434,6 +5434,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case LISTROW: case BUT_IMAGE: case PROGRESSBAR: + case NODESOCKET: retval = ui_do_but_EXIT(C, but, data, event); break; case HISTOGRAM: diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6065fcfe574..19b863dd6fa 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -510,6 +510,7 @@ void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); +void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); /* interface_handlers.c */ extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index afb44101910..f376d42e7a8 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -32,6 +32,7 @@ #include "MEM_guardedalloc.h" #include "DNA_dynamicpaint_types.h" +#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" @@ -57,6 +58,7 @@ #include "BKE_main.h" #include "BKE_material.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_packedFile.h" #include "BKE_particle.h" @@ -3073,3 +3075,65 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0); } + +/********************************* Component Menu *************************************/ + +typedef struct ComponentMenuArgs { + PointerRNA ptr; + char propname[64]; /* XXX arbitrary */ +} ComponentMenuArgs; +/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */ +static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v) +{ + ComponentMenuArgs *args = (ComponentMenuArgs *)args_v; + uiBlock *block; + uiLayout *layout; + + block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN); + + layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, UI_GetStyle()), 0); + + uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE); + + uiBoundsBlock(block, 6); + uiBlockSetDirection(block, UI_DOWN); + uiEndBlock(C, block); + + return block; +} +void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name) +{ + ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args"); + uiBlock *block; + + args->ptr = *ptr; + BLI_strncpy(args->propname, propname, sizeof(args->propname)); + + block = uiLayoutGetBlock(layout); + uiBlockBeginAlign(block); + + uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, ""); + + uiBlockEndAlign(block); +} + +/************************* Node Socket Icon **************************/ + +void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color) +{ + uiBlock *block; + uiBut *but; + + block = uiLayoutGetBlock(layout); + uiBlockBeginAlign(block); + + /* XXX using explicit socket colors is not quite ideal. + * Eventually it should be possible to use theme colors for this purpose, + * but this requires a better design for extendable color palettes in user prefs. + */ + but = uiDefBut(block, NODESOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + rgba_float_to_uchar(but->col, color); + + uiBlockEndAlign(block); +} diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 78b6d2541fd..f2e553bd140 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -767,7 +767,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) const unsigned char tcol[4] = {wcol->outline[0], wcol->outline[1], wcol->outline[2], - UCHAR_MAX / WIDGET_AA_JITTER}; + wcol->outline[3] / WIDGET_AA_JITTER}; widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip); @@ -1184,7 +1184,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b but->drawstr[selend_tmp] = ch; - glColor3ubv((unsigned char *)wcol->item); + glColor4ubv((unsigned char *)wcol->item); glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2); } } @@ -1224,7 +1224,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } } - glColor3ubv((unsigned char *)wcol->text); + glColor4ubv((unsigned char *)wcol->text); uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, &font_xofs, &font_yofs); @@ -1272,6 +1272,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b /* draws text and icons for buttons */ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect) { + float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; if (but == NULL) @@ -1311,12 +1312,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr); } - widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect); + widget_draw_icon(but, ICON_DOT, dualset ? alpha : 0.25f, rect); } else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) { int tmp = rect->xmin; rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1; - widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect); + widget_draw_icon(but, ICON_LAYER_USED, alpha, rect); rect->xmin = tmp; } @@ -1324,7 +1325,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB * and offset the text label to accommodate it */ if (but->flag & UI_HAS_ICON) { - widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect); + widget_draw_icon(but, but->icon + but->iconadd, alpha, rect); /* icons default draw 0.8f x height */ rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect)); @@ -1342,7 +1343,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB rcti temp = *rect; temp.xmin = temp.xmax - BLI_rcti_size_y(rect); - widget_draw_icon(but, ICON_X, 1.0f, &temp); + widget_draw_icon(but, ICON_X, alpha, &temp); } /* always draw text for textbutton cursor */ @@ -1379,12 +1380,12 @@ static struct uiWidgetStateColors wcol_state_colors = { }; /* uiWidgetColors - * float outline[3]; - * float inner[4]; - * float inner_sel[4]; - * float item[3]; - * float text[3]; - * float text_sel[3]; + * char outline[3]; + * char inner[4]; + * char inner_sel[4]; + * char item[3]; + * char text[3]; + * char text_sel[3]; * * short shaded; * float shadetop, shadedown; @@ -2873,12 +2874,7 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED( round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - - /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects - * over the top to indicate disabled buttons */ - /* XXX, this doesnt work right since the color applies to buttons outside the box too. */ - glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0); - + copy_v3_v3_char(wcol->inner, old_col); } @@ -2941,24 +2937,6 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * } - -static void widget_disabled(const rcti *rect) -{ - float col[4]; - - glEnable(GL_BLEND); - - /* can't use theme TH_BACK or TH_PANEL... undefined */ - glGetFloatv(GL_COLOR_CLEAR_VALUE, col); - glColor4f(col[0], col[1], col[2], 0.5f); - - /* need -1 and +1 to make it work right for aligned buttons, - * but problem may be somewhere else? */ - glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1); - - glDisable(GL_BLEND); -} - static uiWidgetType *widget_type(uiWidgetTypeEnum type) { bTheme *btheme = UI_GetTheme(); @@ -3171,6 +3149,23 @@ static int widget_roundbox_set(uiBut *but, rcti *rect) return roundbox; } +/* put all widget colors on half alpha, use local storage */ +static void ui_widget_color_disabled(uiWidgetType *wt) +{ + static uiWidgetColors wcol_theme_s; + + wcol_theme_s = *wt->wcol_theme; + + wcol_theme_s.outline[3] *= 0.5; + wcol_theme_s.inner[3] *= 0.5; + wcol_theme_s.inner_sel[3] *= 0.5; + wcol_theme_s.item[3] *= 0.5; + wcol_theme_s.text[3] *= 0.5; + wcol_theme_s.text_sel[3] *= 0.5; + + wt->wcol_theme = &wcol_theme_s; +} + /* conversion from old to new buttons, so still messy */ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect) { @@ -3367,30 +3362,47 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect); break; + case NODESOCKET: + ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect); + break; + default: wt = widget_type(UI_WTYPE_REGULAR); } } if (wt) { - rcti disablerect = *rect; /* rect gets clipped smaller for text */ + //rcti disablerect = *rect; /* rect gets clipped smaller for text */ int roundboxalign, state; + bool disabled = FALSE; roundboxalign = widget_roundbox_set(but, rect); state = but->flag; if (but->editstr) state |= UI_TEXTINPUT; + if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) + if (but->dt != UI_EMBOSSP) + disabled = TRUE; + + if (disabled) + ui_widget_color_disabled(wt); + wt->state(wt, state); if (wt->custom) wt->custom(but, &wt->wcol, rect, state, roundboxalign); else if (wt->draw) wt->draw(&wt->wcol, rect, state, roundboxalign); + + if (disabled) + glEnable(GL_BLEND); wt->text(fstyle, &wt->wcol, but, rect); + if (disabled) + glDisable(GL_BLEND); - if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) - if (but->dt != UI_EMBOSSP) - widget_disabled(&disablerect); +// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) +// if (but->dt != UI_EMBOSSP) +// widget_disabled(&disablerect); } } @@ -3474,7 +3486,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10; } - glColor3ubv((unsigned char *)wt->wcol.text); + glColor4ubv((unsigned char *)wt->wcol.text); uiStyleFontDraw(fstyle, rect, name); /* part text right aligned */ @@ -3541,9 +3553,9 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int glDisable(GL_BLEND); if (state == UI_ACTIVE) - glColor3ubv((unsigned char *)wt->wcol.text); + glColor4ubv((unsigned char *)wt->wcol.text); else - glColor3ubv((unsigned char *)wt->wcol.text_sel); + glColor4ubv((unsigned char *)wt->wcol.text_sel); uiStyleFontDraw(fstyle, &trect, name); } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 09122737373..658d89abea3 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -395,6 +395,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->syntaxv; break; case TH_NODE_GROUP: cp = ts->syntaxc; break; + case TH_NODE_INTERFACE: + cp = ts->console_output; break; case TH_NODE_FRAME: cp = ts->movie; break; case TH_NODE_MATTE: @@ -961,7 +963,7 @@ void ui_theme_init_default(void) rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0); rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */ - /* space node, re-uses syntax color storage */ + /* space node, re-uses syntax and console color storage */ btheme->tnode = btheme->tv3d; rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */ rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */ @@ -970,6 +972,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */ rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */ rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */ + rgba_char_args_set(btheme->tnode.console_output, 190, 190, 80, 255); /* group input/output */ btheme->tnode.noodle_curving = 5; /* space logic */ @@ -1545,7 +1548,7 @@ void init_userdef_do_versions(void) rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128); } if (U.coba_weight.tot == 0) - init_colorband(&U.coba_weight, 1); + init_colorband(&U.coba_weight, true); } if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 11)) { bTheme *btheme; @@ -2174,6 +2177,13 @@ void init_userdef_do_versions(void) } } + if (U.versionfile < 266 || (U.versionfile == 266 && U.subversionfile < 2)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */ + } + } + /* NOTE!! from now on use U.versionfile and U.subversionfile */ diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 8a6de9a549b..013b6d3c606 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1368,7 +1368,7 @@ void UI_view2d_constant_grid_draw(View2D *v2d) } /* Draw a multi-level grid in given 2d-region */ -void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totlevels) +void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels) { int offset = -10; float lstep = step; @@ -1378,7 +1378,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl int i; float start; - UI_ThemeColorShade(TH_BACK, offset); + UI_ThemeColorShade(colorid, offset); i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep)); start = i * lstep; @@ -1402,7 +1402,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl } /* X and Y axis */ - UI_ThemeColorShade(TH_BACK, offset - 8); + UI_ThemeColorShade(colorid, offset - 8); glVertex2f(0.0f, v2d->cur.ymin); glVertex2f(0.0f, v2d->cur.ymax); glVertex2f(v2d->cur.xmin, 0.0f); @@ -2075,6 +2075,28 @@ void UI_view2d_getscale_inverse(View2D *v2d, float *x, float *y) if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); } +/* Simple functions for consistent center offset access. + * Used by node editor to shift view center for each individual node tree. + */ +void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y) +{ + /* get center */ + if (x) *x = BLI_rctf_cent_x(&v2d->cur); + if (y) *y = BLI_rctf_cent_y(&v2d->cur); +} +void UI_view2d_setcenter(struct View2D *v2d, float x, float y) +{ + /* get delta from current center */ + float dx = x - BLI_rctf_cent_x(&v2d->cur); + float dy = y - BLI_rctf_cent_y(&v2d->cur); + + /* add to cur */ + BLI_rctf_translate(&v2d->cur, dx, dy); + + /* make sure that 'cur' rect is in a valid state as a result of these changes */ + UI_view2d_curRect_validate(v2d); +} + /* Check if mouse is within scrollers * - Returns appropriate code for match * 'h' = in horizontal scroller diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index dbb0d55a2b1..312cceac77d 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -852,7 +852,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) rename_id(&la->id, get_lamp_defname(type)); if (BKE_scene_use_new_shading_nodes(scene)) { - ED_node_shader_default(scene, &la->id); + ED_node_shader_default(C, &la->id); la->use_nodes = TRUE; } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 8e2a87c7c64..9b61fa44955 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -604,7 +604,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int list = &pchan->constraints; else { //if (G.debug & G_DEBUG) - //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name+2 : "<None>"); + //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name + 2 : "<None>"); return NULL; } } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index dd5b97a68ed..948e272eca0 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -378,8 +378,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre sce->lay = 1 << mat->pr_type; if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { /* two previews, they get copied by wmJob */ - ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey); - ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey); + BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE); + BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE); } } } @@ -442,8 +442,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) { /* two previews, they get copied by wmJob */ - ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey); - ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey); + BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE); + BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE); } } else if (id_type == ID_LA) { @@ -479,8 +479,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) { /* two previews, they get copied by wmJob */ - ntreeInitPreview(origla->nodetree, sp->sizex, sp->sizey); - ntreeInitPreview(la->nodetree, sp->sizex, sp->sizey); + BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE); + BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE); } } else if (id_type == ID_WO) { @@ -497,8 +497,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) { /* two previews, they get copied by wmJob */ - ntreeInitPreview(wrld->nodetree, sp->sizex, sp->sizey); - ntreeInitPreview(origwrld->nodetree, sp->sizex, sp->sizey); + BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE); + BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE); } } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index decc5b131ae..68766591788 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -385,7 +385,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) ma = BKE_material_add(bmain, "Material"); if (BKE_scene_use_new_shading_nodes(scene)) { - ED_node_shader_default(scene, &ma->id); + ED_node_shader_default(C, &ma->id); ma->use_nodes = TRUE; } } @@ -487,7 +487,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) wo = add_world(bmain, "World"); if (BKE_scene_use_new_shading_nodes(scene)) { - ED_node_shader_default(scene, &wo->id); + ED_node_shader_default(C, &wo->id); wo->use_nodes = TRUE; } } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index a467b053443..d29c711cad0 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -377,7 +377,7 @@ static void texture_changed(Main *bmain, Tex *tex) if (scene->use_nodes && scene->nodetree) { for (node = scene->nodetree->nodes.first; node; node = node->next) { if (node->id == &tex->id) - ED_node_changed_update(&scene->id, node); + ED_node_tag_update_id(&scene->id); } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 1906a3259a9..8b69e6e831d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -47,6 +47,7 @@ #include "DNA_meta_types.h" #include "DNA_mesh_types.h" #include "DNA_mask_types.h" +#include "DNA_node_types.h" #include "DNA_userdef_types.h" #include "BKE_context.h" @@ -54,6 +55,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -252,7 +254,7 @@ int ED_operator_node_active(bContext *C) { SpaceNode *snode = CTX_wm_space_node(C); - if (snode && snode->edittree) + if (snode && ntreeIsValid(snode->edittree)) return 1; return 0; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index d94b9372560..92a55151b66 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -407,7 +407,7 @@ void paint_brush_init_tex(Brush *brush) if (brush) { MTex *mtex = &brush->mtex; if (mtex->tex && mtex->tex->nodetree) - ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */ + ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */ } } @@ -416,7 +416,7 @@ void paint_brush_exit_tex(Brush *brush) if (brush) { MTex *mtex = &brush->mtex; if (mtex->tex && mtex->tex->nodetree) - ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1); + ntreeTexEndExecTree(mtex->tex->nodetree->execdata); } } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 156be008a96..51500ab8e1c 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4073,7 +4073,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession /* init mtex nodes */ if (mtex->tex && mtex->tex->nodetree) - ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */ + ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */ /* TODO: Shouldn't really have to do this at the start of every * stroke, but sculpt would need some sort of notification when @@ -4249,7 +4249,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd) MTex *mtex = &brush->mtex; if (mtex->tex && mtex->tex->nodetree) - ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1); + ntreeTexEndExecTree(mtex->tex->nodetree->execdata); } static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke)) diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 1643921e4dd..bb1310d486a 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -113,7 +113,7 @@ static void buttons_texture_users_find_nodetree(ListBase *users, ID *id, { bNode *node; - if (ntree) { + if (ntreeIsValid(ntree)) { for (node = ntree->nodes.first; node; node = node->next) { if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { PointerRNA ptr; diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index fa7e888f8d7..816ad9960df 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -2321,7 +2321,7 @@ void logic_buttons(bContext *C, ARegion *ar) uiItemR(split, &settings_ptr, "show_state_panel", UI_ITEM_R_NO_BG, "", ICON_DISCLOSURE_TRI_RIGHT); row = uiLayoutRow(split, TRUE); - uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers")); + uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers")); RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); uiLayoutSetContextPointer(row, "object", &object_ptr); @@ -2418,7 +2418,7 @@ void logic_buttons(bContext *C, ARegion *ar) if ((ob->scavisflag & OB_VIS_SENS) == 0) continue; row = uiLayoutRow(layout, TRUE); - uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors")); + uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors")); RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); uiLayoutSetContextPointer(row, "object", &object_ptr); @@ -2489,7 +2489,7 @@ void logic_buttons(bContext *C, ARegion *ar) } row = uiLayoutRow(layout, TRUE); - uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators")); + uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators")); RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); uiLayoutSetContextPointer(row, "object", &object_ptr); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 4a14d6ba6fd..0b02aef2fab 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -43,18 +43,23 @@ #include "BKE_image.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_scene.h" #include "BKE_tracking.h" #include "BLF_api.h" #include "BLF_translation.h" +#include "NOD_texture.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BLF_translation.h" #include "MEM_guardedalloc.h" #include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" #include "ED_node.h" @@ -68,189 +73,136 @@ #include "IMB_imbuf_types.h" #include "node_intern.h" /* own include */ +#include "NOD_composite.h" +#include "NOD_shader.h" +#include "NOD_texture.h" -/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */ +/* ****************** MENU FUNCTIONS ***************** */ -static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v) +static void node_add_menu_class(bContext *C, uiLayout *layout, void *arg_nodeclass) { - SpaceNode *snode = snode_v; + Scene *scene = CTX_data_scene(C); + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree; + int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass); + int event, compatibility = 0; - if (snode->treetype == NTREE_SHADER) { - nodeShaderSynchronizeID(node_v, 1); - // allqueue(REDRAWBUTSSHADING, 0); + ntree = snode->nodetree; + + if (!ntree) { + uiItemS(layout); + return; } -} - -static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block, - bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock, - const char *UNUSED(name), int x, int y, int width) -{ - uiDefBut(block, LABEL, 0, IFACE_(sock->name), x, y, width, NODE_DY, NULL, 0, 0, 0, 0, ""); -} -static void node_socket_button_default(const bContext *C, uiBlock *block, - bNodeTree *ntree, bNode *node, bNodeSocket *sock, - const char *name, int x, int y, int width) -{ - if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) - node_socket_button_label(C, block, ntree, node, sock, name, x, y, width); - else { + if (ntree->type == NTREE_SHADER) { + if (BKE_scene_use_new_shading_nodes(scene)) + compatibility = NODE_NEW_SHADING; + else + compatibility = NODE_OLD_SHADING; + } + + if (nodeclass == NODE_CLASS_GROUP) { + Main *bmain = CTX_data_main(C); + bNodeTree *ngroup; + const char *ngroup_type, *node_type; PointerRNA ptr; - uiBut *bt; - - RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); - bt = uiDefButR(block, NUM, B_NODE_EXEC, IFACE_(name), - x, y + 1, width, NODE_DY - 2, - &ptr, "default_value", 0, 0, 0, -1, -1, NULL); - if (node) - uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node); + NODE_TYPES_BEGIN(ntype) + if (ntype->nclass != nodeclass || !ntype->ui_name) + continue; + if (!ntype->poll(ntype, ntree)) + continue; + + switch (ntree->type) { + case NTREE_COMPOSIT: + ngroup_type = "CompositorNodeTree"; + node_type = "CompositorNodeGroup"; + break; + case NTREE_SHADER: + ngroup_type = "ShaderNodeTree"; + node_type = "ShaderNodeGroup"; + break; + case NTREE_TEXTURE: + ngroup_type = "TextureNodeTree"; + node_type = "TextureNodeGroup"; + break; + } + + ptr = uiItemFullO(layout, "NODE_OT_group_make", "New Group", ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_string_set(&ptr, "node_type", node_type); + + uiItemS(layout); + + for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) { + /* only use group trees of the right type */ + if (STRNEQ(ngroup->idname, ngroup_type)) + continue; + if (!nodeGroupPoll(ntree, ngroup)) + continue; + + ptr = uiItemFullO(layout, "NODE_OT_add_group_node", ngroup->id.name + 2, ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_string_set(&ptr, "type", ntype->idname); + RNA_string_set(&ptr, "grouptree", ngroup->id.name + 2); + } + NODE_TYPES_END + } + else if (nodeclass == NODE_DYNAMIC) { + /* disabled */ } -} - -static void node_socket_button_string(const bContext *C, uiBlock *block, - bNodeTree *ntree, bNode *node, bNodeSocket *sock, - const char *name, int x, int y, int width) -{ - if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) - node_socket_button_label(C, block, ntree, node, sock, name, x, y, width); else { PointerRNA ptr; - uiBut *bt; - - SpaceNode *snode = CTX_wm_space_node(C); - const char *ui_name = IFACE_(name); - float slen; - - UI_ThemeColor(TH_TEXT); - slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect; /* XXX, check for dpis */ - while (slen > (width * 0.5f) && *ui_name) { - ui_name = BLI_str_find_next_char_utf8(ui_name, NULL); - slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect; - } - - RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); - - if (name[0] == '\0') - slen = 0.0; - bt = uiDefButR(block, TEX, B_NODE_EXEC, "", - x, y + 1, width - slen, NODE_DY - 2, - &ptr, "default_value", 0, 0, 0, -1, -1, ""); - if (node) - uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node); - - if (slen > 0.0f) - uiDefBut(block, LABEL, 0, IFACE_(name), x + (width - slen), y + 2, slen, NODE_DY - 2, NULL, 0, 0, 0, 0, ""); + NODE_TYPES_BEGIN(ntype) + if (ntype->nclass != nodeclass || !ntype->ui_name) + continue; + if (!ntype->poll(ntype, ntree)) + continue; + if (compatibility && (ntype->compatibility & compatibility) == 0) + continue; + + ptr = uiItemFullO(layout, "NODE_OT_add_node", IFACE_(ntype->ui_name), ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_string_set(&ptr, "type", ntype->idname); + NODE_TYPES_END } } -typedef struct SocketComponentMenuArgs { - PointerRNA ptr; - int x, y, width; - uiButHandleFunc cb; - void *arg1, *arg2; -} SocketComponentMenuArgs; -/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */ -static uiBlock *socket_component_menu(bContext *C, ARegion *ar, void *args_v) +static void node_add_menu_foreach_class_cb(void *calldata, int nclass, const char *name) { - SocketComponentMenuArgs *args = (SocketComponentMenuArgs *)args_v; - uiBlock *block; - uiLayout *layout; - - block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN); - - layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, - args->x, args->y + 2, args->width, NODE_DY, UI_GetStyle()), FALSE); - - uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE); - - return block; + uiLayout *layout = calldata; + uiItemMenuF(layout, IFACE_(name), 0, node_add_menu_class, SET_INT_IN_POINTER(nclass)); } -static void node_socket_button_components(const bContext *C, uiBlock *block, - bNodeTree *ntree, bNode *node, bNodeSocket *sock, - const char *name, int x, int y, int width) + +static void node_add_menu_default(const bContext *C, uiLayout *layout, bNodeTree *ntree) { - if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) - node_socket_button_label(C, block, ntree, node, sock, name, x, y, width); - else { - PointerRNA ptr; - SocketComponentMenuArgs *args; - - RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); - - args = MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs"); - - args->ptr = ptr; - args->x = x; - args->y = y; - args->width = width; - args->cb = node_sync_cb; - args->arg1 = CTX_wm_space_node(C); - args->arg2 = node; - - uiDefBlockButN(block, socket_component_menu, args, IFACE_(name), x, y + 1, width, NODE_DY - 2, ""); - } + Scene *scene = CTX_data_scene(C); + + if (ntree->typeinfo->foreach_nodeclass) + ntree->typeinfo->foreach_nodeclass(scene, layout, node_add_menu_foreach_class_cb); } -static void node_socket_button_color(const bContext *C, uiBlock *block, - bNodeTree *ntree, bNode *node, bNodeSocket *sock, - const char *name, int x, int y, int width) +/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */ + +static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr)) { - if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) - node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width); - else { - PointerRNA ptr; - uiBut *bt; - int labelw = width - 40; - RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); - - bt = uiDefButR(block, COLOR, B_NODE_EXEC, "", - x, y + 2, (labelw > 0 ? 40 : width), NODE_DY - 2, - &ptr, "default_value", -1, 0, 0, -1, -1, NULL); - if (node) - uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node); - - if (name[0] != '\0' && labelw > 0) - uiDefBut(block, LABEL, 0, IFACE_(name), x + 40, y + 2, labelw, NODE_DY - 2, NULL, 0, 0, 0, 0, ""); - } + bNodeSocket *sock = (bNodeSocket *)ptr->data; + uiItemL(layout, sock->name, 0); } -/* standard draw function, display the default input value */ -static void node_draw_input_default(const bContext *C, uiBlock *block, - bNodeTree *ntree, bNode *node, bNodeSocket *sock, - const char *name, int x, int y, int width) +static void node_draw_input_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int linked) { - bNodeSocketType *stype = ntreeGetSocketType(sock->type); - if (stype->buttonfunc) - stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width); + bNodeSocket *sock = (bNodeSocket *)ptr->data; + if (linked || (sock->flag & SOCK_HIDE_VALUE)) + node_socket_button_label(C, layout, ptr, node_ptr); else - node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width); + sock->typeinfo->draw(C, layout, ptr, node_ptr); } -static void node_draw_output_default(const bContext *UNUSED(C), uiBlock *block, - bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock, - const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width)) +static void node_draw_output_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked)) { - const char *ui_name = IFACE_(name); - float slen; - - UI_ThemeColor(TH_TEXT); - slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) ; - while (slen > NODE_WIDTH(node) && *ui_name) { - ui_name = BLI_str_find_next_char_utf8(ui_name, NULL); - slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X); - } - - if (*ui_name) { - uiDefBut(block, LABEL, 0, ui_name, - (int)(sock->locx - slen), (int)(sock->locy - 9.0f), - (short)slen, (short)NODE_DY, - NULL, 0, 0, 0, 0, ""); - } + node_socket_button_label(C, layout, ptr, node_ptr); } + /* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */ #if 0 /* UNUSED */ @@ -297,25 +249,23 @@ static void node_draw_socket_new(bNodeSocket *sock, float size) static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { + bNode *node = ptr->data; + /* first output stores value */ + bNodeSocket *output = node->outputs.first; PointerRNA sockptr; - PropertyRNA *prop; - - /* first socket stores value */ - prop = RNA_struct_find_property(ptr, "outputs"); - RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr); + RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr); uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiLayout *col; + bNode *node = ptr->data; + /* first output stores value */ + bNodeSocket *output = node->outputs.first; PointerRNA sockptr; - PropertyRNA *prop; - - /* first socket stores value */ - prop = RNA_struct_find_property(ptr, "outputs"); - RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr); + uiLayout *col; + RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr); col = uiLayoutColumn(layout, FALSE); uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); @@ -399,14 +349,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; - bNode *node = (bNode *)ptr->data; - bNodeSocket *sock = node->outputs.first; /* first socket stores normal */ + bNode *node = ptr->data; + /* first output stores normal */ + bNodeSocket *output = node->outputs.first; PointerRNA sockptr; - - RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr); + RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr); + uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } + #if 0 /* not used in 2.5x yet */ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v) { @@ -491,427 +442,6 @@ static int node_resize_area_default(bNode *node, int x, int y) /* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */ -/* width of socket columns in group display */ -#define NODE_GROUP_FRAME 120 - -/* based on settings in node, sets drawing rect info. each redraw! */ -/* note: this assumes only 1 group at a time is drawn (linked data) */ -/* in node->totr the entire boundbox for the group is stored */ -static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode) -{ - if (!(gnode->flag & NODE_GROUP_EDIT)) { - node_update_default(C, ntree, gnode); - } - else { - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNode *node; - bNodeSocket *sock, *gsock; - float locx, locy; - rctf *rect = &gnode->totr; - const float dpi_fac = UI_DPI_FAC; - const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; - const float group_header = 26 * dpi_fac; - int counter; - int dy; - - /* get "global" coords */ - node_to_view(gnode, 0.0f, 0.0f, &locx, &locy); - - /* center them, is a bit of abuse of locx and locy though */ - node_update_nodetree(C, ngroup, locx, locy); - - rect->xmin = rect->xmax = locx; - rect->ymin = rect->ymax = locy; - - counter = 1; - for (node = ngroup->nodes.first; node; node = node->next) { - if (counter) { - *rect = node->totr; - counter = 0; - } - else - BLI_rctf_union(rect, &node->totr); - } - - /* add some room for links to group sockets */ - rect->xmin -= 4 * NODE_DY; - rect->xmax += 4 * NODE_DY; - rect->ymin -= NODE_DY; - rect->ymax += NODE_DY; - - /* input sockets */ - dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1)); - gsock = ngroup->inputs.first; - sock = gnode->inputs.first; - while (gsock || sock) { - while (sock && !sock->groupsock) { - sock->locx = rect->xmin - node_group_frame; - sock->locy = dy; - - /* prevent long socket lists from growing out of the group box */ - if (dy - 3 * NODE_DYS < rect->ymin) - rect->ymin = dy - 3 * NODE_DYS; - if (dy + 3 * NODE_DYS > rect->ymax) - rect->ymax = dy + 3 * NODE_DYS; - dy -= 2 * NODE_DY; - - sock = sock->next; - } - while (gsock && (!sock || sock->groupsock != gsock)) { - gsock->locx = rect->xmin; - gsock->locy = dy; - - /* prevent long socket lists from growing out of the group box */ - if (dy - 3 * NODE_DYS < rect->ymin) - rect->ymin = dy - 3 * NODE_DYS; - if (dy + 3 * NODE_DYS > rect->ymax) - rect->ymax = dy + 3 * NODE_DYS; - dy -= 2 * NODE_DY; - - gsock = gsock->next; - } - while (sock && gsock && sock->groupsock == gsock) { - gsock->locx = rect->xmin; - sock->locx = rect->xmin - node_group_frame; - sock->locy = gsock->locy = dy; - - /* prevent long socket lists from growing out of the group box */ - if (dy - 3 * NODE_DYS < rect->ymin) - rect->ymin = dy - 3 * NODE_DYS; - if (dy + 3 * NODE_DYS > rect->ymax) - rect->ymax = dy + 3 * NODE_DYS; - dy -= 2 * NODE_DY; - - sock = sock->next; - gsock = gsock->next; - } - } - - /* output sockets */ - dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1)); - gsock = ngroup->outputs.first; - sock = gnode->outputs.first; - while (gsock || sock) { - while (sock && !sock->groupsock) { - sock->locx = rect->xmax + node_group_frame; - sock->locy = dy - NODE_DYS; - - /* prevent long socket lists from growing out of the group box */ - if (dy - 3 * NODE_DYS < rect->ymin) - rect->ymin = dy - 3 * NODE_DYS; - if (dy + 3 * NODE_DYS > rect->ymax) - rect->ymax = dy + 3 * NODE_DYS; - dy -= 2 * NODE_DY; - - sock = sock->next; - } - while (gsock && (!sock || sock->groupsock != gsock)) { - gsock->locx = rect->xmax; - gsock->locy = dy - NODE_DYS; - - /* prevent long socket lists from growing out of the group box */ - if (dy - 3 * NODE_DYS < rect->ymin) - rect->ymin = dy - 3 * NODE_DYS; - if (dy + 3 * NODE_DYS > rect->ymax) - rect->ymax = dy + 3 * NODE_DYS; - dy -= 2 * NODE_DY; - - gsock = gsock->next; - } - while (sock && gsock && sock->groupsock == gsock) { - gsock->locx = rect->xmax; - sock->locx = rect->xmax + node_group_frame; - sock->locy = gsock->locy = dy - NODE_DYS; - - /* prevent long socket lists from growing out of the group box */ - if (dy - 3 * NODE_DYS < rect->ymin) - rect->ymin = dy - 3 * NODE_DYS; - if (dy + 3 * NODE_DYS > rect->ymax) - rect->ymax = dy + 3 * NODE_DYS; - dy -= 2 * NODE_DY; - - sock = sock->next; - gsock = gsock->next; - } - } - - /* Set the block bounds to clip mouse events from underlying nodes. - * Add margin for header and input/output columns. - */ - uiExplicitBoundsBlock(gnode->block, - rect->xmin - node_group_frame, - rect->ymin, - rect->xmax + node_group_frame, - rect->ymax + group_header); - } -} - -static void update_group_input_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v) -{ - bNodeTree *ngroup = (bNodeTree *)ngroup_v; - - ngroup->update |= NTREE_UPDATE_GROUP_IN; - ntreeUpdateTree(ngroup); -} - -static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v) -{ - bNodeTree *ngroup = (bNodeTree *)ngroup_v; - - ngroup->update |= NTREE_UPDATE_GROUP_OUT; - ntreeUpdateTree(ngroup); -} - -static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock, - int in_out, float xoffset, float yoffset, short width, short height) -{ - if (sock->flag & SOCK_DYNAMIC) { - bNodeTree *ngroup = (bNodeTree *)gnode->id; - uiBut *but; - but = uiDefBut(gnode->block, TEX, 0, "", - sock->locx + xoffset, sock->locy + 1 + yoffset, width, height, - sock->name, 0, sizeof(sock->name), 0, 0, ""); - if (in_out == SOCK_IN) - uiButSetFunc(but, update_group_input_cb, snode, ngroup); - else - uiButSetFunc(but, update_group_output_cb, snode, ngroup); - } - else { - const char *ui_name = IFACE_(sock->name); - uiDefBut(gnode->block, LABEL, 0, ui_name, - sock->locx + xoffset, sock->locy + 1 + yoffset, width, height, - NULL, 0, 0, 0, 0, ""); - } -} - -static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode, - bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out) -{ - const float dpi_fac = UI_DPI_FAC; - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type); - uiBut *bt; - float offset; - int draw_value; - const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; - const float socket_size = NODE_SOCKSIZE; - const float arrowbutw = 0.8f * UI_UNIT_X; - const short co_text_w = 72 * dpi_fac; - const float co_margin = 6.0f * dpi_fac; - /* layout stuff for buttons on group left frame */ - const float colw = 0.6f * node_group_frame; - const float col1 = co_margin - node_group_frame; - const float col2 = col1 + colw + co_margin; - const float col3 = -arrowbutw - co_margin; - /* layout stuff for buttons on group right frame */ - const float cor1 = co_margin; - const float cor2 = cor1 + arrowbutw; - const float cor3 = cor2 + arrowbutw + co_margin; - - /* node and group socket circles */ - if (sock) - node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT); - if (gsock) - node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT); - - /* socket name */ - offset = (in_out == SOCK_IN ? col1 : cor3); - if (!gsock) - offset += (in_out == SOCK_IN ? node_group_frame : -node_group_frame); - - /* draw both name and value button if: - * 1) input: not internal - * 2) output: (node type uses const outputs) and (group output is unlinked) - */ - draw_value = 0; - switch (in_out) { - case SOCK_IN: - draw_value = !(gsock && (gsock->flag & SOCK_INTERNAL)); - break; - case SOCK_OUT: - if (gnode->typeinfo->flag & NODE_CONST_OUTPUT) - draw_value = !(gsock && gsock->link); - break; - } - if (draw_value) { - /* both name and value buttons */ - if (gsock) { - draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY); - if (stype->buttonfunc) - stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "", - gsock->locx + offset, gsock->locy - NODE_DY, colw); - } - else { - draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY); - if (stype->buttonfunc) - stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "", - sock->locx + offset, sock->locy - NODE_DY, colw); - } - } - else { - /* only name, no value button */ - if (gsock) - draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY); - else - draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY); - } - - if (gsock && (gsock->flag & SOCK_DYNAMIC)) { - /* up/down buttons */ - offset = (in_out == SOCK_IN ? col2 : cor2); - uiBlockSetDirection(gnode->block, UI_TOP); - uiBlockBeginAlign(gnode->block); - bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP, - gsock->locx + offset, gsock->locy, arrowbutw, arrowbutw, ""); - if (!gsock->prev || !(gsock->prev->flag & SOCK_DYNAMIC)) - uiButSetFlag(bt, UI_BUT_DISABLED); - RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); - RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out); - bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN, - gsock->locx + offset, gsock->locy - arrowbutw, arrowbutw, arrowbutw, ""); - if (!gsock->next || !(gsock->next->flag & SOCK_DYNAMIC)) - uiButSetFlag(bt, UI_BUT_DISABLED); - RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); - RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out); - uiBlockEndAlign(gnode->block); - uiBlockSetDirection(gnode->block, 0); - - /* remove button */ - offset = (in_out == SOCK_IN ? col3 : cor1); - uiBlockSetEmboss(gnode->block, UI_EMBOSSN); - bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X, - gsock->locx + offset, gsock->locy - 0.5f * arrowbutw, arrowbutw, arrowbutw, ""); - RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); - RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out); - uiBlockSetEmboss(gnode->block, UI_EMBOSS); - } -} - -/* groups are, on creation, centered around 0,0 */ -static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode) -{ - if (!(gnode->flag & NODE_GROUP_EDIT)) { - node_draw_default(C, ar, snode, ntree, gnode); - } - else { - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNodeSocket *sock, *gsock; - uiLayout *layout; - PointerRNA ptr; - rctf rect = gnode->totr; - const float dpi_fac = UI_DPI_FAC; - const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; - const float group_header = 26 * dpi_fac; - - int index; - - /* backdrop header */ - glEnable(GL_BLEND); - uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); - UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70); - uiDrawBox(GL_POLYGON, - rect.xmin - node_group_frame, rect.ymax, - rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD); - - /* backdrop body */ - UI_ThemeColorShadeAlpha(TH_BACK, -8, -70); - uiSetRoundBox(UI_CNR_NONE); - uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD); - - /* input column */ - UI_ThemeColorShadeAlpha(TH_BACK, 10, -50); - uiSetRoundBox(UI_CNR_BOTTOM_LEFT); - uiDrawBox(GL_POLYGON, rect.xmin - node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD); - - /* output column */ - UI_ThemeColorShadeAlpha(TH_BACK, 10, -50); - uiSetRoundBox(UI_CNR_BOTTOM_RIGHT); - uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax + node_group_frame, rect.ymax, BASIS_RAD); - - /* input column separator */ - glColor4ub(200, 200, 200, 140); - glBegin(GL_LINES); - glVertex2f(rect.xmin, rect.ymin); - glVertex2f(rect.xmin, rect.ymax); - glEnd(); - - /* output column separator */ - glColor4ub(200, 200, 200, 140); - glBegin(GL_LINES); - glVertex2f(rect.xmax, rect.ymin); - glVertex2f(rect.xmax, rect.ymax); - glEnd(); - - /* group node outline */ - uiSetRoundBox(UI_CNR_ALL); - glColor4ub(200, 200, 200, 140); - glEnable(GL_LINE_SMOOTH); - uiDrawBox(GL_LINE_LOOP, - rect.xmin - node_group_frame, rect.ymin, - rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); - - /* backdrop title */ - UI_ThemeColor(TH_TEXT_HI); - - layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, - (int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))), - min_ii((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle()); - RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr); - uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL); - uiBlockLayoutResolve(gnode->block, NULL, NULL); - - /* draw the internal tree nodes and links */ - node_draw_nodetree(C, ar, snode, ngroup); - - /* group sockets */ - gsock = ngroup->inputs.first; - sock = gnode->inputs.first; - index = 0; - while (gsock || sock) { - while (sock && !sock->groupsock) { - draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_IN); - sock = sock->next; - } - while (gsock && (!sock || sock->groupsock != gsock)) { - draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_IN); - gsock = gsock->next; - index++; - } - while (sock && gsock && sock->groupsock == gsock) { - draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_IN); - sock = sock->next; - gsock = gsock->next; - index++; - } - } - gsock = ngroup->outputs.first; - sock = gnode->outputs.first; - index = 0; - while (gsock || sock) { - while (sock && !sock->groupsock) { - draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_OUT); - sock = sock->next; - } - while (gsock && (!sock || sock->groupsock != gsock)) { - draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_OUT); - gsock = gsock->next; - index++; - } - while (sock && gsock && sock->groupsock == gsock) { - draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_OUT); - sock = sock->next; - gsock = gsock->next; - index++; - } - } - - uiEndBlock(C, gnode->block); - uiDrawBlock(C, gnode->block); - gnode->block = NULL; - } -} static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) { @@ -1003,7 +533,8 @@ static void node_draw_frame_label(bNode *node, const float aspect) BLF_disable(fontid, BLF_ASPECT); } -static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *UNUSED(ntree), bNode *node) +static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, + bNodeTree *UNUSED(ntree), bNode *node, bNodeInstanceKey UNUSED(key)) { rctf *rct = &node->totr; int color_id = node_get_colorid(node); @@ -1118,7 +649,8 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr node->totr.ymin = locy - size; } -static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node) +static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), + bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) { bNodeSocket *sock; char showname[128]; /* 128 used below */ @@ -1178,7 +710,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( * highlight also if node itself is selected, since we don't display the node body separately! */ for (sock = node->inputs.first; sock; sock = sock->next) { - node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT)); + node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT)); } uiEndBlock(C, node->block); @@ -1205,8 +737,6 @@ static void node_common_set_butfunc(bNodeType *ntype) switch (ntype->type) { case NODE_GROUP: ntype->uifunc = node_uifunc_group; - ntype->drawfunc = node_draw_group; - ntype->drawupdatefunc = node_update_group; break; case NODE_FRAME: ntype->drawfunc = node_draw_frame; @@ -1491,8 +1021,6 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point static void node_shader_set_butfunc(bNodeType *ntype) { switch (ntype->type) { - /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ - case SH_NODE_MATERIAL: case SH_NODE_MATERIAL_EXT: ntype->uifunc = node_shader_buts_material; @@ -2092,20 +1620,17 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po } /* draw function for file output node sockets, displays only sub-path and format, no value button */ -static void node_draw_input_file_output(const bContext *C, uiBlock *block, - bNodeTree *ntree, bNode *node, bNodeSocket *sock, - const char *UNUSED(name), int x, int y, int width) +static void node_draw_input_file_output(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked)) { - uiLayout *layout, *row; - PointerRNA nodeptr, inputptr, imfptr; + bNodeTree *ntree = ptr->id.data; + bNodeSocket *sock = ptr->data; + uiLayout *row; + PointerRNA inputptr, imfptr; int imtype; - int rx, ry; - RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); - layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle()); row = uiLayoutRow(layout, FALSE); - imfptr = RNA_pointer_get(&nodeptr, "format"); + imfptr = RNA_pointer_get(node_ptr, "format"); imtype = RNA_enum_get(&imfptr, "file_format"); if (imtype == R_IMF_IMTYPE_MULTILAYER) { NodeImageMultiFileSocket *input = sock->storage; @@ -2117,6 +1642,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block, NodeImageMultiFileSocket *input = sock->storage; PropertyRNA *imtype_prop; const char *imtype_name; + uiBlock *block; RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr); uiItemL(row, input->path, ICON_NONE); @@ -2127,12 +1653,11 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block, imtype_prop = RNA_struct_find_property(&imfptr, "file_format"); RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name); + block = uiLayoutGetBlock(row); uiBlockSetEmboss(block, UI_EMBOSSP); uiItemL(row, imtype_name, ICON_NONE); uiBlockSetEmboss(block, UI_EMBOSSN); } - - uiBlockLayoutResolve(block, &rx, &ry); } static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { @@ -2781,8 +2306,6 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN static void node_composit_set_butfunc(bNodeType *ntype) { switch (ntype->type) { - /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ - case CMP_NODE_IMAGE: ntype->uifunc = node_composit_buts_image; ntype->uifuncbut = node_composit_buts_image_details; @@ -2998,8 +2521,6 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_TRACKPOS: ntype->uifunc = node_composit_buts_trackpos; break; - default: - ntype->uifunc = NULL; } } @@ -3158,81 +2679,170 @@ static void node_texture_set_butfunc(bNodeType *ntype) /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */ -void ED_node_init_butfuncs(void) +static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTreeType *treetype; - bNodeType *ntype; - bNodeSocketType *stype; - int i; + bNodeTree *ntree = ptr->id.data; + ED_node_tag_update_nodetree(bmain, ntree); +} + +static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp) +{ + StructRNA *srna = ntype->ext.srna; + PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier); - /* node type ui functions */ - for (i = 0; i < NUM_NTREE_TYPES; ++i) { - treetype = ntreeGetType(i); - if (treetype) { - for (ntype = treetype->node_types.first; ntype; ntype = ntype->next) { - /* default ui functions */ - ntype->drawfunc = node_draw_default; - ntype->drawupdatefunc = node_update_default; - ntype->select_area_func = node_select_area_default; - ntype->tweak_area_func = node_tweak_area_default; - ntype->uifunc = NULL; - ntype->uifuncbut = NULL; - ntype->drawinputfunc = node_draw_input_default; - ntype->drawoutputfunc = node_draw_output_default; - ntype->resize_area_func = node_resize_area_default; - - node_common_set_butfunc(ntype); - - switch (i) { - case NTREE_COMPOSIT: - node_composit_set_butfunc(ntype); - break; - case NTREE_SHADER: - node_shader_set_butfunc(ntype); - break; - case NTREE_TEXTURE: - node_texture_set_butfunc(ntype); - break; - } - } - } + if (prop) + RNA_def_property_update_runtime(prop, node_property_update_default); +} + +static void node_template_properties_update(bNodeType *ntype) +{ + bNodeSocketTemplate *stemp; + + if (ntype->inputs) { + for (stemp = ntype->inputs; stemp->type >= 0; ++stemp) + node_socket_template_properties_update(ntype, stemp); } + if (ntype->outputs) { + for (stemp = ntype->outputs; stemp->type >= 0; ++stemp) + node_socket_template_properties_update(ntype, stemp); + } +} + +void ED_node_init_butfuncs(void) +{ + /* node type ui functions */ + NODE_TYPES_BEGIN(ntype) + /* default ui functions */ + ntype->drawfunc = node_draw_default; + ntype->drawupdatefunc = node_update_default; + ntype->select_area_func = node_select_area_default; + ntype->tweak_area_func = node_tweak_area_default; + ntype->uifunc = NULL; + ntype->uifuncbut = NULL; + ntype->drawinputfunc = node_draw_input_default; + ntype->drawoutputfunc = node_draw_output_default; + ntype->resize_area_func = node_resize_area_default; + + node_common_set_butfunc(ntype); + + node_composit_set_butfunc(ntype); + node_shader_set_butfunc(ntype); + node_texture_set_butfunc(ntype); + + /* define update callbacks for socket properties */ + node_template_properties_update(ntype); + NODE_TYPES_END - /* socket type ui functions */ - for (i = 0; i < NUM_SOCKET_TYPES; ++i) { - stype = ntreeGetSocketType(i); - if (stype) { - switch (stype->type) { - case SOCK_FLOAT: - case SOCK_INT: - case SOCK_BOOLEAN: - stype->buttonfunc = node_socket_button_default; - break; - case SOCK_STRING: - stype->buttonfunc = node_socket_button_string; - break; - case SOCK_VECTOR: - stype->buttonfunc = node_socket_button_components; - break; - case SOCK_RGBA: - stype->buttonfunc = node_socket_button_color; - break; - case SOCK_SHADER: - stype->buttonfunc = node_socket_button_label; - break; - default: - stype->buttonfunc = NULL; - } + /* tree type icons */ + ntreeType_Composite->ui_icon = ICON_RENDERLAYERS; + ntreeType_Composite->draw_add_menu = node_add_menu_default; + ntreeType_Shader->ui_icon = ICON_MATERIAL; + ntreeType_Shader->draw_add_menu = node_add_menu_default; + ntreeType_Texture->ui_icon = ICON_TEXTURE; + ntreeType_Texture->draw_add_menu = node_add_menu_default; +} + +void ED_init_custom_node_type(bNodeType *ntype) +{ + /* default ui functions */ + ntype->drawfunc = node_draw_default; + ntype->drawupdatefunc = node_update_default; + ntype->drawinputfunc = node_draw_input_default; + ntype->drawoutputfunc = node_draw_output_default; + ntype->resize_area_func = node_resize_area_default; + ntype->select_area_func = node_select_area_default; + ntype->tweak_area_func = node_tweak_area_default; +} + +void ED_init_custom_node_socket_type(bNodeSocketType *stype) +{ + /* default ui functions */ + stype->draw = node_socket_button_label; +} + +/* maps standard socket integer type to a color */ +static const float std_node_socket_colors[][4] = { + {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */ + {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */ + {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */ + {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */ + {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */ + {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */ + {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */ + {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */ +}; + +/* common color callbacks for standard types */ +static void std_node_socket_draw_color(bContext *UNUSED(C), PointerRNA *ptr, PointerRNA *UNUSED(node_ptr), float *r_color) +{ + bNodeSocket *sock = ptr->data; + int type = sock->typeinfo->type; + copy_v4_v4(r_color, std_node_socket_colors[type]); +} +static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA *ptr, float *r_color) +{ + bNodeSocket *sock = ptr->data; + int type = sock->typeinfo->type; + copy_v4_v4(r_color, std_node_socket_colors[type]); +} + +static void std_node_socket_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr)) +{ + bNodeSocket *sock = ptr->data; + int type = sock->typeinfo->type; + /*int subtype = sock->typeinfo->subtype;*/ + + switch (type) { + case SOCK_FLOAT: + case SOCK_INT: + case SOCK_BOOLEAN: + uiItemR(layout, ptr, "default_value", 0, sock->name, 0); + break; + case SOCK_VECTOR: + uiTemplateComponentMenu(layout, ptr, "default_value", sock->name); + break; + case SOCK_RGBA: { + uiLayout *row = uiLayoutRow(layout, false); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); + /* draw the socket name right of the actual button */ + uiItemR(row, ptr, "default_value", 0, "", 0); + uiItemL(row, sock->name, 0); + break; + } + case SOCK_STRING: { + uiLayout *row = uiLayoutRow(layout, true); + /* draw the socket name right of the actual button */ + uiItemR(row, ptr, "default_value", 0, "", 0); + uiItemL(row, sock->name, 0); + break; } } } +void ED_init_standard_node_socket_type(bNodeSocketType *stype) +{ + stype->draw = std_node_socket_draw; + stype->draw_color = std_node_socket_draw_color; + stype->interface_draw_color = std_node_socket_interface_draw_color; +} + +static void node_socket_virtual_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color) +{ + /* alpha = 0, empty circle */ + zero_v4(r_color); +} + +void ED_init_node_socket_type_virtual(bNodeSocketType *stype) +{ + stype->draw = node_socket_button_label; + stype->draw_color = node_socket_virtual_draw_color; +} + /* ************** Generic drawing ************** */ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) { - - if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) { + if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); @@ -3640,18 +3250,13 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) do_triple = TRUE; } else { - int cycle = 0; - /* going to give issues once... */ if (link->tosock->flag & SOCK_UNAVAIL) return; if (link->fromsock->flag & SOCK_UNAVAIL) return; - /* check cyclic */ - if (link->fromnode && link->tonode) - cycle = (link->fromnode->level < link->tonode->level || link->tonode->level == 0xFFF); - if (!cycle && (link->flag & NODE_LINK_VALID)) { + if (link->flag & NODE_LINK_VALID) { /* special indicated link, on drop-node */ if (link->flag & NODE_LINKFLAG_HILITE) { th_col1 = th_col2 = TH_ACTIVE; diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 235d91ecd92..765f2b67549 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -62,62 +62,60 @@ #include "node_intern.h" /* own include */ -/* can be called from menus too, but they should do own undopush and redraws */ -bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, - bNodeTemplate *ntemp, float locx, float locy) +/* XXX Does some additional initialization on top of nodeAddNode + * Can be used with both custom and static nodes, if idname==NULL the static int type will be used instead. + * Can be called from menus too, but they should do own undopush and redraws. + */ +bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy) { - bNode *node = NULL, *gnode; - + SpaceNode *snode = CTX_wm_space_node(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + bNode *node = NULL; + node_deselect_all(snode); - - node = nodeAddNode(snode->edittree, ntemp); - + + if (idname) + node = nodeAddNode(C, snode->edittree, idname); + else + node = nodeAddStaticNode(C, snode->edittree, type); + BLI_assert(node && node->typeinfo); + /* generics */ - if (node) { - node_select(node); - - /* node location is mapped */ - locx /= UI_DPI_FAC; - locy /= UI_DPI_FAC; - - gnode = node_tree_get_editgroup(snode->nodetree); - // arbitrary y offset of 60 so its visible - if (gnode) { - node_from_view(gnode, locx, locy + 60.0f, &node->locx, &node->locy); - } - else { - node->locx = locx; - node->locy = locy + 60.0f; + node->locx = locx; + node->locy = locy + 60.0f; // arbitrary.. so its visible, (0,0) is top of node + nodeSetSelected(node, TRUE); + + /* node location is mapped */ + locx /= UI_DPI_FAC; + locy /= UI_DPI_FAC; + + node->locx = locx; + node->locy = locy + 60.0f; + + ntreeUpdateTree(snode->edittree); + ED_node_set_active(bmain, snode->edittree, node); + + if (snode->nodetree->type == NTREE_COMPOSIT) { + if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) { + node->id = &scene->id; } - - ntreeUpdateTree(snode->edittree); - ED_node_set_active(bmain, snode->edittree, node); - - if (snode->nodetree->type == NTREE_COMPOSIT) { - if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) { - node->id = &scene->id; - } - else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) { - node->id = (ID *)scene->clip; - } - - ntreeCompositForceHidden(snode->edittree, scene); + else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) { + node->id = (ID *)scene->clip; } - - if (node->id) - id_us_plus(node->id); - - - if (snode->flag & SNODE_USE_HIDDEN_PREVIEW) - node->flag &= ~NODE_PREVIEW; - - snode_update(snode, node); + + ntreeCompositForceHidden(snode->edittree, scene); } - + + if (node->id) + id_us_plus(node->id); + + snode_update(snode, node); + if (snode->nodetree->type == NTREE_TEXTURE) { ntreeTexCheckCyclics(snode->edittree); } - + return node; } @@ -183,9 +181,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi /* create the reroute node for this cursock */ if (!reroute_node) { - bNodeTemplate ntemp; - ntemp.type = NODE_REROUTE; - reroute_node = nodeAddNode(ntree, &ntemp); + reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE); /* add a single link to/from the reroute node to replace multiple links */ if (in_out == SOCK_OUT) { @@ -213,18 +209,11 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi } if (num_links > 0) { - bNode *gnode = node_tree_get_editgroup(snode->nodetree); - /* average cut point from shared links */ mul_v2_fl(insert_point, 1.0f / num_links); - if (gnode) { - node_from_view(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy); - } - else { - reroute_node->locx = insert_point[0]; - reroute_node->locy = insert_point[1]; - } + reroute_node->locx = insert_point[0]; + reroute_node->locy = insert_point[1]; } return socklink; @@ -266,6 +255,8 @@ static int add_reroute_exec(bContext *C, wmOperator *op) output_links.first = output_links.last = NULL; input_links.first = input_links.last = NULL; for (link = ntree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; if (add_reroute_intersect_check(link, mcoords, i, insert_point)) { add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point); add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point); @@ -330,12 +321,10 @@ void NODE_OT_add_reroute(wmOperatorType *ot) static int node_add_file_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); SpaceNode *snode = CTX_wm_space_node(C); bNode *node; Image *ima = NULL; - bNodeTemplate ntemp; + int type = 0; /* check input variables */ if (RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -367,36 +356,35 @@ static int node_add_file_exec(bContext *C, wmOperator *op) switch (snode->nodetree->type) { case NTREE_SHADER: - ntemp.type = SH_NODE_TEX_IMAGE; + type = SH_NODE_TEX_IMAGE; break; case NTREE_TEXTURE: - ntemp.type = TEX_NODE_IMAGE; + type = TEX_NODE_IMAGE; break; case NTREE_COMPOSIT: - ntemp.type = CMP_NODE_IMAGE; + type = CMP_NODE_IMAGE; break; default: return OPERATOR_CANCELLED; } - + ED_preview_kill_jobs(C); - - node = node_add_node(snode, bmain, scene, &ntemp, snode->cursor[0], snode->cursor[1]); - + + node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]); + if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add an image node"); return OPERATOR_CANCELLED; } - + node->id = (ID *)ima; - id_us_plus(node->id); - + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); snode_notify(C, snode); snode_dag_update(C, snode); - + return OPERATOR_FINISHED; } @@ -404,11 +392,11 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even { ARegion *ar = CTX_wm_region(C); SpaceNode *snode = CTX_wm_space_node(C); - + /* convert mouse coordinates to v2d space */ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); - + if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name")) return node_add_file_exec(C, op); else @@ -435,35 +423,35 @@ void NODE_OT_add_file(wmOperatorType *ot) RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign"); } - /********************** New node tree operator *********************/ static int new_node_tree_exec(bContext *C, wmOperator *op) { - SpaceNode *snode; + SpaceNode *snode = CTX_wm_space_node(C); + Main *bmain = CTX_data_main(C); bNodeTree *ntree; - Main *bmain; PointerRNA ptr, idptr; PropertyRNA *prop; - int treetype; + const char *idname; char treename[MAX_ID_NAME - 2] = "NodeTree"; - - /* retrieve state */ - snode = CTX_wm_space_node(C); - bmain = CTX_data_main(C); - - if (RNA_struct_property_is_set(op->ptr, "type")) - treetype = RNA_enum_get(op->ptr, "type"); - else - treetype = snode->treetype; - + + if (RNA_struct_property_is_set(op->ptr, "type")) { + prop = RNA_struct_find_property(op->ptr, "type"); + RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname); + } + else if (snode) + idname = snode->tree_idname; + if (RNA_struct_property_is_set(op->ptr, "name")) RNA_string_get(op->ptr, "name", treename); - - ntree = ntreeAddTree(bmain, treename, treetype, 0); - if (!ntree) + + if (!ntreeTypeFind(idname)) { + BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname); return OPERATOR_CANCELLED; - + } + + ntree = ntreeAddTree(bmain, treename, idname); + /* hook into UI */ uiIDContextProperty(C, &ptr, &prop); @@ -477,29 +465,36 @@ static int new_node_tree_exec(bContext *C, wmOperator *op) RNA_property_update(C, &ptr, prop); } else if (snode) { - Scene *scene = CTX_data_scene(C); snode->nodetree = ntree; - - ED_node_tree_update(snode, scene); + + ED_node_tree_update(C); } - + return OPERATOR_FINISHED; } +static EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) +{ + return rna_node_tree_type_itemf(NULL, NULL, free); +} + void NODE_OT_new_node_tree(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "New Node Tree"; ot->idname = "NODE_OT_new_node_tree"; ot->description = "Create a new node tree"; - + /* api callbacks */ ot->exec = new_node_tree_exec; - ot->poll = ED_operator_node_active; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", ""); + + prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", ""); + RNA_def_enum_funcs(prop, new_node_tree_type_itemf); RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", ""); } + diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 300328f5fd4..688377c7f3b 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -62,7 +62,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt)) { SpaceNode *snode = CTX_wm_space_node(C); - return (snode && snode->nodetree); + return (snode && ntreeIsValid(snode->nodetree)); } /* poll callback for active node */ @@ -70,7 +70,7 @@ static int active_node_poll(const bContext *C, PanelType *UNUSED(pt)) { SpaceNode *snode = CTX_wm_space_node(C); - return (snode && snode->edittree && nodeGetActive(snode->edittree)); + return (snode && ntreeIsValid(snode->edittree) && nodeGetActive(snode->edittree)); } /* active node */ @@ -160,6 +160,86 @@ static void node_sockets_panel(const bContext *C, Panel *pa) } } +static int node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + return (snode && snode->edittree && (snode->edittree->inputs.first || snode->edittree->outputs.first)); +} + +static int node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock, int *r_in_out) +{ + bNodeSocket *sock; + for (sock = ntree->inputs.first; sock; sock = sock->next) { + if (sock->flag & SELECT) { + *r_sock = sock; + *r_in_out = SOCK_IN; + return TRUE; + } + } + for (sock = ntree->outputs.first; sock; sock = sock->next) { + if (sock->flag & SELECT) { + *r_sock = sock; + *r_in_out = SOCK_OUT; + return TRUE; + } + } + + *r_sock = NULL; + *r_in_out = 0; + return FALSE; +} + +static void node_tree_interface_panel(const bContext *C, Panel *pa) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = (snode) ? snode->edittree : NULL; + bNodeSocket *sock; + int in_out; + uiLayout *layout = pa->layout, *row, *split, *col; + PointerRNA ptr, sockptr, opptr; + + if (!ntree) + return; + + RNA_id_pointer_create((ID *)ntree, &ptr); + + node_tree_find_active_socket(ntree, &sock, &in_out); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr); + + row = uiLayoutRow(layout, FALSE); + + split = uiLayoutRow(row, TRUE); + col = uiLayoutColumn(split, TRUE); + uiItemL(col, "Inputs:", ICON_NONE); + uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "inputs", &ptr, "active_input", 0, 0, 0); + opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_enum_set(&opptr, "in_out", SOCK_IN); + + col = uiLayoutColumn(split, TRUE); + uiItemL(col, "Outputs:", ICON_NONE); + uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "outputs", &ptr, "active_output", 0, 0, 0); + opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_enum_set(&opptr, "in_out", SOCK_OUT); + + col = uiLayoutColumn(row, TRUE); + opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_enum_set(&opptr, "direction", 1); + opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_enum_set(&opptr, "direction", 2); + + if (sock) { + row = uiLayoutRow(layout, TRUE); + uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE); + uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove"); + + if (sock->typeinfo->interface_draw) { + uiItemS(layout); + sock->typeinfo->interface_draw((bContext *)C, layout, &sockptr); + } + } +} + /* ******************* node buttons registration ************** */ void node_buttons_register(ARegionType *art) @@ -180,7 +260,14 @@ void node_buttons_register(ARegionType *art) pt->poll = node_sockets_poll; pt->flag |= PNL_DEFAULT_CLOSED; BLI_addtail(&art->paneltypes, pt); - + + pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface"); + strcpy(pt->idname, "NODE_PT_node_tree_interface"); + strcpy(pt->label, "Interface"); + pt->draw = node_tree_interface_panel; + pt->poll = node_tree_interface_poll; + BLI_addtail(&art->paneltypes, pt); + pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil"); strcpy(pt->idname, "NODE_PT_gpencil"); strcpy(pt->label, "Grease Pencil"); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d2cc42b0a56..0636dee9bc5 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -29,10 +29,14 @@ * \brief higher level node drawing for the node editor. */ +#include "DNA_lamp_types.h" #include "DNA_node_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" -#include "DNA_space_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -44,6 +48,8 @@ #include "BKE_main.h" #include "BKE_node.h" +#include "BLF_api.h" + #include "BIF_gl.h" #include "BIF_glutil.h" @@ -52,6 +58,7 @@ #include "ED_node.h" #include "ED_gpencil.h" +#include "ED_screen.h" #include "ED_space_api.h" #include "UI_resources.h" @@ -65,25 +72,49 @@ /* XXX interface.h */ extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select); -/* XXX update functions for node editor are a mess, needs a clear concept */ -void ED_node_tree_update(SpaceNode *snode, Scene *scene) +void ED_node_tree_update(const bContext *C) { - snode_set_context(snode, scene); + SpaceNode *snode = CTX_wm_space_node(C); + snode_set_context(C); if (snode->nodetree && snode->nodetree->id.us == 0) snode->nodetree->id.us = 1; } -void ED_node_changed_update(ID *id, bNode *node) +/* id is supposed to contain a node tree */ +static bNodeTree *node_tree_from_ID(ID *id) { - bNodeTree *nodetree, *edittree; - int treetype; - - node_tree_from_ID(id, &nodetree, &edittree, &treetype); + if (id) { + short idtype = GS(id->name); + + switch (idtype) { + case ID_NT: + return (bNodeTree *)id; + case ID_MA: + return ((Material *)id)->nodetree; + case ID_LA: + return ((Lamp *)id)->nodetree; + case ID_WO: + return ((World *)id)->nodetree; + case ID_SCE: + return ((Scene *)id)->nodetree; + case ID_TE: + return ((Tex *)id)->nodetree; + } + } + + return NULL; +} - if (treetype == NTREE_SHADER) { +void ED_node_tag_update_id(ID *id) +{ + bNodeTree *ntree = node_tree_from_ID(id); + if (id == NULL) + return; + + if (ntree->type == NTREE_SHADER) { DAG_id_tag_update(id, 0); - + if (GS(id->name) == ID_MA) WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, id); else if (GS(id->name) == ID_LA) @@ -91,18 +122,10 @@ void ED_node_changed_update(ID *id, bNode *node) else if (GS(id->name) == ID_WO) WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, id); } - else if (treetype == NTREE_COMPOSIT) { - if (node) - nodeUpdate(edittree, node); - /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ - - node = node_tree_get_editgroup(nodetree); - if (node) - nodeUpdateID(nodetree, node->id); - + else if (ntree->type == NTREE_COMPOSIT) { WM_main_add_notifier(NC_SCENE | ND_NODES, id); } - else if (treetype == NTREE_TEXTURE) { + else if (ntree->type == NTREE_TEXTURE) { DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_TEXTURE | ND_NODES, id); } @@ -123,25 +146,17 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup) return 0; } -typedef struct NodeUpdateCalldata { - bNodeTree *ntree; - bNode *node; -} NodeUpdateCalldata; -static void node_generic_update_cb(void *calldata, ID *owner_id, bNodeTree *ntree) -{ - NodeUpdateCalldata *cd = (NodeUpdateCalldata *)calldata; - /* check if nodetree uses the group stored in calldata */ - if (has_nodetree(ntree, cd->ntree)) - ED_node_changed_update(owner_id, cd->node); -} -void ED_node_generic_update(Main *bmain, bNodeTree *ntree, bNode *node) +void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree) { - bNodeTreeType *tti = ntreeGetType(ntree->type); - NodeUpdateCalldata cd; - cd.ntree = ntree; - cd.node = node; + if (!ntreeIsValid(ntree)) + return; + /* look through all datablocks, to support groups */ - tti->foreach_nodetree(bmain, &cd, node_generic_update_cb); + FOREACH_NODETREE(bmain, tntree, id) { + /* check if nodetree uses the group */ + if (has_nodetree(tntree, ntree)) + ED_node_tag_update_id(id); + } FOREACH_NODETREE_END if (ntree->type == NTREE_TEXTURE) ntreeTexCheckCyclics(ntree); @@ -251,12 +266,12 @@ void ED_node_sort(bNodeTree *ntree) } -static void do_node_internal_buttons(bContext *C, void *node_v, int event) +static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event) { if (event == B_NODE_EXEC) { SpaceNode *snode = CTX_wm_space_node(C); if (snode && snode->id) - ED_node_changed_update(snode->id, node_v); + ED_node_tag_update_id(snode->id); } } @@ -296,13 +311,15 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry) /* based on settings in node, sets drawing rect info. each redraw! */ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) { - uiLayout *layout; - PointerRNA ptr; + uiLayout *layout, *row; + PointerRNA nodeptr, sockptr; bNodeSocket *nsock; float locx, locy; float dy; int buty; + RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); + /* get "global" coords */ node_to_view(node, 0.0f, 0.0f, &locx, &locy); dy = locy; @@ -313,14 +330,36 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) /* little bit space in top */ if (node->outputs.first) dy -= NODE_DYS / 2; - + /* output sockets */ for (nsock = node->outputs.first; nsock; nsock = nsock->next) { - if (!nodeSocketIsHidden(nsock)) { - nsock->locx = locx + NODE_WIDTH(node); - nsock->locy = dy - NODE_DYS; - dy -= NODE_DY; - } + if (nodeSocketIsHidden(nsock)) + continue; + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr); + + layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, + locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, UI_GetStyle()); + /* context pointers for current node and socket */ + uiLayoutSetContextPointer(layout, "node", &nodeptr); + uiLayoutSetContextPointer(layout, "socket", &sockptr); + + /* align output buttons to the right */ + row = uiLayoutRow(layout, 1); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); + + node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE)); + + uiBlockEndAlign(node->block); + uiBlockLayoutResolve(node->block, NULL, &buty); + + /* ensure minimum socket height in case layout is empty */ + buty = MIN2(buty, dy - NODE_DY); + + nsock->locx = locx + NODE_WIDTH(node); + /* place the socket circle in the middle of the layout */ + nsock->locy = 0.5f * (dy + buty); + dy = buty; } node->prvr.xmin = locx + NODE_DYS; @@ -328,43 +367,32 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) /* preview rect? */ if (node->flag & NODE_PREVIEW) { - if (node->preview && node->preview->rect) { - float aspect = 1.0f; - - if (node->preview && node->preview->xsize && node->preview->ysize) - aspect = (float)node->preview->ysize / (float)node->preview->xsize; + float aspect = 1.0f; + + if (node->preview_xsize && node->preview_ysize) + aspect = (float)node->preview_ysize / (float)node->preview_xsize; + + dy -= NODE_DYS / 2; + node->prvr.ymax = dy; + + if (aspect <= 1.0f) + node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY); + else { + /* width correction of image */ + /* XXX huh? (ton) */ + float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect; - dy -= NODE_DYS / 2; - node->prvr.ymax = dy; + node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY); - if (aspect <= 1.0f) - node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY); - else { - /* width correction of image */ - /* XXX huh? (ton) */ - float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect; - - node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY); - - node->prvr.xmin += 0.5f * dx; - node->prvr.xmax -= 0.5f * dx; - } - - dy = node->prvr.ymin - NODE_DYS / 2; - - /* make sure that maximums are bigger or equal to minimums */ - if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin); - if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin); - } - else { - float oldh = BLI_rctf_size_y(&node->prvr); - if (oldh == 0.0f) - oldh = 0.6f * NODE_WIDTH(node) - NODE_DY; - dy -= NODE_DYS / 2; - node->prvr.ymax = dy; - node->prvr.ymin = dy - oldh; - dy = node->prvr.ymin - NODE_DYS / 2; + node->prvr.xmin += 0.5f * dx; + node->prvr.xmax -= 0.5f * dx; } + + dy = node->prvr.ymin - NODE_DYS / 2; + + /* make sure that maximums are bigger or equal to minimums */ + if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin); + if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin); } /* buttons rect? */ @@ -378,14 +406,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) node->butr.ymin = 0; node->butr.ymax = 0; - RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); - layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle()); - uiLayoutSetContextPointer(layout, "node", &ptr); + uiLayoutSetContextPointer(layout, "node", &nodeptr); - node->typeinfo->uifunc(layout, (bContext *)C, &ptr); + node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr); uiBlockEndAlign(node->block); uiBlockLayoutResolve(node->block, NULL, &buty); @@ -395,11 +421,29 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) /* input sockets */ for (nsock = node->inputs.first; nsock; nsock = nsock->next) { - if (!nodeSocketIsHidden(nsock)) { - nsock->locx = locx; - nsock->locy = dy - NODE_DYS; - dy -= NODE_DY; - } + if (nodeSocketIsHidden(nsock)) + continue; + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr); + + layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, + locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, UI_GetStyle()); + /* context pointers for current node and socket */ + uiLayoutSetContextPointer(layout, "node", &nodeptr); + uiLayoutSetContextPointer(layout, "socket", &sockptr); + + node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE)); + + uiBlockEndAlign(node->block); + uiBlockLayoutResolve(node->block, NULL, &buty); + + /* ensure minimum socket height in case layout is empty */ + buty = MIN2(buty, dy - NODE_DY); + + nsock->locx = locx; + /* place the socket circle in the middle of the layout */ + nsock->locy = 0.5f * (dy + buty); + dy = buty; } /* little bit space in end */ @@ -510,6 +554,7 @@ int node_get_colorid(bNode *node) case NODE_CLASS_OP_VECTOR: case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR; case NODE_CLASS_GROUP: return TH_NODE_GROUP; + case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE; case NODE_CLASS_MATTE: return TH_NODE_MATTE; case NODE_CLASS_DISTORT: return TH_NODE_DISTORT; default: return TH_NODE; @@ -534,7 +579,7 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) } /* this might have some more generic use */ -static void node_circle_draw(float x, float y, float size, char *col, int highlight) +static void node_circle_draw(float x, float y, float size, float *col, int highlight) { /* 16 values of sin function */ static float si[16] = { @@ -552,12 +597,14 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli }; int a; - glColor3ub(col[0], col[1], col[2]); + glColor4fv(col); + glEnable(GL_BLEND); glBegin(GL_POLYGON); for (a = 0; a < 16; a++) glVertex2f(x + size * si[a], y + size * co[a]); glEnd(); + glDisable(GL_BLEND); if (highlight) { UI_ThemeColor(TH_TEXT_HI); @@ -577,66 +624,93 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli glLineWidth(1.0f); } -void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight) +void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight) { - bNodeSocketType *stype = ntreeGetSocketType(sock->type); - node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight); + PointerRNA ptr, node_ptr; + float color[4]; + + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); + sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); + node_circle_draw(sock->locx, sock->locy, size, color, highlight); } /* ************** Socket callbacks *********** */ -/* not a callback */ -static void node_draw_preview(bNodePreview *preview, rctf *prv) +static void node_draw_preview_background(float tile, rctf *rect) { - float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize); - float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize); - float tile = BLI_rctf_size_x(prv) / 10.0f; float x, y; /* draw checkerboard backdrop to show alpha */ glColor3ub(120, 120, 120); - glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax); + glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); glColor3ub(160, 160, 160); - for (y = prv->ymin; y < prv->ymax; y += tile * 2) { - for (x = prv->xmin; x < prv->xmax; x += tile * 2) { + for (y = rect->ymin; y < rect->ymax; y += tile * 2) { + for (x = rect->xmin; x < rect->xmax; x += tile * 2) { float tilex = tile, tiley = tile; - if (x + tile > prv->xmax) - tilex = prv->xmax - x; - if (y + tile > prv->ymax) - tiley = prv->ymax - y; + if (x + tile > rect->xmax) + tilex = rect->xmax - x; + if (y + tile > rect->ymax) + tiley = rect->ymax - y; glRectf(x, y, x + tilex, y + tiley); } } - for (y = prv->ymin + tile; y < prv->ymax; y += tile * 2) { - for (x = prv->xmin + tile; x < prv->xmax; x += tile * 2) { + for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) { + for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) { float tilex = tile, tiley = tile; - if (x + tile > prv->xmax) - tilex = prv->xmax - x; - if (y + tile > prv->ymax) - tiley = prv->ymax - y; + if (x + tile > rect->xmax) + tilex = rect->xmax - x; + if (y + tile > rect->ymax) + tiley = rect->ymax - y; glRectf(x, y, x + tilex, y + tiley); } } - - glPixelZoom(xscale, yscale); +} +/* not a callback */ +static void node_draw_preview(bNodePreview *preview, rctf *prv) +{ + float xrect = BLI_rctf_size_x(prv); + float yrect = BLI_rctf_size_y(prv); + float xscale = xrect / ((float)preview->xsize); + float yscale = yrect / ((float)preview->ysize); + float scale; + rctf draw_rect; + + /* uniform scale and offset */ + draw_rect = *prv; + if (xscale < yscale) { + float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale); + draw_rect.ymin += offset; + draw_rect.ymax -= offset; + scale = xscale; + } + else { + float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale); + draw_rect.xmin += offset; + draw_rect.xmax -= offset; + scale = yscale; + } + + node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */ glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); + glPixelZoom(scale, scale); + glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); + glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); - glPixelZoom(1.0f, 1.0f); UI_ThemeColorShadeAlpha(TH_BACK, -15, +100); - fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax); - + fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax); } /* common handle function for operator buttons that need to select the node first */ @@ -669,8 +743,9 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha) } } -static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) +static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) { + bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data; bNodeSocket *sock; rctf *rct = &node->totr; float iconofs; @@ -680,9 +755,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN char showname[128]; /* 128 used below */ View2D *v2d = &ar->v2d; - /* hurmf... another candidate for callback, have to see how this works first */ - if (node->id && node->block && snode->treetype == NTREE_SHADER) - nodeShaderSynchronizeID(node, 0); + /* XXX hack: copy values from linked ID data where displayed as sockets */ + if (node->block) + nodeSynchronizeID(node, false); /* skip if out of view */ if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == FALSE) { @@ -823,11 +898,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if (nodeSocketIsHidden(sock)) continue; - node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT); - - node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name), - sock->locx + (NODE_DYS), sock->locy - NODE_DYS, - NODE_WIDTH(node) - NODE_DY); + node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT); } /* socket outputs */ @@ -835,17 +906,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if (nodeSocketIsHidden(sock)) continue; - node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT); - - node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name), - sock->locx - NODE_WIDTH(node) + (NODE_DYS), sock->locy - NODE_DYS, - NODE_WIDTH(node) - NODE_DY); + node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT); } /* preview */ if (node->flag & NODE_PREVIEW) { - if (node->preview && node->preview->rect && !BLI_rctf_is_empty(&node->prvr)) - node_draw_preview(node->preview, &node->prvr); + bNodePreview *preview = previews ? BKE_node_instance_hash_lookup(previews, key) : NULL; + if (preview && preview->rect && !BLI_rctf_is_empty(&node->prvr)) + node_draw_preview(preview, &node->prvr); } UI_ThemeClearColor(color_id); @@ -855,7 +923,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN node->block = NULL; } -static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) +static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) { bNodeSocket *sock; rctf *rct = &node->totr; @@ -957,12 +1025,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b /* sockets */ for (sock = node->inputs.first; sock; sock = sock->next) { if (!nodeSocketIsHidden(sock)) - node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT); + node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); } for (sock = node->outputs.first; sock; sock = sock->next) { if (!nodeSocketIsHidden(sock)) - node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT); + node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); } uiEndBlock(C, node->block); @@ -989,7 +1057,7 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode) bNodeSocket *sock; int cursor = CURSOR_STD; - if (ntree) { + if (ntreeIsValid(ntree)) { if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) { /* pass */ } @@ -1009,12 +1077,12 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode) WM_cursor_set(win, cursor); } -void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) +void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) { if (node->flag & NODE_HIDDEN) - node_draw_hidden(C, ar, snode, ntree, node); + node_draw_hidden(C, ar, snode, ntree, node, key); else - node_draw_basis(C, ar, snode, ntree, node); + node_draw_basis(C, ar, snode, ntree, node, key); } static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) @@ -1023,34 +1091,28 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) node->typeinfo->drawupdatefunc(C, ntree, node); } -void node_update_nodetree(const bContext *C, bNodeTree *ntree, float offsetx, float offsety) +void node_update_nodetree(const bContext *C, bNodeTree *ntree) { bNode *node; /* update nodes front to back, so children sizes get updated before parents */ for (node = ntree->nodes.last; node; node = node->prev) { - /* XXX little hack (not used anyore?) */ - node->locx += offsetx; - node->locy += offsety; - node_update(C, ntree, node); - - node->locx -= offsetx; - node->locy -= offsety; } } -static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) +static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) { if (node->typeinfo->drawfunc) - node->typeinfo->drawfunc(C, ar, snode, ntree, node); + node->typeinfo->drawfunc(C, ar, snode, ntree, node, key); } #define USE_DRAW_TOT_UPDATE -void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree) +void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key) { bNode *node; + bNodeInstanceKey key; bNodeLink *link; int a; @@ -1073,122 +1135,200 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT if (!(node->flag & NODE_BACKGROUND)) continue; + + key = BKE_node_instance_key(parent_key, ntree, node); node->nr = a; /* index of node in list, used for exec event code */ - node_draw(C, ar, snode, ntree, node); + node_draw(C, ar, snode, ntree, node, key); } /* node lines */ glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - for (link = ntree->links.first; link; link = link->next) - node_draw_link(&ar->v2d, snode, link); + for (link = ntree->links.first; link; link = link->next) { + if (!nodeLinkIsHidden(link)) + node_draw_link(&ar->v2d, snode, link); + } glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); /* draw foreground nodes, last nodes in front */ for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) { + bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node); if (node->flag & NODE_BACKGROUND) continue; + + key = BKE_node_instance_key(parent_key, ntree, node); node->nr = a; /* index of node in list, used for exec event code */ - node_draw(C, ar, snode, ntree, node); + node_draw(C, ar, snode, ntree, node, key); } } -void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) +/* draw tree path info in lower left corner */ +static void draw_tree_path(SpaceNode *snode) +{ + char info[256]; + + ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info)); + + UI_ThemeColor(TH_TEXT_HI); + BLF_draw_default(30, 30, 0.0f, info, sizeof(info)); +} + +static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, float centerx, float centery) +{ + View2D *v2d = &ar->v2d; + + /* shift view to node tree center */ + UI_view2d_setcenter(v2d, centerx, centery); + UI_view2d_view_ortho(v2d); + + /* aspect+font, set each time */ + snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx; + // XXX snode->curfont = uiSetCurFont_ext(snode->aspect); +} + +static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + node_uiblocks_init(C, ntree); + +#ifdef WITH_COMPOSITOR + if (ntree->type == NTREE_COMPOSIT) { + COM_startReadHighlights(); + } +#endif + + node_update_nodetree(C, ntree); + node_draw_nodetree(C, ar, snode, ntree, parent_key); +} + +/* shade the parent node group and add a uiBlock to clip mouse events */ +static void draw_group_overlay(const bContext *C, ARegion *ar) +{ + View2D *v2d = &ar->v2d; + rctf rect = v2d->cur; + uiBlock *block; + + /* shade node groups to separate them visually */ + UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70); + glEnable(GL_BLEND); + uiSetRoundBox(0); + uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0); + glDisable(GL_BLEND); + + /* set the block bounds to clip mouse events from underlying nodes */ + block = uiBeginBlock(C, ar, "node tree bounds block", UI_EMBOSS); + uiExplicitBoundsBlock(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + uiBlockSetFlag(block, UI_BLOCK_CLIP_EVENTS); + uiEndBlock(C, block); +} + +void drawnodespace(const bContext *C, ARegion *ar) { View2DScrollers *scrollers; SpaceNode *snode = CTX_wm_space_node(C); - bNodeLinkDrag *nldrag; - LinkData *linkdata; + View2D *v2d = &ar->v2d; UI_ThemeClearColor(TH_BACK); glClear(GL_COLOR_BUFFER_BIT); UI_view2d_view_ortho(v2d); - - //uiFreeBlocksWin(&sa->uiblocks, sa->win); ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); /* only set once */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_MAP1_VERTEX_3); - - /* aspect+font, set each time */ - snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx; - // XXX snode->curfont = uiSetCurFont_ext(snode->aspect); - - /* grid */ - UI_view2d_multi_grid_draw(v2d, U.widget_unit, 5, 2); - - /* backdrop */ - draw_nodespace_back_pix(C, ar, snode); /* nodes */ - snode_set_context(snode, CTX_data_scene(C)); - - if (snode->nodetree) { - bNode *node; - /* void **highlights = 0; */ /* UNUSED */ + snode_set_context(C); + + /* draw parent node trees */ + if (snode->treepath.last) { + static const int max_depth = 2; + bNodeTreePath *path; + int depth, curdepth; + float center[2]; + bNodeTree *ntree; + bNodeLinkDrag *nldrag; + LinkData *linkdata; - node_uiblocks_init(C, snode->nodetree); + /* current View2D center, will be set temporarily for parent node trees */ + UI_view2d_getcenter(v2d, ¢er[0], ¢er[1]); - /* uiBlocks must be initialized in drawing order for correct event clipping. - * Node group internal blocks added after the main group block. - */ - for (node = snode->nodetree->nodes.first; node; node = node->next) { - if (node->flag & NODE_GROUP_EDIT) - node_uiblocks_init(C, (bNodeTree *)node->id); + /* store new view center in current edittree */ + if (snode->edittree) + copy_v2_v2(snode->edittree->view_center, center); + + depth = 0; + path = snode->treepath.last; + while (path->prev && depth < max_depth) { + path = path->prev; + ++depth; + } + /* parent node trees in the background */ + for (curdepth = depth; curdepth >= 0; path = path->next, --curdepth) { + ntree = path->nodetree; + + if (ntreeIsValid(ntree)) { + snode_setup_v2d(snode, ar, ntree->view_center[0], ntree->view_center[1]); + + if (curdepth == 0) { + /* grid, uses theme color based on node path depth */ + UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), U.widget_unit, 5, 2); + + /* backdrop */ + draw_nodespace_back_pix(C, ar, snode); + } + + draw_nodetree(C, ar, ntree, path->parent_key); + + if (curdepth > 0) + draw_group_overlay(C, ar); + } } - node_update_nodetree(C, snode->nodetree, 0.0f, 0.0f); - -#ifdef WITH_COMPOSITOR - if (snode->nodetree->type == NTREE_COMPOSIT) { - COM_startReadHighlights(); + /* reset View2D */ + UI_view2d_setcenter(v2d, center[0], center[1]); + + /* temporary links */ + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) { + for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) + node_draw_link(v2d, snode, (bNodeLink *)linkdata->data); } -#endif - - node_draw_nodetree(C, ar, snode, snode->nodetree); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); - #if 0 - /* active group */ - for (node = snode->nodetree->nodes.first; node; node = node->next) { - if (node->flag & NODE_GROUP_EDIT) - node_draw_group(C, ar, snode, snode->nodetree, node); + if (snode->flag & SNODE_SHOW_GPENCIL) { + /* draw grease-pencil ('canvas' strokes) */ + draw_gpencil_view2d(C, TRUE); } - #endif } - - /* temporary links */ - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) { - for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { - node_draw_link(&ar->v2d, snode, (bNodeLink *)linkdata->data); - } + else { + /* default grid */ + UI_view2d_multi_grid_draw(v2d, TH_BACK, U.widget_unit, 5, 2); + + /* backdrop */ + draw_nodespace_back_pix(C, ar, snode); } - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); - if (snode->flag & SNODE_SHOW_GPENCIL) { - /* draw grease-pencil ('canvas' strokes) */ - if (snode->nodetree) { - draw_gpencil_view2d(C, TRUE); - } - } - /* reset view matrix */ UI_view2d_view_restore(C); - if (snode->flag & SNODE_SHOW_GPENCIL) { - /* draw grease-pencil (screen strokes, and also paintbuffer) */ - if (snode->nodetree) { + if (snode->treepath.last) { + if (snode->flag & SNODE_SHOW_GPENCIL) { + /* draw grease-pencil (screen strokes, and also paintbuffer) */ draw_gpencil_view2d(C, FALSE); } } + + /* tree path info */ + draw_tree_path(snode); /* scrollers */ scrollers = UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 941bd783c39..256b02d3288 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -31,6 +31,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_action_types.h" +#include "DNA_anim_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_node_types.h" @@ -65,6 +67,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -76,6 +79,12 @@ #include "IMB_imbuf_types.h" #include "node_intern.h" /* own include */ +#include "NOD_common.h" +#include "NOD_socket.h" +#include "NOD_composite.h" +#include "NOD_shader.h" +#include "NOD_texture.h" + #define USE_ESC_COMPO @@ -241,27 +250,12 @@ int composite_node_active(bContext *C) { if (ED_operator_node_active(C)) { SpaceNode *snode = CTX_wm_space_node(C); - if (snode->treetype == NTREE_COMPOSIT) + if (ED_node_is_compositor(snode)) return 1; } return 0; } -/* also checks for edited groups */ -bNode *editnode_get_active(bNodeTree *ntree) -{ - bNode *node; - - /* check for edited group */ - for (node = ntree->nodes.first; node; node = node->next) - if (nodeGroupEditGet(node)) - break; - if (node) - return nodeGetActive((bNodeTree *)node->id); - else - return nodeGetActive(ntree); -} - static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup) { bNode *node; @@ -277,20 +271,16 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup) return 0; } -static void snode_dag_update_group(void *calldata, ID *owner_id, bNodeTree *ntree) -{ - if (has_nodetree(ntree, calldata)) - DAG_id_tag_update(owner_id, 0); -} - void snode_dag_update(bContext *C, SpaceNode *snode) { Main *bmain = CTX_data_main(C); /* for groups, update all ID's using this */ if (snode->edittree != snode->nodetree) { - bNodeTreeType *tti = ntreeGetType(snode->edittree->type); - tti->foreach_nodetree(bmain, snode->edittree, snode_dag_update_group); + FOREACH_NODETREE(bmain, tntree, id) { + if (has_nodetree(tntree, snode->edittree)) + DAG_id_tag_update(id, 0); + } FOREACH_NODETREE_END } DAG_id_tag_update(snode->id, 0); @@ -300,37 +290,53 @@ void snode_notify(bContext *C, SpaceNode *snode) { WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL); - if (snode->treetype == NTREE_SHADER) + if (ED_node_is_shader(snode)) WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id); - else if (snode->treetype == NTREE_COMPOSIT) + else if (ED_node_is_compositor(snode)) WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id); - else if (snode->treetype == NTREE_TEXTURE) + else if (ED_node_is_texture(snode)) WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id); } -bNode *node_tree_get_editgroup(bNodeTree *nodetree) +void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo) { - bNode *gnode; - - /* get the groupnode */ - for (gnode = nodetree->nodes.first; gnode; gnode = gnode->next) - if (nodeGroupEditGet(gnode)) - break; - return gnode; + if (typeinfo) + BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname)); + else + snode->tree_idname[0] = '\0'; +} + +int ED_node_is_compositor(struct SpaceNode *snode) +{ + return STREQ(snode->tree_idname, ntreeType_Composite->idname); +} + +int ED_node_is_shader(struct SpaceNode *snode) +{ + return STREQ(snode->tree_idname, ntreeType_Shader->idname); +} + +int ED_node_is_texture(struct SpaceNode *snode) +{ + return STREQ(snode->tree_idname, ntreeType_Texture->idname); } /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ -void ED_node_shader_default(Scene *scene, ID *id) +void ED_node_shader_default(const bContext *C, ID *id) { + Scene *scene = CTX_data_scene(C); bNode *in, *out; bNodeSocket *fromsock, *tosock, *sock; bNodeTree *ntree; - bNodeTemplate ntemp; + PointerRNA ptr; int output_type, shader_type; - float color[3], strength = 1.0f; + float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }, strength = 1.0f; - ntree = ntreeAddTree(G.main, "Shader Nodetree", NTREE_SHADER, 0); + ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + + RNA_id_pointer_create((ID *)ntree, &ptr); + RNA_boolean_set(&ptr, "is_local_tree", TRUE); switch (GS(id->name)) { case ID_MA: @@ -383,12 +389,10 @@ void ED_node_shader_default(Scene *scene, ID *id) return; } - ntemp.type = output_type; - out = nodeAddNode(ntree, &ntemp); + out = nodeAddStaticNode(C, ntree, output_type); out->locx = 300.0f; out->locy = 300.0f; - ntemp.type = shader_type; - in = nodeAddNode(ntree, &ntemp); + in = nodeAddStaticNode(C, ntree, shader_type); in->locx = 10.0f; in->locy = 300.0f; nodeSetActive(ntree, in); @@ -399,12 +403,16 @@ void ED_node_shader_default(Scene *scene, ID *id) /* default values */ if (BKE_scene_use_new_shading_nodes(scene)) { + PointerRNA sockptr; sock = in->inputs.first; - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, color); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); + + RNA_float_set_array(&sockptr, "default_value", color); if (strength != 0.0f) { sock = in->inputs.last; - ((bNodeSocketValueFloat *)sock->default_value)->value = strength; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); + RNA_float_set(&sockptr, "default_value", strength); } } @@ -413,11 +421,11 @@ void ED_node_shader_default(Scene *scene, ID *id) /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ -void ED_node_composit_default(Scene *sce) +void ED_node_composit_default(const bContext *C, struct Scene *sce) { bNode *in, *out; bNodeSocket *fromsock, *tosock; - bNodeTemplate ntemp; + PointerRNA ptr; /* but lets check it anyway */ if (sce->nodetree) { @@ -426,20 +434,21 @@ void ED_node_composit_default(Scene *sce) return; } - sce->nodetree = ntreeAddTree(G.main, "Compositing Nodetree", NTREE_COMPOSIT, 0); - + sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname); + + RNA_id_pointer_create((ID *)sce->nodetree, &ptr); + RNA_boolean_set(&ptr, "is_local_tree", TRUE); + sce->nodetree->chunksize = 256; sce->nodetree->edit_quality = NTREE_QUALITY_HIGH; sce->nodetree->render_quality = NTREE_QUALITY_HIGH; - ntemp.type = CMP_NODE_COMPOSITE; - out = nodeAddNode(sce->nodetree, &ntemp); + out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE); out->locx = 300.0f; out->locy = 400.0f; out->id = &sce->id; id_us_plus(out->id); - ntemp.type = CMP_NODE_R_LAYERS; - in = nodeAddNode(sce->nodetree, &ntemp); + in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS); in->locx = 10.0f; in->locy = 400.0f; in->id = &sce->id; id_us_plus(in->id); @@ -457,11 +466,11 @@ void ED_node_composit_default(Scene *sce) /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ -void ED_node_texture_default(Tex *tx) +void ED_node_texture_default(const bContext *C, Tex *tx) { bNode *in, *out; bNodeSocket *fromsock, *tosock; - bNodeTemplate ntemp; + PointerRNA ptr; /* but lets check it anyway */ if (tx->nodetree) { @@ -470,14 +479,15 @@ void ED_node_texture_default(Tex *tx) return; } - tx->nodetree = ntreeAddTree(G.main, "Texture Nodetree", NTREE_TEXTURE, 0); + tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname); - ntemp.type = TEX_NODE_OUTPUT; - out = nodeAddNode(tx->nodetree, &ntemp); + RNA_id_pointer_create((ID *)tx->nodetree, &ptr); + RNA_boolean_set(&ptr, "is_local_tree", TRUE); + + out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT); out->locx = 300.0f; out->locy = 300.0f; - ntemp.type = TEX_NODE_CHECKER; - in = nodeAddNode(tx->nodetree, &ntemp); + in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER); in->locx = 10.0f; in->locy = 300.0f; nodeSetActive(tx->nodetree, in); @@ -488,162 +498,68 @@ void ED_node_texture_default(Tex *tx) ntreeUpdateTree(tx->nodetree); } -/* id is supposed to contain a node tree */ -void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype) +/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */ +void snode_set_context(const bContext *C) { - if (id) { - bNode *node = NULL; - short idtype = GS(id->name); + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname); + bNodeTree *ntree = snode->nodetree; + ID *id = snode->id, *from = snode->from; - if (idtype == ID_NT) { - *ntree = (bNodeTree *)id; - if (treetype) *treetype = (*ntree)->type; - } - else if (idtype == ID_MA) { - *ntree = ((Material *)id)->nodetree; - if (treetype) *treetype = NTREE_SHADER; - } - else if (idtype == ID_LA) { - *ntree = ((Lamp *)id)->nodetree; - if (treetype) *treetype = NTREE_SHADER; - } - else if (idtype == ID_WO) { - *ntree = ((World *)id)->nodetree; - if (treetype) *treetype = NTREE_SHADER; - } - else if (idtype == ID_SCE) { - *ntree = ((Scene *)id)->nodetree; - if (treetype) *treetype = NTREE_COMPOSIT; - } - else if (idtype == ID_TE) { - *ntree = ((Tex *)id)->nodetree; - if (treetype) *treetype = NTREE_TEXTURE; - } - else { - if (treetype) *treetype = 0; - return; - } + /* we use this to signal warnings, when node shaders are drawn in wrong render engine */ + if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C))) + snode->flag |= SNODE_NEW_SHADERS; + else + snode->flag &= ~SNODE_NEW_SHADERS; + + /* check the tree type */ + if (!treetype || + (treetype->poll && !treetype->poll(C, treetype))) + { + /* invalid tree type, disable */ + snode->tree_idname[0] = '\0'; + ED_node_tree_start(snode, NULL, NULL, NULL); + return; + } - /* find editable group */ - if (edittree) { - if (*ntree) - for (node = (*ntree)->nodes.first; node; node = node->next) - if (nodeGroupEditGet(node)) - break; - - if (node && node->id) - *edittree = (bNodeTree *)node->id; - else - *edittree = *ntree; - } + if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) { + /* current tree does not match selected type, clear tree path */ + ntree = NULL; + id = NULL; + from = NULL; } - else { - *ntree = NULL; - *edittree = NULL; - if (treetype) *treetype = 0; + + if (!(snode->flag & SNODE_PIN) || ntree == NULL) { + if (treetype->get_from_context) + treetype->get_from_context(C, treetype, &ntree, &id, &from); + } + + if (snode->nodetree != ntree || snode->id != id || snode->from != snode->from) { + ED_node_tree_start(snode, ntree, id, from); } } -/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */ -void snode_set_context(SpaceNode *snode, Scene *scene) +void snode_update(SpaceNode *snode, bNode *node) { - Object *ob = OBACT; + bNodeTreePath *path; - snode->id = snode->from = NULL; + /* XXX this only updates nodes in the current node space tree path. + * The function supposedly should update any potential group node linking to changed tree, + * this really requires a working depsgraph ... + */ - if (snode->treetype == NTREE_SHADER) { - /* we use this to signal warnings, when node shaders are drawn in wrong render engine */ - if (BKE_scene_use_new_shading_nodes(scene)) - snode->flag |= SNODE_NEW_SHADERS; - else - snode->flag &= ~SNODE_NEW_SHADERS; - - /* need active object, or we allow pinning... */ - if (snode->shaderfrom == SNODE_SHADER_OBJECT) { - if (ob) { - if (ob->type == OB_LAMP) { - snode->from = &ob->id; - snode->id = ob->data; - } - else { - Material *ma = give_current_material(ob, ob->actcol); - if (ma) { - snode->from = &ob->id; - snode->id = &ma->id; - } - } - } - } - else { /* SNODE_SHADER_WORLD */ - if (scene->world) { - snode->from = NULL; - snode->id = &scene->world->id; - } - } - } - else if (snode->treetype == NTREE_COMPOSIT) { - snode->id = &scene->id; - - /* update output sockets based on available layers */ - ntreeCompositForceHidden(scene->nodetree, scene); - } - else if (snode->treetype == NTREE_TEXTURE) { - Tex *tx = NULL; - - if (snode->texfrom == SNODE_TEX_OBJECT) { - if (ob) { - tx = give_current_object_texture(ob); - - if (ob->type == OB_LAMP) - snode->from = (ID *)ob->data; - else - snode->from = (ID *)give_current_material(ob, ob->actcol); - - /* from is not set fully for material nodes, should be ID + Node then */ - snode->id = &tx->id; - } + /* update all edited group nodes */ + path = snode->treepath.last; + if (path) { + bNodeTree *ngroup = path->nodetree; + for (path = path->prev; path; path = path->prev) { + nodeUpdateID(path->nodetree, (ID *)ngroup); + ngroup = path->nodetree; } - else if (snode->texfrom == SNODE_TEX_WORLD) { - tx = give_current_world_texture(scene->world); - snode->from = (ID *)scene->world; - snode->id = &tx->id; - } - else { - struct Brush *brush = NULL; - - if (ob && (ob->mode & OB_MODE_SCULPT)) - brush = paint_brush(&scene->toolsettings->sculpt->paint); - else - brush = paint_brush(&scene->toolsettings->imapaint.paint); - - if (brush) { - snode->from = (ID *)brush; - tx = give_current_brush_texture(brush); - snode->id = &tx->id; - } - } - } - else { - if (snode->nodetree && snode->nodetree->type == snode->treetype) - snode->id = &snode->nodetree->id; - else - snode->id = NULL; } - node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL); -} - -void snode_update(SpaceNode *snode, bNode *node) -{ - bNode *gnode; - if (node) nodeUpdate(snode->edittree, node); - - /* if inside group, tag entire group */ - gnode = node_tree_get_editgroup(snode->nodetree); - if (gnode) - nodeUpdateID(snode->nodetree, gnode->id); } void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) @@ -654,6 +570,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) if (node->type != NODE_GROUP) { int was_output = (node->flag & NODE_DO_OUTPUT); + int do_update = 0; + + /* generic node group output: set node as active output */ + if (node->type == NODE_GROUP_OUTPUT) { + bNode *tnode; + for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) + if (tnode->type == NODE_GROUP_OUTPUT) + tnode->flag &= ~NODE_DO_OUTPUT; + + node->flag |= NODE_DO_OUTPUT; + if (!was_output) + do_update = 1; + } /* tree specific activate calls */ if (ntree->type == NTREE_SHADER) { @@ -670,8 +599,10 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) node->flag |= NODE_DO_OUTPUT; if (was_output == 0) - ED_node_generic_update(bmain, ntree, node); + ED_node_tag_update_nodetree(bmain, ntree); } + else if (do_update) + ED_node_tag_update_nodetree(bmain, ntree); /* if active texture changed, free glsl materials */ if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) { @@ -698,7 +629,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) node->flag |= NODE_DO_OUTPUT; if (was_output == 0) - ED_node_generic_update(bmain, ntree, node); + ED_node_tag_update_nodetree(bmain, ntree); /* addnode() doesnt link this yet... */ node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); @@ -723,9 +654,11 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) tnode->flag &= ~NODE_DO_OUTPUT; node->flag |= NODE_DO_OUTPUT; - ED_node_generic_update(bmain, ntree, node); + ED_node_tag_update_nodetree(bmain, ntree); } } + else if (do_update) + ED_node_tag_update_nodetree(bmain, ntree); } else if (ntree->type == NTREE_TEXTURE) { // XXX @@ -762,7 +695,7 @@ static void edit_node_properties(wmOperatorType *ot) /* XXX could node be a context pointer? */ RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", ""); RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET); - RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Side", ""); + RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Side", ""); } static int edit_node_invoke_properties(bContext *C, wmOperator *op) @@ -874,7 +807,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); - bNode *node = editnode_get_active(snode->edittree); + bNode *node = nodeGetActive(snode->edittree); NodeSizeWidget *nsw = op->customdata; float mx, my, dx, dy; @@ -977,7 +910,7 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); - bNode *node = editnode_get_active(snode->edittree); + bNode *node = nodeGetActive(snode->edittree); int dir; if (node) { @@ -1056,33 +989,6 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) } } -/* return 0, nothing done */ -static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode *snode) -{ - bNode *gnode; - float mx = 0, my = 0; -// XXX int mval[2]; - - gnode = node_tree_get_editgroup(snode->nodetree); - if (gnode == NULL) return 0; - -// XXX getmouseco_areawin(mval); -// XXX areamouseco_to_ipoco(G.v2d, mval, &mx, &my); - - /* click in header or outside? */ - if (BLI_rctf_isect_pt(&gnode->totr, mx, my) == 0) { - rctf rect = gnode->totr; - - rect.ymax += NODE_DY; - if (BLI_rctf_isect_pt(&rect, mx, my) == 0) - snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */ -// else -// XXX transform_nodes(snode->nodetree, 'g', "Move group"); - - return 1; - } - return 0; -} /* checks snode->mouse position, and returns found node/socket */ /* type is SOCK_IN and/or SOCK_OUT */ @@ -1143,32 +1049,6 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so } } - /* check group sockets - * NB: using ngroup->outputs as input sockets and vice versa here! - */ - if (in_out & SOCK_IN) { - for (sock = snode->edittree->outputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { - *nodep = NULL; /* NULL node pointer indicates group socket */ - *sockp = sock; - return 1; - } - } - } - } - if (in_out & SOCK_OUT) { - for (sock = snode->edittree->inputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { - *nodep = NULL; /* NULL node pointer indicates group socket */ - *sockp = sock; - return 1; - } - } - } - } - return 0; } @@ -1215,7 +1095,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) * but operators and readfile.c do. */ id_us_plus(newnode->id); /* to ensure redraws or rerenders happen */ - ED_node_changed_update(snode->id, newnode); + ED_node_tag_update_id(snode->id); } } @@ -1276,9 +1156,9 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) /* has been set during copy above */ newnode = node->new_node; - node_deselect(node); + nodeSetSelected(node, FALSE); node->flag &= ~NODE_ACTIVE; - node_select(newnode); + nodeSetSelected(newnode, TRUE); } /* make sure we don't copy new nodes again! */ @@ -1312,6 +1192,8 @@ void NODE_OT_duplicate(wmOperatorType *ot) } int ED_node_select_check(ListBase *lb) + + { bNode *node; @@ -1456,6 +1338,7 @@ void NODE_OT_render_changed(wmOperatorType *ot) ot->flag = 0; } + /* ****************** Hide operator *********************** */ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) @@ -1962,8 +1845,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNode *gnode = node_tree_get_editgroup(snode->nodetree); - float gnode_x = 0.0f, gnode_y = 0.0f; bNode *node; bNodeLink *link, *newlink; @@ -1973,10 +1854,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) BKE_node_clipboard_clear(); BKE_node_clipboard_init(ntree); - /* get group node offset */ - if (gnode) - node_to_view(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y); - for (node = ntree->nodes.first; node; node = node->next) { if (node->flag & SELECT) { bNode *new_node; @@ -1999,12 +1876,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) nodeDetachNode(new_node); } } - - /* transform to basic view space. child node location is relative to parent */ - if (!new_node->parent) { - new_node->locx += gnode_x; - new_node->locy += gnode_y; - } } } @@ -2051,8 +1922,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNode *gnode = node_tree_get_editgroup(snode->nodetree); - float gnode_center[2]; const ListBase *clipboard_nodes_lb; const ListBase *clipboard_links_lb; bNode *node; @@ -2086,14 +1955,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) /* deselect old nodes */ node_deselect_all(snode); - /* get group node offset */ - if (gnode) { - node_to_view(gnode, 0.0f, 0.0f, &gnode_center[0], &gnode_center[1]); - } - else { - zero_v2(gnode_center); - } - /* calculate "barycenter" for placing on mouse cursor */ zero_v2(center); for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) { @@ -2110,7 +1971,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) id_us_plus(node->id); /* pasted nodes are selected */ - node_select(new_node); + nodeSetSelected(new_node, TRUE); } /* reparent copied nodes */ @@ -2118,13 +1979,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) bNode *new_node = node->new_node; if (new_node->parent) new_node->parent = new_node->parent->new_node; - - - /* place nodes around the mouse cursor. child nodes locations are relative to parent */ - if (!new_node->parent) { - new_node->locx += snode->cursor[0] - center[0] - gnode_center[0]; - new_node->locy += snode->cursor[1] - center[1] - gnode_center[1]; - } } for (link = clipboard_links_lb->first; link; link = link->next) { @@ -2167,15 +2021,195 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************** Shader Script Update ******************/ +/********************** Add interface socket operator *********************/ -typedef struct ScriptUpdateData { - RenderEngine *engine; - RenderEngineType *type; +static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb) +{ + bNodeSocket *sock; + for (sock = lb->first; sock; sock = sock->next) + if (sock->flag & SELECT) + return sock; + return NULL; +} - Text *text; - int found; -} ScriptUpdateData; +static int ntree_socket_add_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + int in_out = RNA_enum_get(op->ptr, "in_out"); + PointerRNA ntree_ptr; + bNodeSocket *sock, *tsock, *active_sock; + const char *default_name; + + RNA_id_pointer_create((ID *)ntree, &ntree_ptr); + + if (in_out == SOCK_IN) { + active_sock = ntree_get_active_interface_socket(&ntree->inputs); + default_name = "Input"; + } + else { + active_sock = ntree_get_active_interface_socket(&ntree->outputs); + default_name = "Output"; + } + + if (active_sock) { + /* insert a copy of the active socket right after it */ + sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name); + /* XXX this only works for actual sockets, not interface templates! */ + /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/ + } + else { + /* XXX TODO define default socket type for a tree! */ + sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name); + } + + /* deactivate sockets (has to check both lists) */ + for (tsock = ntree->inputs.first; tsock; tsock = tsock->next) + tsock->flag &= ~SELECT; + for (tsock = ntree->outputs.first; tsock; tsock = tsock->next) + tsock->flag &= ~SELECT; + /* make the new socket active */ + sock->flag |= SELECT; + + ntreeUpdateTree(ntree); + + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + + return OPERATOR_FINISHED; +} + +void NODE_OT_tree_socket_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Node Tree Interface Socket"; + ot->description = "Add an input or output socket to the current node tree"; + ot->idname = "NODE_OT_tree_socket_add"; + + /* api callbacks */ + ot->exec = ntree_socket_add_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Type", ""); +} + +/********************** Remove interface socket operator *********************/ + +static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + bNodeSocket *iosock, *active_sock; + + iosock = ntree_get_active_interface_socket(&ntree->inputs); + if (!iosock) + iosock = ntree_get_active_interface_socket(&ntree->outputs); + if (!iosock) + return OPERATOR_CANCELLED; + + /* preferably next socket becomes active, otherwise try previous socket */ + active_sock = (iosock->next ? iosock->next : iosock->prev); + ntreeRemoveSocketInterface(ntree, iosock); + + /* set active socket */ + if (active_sock) + active_sock->flag |= SELECT; + + ntreeUpdateTree(ntree); + + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + + return OPERATOR_FINISHED; +} + +void NODE_OT_tree_socket_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Node Tree Interface Socket"; + ot->description = "Remove an input or output socket to the current node tree"; + ot->idname = "NODE_OT_tree_socket_remove"; + + /* api callbacks */ + ot->exec = ntree_socket_remove_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/********************** Move interface socket operator *********************/ + +static EnumPropertyItem move_direction_items[] = { + { 1, "UP", 0, "Up", "" }, + { 2, "DOWN", 0, "Down", "" }, + { 0, NULL, 0, NULL, NULL }, +}; + +static int ntree_socket_move_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + int direction = RNA_enum_get(op->ptr, "direction"); + bNodeSocket *iosock; + ListBase *lb; + + lb = &ntree->inputs; + iosock = ntree_get_active_interface_socket(lb); + if (!iosock) { + lb = &ntree->outputs; + iosock = ntree_get_active_interface_socket(lb); + } + if (!iosock) + return OPERATOR_CANCELLED; + + switch (direction) { + case 1: { /* up */ + bNodeSocket *before = iosock->prev; + BLI_remlink(lb, iosock); + if (before) + BLI_insertlinkbefore(lb, before, iosock); + else + BLI_addhead(lb, iosock); + break; + } + case 2: { /* down */ + bNodeSocket *after = iosock->next; + BLI_remlink(lb, iosock); + if (after) + BLI_insertlinkafter(lb, after, iosock); + else + BLI_addtail(lb, iosock); + break; + } + } + + ntreeUpdateTree(ntree); + + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + + return OPERATOR_FINISHED; +} + +void NODE_OT_tree_socket_move(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Move Node Tree Socket"; + ot->description = "Move a socket up or down in the current node tree's sockets stack"; + ot->idname = "NODE_OT_tree_socket_move"; + + /* api callbacks */ + ot->exec = ntree_socket_move_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", ""); +} + +/* ********************** Shader Script Update ******************/ static int node_shader_script_update_poll(bContext *C) { @@ -2208,64 +2242,79 @@ static int node_shader_script_update_poll(bContext *C) return 0; } -static void node_shader_script_update_text(void *data_, ID *UNUSED(id), bNodeTree *ntree) +/* recursively check for script nodes in groups using this text and update */ +static int node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text) { - ScriptUpdateData *data = (ScriptUpdateData *)data_; + int found = FALSE; bNode *node; - + + ntree->done = TRUE; + /* update each script that is using this text datablock */ for (node = ntree->nodes.first; node; node = node->next) { if (node->type == NODE_GROUP) { - node_shader_script_update_text(data_, NULL, (bNodeTree *)node->id); + bNodeTree *ngroup = (bNodeTree *)node->id; + if (ngroup && !ngroup->done) + found |= node_shader_script_update_text_recursive(engine, type, ngroup, text); } - else if (node->type == SH_NODE_SCRIPT && node->id == &data->text->id) { - data->type->update_script_node(data->engine, ntree, node); - data->found = TRUE; + else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) { + type->update_script_node(engine, ntree, node); + found = TRUE; } } + + return found; } static int node_shader_script_update_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - ScriptUpdateData data; PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript); + RenderEngine *engine; + RenderEngineType *type; + int found = FALSE; /* setup render engine */ - data.type = RE_engines_find(scene->r.engine); - data.engine = RE_engine_create(data.type); - data.engine->reports = op->reports; - data.text = NULL; - data.found = FALSE; + type = RE_engines_find(scene->r.engine); + engine = RE_engine_create(type); + engine->reports = op->reports; if (nodeptr.data) { /* update single node */ bNodeTree *ntree = nodeptr.id.data; bNode *node = nodeptr.data; - data.type->update_script_node(data.engine, ntree, node); + type->update_script_node(engine, ntree, node); - data.found = TRUE; + found = TRUE; } else { /* update all nodes using text datablock */ - data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; - - if (data.text) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); - - if (ntreetype && ntreetype->foreach_nodetree) - ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text); + Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; + + if (text) { + /* clear flags for recursion check */ + FOREACH_NODETREE(bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) + ntree->done = FALSE; + } FOREACH_NODETREE_END + + FOREACH_NODETREE(bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + if (!ntree->done) + found |= node_shader_script_update_text_recursive(engine, type, ntree, text); + } + } FOREACH_NODETREE_END - if (!data.found) + if (!found) BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done"); } } - RE_engine_free(data.engine); + RE_engine_free(engine); - return (data.found)? OPERATOR_FINISHED: OPERATOR_CANCELLED; + return (found)? OPERATOR_FINISHED: OPERATOR_CANCELLED; } void NODE_OT_shader_script_update(wmOperatorType *ot) diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 6696284b169..10f9718f1b6 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -66,85 +66,132 @@ #include "UI_resources.h" #include "node_intern.h" /* own include */ +#include "NOD_common.h" #include "NOD_socket.h" -static EnumPropertyItem socket_in_out_items[] = { - { SOCK_IN, "SOCK_IN", 0, "Input", "" }, - { SOCK_OUT, "SOCK_OUT", 0, "Output", "" }, - { 0, NULL, 0, NULL, NULL }, -}; - -/* ***************** Edit Group operator ************* */ - -void snode_make_group_editable(SpaceNode *snode, bNode *gnode) +/* define common group node operator properties */ +static void node_group_operator_properties(wmOperatorType *ot) { - bNode *node; - - /* make sure nothing has group editing on */ - for (node = snode->nodetree->nodes.first; node; node = node->next) { - nodeGroupEditClear(node); + /* NB: not using an enum here, because that it would have to use an item callback and thus require + * copying of identifier strings anyway. node_type is not a user option, just a way of allowing + * node group operators to work on different types of group nodes. + */ + RNA_def_string(ot->srna, "node_type", "", 0, "Node Type", "Group node type the operator works on"); +} - /* while we're here, clear texture active */ - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { - /* this is not 100% sure to be reliable, see comment on the flag */ - node->flag &= ~NODE_ACTIVE_TEXTURE; - } +/* Internal poll functions so group node operators can work with different group node types. + * This checks the operator node type property and looks up the respective types. + * If this function returns FALSE the operator should return PASS_THROUGH to allow other variants. + */ +static int node_group_operator_check_type(bContext *C, wmOperator *op, char **r_node_idname, char **r_ntree_idname) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + PropertyRNA *ntype_prop = RNA_struct_find_property(op->ptr, "node_type"); + char *node_idname, *ntree_idname; + bNodeType *ntype; + bNodeTreeType *ntreetype; + + if (!RNA_property_is_set(op->ptr, ntype_prop)) { + BKE_report(op->reports, RPT_ERROR, "Group node type not set"); + return FALSE; } - - if (gnode == NULL) { - /* with NULL argument we do a toggle */ - if (snode->edittree == snode->nodetree) - gnode = nodeGetActive(snode->nodetree); + + node_idname = RNA_property_string_get_alloc(op->ptr, ntype_prop, NULL, 0, NULL); + ntype = nodeTypeFind(node_idname); + if (!ntype) { + BKE_reportf(op->reports, RPT_ERROR, "Group node type %s undefined", node_idname); + MEM_freeN(node_idname); + return FALSE; } - - if (gnode) { - snode->edittree = nodeGroupEditSet(gnode, 1); - - /* deselect all other nodes, so we can also do grabbing of entire subtree */ - for (node = snode->nodetree->nodes.first; node; node = node->next) { - node_deselect(node); - - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { - /* this is not 100% sure to be reliable, see comment on the flag */ - node->flag &= ~NODE_ACTIVE_TEXTURE; - } - } - node_select(gnode); + + if (!ntype->poll(ntype, ntree)) { + MEM_freeN(node_idname); + return FALSE; } + + ntree_idname = BLI_strdup(ntype->group_tree_idname); + ntreetype = ntreeTypeFind(ntree_idname); + if (!ntreetype) { + BKE_reportf(op->reports, RPT_ERROR, "Group node tree type %s undefined", ntree_idname); + MEM_freeN(node_idname); + MEM_freeN(ntree_idname); + return FALSE; + } + + if (r_node_idname) + *r_node_idname = node_idname; + else + MEM_freeN(node_idname); + + if (r_ntree_idname) + *r_ntree_idname = ntree_idname; else - snode->edittree = snode->nodetree; + MEM_freeN(ntree_idname); + + return TRUE; } -static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op)) +static bNode *node_group_get_active(bContext *C, const char *node_idname) { SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + if (node && STREQ(node->idname, node_idname)) + return node; + else + return NULL; +} - ED_preview_kill_jobs(C); +/* ***************** Edit Group operator ************* */ - if (snode->nodetree == snode->edittree) { - bNode *gnode = nodeGetActive(snode->edittree); - snode_make_group_editable(snode, gnode); +static int node_group_edit_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + char *node_idname; + bNode *gnode; + int exit = RNA_boolean_get(op->ptr, "exit"); + + ED_preview_kill_jobs(C); + + if (!node_group_operator_check_type(C, op, &node_idname, NULL)) + return OPERATOR_PASS_THROUGH; + + gnode = node_group_get_active(C, node_idname); + MEM_freeN(node_idname); + + if (gnode && !exit) { + bNodeTree *ngroup = (bNodeTree *)gnode->id; + + if (ngroup) { + if (ngroup->id.lib) + ntreeMakeLocal(ngroup); + + ED_node_tree_push(snode, ngroup, gnode); + } } else - snode_make_group_editable(snode, NULL); - + ED_node_tree_pop(snode); + WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL); - + return OPERATOR_FINISHED; } static int node_group_edit_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - SpaceNode *snode = CTX_wm_space_node(C); + char *node_idname; bNode *gnode; - - /* XXX callback? */ - if (snode->nodetree == snode->edittree) { - gnode = nodeGetActive(snode->edittree); - if (gnode && gnode->id && GS(gnode->id->name) == ID_NT && gnode->id->lib) { - uiPupMenuOkee(C, op->type->idname, "Make group local?"); - return OPERATOR_CANCELLED; - } + + if (!node_group_operator_check_type(C, op, &node_idname, NULL)) + return OPERATOR_PASS_THROUGH; + + gnode = node_group_get_active(C, node_idname); + MEM_freeN(node_idname); + + if (gnode && gnode->id && gnode->id->lib) { + WM_operator_confirm_message(C, op, "Make group local?"); + return OPERATOR_CANCELLED; } return node_group_edit_exec(C, op); @@ -156,258 +203,17 @@ void NODE_OT_group_edit(wmOperatorType *ot) ot->name = "Edit Group"; ot->description = "Edit node group"; ot->idname = "NODE_OT_group_edit"; - + /* api callbacks */ ot->invoke = node_group_edit_invoke; ot->exec = node_group_edit_exec; ot->poll = ED_operator_node_active; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* ***************** Add Group Socket operator ************* */ - -static int node_group_socket_add_exec(bContext *C, wmOperator *op) -{ - SpaceNode *snode = CTX_wm_space_node(C); - int in_out = -1; - char name[MAX_NAME] = ""; - int type = SOCK_FLOAT; - bNodeTree *ngroup = snode->edittree; - /* bNodeSocket *sock; */ /* UNUSED */ - - ED_preview_kill_jobs(C); - - if (RNA_struct_property_is_set(op->ptr, "name")) - RNA_string_get(op->ptr, "name", name); - - if (RNA_struct_property_is_set(op->ptr, "type")) - type = RNA_enum_get(op->ptr, "type"); - - if (RNA_struct_property_is_set(op->ptr, "in_out")) - in_out = RNA_enum_get(op->ptr, "in_out"); - else - return OPERATOR_CANCELLED; - - /* using placeholder subtype first */ - /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out); - - ntreeUpdateTree(ngroup); - - snode_notify(C, snode); - - return OPERATOR_FINISHED; -} - -void NODE_OT_group_socket_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Add Group Socket"; - ot->description = "Add node group socket"; - ot->idname = "NODE_OT_group_socket_add"; - - /* api callbacks */ - ot->exec = node_group_socket_add_exec; - ot->poll = ED_operator_node_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output"); - RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name"); - RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket"); -} - -/* ***************** Remove Group Socket operator ************* */ - -static int node_group_socket_remove_exec(bContext *C, wmOperator *op) -{ - SpaceNode *snode = CTX_wm_space_node(C); - int index = -1; - int in_out = -1; - bNodeTree *ngroup = snode->edittree; - bNodeSocket *sock; - - ED_preview_kill_jobs(C); - - if (RNA_struct_property_is_set(op->ptr, "index")) - index = RNA_int_get(op->ptr, "index"); - else - return OPERATOR_CANCELLED; - - if (RNA_struct_property_is_set(op->ptr, "in_out")) - in_out = RNA_enum_get(op->ptr, "in_out"); - else - return OPERATOR_CANCELLED; - - sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index); - if (sock) { - node_group_remove_socket(ngroup, sock, in_out); - ntreeUpdateTree(ngroup); - - snode_notify(C, snode); - } - - return OPERATOR_FINISHED; -} - -void NODE_OT_group_socket_remove(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Remove Group Socket"; - ot->description = "Remove a node group socket"; - ot->idname = "NODE_OT_group_socket_remove"; - - /* api callbacks */ - ot->exec = node_group_socket_remove_exec; - ot->poll = ED_operator_node_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX); - RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output"); -} - -/* ***************** Move Group Socket Up operator ************* */ - -static int node_group_socket_move_up_exec(bContext *C, wmOperator *op) -{ - SpaceNode *snode = CTX_wm_space_node(C); - int index = -1; - int in_out = -1; - bNodeTree *ngroup = snode->edittree; - bNodeSocket *sock, *prev; - - ED_preview_kill_jobs(C); - - if (RNA_struct_property_is_set(op->ptr, "index")) - index = RNA_int_get(op->ptr, "index"); - else - return OPERATOR_CANCELLED; - - if (RNA_struct_property_is_set(op->ptr, "in_out")) - in_out = RNA_enum_get(op->ptr, "in_out"); - else - return OPERATOR_CANCELLED; - - /* swap */ - if (in_out == SOCK_IN) { - sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index); - prev = sock->prev; - /* can't move up the first socket */ - if (!prev) - return OPERATOR_CANCELLED; - BLI_remlink(&ngroup->inputs, sock); - BLI_insertlinkbefore(&ngroup->inputs, prev, sock); - - ngroup->update |= NTREE_UPDATE_GROUP_IN; - } - else if (in_out == SOCK_OUT) { - sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index); - prev = sock->prev; - /* can't move up the first socket */ - if (!prev) - return OPERATOR_CANCELLED; - BLI_remlink(&ngroup->outputs, sock); - BLI_insertlinkbefore(&ngroup->outputs, prev, sock); - - ngroup->update |= NTREE_UPDATE_GROUP_OUT; - } - ntreeUpdateTree(ngroup); - - snode_notify(C, snode); - - return OPERATOR_FINISHED; -} - -void NODE_OT_group_socket_move_up(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Move Group Socket Up"; - ot->description = "Move up node group socket"; - ot->idname = "NODE_OT_group_socket_move_up"; - - /* api callbacks */ - ot->exec = node_group_socket_move_up_exec; - ot->poll = ED_operator_node_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX); - RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output"); -} - -/* ***************** Move Group Socket Up operator ************* */ - -static int node_group_socket_move_down_exec(bContext *C, wmOperator *op) -{ - SpaceNode *snode = CTX_wm_space_node(C); - int index = -1; - int in_out = -1; - bNodeTree *ngroup = snode->edittree; - bNodeSocket *sock, *next; - - ED_preview_kill_jobs(C); - - if (RNA_struct_property_is_set(op->ptr, "index")) - index = RNA_int_get(op->ptr, "index"); - else - return OPERATOR_CANCELLED; - - if (RNA_struct_property_is_set(op->ptr, "in_out")) - in_out = RNA_enum_get(op->ptr, "in_out"); - else - return OPERATOR_CANCELLED; - - /* swap */ - if (in_out == SOCK_IN) { - sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index); - next = sock->next; - /* can't move down the last socket */ - if (!next) - return OPERATOR_CANCELLED; - BLI_remlink(&ngroup->inputs, sock); - BLI_insertlinkafter(&ngroup->inputs, next, sock); - - ngroup->update |= NTREE_UPDATE_GROUP_IN; - } - else if (in_out == SOCK_OUT) { - sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index); - next = sock->next; - /* can't move down the last socket */ - if (!next) - return OPERATOR_CANCELLED; - BLI_remlink(&ngroup->outputs, sock); - BLI_insertlinkafter(&ngroup->outputs, next, sock); - - ngroup->update |= NTREE_UPDATE_GROUP_OUT; - } - ntreeUpdateTree(ngroup); - - snode_notify(C, snode); - - return OPERATOR_FINISHED; -} - -void NODE_OT_group_socket_move_down(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Move Group Socket Down"; - ot->description = "Move down node group socket"; - ot->idname = "NODE_OT_group_socket_move_down"; - - /* api callbacks */ - ot->exec = node_group_socket_move_down_exec; - ot->poll = ED_operator_node_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX); - RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output"); + + node_group_operator_properties(ot); + RNA_def_boolean(ot->srna, "exit", FALSE, "Exit", ""); } /* ******************** Ungroup operator ********************** */ @@ -415,180 +221,185 @@ void NODE_OT_group_socket_move_down(wmOperatorType *ot) /* returns 1 if its OK */ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) { - bNodeLink *link, *linkn; - bNode *node, *nextn; + bNodeLink *link, *linkn, *tlink; + bNode *node, *nextnode; bNodeTree *ngroup, *wgroup; ListBase anim_basepaths = {NULL, NULL}; - + ngroup = (bNodeTree *)gnode->id; - if (ngroup == NULL) return 0; - + /* clear new pointers, set in copytree */ for (node = ntree->nodes.first; node; node = node->next) node->new_node = NULL; - + /* wgroup is a temporary copy of the NodeTree we're merging in * - all of wgroup's nodes are transferred across to their new home * - ngroup (i.e. the source NodeTree) is left unscathed * - temp copy. don't change ID usercount */ wgroup = ntreeCopyTree_ex(ngroup, FALSE); - - /* add the nodes into the ntree */ - for (node = wgroup->nodes.first; node; node = nextn) { - nextn = node->next; - - /* keep track of this node's RNA "base" path (the part of the path identifying the node) + + /* Add the nodes into the ntree */ + for (node = wgroup->nodes.first; node; node = nextnode) { + nextnode = node->next; + + /* Remove interface nodes. + * This also removes remaining links to and from interface nodes. + */ + if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { + nodeFreeNode(wgroup, node); + continue; + } + + /* keep track of this node's RNA "base" path (the part of the path identifying the node) * if the old nodetree has animation data which potentially covers this node */ if (wgroup->adt) { PointerRNA ptr; char *path; - + RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr); path = RNA_path_from_ID_to_struct(&ptr); - + if (path) BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); } - + /* migrate node */ BLI_remlink(&wgroup->nodes, node); BLI_addtail(&ntree->nodes, node); - - /* ensure unique node name in the nodee tree */ + + /* ensure unique node name in the node tree */ nodeUniqueName(ntree, node); - + if (!node->parent) { node->locx += gnode->locx; node->locy += gnode->locy; } - + node->flag |= NODE_SELECT; } - - /* restore external links to and from the gnode */ - for (link = ntree->links.first; link; link = link->next) { - if (link->fromnode == gnode) { - if (link->fromsock->groupsock) { - bNodeSocket *gsock = link->fromsock->groupsock; - if (gsock->link) { - if (gsock->link->fromnode) { - /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */ - link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL); - link->fromsock = gsock->link->fromsock->new_sock; - } - else { - /* group output directly maps to group input */ - bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock); - if (insock->link) { - link->fromnode = insock->link->fromnode; - link->fromsock = insock->link->fromsock; - } - } - } - else { - /* copy the default input value from the group socket default to the external socket */ - node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value); - } - } - } - } - /* remove internal output links, these are not used anymore */ - for (link = wgroup->links.first; link; link = linkn) { - linkn = link->next; - if (!link->tonode) - nodeRemLink(wgroup, link); - } - /* restore links from internal nodes */ - for (link = wgroup->links.first; link; link = linkn) { - linkn = link->next; - /* indicates link to group input */ - if (!link->fromnode) { - /* NB: can't use find_group_node_input here, - * because gnode sockets still point to the old tree! - */ - bNodeSocket *insock; - for (insock = gnode->inputs.first; insock; insock = insock->next) - if (insock->groupsock->new_sock == link->fromsock) - break; - if (insock->link) { - link->fromnode = insock->link->fromnode; - link->fromsock = insock->link->fromsock; - } - else { - /* copy the default input value from the group node socket default to the internal socket */ - node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value); - nodeRemLink(wgroup, link); - } - } - } - - /* add internal links to the ntree */ + + /* Add internal links to the ntree */ for (link = wgroup->links.first; link; link = linkn) { linkn = link->next; BLI_remlink(&wgroup->links, link); BLI_addtail(&ntree->links, link); } - + /* and copy across the animation, * note that the animation data's action can be NULL here */ if (wgroup->adt) { LinkData *ld, *ldn = NULL; bAction *waction; - + /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */ waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action); - + /* now perform the moving */ BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths); - + /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { ldn = ld->next; - + MEM_freeN(ld->data); BLI_freelinkN(&anim_basepaths, ld); } - + /* free temp action too */ if (waction) { BKE_libblock_free(&G.main->action, waction); } } - - /* delete the group instance. this also removes old input links! */ - nodeFreeNode(ntree, gnode); - + /* free the group tree (takes care of user count) */ BKE_libblock_free(&G.main->nodetree, wgroup); - + + /* restore external links to and from the gnode */ + /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node), + * then transferred to ntree (new_node pointers remain valid). + */ + + /* input links */ + for (link = ngroup->links.first; link; link = link->next) { + if (link->fromnode->type == NODE_GROUP_INPUT) { + const char *identifier = link->fromsock->identifier; + int num_external_links = 0; + + /* find external links to this input */ + for (tlink = ntree->links.first; tlink; tlink = tlink->next) { + if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) { + nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode->new_node, link->tosock->new_sock); + ++num_external_links; + } + } + + /* if group output is not externally linked, + * convert the constant input value to ensure somewhat consistent behavior */ + if (num_external_links == 0) { + bNodeSocket *sock = node_group_find_input_socket(gnode, identifier); + BLI_assert(sock); + + /* XXX TODO nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node, ntree, sock, gnode);*/ + } + } + } + + /* output links */ + for (link = ntree->links.first; link; link = link->next) { + if (link->fromnode == gnode) { + const char *identifier = link->fromsock->identifier; + int num_internal_links = 0; + + /* find internal links to this output */ + for (tlink = ngroup->links.first; tlink; tlink = tlink->next) { + /* only use active output node */ + if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) { + if (STREQ(tlink->tosock->identifier, identifier)) { + nodeAddLink(ntree, tlink->fromnode->new_node, tlink->fromsock->new_sock, link->tonode, link->tosock); + ++num_internal_links; + } + } + } + + /* if group output is not internally linked, + * convert the constant output value to ensure somewhat consistent behavior */ + if (num_internal_links == 0) { + bNodeSocket *sock = node_group_find_output_socket(gnode, identifier); + BLI_assert(sock); + + /* XXX TODO nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */ + } + } + } + + /* delete the group instance */ + nodeFreeNode(ntree, gnode); + ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; - + return 1; } + static int node_group_ungroup_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); + char *node_idname; bNode *gnode; ED_preview_kill_jobs(C); - /* are we inside of a group? */ - gnode = node_tree_get_editgroup(snode->nodetree); - if (gnode) - snode_make_group_editable(snode, NULL); - - gnode = nodeGetActive(snode->edittree); - if (gnode == NULL) + if (!node_group_operator_check_type(C, op, &node_idname, NULL)) + return OPERATOR_PASS_THROUGH; + + gnode = node_group_get_active(C, node_idname); + MEM_freeN(node_idname); + if (!gnode) return OPERATOR_CANCELLED; - - if (gnode->type != NODE_GROUP) { - BKE_report(op->reports, RPT_WARNING, "Not a group"); - return OPERATOR_CANCELLED; - } - else if (node_group_ungroup(snode->nodetree, gnode)) { + + if (gnode->id && node_group_ungroup(snode->edittree, gnode)) { ntreeUpdateTree(snode->nodetree); } else { @@ -608,93 +419,92 @@ void NODE_OT_group_ungroup(wmOperatorType *ot) ot->name = "Ungroup"; ot->description = "Ungroup selected nodes"; ot->idname = "NODE_OT_group_ungroup"; - + /* api callbacks */ ot->exec = node_group_ungroup_exec; ot->poll = ED_operator_node_active; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + node_group_operator_properties(ot); } /* ******************** Separate operator ********************** */ /* returns 1 if its OK */ -static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy) +static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy) { bNodeLink *link, *link_next; bNode *node, *node_next, *newnode; - bNodeTree *ngroup; ListBase anim_basepaths = {NULL, NULL}; - - ngroup = (bNodeTree *)gnode->id; - if (ngroup == NULL) return 0; - + /* deselect all nodes in the target tree */ for (node = ntree->nodes.first; node; node = node->next) - node_deselect(node); - + nodeSetSelected(node, FALSE); + /* clear new pointers, set in nodeCopyNode */ for (node = ngroup->nodes.first; node; node = node->next) node->new_node = NULL; - + /* add selected nodes into the ntree */ for (node = ngroup->nodes.first; node; node = node_next) { node_next = node->next; - if (node->flag & NODE_SELECT) { - - if (make_copy) { - /* make a copy */ - newnode = nodeCopyNode(ngroup, node); - } - else { - /* use the existing node */ - newnode = node; - } - - /* keep track of this node's RNA "base" path (the part of the path identifying the node) - * if the old nodetree has animation data which potentially covers this node - */ - if (ngroup->adt) { - PointerRNA ptr; - char *path; - - RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr); - path = RNA_path_from_ID_to_struct(&ptr); - - if (path) - BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); - } - - /* ensure valid parent pointers, detach if parent stays inside the group */ - if (newnode->parent && !(newnode->parent->flag & NODE_SELECT)) - nodeDetachNode(newnode); - - /* migrate node */ - BLI_remlink(&ngroup->nodes, newnode); - BLI_addtail(&ntree->nodes, newnode); + if (!(node->flag & NODE_SELECT)) + continue; + + /* ignore interface nodes */ + if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { + nodeSetSelected(node, FALSE); + continue; + } + + if (make_copy) { + /* make a copy */ + newnode = nodeCopyNode(ngroup, node); + } + else { + /* use the existing node */ + newnode = node; + } + + /* keep track of this node's RNA "base" path (the part of the path identifying the node) + * if the old nodetree has animation data which potentially covers this node + */ + if (ngroup->adt) { + PointerRNA ptr; + char *path; - /* ensure unique node name in the node tree */ - nodeUniqueName(ntree, newnode); + RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr); + path = RNA_path_from_ID_to_struct(&ptr); - if (!newnode->parent) { - newnode->locx += gnode->locx; - newnode->locy += gnode->locy; - } + if (path) + BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); } - else { - /* ensure valid parent pointers, detach if child stays inside the group */ - if (node->parent && (node->parent->flag & NODE_SELECT)) - nodeDetachNode(node); + + /* ensure valid parent pointers, detach if parent stays inside the group */ + if (newnode->parent && !(newnode->parent->flag & NODE_SELECT)) + nodeDetachNode(newnode); + + /* migrate node */ + BLI_remlink(&ngroup->nodes, newnode); + BLI_addtail(&ntree->nodes, newnode); + + /* ensure unique node name in the node tree */ + nodeUniqueName(ntree, newnode); + + if (!newnode->parent) { + newnode->locx += offx; + newnode->locy += offy; } } - + /* add internal links to the ntree */ for (link = ngroup->links.first; link; link = link_next) { int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT)); int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT)); link_next = link->next; - + if (make_copy) { /* make a copy of internal links */ if (fromselect && toselect) @@ -711,28 +521,28 @@ static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make } } } - + /* and copy across the animation, * note that the animation data's action can be NULL here */ if (ngroup->adt) { LinkData *ld, *ldn = NULL; - + /* now perform the moving */ BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths); - + /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { ldn = ld->next; - + MEM_freeN(ld->data); BLI_freelinkN(&anim_basepaths, ld); } } - + ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; if (!make_copy) ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; - + return 1; } @@ -751,56 +561,64 @@ EnumPropertyItem node_group_separate_types[] = { static int node_group_separate_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); - bNode *gnode; + bNodeTree *ngroup, *nparent; int type = RNA_enum_get(op->ptr, "type"); + float offx, offy; ED_preview_kill_jobs(C); /* are we inside of a group? */ - gnode = node_tree_get_editgroup(snode->nodetree); - if (!gnode) { + ngroup = snode->edittree; + nparent = ED_node_tree_get(snode, 1); + if (!nparent) { BKE_report(op->reports, RPT_WARNING, "Not inside node group"); return OPERATOR_CANCELLED; } - + /* get node tree offset */ + snode_group_offset(snode, &offx, &offy); + switch (type) { case NODE_GS_COPY: - if (!node_group_separate_selected(snode->nodetree, gnode, 1)) { + if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) { BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } break; case NODE_GS_MOVE: - if (!node_group_separate_selected(snode->nodetree, gnode, 0)) { + if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) { BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } break; } - + /* switch to parent tree */ - snode_make_group_editable(snode, NULL); - + ED_node_tree_pop(snode); + ntreeUpdateTree(snode->nodetree); - + snode_notify(C, snode); snode_dag_update(C, snode); return OPERATOR_FINISHED; } -static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +static int node_group_separate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE); - uiLayout *layout = uiPupMenuLayout(pup); - - uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); - uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY); - uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE); - - uiPupMenuEnd(C, pup); - - return OPERATOR_CANCELLED; + if (!node_group_operator_check_type(C, op, NULL, NULL)) + return OPERATOR_PASS_THROUGH; + else { + uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE); + uiLayout *layout = uiPupMenuLayout(pup); + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); + uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY); + uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE); + + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; + } } void NODE_OT_group_separate(wmOperatorType *ot) @@ -809,162 +627,183 @@ void NODE_OT_group_separate(wmOperatorType *ot) ot->name = "Separate"; ot->description = "Separate selected nodes from the node group"; ot->idname = "NODE_OT_group_separate"; - + /* api callbacks */ ot->invoke = node_group_separate_invoke; ot->exec = node_group_separate_exec; ot->poll = ED_operator_node_active; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + + node_group_operator_properties(ot); RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", ""); } /* ****************** Make Group operator ******************* */ -static int node_group_make_test(bNodeTree *ntree, bNode *gnode) +static bool node_group_make_use_node(bNode *node, bNode *gnode) { + return (node != gnode && + !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT) && + (node->flag & NODE_SELECT)); +} + +static bool node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const char *ntree_idname, struct ReportList *reports) +{ + bNodeTree *ngroup; bNode *node; bNodeLink *link; - int totnode = 0; - - /* is there something to group? also do some clearing */ + int ok = true; + + /* make a local pseudo node tree to pass to the node poll functions */ + ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname); + + /* check poll functions for selected nodes */ for (node = ntree->nodes.first; node; node = node->next) { - if (node == gnode) - continue; - - if (node->flag & NODE_SELECT) { - /* no groups in groups */ - if (node->type == NODE_GROUP) - return 0; - totnode++; + if (node_group_make_use_node(node, gnode)) { + if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup)) { + BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name); + ok = false; + break; + } } node->done = 0; } - if (totnode == 0) return 0; - + + /* free local pseudo node tree again */ + ntreeFreeTree(ngroup); + MEM_freeN(ngroup); + if (!ok) + return false; + /* check if all connections are OK, no unselected node has both * inputs and outputs to a selection */ for (link = ntree->links.first; link; link = link->next) { - if (link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT && link->fromnode != gnode) + if (node_group_make_use_node(link->fromnode, gnode)) link->tonode->done |= 1; - if (link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT && link->tonode != gnode) + if (node_group_make_use_node(link->tonode, gnode)) link->fromnode->done |= 2; } - for (node = ntree->nodes.first; node; node = node->next) { - if (node == gnode) - continue; - if ((node->flag & NODE_SELECT) == 0) - if (node->done == 3) - break; + if (!(node->flag & NODE_SELECT) && + node != gnode && + node->done == 3) + { + return false; + } } - if (node) - return 0; - - return 1; + return true; } - -static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max) +static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max) { bNode *node; float loc[2]; + int totselect = 0; + INIT_MINMAX2(min, max); for (node = ntree->nodes.first; node; node = node->next) { - if (node == gnode) - continue; - if (node->flag & NODE_SELECT) { + if (node_group_make_use_node(node, gnode)) { nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]); minmax_v2v2_v2(min, max, loc); + ++totselect; } } + + /* sane min/max if no selected nodes */ + if (totselect == 0) { + min[0] = min[1] = max[0] = max[1] = 0.0f; + } + + return totselect; } -static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode) +static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode) { bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeLink *link, *linkn; bNode *node, *nextn; - bNodeSocket *gsock, *sock; + bNodeSocket *sock; ListBase anim_basepaths = {NULL, NULL}; - float min[2], max[2]; - + float min[2], max[2], center[2]; + int totselect; + int expose_all = FALSE; + bNode *input_node = NULL, *output_node = NULL; /* lazy initialized, in case there are no external links */ + + /* XXX rough guess, not nice but we don't have access to UI constants here ... */ + static const float offsetx = 200; + static const float offsety = 0.0f; + /* deselect all nodes in the target tree */ for (node = ngroup->nodes.first; node; node = node->next) - node_deselect(node); - - node_get_selected_minmax(ntree, gnode, min, max); - + nodeSetSelected(node, FALSE); + + totselect = node_get_selected_minmax(ntree, gnode, min, max); + add_v2_v2v2(center, min, max); + mul_v2_fl(center, 0.5f); + + /* auto-add interface for "solo" nodes */ + if (totselect == 1) + expose_all = TRUE; + /* move nodes over */ for (node = ntree->nodes.first; node; node = nextn) { nextn = node->next; - if (node == gnode) - continue; - if (node->flag & NODE_SELECT) { - /* keep track of this node's RNA "base" path (the part of the pat identifying the node) + if (node_group_make_use_node(node, gnode)) { + /* keep track of this node's RNA "base" path (the part of the pat identifying the node) * if the old nodetree has animation data which potentially covers this node */ if (ntree->adt) { PointerRNA ptr; char *path; - + RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); path = RNA_path_from_ID_to_struct(&ptr); - + if (path) BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); } - + /* ensure valid parent pointers, detach if parent stays outside the group */ if (node->parent && !(node->parent->flag & NODE_SELECT)) nodeDetachNode(node); - + /* change node-collection membership */ BLI_remlink(&ntree->nodes, node); BLI_addtail(&ngroup->nodes, node); - + /* ensure unique node name in the ngroup */ nodeUniqueName(ngroup, node); - - if (!node->parent) { - node->locx -= 0.5f * (min[0] + max[0]); - node->locy -= 0.5f * (min[1] + max[1]); - } - } - else { - /* if the parent is to be inserted but not the child, detach properly */ - if (node->parent && (node->parent->flag & NODE_SELECT)) - nodeDetachNode(node); } } - + /* move animation data over */ if (ntree->adt) { LinkData *ld, *ldn = NULL; - + BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); - + /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { ldn = ld->next; - + MEM_freeN(ld->data); BLI_freelinkN(&anim_basepaths, ld); } } - + /* node groups don't use internal cached data */ ntreeFreeCache(ngroup); - + /* relink external sockets */ for (link = ntree->links.first; link; link = linkn) { - int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT) && link->fromnode != gnode); - int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT) && link->tonode != gnode); + int fromselect = node_group_make_use_node(link->fromnode, gnode); + int toselect = node_group_make_use_node(link->tonode, gnode); + linkn = link->next; - + if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) { /* remove all links to/from the gnode. * this can remove link information, but there's no general way to preserve it. @@ -976,58 +815,123 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode) BLI_addtail(&ngroup->links, link); } else if (toselect) { - gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN); - link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock); - link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock); + bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock); + bNodeSocket *input_sock; + + /* lazy init */ + if (!input_node) { + input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT); + + input_node->locx = min[0] - center[0] - offsetx; + input_node->locy = -offsety; + } + /* update the group node and interface node sockets, + * so the new interface socket can be linked. + */ + node_group_verify(ntree, gnode, (ID *)ngroup); + node_group_input_verify(ngroup, input_node, (ID *)ngroup); + + /* create new internal link */ + input_sock = node_group_input_find_socket(input_node, iosock->identifier); + nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock); + + /* redirect external link */ link->tonode = gnode; + link->tosock = node_group_find_input_socket(gnode, iosock->identifier); } else if (fromselect) { - /* search for existing group node socket */ - for (gsock = ngroup->outputs.first; gsock; gsock = gsock->next) - if (gsock->link && gsock->link->fromsock == link->fromsock) - break; - if (!gsock) { - gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT); - gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock); - link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock); + bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->fromnode, link->fromsock); + bNodeSocket *output_sock; + + /* lazy init */ + if (!output_node) { + output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT); + + output_node->locx = max[0] - center[0] + offsetx; + output_node->locy = -offsety; } - else - link->fromsock = node_group_find_output(gnode, gsock); + /* update the group node and interface node sockets, + * so the new interface socket can be linked. + */ + node_group_verify(ntree, gnode, (ID *)ngroup); + node_group_output_verify(ngroup, output_node, (ID *)ngroup); + + /* create new internal link */ + output_sock = node_group_output_find_socket(output_node, iosock->identifier); + nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock); + + /* redirect external link */ link->fromnode = gnode; + link->fromsock = node_group_find_output_socket(gnode, iosock->identifier); } } - /* auto-add interface for "solo" nodes */ - node = ((bNodeTree *)gnode->id)->nodes.first; - if (node && !node->next) { - for (sock = node->inputs.first; sock; sock = sock->next) { - int skip = FALSE; - - for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next) - if (link->tosock == sock) - skip = TRUE; - - if (skip == TRUE) - continue; - - gsock = node_group_expose_socket(ngroup, sock, SOCK_IN); - node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock); - nodeAddLink(ngroup, NULL, gsock, node, sock); + /* move nodes in the group to the center */ + for (node = ngroup->nodes.first; node; node = node->next) { + if (node_group_make_use_node(node, gnode) && !node->parent) { + node->locx -= center[0]; + node->locy -= center[1]; } - - for (sock = node->outputs.first; sock; sock = sock->next) { - int skip = FALSE; - - for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next) - if (link->fromsock == sock) - skip = TRUE; - - if (skip == TRUE) - continue; - - gsock = node_group_expose_socket(ngroup, sock, SOCK_OUT); - node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock); - nodeAddLink(ngroup, NULL, gsock, node, sock); + } + + /* expose all unlinked sockets too */ + if (expose_all) { + for (node = ngroup->nodes.first; node; node = node->next) { + if (node_group_make_use_node(node, gnode)) { + for (sock = node->inputs.first; sock; sock = sock->next) { + bNodeSocket *iosock, *input_sock; + int skip = FALSE; + for (link = ngroup->links.first; link; link = link->next) { + if (link->tosock == sock) { + skip = TRUE; + break; + } + } + if (skip) + continue; + + iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock); + + /* lazy init */ + if (!input_node) { + input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT); + + input_node->locx = min[0] - center[0] - offsetx; + input_node->locy = -offsety; + } + node_group_input_verify(ngroup, input_node, (ID *)ngroup); + + /* create new internal link */ + input_sock = node_group_input_find_socket(input_node, iosock->identifier); + nodeAddLink(ngroup, input_node, input_sock, node, sock); + } + + for (sock = node->outputs.first; sock; sock = sock->next) { + bNodeSocket *iosock, *output_sock; + int skip = FALSE; + for (link = ngroup->links.first; link; link = link->next) + if (link->fromsock == sock) + skip = TRUE; + if (skip) + continue; + + iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock); + + /* lazy init */ + if (!output_node) { + output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT); + + output_node->locx = max[0] - center[0] + offsetx; + output_node->locy = -offsety; + } + + node_group_output_verify(ngroup, output_node, (ID *)ngroup); + + /* create new internal link */ + output_sock = node_group_output_find_socket(output_node, iosock->identifier); + nodeAddLink(ngroup, node, sock, output_node, output_sock); + } + } } } @@ -1035,30 +939,32 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode) ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS; /* update of the tree containing the group instance node */ ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; - - return 1; } -static bNode *node_group_make_from_selected(bNodeTree *ntree) +static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype) { + Main *bmain = CTX_data_main(C); bNode *gnode; bNodeTree *ngroup; float min[2], max[2]; - bNodeTemplate ntemp; - - node_get_selected_minmax(ntree, NULL, min, max); - + int totselect; + + totselect = node_get_selected_minmax(ntree, NULL, min, max); + /* don't make empty group */ + if (totselect == 0) + return NULL; + /* new nodetree */ - ngroup = ntreeAddTree(G.main, "NodeGroup", ntree->type, NODE_GROUP); - + ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype); + /* make group node */ - ntemp.type = NODE_GROUP; - ntemp.ngroup = ngroup; - gnode = nodeAddNode(ntree, &ntemp); + gnode = nodeAddNode(C, ntree, ntype); + gnode->id = (ID *)ngroup; + gnode->locx = 0.5f * (min[0] + max[0]); gnode->locy = 0.5f * (min[1] + max[1]); - - node_group_make_insert_selected(ntree, gnode); + + node_group_make_insert_selected(C, ntree, gnode); /* update of the tree containing the group instance node */ ntree->update |= NTREE_UPDATE_NODES; @@ -1066,120 +972,116 @@ static bNode *node_group_make_from_selected(bNodeTree *ntree) return gnode; } -typedef enum eNodeGroupMakeType { - NODE_GM_NEW, - NODE_GM_INSERT -} eNodeGroupMakeType; - -/* Operator Property */ -EnumPropertyItem node_group_make_types[] = { - {NODE_GM_NEW, "NEW", 0, "New", "Create a new node group from selected nodes"}, - {NODE_GM_INSERT, "INSERT", 0, "Insert", "Insert into active node group"}, - {0, NULL, 0, NULL, NULL} -}; - static int node_group_make_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + char *node_idname, *ntree_idname; + bNodeTree *ngroup; bNode *gnode; - int type = RNA_enum_get(op->ptr, "type"); - - if (snode->edittree != snode->nodetree) { - BKE_report(op->reports, RPT_WARNING, "Cannot add a new group in a group"); - return OPERATOR_CANCELLED; - } - - /* for time being... is too complex to handle */ - if (snode->treetype == NTREE_COMPOSIT) { - for (gnode = snode->nodetree->nodes.first; gnode; gnode = gnode->next) { - if (gnode->flag & SELECT) - if (gnode->type == CMP_NODE_R_LAYERS) - break; - } - - if (gnode) { - BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group"); - return OPERATOR_CANCELLED; - } - } - + ED_preview_kill_jobs(C); - - switch (type) { - case NODE_GM_NEW: - if (node_group_make_test(snode->nodetree, NULL)) { - gnode = node_group_make_from_selected(snode->nodetree); - } - else { - BKE_report(op->reports, RPT_WARNING, "Cannot make group"); - return OPERATOR_CANCELLED; - } - break; - case NODE_GM_INSERT: - gnode = nodeGetActive(snode->nodetree); - if (!gnode || gnode->type != NODE_GROUP) { - BKE_report(op->reports, RPT_WARNING, "No active group node"); - return OPERATOR_CANCELLED; - } - if (node_group_make_test(snode->nodetree, gnode)) { - node_group_make_insert_selected(snode->nodetree, gnode); - } - else { - BKE_report(op->reports, RPT_WARNING, "Cannot insert into group"); - return OPERATOR_CANCELLED; - } - break; + + if (!node_group_operator_check_type(C, op, &node_idname, &ntree_idname)) + return OPERATOR_PASS_THROUGH; + + if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) { + MEM_freeN(node_idname); + MEM_freeN(ntree_idname); + return OPERATOR_CANCELLED; } - + + gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname); + MEM_freeN(node_idname); + MEM_freeN(ntree_idname); + if (gnode) { - nodeSetActive(snode->nodetree, gnode); - snode_make_group_editable(snode, gnode); + ngroup = (bNodeTree *)gnode->id; + + nodeSetActive(ntree, gnode); + if (ngroup) { + ED_node_tree_push(snode, ngroup, gnode); + ntreeUpdateTree(ngroup); + } } - - if (gnode) - ntreeUpdateTree((bNodeTree *)gnode->id); - ntreeUpdateTree(snode->nodetree); + + ntreeUpdateTree(ntree); snode_notify(C, snode); snode_dag_update(C, snode); - + return OPERATOR_FINISHED; } -static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - bNode *act = nodeGetActive(snode->edittree); - uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Group"), ICON_NONE); - uiLayout *layout = uiPupMenuLayout(pup); - - uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); - uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_NEW); - - /* if active node is a group, add insert option */ - if (act && act->type == NODE_GROUP) { - uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_INSERT); - } - - uiPupMenuEnd(C, pup); - - return OPERATOR_CANCELLED; -} - void NODE_OT_group_make(wmOperatorType *ot) { /* identifiers */ - ot->name = "Group"; + ot->name = "Make Group"; ot->description = "Make group from selected nodes"; ot->idname = "NODE_OT_group_make"; - + /* api callbacks */ - ot->invoke = node_group_make_invoke; ot->exec = node_group_make_exec; ot->poll = ED_operator_node_active; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + node_group_operator_properties(ot); +} - RNA_def_enum(ot->srna, "type", node_group_make_types, NODE_GM_NEW, "Type", ""); +/* ****************** Group Insert operator ******************* */ + +static int node_group_insert_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + bNodeTree *ngroup; + char *node_idname; + bNode *gnode; + + ED_preview_kill_jobs(C); + + if (!node_group_operator_check_type(C, op, &node_idname, NULL)) + return OPERATOR_PASS_THROUGH; + + gnode = node_group_get_active(C, node_idname); + MEM_freeN(node_idname); + + if (!gnode || !gnode->id) + return OPERATOR_CANCELLED; + + ngroup = (bNodeTree *)gnode->id; + if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports)) + return OPERATOR_CANCELLED; + + node_group_make_insert_selected(C, ntree, gnode); + + nodeSetActive(ntree, gnode); + ED_node_tree_push(snode, ngroup, gnode); + ntreeUpdateTree(ngroup); + + ntreeUpdateTree(ntree); + + snode_notify(C, snode); + snode_dag_update(C, snode); + + return OPERATOR_FINISHED; +} + +void NODE_OT_group_insert(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Group Insert"; + ot->description = "Insert selected nodes into a node group"; + ot->idname = "NODE_OT_group_insert"; + + /* api callbacks */ + ot->exec = node_group_insert_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + node_group_operator_properties(ot); } diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index f26b6ff0f54..175bbce756e 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -58,186 +58,21 @@ /* ************************ add menu *********************** */ -static void do_node_add(bContext *C, bNodeTemplate *ntemp) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - SpaceNode *snode = CTX_wm_space_node(C); - ScrArea *sa = CTX_wm_area(C); - ARegion *ar; - bNode *node, *node_new; - - /* get location to add node at mouse */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - wmWindow *win = CTX_wm_window(C); - int x = win->eventstate->x - ar->winrct.xmin; - int y = win->eventstate->y - ar->winrct.ymin; - - if (y < 60) y += 60; - UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]); - } - } - - /* store selection in temp test flag */ - for (node = snode->edittree->nodes.first; node; node = node->next) { - if (node->flag & NODE_SELECT) node->flag |= NODE_TEST; - else node->flag &= ~NODE_TEST; - } - - node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]); - - /* select previous selection before autoconnect */ - for (node = snode->edittree->nodes.first; node; node = node->next) { - if (node->flag & NODE_TEST) node->flag |= NODE_SELECT; - } - - /* deselect after autoconnection */ - for (node = snode->edittree->nodes.first; node; node = node->next) { - if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT; - } - - /* once this is called from an operator, this should be removed */ - if (node_new) { - char undostr[BKE_UNDO_STR_MAX]; - BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new)); - BKE_write_undo(C, undostr); - } - - snode_notify(C, snode); - snode_dag_update(C, snode); -} - -static void do_node_add_static(bContext *C, void *UNUSED(arg), int event) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - bNodeTemplate ntemp; - - ntemp.type = event; - ntemp.main = bmain; - ntemp.scene = scene; - - do_node_add(C, &ntemp); -} - -static void do_node_add_group(bContext *C, void *UNUSED(arg), int event) -{ - SpaceNode *snode = CTX_wm_space_node(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - bNodeTemplate ntemp; - - if (event >= 0) { - ntemp.ngroup = BLI_findlink(&G.main->nodetree, event); - ntemp.type = ntemp.ngroup->nodetype; - } - else { - ntemp.type = -event; - switch (ntemp.type) { - case NODE_GROUP: - ntemp.ngroup = ntreeAddTree(bmain, "Group", snode->treetype, ntemp.type); - break; - default: - ntemp.ngroup = NULL; - } - } - if (!ntemp.ngroup) - return; - - ntemp.main = bmain; - ntemp.scene = scene; - - do_node_add(C, &ntemp); -} - -static int node_tree_has_type(int treetype, int nodetype) -{ - bNodeTreeType *ttype = ntreeGetType(treetype); - bNodeType *ntype; - for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) { - if (ntype->type == nodetype) - return 1; - } - return 0; -} - -static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - SpaceNode *snode = CTX_wm_space_node(C); - bNodeTree *ntree; - int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass); - int event, compatibility = 0; - - ntree = snode->nodetree; - - if (!ntree) { - uiItemS(layout); - return; - } - - if (ntree->type == NTREE_SHADER) { - if (BKE_scene_use_new_shading_nodes(scene)) - compatibility = NODE_NEW_SHADING; - else - compatibility = NODE_OLD_SHADING; - } - - if (nodeclass == NODE_CLASS_GROUP) { - bNodeTree *ngroup; - - uiLayoutSetFunc(layout, do_node_add_group, NULL); - - /* XXX hack: negative numbers used for empty group types */ - if (node_tree_has_type(ntree->type, NODE_GROUP)) - uiItemV(layout, IFACE_("New Group"), 0, -NODE_GROUP); - uiItemS(layout); - - for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) { - /* only use group trees */ - if (ngroup->type == ntree->type && ngroup->nodetype == NODE_GROUP) { - uiItemV(layout, ngroup->id.name + 2, 0, event); - } - } - } - else { - bNodeType *ntype; - - uiLayoutSetFunc(layout, do_node_add_static, NULL); - - for (ntype = ntreeGetType(ntree->type)->node_types.first; ntype; ntype = ntype->next) { - if (ntype->nclass == nodeclass && ntype->name) { - if (!compatibility || (ntype->compatibility & compatibility)) { - uiItemV(layout, IFACE_(ntype->name), 0, ntype->type); - } - } - } - } -} - -static void node_menu_add_foreach_cb(void *calldata, int nclass, const char *name) -{ - uiLayout *layout = calldata; - uiItemMenuF(layout, IFACE_(name), 0, node_add_menu, SET_INT_IN_POINTER(nclass)); -} - static void node_menu_add(const bContext *C, Menu *menu) { - Scene *scene = CTX_data_scene(C); SpaceNode *snode = CTX_wm_space_node(C); uiLayout *layout = menu->layout; - bNodeTreeType *ntreetype = ntreeGetType(snode->treetype); + bNodeTree *ntree = snode->edittree; - if (!snode->nodetree) + if (!ntree || !ntree->typeinfo || !ntree->typeinfo->draw_add_menu) { uiLayoutSetActive(layout, FALSE); - + return; + } + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Search ..."), 0, "NODE_OT_add_search"); - if (ntreetype && ntreetype->foreach_nodeclass) - ntreetype->foreach_nodeclass(scene, layout, node_menu_add_foreach_cb); + ntree->typeinfo->draw_add_menu(C, layout, ntree); } void node_menus_register(void) diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index cbf7101a101..a24da7143f9 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -32,6 +32,7 @@ #define __NODE_INTERN_H__ #include <stddef.h> /* for size_t */ +#include "BKE_node.h" #include "UI_interface.h" /* internal exports only */ @@ -43,7 +44,6 @@ struct bContext; struct wmWindow; struct wmWindowManager; struct wmEvent; -struct bNodeTemplate; struct bNode; struct bNodeSocket; struct bNodeLink; @@ -66,21 +66,26 @@ typedef struct bNodeLinkDrag { ARegion *node_has_buttons_region(ScrArea *sa); ARegion *node_has_tools_region(ScrArea *sa); +void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transform between View2Ds in the tree path */ + /* node_header.c */ void node_menus_register(void); /* node_draw.c */ int node_get_colorid(struct bNode *node); -void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight); +void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, + struct bNodeSocket *sock, float size, int highlight); int node_get_resize_cursor(int directions); void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha); -void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node); +void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, + struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); int node_select_area_default(struct bNode *node, int x, int y); int node_tweak_area_default(struct bNode *node, int x, int y); -void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety); -void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree); -void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d); +void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree); +void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, + struct bNodeTree *ntree, bNodeInstanceKey parent_key); +void drawnodespace(const bContext *C, ARegion *ar); void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode); /* DPI scaled coords */ @@ -100,8 +105,6 @@ void node_operatortypes(void); void node_keymap(struct wmKeyConfig *keyconf); /* node_select.c */ -void node_select(struct bNode *node); -void node_deselect(struct bNode *node); void node_deselect_all(struct SpaceNode *snode); void node_socket_select(struct bNode *node, struct bNodeSocket *sock); void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, int deselect_node); @@ -138,13 +141,15 @@ void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struc /* node_add.c */ -bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene, - struct bNodeTemplate *ntemp, float locx, float locy); +bNode *node_add_node(const struct bContext *C, const char *idname, int type, float locx, float locy); void NODE_OT_add_reroute(struct wmOperatorType *ot); +void NODE_OT_add_file(struct wmOperatorType *ot); +void NODE_OT_new_node_tree(struct wmOperatorType *ot); /* node_group.c */ void NODE_OT_group_make(struct wmOperatorType *ot); +void NODE_OT_group_insert(struct wmOperatorType *ot); void NODE_OT_group_ungroup(struct wmOperatorType *ot); void NODE_OT_group_separate(struct wmOperatorType *ot); void NODE_OT_group_edit(struct wmOperatorType *ot); @@ -154,11 +159,6 @@ void NODE_OT_group_socket_move_up(struct wmOperatorType *ot); void NODE_OT_group_socket_move_down(struct wmOperatorType *ot); -/* note_add.c */ -void NODE_OT_add_file(struct wmOperatorType *ot); -void NODE_OT_new_node_tree(struct wmOperatorType *ot); - - /* node_relationships.c */ void NODE_OT_link(struct wmOperatorType *ot); void NODE_OT_link_make(struct wmOperatorType *ot); @@ -175,11 +175,9 @@ void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot); /* node_edit.c */ -void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype); void snode_notify(struct bContext *C, struct SpaceNode *snode); void snode_dag_update(struct bContext *C, struct SpaceNode *snode); -void snode_set_context(struct SpaceNode *snode, Scene *scene); -void snode_make_group_editable(struct SpaceNode *snode, struct bNode *gnode); +void snode_set_context(const struct bContext *C); bNode *node_tree_get_editgroup(bNodeTree *ntree); void snode_update(struct SpaceNode *snode, struct bNode *node); @@ -215,6 +213,10 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); void NODE_OT_clipboard_copy(struct wmOperatorType *ot); void NODE_OT_clipboard_paste(struct wmOperatorType *ot); +void NODE_OT_tree_socket_add(struct wmOperatorType *ot); +void NODE_OT_tree_socket_remove(struct wmOperatorType *ot); +void NODE_OT_tree_socket_move(struct wmOperatorType *ot); + void NODE_OT_shader_script_update(struct wmOperatorType *ot); void NODE_OT_viewer_border(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index d16c6627d3f..1e4e02b6ae1 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -84,13 +84,10 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_add_reroute); WM_operatortype_append(NODE_OT_group_make); + WM_operatortype_append(NODE_OT_group_insert); WM_operatortype_append(NODE_OT_group_ungroup); WM_operatortype_append(NODE_OT_group_separate); WM_operatortype_append(NODE_OT_group_edit); - WM_operatortype_append(NODE_OT_group_socket_add); - WM_operatortype_append(NODE_OT_group_socket_remove); - WM_operatortype_append(NODE_OT_group_socket_move_up); - WM_operatortype_append(NODE_OT_group_socket_move_down); WM_operatortype_append(NODE_OT_link_viewer); @@ -122,6 +119,10 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_shader_script_update); WM_operatortype_append(NODE_OT_viewer_border); + + WM_operatortype_append(NODE_OT_tree_socket_add); + WM_operatortype_append(NODE_OT_tree_socket_remove); + WM_operatortype_append(NODE_OT_tree_socket_move); } void ED_operatormacros_node(void) @@ -198,6 +199,29 @@ static void node_select_keymap(wmKeyMap *keymap, int extend) } } +/* register group operators for a specific group node type */ +static void node_group_operators(wmKeyMap *keymap, const char *node_type) +{ + wmKeyMapItem *kmi; + + kmi = WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "node_type", node_type); + + kmi = WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0); + RNA_string_set(kmi->ptr, "node_type", node_type); + + kmi = WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "node_type", node_type); + + kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "node_type", node_type); + RNA_boolean_set(kmi->ptr, "exit", FALSE); + + kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_SHIFT, 0); + RNA_string_set(kmi->ptr, "node_type", node_type); + RNA_boolean_set(kmi->ptr, "exit", TRUE); +} + void node_keymap(struct wmKeyConfig *keyconf) { wmKeyMap *keymap; @@ -230,9 +254,18 @@ void node_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "deselect", TRUE); /* each of these falls through if not handled... */ - WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "detach", FALSE); + RNA_boolean_set(kmi->ptr, "expose", FALSE); kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "detach", TRUE); + RNA_boolean_set(kmi->ptr, "expose", FALSE); + kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "detach", FALSE); + RNA_boolean_set(kmi->ptr, "expose", TRUE); + kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "detach", TRUE); + RNA_boolean_set(kmi->ptr, "expose", TRUE); WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); @@ -288,11 +321,10 @@ void node_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NODE_OT_select_same_type_next", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NODE_OT_select_same_type_prev", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0); - + node_group_operators(keymap, "ShaderNodeGroup"); + node_group_operators(keymap, "CompositorNodeGroup"); + node_group_operators(keymap, "TextureNodeGroup"); + WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 097e4f418e0..8ff964aa932 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -54,6 +54,7 @@ #include "UI_view2d.h" #include "node_intern.h" /* own include */ +#include "NOD_common.h" /* ****************** Add *********************** */ @@ -107,7 +108,7 @@ static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocke /* check for same types */ if (sock->type == sock_target->type) { - if (strcmp(sock->name, sock_target->name) == 0) + if (STREQ(sock->name, sock_target->name)) return sock; } } @@ -323,13 +324,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode) if (sock) { /* add a new viewer if none exists yet */ if (!node) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - bNodeTemplate ntemp; - - ntemp.type = CMP_NODE_VIEWER; /* XXX location is a quick hack, just place it next to the linked socket */ - node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy); + node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy); if (!node) return OPERATOR_CANCELLED; @@ -364,7 +360,7 @@ static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op)) SpaceNode *snode = CTX_wm_space_node(C); bNode *node; - node = editnode_get_active(snode->edittree); + node = nodeGetActive(snode->edittree); if (!node) return OPERATOR_CANCELLED; @@ -434,18 +430,6 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL } } -static int outside_group_rect(SpaceNode *snode) -{ - bNode *gnode = node_tree_get_editgroup(snode->nodetree); - if (gnode) { - return (snode->cursor[0] < gnode->totr.xmin || - snode->cursor[0] >= gnode->totr.xmax || - snode->cursor[1] < gnode->totr.ymin || - snode->cursor[1] >= gnode->totr.ymax); - } - return 0; -} - /* loop that adds a nodelink, called by function below */ /* in_out = starting socket */ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) @@ -459,55 +443,41 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) bNodeLink *link; LinkData *linkdata; int in_out; + int expose; in_out = nldrag->in_out; - + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); + expose = RNA_boolean_get(op->ptr, "expose"); + switch (event->type) { case MOUSEMOVE: - + if (in_out == SOCK_OUT) { if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) { for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; - + /* skip if this is already the target socket */ if (link->tosock == tsock) continue; /* skip if socket is on the same node as the fromsock */ if (tnode && link->fromnode == tnode) continue; - + /* attach links to the socket */ link->tonode = tnode; link->tosock = tsock; - /* add it to the node tree temporarily */ - if (BLI_findindex(&ntree->links, link) < 0) - BLI_addtail(&ntree->links, link); - - ntree->update |= NTREE_UPDATE_LINKS; } - ntreeUpdateTree(ntree); } else { - int do_update = FALSE; for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; - - if (link->tonode || link->tosock) { - BLI_remlink(&ntree->links, link); - link->prev = link->next = NULL; - link->tonode = NULL; - link->tosock = NULL; - - ntree->update |= NTREE_UPDATE_LINKS; - do_update = TRUE; - } - } - if (do_update) { - ntreeUpdateTree(ntree); + + link->tonode = NULL; + link->tosock = NULL; } } } @@ -515,108 +485,126 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) { for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; - + /* skip if this is already the target socket */ if (link->fromsock == tsock) continue; /* skip if socket is on the same node as the fromsock */ if (tnode && link->tonode == tnode) continue; - + /* attach links to the socket */ link->fromnode = tnode; link->fromsock = tsock; - /* add it to the node tree temporarily */ - if (BLI_findindex(&ntree->links, link) < 0) - BLI_addtail(&ntree->links, link); - - ntree->update |= NTREE_UPDATE_LINKS; } - ntreeUpdateTree(ntree); } else { - int do_update = FALSE; for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; - - if (link->fromnode || link->fromsock) { - BLI_remlink(&ntree->links, link); - link->prev = link->next = NULL; - link->fromnode = NULL; - link->fromsock = NULL; - - ntree->update |= NTREE_UPDATE_LINKS; - do_update = TRUE; - } - } - if (do_update) { - ntreeUpdateTree(ntree); + + link->fromnode = NULL; + link->fromsock = NULL; } } } - + ED_region_tag_redraw(ar); break; - + case LEFTMOUSE: case RIGHTMOUSE: case MIDDLEMOUSE: { + /* XXX expose + detach could have some ugly corner cases and is not great. + * The first link will define the exposed socket type, which is arbitrary. + * Some of the resulting links may turn out to be invalid. + */ + bNode *ionode = NULL; + bNodeSocket *iosock = NULL, *gsock; for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; - + if (link->tosock && link->fromsock) { - /* send changed events for original tonode and new */ - if (link->tonode) - snode_update(snode, link->tonode); - + /* add link to the node tree */ + BLI_addtail(&ntree->links, link); + + ntree->update |= NTREE_UPDATE_LINKS; + + /* tag tonode for update */ + link->tonode->update |= NODE_UPDATE; + /* we might need to remove a link */ if (in_out == SOCK_OUT) node_remove_extra_links(snode, link->tosock, link); - - /* when linking to group outputs, update the socket type */ - /* XXX this should all be part of a generic update system */ - if (!link->tonode) { - if (link->tosock->type != link->fromsock->type) - nodeSocketSetType(link->tosock, link->fromsock->type); - } } - else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) { - /* automatically add new group socket */ - if (link->tonode && link->tosock) { - link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN); - link->fromnode = NULL; - if (BLI_findindex(&ntree->links, link) < 0) - BLI_addtail(&ntree->links, link); - + else if (expose) { + if (link->tosock) { + if (!ionode) { + ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_INPUT); + gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->tonode, link->tosock); + node_group_input_verify(snode->edittree, ionode, (ID *)snode->edittree); + iosock = node_group_input_find_socket(ionode, gsock->identifier); + + { + /* place the node at the mouse pointer */ + float sockx = 42.0f + 3 * HIDDEN_RAD; /* XXX totally arbitrary initial hidden node size ... */ + float socky = -HIDDEN_RAD; + + ionode->locx = snode->cursor[0] - sockx; + ionode->locy = snode->cursor[1] - socky; + } + } + link->fromnode = ionode; + link->fromsock = iosock; + + BLI_addtail(&ntree->links, link); + ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS; } - else if (link->fromnode && link->fromsock) { - link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT); - link->tonode = NULL; - if (BLI_findindex(&ntree->links, link) < 0) - BLI_addtail(&ntree->links, link); - + else if (link->fromsock) { + if (!ionode) { + ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_OUTPUT); + gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->fromnode, link->fromsock); + node_group_output_verify(snode->edittree, ionode, (ID *)snode->edittree); + iosock = node_group_output_find_socket(ionode, gsock->identifier); + + { + /* place the node at the mouse pointer */ + float sockx = 0; + float socky = -HIDDEN_RAD; + + ionode->locx = snode->cursor[0] - sockx; + ionode->locy = snode->cursor[1] - socky; + } + } + link->tonode = ionode; + link->tosock = iosock; + + BLI_addtail(&ntree->links, link); + ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS; } + else { + nodeRemLink(snode->edittree, link); + } } else nodeRemLink(ntree, link); } - + ntreeUpdateTree(ntree); snode_notify(C, snode); snode_dag_update(C, snode); - + BLI_remlink(&snode->linkdrag, nldrag); /* links->data pointers are either held by the tree or freed already */ BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); - + return OPERATOR_FINISHED; } } - + return OPERATOR_RUNNING_MODAL; } @@ -646,6 +634,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); *oplink = *link; oplink->next = oplink->prev = NULL; + oplink->flag |= NODE_LINK_VALID; + BLI_addtail(&nldrag->links, linkdata); nodeRemLink(snode->edittree, link); } @@ -659,6 +649,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); oplink->fromnode = node; oplink->fromsock = sock; + oplink->flag |= NODE_LINK_VALID; + BLI_addtail(&nldrag->links, linkdata); } } @@ -678,9 +670,11 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); *oplink = *link; oplink->next = oplink->prev = NULL; + oplink->flag |= NODE_LINK_VALID; + BLI_addtail(&nldrag->links, linkdata); nodeRemLink(snode->edittree, link); - + /* send changed event to original link->tonode */ if (node) snode_update(snode, node); @@ -695,6 +689,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); oplink->tonode = node; oplink->tosock = sock; + oplink->flag |= NODE_LINK_VALID; + BLI_addtail(&nldrag->links, linkdata); } } @@ -760,6 +756,7 @@ void NODE_OT_link(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; RNA_def_boolean(ot->srna, "detach", FALSE, "Detach", "Detach and redirect existing links"); + RNA_def_boolean(ot->srna, "expose", FALSE, "Expose", "Expose the socket as an interface node"); } /* ********************** Make Link operator ***************** */ @@ -845,6 +842,8 @@ static int cut_links_exec(bContext *C, wmOperator *op) for (link = snode->edittree->links.first; link; link = next) { next = link->next; + if (nodeLinkIsHidden(link)) + continue; if (cut_links_intersect(link, mcoords, i)) { @@ -1075,11 +1074,8 @@ static void node_join_attach_recursive(bNode *node, bNode *frame) static int node_join_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); bNodeTree *ntree = snode->edittree; bNode *node, *frame; - bNodeTemplate ntemp; /* XXX save selection: node_add_node call below sets the new frame as single active+selected node */ for (node = ntree->nodes.first; node; node = node->next) { @@ -1089,10 +1085,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op)) node->flag &= ~NODE_TEST; } - ntemp.main = bmain; - ntemp.scene = scene; - ntemp.type = NODE_FRAME; - frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f); + frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f); /* reset tags */ for (node = ntree->nodes.first; node; node = node->next) @@ -1310,6 +1303,9 @@ static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select) /* test node for links */ for (link = snode->edittree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; + if (link->tonode == *select || link->fromnode == *select) return NULL; } @@ -1350,7 +1346,9 @@ void ED_node_link_intersect_test(ScrArea *sa, int test) /* we only tag a single link for intersect now */ /* idea; use header dist when more? */ for (link = snode->edittree->links.first; link; link = link->next) { - + if (nodeLinkIsHidden(link)) + continue; + if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */ if (selink) break; @@ -1415,11 +1413,12 @@ void ED_node_link_insert(ScrArea *sa) link->tonode = select; link->tosock = socket_best_match(&select->inputs); + node_remove_extra_links(snode, link->tosock, link); link->flag &= ~NODE_LINKFLAG_HILITE; nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto); ntreeUpdateTree(snode->edittree); /* needed for pointers */ snode_update(snode, select); - ED_node_changed_update(snode->id, select); + ED_node_tag_update_id(snode->id); } } diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index c917b8ee756..faebeabdbba 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -82,30 +82,9 @@ static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my) return NULL; } -void node_select(bNode *node) -{ - node->flag |= SELECT; -} - -void node_deselect(bNode *node) -{ - bNodeSocket *sock; - - node->flag &= ~SELECT; - - /* deselect sockets too */ - for (sock = node->inputs.first; sock; sock = sock->next) - sock->flag &= ~SELECT; - for (sock = node->outputs.first; sock; sock = sock->next) - sock->flag &= ~SELECT; -} - static void node_toggle(bNode *node) { - if (node->flag & SELECT) - node_deselect(node); - else - node_select(node); + nodeSetSelected(node, !(node->flag & SELECT)); } void node_socket_select(bNode *node, bNodeSocket *sock) @@ -157,7 +136,7 @@ void node_deselect_all(SpaceNode *snode) bNode *node; for (node = snode->edittree->nodes.first; node; node = node->next) - node_deselect(node); + nodeSetSelected(node, FALSE); } void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes) @@ -189,9 +168,6 @@ void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes) node->flag &= ~SELECT; } } - - for (sock = snode->edittree->outputs.first; sock; sock = sock->next) - sock->flag &= ~SELECT; } void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes) @@ -223,9 +199,6 @@ void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes) node->flag &= ~SELECT; } } - - for (sock = snode->edittree->inputs.first; sock; sock = sock->next) - sock->flag &= ~SELECT; } /* return 1 if we need redraw otherwise zero. */ @@ -249,12 +222,12 @@ int node_select_same_type(SpaceNode *snode) if (p->type != nac->type && p->flag & SELECT) { /* if it's selected but different type, unselect */ redraw = 1; - node_deselect(p); + nodeSetSelected(p, FALSE); } else if (p->type == nac->type && (!(p->flag & SELECT))) { /* if it's the same type and is not selected, select! */ redraw = 1; - node_select(p); + nodeSetSelected(p, TRUE); } } return(redraw); @@ -296,8 +269,8 @@ int node_select_same_type_np(SpaceNode *snode, int dir) if (p) { for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) if (tnode != p) - node_deselect(tnode); - node_select(p); + nodeSetSelected(tnode, FALSE); + nodeSetSelected(p, TRUE); return(1); } return(0); @@ -311,8 +284,8 @@ void node_select_single(bContext *C, bNode *node) for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) if (tnode != node) - node_deselect(tnode); - node_select(node); + nodeSetSelected(tnode, FALSE); + nodeSetSelected(node, TRUE); ED_node_set_active(bmain, snode->edittree, node); @@ -386,9 +359,10 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i node = node_under_mouse_select(snode->edittree, mx, my); if (node) { - for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) - node_deselect(tnode); - node_select(node); + for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + nodeSetSelected(tnode, false); + } + nodeSetSelected(node, TRUE); ED_node_set_active(bmain, snode->edittree, node); selected = 1; } @@ -477,13 +451,10 @@ static int node_borderselect_exec(bContext *C, wmOperator *op) for (node = snode->edittree->nodes.first; node; node = node->next) { if (BLI_rctf_isect(&rectf, &node->totr, NULL)) { - if (gesture_mode == GESTURE_MODAL_SELECT) - node_select(node); - else - node_deselect(node); + nodeSetSelected(node, (gesture_mode == GESTURE_MODAL_SELECT)); } else if (!extend) { - node_deselect(node); + nodeSetSelected(node, FALSE); } } @@ -566,11 +537,7 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves, if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) { - if (select) - node_select(node); - else - node_deselect(node); - + nodeSetSelected(node, select); change = TRUE; } } @@ -642,13 +609,13 @@ static int node_select_all_exec(bContext *C, wmOperator *op) for (node = node_lb->first; node; node = node->next) { switch (action) { case SEL_SELECT: - node_select(node); + nodeSetSelected(node, TRUE); break; case SEL_DESELECT: - node_deselect(node); + nodeSetSelected(node, FALSE); break; case SEL_INVERT: - ((node->flag & SELECT) ? node_deselect : node_select)(node); + nodeSetSelected(node, !(node->flag & SELECT)); break; } } @@ -688,13 +655,15 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op)) node->flag &= ~NODE_TEST; for (link = snode->edittree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) link->tonode->flag |= NODE_TEST; } for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) - node_select(node); + nodeSetSelected(node, TRUE); } ED_node_sort(snode->edittree); @@ -730,13 +699,15 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) node->flag &= ~NODE_TEST; for (link = snode->edittree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) link->fromnode->flag |= NODE_TEST; } for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) - node_select(node); + nodeSetSelected(node, TRUE); } ED_node_sort(snode->edittree); diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index ca85415cb5a..0bc2fba0d0b 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -130,7 +130,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to nodeUpdate(ntree, node_to); ntreeUpdateTree(ntree); - ED_node_generic_update(bmain, ntree, node_to); + ED_node_tag_update_nodetree(bmain, ntree); } /* remove all nodes connected to this socket, if they aren't connected to other nodes */ @@ -145,11 +145,11 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN nodeUpdate(ntree, node_to); ntreeUpdateTree(ntree); - ED_node_generic_update(bmain, ntree, node_to); + ED_node_tag_update_nodetree(bmain, ntree); } /* add new node connected to this socket, or replace an existing one */ -static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num) +static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, bNodeTree *ngroup, int sock_num) { bNode *node_from; bNodeSocket *sock_from_tmp; @@ -163,24 +163,30 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t /* find existing node that we can use */ for (node_from = ntree->nodes.first; node_from; node_from = node_from->next) - if (node_from->type == ntemp->type) + if (node_from->type == type) break; if (node_from) if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS))) node_from = NULL; - if (node_prev && node_prev->type == ntemp->type && - (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id)) + /* XXX how can this be done nicely? bNodeTemplate is removed, it doesn't work for generic custom nodes */ + if (node_prev && node_prev->type == type && + (type != NODE_GROUP || node_prev->id == &ngroup->id)) { /* keep the previous node if it's the same type */ node_from = node_prev; } else if (!node_from) { - node_from = nodeAddNode(ntree, ntemp); + node_from = nodeAddStaticNode(C, ntree, type); node_from->locx = node_to->locx - (node_from->typeinfo->width + 50); node_from->locy = node_to->locy; - + + /* XXX bad, should be dispatched to generic operator or something ... */ + if (type == NODE_GROUP) { + node_from->id = (ID *)ngroup; + } + if (node_from->id) id_us_plus(node_from->id); } @@ -201,7 +207,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit) continue; - if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) { + if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) { bNodeLink *link = sock_prev->link; if (link && link->fromnode) { @@ -209,9 +215,11 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t nodeRemLink(ntree, link); } - node_socket_free_default_value(sock_from->type, sock_from->default_value); - sock_from->default_value = node_socket_make_default_value(sock_from->type); - node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value); +#if 0 /* XXX TODO */ + node_socket_free_default_value(sock_from->typeinfo, sock_from->default_value); + sock_from->default_value = node_socket_make_default_value(sock_from->typeinfo); + node_socket_copy_default_value(sock_from->typeinfo, sock_from->default_value, sock_prev->default_value); +#endif } } } @@ -231,7 +239,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t nodeUpdate(ntree, node_to); ntreeUpdateTree(ntree); - ED_node_generic_update(bmain, ntree, node_to); + ED_node_tag_update_nodetree(CTX_data_main(C), ntree); } /****************************** Node Link Menu *******************************/ @@ -262,19 +270,13 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p) bNodeSocket *sock_to = arg->sock; bNodeTree *ntree = arg->ntree; int event = GET_INT_FROM_POINTER(event_p); - bNodeTemplate ntemp; - - ntemp.type = arg->type; - ntemp.ngroup = arg->ngroup; - ntemp.scene = CTX_data_scene(C); - ntemp.main = CTX_data_main(C); if (event == UI_NODE_LINK_DISCONNECT) node_socket_disconnect(bmain, ntree, node_to, sock_to); else if (event == UI_NODE_LINK_REMOVE) node_socket_remove(bmain, ntree, node_to, sock_to); else - node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output); + node_socket_add_replace(C, ntree, node_to, sock_to, arg->type, arg->ngroup, arg->output); ED_undo_push(C, "Node input modify"); } @@ -289,10 +291,10 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR]) if (node->id) BLI_strncpy(node_name, node->id->name + 2, UI_MAX_NAME_STR); else - BLI_strncpy(node_name, N_("Group"), UI_MAX_NAME_STR); + BLI_strncpy(node_name, N_(node->typeinfo->ui_name), UI_MAX_NAME_STR); } else - BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR); + BLI_strncpy(node_name, node->typeinfo->ui_name, UI_MAX_NAME_STR); if (node->inputs.first == NULL && node->outputs.first != node->outputs.last) @@ -316,19 +318,16 @@ static int ui_compatible_sockets(int typeA, int typeB) static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) { - Main *bmain = arg->bmain; bNodeTree *ntree = arg->ntree; bNodeSocket *sock = arg->sock; uiLayout *layout = arg->layout; uiLayout *column = NULL; uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; - bNodeType *ntype; - bNodeTree *ngroup; NodeLinkArg *argN; int first = 1; int compatibility = 0; - + if (ntree->type == NTREE_SHADER) { if (BKE_scene_use_new_shading_nodes(arg->scene)) compatibility = NODE_NEW_SHADING; @@ -336,114 +335,58 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) compatibility = NODE_OLD_SHADING; } - if (nclass == NODE_CLASS_GROUP) { - for (ngroup = bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) { - bNodeSocket *gsock; - char name[UI_MAX_NAME_STR]; - int i, j, num = 0; - - if (ngroup->type != ntree->type) + NODE_TYPES_BEGIN(ntype) + bNodeSocketTemplate *stemp; + char name[UI_MAX_NAME_STR]; + int i, j, num = 0; + + if (compatibility && !(ntype->compatibility & compatibility)) + continue; + + if (ntype->nclass != nclass) + continue; + + for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) + if (ui_compatible_sockets(stemp->type, sock->type)) + num++; + + for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) { + if (!ui_compatible_sockets(stemp->type, sock->type)) continue; - - for (gsock = ngroup->inputs.first; gsock; gsock = gsock->next) - if (ui_compatible_sockets(gsock->type, sock->type)) - num++; - - for (i = 0, j = 0, gsock = ngroup->outputs.first; gsock; gsock = gsock->next, i++) { - if (!ui_compatible_sockets(gsock->type, sock->type)) - continue; - - if (first) { - column = uiLayoutColumn(layout, FALSE); - uiBlockSetCurLayout(block, column); - - uiItemL(column, IFACE_(cname), ICON_NODE); - but = block->buttons.last; - but->flag = UI_TEXT_LEFT; - - first = 0; - } - - if (num > 1) { - if (j == 0) { - uiItemL(column, ngroup->id.name + 2, ICON_NODE); - but = block->buttons.last; - but->flag = UI_TEXT_LEFT; - } - - BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name); - j++; - } - else - BLI_strncpy(name, ngroup->id.name + 2, UI_MAX_NAME_STR); - - but = uiDefBut(block, BUT, 0, ngroup->id.name + 2, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, - NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input")); - - argN = MEM_dupallocN(arg); - argN->type = NODE_GROUP; - argN->ngroup = ngroup; - argN->output = i; - uiButSetNFunc(but, ui_node_link, argN, NULL); + + if (first) { + column = uiLayoutColumn(layout, 0); + uiBlockSetCurLayout(block, column); + + uiItemL(column, IFACE_(cname), ICON_NODE); + but = block->buttons.last; + but->flag = UI_TEXT_LEFT; + + first = 0; } - } - } - else { - bNodeTreeType *ttype = ntreeGetType(ntree->type); - - for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) { - bNodeSocketTemplate *stemp; - char name[UI_MAX_NAME_STR]; - int i, j, num = 0; - - if (compatibility && !(ntype->compatibility & compatibility)) - continue; - - if (ntype->nclass != nclass) - continue; - - for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) - if (ui_compatible_sockets(stemp->type, sock->type)) - num++; - - for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) { - if (!ui_compatible_sockets(stemp->type, sock->type)) - continue; - - if (first) { - column = uiLayoutColumn(layout, FALSE); - uiBlockSetCurLayout(block, column); - - uiItemL(column, IFACE_(cname), ICON_NODE); + + if (num > 1) { + if (j == 0) { + uiItemL(column, IFACE_(ntype->ui_name), ICON_NODE); but = block->buttons.last; but->flag = UI_TEXT_LEFT; - - first = 0; - } - - if (num > 1) { - if (j == 0) { - uiItemL(column, IFACE_(ntype->name), ICON_NODE); - but = block->buttons.last; - but->flag = UI_TEXT_LEFT; - } - - BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name)); - j++; } - else - BLI_strncpy(name, IFACE_(ntype->name), UI_MAX_NAME_STR); - - but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, - NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input")); - - argN = MEM_dupallocN(arg); - argN->type = ntype->type; - argN->output = i; - uiButSetNFunc(but, ui_node_link, argN, NULL); + + BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name)); + j++; } + else + BLI_strncpy(name, IFACE_(ntype->ui_name), UI_MAX_NAME_STR); + + but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input")); + + argN = MEM_dupallocN(arg); + argN->type = ntype->type; + argN->output = i; + uiButSetNFunc(but, ui_node_link, argN, NULL); } - } + NODE_TYPES_END } static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name) @@ -463,7 +406,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ uiLayout *split, *column; NodeLinkArg *arg = (NodeLinkArg *)but->func_argN; bNodeSocket *sock = arg->sock; - bNodeTreeType *ntreetype = ntreeGetType(arg->ntree->type); + bNodeTreeType *ntreetype = arg->ntree->typeinfo; uiBlockSetCurLayout(block, layout); split = uiLayoutSplit(layout, 0.0f, FALSE); @@ -557,7 +500,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth) { - PointerRNA inputptr; + PointerRNA inputptr, nodeptr; uiBlock *block = uiLayoutGetBlock(layout); uiBut *bt; uiLayout *split, *row, *col; @@ -579,6 +522,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, /* socket RNA pointer */ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr); + RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); /* indented label */ memset(label, ' ', indent); @@ -627,16 +571,25 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, } else { /* input not linked, show value */ - if (input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) { - if (input->type == SOCK_VECTOR) { + if (!(input->flag & SOCK_HIDE_VALUE)) { + switch (input->type) { + case SOCK_FLOAT: + case SOCK_INT: + case SOCK_BOOLEAN: + case SOCK_RGBA: + case SOCK_STRING: + row = uiLayoutRow(split, TRUE); + uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE); + break; + case SOCK_VECTOR: row = uiLayoutRow(split, FALSE); col = uiLayoutColumn(row, FALSE); - uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE); - } - else { - row = uiLayoutRow(split, TRUE); - uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE); + break; + + default: + row = uiLayoutRow(split, FALSE); + break; } } else @@ -653,7 +606,7 @@ void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode * { bNode *tnode; - if (!ntree) + if (!ntreeIsValid(ntree)) return; /* clear for cycle check */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index a2fa7d3caf6..293913dff11 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -61,6 +61,7 @@ #include "IMB_imbuf_types.h" #include "node_intern.h" /* own include */ +#include "NOD_composite.h" /* **************** View All Operator ************** */ @@ -370,7 +371,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float float fx, fy, bufx, bufy; int ret = FALSE; - if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) { + if (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (snode->flag & SNODE_BACKDRAW) == 0) { /* use viewer image for color sampling only if we're in compositor tree * with backdrop enabled */ @@ -524,7 +525,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) ARegion *ar = CTX_wm_region(C); ImageSampleInfo *info; - if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW)) + if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW)) return OPERATOR_CANCELLED; info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 75f28baf558..2d5207e69db 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -45,10 +45,10 @@ #include "BKE_node.h" #include "ED_space_api.h" +#include "ED_node.h" #include "ED_render.h" #include "ED_screen.h" #include "ED_node.h" - #include "WM_api.h" #include "WM_types.h" @@ -59,6 +59,168 @@ #include "node_intern.h" /* own include */ + +/* ******************** tree path ********************* */ + +void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from) +{ + bNodeTreePath *path, *path_next; + for (path = snode->treepath.first; path; path = path_next) { + path_next = path->next; + MEM_freeN(path); + } + snode->treepath.first = snode->treepath.last = NULL; + + if (ntree) { + path = MEM_callocN(sizeof(bNodeTreePath), "node tree path"); + path->nodetree = ntree; + path->parent_key = NODE_INSTANCE_KEY_BASE; + if (id) + BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name)); + BLI_addtail(&snode->treepath, path); + } + + /* update current tree */ + snode->nodetree = snode->edittree = ntree; + snode->id = id; + snode->from = from; + + /* listener updates the View2D center from edittree */ + WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); +} + +void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode) +{ + bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path"); + bNodeTreePath *prev_path = snode->treepath.last; + path->nodetree = ntree; + if (gnode) { + if (prev_path) + path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode); + else + path->parent_key = NODE_INSTANCE_KEY_BASE; + + BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name)); + } + else + path->parent_key = NODE_INSTANCE_KEY_BASE; + + BLI_addtail(&snode->treepath, path); + + /* update current tree */ + snode->edittree = ntree; + + /* listener updates the View2D center from edittree */ + WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); +} + +void ED_node_tree_pop(SpaceNode *snode) +{ + bNodeTreePath *path = snode->treepath.last; + + /* don't remove root */ + if (path == snode->treepath.first) + return; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); + + /* update current tree */ + path = snode->treepath.last; + snode->edittree = path->nodetree; + + /* listener updates the View2D center from edittree */ + WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); +} + +int ED_node_tree_depth(SpaceNode *snode) +{ + return BLI_countlist(&snode->treepath); +} + +bNodeTree *ED_node_tree_get(SpaceNode *snode, int level) +{ + bNodeTreePath *path; + int i; + for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) { + if (i == level) + return path->nodetree; + } + return NULL; +} + +int ED_node_tree_path_length(SpaceNode *snode) +{ + bNodeTreePath *path; + int length = 0; + int i; + for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) { + length += strlen(path->node_name); + if (i > 0) + length += 1; /* for separator char */ + } + return length; +} + +void ED_node_tree_path_get(SpaceNode *snode, char *value) +{ + bNodeTreePath *path; + int i; + + value[0] = '\0'; + for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) { + if (i == 0) { + strcpy(value, path->node_name); + value += strlen(path->node_name); + } + else { + sprintf(value, "/%s", path->node_name); + value += strlen(path->node_name) + 1; + } + } +} + +void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length) +{ + bNodeTreePath *path; + int size, i; + + value[0] = '\0'; + for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) { + if (i == 0) { + BLI_strncpy(value, path->node_name, max_length); + size = strlen(path->node_name); + } + else { + BLI_snprintf(value, max_length, "/%s", path->node_name); + size = strlen(path->node_name) + 1; + } + max_length -= size; + if (max_length <= 0) + break; + value += size; + } +} + +void snode_group_offset(SpaceNode *snode, float *x, float *y) +{ + bNodeTreePath *path = snode->treepath.last; + float cx, cy; + + if (path) { + cx = path->nodetree->view_center[0]; + cy = path->nodetree->view_center[1]; + + if (path->prev) { + *x = cx - path->prev->nodetree->view_center[0]; + *y = cy - path->prev->nodetree->view_center[1]; + return; + } + } + + *x = *y = 0.0f; +} + /* ******************** manage regions ********************* */ ARegion *node_has_buttons_region(ScrArea *sa) @@ -124,6 +286,12 @@ static SpaceLink *node_new(const bContext *UNUSED(C)) /* backdrop */ snode->zoom = 1.0f; + /* select the first tree type for valid type */ + NODE_TREE_TYPES_BEGIN(treetype) + strcpy(snode->tree_idname, treetype->idname); + break; + NODE_TREE_TYPES_END + /* header */ ar = MEM_callocN(sizeof(ARegion), "header for node"); @@ -167,10 +335,15 @@ static SpaceLink *node_new(const bContext *UNUSED(C)) return (SpaceLink *)snode; } -/* not spacelink itself */ -static void node_free(SpaceLink *UNUSED(sl)) +static void node_free(SpaceLink *sl) { + SpaceNode *snode = (SpaceNode *)sl; + bNodeTreePath *path, *path_next; + for (path = snode->treepath.first; path; path = path_next) { + path_next = path->next; + MEM_freeN(path); + } } @@ -184,14 +357,21 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) { /* note, ED_area_tag_refresh will re-execute compositor */ SpaceNode *snode = sa->spacedata.first; - int type = snode->treetype; short shader_type = snode->shaderfrom; /* preview renders */ switch (wmn->category) { case NC_SCENE: switch (wmn->data) { - case ND_NODES: + case ND_NODES: { + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + /* shift view to node tree center */ + if (ar && snode->edittree) + UI_view2d_setcenter(&ar->v2d, snode->edittree->view_center[0], snode->edittree->view_center[1]); + + ED_area_tag_refresh(sa); + break; + } case ND_FRAME: ED_area_tag_refresh(sa); break; @@ -199,7 +379,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_redraw(sa); break; case ND_TRANSFORM_DONE: - if (type == NTREE_COMPOSIT) { + if (ED_node_is_compositor(snode)) { if (snode->flag & SNODE_AUTO_RENDER) { snode->recalc = 1; ED_area_tag_refresh(sa); @@ -211,7 +391,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) /* future: add ID checks? */ case NC_MATERIAL: - if (type == NTREE_SHADER) { + if (ED_node_is_shader(snode)) { if (wmn->data == ND_SHADING) ED_area_tag_refresh(sa); else if (wmn->data == ND_SHADING_DRAW) @@ -224,18 +404,18 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) } break; case NC_TEXTURE: - if (type == NTREE_SHADER || type == NTREE_TEXTURE) { + if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) { if (wmn->data == ND_NODES) ED_area_tag_refresh(sa); } break; case NC_WORLD: - if (type == NTREE_SHADER && shader_type == SNODE_SHADER_WORLD) { + if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) { ED_area_tag_refresh(sa); } break; case NC_OBJECT: - if (type == NTREE_SHADER) { + if (ED_node_is_shader(snode)) { if (wmn->data == ND_OB_SHADING) ED_area_tag_refresh(sa); } @@ -261,7 +441,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) break; case NC_MASK: if (wmn->action == NA_EDITED) { - if (type == NTREE_COMPOSIT) { + if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) { ED_area_tag_refresh(sa); } } @@ -269,7 +449,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) case NC_IMAGE: if (wmn->action == NA_EDITED) { - if (type == NTREE_COMPOSIT) { + if (ED_node_is_compositor(snode)) { /* note that nodeUpdateID is already called by BKE_image_signal() on all * scenes so really this is just to know if the images is used in the compo else * painting on images could become very slow when the compositor is open. */ @@ -281,7 +461,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) case NC_MOVIECLIP: if (wmn->action == NA_EDITED) { - if (type == NTREE_COMPOSIT) { + if (ED_node_is_compositor(snode)) { if (nodeUpdateID(snode->nodetree, wmn->reference)) ED_area_tag_refresh(sa); } @@ -294,11 +474,13 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa) { /* default now: refresh node is starting preview */ SpaceNode *snode = sa->spacedata.first; + + ED_preview_kill_jobs(C); + + snode_set_context(C); - snode_set_context(snode, CTX_data_scene(C)); - - if (snode->nodetree) { - if (snode->treetype == NTREE_SHADER) { + if (ntreeIsValid(snode->nodetree)) { + if (snode->nodetree->type == NTREE_SHADER) { if (GS(snode->id->name) == ID_MA) { Material *ma = (Material *)snode->id; if (ma->use_nodes) @@ -315,7 +497,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa) ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); } } - else if (snode->treetype == NTREE_COMPOSIT) { + else if (snode->nodetree->type == NTREE_COMPOSIT) { Scene *scene = (Scene *)snode->id; if (scene->use_nodes) { /* recalc is set on 3d view changes for auto compo */ @@ -328,7 +510,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa) } } } - else if (snode->treetype == NTREE_TEXTURE) { + else if (snode->nodetree->type == NTREE_TEXTURE) { Tex *tex = (Tex *)snode->id; if (tex->use_nodes) { ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); @@ -339,11 +521,14 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa) static SpaceLink *node_duplicate(SpaceLink *sl) { - SpaceNode *snoden = MEM_dupallocN(sl); + SpaceNode *snode = (SpaceNode *)sl; + SpaceNode *snoden = MEM_dupallocN(snode); /* clear or remove stuff from old */ snoden->nodetree = NULL; snoden->linkdrag.first = snoden->linkdrag.last = NULL; + + BLI_duplicatelist(&snoden->treepath, &snode->treepath); return (SpaceLink *)snoden; } @@ -415,9 +600,7 @@ static void node_main_area_init(wmWindowManager *wm, ARegion *ar) static void node_main_area_draw(const bContext *C, ARegion *ar) { - View2D *v2d = &ar->v2d; - - drawnodespace(C, ar, v2d); + drawnodespace(C, ar); } @@ -469,11 +652,8 @@ static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar) static void node_header_area_draw(const bContext *C, ARegion *ar) { - SpaceNode *snode = CTX_wm_space_node(C); - Scene *scene = CTX_data_scene(C); - /* find and set the context */ - snode_set_context(snode, scene); + snode_set_context(C); ED_region_header(C, ar); } @@ -549,6 +729,14 @@ static int node_context(const bContext *C, const char *member, bContextDataResul CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); return 1; } + else if (CTX_data_equals(member, "node_previews")) { + if (snode->nodetree) { + CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews); + } + + CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); + return 1; + } return 0; } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 743b53ce16c..15c3385f67c 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -5992,6 +5992,15 @@ static void draw_bb_quadric(BoundBox *bb, char type) glScalef(radius, radius, 2.0f * size[2]); gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); } + else if (type == OB_BOUND_CAPSULE) { + float radius = size[0] > size[1] ? size[0] : size[1]; + float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f; + glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f); + gluCylinder(qobj, radius, radius, length, 8, 1); + gluSphere(qobj, radius, 8, 4); + glTranslatef(0.0, 0.0, length); + gluSphere(qobj, radius, 8, 4); + } glPopMatrix(); gluDeleteQuadric(qobj); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d18ec225c5f..e27f00de748 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2041,11 +2041,11 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas (dob->type == OB_DUPLIGROUP && dob->animated) || !(bb_tmp = BKE_object_boundbox_get(dob->ob))) { - // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2); + // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2); use_displist = FALSE; } else { - // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2); + // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2); bb = *bb_tmp; /* must make a copy */ /* disable boundbox check for list creation */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 85375bcaf83..6ea37644533 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -159,7 +159,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i if (node && is_image_texture_node(node)) { node->id = &ima->id; - ED_node_generic_update(bmain, ma->nodetree, node); + ED_node_tag_update_nodetree(bmain, ma->nodetree); } } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index fc3bf75e784..e153651caca 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1264,7 +1264,7 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, static Material *gpu_active_node_material(Material *ma) { if (ma && ma->use_nodes && ma->nodetree) { - bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); + bNode *node = nodeGetActiveID(ma->nodetree, ID_MA); if (node) return (Material *)node->id; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 2e24b6ed78d..5ccdd5c6ac2 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -44,11 +44,19 @@ struct SpaceNode; struct bNodeLink; struct bNodeType; struct bNodeTreeExec; +struct bNodePreview; +struct bNodeInstanceHash; struct AnimData; struct bGPdata; struct uiBlock; struct Image; +/* In writefile.c: write deprecated DNA data, + * to ensure forward compatibility in 2.6x versions. + * Will be removed eventually. + */ +#define USE_NODE_COMPAT_CUSTOMNODES + #define NODE_MAXSTR 64 typedef struct bNodeStack { @@ -79,13 +87,22 @@ typedef struct bNodeStack { typedef struct bNodeSocket { struct bNodeSocket *next, *prev, *new_sock; + IDProperty *prop; /* user-defined properties */ + + char identifier[64]; /* unique identifier for mapping */ + char name[64]; /* MAX_NAME */ + /* XXX deprecated, only used for the Image and OutputFile nodes, + * should be removed at some point. + */ void *storage; /* custom storage */ short type, flag; short limit; /* max. number of links */ - short pad1; + short in_out; /* input/output type */ + struct bNodeSocketType *typeinfo; /* runtime type information */ + char idname[64]; /* runtime type identifier */ float locx, locy; @@ -98,11 +115,14 @@ typedef struct bNodeSocket { int resizemode; /* compositor resize mode of the socket */ void *cache; /* cached data from execution */ - /* internal data to retrieve relations and groups */ - int own_index; /* group socket identifiers, to find matching pairs after reading files */ + /* internal data to retrieve relations and groups + * DEPRECATED, now uses the generic identifier string instead + */ + int own_index DNA_DEPRECATED; /* group socket identifiers, to find matching pairs after reading files */ /* XXX deprecated, only used for restoring old group node links */ int to_index DNA_DEPRECATED; - struct bNodeSocket *groupsock; + /* XXX deprecated, still forward compatible since verification restores pointer from matching own_index. */ + struct bNodeSocket *groupsock DNA_DEPRECATED; struct bNodeLink *link; /* a link pointer, set in ntreeUpdateTree */ @@ -111,31 +131,34 @@ typedef struct bNodeSocket { } bNodeSocket; /* sock->type */ +#define SOCK_CUSTOM -1 /* socket has no integer type */ #define SOCK_FLOAT 0 #define SOCK_VECTOR 1 #define SOCK_RGBA 2 #define SOCK_SHADER 3 #define SOCK_BOOLEAN 4 -#define SOCK_MESH 5 +#define __SOCK_MESH 5 /* deprecated */ #define SOCK_INT 6 #define SOCK_STRING 7 #define NUM_SOCKET_TYPES 8 /* must be last! */ /* socket side (input/output) */ -#define SOCK_IN 1 -#define SOCK_OUT 2 +typedef enum eNodeSocketInOut { + SOCK_IN = 1, + SOCK_OUT = 2 +} eNodeSocketInOut; /* sock->flag, first bit is select */ /* hidden is user defined, to hide unused */ #define SOCK_HIDDEN 2 /* for quick check if socket is linked */ -#define SOCK_IN_USE 4 /* XXX deprecated */ +#define SOCK_IN_USE 4 /* unavailable is for dynamic sockets */ #define SOCK_UNAVAIL 8 - /* dynamic socket (can be modified by user) */ -#define SOCK_DYNAMIC 16 - /* group socket should not be exposed */ -#define SOCK_INTERNAL 32 + /* DEPRECATED dynamic socket (can be modified by user) */ +#define __SOCK_DYNAMIC 16 + /* DEPRECATED group socket should not be exposed */ +#define __SOCK_INTERNAL 32 /* socket collapsed in UI */ #define SOCK_COLLAPSED 64 /* hide socket value, if it gets auto default */ @@ -144,19 +167,18 @@ typedef struct bNodeSocket { /* DEPRECATED, only kept here to avoid reusing the flag */ #define SOCK_AUTO_HIDDEN__DEPRECATED 256 -typedef struct bNodePreview { - unsigned char *rect; - short xsize, ysize; - int pad; -} bNodePreview; - /* limit data in bNode to what we want to see saved? */ typedef struct bNode { struct bNode *next, *prev, *new_node; + + IDProperty *prop; /* user-defined properties */ + + struct bNodeType *typeinfo; /* runtime type information */ + char idname[64]; /* runtime type identifier */ char name[64]; /* MAX_NAME */ int flag; - short type, pad2; + short type, pad; short done, level; /* both for dependency and sorting */ short lasty, menunr; /* lasty: check preview render status, menunr: browse ID blocks */ short stack_index; /* for groupnode, offset in global caller stack */ @@ -186,10 +208,17 @@ typedef struct bNode { rctf totr; /* entire boundbox (worldspace) */ rctf butr; /* optional buttons area */ rctf prvr; /* optional preview area */ - bNodePreview *preview; /* optional preview image */ + /* XXX TODO + * Node totr size depends on the prvr size, which in turn is determined from preview size. + * In earlier versions bNodePreview was stored directly in nodes, but since now there can be + * multiple instances using different preview images it is possible that required node size varies between instances. + * preview_xsize, preview_ysize defines a common reserved size for preview rect for now, + * could be replaced by more accurate node instance drawing, but that requires removing totr from DNA + * and replacing all uses with per-instance data. + */ + short preview_xsize, preview_ysize; /* reserved size of the preview rect */ + int pad2; struct uiBlock *block; /* runtime during drawing */ - - struct bNodeType *typeinfo; /* lookup of callbacks and defaults */ } bNode; /* node->flag */ @@ -200,7 +229,7 @@ typedef struct bNode { #define NODE_ACTIVE 16 #define NODE_ACTIVE_ID 32 #define NODE_DO_OUTPUT 64 -#define NODE_GROUP_EDIT 128 +#define __NODE_GROUP_EDIT 128 /* DEPRECATED */ /* free test flag, undefined */ #define NODE_TEST 256 /* node is disabled */ @@ -221,6 +250,12 @@ typedef struct bNode { #define NODE_ACTIVE_TEXTURE (1<<14) /* use a custom color for the node */ #define NODE_CUSTOM_COLOR (1<<15) + /* Node has been initialized + * This flag indicates the node->typeinfo->init function has been called. + * In case of undefined type at creation time this can be delayed until + * until the node type is registered. + */ +#define NODE_INIT (1<<16) /* node->update */ /* XXX NODE_UPDATE is a generic update flag. More fine-grained updates @@ -229,6 +264,36 @@ typedef struct bNode { #define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ #define NODE_UPDATE_ID 1 /* associated id data block has changed */ +/* Unique hash key for identifying node instances + * Defined as a struct because DNA does not support other typedefs. + */ +typedef struct bNodeInstanceKey +{ + unsigned int value; +} bNodeInstanceKey; + +/* Base struct for entries in node instance hash. + * WARNING: pointers are cast to this struct internally, + * it must be first member in hash entry structs! + */ +typedef struct bNodeInstanceHashEntry { + bNodeInstanceKey key; + + /* tags for cleaning the cache */ + short tag; + short pad; +} bNodeInstanceHashEntry; + + +typedef struct bNodePreview { + bNodeInstanceHashEntry hash_entry; /* must be first */ + + unsigned char *rect; + short xsize, ysize; + int pad; +} bNodePreview; + + typedef struct bNodeLink { struct bNodeLink *next, *prev; @@ -263,7 +328,13 @@ typedef struct bNodeTree { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ + struct bNodeTreeType *typeinfo; /* runtime type information */ + char idname[64]; /* runtime type identifier */ + + struct StructRNA *interface_type; /* runtime RNA type of the group interface */ + struct bGPdata *gpd; /* grease pencil data */ + float view_center[2]; /* node tree stores own offset for consistent editor view */ ListBase nodes, links; @@ -272,8 +343,11 @@ typedef struct bNodeTree { * will increase this counter */ int flag; int update; /* update flags */ + short is_updating; /* flag to prevent reentrant update calls */ + short done; /* generic temporary flag for recursion check (DFS/BFS) */ + int pad2; - int nodetype; /* specific node type this tree is used for */ + int nodetype DNA_DEPRECATED; /* specific node type this tree is used for */ short edit_quality; /* Quality setting when editing */ short render_quality; /* Quality setting when rendering */ @@ -281,7 +355,16 @@ typedef struct bNodeTree { rctf viewer_border; - ListBase inputs, outputs; /* external sockets for group nodes */ + /* Lists of bNodeSocket to hold default values and own_index. + * Warning! Don't make links to these sockets, input/output nodes are used for that. + * These sockets are used only for generating external interfaces. + */ + ListBase inputs, outputs; + + /* Node preview hash table + * Only available in base node trees (e.g. scene->node_tree) + */ + struct bNodeInstanceHash *previews; /* execution data */ /* XXX It would be preferable to completely move this data out of the underlying node tree, @@ -302,10 +385,10 @@ typedef struct bNodeTree { } bNodeTree; /* ntree->type, index */ +#define NTREE_CUSTOM -1 /* for dynamically registered custom types */ #define NTREE_SHADER 0 #define NTREE_COMPOSIT 1 #define NTREE_TEXTURE 2 -#define NUM_NTREE_TYPES 3 /* ntree->init, flag */ #define NTREE_TYPE_INIT 1 @@ -320,18 +403,24 @@ typedef struct bNodeTree { /* XXX not nice, but needed as a temporary flags * for group updates after library linking. */ -#define NTREE_DO_VERSIONS_GROUP_EXPOSE 1024 +#define NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 1024 /* changes from r35033 */ +#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP 2048 /* custom_nodes branch: remove links to node tree sockets */ +#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE 4096 /* custom_nodes branch: create group input/output nodes */ /* ntree->update */ -#define NTREE_UPDATE 0xFFFF /* generic update flag (includes all others) */ -#define NTREE_UPDATE_LINKS 1 /* links have been added or removed */ -#define NTREE_UPDATE_NODES 2 /* nodes or sockets have been added or removed */ -#define NTREE_UPDATE_GROUP_IN 16 /* group inputs have changed */ -#define NTREE_UPDATE_GROUP_OUT 32 /* group outputs have changed */ -#define NTREE_UPDATE_GROUP 48 /* group has changed (generic flag including all other group flags) */ - - -/* socket value structs for input buttons */ +typedef enum eNodeTreeUpdate { + NTREE_UPDATE = 0xFFFF, /* generic update flag (includes all others) */ + NTREE_UPDATE_LINKS = 1, /* links have been added or removed */ + NTREE_UPDATE_NODES = 2, /* nodes or sockets have been added or removed */ + NTREE_UPDATE_GROUP_IN = 16, /* group inputs have changed */ + NTREE_UPDATE_GROUP_OUT = 32, /* group outputs have changed */ + NTREE_UPDATE_GROUP = 48 /* group has changed (generic flag including all other group flags) */ +} eNodeTreeUpdate; + + +/* socket value structs for input buttons + * DEPRECATED now using ID properties + */ typedef struct bNodeSocketValueInt { int subtype; /* RNA subtype */ @@ -731,8 +820,6 @@ typedef struct NodeShaderScript { char bytecode_hash[64]; char *bytecode; - - IDProperty *prop; } NodeShaderScript; typedef struct NodeShaderTangent { @@ -758,6 +845,9 @@ typedef struct NodeShaderNormalMap { #define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ #define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */ +/* proxy node flags */ +#define NODE_PROXY_AUTOTYPE 1 /* automatically change output type based on link */ + /* comp channel matte */ #define CMP_NODE_CHANNEL_MATTE_CS_RGB 1 #define CMP_NODE_CHANNEL_MATTE_CS_HSV 2 @@ -857,6 +947,39 @@ typedef struct NodeShaderNormalMap { #define CMP_NODE_MASK_MBLUR_SAMPLES_MAX 64 +/* geometry output socket defines */ +#define GEOM_OUT_GLOB 0 +#define GEOM_OUT_LOCAL 1 +#define GEOM_OUT_VIEW 2 +#define GEOM_OUT_ORCO 3 +#define GEOM_OUT_UV 4 +#define GEOM_OUT_NORMAL 5 +#define GEOM_OUT_VCOL 6 +#define GEOM_OUT_VCOL_ALPHA 7 +#define GEOM_OUT_FRONTBACK 8 + +/* material input socket defines */ +#define MAT_IN_COLOR 0 +#define MAT_IN_SPEC 1 +#define MAT_IN_REFL 2 +#define MAT_IN_NORMAL 3 +#define MAT_IN_MIR 4 +#define MAT_IN_AMB 5 +#define MAT_IN_EMIT 6 +#define MAT_IN_SPECTRA 7 +#define MAT_IN_RAY_MIRROR 8 +#define MAT_IN_ALPHA 9 +#define MAT_IN_TRANSLUCENCY 10 +#define NUM_MAT_IN 11 /* for array size */ + +/* material output socket defines */ +#define MAT_OUT_COLOR 0 +#define MAT_OUT_ALPHA 1 +#define MAT_OUT_NORMAL 2 +#define MAT_OUT_DIFFUSE 3 +#define MAT_OUT_SPEC 4 +#define MAT_OUT_AO 5 + /* image */ #define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT 1 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 4587ed948cf..b9c4788336f 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -43,6 +43,7 @@ #include "DNA_image_types.h" /* ImageUser */ #include "DNA_movieclip_types.h" /* MovieClipUser */ #include "DNA_sequence_types.h" /* SequencerScopes */ +#include "DNA_node_types.h" /* for bNodeInstanceKey */ /* Hum ... Not really nice... but needed for spacebuts. */ #include "DNA_view2d_types.h" @@ -881,6 +882,17 @@ typedef struct SpaceScript { /* Nodes Editor =========================================== */ /* Node Editor */ + +typedef struct bNodeTreePath { + struct bNodeTreePath *next, *prev; + + struct bNodeTree *nodetree; + bNodeInstanceKey parent_key; /* base key for nodes in this tree instance */ + int pad; + /* XXX this is not automatically updated when node names are changed! */ + char node_name[64]; /* MAX_NAME */ +} bNodeTreePath; + typedef struct SpaceNode { SpaceLink *next, *prev; ListBase regionbase; /* storage of regions for inactive spaces */ @@ -898,12 +910,24 @@ typedef struct SpaceNode { float zoom; /* zoom for backdrop */ float cursor[2]; /* mouse pos for drawing socketless link and adding nodes */ + /* XXX nodetree pointer info is all in the path stack now, + * remove later on and use bNodeTreePath instead. For now these variables are set when pushing/popping + * from path stack, to avoid having to update all the functions and operators. Can be done when + * design is accepted and everything is properly tested. + */ + ListBase treepath; + struct bNodeTree *nodetree, *edittree; - int treetype; /* treetype: as same nodetree->type */ + + /* tree type for the current node tree */ + char tree_idname[64]; + int treetype DNA_DEPRECATED; /* treetype: as same nodetree->type */ + int pad3; + short texfrom; /* texfrom object, world or brush */ short shaderfrom; /* shader from object or world */ short recalc; /* currently on 0/1, for auto compo */ - short pad[3]; + short pad4; ListBase linkdrag; /* temporary data for modal linking operator */ struct bGPdata *gpd; /* grease-pencil data */ @@ -922,6 +946,7 @@ typedef enum eSpaceNode_Flag { SNODE_SHOW_HIGHLIGHT = (1 << 6), SNODE_USE_HIDDEN_PREVIEW = (1 << 10), SNODE_NEW_SHADERS = (1 << 11), + SNODE_PIN = (1 << 12), } eSpaceNode_Flag; /* snode->texfrom */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 770508cd625..f8c49d683c3 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -402,14 +402,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; @@ -694,7 +693,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); @@ -760,7 +761,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); @@ -1015,9 +1018,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); @@ -1034,6 +1039,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 8038f97ec54..09d08db59d7 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 44792951cad..0375868915b 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -265,6 +265,7 @@ blender_include_dirs( ../../imbuf ../../ikplugin ../../makesdna + ../../nodes/ ../../windowmanager ../../editors/include ../../render/extern/include @@ -309,7 +310,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 c5f6744bcbe..98672f2fca2 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -327,7 +327,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..02cacb00bec 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 de7911aeccb..f5c23923f81 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -238,23 +238,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)); } } @@ -1094,10 +1103,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} }; @@ -1110,7 +1117,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..8936609c7db 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); } @@ -273,7 +274,7 @@ static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value) else ma->mode &= ~MA_RAMP_COL; if ((ma->mode & MA_RAMP_COL) && ma->ramp_col == NULL) - ma->ramp_col = add_colorband(0); + ma->ramp_col = add_colorband(false); } static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value) @@ -284,17 +285,17 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value) else ma->mode &= ~MA_RAMP_SPEC; if ((ma->mode & MA_RAMP_SPEC) && ma->ramp_spec == NULL) - ma->ramp_spec = add_colorband(0); + ma->ramp_spec = add_colorband(false); } -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..b558e6d2eeb 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,42 +205,947 @@ 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 (STREQ(nt->idname, idname)) { + result = i; + break; + } + ++i; + NODE_TREE_TYPES_END + return result; +} + +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; +} - switch (node->type) { +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 (STREQ(ntype->idname, idname)) { + 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 (STREQ(stype->idname, idname)) { + 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 (STREQ(#Category, "Node")) { \ + 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 (STREQ(#Category, "ShaderNode")) { \ + 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 (STREQ(#Category, "CompositorNode")) { \ + 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 (STREQ(#Category, "TextureNode")) { \ + 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; +} - 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 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); +} + +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 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) @@ -272,21 +1155,384 @@ static char *rna_Node_path(PointerRNA *ptr) 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); } - return &RNA_NodeSocket; + /* 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); + + /* 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,369 @@ 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) +static void rna_NodeSocketStandard_float_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; - bNode *node = (bNode *)ptr->data; + bNodeSocket *sock = ptr->data; + bNodeSocketValueFloat *dval = sock->default_value; + int subtype = sock->typeinfo->subtype; + + *min = (subtype == PROP_UNSIGNED ? 0.0f : -FLT_MAX); + *max = FLT_MAX; + *softmin = dval->min; + *softmax = dval->max; +} - if (node->id) - nodeSetActive(ntree, node); +static void rna_NodeSocketStandard_int_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) +{ + bNodeSocket *sock = ptr->data; + bNodeSocketValueFloat *dval = sock->default_value; + int subtype = sock->typeinfo->subtype; + + *min = (subtype == PROP_UNSIGNED ? 0 : INT_MIN); + *max = INT_MAX; + *softmin = dval->min; + *softmax = dval->max; +} - node_update(bmain, scene, ntree, node); +static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax) +{ + bNodeSocket *sock = ptr->data; + bNodeSocketValueVector *dval = sock->default_value; + + *min = -FLT_MAX; + *max = FLT_MAX; + *softmin = dval->min; + *softmax = dval->max; } -static void rna_NodeTree_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; + + /* 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); +} - /* 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); +/* ******** Node Types ******** */ - if (ibuf->rect_float) - memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float)); +static void rna_CompositorNode_tag_need_exec(bNode *node) +{ + node->need_exec = TRUE; +} - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - } +static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; - BKE_image_release_ibuf(ima, ibuf, lock); - } + ED_node_tag_update_nodetree(bmain, ntree); + WM_main_add_notifier(NC_IMAGE, NULL); +} - WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id); +static void rna_Node_material_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + + if (node->id) + nodeSetActive(ntree, node); + + 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 +2414,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) @@ -782,274 +2631,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 +2661,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 +2716,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 +2779,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 +2792,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 +2841,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 +2878,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 +3501,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 +3511,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 +3541,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 +3567,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 +5821,574 @@ 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_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_float_range"); + 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_int_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_int_range"); + 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_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_vector_range"); + 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"); +} - rna_def_nodetree_active_api(srna, cprop); +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"); +} + +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 +6396,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 +6445,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 +6484,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 +6513,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 +6634,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); - RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "Internal node socket to expose"); +} + +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); + 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 +6800,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 +6829,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 +6933,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 +6964,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 +6984,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 +7000,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_object.c b/source/blender/makesrna/intern/rna_object.c index 4b32c4a237a..594b86f000c 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2030,6 +2030,7 @@ static void rna_def_object(BlenderRNA *brna) {OB_BOUND_SPHERE, "SPHERE", 0, "Sphere", "Draw bounds as sphere"}, {OB_BOUND_CYLINDER, "CYLINDER", 0, "Cylinder", "Draw bounds as cylinder"}, {OB_BOUND_CONE, "CONE", 0, "Cone", "Draw bounds as cone"}, + {OB_BOUND_CAPSULE, "CAPSULE", 0, "Capsule", "Draw bounds as capsule"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 23a3c2188da..0553402d111 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1180,13 +1180,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) @@ -3109,7 +3108,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "fps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "ticrate"); RNA_def_property_ui_range(prop, 1, 60, 1, 1); - RNA_def_property_range(prop, 1, 250); + RNA_def_property_range(prop, 1, 10000); RNA_def_property_ui_text(prop, "Frames Per Second", "Nominal number of game frames per second " "(physics fixed timestep = 1/fps, independently of actual frame rate)"); @@ -5051,9 +5050,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_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 9b81f042358..ed9d12cd1e0 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -35,6 +35,8 @@ #include "BLI_math.h" +#include "BLF_translation.h" + #include "BKE_animsys.h" #include "BKE_global.h" #include "BKE_sequencer.h" @@ -50,8 +52,6 @@ #include "WM_types.h" -#include "BLF_translation.h" - typedef struct EffectInfo { const char *struct_name; const char *ui_name; @@ -1325,6 +1325,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, seq_type_items); RNA_def_property_ui_text(prop, "Type", ""); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SEQUENCE); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 4bfc54c25ed..309de9c7fd1 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)) +{ + 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), @@ -3078,6 +3151,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; @@ -3107,13 +3232,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); @@ -3138,17 +3267,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); 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); @@ -3545,6 +3686,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..e8f812506e2 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); } } @@ -381,18 +382,21 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value) else tex->flag &= ~TEX_COLORBAND; if ((tex->flag & TEX_COLORBAND) && tex->coba == NULL) - tex->coba = add_colorband(0); + tex->coba = add_colorband(false); } -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..b2f17bfed8b 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 c7b5d30e4d1..2a4a73b91c1 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1898,6 +1898,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"); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 12842085189..f3b3d6b1f53 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -123,7 +123,7 @@ set(SRC composite/nodes/node_composite_pixelate.c composite/node_composite_tree.c - composite/node_composite_util.h + composite/node_composite_util.c shader/nodes/node_shader_camera.c shader/nodes/node_shader_common.c @@ -224,13 +224,16 @@ set(SRC intern/node_common.c intern/node_socket.c + composite/node_composite_util.h shader/node_shader_util.h texture/node_texture_util.h + NOD_common.h NOD_composite.h NOD_shader.h NOD_texture.h NOD_socket.h + NOD_static_types.h intern/node_util.h intern/node_exec.h intern/node_common.h diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h new file mode 100644 index 00000000000..ac0ceab36d4 --- /dev/null +++ b/source/blender/nodes/NOD_common.h @@ -0,0 +1,54 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Toenne. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file NOD_common.h + * \ingroup nodes + */ + +#ifndef NOD_COMMON_H +#define NOD_COMMON_H + +#include "BKE_node.h" + +void register_node_type_frame(void); +void register_node_type_reroute(void); + +void register_node_type_group_input(void); +void register_node_type_group_output(void); + + +/* internal functions for editor */ +struct bNodeSocket *node_group_find_input_socket(struct bNode *groupnode, const char *identifier); +struct bNodeSocket *node_group_find_output_socket(struct bNode *groupnode, const char *identifier); +void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id); + +struct bNodeSocket *node_group_input_find_socket(struct bNode *node, const char *identifier); +struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char *identifier); +void node_group_input_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id); +void node_group_output_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id); + +#endif diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 6d60ac0bb58..f272ec670e7 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -34,105 +34,109 @@ #include "BKE_node.h" -extern bNodeTreeType ntreeType_Composite; +extern struct bNodeTreeType *ntreeType_Composite; /* ****************** types array for all composite nodes ****************** */ -void register_node_type_cmp_group(struct bNodeTreeType *ttype); +void register_node_tree_type_cmp(void); -void register_node_type_cmp_rlayers(struct bNodeTreeType *ttype); -void register_node_type_cmp_image(struct bNodeTreeType *ttype); -void register_node_type_cmp_texture(struct bNodeTreeType *ttype); -void register_node_type_cmp_value(struct bNodeTreeType *ttype); -void register_node_type_cmp_rgb(struct bNodeTreeType *ttype); -void register_node_type_cmp_curve_time(struct bNodeTreeType *ttype); -void register_node_type_cmp_movieclip(struct bNodeTreeType *ttype); +void register_node_type_cmp_group(void); +void register_node_type_cmp_forloop(void); +void register_node_type_cmp_whileloop(void); + +void register_node_type_cmp_rlayers(void); +void register_node_type_cmp_image(void); +void register_node_type_cmp_texture(void); +void register_node_type_cmp_value(void); +void register_node_type_cmp_rgb(void); +void register_node_type_cmp_curve_time(void); +void register_node_type_cmp_movieclip(void); void register_node_type_cmp_usermask(struct bNodeTreeType *ttype); -void register_node_type_cmp_composite(struct bNodeTreeType *ttype); -void register_node_type_cmp_viewer(struct bNodeTreeType *ttype); -void register_node_type_cmp_splitviewer(struct bNodeTreeType *ttype); -void register_node_type_cmp_output_file(struct bNodeTreeType *ttype); -void register_node_type_cmp_view_levels(struct bNodeTreeType *ttype); - -void register_node_type_cmp_curve_rgb(struct bNodeTreeType *ttype); -void register_node_type_cmp_mix_rgb(struct bNodeTreeType *ttype); -void register_node_type_cmp_hue_sat(struct bNodeTreeType *ttype); -void register_node_type_cmp_brightcontrast(struct bNodeTreeType *ttype); -void register_node_type_cmp_gamma(struct bNodeTreeType *ttype); -void register_node_type_cmp_invert(struct bNodeTreeType *ttype); -void register_node_type_cmp_alphaover(struct bNodeTreeType *ttype); -void register_node_type_cmp_zcombine(struct bNodeTreeType *ttype); -void register_node_type_cmp_colorbalance(struct bNodeTreeType *ttype); -void register_node_type_cmp_huecorrect(struct bNodeTreeType *ttype); - -void register_node_type_cmp_normal(struct bNodeTreeType *ttype); -void register_node_type_cmp_curve_vec(struct bNodeTreeType *ttype); -void register_node_type_cmp_map_value(struct bNodeTreeType *ttype); -void register_node_type_cmp_map_range(struct bNodeTreeType *ttype); -void register_node_type_cmp_normalize(struct bNodeTreeType *ttype); - -void register_node_type_cmp_filter(struct bNodeTreeType *ttype); -void register_node_type_cmp_blur(struct bNodeTreeType *ttype); -void register_node_type_cmp_dblur(struct bNodeTreeType *ttype); -void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype); -void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype); -void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype); -void register_node_type_cmp_inpaint(struct bNodeTreeType *ttype); -void register_node_type_cmp_despeckle(struct bNodeTreeType *ttype); -void register_node_type_cmp_defocus(struct bNodeTreeType *ttype); - -void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype); -void register_node_type_cmp_rgbtobw(struct bNodeTreeType *ttype); -void register_node_type_cmp_setalpha(struct bNodeTreeType *ttype); -void register_node_type_cmp_idmask(struct bNodeTreeType *ttype); -void register_node_type_cmp_math(struct bNodeTreeType *ttype); -void register_node_type_cmp_seprgba(struct bNodeTreeType *ttype); -void register_node_type_cmp_combrgba(struct bNodeTreeType *ttype); -void register_node_type_cmp_sephsva(struct bNodeTreeType *ttype); -void register_node_type_cmp_combhsva(struct bNodeTreeType *ttype); -void register_node_type_cmp_sepyuva(struct bNodeTreeType *ttype); -void register_node_type_cmp_combyuva(struct bNodeTreeType *ttype); -void register_node_type_cmp_sepycca(struct bNodeTreeType *ttype); -void register_node_type_cmp_combycca(struct bNodeTreeType *ttype); -void register_node_type_cmp_premulkey(struct bNodeTreeType *ttype); - -void register_node_type_cmp_diff_matte(struct bNodeTreeType *ttype); -void register_node_type_cmp_distance_matte(struct bNodeTreeType *ttype); -void register_node_type_cmp_chroma_matte(struct bNodeTreeType *ttype); -void register_node_type_cmp_color_matte(struct bNodeTreeType *ttype); -void register_node_type_cmp_channel_matte(struct bNodeTreeType *ttype); -void register_node_type_cmp_color_spill(struct bNodeTreeType *ttype); -void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype); -void register_node_type_cmp_doubleedgemask(struct bNodeTreeType *ttype); -void register_node_type_cmp_keyingscreen(struct bNodeTreeType *ttype); -void register_node_type_cmp_keying(struct bNodeTreeType *ttype); - -void register_node_type_cmp_translate(struct bNodeTreeType *ttype); -void register_node_type_cmp_rotate(struct bNodeTreeType *ttype); -void register_node_type_cmp_scale(struct bNodeTreeType *ttype); -void register_node_type_cmp_flip(struct bNodeTreeType *ttype); -void register_node_type_cmp_crop(struct bNodeTreeType *ttype); -void register_node_type_cmp_displace(struct bNodeTreeType *ttype); -void register_node_type_cmp_mapuv(struct bNodeTreeType *ttype); -void register_node_type_cmp_transform(struct bNodeTreeType *ttype); -void register_node_type_cmp_stabilize2d(struct bNodeTreeType *ttype); -void register_node_type_cmp_moviedistortion(struct bNodeTreeType *ttype); -void register_node_type_cmp_mask(struct bNodeTreeType *ttype); - -void register_node_type_cmp_glare(struct bNodeTreeType *ttype); -void register_node_type_cmp_tonemap(struct bNodeTreeType *ttype); -void register_node_type_cmp_lensdist(struct bNodeTreeType *ttype); - - -void register_node_type_cmp_colorcorrection(struct bNodeTreeType *ttype); -void register_node_type_cmp_boxmask(struct bNodeTreeType *ttype); -void register_node_type_cmp_ellipsemask(struct bNodeTreeType *ttype); -void register_node_type_cmp_bokehimage(struct bNodeTreeType *ttype); -void register_node_type_cmp_bokehblur(struct bNodeTreeType *ttype); -void register_node_type_cmp_switch(struct bNodeTreeType *ttype); -void register_node_type_cmp_pixelate(struct bNodeTreeType *ttype); -void register_node_type_cmp_trackpos(struct bNodeTreeType *ttype); +void register_node_type_cmp_composite(void); +void register_node_type_cmp_viewer(void); +void register_node_type_cmp_splitviewer(void); +void register_node_type_cmp_output_file(void); +void register_node_type_cmp_view_levels(void); + +void register_node_type_cmp_curve_rgb(void); +void register_node_type_cmp_mix_rgb(void); +void register_node_type_cmp_hue_sat(void); +void register_node_type_cmp_brightcontrast(void); +void register_node_type_cmp_gamma(void); +void register_node_type_cmp_invert(void); +void register_node_type_cmp_alphaover(void); +void register_node_type_cmp_zcombine(void); +void register_node_type_cmp_colorbalance(void); +void register_node_type_cmp_huecorrect(void); + +void register_node_type_cmp_normal(void); +void register_node_type_cmp_curve_vec(void); +void register_node_type_cmp_map_value(void); +void register_node_type_cmp_map_range(void); +void register_node_type_cmp_normalize(void); + +void register_node_type_cmp_filter(void); +void register_node_type_cmp_blur(void); +void register_node_type_cmp_dblur(void); +void register_node_type_cmp_bilateralblur(void); +void register_node_type_cmp_vecblur(void); +void register_node_type_cmp_dilateerode(void); +void register_node_type_cmp_inpaint(void); +void register_node_type_cmp_despeckle(void); +void register_node_type_cmp_defocus(void); + +void register_node_type_cmp_valtorgb(void); +void register_node_type_cmp_rgbtobw(void); +void register_node_type_cmp_setalpha(void); +void register_node_type_cmp_idmask(void); +void register_node_type_cmp_math(void); +void register_node_type_cmp_seprgba(void); +void register_node_type_cmp_combrgba(void); +void register_node_type_cmp_sephsva(void); +void register_node_type_cmp_combhsva(void); +void register_node_type_cmp_sepyuva(void); +void register_node_type_cmp_combyuva(void); +void register_node_type_cmp_sepycca(void); +void register_node_type_cmp_combycca(void); +void register_node_type_cmp_premulkey(void); + +void register_node_type_cmp_diff_matte(void); +void register_node_type_cmp_distance_matte(void); +void register_node_type_cmp_chroma_matte(void); +void register_node_type_cmp_color_matte(void); +void register_node_type_cmp_channel_matte(void); +void register_node_type_cmp_color_spill(void); +void register_node_type_cmp_luma_matte(void); +void register_node_type_cmp_doubleedgemask(void); +void register_node_type_cmp_keyingscreen(void); +void register_node_type_cmp_keying(void); + +void register_node_type_cmp_translate(void); +void register_node_type_cmp_rotate(void); +void register_node_type_cmp_scale(void); +void register_node_type_cmp_flip(void); +void register_node_type_cmp_crop(void); +void register_node_type_cmp_displace(void); +void register_node_type_cmp_mapuv(void); +void register_node_type_cmp_transform(void); +void register_node_type_cmp_stabilize2d(void); +void register_node_type_cmp_moviedistortion(void); +void register_node_type_cmp_mask(void); + +void register_node_type_cmp_glare(void); +void register_node_type_cmp_tonemap(void); +void register_node_type_cmp_lensdist(void); + + +void register_node_type_cmp_colorcorrection(void); +void register_node_type_cmp_boxmask(void); +void register_node_type_cmp_ellipsemask(void); +void register_node_type_cmp_bokehimage(void); +void register_node_type_cmp_bokehblur(void); +void register_node_type_cmp_switch(void); +void register_node_type_cmp_pixelate(void); +void register_node_type_cmp_trackpos(void); #endif diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 0a7a11e4506..9561fe00409 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -34,87 +34,91 @@ #include "BKE_node.h" -extern struct bNodeTreeType ntreeType_Shader; +extern struct bNodeTreeType *ntreeType_Shader; /* the type definitions array */ /* ****************** types array for all shaders ****************** */ -void register_node_type_sh_group(struct bNodeTreeType *ttype); - -void register_node_type_sh_output(struct bNodeTreeType *ttype); -void register_node_type_sh_material(struct bNodeTreeType *ttype); -void register_node_type_sh_camera(struct bNodeTreeType *ttype); -void register_node_type_sh_value(struct bNodeTreeType *ttype); -void register_node_type_sh_rgb(struct bNodeTreeType *ttype); -void register_node_type_sh_mix_rgb(struct bNodeTreeType *ttype); -void register_node_type_sh_valtorgb(struct bNodeTreeType *ttype); -void register_node_type_sh_rgbtobw(struct bNodeTreeType *ttype); -void register_node_type_sh_texture(struct bNodeTreeType *ttype); -void register_node_type_sh_normal(struct bNodeTreeType *ttype); -void register_node_type_sh_gamma(struct bNodeTreeType *ttype); -void register_node_type_sh_brightcontrast(struct bNodeTreeType *ttype); -void register_node_type_sh_geom(struct bNodeTreeType *ttype); -void register_node_type_sh_mapping(struct bNodeTreeType *ttype); -void register_node_type_sh_curve_vec(struct bNodeTreeType *ttype); -void register_node_type_sh_curve_rgb(struct bNodeTreeType *ttype); -void register_node_type_sh_math(struct bNodeTreeType *ttype); -void register_node_type_sh_vect_math(struct bNodeTreeType *ttype); -void register_node_type_sh_squeeze(struct bNodeTreeType *ttype); -void register_node_type_sh_dynamic(struct bNodeTreeType *ttype); -void register_node_type_sh_material_ext(struct bNodeTreeType *ttype); -void register_node_type_sh_invert(struct bNodeTreeType *ttype); -void register_node_type_sh_seprgb(struct bNodeTreeType *ttype); -void register_node_type_sh_combrgb(struct bNodeTreeType *ttype); -void register_node_type_sh_hue_sat(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_brick(struct bNodeTreeType *ttype); - -void register_node_type_sh_attribute(struct bNodeTreeType *ttype); -void register_node_type_sh_geometry(struct bNodeTreeType *ttype); -void register_node_type_sh_light_path(struct bNodeTreeType *ttype); -void register_node_type_sh_light_falloff(struct bNodeTreeType *ttype); -void register_node_type_sh_object_info(struct bNodeTreeType *ttype); -void register_node_type_sh_fresnel(struct bNodeTreeType *ttype); -void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype); -void register_node_type_sh_particle_info(struct bNodeTreeType *ttype); -void register_node_type_sh_hair_info(struct bNodeTreeType *ttype); -void register_node_type_sh_script(struct bNodeTreeType *ttype); -void register_node_type_sh_normal_map(struct bNodeTreeType *ttype); -void register_node_type_sh_tangent(struct bNodeTreeType *ttype); - -void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype); -void register_node_type_sh_background(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype); -void register_node_type_sh_bsdf_anisotropic(struct bNodeTreeType *ttype); -void register_node_type_sh_emission(struct bNodeTreeType *ttype); -void register_node_type_sh_holdout(struct bNodeTreeType *ttype); -void register_node_type_sh_volume_transparent(struct bNodeTreeType *ttype); -void register_node_type_sh_volume_isotropic(struct bNodeTreeType *ttype); -void register_node_type_sh_mix_shader(struct bNodeTreeType *ttype); -void register_node_type_sh_add_shader(struct bNodeTreeType *ttype); - -void register_node_type_sh_output_lamp(struct bNodeTreeType *ttype); -void register_node_type_sh_output_material(struct bNodeTreeType *ttype); -void register_node_type_sh_output_world(struct bNodeTreeType *ttype); - -void register_node_type_sh_tex_image(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_environment(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_sky(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_voronoi(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_gradient(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_magic(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype); -void register_node_type_sh_bump(struct bNodeTreeType *ttype); +void register_node_tree_type_sh(void); + +void register_node_type_sh_group(void); +void register_node_type_sh_forloop(void); +void register_node_type_sh_whileloop(void); + +void register_node_type_sh_output(void); +void register_node_type_sh_material(void); +void register_node_type_sh_camera(void); +void register_node_type_sh_value(void); +void register_node_type_sh_rgb(void); +void register_node_type_sh_mix_rgb(void); +void register_node_type_sh_valtorgb(void); +void register_node_type_sh_rgbtobw(void); +void register_node_type_sh_texture(void); +void register_node_type_sh_normal(void); +void register_node_type_sh_gamma(void); +void register_node_type_sh_brightcontrast(void); +void register_node_type_sh_geom(void); +void register_node_type_sh_mapping(void); +void register_node_type_sh_curve_vec(void); +void register_node_type_sh_curve_rgb(void); +void register_node_type_sh_math(void); +void register_node_type_sh_vect_math(void); +void register_node_type_sh_squeeze(void); +void register_node_type_sh_dynamic(void); +void register_node_type_sh_material_ext(void); +void register_node_type_sh_invert(void); +void register_node_type_sh_seprgb(void); +void register_node_type_sh_combrgb(void); +void register_node_type_sh_hue_sat(void); +void register_node_type_sh_tex_brick(void); + +void register_node_type_sh_attribute(void); +void register_node_type_sh_geometry(void); +void register_node_type_sh_light_path(void); +void register_node_type_sh_light_falloff(void); +void register_node_type_sh_object_info(void); +void register_node_type_sh_fresnel(void); +void register_node_type_sh_layer_weight(void); +void register_node_type_sh_tex_coord(void); +void register_node_type_sh_particle_info(void); +void register_node_type_sh_hair_info(void); +void register_node_type_sh_script(void); +void register_node_type_sh_normal_map(void); +void register_node_type_sh_tangent(void); + +void register_node_type_sh_ambient_occlusion(void); +void register_node_type_sh_background(void); +void register_node_type_sh_bsdf_diffuse(void); +void register_node_type_sh_bsdf_glossy(void); +void register_node_type_sh_bsdf_glass(void); +void register_node_type_sh_bsdf_refraction(void); +void register_node_type_sh_bsdf_translucent(void); +void register_node_type_sh_bsdf_transparent(void); +void register_node_type_sh_bsdf_velvet(void); +void register_node_type_sh_bsdf_anisotropic(void); +void register_node_type_sh_emission(void); +void register_node_type_sh_holdout(void); +void register_node_type_sh_volume_transparent(void); +void register_node_type_sh_volume_isotropic(void); +void register_node_type_sh_mix_shader(void); +void register_node_type_sh_add_shader(void); + +void register_node_type_sh_output_lamp(void); +void register_node_type_sh_output_material(void); +void register_node_type_sh_output_world(void); + +void register_node_type_sh_tex_image(void); +void register_node_type_sh_tex_environment(void); +void register_node_type_sh_tex_sky(void); +void register_node_type_sh_tex_voronoi(void); +void register_node_type_sh_tex_gradient(void); +void register_node_type_sh_tex_magic(void); +void register_node_type_sh_tex_wave(void); +void register_node_type_sh_tex_musgrave(void); +void register_node_type_sh_tex_noise(void); +void register_node_type_sh_tex_checker(void); +void register_node_type_sh_bump(void); #endif diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h index b14f7c4e884..5f7da1c3f4d 100644 --- a/source/blender/nodes/NOD_socket.h +++ b/source/blender/nodes/NOD_socket.h @@ -45,41 +45,11 @@ struct bNodeTree; struct bNode; struct bNodeStack; -void node_socket_type_init(struct bNodeSocketType *types[]); - -void *node_socket_make_default_value(int type); -void node_socket_free_default_value(int type, void *default_value); -void node_socket_init_default_value(int type, void *default_value); -void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value); -void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value); - -void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max); -void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max); -void node_socket_set_default_value_boolean(void *default_value, char value); -void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max); -void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a); -void node_socket_set_default_value_shader(void *default_value); -void node_socket_set_default_value_mesh(void *default_value); -void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value); - -struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp); -struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp); +struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out); void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node); - -/* Socket Converters */ - -#define SOCK_VECTOR_X 1 -#define SOCK_VECTOR_Y 2 -#define SOCK_VECTOR_Z 3 - -#define SOCK_RGBA_R 1 -#define SOCK_RGBA_G 2 -#define SOCK_RGBA_B 3 -#define SOCK_RGBA_A 4 - -#define SOCK_MESH_VERT_CO 1 -#define SOCK_MESH_VERT_NO 2 +void node_socket_init_default_value(struct bNodeSocket *sock); +void register_standard_node_socket_types(void); #endif diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/nodes/NOD_static_types.h index b7ec9235483..9d044772274 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -20,8 +20,8 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/makesrna/intern/rna_nodetree_types.h - * \ingroup RNA +/** \file blender/makesrna/intern/NOD_static_types.h + * \ingroup nodes */ /* intentionally no include guard */ @@ -34,6 +34,12 @@ /* 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( Node, NODE_FRAME, def_frame, "FRAME", Frame, "Frame", "" ) +DefNode( Node, NODE_GROUP, def_group, "GROUP", Group, "Group", "" ) +DefNode( Node, NODE_GROUP_INPUT, def_group_input, "GROUP_INPUT", GroupInput, "Group Input", "" ) +DefNode( Node, NODE_GROUP_OUTPUT, def_group_output, "GROUP_OUTPUT", GroupOutput, "Group Output", "" ) +DefNode( Node, NODE_REROUTE, 0, "REROUTE", Reroute, "Reroute", "" ) + 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", "" ) @@ -186,7 +192,7 @@ DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYIN 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", "" ) @@ -209,6 +215,18 @@ DefNode( TextureNode, TEX_NODE_COMPOSE, 0, "COMPO 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", "" ) +DefNode( TextureNode, TEX_NODE_AT, 0, "AT", At, "At", "" ) +/* procedural textures */ +DefNode( TextureNode, TEX_NODE_PROC+TEX_VORONOI, 0, "TEX_VORONOI", TexVoronoi, "Voronoi", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_BLEND, 0, "TEX_BLEND", TexBlend, "Blend", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_MAGIC, 0, "TEX_MAGIC", TexMagic, "Magic", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_MARBLE, 0, "TEX_MARBLE", TexMarble, "Marble", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_CLOUDS, 0, "TEX_CLOUDS", TexClouds, "Clouds", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_WOOD, 0, "TEX_WOOD", TexWood, "Wood", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_MUSGRAVE, 0, "TEX_MUSGRAVE", TexMusgrave, "Musgrave", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NOISE", TexNoise, "Noise", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" ) +DefNode( TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" ) /* undefine macros */ diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h index a1be9963b8a..ea003f23960 100644 --- a/source/blender/nodes/NOD_texture.h +++ b/source/blender/nodes/NOD_texture.h @@ -34,48 +34,52 @@ #include "BKE_node.h" -extern bNodeTreeType ntreeType_Texture; +extern struct bNodeTreeType *ntreeType_Texture; /* ****************** types array for all texture nodes ****************** */ -void register_node_type_tex_group(struct bNodeTreeType *ttype); +void register_node_tree_type_tex(void); -void register_node_type_tex_math(struct bNodeTreeType *ttype); -void register_node_type_tex_mix_rgb(struct bNodeTreeType *ttype); -void register_node_type_tex_valtorgb(struct bNodeTreeType *ttype); -void register_node_type_tex_valtonor(struct bNodeTreeType *ttype); -void register_node_type_tex_rgbtobw(struct bNodeTreeType *ttype); -void register_node_type_tex_output(struct bNodeTreeType *ttype); -void register_node_type_tex_viewer(struct bNodeTreeType *ttype); -void register_node_type_tex_checker(struct bNodeTreeType *ttype); -void register_node_type_tex_texture(struct bNodeTreeType *ttype); -void register_node_type_tex_bricks(struct bNodeTreeType *ttype); -void register_node_type_tex_image(struct bNodeTreeType *ttype); -void register_node_type_tex_curve_rgb(struct bNodeTreeType *ttype); -void register_node_type_tex_curve_time(struct bNodeTreeType *ttype); -void register_node_type_tex_invert(struct bNodeTreeType *ttype); -void register_node_type_tex_hue_sat(struct bNodeTreeType *ttype); -void register_node_type_tex_coord(struct bNodeTreeType *ttype); -void register_node_type_tex_distance(struct bNodeTreeType *ttype); +void register_node_type_tex_group(void); +void register_node_type_tex_forloop(void); +void register_node_type_tex_whileloop(void); -void register_node_type_tex_rotate(struct bNodeTreeType *ttype); -void register_node_type_tex_translate(struct bNodeTreeType *ttype); -void register_node_type_tex_scale(struct bNodeTreeType *ttype); -void register_node_type_tex_at(struct bNodeTreeType *ttype); +void register_node_type_tex_math(void); +void register_node_type_tex_mix_rgb(void); +void register_node_type_tex_valtorgb(void); +void register_node_type_tex_valtonor(void); +void register_node_type_tex_rgbtobw(void); +void register_node_type_tex_output(void); +void register_node_type_tex_viewer(void); +void register_node_type_tex_checker(void); +void register_node_type_tex_texture(void); +void register_node_type_tex_bricks(void); +void register_node_type_tex_image(void); +void register_node_type_tex_curve_rgb(void); +void register_node_type_tex_curve_time(void); +void register_node_type_tex_invert(void); +void register_node_type_tex_hue_sat(void); +void register_node_type_tex_coord(void); +void register_node_type_tex_distance(void); -void register_node_type_tex_compose(struct bNodeTreeType *ttype); -void register_node_type_tex_decompose(struct bNodeTreeType *ttype); +void register_node_type_tex_rotate(void); +void register_node_type_tex_translate(void); +void register_node_type_tex_scale(void); +void register_node_type_tex_at(void); -void register_node_type_tex_proc_voronoi(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_blend(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_magic(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_marble(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_clouds(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_wood(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_musgrave(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_noise(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_stucci(struct bNodeTreeType *ttype); -void register_node_type_tex_proc_distnoise(struct bNodeTreeType *ttype); +void register_node_type_tex_compose(void); +void register_node_type_tex_decompose(void); + +void register_node_type_tex_proc_voronoi(void); +void register_node_type_tex_proc_blend(void); +void register_node_type_tex_proc_magic(void); +void register_node_type_tex_proc_marble(void); +void register_node_type_tex_proc_clouds(void); +void register_node_type_tex_proc_wood(void); +void register_node_type_tex_proc_musgrave(void); +void register_node_type_tex_proc_noise(void); +void register_node_type_tex_proc_stucci(void); +void register_node_type_tex_proc_distnoise(void); #endif diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 999bcb9bba5..200e5341868 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -44,6 +44,7 @@ #include "BKE_animsys.h" #include "BKE_colortools.h" +#include "BKE_context.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_main.h" @@ -64,14 +65,17 @@ #include "COM_compositor.h" #endif -static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) +static void composite_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from) { - Scene *sce; - for (sce= main->scene.first; sce; sce= sce->id.next) { - if (sce->nodetree) { - func(calldata, &sce->id, sce->nodetree); - } - } + Scene *scene = CTX_data_scene(C); + + *r_from = NULL; + *r_id = &scene->id; + *r_ntree = scene->nodetree; + + /* update output sockets based on available layers */ + ntreeCompositForceHidden(scene->nodetree, scene); + } static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func) @@ -85,6 +89,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa func(calldata, NODE_CLASS_MATTE, N_("Matte")); func(calldata, NODE_CLASS_DISTORT, N_("Distort")); func(calldata, NODE_CLASS_GROUP, N_("Group")); + func(calldata, NODE_CLASS_INTERFACE, N_("Interface")); func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); } @@ -102,33 +107,17 @@ static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node) static void free_cache(bNodeTree *ntree) { bNode *node; - for (node= ntree->nodes.first; node; node= node->next) + for (node = ntree->nodes.first; node; node = node->next) free_node_cache(ntree, node); } -static void update_node(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *sock; - - for (sock= node->outputs.first; sock; sock= sock->next) { - if (sock->cache) { - //free_compbuf(sock->cache); - //sock->cache= NULL; - } - } - node->need_exec= 1; - /* individual node update call */ - if (node->typeinfo->updatefunc) - node->typeinfo->updatefunc(ntree, node); -} - /* local tree then owns all compbufs */ static void localize(bNodeTree *localtree, bNodeTree *ntree) { bNode *node, *node_next; bNodeSocket *sock; - for (node= ntree->nodes.first; node; node= node->next) { + for (node = ntree->nodes.first; node; node = node->next) { /* ensure new user input gets handled ok */ node->need_exec= 0; node->new_node->original = node; @@ -145,16 +134,6 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) } } - /* copy over the preview buffers to update graduatly */ - if (node->preview) { - bNodePreview *preview = MEM_callocN(sizeof(bNodePreview), "Preview"); - preview->pad = node->preview->pad; - preview->xsize = node->preview->xsize; - preview->ysize = node->preview->ysize; - preview->rect = MEM_dupallocN(node->preview->rect); - node->new_node->preview = preview; - } - for (sock= node->outputs.first; sock; sock= sock->next) { sock->new_sock->cache= sock->cache; sock->cache= NULL; @@ -163,7 +142,7 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) } /* replace muted nodes and reroute nodes by internal links */ - for (node= localtree->nodes.first; node; node= node_next) { + for (node = localtree->nodes.first; node; node = node_next) { node_next = node->next; if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { @@ -183,24 +162,8 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) } } -static void local_sync(bNodeTree *localtree, bNodeTree *ntree) +static void local_sync(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree)) { - bNode *lnode; - - /* move over the compbufs and previews */ - for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) { - if ( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) { - if (ntreeNodeExists(ntree, lnode->new_node)) { - - if (lnode->preview && lnode->preview->rect) { - nodeFreePreview(lnode->new_node); - lnode->new_node->preview= lnode->preview; - lnode->preview= NULL; - } - - } - } - } } static void local_merge(bNodeTree *localtree, bNodeTree *ntree) @@ -245,27 +208,38 @@ static void update(bNodeTree *ntree) ntreeSetOutput(ntree); ntree_update_reroute_nodes(ntree); + + if (ntree->update & NTREE_UPDATE_NODES) { + /* clean up preview cache, in case nodes have been removed */ + BKE_node_preview_remove_unused(ntree); + } } -bNodeTreeType ntreeType_Composite = { - /* type */ NTREE_COMPOSIT, - /* idname */ "NTCompositing Nodetree", +bNodeTreeType *ntreeType_Composite; + +void register_node_tree_type_cmp(void) +{ + bNodeTreeType *tt = ntreeType_Composite = MEM_callocN(sizeof(bNodeTreeType), "compositor node tree type"); - /* node_types */ { NULL, NULL }, + tt->type = NTREE_COMPOSIT; + strcpy(tt->idname, "CompositorNodeTree"); + strcpy(tt->ui_name, "Compositing"); + tt->ui_icon = 0; /* defined in drawnode.c */ + strcpy(tt->ui_description, ""); - /* free_cache */ free_cache, - /* free_node_cache */ free_node_cache, - /* foreach_nodetree */ foreach_nodetree, - /* foreach_nodeclass */ foreach_nodeclass, - /* localize */ localize, - /* local_sync */ local_sync, - /* local_merge */ local_merge, - /* update */ update, - /* update_node */ update_node, - /* validate_link */ NULL, - /* update_internal_links */ node_update_internal_links_default -}; - + tt->free_cache = free_cache; + tt->free_node_cache = free_node_cache; + tt->foreach_nodeclass = foreach_nodeclass; + tt->localize = localize; + tt->local_sync = local_sync; + tt->local_merge = local_merge; + tt->update = update; + tt->get_from_context = composite_get_from_context; + + tt->ext.srna = &RNA_CompositorNodeTree; + + ntreeTypeAdd(tt); +} void *COM_linker_hack = NULL; diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c new file mode 100644 index 00000000000..6209ca6aa4f --- /dev/null +++ b/source/blender/nodes/composite/node_composite_util.c @@ -0,0 +1,59 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/node_composite_util.c + * \ingroup nodes + */ + +#include "node_composite_util.h" + + +int cmp_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return (strcmp(ntree->idname, "CompositorNodeTree")==0); +} + +void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock; + for (sock= node->outputs.first; sock; sock= sock->next) { + if(sock->cache) { + //free_compbuf(sock->cache); + //sock->cache= NULL; + } + } + node->need_exec= 1; +} + +void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + + ntype->poll = cmp_node_poll_default; + ntype->updatefunc = cmp_node_update_default; + ntype->update_internal_links = node_update_internal_links_default; +} diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h index a3c4bffe018..3f9cfc03089 100644 --- a/source/blender/nodes/composite/node_composite_util.h +++ b/source/blender/nodes/composite/node_composite_util.h @@ -59,4 +59,9 @@ #define CMP_SCALE_MAX 12000 +int cmp_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); +void cmp_node_update_default(struct bNodeTree *UNUSED(ntree), struct bNode *node); +void cmp_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag); + #endif /* __NODE_COMPOSITE_UTIL_H__ */ + diff --git a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c index 217670621a8..cdfcf045e35 100644 --- a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c +++ b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c @@ -43,19 +43,19 @@ static bNodeSocketTemplate cmp_node_alphaover_out[] = { { -1, 0, "" } }; -static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= MEM_callocN(sizeof(NodeTwoFloats), "NodeTwoFloats"); } -void register_node_type_cmp_alphaover(bNodeTreeType *ttype) +void register_node_type_cmp_alphaover(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_ALPHAOVER, "Alpha Over", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_ALPHAOVER, "Alpha Over", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_alphaover_in, cmp_node_alphaover_out); node_type_init(&ntype, node_alphaover_init); node_type_storage(&ntype, "NodeTwoFloats", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c index b8bf379b14b..1f80df602df 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_bilateralblur_out[] = { { -1, 0, "" } }; -static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node) { NodeBilateralBlurData *nbbd = MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data"); node->storage = nbbd; @@ -51,14 +51,14 @@ static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *no nbbd->sigma_space = 5.0; } -void register_node_type_cmp_bilateralblur(bNodeTreeType *ttype) +void register_node_type_cmp_bilateralblur(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_bilateralblur_in, cmp_node_bilateralblur_out); node_type_init(&ntype, node_composit_init_bilateralblur); node_type_storage(&ntype, "NodeBilateralBlurData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c index 20fce05a40e..e544ec7d9d8 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.c +++ b/source/blender/nodes/composite/nodes/node_composite_blur.c @@ -44,21 +44,21 @@ static bNodeSocketTemplate cmp_node_blur_out[] = { { -1, 0, "" } }; -static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node) { NodeBlurData *data = MEM_callocN(sizeof(NodeBlurData), "node blur data"); data->filtertype = R_FILTER_GAUSS; node->storage = data; } -void register_node_type_cmp_blur(bNodeTreeType *ttype) +void register_node_type_cmp_blur(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW | NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW | NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_blur_in, cmp_node_blur_out); node_type_init(&ntype, node_composit_init_blur); node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c index ea3162a9e55..a2d9e6e1473 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c @@ -49,19 +49,19 @@ static bNodeSocketTemplate cmp_node_bokehblur_out[] = { { -1, 0, "" } }; -static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode *node) { node->custom3 = 4.0f; node->custom4 = 16.0f; } -void register_node_type_cmp_bokehblur(bNodeTreeType *ttype) +void register_node_type_cmp_bokehblur(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_bokehblur_in, cmp_node_bokehblur_out); node_type_init(&ntype, node_composit_init_bokehblur); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c index b006280ca8a..c04682c42a6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c +++ b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c @@ -41,7 +41,8 @@ static bNodeSocketTemplate cmp_node_bokehimage_out[] = { { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) + +static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node) { NodeBokehImage * data = MEM_callocN(sizeof(NodeBokehImage), "NodeBokehImage"); data->angle = 0.0f; @@ -52,14 +53,14 @@ static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node, node->storage = data; } -void register_node_type_cmp_bokehimage(bNodeTreeType *ttype) +void register_node_type_cmp_bokehimage(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_BOKEHIMAGE, "Bokeh Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_BOKEHIMAGE, "Bokeh Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_bokehimage_out); node_type_init(&ntype, node_composit_init_bokehimage); node_type_storage(&ntype, "NodeBokehImage", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c index eb2c58894f3..41820457b4b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c +++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_boxmask_out[] = { { -1, 0, "" } }; -static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node) { NodeBoxMask *data = MEM_callocN(sizeof(NodeBoxMask), "NodeBoxMask"); data->x = 0.5; @@ -55,16 +55,16 @@ static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bN node->storage = data; } -void register_node_type_cmp_boxmask(bNodeTreeType *ttype) +void register_node_type_cmp_boxmask(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MASK_BOX, "Box Mask", NODE_CLASS_MATTE, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MASK_BOX, "Box Mask", NODE_CLASS_MATTE, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_boxmask_in, cmp_node_boxmask_out); node_type_init(&ntype, node_composit_init_boxmask); node_type_storage(&ntype, "NodeBoxMask", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c index 025f5c03c7c..669668fa654 100644 --- a/source/blender/nodes/composite/nodes/node_composite_brightness.c +++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c @@ -48,12 +48,12 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = { }; -void register_node_type_cmp_brightcontrast(bNodeTreeType *ttype) +void register_node_type_cmp_brightcontrast(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c index acb0566be7c..92cc55f511f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_channel_matte_out[] = { {-1, 0, ""} }; -static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); node->storage=c; @@ -60,14 +60,14 @@ static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *no node->custom2= 2; /* Green Channel */ } -void register_node_type_cmp_channel_matte(bNodeTreeType *ttype) +void register_node_type_cmp_channel_matte(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_CHANNEL_MATTE, "Channel Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_CHANNEL_MATTE, "Channel Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_channel_matte_in, cmp_node_channel_matte_out); node_type_init(&ntype, node_composit_init_channel_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c index 29782c3bc51..2e04ddb4f9f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_chroma_out[] = { {-1, 0, ""} }; -static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); node->storage= c; @@ -56,14 +56,14 @@ static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *nod c->fstrength= 1.0f; } -void register_node_type_cmp_chroma_matte(bNodeTreeType *ttype) +void register_node_type_cmp_chroma_matte(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_chroma_in, cmp_node_chroma_out); node_type_init(&ntype, node_composit_init_chroma_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c index 9905a2446b8..2ecb5e3fb7c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_color_out[] = { {-1, 0, ""} }; -static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node color"); node->storage= c; @@ -56,14 +56,14 @@ static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node c->fstrength= 1.0f; } -void register_node_type_cmp_color_matte(bNodeTreeType *ttype) +void register_node_type_cmp_color_matte(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COLOR_MATTE, "Color Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COLOR_MATTE, "Color Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_color_in, cmp_node_color_out); node_type_init(&ntype, node_composit_init_color_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c index 32fa446790e..60cfd7c90f3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = { {-1, 0, ""} }; -static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node) { NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill"); node->storage=ncs; @@ -54,14 +54,14 @@ static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node ncs->unspill=0; /* do not use unspill */ } -void register_node_type_cmp_color_spill(bNodeTreeType *ttype) +void register_node_type_cmp_color_spill(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_color_spill_in, cmp_node_color_spill_out); node_type_init(&ntype, node_composit_init_color_spill); node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c index da9ce64d994..693680f58a8 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c @@ -46,7 +46,7 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = { {-1, 0, ""} }; -static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node) { NodeColorBalance *n= node->storage= MEM_callocN(sizeof(NodeColorBalance), "node colorbalance"); @@ -55,15 +55,15 @@ static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *nod n->gain[0] = n->gain[1] = n->gain[2] = 1.0f; } -void register_node_type_cmp_colorbalance(bNodeTreeType *ttype) +void register_node_type_cmp_colorbalance(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_colorbalance_in, cmp_node_colorbalance_out); node_type_size(&ntype, 400, 200, 400); node_type_init(&ntype, node_composit_init_colorbalance); node_type_storage(&ntype, "NodeColorBalance", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c index 19f2fad2e42..9b09462ed0f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c @@ -47,7 +47,7 @@ static bNodeSocketTemplate cmp_node_colorcorrection_out[] = { { -1,0,""} }; -static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *node) { NodeColorCorrection *n= node->storage= MEM_callocN(sizeof(NodeColorCorrection), "node colorcorrection"); n->startmidtones = 0.2f; @@ -75,15 +75,15 @@ static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode * node->custom1 = 7; // red + green + blue enabled } -void register_node_type_cmp_colorcorrection(bNodeTreeType *ttype) +void register_node_type_cmp_colorcorrection(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COLORCORRECTION, "Color Correction", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COLORCORRECTION, "Color Correction", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_colorcorrection_in, cmp_node_colorcorrection_out); node_type_size(&ntype, 400, 200, 600); node_type_init(&ntype, node_composit_init_colorcorrection); node_type_storage(&ntype, "NodeColorCorrection", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c index 7198798a152..44643724073 100644 --- a/source/blender/nodes/composite/nodes/node_composite_common.c +++ b/source/blender/nodes/composite/nodes/node_composite_common.c @@ -33,25 +33,35 @@ #include "DNA_node_types.h" #include "node_composite_util.h" +#include "NOD_common.h" #include "node_common.h" #include "node_exec.h" #include "BKE_node.h" -void register_node_type_cmp_group(bNodeTreeType *ttype) +#include "RNA_access.h" + +void register_node_type_cmp_group(void) { static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); + + /* NB: cannot use sh_node_type_base for node group, because it would map the node type + * to the shared NODE_GROUP integer type id. + */ + node_type_base_custom(&ntype, "CompositorNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); + ntype.type = NODE_GROUP; + ntype.poll = cmp_node_poll_default; + ntype.update_internal_links = node_update_internal_links_default; + ntype.ext.srna = RNA_struct_find("CompositorNodeGroup"); + BLI_assert(ntype.ext.srna != NULL); + RNA_struct_blender_type_set(ntype.ext.srna, &ntype); + node_type_socket_templates(&ntype, NULL, NULL); node_type_size(&ntype, 120, 60, 200); node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_group_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_group_template); node_type_update(&ntype, NULL, node_group_verify); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); + strcpy(ntype.group_tree_idname, "CompositorNodeTree"); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c index ea281a3f556..7fa7a5048ab 100644 --- a/source/blender/nodes/composite/nodes/node_composite_composite.c +++ b/source/blender/nodes/composite/nodes/node_composite_composite.c @@ -39,15 +39,15 @@ static bNodeSocketTemplate cmp_node_composite_in[] = { { -1, 0, "" } }; -void register_node_type_cmp_composite(bNodeTreeType *ttype) +void register_node_type_cmp_composite(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW); + cmp_node_type_base(&ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW); node_type_socket_templates(&ntype, cmp_node_composite_in, NULL); /* Do not allow muting for this node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_crop.c b/source/blender/nodes/composite/nodes/node_composite_crop.c index 10af55480cd..677dafeb527 100644 --- a/source/blender/nodes/composite/nodes/node_composite_crop.c +++ b/source/blender/nodes/composite/nodes/node_composite_crop.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_crop_out[] = { { -1, 0, "" } }; -static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node) { NodeTwoXYs *nxy= MEM_callocN(sizeof(NodeTwoXYs), "node xy data"); node->storage= nxy; @@ -53,14 +53,14 @@ static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNode nxy->y2= 0; } -void register_node_type_cmp_crop(bNodeTreeType *ttype) +void register_node_type_cmp_crop(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_CROP, "Crop", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_CROP, "Crop", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_crop_in, cmp_node_crop_out); node_type_init(&ntype, node_composit_init_crop); node_type_storage(&ntype, "NodeTwoXYs", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.c b/source/blender/nodes/composite/nodes/node_composite_curves.c index 9f40159baf3..2bf901491bf 100644 --- a/source/blender/nodes/composite/nodes/node_composite_curves.c +++ b/source/blender/nodes/composite/nodes/node_composite_curves.c @@ -41,24 +41,24 @@ static bNodeSocketTemplate cmp_node_time_out[] = { { -1, 0, "" } }; -static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1= 1; node->custom2= 250; node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } -void register_node_type_cmp_curve_time(bNodeTreeType *ttype) +void register_node_type_cmp_curve_time(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_time_out); node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_curves_time); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -74,22 +74,22 @@ static bNodeSocketTemplate cmp_node_curve_vec_out[] = { { -1, 0, "" } }; -static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); } -void register_node_type_cmp_curve_vec(bNodeTreeType *ttype) +void register_node_type_cmp_curve_vec(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_curve_vec_in, cmp_node_curve_vec_out); node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, node_composit_init_curve_vec); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -107,20 +107,20 @@ static bNodeSocketTemplate cmp_node_curve_rgb_out[] = { { -1, 0, "" } }; -static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } -void register_node_type_cmp_curve_rgb(bNodeTreeType *ttype) +void register_node_type_cmp_curve_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_curve_rgb_in, cmp_node_curve_rgb_out); node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, node_composit_init_curve_rgb); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c index c05f1d6fcff..9581ef981cb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_defocus.c +++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_defocus_out[] = { { -1, 0, "" } }; -static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node) { /* qdn: defocus node */ NodeDefocus *nbd = MEM_callocN(sizeof(NodeDefocus), "node defocus data"); @@ -61,14 +61,14 @@ static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bN node->storage = nbd; } -void register_node_type_cmp_defocus(bNodeTreeType *ttype) +void register_node_type_cmp_defocus(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_defocus_in, cmp_node_defocus_out); node_type_init(&ntype, node_composit_init_defocus); node_type_storage(&ntype, "NodeDefocus", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_despeckle.c b/source/blender/nodes/composite/nodes/node_composite_despeckle.c index 816a1803e47..486c69caba0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_despeckle.c +++ b/source/blender/nodes/composite/nodes/node_composite_despeckle.c @@ -42,19 +42,19 @@ static bNodeSocketTemplate cmp_node_despeckle_out[] = { { -1, 0, "" } }; -static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node) { node->custom3 = 0.5f; node->custom4 = 0.5f; } -void register_node_type_cmp_despeckle(bNodeTreeType *ttype) +void register_node_type_cmp_despeckle(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_despeckle_in, cmp_node_despeckle_out); node_type_init(&ntype, node_composit_init_despeckle); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c index 29712d54e32..99170c294de 100644 --- a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_diff_matte_out[] = { {-1, 0, ""} }; -static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); node->storage= c; @@ -53,14 +53,14 @@ static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node, c->t2= 0.1f; } -void register_node_type_cmp_diff_matte(bNodeTreeType *ttype) +void register_node_type_cmp_diff_matte(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DIFF_MATTE, "Difference Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DIFF_MATTE, "Difference Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_diff_matte_in, cmp_node_diff_matte_out); node_type_init(&ntype, node_composit_init_diff_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c index fabc54f61b3..d9caff0d495 100644 --- a/source/blender/nodes/composite/nodes/node_composite_dilate.c +++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c @@ -44,22 +44,21 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[] = { { -1, 0, "" } }; -static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node) { NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), "NodeDilateErode"); data->falloff = PROP_SMOOTH; node->storage = data; } -void register_node_type_cmp_dilateerode(bNodeTreeType *ttype) +void register_node_type_cmp_dilateerode(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DILATEERODE, "Dilate/Erode", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DILATEERODE, "Dilate/Erode", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_dilateerode_in, cmp_node_dilateerode_out); node_type_init(&ntype, node_composit_init_dilateerode); - node_type_storage(&ntype, "NodeDilateErode", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c index 6197d78563c..7edef3bf319 100644 --- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate cmp_node_dblur_out[] = { { -1, 0, "" } }; -static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node) { NodeDBlurData *ndbd = MEM_callocN(sizeof(NodeDBlurData), "node dblur data"); node->storage = ndbd; @@ -50,14 +50,14 @@ static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNod ndbd->center_y = 0.5; } -void register_node_type_cmp_dblur(bNodeTreeType *ttype) +void register_node_type_cmp_dblur(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_dblur_in, cmp_node_dblur_out); node_type_init(&ntype, node_composit_init_dblur); node_type_storage(&ntype, "NodeDBlurData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_displace.c b/source/blender/nodes/composite/nodes/node_composite_displace.c index 251345d8a28..33f82355629 100644 --- a/source/blender/nodes/composite/nodes/node_composite_displace.c +++ b/source/blender/nodes/composite/nodes/node_composite_displace.c @@ -47,12 +47,12 @@ static bNodeSocketTemplate cmp_node_displace_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_displace(bNodeTreeType *ttype) +void register_node_type_cmp_displace(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_displace_in, cmp_node_displace_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c index 26f8055e7f2..b75301676e6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_distance_matte_out[] = { {-1, 0, ""} }; -static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); node->storage= c; @@ -54,14 +54,14 @@ static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *n c->t2= 0.1f; } -void register_node_type_cmp_distance_matte(bNodeTreeType *ttype) +void register_node_type_cmp_distance_matte(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_DIST_MATTE, "Distance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DIST_MATTE, "Distance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_distance_matte_in, cmp_node_distance_matte_out); node_type_init(&ntype, node_composit_init_distance_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c index d5dd63a4042..0659a353afb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c +++ b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c @@ -42,12 +42,13 @@ static bNodeSocketTemplate cmp_node_doubleedgemask_out[] = { { -1, 0, "" } // output socket array terminator }; -void register_node_type_cmp_doubleedgemask(bNodeTreeType *ttype) +void register_node_type_cmp_doubleedgemask(void) { static bNodeType ntype; // allocate a node type data structure - node_type_base(ttype, &ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out); node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c index c2e34dc07a0..c4a01abc6d1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c +++ b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_ellipsemask_out[] = { { -1, 0, "" } }; -static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node) { NodeEllipseMask *data = MEM_callocN(sizeof(NodeEllipseMask), "NodeEllipseMask"); data->x = 0.5; @@ -55,17 +55,17 @@ static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node node->storage = data; } -void register_node_type_cmp_ellipsemask(bNodeTreeType *ttype) +void register_node_type_cmp_ellipsemask(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MASK_ELLIPSE, "Ellipse Mask", NODE_CLASS_MATTE, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MASK_ELLIPSE, "Ellipse Mask", NODE_CLASS_MATTE, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_ellipsemask_in, cmp_node_ellipsemask_out); node_type_size(&ntype, 260, 110, 320); node_type_init(&ntype, node_composit_init_ellipsemask); node_type_storage(&ntype, "NodeEllipseMask", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.c b/source/blender/nodes/composite/nodes/node_composite_filter.c index 3ecc7282632..408c2ff8d73 100644 --- a/source/blender/nodes/composite/nodes/node_composite_filter.c +++ b/source/blender/nodes/composite/nodes/node_composite_filter.c @@ -43,13 +43,13 @@ static bNodeSocketTemplate cmp_node_filter_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_filter(bNodeTreeType *ttype) +void register_node_type_cmp_filter(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out); node_type_label(&ntype, node_filter_label); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_flip.c b/source/blender/nodes/composite/nodes/node_composite_flip.c index f56805809c5..f05447d79c2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_flip.c +++ b/source/blender/nodes/composite/nodes/node_composite_flip.c @@ -43,12 +43,12 @@ static bNodeSocketTemplate cmp_node_flip_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_flip(bNodeTreeType *ttype) +void register_node_type_cmp_flip(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_flip_in, cmp_node_flip_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_gamma.c b/source/blender/nodes/composite/nodes/node_composite_gamma.c index 6da56165979..27bf72d53b4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_gamma.c +++ b/source/blender/nodes/composite/nodes/node_composite_gamma.c @@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_gamma_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_gamma(bNodeTreeType *ttype) +void register_node_type_cmp_gamma(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_gamma_in, cmp_node_gamma_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_glare.c b/source/blender/nodes/composite/nodes/node_composite_glare.c index dde056de807..19f5ab10a15 100644 --- a/source/blender/nodes/composite/nodes/node_composite_glare.c +++ b/source/blender/nodes/composite/nodes/node_composite_glare.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate cmp_node_glare_out[] = { { -1, 0, "" } }; -static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node) { NodeGlare *ndg = MEM_callocN(sizeof(NodeGlare), "node glare data"); ndg->quality = 1; @@ -57,14 +57,14 @@ static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNod node->storage = ndg; } -void register_node_type_cmp_glare(bNodeTreeType *ttype) +void register_node_type_cmp_glare(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_glare_in, cmp_node_glare_out); node_type_init(&ntype, node_composit_init_glare); node_type_storage(&ntype, "NodeGlare", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c index 64ba24e082d..01c6f639cbb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c +++ b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_hue_sat_out[] = { { -1, 0, "" } }; -static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node) { NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat"); node->storage= nhs; @@ -53,14 +53,14 @@ static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bN nhs->val= 1.0f; } -void register_node_type_cmp_hue_sat(bNodeTreeType *ttype) +void register_node_type_cmp_hue_sat(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_hue_sat_in, cmp_node_hue_sat_out); node_type_init(&ntype, node_composit_init_hue_sat); node_type_storage(&ntype, "NodeHueSat", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c index 738f2f511f7..71e4df04911 100644 --- a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c +++ b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_huecorrect_out[] = { { -1, 0, "" } }; -static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node) { CurveMapping *cumapping = node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); int c; @@ -59,15 +59,15 @@ static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node, cumapping->cur = 1; } -void register_node_type_cmp_huecorrect(bNodeTreeType *ttype) +void register_node_type_cmp_huecorrect(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_HUECORRECT, "Hue Correct", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_HUECORRECT, "Hue Correct", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_huecorrect_in, cmp_node_huecorrect_out); node_type_size(&ntype, 320, 140, 500); node_type_init(&ntype, node_composit_init_huecorrect); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_idMask.c b/source/blender/nodes/composite/nodes/node_composite_idMask.c index 89ef4ad3d01..529bc83946b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_idMask.c +++ b/source/blender/nodes/composite/nodes/node_composite_idMask.c @@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_idmask_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_idmask(bNodeTreeType *ttype) +void register_node_type_cmp_idmask(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_idmask_in, cmp_node_idmask_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 563ad2b74b2..aa218252472 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -70,7 +70,7 @@ static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNod bNodeSocket *sock; NodeImageLayer *sockdata; - sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]); + sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); /* extra socket info */ sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; @@ -157,7 +157,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, else type = SOCK_RGBA; - sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type); + sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->name, rpass->name); /* extra socket info */ sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; @@ -202,8 +202,8 @@ static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeS { bNodeSocket *sock; - for (sock=oldsocklist->first; sock; sock=sock->next) - if (strcmp(sock->name, newsock->name)==0) + for (sock=oldsocklist->first; sock; sock = sock->next) + if (STREQ(sock->name, newsock->name)) return sock; return NULL; } @@ -213,8 +213,8 @@ static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldso bNodeSocket *sock; /* first try to find matching socket name */ - for (sock=node->outputs.first; sock; sock=sock->next) - if (strcmp(sock->name, oldsock->name)==0) + for (sock = node->outputs.first; sock; sock = sock->next) + if (STREQ(sock->name, oldsock->name)) return sock; /* no matching name, simply link to same index */ @@ -240,11 +240,8 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node) /* XXX make callback */ cmp_node_image_create_outputs(ntree, node); - /* flag all new sockets as dynamic, to prevent removal by socket verification function */ - for (newsock=node->outputs.first; newsock; newsock=newsock->next) - newsock->flag |= SOCK_DYNAMIC; - for (newsock=node->outputs.first; newsock; newsock=newsock->next) { + for (newsock = node->outputs.first; newsock; newsock=newsock->next) { /* XXX make callback */ oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist); if (oldsock) { @@ -284,7 +281,7 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node) cmp_node_image_verify_outputs(ntree, node); } -static void node_composit_init_image(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_image(bNodeTree *ntree, bNode *node) { ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); node->storage= iuser; @@ -302,44 +299,54 @@ static void node_composit_free_image(bNode *node) bNodeSocket *sock; /* free extra socket info */ - for (sock=node->outputs.first; sock; sock=sock->next) + for (sock = node->outputs.first; sock; sock = sock->next) MEM_freeN(sock->storage); MEM_freeN(node->storage); } -static void node_composit_copy_image(bNode *orig_node, bNode *new_node) +static void node_composit_copy_image(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { bNodeSocket *sock; - new_node->storage= MEM_dupallocN(orig_node->storage); + dest_node->storage= MEM_dupallocN(src_node->storage); /* copy extra socket info */ - for (sock=orig_node->outputs.first; sock; sock=sock->next) + for (sock=src_node->outputs.first; sock; sock = sock->next) sock->new_sock->storage = MEM_dupallocN(sock->storage); } -void register_node_type_cmp_image(bNodeTreeType *ttype) +void register_node_type_cmp_image(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_init(&ntype, node_composit_init_image); node_type_storage(&ntype, "ImageUser", node_composit_free_image, node_composit_copy_image); node_type_update(&ntype, cmp_node_image_update, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } /* **************** RENDER RESULT ******************** */ -void register_node_type_cmp_rlayers(bNodeTreeType *ttype) +static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + PointerRNA ptr; + + /* render layers node can only be used in local scene->nodetree, since it directly links to the scene */ + RNA_id_pointer_create((ID *)ntree, &ptr); + return (strcmp(ntree->idname, "CompositorNodeTree")==0 && RNA_boolean_get(&ptr, "is_local_tree")); +} + +void register_node_type_cmp_rlayers(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); + ntype.poll = node_composit_poll_rlayers; - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_inpaint.c b/source/blender/nodes/composite/nodes/node_composite_inpaint.c index 4844b35fb62..83517d07b69 100644 --- a/source/blender/nodes/composite/nodes/node_composite_inpaint.c +++ b/source/blender/nodes/composite/nodes/node_composite_inpaint.c @@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_inpaint_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_inpaint(bNodeTreeType *ttype) +void register_node_type_cmp_inpaint(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_inpaint_in, cmp_node_inpaint_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_invert.c b/source/blender/nodes/composite/nodes/node_composite_invert.c index 0bfbe42868b..6a3da2c854b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_invert.c +++ b/source/blender/nodes/composite/nodes/node_composite_invert.c @@ -43,19 +43,19 @@ static bNodeSocketTemplate cmp_node_invert_out[] = { { -1, 0, "" } }; -static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 |= CMP_CHAN_RGB; } /* custom1 = mix type */ -void register_node_type_cmp_invert(bNodeTreeType *ttype) +void register_node_type_cmp_invert(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_invert_in, cmp_node_invert_out); node_type_init(&ntype, node_composit_init_invert); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c index 51e0e9a8e39..464df4d72ab 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keying.c +++ b/source/blender/nodes/composite/nodes/node_composite_keying.c @@ -60,7 +60,7 @@ static bNodeSocketTemplate cmp_node_keying_out[] = { { -1, 0, "" } }; -static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node) { NodeKeyingData *data; @@ -78,14 +78,14 @@ static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNo node->storage = data; } -void register_node_type_cmp_keying(bNodeTreeType *ttype) +void register_node_type_cmp_keying(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_keying_in, cmp_node_keying_out); node_type_init(&ntype, node_composit_init_keying); node_type_storage(&ntype, "NodeKeyingData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index 1974087e8e7..b593196d815 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -50,7 +50,7 @@ static bNodeSocketTemplate cmp_node_keyingscreen_out[] = { { -1, 0, "" } }; -static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node) { NodeKeyingScreenData *data; @@ -59,14 +59,14 @@ static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *nod node->storage = data; } -void register_node_type_cmp_keyingscreen(bNodeTreeType *ttype) +void register_node_type_cmp_keyingscreen(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_keyingscreen_out); node_type_init(&ntype, node_composit_init_keyingscreen); node_type_storage(&ntype, "NodeKeyingScreenData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_lensdist.c b/source/blender/nodes/composite/nodes/node_composite_lensdist.c index 15d10e07946..c093d563363 100644 --- a/source/blender/nodes/composite/nodes/node_composite_lensdist.c +++ b/source/blender/nodes/composite/nodes/node_composite_lensdist.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_lensdist_out[] = { { -1, 0, "" } }; -static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node) { NodeLensDist *nld = MEM_callocN(sizeof(NodeLensDist), "node lensdist data"); nld->jit = nld->proj = nld->fit = 0; @@ -51,14 +51,14 @@ static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, b } -void register_node_type_cmp_lensdist(bNodeTreeType *ttype) +void register_node_type_cmp_lensdist(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_lensdist_in, cmp_node_lensdist_out); node_type_init(&ntype, node_composit_init_lensdist); node_type_storage(&ntype, "NodeLensDist", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.c b/source/blender/nodes/composite/nodes/node_composite_levels.c index f50a8838d74..e2b3895a96f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_levels.c +++ b/source/blender/nodes/composite/nodes/node_composite_levels.c @@ -45,19 +45,19 @@ static bNodeSocketTemplate cmp_node_view_levels_out[] = { {-1, 0, ""} }; -static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1=1; /*All channels*/ } -void register_node_type_cmp_view_levels(bNodeTreeType *ttype) +void register_node_type_cmp_view_levels(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW); + cmp_node_type_base(&ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_socket_templates(&ntype, cmp_node_view_levels_in, cmp_node_view_levels_out); node_type_init(&ntype, node_composit_init_view_levels); node_type_storage(&ntype, "ImageUser", NULL, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c index 60a7f3014de..606c95b495d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_luma_matte_out[] = { {-1, 0, ""} }; -static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); node->storage=c; @@ -53,14 +53,14 @@ static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node, c->t2= 0.0f; } -void register_node_type_cmp_luma_matte(bNodeTreeType *ttype) +void register_node_type_cmp_luma_matte(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_LUMA_MATTE, "Luminance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_LUMA_MATTE, "Luminance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_luma_matte_in, cmp_node_luma_matte_out); node_type_init(&ntype, node_composit_init_luma_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapRange.c b/source/blender/nodes/composite/nodes/node_composite_mapRange.c index 07f34e79bd1..74c36a3e25a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapRange.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapRange.c @@ -46,12 +46,12 @@ static bNodeSocketTemplate cmp_node_map_range_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_map_range(bNodeTreeType *ttype) +void register_node_type_cmp_map_range(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_map_range_in, cmp_node_map_range_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapUV.c b/source/blender/nodes/composite/nodes/node_composite_mapUV.c index fa4c8d7022c..0d2c53f241c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapUV.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapUV.c @@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_mapuv_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_mapuv(bNodeTreeType *ttype) +void register_node_type_cmp_mapuv(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_mapuv_in, cmp_node_mapuv_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c index 046eeaf4fc8..a61ecd41746 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c @@ -42,19 +42,19 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = { { -1, 0, "" } }; -static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= add_tex_mapping(); } -void register_node_type_cmp_map_value(bNodeTreeType *ttype) +void register_node_type_cmp_map_value(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MAP_VALUE, "Map Value", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MAP_VALUE, "Map Value", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_map_value_in, cmp_node_map_value_out); node_type_init(&ntype, node_composit_init_map_value); node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index 27534698422..f97e83f177a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_mask_out[] = { { -1, 0, "" } }; -static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node) { NodeMask *data = MEM_callocN(sizeof(NodeMask), "NodeMask"); data->size_x = data->size_y = 256; @@ -55,15 +55,15 @@ static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNode node->custom3 = 0.5f; /* shutter */ } -void register_node_type_cmp_mask(bNodeTreeType *ttype) +void register_node_type_cmp_mask(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_mask_out); node_type_init(&ntype, node_composit_init_mask); node_type_storage(&ntype, "NodeMask", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index 5f5369ce03a..802a370f882 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -45,13 +45,13 @@ static bNodeSocketTemplate cmp_node_math_out[] = { }; -void register_node_type_cmp_math(bNodeTreeType *ttype) +void register_node_type_cmp_math(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_math_in, cmp_node_math_out); node_type_label(&ntype, node_math_label); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c index 23e4fc90457..a3415761bf8 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c @@ -44,13 +44,13 @@ static bNodeSocketTemplate cmp_node_mix_rgb_out[] = { }; /* custom1 = mix type */ -void register_node_type_cmp_mix_rgb(bNodeTreeType *ttype) +void register_node_type_cmp_mix_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_mix_rgb_in, cmp_node_mix_rgb_out); node_type_label(&ntype, node_blend_label); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c index 39d46e053bf..34d7eeb570d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c +++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate cmp_node_movieclip_out[] = { { -1, 0, "" } }; -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { MovieClipUser *user = MEM_callocN(sizeof(MovieClipUser), "node movie clip user"); @@ -50,14 +50,14 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt user->framenr = 1; } -void register_node_type_cmp_movieclip(bNodeTreeType *ttype) +void register_node_type_cmp_movieclip(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_movieclip_out); node_type_init(&ntype, init); node_type_storage(&ntype, "MovieClipUser", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c index 198ffbb2857..86666a38f1d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c +++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c @@ -60,21 +60,21 @@ static void storage_free(bNode *node) node->storage = NULL; } -static void storage_copy(bNode *orig_node, bNode *new_node) +static void storage_copy(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - if (orig_node->storage) - new_node->storage = BKE_tracking_distortion_copy(orig_node->storage); + if (src_node->storage) + dest_node->storage = BKE_tracking_distortion_copy(src_node->storage); } -void register_node_type_cmp_moviedistortion(bNodeTreeType *ttype) +void register_node_type_cmp_moviedistortion(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_moviedistortion_in, cmp_node_moviedistortion_out); node_type_label(&ntype, label); node_type_storage(&ntype, NULL, storage_free, storage_copy); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c index 88db5d36810..0f7fdb53693 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.c +++ b/source/blender/nodes/composite/nodes/node_composite_normal.c @@ -32,7 +32,6 @@ #include "node_composite_util.h" - /* **************** NORMAL ******************** */ static bNodeSocketTemplate cmp_node_normal_in[] = { { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, @@ -40,28 +39,17 @@ static bNodeSocketTemplate cmp_node_normal_in[] = { }; static bNodeSocketTemplate cmp_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) -{ - bNodeSocket *sock= node->outputs.first; - float *nor= ((bNodeSocketValueVector*)sock->default_value)->value; - - nor[0] = 0.0f; - nor[1] = 0.0f; - nor[2] = 1.0f; -} - -void register_node_type_cmp_normal(bNodeTreeType *ttype) +void register_node_type_cmp_normal(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_normal_in, cmp_node_normal_out); - node_type_init(&ntype, init); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.c b/source/blender/nodes/composite/nodes/node_composite_normalize.c index db811666900..c101d7edec4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normalize.c +++ b/source/blender/nodes/composite/nodes/node_composite_normalize.c @@ -43,12 +43,12 @@ static bNodeSocketTemplate cmp_node_normalize_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_normalize(bNodeTreeType *ttype) +void register_node_type_cmp_normalize(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_normalize_in, cmp_node_normalize_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index d9a146ddaad..18bb97c70ed 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -34,6 +34,10 @@ #include "BLI_utildefines.h" #include "BLI_path_util.h" +#include "BKE_context.h" + +#include "RNA_access.h" + #include "node_composite_util.h" #include "IMB_imbuf.h" @@ -49,10 +53,10 @@ static bool unique_path_unique_check(void *arg, const char *name) { struct {ListBase *lb; bNodeSocket *sock;} *data= arg; bNodeSocket *sock; - for (sock=data->lb->first; sock; sock=sock->next) { + for (sock=data->lb->first; sock; sock = sock->next) { if (sock != data->sock) { NodeImageMultiFileSocket *sockdata = sock->storage; - if (strcmp(sockdata->path, name)==0) + if (STREQ(sockdata->path, name)) return true; } } @@ -78,10 +82,10 @@ static bool unique_layer_unique_check(void *arg, const char *name) { struct {ListBase *lb; bNodeSocket *sock;} *data= arg; bNodeSocket *sock; - for (sock=data->lb->first; sock; sock=sock->next) { + for (sock=data->lb->first; sock; sock = sock->next) { if (sock != data->sock) { NodeImageMultiFileSocket *sockdata = sock->storage; - if (strcmp(sockdata->layer, name)==0) + if (STREQ(sockdata->layer, name)) return true; } } @@ -105,7 +109,7 @@ void ntreeCompositOutputFileUniqueLayer(ListBase *list, bNodeSocket *sock, const bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format) { NodeImageMultiFile *nimf = node->storage; - bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, "", SOCK_RGBA); + bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, name); /* create format data for the input socket */ NodeImageMultiFileSocket *sockdata = MEM_callocN(sizeof(NodeImageMultiFileSocket), "socket image format"); @@ -165,14 +169,19 @@ void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, name, '_'); } -static void init_output_file(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) +/* XXX uses initfunc_api callback, regular initfunc does not support context yet */ +static void init_output_file(const bContext *C, PointerRNA *ptr) { + Scene *scene = CTX_data_scene(C); + bNodeTree *ntree = ptr->id.data; + bNode *node = ptr->data; NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file"); ImageFormatData *format = NULL; node->storage= nimf; + + if (scene) { + RenderData *rd = &scene->r; - if (ntemp->scene) { - RenderData *rd = &ntemp->scene->r; BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path)); nimf->format = rd->im_format; if (BKE_imtype_is_movie(nimf->format.imtype)) { @@ -193,48 +202,50 @@ static void free_output_file(bNode *node) bNodeSocket *sock; /* free storage data in sockets */ - for (sock=node->inputs.first; sock; sock=sock->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { MEM_freeN(sock->storage); } MEM_freeN(node->storage); } -static void copy_output_file(struct bNode *node, struct bNode *target) +static void copy_output_file(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - bNodeSocket *sock, *newsock; + bNodeSocket *src_sock, *dest_sock; - target->storage = MEM_dupallocN(node->storage); + dest_node->storage = MEM_dupallocN(src_node->storage); /* duplicate storage data in sockets */ - for (sock=node->inputs.first, newsock=target->inputs.first; sock && newsock; sock=sock->next, newsock=newsock->next) { - newsock->storage = MEM_dupallocN(sock->storage); + for (src_sock=src_node->inputs.first, dest_sock=dest_node->inputs.first; src_sock && dest_sock; src_sock=src_sock->next, dest_sock=dest_sock->next) { + dest_sock->storage = MEM_dupallocN(src_sock->storage); } } -static void update_output_file(bNodeTree *UNUSED(ntree), bNode *node) +static void update_output_file(bNodeTree *ntree, bNode *node) { bNodeSocket *sock; + PointerRNA ptr; + + cmp_node_update_default(ntree, node); /* automatically update the socket type based on linked input */ - for (sock=node->inputs.first; sock; sock=sock->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { if (sock->link) { - int linktype = sock->link->fromsock->type; - if (linktype != sock->type) - nodeSocketSetType(sock, linktype); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_enum_set(&ptr, "type", sock->link->fromsock->type); } } } -void register_node_type_cmp_output_file(bNodeTreeType *ttype) +void register_node_type_cmp_output_file(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW); + cmp_node_type_base(&ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_socket_templates(&ntype, NULL, NULL); - node_type_init(&ntype, init_output_file); + ntype.initfunc_api = init_output_file; node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file); node_type_update(&ntype, update_output_file, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.c b/source/blender/nodes/composite/nodes/node_composite_pixelate.c index 3b65a2cdbd5..d12c09cb25e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_pixelate.c +++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.c @@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_pixelate_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_pixelate(bNodeTreeType *ttype) +void register_node_type_cmp_pixelate(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_pixelate_in, cmp_node_pixelate_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_premulkey.c b/source/blender/nodes/composite/nodes/node_composite_premulkey.c index 01eb3607760..bfc5a54cf73 100644 --- a/source/blender/nodes/composite/nodes/node_composite_premulkey.c +++ b/source/blender/nodes/composite/nodes/node_composite_premulkey.c @@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_premulkey_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_premulkey(bNodeTreeType *ttype) +void register_node_type_cmp_premulkey(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_premulkey_in, cmp_node_premulkey_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_rgb.c b/source/blender/nodes/composite/nodes/node_composite_rgb.c index 30b23a4c146..e3209844319 100644 --- a/source/blender/nodes/composite/nodes/node_composite_rgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_rgb.c @@ -32,32 +32,19 @@ #include "node_composite_util.h" - /* **************** RGB ******************** */ static bNodeSocketTemplate cmp_node_rgb_out[] = { - { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f}, + { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f}, { -1, 0, "" } }; -static void node_composit_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) -{ - bNodeSocket *sock= node->outputs.first; - float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; - /* uses the default value of the output socket, must be initialized here */ - col[0] = 0.5f; - col[1] = 0.5f; - col[2] = 0.5f; - col[3] = 1.0f; -} - -void register_node_type_cmp_rgb(bNodeTreeType *ttype) +void register_node_type_cmp_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_rgb_out); - node_type_init(&ntype, node_composit_init_rgb); node_type_size_preset(&ntype, NODE_SIZE_SMALL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_rotate.c b/source/blender/nodes/composite/nodes/node_composite_rotate.c index 6b5521ea4d2..1f51e25798d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_rotate.c +++ b/source/blender/nodes/composite/nodes/node_composite_rotate.c @@ -44,18 +44,18 @@ static bNodeSocketTemplate cmp_node_rotate_out[] = { { -1, 0, "" } }; -static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1= 1; /* Bilinear Filter*/ } -void register_node_type_cmp_rotate(bNodeTreeType *ttype) +void register_node_type_cmp_rotate(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_rotate_in, cmp_node_rotate_out); node_type_init(&ntype, node_composit_init_rotate); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c index 6c2c6c37cb7..0d8763bf321 100644 --- a/source/blender/nodes/composite/nodes/node_composite_scale.c +++ b/source/blender/nodes/composite/nodes/node_composite_scale.c @@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_scale_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_scale(bNodeTreeType *ttype) +void register_node_type_cmp_scale(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c index d463f35a07a..9aa64138cd6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c @@ -46,14 +46,14 @@ static bNodeSocketTemplate cmp_node_sephsva_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_sephsva(bNodeTreeType *ttype) +void register_node_type_cmp_sephsva(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0); + cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_sephsva_in, cmp_node_sephsva_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -70,12 +70,12 @@ static bNodeSocketTemplate cmp_node_combhsva_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_combhsva(bNodeTreeType *ttype) +void register_node_type_cmp_combhsva(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combhsva_in, cmp_node_combhsva_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c index 03b43f5073f..603cc01c259 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c @@ -45,14 +45,14 @@ static bNodeSocketTemplate cmp_node_seprgba_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_seprgba(bNodeTreeType *ttype) +void register_node_type_cmp_seprgba(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0); + cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_seprgba_in, cmp_node_seprgba_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -70,12 +70,12 @@ static bNodeSocketTemplate cmp_node_combrgba_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_combrgba(bNodeTreeType *ttype) +void register_node_type_cmp_combrgba(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combrgba_in, cmp_node_combrgba_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c index 16aba1ba408..cae70efc85d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c @@ -47,14 +47,14 @@ static bNodeSocketTemplate cmp_node_sepycca_out[] = { }; -void register_node_type_cmp_sepycca(bNodeTreeType *ttype) +void register_node_type_cmp_sepycca(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_sepycca_in, cmp_node_sepycca_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -72,12 +72,12 @@ static bNodeSocketTemplate cmp_node_combycca_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_combycca(bNodeTreeType *ttype) +void register_node_type_cmp_combycca(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combycca_in, cmp_node_combycca_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c index 7d7ec166fd4..74c840adef1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c @@ -46,15 +46,14 @@ static bNodeSocketTemplate cmp_node_sepyuva_out[] = { { -1, 0, "" } }; - -void register_node_type_cmp_sepyuva(bNodeTreeType *ttype) +void register_node_type_cmp_sepyuva(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0); + cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_sepyuva_in, cmp_node_sepyuva_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -72,12 +71,12 @@ static bNodeSocketTemplate cmp_node_combyuva_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_combyuva(bNodeTreeType *ttype) +void register_node_type_cmp_combyuva(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combyuva_in, cmp_node_combyuva_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_setalpha.c b/source/blender/nodes/composite/nodes/node_composite_setalpha.c index d36acc6c054..a162936c9a2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_setalpha.c +++ b/source/blender/nodes/composite/nodes/node_composite_setalpha.c @@ -43,12 +43,12 @@ static bNodeSocketTemplate cmp_node_setalpha_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_setalpha(bNodeTreeType *ttype) +void register_node_type_cmp_setalpha(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_setalpha_in, cmp_node_setalpha_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index 38a6981613a..7cb1cf1d65d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -39,7 +39,7 @@ static bNodeSocketTemplate cmp_node_splitviewer_in[] = { { -1, 0, "" } }; -static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node) { ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); node->storage= iuser; @@ -49,11 +49,11 @@ static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node node->custom1= 50; /* default 50% split */ } -void register_node_type_cmp_splitviewer(bNodeTreeType *ttype) +void register_node_type_cmp_splitviewer(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_splitviewer_in, NULL); node_type_init(&ntype, node_composit_init_splitviewer); node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); @@ -61,5 +61,5 @@ void register_node_type_cmp_splitviewer(bNodeTreeType *ttype) /* Do not allow muting for this node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c index 6b345b4c15c..3b85b4a6b8c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c +++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c @@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_stabilize2d_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_stabilize2d(bNodeTreeType *ttype) +void register_node_type_cmp_stabilize2d(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_stabilize2d_in, cmp_node_stabilize2d_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_switch.c b/source/blender/nodes/composite/nodes/node_composite_switch.c index 49fa61a8397..a6254de62d5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switch.c +++ b/source/blender/nodes/composite/nodes/node_composite_switch.c @@ -46,13 +46,13 @@ static bNodeSocketTemplate cmp_node_switch_out[] = { }; /* custom1 = mix type */ -void register_node_type_cmp_switch(bNodeTreeType *ttype) +void register_node_type_cmp_switch(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_SWITCH, "Switch", NODE_CLASS_LAYOUT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_SWITCH, "Switch", NODE_CLASS_LAYOUT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_switch_in, cmp_node_switch_out); node_type_size_preset(&ntype, NODE_SIZE_SMALL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_texture.c b/source/blender/nodes/composite/nodes/node_composite_texture.c index 515093fc3e1..320b8f6aabe 100644 --- a/source/blender/nodes/composite/nodes/node_composite_texture.c +++ b/source/blender/nodes/composite/nodes/node_composite_texture.c @@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_texture_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_texture(bNodeTreeType *ttype) +void register_node_type_cmp_texture(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + cmp_node_type_base(&ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_socket_templates(&ntype, cmp_node_texture_in, cmp_node_texture_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.c b/source/blender/nodes/composite/nodes/node_composite_tonemap.c index fd3a217b150..6f6fbc21a40 100644 --- a/source/blender/nodes/composite/nodes/node_composite_tonemap.c +++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate cmp_node_tonemap_out[] = { { -1, 0, "" } }; -static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node) { NodeTonemap *ntm = MEM_callocN(sizeof(NodeTonemap), "node tonemap data"); ntm->type = 1; @@ -57,14 +57,14 @@ static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bN node->storage = ntm; } -void register_node_type_cmp_tonemap(bNodeTreeType *ttype) +void register_node_type_cmp_tonemap(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_TONEMAP, "Tonemap", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_TONEMAP, "Tonemap", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_tonemap_in, cmp_node_tonemap_out); node_type_init(&ntype, node_composit_init_tonemap); node_type_storage(&ntype, "NodeTonemap", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_trackpos.c b/source/blender/nodes/composite/nodes/node_composite_trackpos.c index 1583680720a..bc3c54702ac 100644 --- a/source/blender/nodes/composite/nodes/node_composite_trackpos.c +++ b/source/blender/nodes/composite/nodes/node_composite_trackpos.c @@ -39,21 +39,21 @@ static bNodeSocketTemplate cmp_node_trackpos_out[] = { { -1, 0, "" } }; -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { NodeTrackPosData *data = MEM_callocN(sizeof(NodeTrackPosData), "node track position data"); node->storage = data; } -void register_node_type_cmp_trackpos(bNodeTreeType *ttype) +void register_node_type_cmp_trackpos(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_trackpos_out); node_type_init(&ntype, init); node_type_storage(&ntype, "NodeTrackPosData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_transform.c b/source/blender/nodes/composite/nodes/node_composite_transform.c index 3ed8bdb9995..8dc272adf38 100644 --- a/source/blender/nodes/composite/nodes/node_composite_transform.c +++ b/source/blender/nodes/composite/nodes/node_composite_transform.c @@ -48,12 +48,12 @@ static bNodeSocketTemplate cmp_node_transform_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_transform(bNodeTreeType *ttype) +void register_node_type_cmp_transform(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_transform_in, cmp_node_transform_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_translate.c b/source/blender/nodes/composite/nodes/node_composite_translate.c index 5d555cdcda9..ae293170004 100644 --- a/source/blender/nodes/composite/nodes/node_composite_translate.c +++ b/source/blender/nodes/composite/nodes/node_composite_translate.c @@ -46,20 +46,20 @@ static bNodeSocketTemplate cmp_node_translate_out[] = { { -1, 0, "" } }; -static void node_composit_init_translate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_translate(bNodeTree *UNUSED(ntree), bNode *node) { NodeTranslateData *data = MEM_callocN(sizeof(NodeTranslateData), "node translate data"); node->storage = data; } -void register_node_type_cmp_translate(bNodeTreeType *ttype) +void register_node_type_cmp_translate(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_translate_in, cmp_node_translate_out); node_type_init(&ntype, node_composit_init_translate); node_type_storage(&ntype, "NodeTranslateData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c index 5a23507bcc7..a1d51bdf171 100644 --- a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c @@ -44,22 +44,22 @@ static bNodeSocketTemplate cmp_node_valtorgb_out[] = { { -1, 0, "" } }; -static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node) { - node->storage= add_colorband(1); + node->storage= add_colorband(true); } -void register_node_type_cmp_valtorgb(bNodeTreeType *ttype) +void register_node_type_cmp_valtorgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_valtorgb_in, cmp_node_valtorgb_out); node_type_size(&ntype, 240, 200, 320); node_type_init(&ntype, node_composit_init_valtorgb); node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -74,13 +74,13 @@ static bNodeSocketTemplate cmp_node_rgbtobw_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_rgbtobw(bNodeTreeType *ttype) +void register_node_type_cmp_rgbtobw(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); + cmp_node_type_base(&ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_rgbtobw_in, cmp_node_rgbtobw_out); node_type_size_preset(&ntype, NODE_SIZE_SMALL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_value.c b/source/blender/nodes/composite/nodes/node_composite_value.c index 306170baf93..87c77440985 100644 --- a/source/blender/nodes/composite/nodes/node_composite_value.c +++ b/source/blender/nodes/composite/nodes/node_composite_value.c @@ -34,29 +34,17 @@ /* **************** VALUE ******************** */ static bNodeSocketTemplate cmp_node_value_out[] = { - /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */ - { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + { SOCK_FLOAT, 0, N_("Value"), 0.5f, 0, 0, 0, -FLT_MAX, FLT_MAX, PROP_NONE}, { -1, 0, "" } }; -static void node_composit_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) -{ - bNodeSocket *sock= node->outputs.first; - bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value; - /* uses the default value of the output socket, must be initialized here */ - dval->value = 0.5f; - dval->min = -FLT_MAX; - dval->max = FLT_MAX; -} - -void register_node_type_cmp_value(bNodeTreeType *ttype) +void register_node_type_cmp_value(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_value_out); - node_type_init(&ntype, node_composit_init_value); node_type_size_preset(&ntype, NODE_SIZE_SMALL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c index 35fb4a944db..b00cfc315b0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c +++ b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_vecblur_out[] = { { -1, 0, "" } }; -static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node) { NodeBlurData *nbd = MEM_callocN(sizeof(NodeBlurData), "node blur data"); node->storage = nbd; @@ -54,14 +54,14 @@ static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bN } /* custom1: itterations, custom2: maxspeed (0 = nolimit) */ -void register_node_type_cmp_vecblur(bNodeTreeType *ttype) +void register_node_type_cmp_vecblur(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_VECBLUR, "Vector Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_VECBLUR, "Vector Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_vecblur_in, cmp_node_vecblur_out); node_type_init(&ntype, node_composit_init_vecblur); node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index 211ebe54eb0..70aae460af7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate cmp_node_viewer_in[] = { { -1, 0, "" } }; -static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node) { ImageUser *iuser = MEM_callocN(sizeof(ImageUser), "node image user"); node->storage = iuser; @@ -52,16 +52,16 @@ static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNo node->custom4 = 0.5f; } -void register_node_type_cmp_viewer(bNodeTreeType *ttype) +void register_node_type_cmp_viewer(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW); + cmp_node_type_base(&ntype, CMP_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW); node_type_socket_templates(&ntype, cmp_node_viewer_in, NULL); node_type_init(&ntype, node_composit_init_viewer); node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c index ba81174e103..6e5f38e1fab 100644 --- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c +++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c @@ -48,12 +48,12 @@ static bNodeSocketTemplate cmp_node_zcombine_out[] = { { -1, 0, "" } }; -void register_node_type_cmp_zcombine(bNodeTreeType *ttype) +void register_node_type_cmp_zcombine(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + cmp_node_type_base(&ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_zcombine_in, cmp_node_zcombine_out); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index d59061dfc0a..54ffd3cd01c 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -31,19 +31,22 @@ #include <string.h> +#include <stddef.h> #include "DNA_node_types.h" #include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" #include "BLF_translation.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" -#include "BLI_math.h" #include "BKE_node.h" #include "RNA_access.h" @@ -55,247 +58,110 @@ #include "node_util.h" #include "node_exec.h" #include "NOD_socket.h" +#include "NOD_common.h" + /**** Group ****/ -bNodeSocket *node_group_find_input(bNode *gnode, bNodeSocket *gsock) +bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifier) { bNodeSocket *sock; - for (sock=gnode->inputs.first; sock; sock=sock->next) - if (sock->groupsock == gsock) + for (sock=groupnode->inputs.first; sock; sock = sock->next) + if (STREQ(sock->identifier, identifier)) return sock; return NULL; } -bNodeSocket *node_group_find_output(bNode *gnode, bNodeSocket *gsock) +bNodeSocket *node_group_find_output_socket(bNode *groupnode, const char *identifier) { bNodeSocket *sock; - for (sock=gnode->outputs.first; sock; sock=sock->next) - if (sock->groupsock == gsock) + for (sock=groupnode->outputs.first; sock; sock = sock->next) + if (STREQ(sock->identifier, identifier)) return sock; return NULL; } -bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb, int in_out, bNodeSocket *gsock) -{ - bNodeSocket *sock; - - if (gsock->flag & SOCK_INTERNAL) - return NULL; - - sock= MEM_callocN(sizeof(bNodeSocket), "sock"); - - /* make a copy of the group socket */ - *sock = *gsock; - sock->link = NULL; - sock->next = sock->prev = NULL; - sock->new_sock = NULL; - - /* group sockets are dynamically added */ - sock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED; - - sock->own_index = gsock->own_index; - sock->groupsock = gsock; - sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF); - - sock->default_value = node_socket_make_default_value(sock->type); - node_socket_copy_default_value(sock->type, sock->default_value, gsock->default_value); - - if (lb) - BLI_addtail(lb, sock); - - return sock; -} - -bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type, int in_out) -{ - bNodeSocketType *stype = ntreeGetSocketType(type); - bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket"); - - BLI_strncpy(gsock->name, name, sizeof(gsock->name)); - gsock->type = type; - /* group sockets are dynamically added */ - gsock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED; - - gsock->next = gsock->prev = NULL; - gsock->new_sock = NULL; - gsock->link = NULL; - /* assign new unique index */ - gsock->own_index = ngroup->cur_index++; - gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1); - - if (stype->value_structsize > 0) - gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value"); - - BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock); - - ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT); - - return gsock; -} - -bNodeSocket *node_group_expose_socket(bNodeTree *ngroup, bNodeSocket *sock, int in_out) -{ - bNodeSocket *gsock= node_group_add_socket(ngroup, sock->name, sock->type, in_out); - - /* initialize the default value. */ - node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value); - - return gsock; -} - -void node_group_expose_all_sockets(bNodeTree *ngroup) -{ - bNode *node; - bNodeSocket *sock, *gsock; - - for (node=ngroup->nodes.first; node; node=node->next) { - for (sock=node->inputs.first; sock; sock=sock->next) { - if (!sock->link && !nodeSocketIsHidden(sock)) { - gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN); - - /* initialize the default value. */ - node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value); - - sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock); - } - } - for (sock=node->outputs.first; sock; sock=sock->next) { - if (nodeCountSocketLinks(ngroup, sock)==0 && !nodeSocketIsHidden(sock)) { - gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT); - - /* initialize the default value. */ - node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value); - - gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock); - } - } - } -} - -void node_group_remove_socket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out) -{ - nodeRemSocketLinks(ngroup, gsock); - - switch (in_out) { - case SOCK_IN: - BLI_remlink(&ngroup->inputs, gsock); - ngroup->update |= NTREE_UPDATE_GROUP_IN; - break; - case SOCK_OUT: - BLI_remlink(&ngroup->outputs, gsock); - ngroup->update |= NTREE_UPDATE_GROUP_OUT; - break; - } - - if (gsock->default_value) - MEM_freeN(gsock->default_value); - - MEM_freeN(gsock); -} - /* groups display their internal tree name as label */ const char *node_group_label(bNode *node) { return (node->id)? node->id->name + 2: IFACE_("Missing Datablock"); } -int node_group_valid(bNodeTree *ntree, bNodeTemplate *ntemp) +int node_group_poll_instance(bNode *node, bNodeTree *nodetree) { - bNodeTemplate childtemp; - bNode *node; - - /* regular groups cannot be recursive */ - if (ntree == ntemp->ngroup) - return 0; - - /* make sure all children are valid */ - for (node=ntemp->ngroup->nodes.first; node; node=node->next) { - childtemp = nodeMakeTemplate(node); - if (!nodeValid(ntree, &childtemp)) - return 0; - } - - return 1; -} - -bNodeTemplate node_group_template(bNode *node) -{ - bNodeTemplate ntemp; - ntemp.type = NODE_GROUP; - ntemp.ngroup = (bNodeTree *)node->id; - return ntemp; + bNodeTree *grouptree = (bNodeTree*)node->id; + if (grouptree) + return nodeGroupPoll(nodetree, grouptree); + else + return 1; } -void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) +int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree) { - node->id = (ID *)ntemp->ngroup; + bNode *node; + int valid = 1; - /* NB: group socket input/output roles are inverted internally! - * Group "inputs" work as outputs in links and vice versa. - */ - if (ntemp->ngroup) { - bNodeSocket *gsock; - for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); - for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); + if (nodetree == grouptree) + return 0; + + for (node=grouptree->nodes.first; node; node=node->next) { + if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, nodetree)) { + valid = 0; + break; + } } + return valid; } -static bNodeSocket *group_verify_socket(bNodeTree *ntree, ListBase *lb, int in_out, bNodeSocket *gsock) +/* used for both group nodes and interface nodes */ +static bNodeSocket *group_verify_socket(bNodeTree *ntree, bNode *gnode, bNodeSocket *iosock, ListBase *verify_lb, int in_out) { bNodeSocket *sock; - /* group sockets tagged as internal are not exposed ever */ - if (gsock->flag & SOCK_INTERNAL) - return NULL; - - for (sock= lb->first; sock; sock= sock->next) { - if (sock->own_index==gsock->own_index) - break; + for (sock= verify_lb->first; sock; sock= sock->next) { + if (STREQ(sock->identifier, iosock->identifier)) + break; } if (sock) { - sock->groupsock = gsock; - - BLI_strncpy(sock->name, gsock->name, sizeof(sock->name)); - if (gsock->type != sock->type) - nodeSocketSetType(sock, gsock->type); - - /* XXX hack: group socket input/output roles are inverted internally, - * need to change the limit value when making actual node sockets from them. - */ - sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF); - - BLI_remlink(lb, sock); - - return sock; + strcpy(sock->name, iosock->name); } else { - return node_group_add_extern_socket(ntree, NULL, in_out, gsock); + sock = nodeAddSocket(ntree, gnode, in_out, iosock->idname, iosock->identifier, iosock->name); + + if (iosock->typeinfo->interface_init_socket) + iosock->typeinfo->interface_init_socket(ntree, iosock, gnode, sock, "interface"); } + + /* remove from list temporarily, to distinguish from orphaned sockets */ + BLI_remlink(verify_lb, sock); + + return sock; } -static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb) +/* used for both group nodes and interface nodes */ +static void group_verify_socket_list(bNodeTree *ntree, bNode *gnode, + ListBase *iosock_lb, ListBase *verify_lb, int in_out) { - bNodeSocket *sock, *nextsock, *gsock; + bNodeSocket *iosock, *sock, *nextsock; /* step by step compare */ - for (gsock= glb->first; gsock; gsock=gsock->next) { + + iosock = iosock_lb->first; + for (; iosock; iosock = iosock->next) { /* abusing new_sock pointer for verification here! only used inside this function */ - gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock); + iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out); } /* leftovers are removed */ - for (sock=lb->first; sock; sock=nextsock) { - nextsock=sock->next; - if (sock->flag & SOCK_DYNAMIC) - nodeRemoveSocket(ntree, node, sock); + for (sock = verify_lb->first; sock; sock = nextsock) { + nextsock = sock->next; + nodeRemoveSocket(ntree, gnode, sock); } /* and we put back the verified sockets */ - for (gsock= glb->first; gsock; gsock=gsock->next) { - if (gsock->new_sock) { - BLI_addtail(lb, gsock->new_sock); - gsock->new_sock = NULL; + iosock = iosock_lb->first; + for (; iosock; iosock = iosock->next) { + if (iosock->new_sock) { + BLI_addtail(verify_lb, iosock->new_sock); + iosock->new_sock = NULL; } } } @@ -304,59 +170,16 @@ static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id) { /* check inputs and outputs, and remove or insert them */ - if (node->id==id) { + if (id == node->id) { bNodeTree *ngroup= (bNodeTree *)node->id; - group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs); - group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs); + group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN); + group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT); } } -struct bNodeTree *node_group_edit_get(bNode *node) -{ - if (node->flag & NODE_GROUP_EDIT) - return (bNodeTree *)node->id; - else - return NULL; -} - -struct bNodeTree *node_group_edit_set(bNode *node, int edit) -{ - if (edit) { - bNodeTree *ngroup= (bNodeTree *)node->id; - if (ngroup) { - if (ngroup->id.lib) - ntreeMakeLocal(ngroup); - - node->flag |= NODE_GROUP_EDIT; - } - return ngroup; - } - else { - node->flag &= ~NODE_GROUP_EDIT; - return NULL; - } -} - -void node_group_edit_clear(bNode *node) -{ - bNodeTree *ngroup= (bNodeTree *)node->id; - bNode *inode; - - node->flag &= ~NODE_GROUP_EDIT; - - if (ngroup) - for (inode=ngroup->nodes.first; inode; inode=inode->next) - nodeGroupEditClear(inode); -} - -static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock, int in_out) -{ - node_group_expose_socket(ntree, sock, in_out); -} - /**** FRAME ****/ -static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node) { NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage"); node->storage = data; @@ -366,19 +189,19 @@ static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate data->label_size = 20; } -void register_node_type_frame(bNodeTreeType *ttype) +void register_node_type_frame(void) { /* frame type is used for all tree types, needs dynamic allocation */ bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type"); - node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS); + node_type_base(ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS); node_type_init(ntype, node_frame_init); node_type_storage(ntype, "NodeFrame", node_free_standard_storage, node_copy_standard_storage); node_type_size(ntype, 150, 100, 0); node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); ntype->needs_free = 1; - nodeRegisterType(ttype, ntype); + nodeRegisterType(ntype); } @@ -403,34 +226,34 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node) BLI_addtail(&node->internal_links, link); } -static void node_reroute_init(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_reroute_init(bNodeTree *ntree, bNode *node) { /* Note: Cannot use socket templates for this, since it would reset the socket type * on each file read via the template verification procedure. */ - nodeAddSocket(ntree, node, SOCK_IN, "Input", SOCK_RGBA); - nodeAddSocket(ntree, node, SOCK_OUT, "Output", SOCK_RGBA); + nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input"); + nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_RGBA, PROP_NONE, "Output", "Output"); } -void register_node_type_reroute(bNodeTreeType *ttype) +void register_node_type_reroute(void) { /* frame type is used for all tree types, needs dynamic allocation */ bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type"); - node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0); + node_type_base(ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0); node_type_init(ntype, node_reroute_init); node_type_internal_links(ntype, node_reroute_update_internal_links); ntype->needs_free = 1; - nodeRegisterType(ttype, ntype); + nodeRegisterType(ntype); } static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) { bNodeSocket *input = node->inputs.first; bNodeSocket *output = node->outputs.first; - int type = SOCK_FLOAT; bNodeLink *link; + int type = SOCK_FLOAT; /* XXX it would be a little bit more efficient to restrict actual updates * to rerout nodes connected to an updated node, but there's no reliable flag @@ -446,6 +269,8 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) bNode *tonode = link->tonode; if (!tonode || !fromnode) continue; + if (nodeLinkIsHidden(link)) + continue; if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done) node_reroute_inherit_type_recursive(ntree, fromnode); @@ -462,9 +287,13 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) /* arbitrary, could also test output->type, both are the same */ if (input->type != type) { + PointerRNA input_ptr, output_ptr; /* same type for input/output */ - nodeSocketSetType(input, type); - nodeSocketSetType(output, type); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, input, &input_ptr); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, output, &output_ptr); + + RNA_enum_set(&input_ptr, "type", type); + RNA_enum_set(&output_ptr, "type", type); } } @@ -484,9 +313,8 @@ void ntree_update_reroute_nodes(bNodeTree *ntree) node_reroute_inherit_type_recursive(ntree, node); } -void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) +void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree) { - ID *id = (ID *)calldata; bNode *node; for (node = ntree->nodes.first; node; node = node->next) { @@ -495,3 +323,179 @@ void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), str } } } + +/**** GROUP_INPUT / GROUP_OUTPUT ****/ + +static void node_group_input_init(bNodeTree *ntree, bNode *node) +{ + node_group_input_verify(ntree, node, (ID *)ntree); +} + +bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier) +{ + bNodeSocket *sock; + for (sock = node->outputs.first; sock; sock = sock->next) + if (STREQ(sock->identifier, identifier)) + return sock; + return NULL; +} + +void node_group_input_verify(bNodeTree *ntree, bNode *node, ID *id) +{ + /* check inputs and outputs, and remove or insert them */ + if (id == (ID *)ntree) { + /* value_in_out inverted for interface nodes to get correct socket value_property */ + group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT); + + /* add virtual extension socket */ + nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", ""); + } +} + +static void node_group_input_update(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *extsock = node->outputs.last; + bNodeLink *link; + /* Adding a tree socket and verifying will remove the extension socket! + * This list caches the existing links from the extension socket + * so they can be recreated after verification. + */ + ListBase tmplinks; + + /* find links from the extension socket and store them */ + tmplinks.first = tmplinks.last = NULL; + for (link = ntree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; + if (link->fromsock == extsock) { + bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link"); + *tlink = *link; + BLI_addtail(&tmplinks, tlink); + } + } + + if (tmplinks.first) { + bNodeSocket *gsock, *newsock; + /* XXX Multiple sockets can be connected to the extension socket at once, + * in that case the arbitrary first link determines name and type. + * This could be improved by choosing the "best" type among all links, + * whatever that means. + */ + bNodeLink *exposelink = tmplinks.first; + + /* XXX what if connecting virtual to virtual socket?? */ + gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->tonode, exposelink->tosock); + + node_group_input_verify(ntree, node, (ID *)ntree); + newsock = node_group_input_find_socket(node, gsock->identifier); + + /* redirect links from the extension socket */ + for (link = tmplinks.first; link; link = link->next) { + nodeAddLink(ntree, node, newsock, link->tonode, link->tosock); + } + + BLI_freelistN(&tmplinks); + } +} + +void register_node_type_group_input(void) +{ + /* used for all tree types, needs dynamic allocation */ + bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type"); + + node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE, NODE_OPTIONS); + node_type_size(ntype, 140, 80, 200); + node_type_init(ntype, node_group_input_init); + node_type_update(ntype, node_group_input_update, node_group_input_verify); + node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); + + ntype->needs_free = 1; + nodeRegisterType(ntype); +} + +static void node_group_output_init(bNodeTree *ntree, bNode *node) +{ + node_group_output_verify(ntree, node, (ID *)ntree); +} + +bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier) +{ + bNodeSocket *sock; + for (sock = node->inputs.first; sock; sock = sock->next) + if (STREQ(sock->identifier, identifier)) + return sock; + return NULL; +} + +void node_group_output_verify(bNodeTree *ntree, bNode *node, ID *id) +{ + /* check inputs and outputs, and remove or insert them */ + if (id == (ID *)ntree) { + /* value_in_out inverted for interface nodes to get correct socket value_property */ + group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN); + + /* add virtual extension socket */ + nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", ""); + } +} + +static void node_group_output_update(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *extsock = node->inputs.last; + bNodeLink *link; + /* Adding a tree socket and verifying will remove the extension socket! + * This list caches the existing links to the extension socket + * so they can be recreated after verification. + */ + ListBase tmplinks; + + /* find links to the extension socket and store them */ + tmplinks.first = tmplinks.last = NULL; + for (link = ntree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; + if (link->tosock == extsock) { + bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link"); + *tlink = *link; + BLI_addtail(&tmplinks, tlink); + } + } + + if (tmplinks.first) { + bNodeSocket *gsock, *newsock; + /* XXX Multiple sockets can be connected to the extension socket at once, + * in that case the arbitrary first link determines name and type. + * This could be improved by choosing the "best" type among all links, + * whatever that means. + */ + bNodeLink *exposelink = tmplinks.first; + + /* XXX what if connecting virtual to virtual socket?? */ + gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock); + + node_group_output_verify(ntree, node, (ID *)ntree); + newsock = node_group_output_find_socket(node, gsock->identifier); + + /* redirect links to the extension socket */ + for (link = tmplinks.first; link; link = link->next) { + nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock); + } + + BLI_freelistN(&tmplinks); + } +} + +void register_node_type_group_output(void) +{ + /* used for all tree types, needs dynamic allocation */ + bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type"); + + node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE, NODE_OPTIONS); + node_type_size(ntype, 140, 80, 200); + node_type_init(ntype, node_group_output_init); + node_type_update(ntype, node_group_output_update, node_group_output_verify); + node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); + + ntype->needs_free = 1; + nodeRegisterType(ntype); +} diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h index 9e04a9e05f8..498da607b91 100644 --- a/source/blender/nodes/intern/node_common.h +++ b/source/blender/nodes/intern/node_common.h @@ -37,15 +37,8 @@ struct bNodeTree; -void node_group_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp); const char *node_group_label(struct bNode *node); -struct bNodeTemplate node_group_template(struct bNode *node); -int node_group_valid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); -void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id); - -struct bNodeTree *node_group_edit_get(struct bNode *node); -struct bNodeTree *node_group_edit_set(struct bNode *node, int edit); -void node_group_edit_clear(bNode *node); +int node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree); void ntree_update_reroute_nodes(struct bNodeTree *ntree); diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 8cf7cc7a1ea..f6bf1db5254 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -41,12 +41,19 @@ #include "MEM_guardedalloc.h" #include "node_exec.h" +#include "node_util.h" +/* supported socket types in old nodes */ +int node_exec_socket_use_stack(bNodeSocket *sock) +{ + return ELEM3(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); +} + /* for a given socket, find the actual stack entry */ bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock) { - if (stack && sock) + if (stack && sock && sock->stack_index >= 0) return stack + sock->stack_index; return NULL; } @@ -75,7 +82,10 @@ static void node_init_input_index(bNodeSocket *sock, int *index) sock->stack_index = sock->link->fromsock->stack_index; } else { - sock->stack_index = (*index)++; + if (node_exec_socket_use_stack(sock)) + sock->stack_index = (*index)++; + else + sock->stack_index = -1; } } @@ -91,19 +101,27 @@ static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *inte } } /* if not internally connected, assign a new stack index anyway to avoid bad stack access */ - if (!link) - sock->stack_index = (*index)++; + if (!link) { + if (node_exec_socket_use_stack(sock)) + sock->stack_index = (*index)++; + else + sock->stack_index = -1; + } } else { - sock->stack_index = (*index)++; + if (node_exec_socket_use_stack(sock)) + sock->stack_index = (*index)++; + else + sock->stack_index = -1; } } /* basic preparation of socket stacks */ -static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock) +static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock) { bNodeStack *ns = node_get_socket_stack(stack, sock); - float null_value[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + if (!ns) + return NULL; /* don't mess with remote socket stacks, these are initialized by other nodes! */ if (sock->link) @@ -111,49 +129,37 @@ static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock) ns->sockettype = sock->type; - if (sock->default_value) { - switch (sock->type) { + switch (sock->type) { case SOCK_FLOAT: - ns->vec[0] = ((bNodeSocketValueFloat *)sock->default_value)->value; + ns->vec[0] = node_socket_get_float(ntree, node, sock); break; case SOCK_VECTOR: - copy_v3_v3(ns->vec, ((bNodeSocketValueVector *)sock->default_value)->value); + node_socket_get_vector(ntree, node, sock, ns->vec); break; case SOCK_RGBA: - copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA *)sock->default_value)->value); + node_socket_get_color(ntree, node, sock, ns->vec); break; - } - } - else { - switch (sock->type) { - case SOCK_FLOAT: - ns->vec[0] = 0.0f; - break; - case SOCK_VECTOR: - copy_v3_v3(ns->vec, null_value); - break; - case SOCK_RGBA: - copy_v4_v4(ns->vec, null_value); - break; - } } return ns; } -bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) +bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) { bNodeTreeExec *exec; bNode *node; bNodeExec *nodeexec; - bNodeSocket *sock, *gsock; + bNodeInstanceKey nodekey; + bNodeSocket *sock; bNodeStack *ns; int index; bNode **nodelist; int totnodes, n; - if ((ntree->init & NTREE_TYPE_INIT)==0) - ntreeInitTypes(ntree); + BLI_assert(ntreeIsValid(ntree)); + + /* ensure all sock->link pointers and node levels are correct */ + ntreeUpdateTree(ntree); /* get a dependency-sorted list of nodes */ ntreeGetDependencyList(ntree, &nodelist, &totnodes); @@ -165,30 +171,24 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) /* set stack indices */ index = 0; - /* group inputs essentially work as outputs */ - for (gsock=ntree->inputs.first; gsock; gsock = gsock->next) - node_init_output_index(gsock, &index, NULL); for (n=0; n < totnodes; ++n) { node = nodelist[n]; node->stack_index = index; /* init node socket stack indexes */ - for (sock=node->inputs.first; sock; sock=sock->next) + for (sock = node->inputs.first; sock; sock = sock->next) node_init_input_index(sock, &index); if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { - for (sock=node->outputs.first; sock; sock=sock->next) + for (sock = node->outputs.first; sock; sock = sock->next) node_init_output_index(sock, &index, &node->internal_links); } else { - for (sock=node->outputs.first; sock; sock=sock->next) + for (sock = node->outputs.first; sock; sock = sock->next) node_init_output_index(sock, &index, NULL); } } - /* group outputs essentially work as inputs */ - for (gsock=ntree->outputs.first; gsock; gsock = gsock->next) - node_init_input_index(gsock, &index); /* allocated exec data pointers for nodes */ exec->totnodes = totnodes; @@ -201,36 +201,30 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) for (n=0; n < exec->stacksize; ++n) exec->stack[n].hasinput = 1; - /* prepare group tree inputs */ - for (sock=ntree->inputs.first; sock; sock=sock->next) { - /* ns = */ setup_stack(exec->stack, sock); - } - /* prepare all internal nodes for execution */ + /* prepare all nodes for execution */ for (n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) { node = nodeexec->node = nodelist[n]; /* tag inputs */ - for (sock=node->inputs.first; sock; sock=sock->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { /* disable the node if an input link is invalid */ if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) node->need_exec= 0; - ns = setup_stack(exec->stack, sock); - ns->hasoutput = 1; + ns = setup_stack(exec->stack, ntree, node, sock); + if (ns) + ns->hasoutput = 1; } /* tag all outputs */ - for (sock=node->outputs.first; sock; sock=sock->next) { - /* ns = */ setup_stack(exec->stack, sock); + for (sock = node->outputs.first; sock; sock = sock->next) { + /* ns = */ setup_stack(exec->stack, ntree, node, sock); } + nodekey = BKE_node_instance_key(parent_key, ntree, node); + nodeexec->data.preview = context->previews ? BKE_node_instance_hash_lookup(context->previews, nodekey) : NULL; if (node->typeinfo->initexecfunc) - nodeexec->data = node->typeinfo->initexecfunc(node); - } - /* prepare group tree outputs */ - for (sock=ntree->outputs.first; sock; sock=sock->next) { - ns = setup_stack(exec->stack, sock); - ns->hasoutput = 1; + nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey); } if (nodelist) @@ -250,7 +244,7 @@ void ntree_exec_end(bNodeTreeExec *exec) for (n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { if (nodeexec->node->typeinfo) if (nodeexec->node->typeinfo->freeexecfunc) - nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data); + nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data.data); } if (exec->nodeexec) @@ -309,9 +303,7 @@ bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call // if (node->typeinfo->compatibility == NODE_NEW_SHADING) // return false; if (node->typeinfo->execfunc) - node->typeinfo->execfunc(callerdata, node, nsin, nsout); - else if (node->typeinfo->newexecfunc) - node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout); + node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout); } } diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index 5febda036e0..7d76ef34934 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -39,6 +39,8 @@ #include "BKE_node.h" +#include "node_util.h" + #include "RNA_types.h" struct bNodeTree; @@ -48,20 +50,20 @@ struct bNodeStack; /* Node execution data */ typedef struct bNodeExec { struct bNode *node; /* backpointer to node */ - void *data; /* custom data storage */ + bNodeExecData data; } bNodeExec; /* Execution Data for each instance of node tree execution */ typedef struct bNodeTreeExec { struct bNodeTree *nodetree; /* backpointer to node tree */ - int totnodes; /* total node count */ + int totnodes; /* total node count */ struct bNodeExec *nodeexec; /* per-node execution data */ int stacksize; struct bNodeStack *stack; /* socket data stack */ /* only used by material and texture trees to keep one stack for each thread */ - ListBase *threadstack; /* one instance of the stack for each thread */ + ListBase *threadstack; /* one instance of the stack for each thread */ } bNodeTreeExec; /* stores one stack copy for each thread (material and texture trees) */ @@ -71,14 +73,22 @@ typedef struct bNodeThreadStack { int used; } bNodeThreadStack; +int node_exec_socket_use_stack(struct bNodeSocket *sock); + struct bNodeStack *node_get_socket_stack(struct bNodeStack *stack, struct bNodeSocket *sock); void node_get_stack(struct bNode *node, struct bNodeStack *stack, struct bNodeStack **in, struct bNodeStack **out); -struct bNodeTreeExec *ntree_exec_begin(struct bNodeTree *ntree); +struct bNodeTreeExec *ntree_exec_begin(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key); void ntree_exec_end(struct bNodeTreeExec *exec); struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread); void ntreeReleaseThreadStack(struct bNodeThreadStack *nts); bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread); +struct bNodeTreeExec *ntreeShaderBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key); +void ntreeShaderEndExecTree_internal(struct bNodeTreeExec *exec); + +struct bNodeTreeExec *ntreeTexBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key); +void ntreeTexEndExecTree_internal(struct bNodeTreeExec *exec); + #endif diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 69256fafc3d..86a8331e5dd 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -33,547 +33,95 @@ #include "DNA_node_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLI_string.h" -#include "BKE_DerivedMesh.h" #include "BKE_node.h" +#include "BKE_idprop.h" #include "RNA_access.h" +#include "RNA_define.h" #include "RNA_types.h" #include "MEM_guardedalloc.h" #include "NOD_socket.h" -/****************** FLOAT ******************/ - -static bNodeSocketType node_socket_type_float = { - /* type */ SOCK_FLOAT, - /* ui_name */ "Float", - /* ui_description */ "Floating Point", - /* ui_icon */ 0, - /* ui_color */ {160, 160, 160, 255}, - - /* value_structname */ "bNodeSocketValueFloat", - /* value_structsize */ sizeof(bNodeSocketValueFloat), - - /* buttonfunc */ NULL, -}; - -/****************** VECTOR ******************/ - -static bNodeSocketType node_socket_type_vector = { - /* type */ SOCK_VECTOR, - /* ui_name */ "Vector", - /* ui_description */ "3-dimensional floating point vector", - /* ui_icon */ 0, - /* ui_color */ {100, 100, 200, 255}, - - /* value_structname */ "bNodeSocketValueVector", - /* value_structsize */ sizeof(bNodeSocketValueVector), - - /* buttonfunc */ NULL, -}; - -/****************** RGBA ******************/ - -static bNodeSocketType node_socket_type_rgba = { - /* type */ SOCK_RGBA, - /* ui_name */ "RGBA", - /* ui_description */ "RGBA color", - /* ui_icon */ 0, - /* ui_color */ {200, 200, 40, 255}, - - /* value_structname */ "bNodeSocketValueRGBA", - /* value_structsize */ sizeof(bNodeSocketValueRGBA), - - /* buttonfunc */ NULL, -}; - -/****************** INT ******************/ - -static bNodeSocketType node_socket_type_int = { - /* type */ SOCK_INT, - /* ui_name */ "Int", - /* ui_description */ "Integer", - /* ui_icon */ 0, - /* ui_color */ {17, 133, 37, 255}, - - /* value_structname */ "bNodeSocketValueInt", - /* value_structsize */ sizeof(bNodeSocketValueInt), - - /* buttonfunc */ NULL, -}; - -/****************** BOOLEAN ******************/ - -static bNodeSocketType node_socket_type_boolean = { - /* type */ SOCK_BOOLEAN, - /* ui_name */ "Boolean", - /* ui_description */ "Boolean", - /* ui_icon */ 0, - /* ui_color */ {158, 139, 63, 255}, - - /* value_structname */ "bNodeSocketValueBoolean", - /* value_structsize */ sizeof(bNodeSocketValueBoolean), - - /* buttonfunc */ NULL, -}; - -/****************** SHADER ******************/ - -static bNodeSocketType node_socket_type_shader = { - /* type */ SOCK_SHADER, - /* ui_name */ "Shader", - /* ui_description */ "Shader", - /* ui_icon */ 0, - /* ui_color */ {100, 200, 100, 255}, - - /* value_structname */ NULL, - /* value_structsize */ 0, - - /* buttonfunc */ NULL, -}; - -/****************** MESH ******************/ - -static bNodeSocketType node_socket_type_mesh = { - /* type */ SOCK_MESH, - /* ui_name */ "Mesh", - /* ui_description */ "Mesh geometry data", - /* ui_icon */ 0, - /* ui_color */ {255, 133, 7, 255}, - - /* value_structname */ NULL, - /* value_structsize */ 0, - - /* buttonfunc */ NULL, -}; +struct Main; -/****************** STRING ******************/ - -static bNodeSocketType node_socket_type_string = { - /* type */ SOCK_STRING, - /* ui_name */ "String", - /* ui_description */ "String", - /* ui_icon */ 0, - /* ui_color */ {255, 255, 255, 255}, - - /* value_structname */ "bNodeSocketValueString", - /* value_structsize */ sizeof(bNodeSocketValueString), - - /* buttonfunc */ NULL, -}; - -void node_socket_type_init(bNodeSocketType *types[]) +struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out) { - #define INIT_TYPE(name) types[node_socket_type_##name.type] = &node_socket_type_##name + bNodeSocket *sock = nodeAddStaticSocket(ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name); - INIT_TYPE(float); - INIT_TYPE(vector); - INIT_TYPE(rgba); - INIT_TYPE(int); - INIT_TYPE(boolean); - INIT_TYPE(shader); - INIT_TYPE(mesh); - INIT_TYPE(string); + sock->flag |= stemp->flag; - #undef INIT_TYPE -} - -void *node_socket_make_default_value(int type) -{ - /* XXX currently just allocates from stype->structsize. - * it might become necessary to do more complex allocations for later types. - */ - bNodeSocketType *stype = ntreeGetSocketType(type); - if (stype->value_structsize > 0) { - void *default_value = MEM_callocN(stype->value_structsize, "default socket value"); - return default_value; - } - else - return NULL; -} - -void node_socket_free_default_value(int UNUSED(type), void *default_value) -{ - /* XXX can just free the pointee for all current socket types. */ - if (default_value) - MEM_freeN(default_value); -} - -void node_socket_init_default_value(int type, void *default_value) -{ - switch (type) { - case SOCK_FLOAT: - node_socket_set_default_value_float(default_value, PROP_NONE, 0.0f, -FLT_MAX, FLT_MAX); - break; - case SOCK_INT: - node_socket_set_default_value_int(default_value, PROP_NONE, 0, INT_MIN, INT_MAX); - break; - case SOCK_BOOLEAN: - node_socket_set_default_value_boolean(default_value, FALSE); - break; - case SOCK_VECTOR: - node_socket_set_default_value_vector(default_value, PROP_NONE, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX); - break; - case SOCK_RGBA: - node_socket_set_default_value_rgba(default_value, 0.0f, 0.0f, 0.0f, 1.0f); - break; - case SOCK_SHADER: - node_socket_set_default_value_shader(default_value); - break; - case SOCK_MESH: - node_socket_set_default_value_mesh(default_value); - break; - case SOCK_STRING: - node_socket_set_default_value_string(default_value, PROP_NONE, (char *)""); - break; - } -} - -void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max) -{ - bNodeSocketValueInt *val = default_value; - val->subtype = subtype; - val->value = value; - val->min = min; - val->max = max; -} - -void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max) -{ - bNodeSocketValueFloat *val = default_value; - val->subtype = subtype; - val->value = value; - val->min = min; - val->max = max; -} - -void node_socket_set_default_value_boolean(void *default_value, char value) -{ - bNodeSocketValueBoolean *val = default_value; - val->value = value; -} - -void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max) -{ - bNodeSocketValueVector *val = default_value; - val->subtype = subtype; - val->value[0] = x; - val->value[1] = y; - val->value[2] = z; - val->min = min; - val->max = max; -} - -void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a) -{ - bNodeSocketValueRGBA *val = default_value; - val->value[0] = r; - val->value[1] = g; - val->value[2] = b; - val->value[3] = a; -} - -void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value) -{ - bNodeSocketValueString *val = default_value; - val->subtype = subtype; - BLI_strncpy(val->value, value, 1024);//FILE_MAX -} - -void node_socket_set_default_value_shader(void *UNUSED(default_value)) -{ -} - -void node_socket_set_default_value_mesh(void *UNUSED(default_value)) -{ -} - - -void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value) -{ - /* XXX only one of these pointers is valid! just putting them here for convenience */ - bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value; - bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value; - bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value; - bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value; - bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value; - bNodeSocketValueString *fromstring= (bNodeSocketValueString*)from_default_value; - - bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value; - bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value; - bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value; - bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value; - bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value; - bNodeSocketValueString *tostring= (bNodeSocketValueString*)to_default_value; - - switch (type) { - case SOCK_FLOAT: - *tofloat = *fromfloat; - break; - case SOCK_INT: - *toint = *fromint; - break; - case SOCK_BOOLEAN: - *tobool = *frombool; - break; - case SOCK_VECTOR: - *tovector = *fromvector; - break; - case SOCK_RGBA: - *torgba = *fromrgba; - break; - case SOCK_STRING: - *tostring = *fromstring; - break; - } -} - -/* XXX This is a makeshift function to have useful initial group socket values. - * In the end this should be implemented by a flexible socket data conversion system, - * which is yet to be implemented. The idea is that beside default standard conversions, - * such as int-to-float, it should be possible to quickly select a conversion method or - * a chain of conversions for each input, whenever there is more than one option. - * E.g. a vector-to-float conversion could use either of the x/y/z components or - * the vector length. - * - * In the interface this could be implemented by a pseudo-script textbox on linked inputs, - * with quick selection from a predefined list of conversion options. Some Examples: - * - vector component 'z' (vector->float): "z" - * - grayscale color (float->color): "gray" - * - color luminance (color->float): "lum" - * - matrix column 2 length (matrix->vector->float): "col[1].len" - * - mesh vertex coordinate 'y' (mesh->vertex->vector->float): "vertex.co.y" - * - * The actual conversion is then done by a series of conversion functions, - * which are defined in the socket type structs. - */ -void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value) -{ - /* XXX only one of these pointers is valid! just putting them here for convenience */ - bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value; - bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value; - bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value; - bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value; - bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value; - - bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value; - bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value; - bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value; - bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value; - bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value; - - switch (from_type) { - case SOCK_FLOAT: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = fromfloat->value; - break; - case SOCK_INT: - toint->value = (int)fromfloat->value; - break; - case SOCK_BOOLEAN: - tobool->value = (fromfloat->value > 0.0f); - break; - case SOCK_VECTOR: - tovector->value[0] = tovector->value[1] = tovector->value[2] = fromfloat->value; - break; - case SOCK_RGBA: - torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = fromfloat->value; - break; - } - break; - case SOCK_INT: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = (float)fromint->value; - break; - case SOCK_INT: - toint->value = fromint->value; - break; - case SOCK_BOOLEAN: - tobool->value = (fromint->value > 0); - break; - case SOCK_VECTOR: - tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)fromint->value; - break; - case SOCK_RGBA: - torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)fromint->value; - break; - } - break; - case SOCK_BOOLEAN: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = (float)frombool->value; - break; - case SOCK_INT: - toint->value = (int)frombool->value; - break; - case SOCK_BOOLEAN: - tobool->value = frombool->value; - break; - case SOCK_VECTOR: - tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)frombool->value; - break; - case SOCK_RGBA: - torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)frombool->value; - break; - } - break; - case SOCK_VECTOR: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = fromvector->value[0]; - break; - case SOCK_INT: - toint->value = (int)fromvector->value[0]; - break; - case SOCK_BOOLEAN: - tobool->value = (fromvector->value[0] > 0.0f); - break; - case SOCK_VECTOR: - copy_v3_v3(tovector->value, fromvector->value); - break; - case SOCK_RGBA: - copy_v3_v3(torgba->value, fromvector->value); - torgba->value[3] = 1.0f; + /* initialize default_value */ + switch (stemp->type) { + case SOCK_FLOAT: { + bNodeSocketValueFloat *dval = sock->default_value; + dval->value = stemp->val1; + dval->min = stemp->min; + dval->max = stemp->max; break; } - break; - case SOCK_RGBA: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = fromrgba->value[0]; - break; - case SOCK_INT: - toint->value = (int)fromrgba->value[0]; - break; - case SOCK_BOOLEAN: - tobool->value = (fromrgba->value[0] > 0.0f); - break; - case SOCK_VECTOR: - copy_v3_v3(tovector->value, fromrgba->value); - break; - case SOCK_RGBA: - copy_v4_v4(torgba->value, fromrgba->value); + case SOCK_INT: { + bNodeSocketValueInt *dval = sock->default_value; + dval->value = (int)stemp->val1; + dval->min = (int)stemp->min; + dval->max = (int)stemp->max; break; } - break; - } -} - -static void node_socket_set_minmax_subtype(bNodeSocket *sock, struct bNodeSocketTemplate *stemp) -{ - switch (sock->type) { - case SOCK_FLOAT: - { - bNodeSocketValueFloat *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; + case SOCK_BOOLEAN: { + bNodeSocketValueBoolean *dval = sock->default_value; + dval->value = (int)stemp->val1; break; } - case SOCK_INT: - { - bNodeSocketValueInt *dval= sock->default_value; + case SOCK_VECTOR: { + bNodeSocketValueVector *dval = sock->default_value; + dval->value[0] = stemp->val1; + dval->value[1] = stemp->val2; + dval->value[2] = stemp->val3; dval->min = stemp->min; dval->max = stemp->max; - dval->subtype = stemp->subtype; break; } - case SOCK_VECTOR: - { - bNodeSocketValueVector *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; + case SOCK_RGBA: { + bNodeSocketValueRGBA *dval = sock->default_value; + dval->value[0] = stemp->val1; + dval->value[1] = stemp->val2; + dval->value[2] = stemp->val3; + dval->value[3] = stemp->val4; break; } } -} - -struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) -{ - bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type); - sock->flag |= stemp->flag; - - switch (stemp->type) { - case SOCK_INT: - node_socket_set_default_value_int(sock->default_value, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max); - break; - case SOCK_FLOAT: - node_socket_set_default_value_float(sock->default_value, stemp->subtype, stemp->val1, stemp->min, stemp->max); - break; - case SOCK_BOOLEAN: - node_socket_set_default_value_boolean(sock->default_value, (char)stemp->val1); - break; - case SOCK_VECTOR: - node_socket_set_default_value_vector(sock->default_value, stemp->subtype, stemp->val1, stemp->val2, stemp->val3, stemp->min, stemp->max); - break; - case SOCK_RGBA: - node_socket_set_default_value_rgba(sock->default_value, stemp->val1, stemp->val2, stemp->val3, stemp->val4); - break; - case SOCK_SHADER: - node_socket_set_default_value_shader(sock->default_value); - break; - case SOCK_MESH: - node_socket_set_default_value_mesh(sock->default_value); - break; - case SOCK_STRING: - node_socket_set_default_value_string(sock->default_value, stemp->subtype, (char *)""); - break; - } return sock; } -struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) -{ - bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type); - node_socket_set_minmax_subtype(sock, stemp); - return sock; -} - static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp) { bNodeSocket *sock; for (sock= socklist->first; sock; sock= sock->next) { - if (!(sock->flag & SOCK_DYNAMIC) && strncmp(sock->name, stemp->name, NODE_MAXSTR)==0) + if (strncmp(sock->name, stemp->name, NODE_MAXSTR)==0) break; } if (sock) { - sock->type = stemp->type; /* in future, read this from tydefs! */ + sock->type = stemp->type; if (stemp->limit == 0) sock->limit= 0xFFF; else sock->limit = stemp->limit; sock->flag |= stemp->flag; - /* Copy the property range and subtype parameters in case the template changed. - * NOT copying the actual value here, only button behavior changes! - */ - node_socket_set_minmax_subtype(sock, stemp); - BLI_remlink(socklist, sock); return sock; } else { /* no socket for this template found, make a new one */ - if (in_out==SOCK_IN) - sock = node_add_input_from_template(ntree, node, stemp); - else - sock = node_add_output_from_template(ntree, node, stemp); + sock = node_add_socket_from_template(ntree, node, stemp, in_out); /* remove the new socket from the node socket list first, * will be added back after verification. */ @@ -592,8 +140,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou if (stemp_first==NULL) { for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) { nextsock = sock->next; - if (!(sock->flag & SOCK_DYNAMIC)) - nodeRemoveSocket(ntree, node, sock); + nodeRemoveSocket(ntree, node, sock); } } else { @@ -606,8 +153,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou /* leftovers are removed */ for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) { nextsock = sock->next; - if (!(sock->flag & SOCK_DYNAMIC)) - nodeRemoveSocket(ntree, node, sock); + nodeRemoveSocket(ntree, node, sock); } /* and we put back the verified sockets */ @@ -635,14 +181,184 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou void node_verify_socket_templates(bNodeTree *ntree, bNode *node) { bNodeType *ntype= node->typeinfo; - /* XXX Small trick: don't try to match socket lists when there are no templates. - * This also prevents group node sockets from being removed, without the need to explicitly + /* Don't try to match socket lists when there are no templates. + * This prevents group node sockets from being removed, without the need to explicitly * check the node type here. */ - if (ntype && ((ntype->inputs && ntype->inputs[0].type >= 0) || - (ntype->outputs && ntype->outputs[0].type >= 0))) - { - verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs); - verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs); + if (ntype) { + if (ntype->inputs && ntype->inputs[0].type >= 0) + verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs); + if (ntype->outputs && ntype->outputs[0].type >= 0) + verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs); + } +} + + +void node_socket_init_default_value(bNodeSocket *sock) +{ + int type = sock->typeinfo->type; + int subtype = sock->typeinfo->subtype; + + if (sock->default_value) + return; /* already initialized */ + + switch (type) { + case SOCK_FLOAT: { + bNodeSocketValueFloat *dval = MEM_callocN(sizeof(bNodeSocketValueFloat), "node socket value float"); + dval->subtype = subtype; + dval->value = 0.0f; + dval->min = -FLT_MAX; + dval->max = FLT_MAX; + + sock->default_value = dval; + break; + } + case SOCK_INT: { + bNodeSocketValueInt *dval = MEM_callocN(sizeof(bNodeSocketValueInt), "node socket value int"); + dval->subtype = subtype; + dval->value = 0; + dval->min = INT_MIN; + dval->max = INT_MAX; + + sock->default_value = dval; + break; + } + case SOCK_BOOLEAN: { + bNodeSocketValueBoolean *dval = MEM_callocN(sizeof(bNodeSocketValueBoolean), "node socket value bool"); + dval->value = false; + + sock->default_value = dval; + break; + } + case SOCK_VECTOR: { + static float default_value[] = { 0.0f, 0.0f, 0.0f }; + bNodeSocketValueVector *dval = MEM_callocN(sizeof(bNodeSocketValueVector), "node socket value vector"); + dval->subtype = subtype; + copy_v3_v3(dval->value, default_value); + dval->min = -FLT_MAX; + dval->max = FLT_MAX; + + sock->default_value = dval; + break; } + case SOCK_RGBA: { + static float default_value[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + bNodeSocketValueRGBA *dval = MEM_callocN(sizeof(bNodeSocketValueRGBA), "node socket value color"); + copy_v4_v4(dval->value, default_value); + + sock->default_value = dval; + break; + } + case SOCK_STRING: { + bNodeSocketValueString *dval = MEM_callocN(sizeof(bNodeSocketValueString), "node socket value string"); + dval->subtype = subtype; + dval->value[0] = '\0'; + + sock->default_value = dval; + break; + } + } +} + + +static void standard_node_socket_interface_init_socket(bNodeTree *UNUSED(ntree), bNodeSocket *UNUSED(stemp), bNode *UNUSED(node), bNodeSocket *sock, const char *UNUSED(data_path)) +{ + /* initialize the type value */ + sock->type = sock->typeinfo->type; +} + +static bNodeSocketType *make_standard_socket_type(int type, int subtype) +{ + extern void ED_init_standard_node_socket_type(bNodeSocketType *); + + const char *socket_idname = nodeStaticSocketType(type, subtype); + const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype); + bNodeSocketType *stype; + StructRNA *srna; + + stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type"); + BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname)); + + /* set the RNA type + * uses the exact same identifier as the socket type idname */ + srna = stype->ext_socket.srna = RNA_struct_find(socket_idname); + BLI_assert(srna != NULL); + /* associate the RNA type with the socket type */ + RNA_struct_blender_type_set(srna, stype); + + /* set the interface RNA type */ + srna = stype->ext_interface.srna = RNA_struct_find(interface_idname); + BLI_assert(srna != NULL); + /* associate the RNA type with the socket type */ + RNA_struct_blender_type_set(srna, stype); + + /* extra type info for standard socket types */ + stype->type = type; + stype->subtype = subtype; + + /* XXX bad-level call! needed for setting draw callbacks */ + ED_init_standard_node_socket_type(stype); + + stype->interface_init_socket = standard_node_socket_interface_init_socket; + + return stype; +} + +static bNodeSocketType *make_socket_type_virtual(void) +{ + extern void ED_init_node_socket_type_virtual(bNodeSocketType *); + + const char *socket_idname = "NodeSocketVirtual"; + bNodeSocketType *stype; + StructRNA *srna; + + stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type"); + BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname)); + + /* set the RNA type + * uses the exact same identifier as the socket type idname */ + srna = stype->ext_socket.srna = RNA_struct_find(socket_idname); + BLI_assert(srna != NULL); + /* associate the RNA type with the socket type */ + RNA_struct_blender_type_set(srna, stype); + + ED_init_node_socket_type_virtual(stype); + + return stype; +} + + +void register_standard_node_socket_types(void) +{ + /* draw callbacks are set in drawnode.c to avoid bad-level calls */ + + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_UNSIGNED)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_PERCENTAGE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_FACTOR)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_ANGLE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_TIME)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_UNSIGNED)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_PERCENTAGE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_FACTOR)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_TRANSLATION)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_DIRECTION)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_VELOCITY)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_ACCELERATION)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_EULER)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_XYZ)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_RGBA, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_STRING, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE)); + + nodeRegisterSocketType(make_socket_type_virtual()); } diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index 09e6ddd18a5..c622c1c5227 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -30,6 +30,7 @@ */ #include <limits.h> +#include <string.h> #include "DNA_action_types.h" #include "DNA_node_types.h" @@ -63,17 +64,17 @@ void node_free_standard_storage(bNode *node) } } -void node_copy_curves(bNode *orig_node, bNode *new_node) +void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - new_node->storage = curvemapping_copy(orig_node->storage); + dest_node->storage = curvemapping_copy(src_node->storage); } -void node_copy_standard_storage(bNode *orig_node, bNode *new_node) +void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - new_node->storage = MEM_dupallocN(orig_node->storage); + dest_node->storage = MEM_dupallocN(src_node->storage); } -void *node_initexec_curves(bNode *node) +void *node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNodeInstanceKey UNUSED(key)) { curvemapping_initialize(node->storage); return NULL; /* unused return */ @@ -129,6 +130,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node) fromindex = INT_MAX; fromsock = NULL; for (link=ntree->links.first; link; link=link->next) { + if (nodeLinkIsHidden(link)) + continue; if (link->tonode == node && link->tosock->type == datatype) { int index = BLI_findindex(&node->inputs, link->tosock); if (index < fromindex) { @@ -146,6 +149,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node) toindex = INT_MAX; tosock = NULL; for (link=ntree->links.first; link; link=link->next) { + if (nodeLinkIsHidden(link)) + continue; if (link->fromnode == node && link->fromsock->type == datatype) { int index = BLI_findindex(&node->outputs, link->fromsock); if (index < toindex) { @@ -188,3 +193,45 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node) BLI_addtail(&node->internal_links, ilink); } } + +float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + return RNA_float_get(&ptr, "default_value"); +} + +void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_set(&ptr, "default_value", value); +} + +void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_get_array(&ptr, "default_value", value); +} + +void node_socket_set_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_set_array(&ptr, "default_value", value); +} + +void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_get_array(&ptr, "default_value", value); +} + +void node_socket_set_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_set_array(&ptr, "default_value", value); +} diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index 6b783915816..2b3f84420f9 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -35,6 +35,8 @@ #include "DNA_listBase.h" +#include "BLI_utildefines.h" + #include "BKE_node.h" #include "MEM_guardedalloc.h" @@ -43,17 +45,29 @@ #include "GPU_material.h" /* For Shader muting GPU code... */ +#include "RNA_access.h" + struct bNodeTree; struct bNode; +/* data for initializing node execution */ +typedef struct bNodeExecContext { + struct bNodeInstanceHash *previews; +} bNodeExecContext; + +typedef struct bNodeExecData { + void *data; /* custom data storage */ + struct bNodePreview *preview; /* optional preview image */ +} bNodeExecData; + /**** Storage Data ****/ extern void node_free_curves(struct bNode *node); extern void node_free_standard_storage(struct bNode *node); -extern void node_copy_curves(struct bNode *orig_node, struct bNode *new_node); -extern void node_copy_standard_storage(struct bNode *orig_node, struct bNode *new_node); -extern void *node_initexec_curves(struct bNode *node); +extern void node_copy_curves(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node); +extern void node_copy_standard_storage(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node); +extern void *node_initexec_curves(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key); /**** Labels ****/ @@ -64,4 +78,11 @@ const char *node_filter_label(struct bNode *node); void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node); +float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock); +void node_socket_set_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float value); +void node_socket_get_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value); +void node_socket_set_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value); +void node_socket_get_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value); +void node_socket_set_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value); + #endif diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 8fde0b9c342..68846255983 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -36,6 +36,7 @@ #include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" +#include "DNA_space_types.h" #include "DNA_world_types.h" #include "BLI_listbase.h" @@ -45,11 +46,14 @@ #include "BLF_translation.h" +#include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_scene.h" +#include "RNA_access.h" + #include "GPU_material.h" #include "RE_shader_ext.h" @@ -59,23 +63,45 @@ #include "node_util.h" #include "node_shader_util.h" -static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) +static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype)) { - Material *ma; - Lamp *la; - World *wo; - - for (ma = main->mat.first; ma; ma = ma->id.next) - if (ma->nodetree) - func(calldata, &ma->id, ma->nodetree); - - for (la = main->lamp.first; la; la = la->id.next) - if (la->nodetree) - func(calldata, &la->id, la->nodetree); + Scene *scene = CTX_data_scene(C); + /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */ + return (scene->r.engine[0] == '\0' + || strcmp(scene->r.engine, "BLENDER_RENDER")==0 + || strcmp(scene->r.engine, "CYCLES")==0); +} - for (wo = main->world.first; wo; wo = wo->id.next) - if (wo->nodetree) - func(calldata, &wo->id, wo->nodetree); +static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from) +{ + SpaceNode *snode = CTX_wm_space_node(C); + Scene *scene = CTX_data_scene(C); + Object *ob = OBACT; + + if (snode->shaderfrom == SNODE_SHADER_OBJECT) { + if (ob) { + if (ob->type == OB_LAMP) { + *r_from = &ob->id; + *r_id = ob->data; + *r_ntree = ((Lamp *)ob->data)->nodetree; + } + else { + Material *ma = give_current_material(ob, ob->actcol); + if (ma) { + *r_from = &ob->id; + *r_id = &ma->id; + *r_ntree = ma->nodetree; + } + } + } + } + else { /* SNODE_SHADER_WORLD */ + if (scene->world) { + *r_from = NULL; + *r_id = &scene->world->id; + *r_ntree = scene->world->nodetree; + } + } } static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func) @@ -93,6 +119,7 @@ static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback f func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor")); func(calldata, NODE_CLASS_SCRIPT, N_("Script")); func(calldata, NODE_CLASS_GROUP, N_("Group")); + func(calldata, NODE_CLASS_INTERFACE, N_("Interface")); func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); } @@ -111,24 +138,8 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) } } -static void local_sync(bNodeTree *localtree, bNodeTree *ntree) +static void local_sync(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree)) { - bNode *lnode; - - /* copy over contents of previews */ - for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) { - if (ntreeNodeExists(ntree, lnode->new_node)) { - bNode *node = lnode->new_node; - - if (node->preview && node->preview->rect) { - if (lnode->preview && lnode->preview->rect) { - int xsize = node->preview->xsize; - int ysize = node->preview->ysize; - memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); - } - } - } - } } static void update(bNodeTree *ntree) @@ -136,26 +147,36 @@ static void update(bNodeTree *ntree) ntreeSetOutput(ntree); ntree_update_reroute_nodes(ntree); + + if (ntree->update & NTREE_UPDATE_NODES) { + /* clean up preview cache, in case nodes have been removed */ + BKE_node_preview_remove_unused(ntree); + } } -bNodeTreeType ntreeType_Shader = { - /* type */ NTREE_SHADER, - /* id_name */ "NTShader Nodetree", +bNodeTreeType *ntreeType_Shader; + +void register_node_tree_type_sh(void) +{ + bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type"); + + tt->type = NTREE_SHADER; + strcpy(tt->idname, "ShaderNodeTree"); + strcpy(tt->ui_name, "Shader"); + tt->ui_icon = 0; /* defined in drawnode.c */ + strcpy(tt->ui_description, ""); - /* node_types */ { NULL, NULL }, + tt->foreach_nodeclass = foreach_nodeclass; + tt->localize = localize; + tt->local_sync = local_sync; + tt->update = update; + tt->poll = shader_tree_poll; + tt->get_from_context = shader_get_from_context; - /* free_cache */ NULL, - /* free_node_cache */ NULL, - /* foreach_nodetree */ foreach_nodetree, - /* foreach_nodeclass */ foreach_nodeclass, - /* localize */ localize, - /* local_sync */ local_sync, - /* local_merge */ NULL, - /* update */ update, - /* update_node */ NULL, - /* validate_link */ NULL, - /* update_internal_links */ node_update_internal_links_default -}; + tt->ext.srna = &RNA_ShaderNodeTree; + + ntreeTypeAdd(tt); +} /* GPU material from shader nodes */ @@ -163,11 +184,11 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) { bNodeTreeExec *exec; - exec = ntreeShaderBeginExecTree(ntree, 1); + exec = ntreeShaderBeginExecTree(ntree); ntreeExecGPUNodes(exec, mat, 1); - ntreeShaderEndExecTree(exec, 1); + ntreeShaderEndExecTree(exec); } /* **************** call to switch lamploop for material node ************ */ @@ -180,27 +201,16 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult } -/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes. - * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. - */ -bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data) +bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) { bNodeTreeExec *exec; bNode *node; - if (use_tree_data) { - /* XXX hack: prevent exec data from being generated twice. - * this should be handled by the renderer! - */ - if (ntree->execdata) - return ntree->execdata; - } - /* ensures only a single output node is enabled */ ntreeSetOutput(ntree); /* common base initialization */ - exec = ntree_exec_begin(ntree); + exec = ntree_exec_begin(context, ntree, parent_key); /* allocate the thread stack listbase array */ exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); @@ -208,43 +218,58 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data) for (node = exec->nodetree->nodes.first; node; node = node->next) node->need_exec = 1; - if (use_tree_data) { - /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, - * which only store the ntree pointer. Should be fixed at some point! - */ - ntree->execdata = exec; - } + return exec; +} + +bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree) +{ + bNodeExecContext context; + bNodeTreeExec *exec; + + /* XXX hack: prevent exec data from being generated twice. + * this should be handled by the renderer! + */ + if (ntree->execdata) + return ntree->execdata; + + context.previews = ntree->previews; + + exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE); + + /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, + * which only store the ntree pointer. Should be fixed at some point! + */ + ntree->execdata = exec; return exec; } -/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes. - * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. - */ -void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data) +void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec) { - if (exec) { - bNodeTree *ntree = exec->nodetree; - bNodeThreadStack *nts; - int a; - - if (exec->threadstack) { - for (a = 0; a < BLENDER_MAX_THREADS; a++) { - for (nts = exec->threadstack[a].first; nts; nts = nts->next) - if (nts->stack) MEM_freeN(nts->stack); - BLI_freelistN(&exec->threadstack[a]); - } - - MEM_freeN(exec->threadstack); - exec->threadstack = NULL; + bNodeThreadStack *nts; + int a; + + if (exec->threadstack) { + for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (nts = exec->threadstack[a].first; nts; nts = nts->next) + if (nts->stack) MEM_freeN(nts->stack); + BLI_freelistN(&exec->threadstack[a]); } - ntree_exec_end(exec); + MEM_freeN(exec->threadstack); + exec->threadstack = NULL; + } + + ntree_exec_end(exec); +} + +void ntreeShaderEndExecTree(bNodeTreeExec *exec) +{ + if (exec) { + ntreeShaderEndExecTree_internal(exec); - if (use_tree_data) { - /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ - ntree->execdata = NULL; - } + /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ + exec->nodetree->execdata = NULL; } } @@ -272,7 +297,7 @@ bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) if (!exec) { BLI_lock_thread(LOCK_NODES); if (!ntree->execdata) - ntree->execdata = ntreeShaderBeginExecTree(ntree, 1); + ntree->execdata = ntreeShaderBeginExecTree(ntree); BLI_unlock_thread(LOCK_NODES); exec = ntree->execdata; diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 1123a0dc44a..c8c4b49edb7 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -36,6 +36,20 @@ #include "node_exec.h" + +int sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return (strcmp(ntree->idname, "ShaderNodeTree")==0); +} + +void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + + ntype->poll = sh_node_poll_default; + ntype->update_internal_links = node_update_internal_links_default; +} + /* ****** */ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) @@ -84,7 +98,7 @@ void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mo bNodeSocket *sock; int a; - for (node= ntree->nodes.first; node; node= node->next) { + for (node = ntree->nodes.first; node; node = node->next) { if (node->type==SH_NODE_TEXTURE) { if ((r_mode & R_OSA) && node->id) { Tex *tex= (Tex *)node->id; @@ -123,74 +137,6 @@ void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mo } } -/* nodes that use ID data get synced with local data */ -void nodeShaderSynchronizeID(bNode *node, int copyto) -{ - if (node->id==NULL) return; - - if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) { - bNodeSocket *sock; - Material *ma= (Material *)node->id; - int a; - - /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */ - for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { - if (!nodeSocketIsHidden(sock)) { - if (copyto) { - switch (a) { - case MAT_IN_COLOR: - copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; - case MAT_IN_SPEC: - copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; - case MAT_IN_REFL: - ma->ref= ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_MIR: - copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; - case MAT_IN_AMB: - ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_EMIT: - ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_SPECTRA: - ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_RAY_MIRROR: - ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_ALPHA: - ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_TRANSLUCENCY: - ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - } - } - else { - switch (a) { - case MAT_IN_COLOR: - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break; - case MAT_IN_SPEC: - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break; - case MAT_IN_REFL: - ((bNodeSocketValueFloat *)sock->default_value)->value= ma->ref; break; - case MAT_IN_MIR: - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break; - case MAT_IN_AMB: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break; - case MAT_IN_EMIT: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break; - case MAT_IN_SPECTRA: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break; - case MAT_IN_RAY_MIRROR: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break; - case MAT_IN_ALPHA: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break; - case MAT_IN_TRANSLUCENCY: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break; - } - } - } - } - } - -} - - void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) { memset(gs, 0, sizeof(*gs)); @@ -231,7 +177,7 @@ static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeS bNodeSocket *sock; int i; - for (sock=sockets->first, i=0; sock; sock=sock->next, i++) + for (sock=sockets->first, i=0; sock; sock = sock->next, i++) node_gpu_stack_from_data(&gs[i], sock->type, ns[i]); gs[i].type= GPU_NONE; @@ -242,30 +188,31 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode bNodeSocket *sock; int i; - for (sock=sockets->first, i=0; sock; sock=sock->next, i++) + for (sock=sockets->first, i=0; sock; sock = sock->next, i++) node_data_from_gpu_stack(ns[i], &gs[i]); } bNode *nodeGetActiveTexture(bNodeTree *ntree) { /* this is the node we texture paint and draw in textured draw */ - bNode *node; + bNode *node, *tnode; if (!ntree) return NULL; - /* check for group edit */ - for (node= ntree->nodes.first; node; node= node->next) - if (node->flag & NODE_GROUP_EDIT) - break; - - if (node) - ntree = (bNodeTree *)node->id; - - for (node= ntree->nodes.first; node; node= node->next) + for (node = ntree->nodes.first; node; node = node->next) if (node->flag & NODE_ACTIVE_TEXTURE) return node; + /* node active texture node in this tree, look inside groups */ + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type==NODE_GROUP) { + tnode = nodeGetActiveTexture((bNodeTree*)node->id); + if (tnode) + return tnode; + } + } + return NULL; } @@ -299,14 +246,7 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs) node_get_stack(node, stack, nsin, nsout); gpu_stack_from_data_list(gpuin, &node->inputs, nsin); gpu_stack_from_data_list(gpuout, &node->outputs, nsout); - if (node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) - data_from_gpu_stack_list(&node->outputs, nsout, gpuout); - } - else if (node->typeinfo->gpuextfunc) { - node_get_stack(node, stack, nsin, nsout); - gpu_stack_from_data_list(gpuin, &node->inputs, nsin); - gpu_stack_from_data_list(gpuout, &node->outputs, nsout); - if (node->typeinfo->gpuextfunc(mat, node, nodeexec->data, gpuin, gpuout)) + if (node->typeinfo->gpufunc(mat, node, &nodeexec->data, gpuin, gpuout)) data_from_gpu_stack_list(&node->outputs, nsout, gpuout); } } diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index 9c911501435..57b129335bb 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -79,6 +79,11 @@ #include "GPU_material.h" + +int sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); +void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag); + + /* ********* exec data struct, remains internal *********** */ typedef struct ShaderCallData { @@ -86,40 +91,6 @@ typedef struct ShaderCallData { ShadeResult *shr; /* from render pipe */ } ShaderCallData; -/* output socket defines */ -#define GEOM_OUT_GLOB 0 -#define GEOM_OUT_LOCAL 1 -#define GEOM_OUT_VIEW 2 -#define GEOM_OUT_ORCO 3 -#define GEOM_OUT_UV 4 -#define GEOM_OUT_NORMAL 5 -#define GEOM_OUT_VCOL 6 -#define GEOM_OUT_VCOL_ALPHA 7 -#define GEOM_OUT_FRONTBACK 8 - - -/* input socket defines */ -#define MAT_IN_COLOR 0 -#define MAT_IN_SPEC 1 -#define MAT_IN_REFL 2 -#define MAT_IN_NORMAL 3 -#define MAT_IN_MIR 4 -#define MAT_IN_AMB 5 -#define MAT_IN_EMIT 6 -#define MAT_IN_SPECTRA 7 -#define MAT_IN_RAY_MIRROR 8 -#define MAT_IN_ALPHA 9 -#define MAT_IN_TRANSLUCENCY 10 -#define NUM_MAT_IN 11 /* for array size */ - -/* output socket defines */ -#define MAT_OUT_COLOR 0 -#define MAT_OUT_ALPHA 1 -#define MAT_OUT_NORMAL 2 -#define MAT_OUT_DIFFUSE 3 -#define MAT_OUT_SPEC 4 -#define MAT_OUT_AO 5 - extern void node_ID_title_cb(void *node_v, void *unused_v); void nodestack_get_vec(float *in, short type_in, bNodeStack *ns); diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.c b/source/blender/nodes/shader/nodes/node_shader_add_shader.c index ec868b2cc38..92b8d2d8111 100644 --- a/source/blender/nodes/shader/nodes/node_shader_add_shader.c +++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.c @@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_add_shader_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_add_shader", in, out); } /* node type definition */ -void register_node_type_sh_add_shader(bNodeTreeType *ttype) +void register_node_type_sh_add_shader(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_add_shader_in, sh_node_add_shader_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_add_shader); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c index 7dfefc9ece0..e3beb9e03b6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c @@ -39,25 +39,24 @@ static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL)); } /* node type definition */ -void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype) +void register_node_type_sh_ambient_occlusion(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c index 9b2ed2f14f0..e3887a1d14d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_attribute.c +++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c @@ -36,25 +36,23 @@ static bNodeSocketTemplate sh_node_attribute_out[] = { { -1, 0, "" } }; -static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node) { NodeShaderAttribute *attr = MEM_callocN(sizeof(NodeShaderAttribute), "NodeShaderAttribute"); node->storage = attr; } /* node type definition */ -void register_node_type_sh_attribute(bNodeTreeType *ttype) +void register_node_type_sh_attribute(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_attribute_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_attribute); node_type_storage(&ntype, "NodeShaderAttribute", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c index d82c513540c..18be896e9aa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_background.c +++ b/source/blender/nodes/shader/nodes/node_shader_background.c @@ -41,18 +41,16 @@ static bNodeSocketTemplate sh_node_background_out[] = { }; /* node type definition */ -void register_node_type_sh_background(bNodeTreeType *ttype) +void register_node_type_sh_background(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c index fa77fce4c88..94f7b8ff86f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_brightness.c +++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c @@ -43,23 +43,22 @@ static bNodeSocketTemplate sh_node_brightcontrast_out[] = { { -1, 0, "" } }; -static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "brightness_contrast", in, out); } -void register_node_type_sh_brightcontrast(bNodeTreeType *ttype) +void register_node_type_sh_brightcontrast(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out); node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, gpu_shader_brightcontrast); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c index 71780e9316e..75923133133 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[3].link) in[3].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -53,18 +53,17 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node } /* node type definition */ -void register_node_type_sh_bsdf_anisotropic(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_anisotropic(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_anisotropic_in, sh_node_bsdf_anisotropic_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_anisotropic); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c index ad9f197afb8..bc764e26666 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[2].link) in[2].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), G } /* node type definition */ -void register_node_type_sh_bsdf_diffuse(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_diffuse(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_diffuse_in, sh_node_bsdf_diffuse_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_diffuse); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c index 9e188092570..fe56a54011d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_bsdf_glass_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[3].link) in[3].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -51,18 +51,17 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPU } /* node type definition */ -void register_node_type_sh_bsdf_glass(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_glass(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_glass_in, sh_node_bsdf_glass_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_glass); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c index 5e32930b707..81f15f3c5a8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[2].link) in[2].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GP } /* node type definition */ -void register_node_type_sh_bsdf_glossy(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_glossy(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_glossy_in, sh_node_bsdf_glossy_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_glossy); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c index 99e66e39002..a14c1050812 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[3].link) in[3].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -51,18 +51,17 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node) } /* node type definition */ -void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_refraction(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c index 3c7084886b7..1ef807fd5ac 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c @@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[1].link) in[1].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -49,18 +49,17 @@ static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node } /* node type definition */ -void register_node_type_sh_bsdf_translucent(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_translucent(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_translucent_in, sh_node_bsdf_translucent_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_translucent); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c index 7fb452ad78d..bdd9de6a3c4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c @@ -39,24 +39,23 @@ static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_bsdf_transparent", in, out); } /* node type definition */ -void register_node_type_sh_bsdf_transparent(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_transparent(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_transparent_in, sh_node_bsdf_transparent_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_transparent); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c index a4d25d42d4e..eeb1365bc43 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[2].link) in[2].link = GPU_builtin(GPU_VIEW_NORMAL); @@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GP } /* node type definition */ -void register_node_type_sh_bsdf_velvet(bNodeTreeType *ttype) +void register_node_type_sh_bsdf_velvet(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_velvet_in, sh_node_bsdf_velvet_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_bsdf_velvet); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c index b0605f9b248..ef57604e07a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.c +++ b/source/blender/nodes/shader/nodes/node_shader_bump.c @@ -46,23 +46,22 @@ static bNodeSocketTemplate sh_node_bump_out[] = { { -1, 0, "" } }; -static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_NORMAL)); } /* node type definition */ -void register_node_type_sh_bump(bNodeTreeType *ttype) +void register_node_type_sh_bump(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bump_in, sh_node_bump_out); node_type_size(&ntype, 150, 60, 200); node_type_storage(&ntype, "BumpNode", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, gpu_shader_bump); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c index fd36a94516e..aee89a02ee1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_camera.c +++ b/source/blender/nodes/shader/nodes/node_shader_camera.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_camera_out[] = { }; -static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **out) +static void node_shader_exec_camera(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out) { if (data) { ShadeInput *shi= ((ShaderCallData *)data)->shi; /* Data we need for shading. */ @@ -52,22 +52,22 @@ static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack } } -static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION)); } -void register_node_type_sh_camera(bNodeTreeType *ttype) +void register_node_type_sh_camera(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_camera_out); node_type_size(&ntype, 95, 95, 120); node_type_storage(&ntype, "node_camera", NULL, NULL); - node_type_exec(&ntype, node_shader_exec_camera); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_camera); node_type_gpu(&ntype, gpu_shader_camera); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c index 9c784709de3..155aa508ed9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_common.c +++ b/source/blender/nodes/shader/nodes/node_shader_common.c @@ -38,9 +38,12 @@ #include "BKE_node.h" #include "node_shader_util.h" +#include "NOD_common.h" #include "node_common.h" #include "node_exec.h" +#include "RNA_access.h" + static void copy_stack(bNodeStack *to, bNodeStack *from) { if (to != from) { @@ -61,16 +64,14 @@ static void move_stack(bNodeStack *to, bNodeStack *from) to->datatype = from->datatype; to->is_copy = from->is_copy; - zero_v4(from->vec); from->data = NULL; - from->datatype = 0; from->is_copy = 0; } } /**** GROUP ****/ -static void *group_initexec(bNode *node) +static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key) { bNodeTree *ngroup = (bNodeTree *)node->id; bNodeTreeExec *exec; @@ -79,7 +80,7 @@ static void *group_initexec(bNode *node) return NULL; /* initialize the internal node tree execution */ - exec = ntreeShaderBeginExecTree(ngroup, 0); + exec = ntreeShaderBeginExecTree_internal(context, ngroup, key); return exec; } @@ -88,42 +89,55 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata) { bNodeTreeExec*gexec = (bNodeTreeExec *)nodedata; - ntreeShaderEndExecTree(gexec, 0); + ntreeShaderEndExecTree_internal(gexec); } /* Copy inputs to the internal stack. */ -static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack) +static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack) { + bNodeTree *ngroup = (bNodeTree*)gnode->id; + bNode *node; bNodeSocket *sock; bNodeStack *ns; int a; - for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - copy_stack(ns, in[a]); + + for (node = ngroup->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP_INPUT) { + for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) { + ns = node_get_socket_stack(gstack, sock); + if (ns) + copy_stack(ns, in[a]); + } } } } /* Copy internal results to the external outputs. */ -static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack) +static void group_move_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack) { + bNodeTree *ngroup = (bNodeTree*)gnode->id; + bNode *node; bNodeSocket *sock; bNodeStack *ns; int a; - for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - move_stack(out[a], ns); + + for (node = ngroup->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) { + for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) { + ns = node_get_socket_stack(gstack, sock); + if (ns) + move_stack(out[a], ns); + } + break; /* only one active output node */ } } } -static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) +static void group_execute(void *data, int thread, struct bNode *node, bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out) { - bNodeTreeExec *exec = (bNodeTreeExec *)nodedata; + bNodeTreeExec *exec = execdata->data; bNodeThreadStack *nts; if (!exec) @@ -147,62 +161,88 @@ static void group_execute(void *data, int thread, struct bNode *node, void *node ntreeReleaseThreadStack(nts); } -static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack) +static void group_gpu_copy_inputs(bNode *gnode, GPUNodeStack *in, bNodeStack *gstack) { + bNodeTree *ngroup = (bNodeTree*)gnode->id; + bNode *node; bNodeSocket *sock; bNodeStack *ns; int a; - for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - /* convert the external gpu stack back to internal node stack data */ - node_data_from_gpu_stack(ns, &in[a]); + + for (node = ngroup->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP_INPUT) { + for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) { + ns = node_get_socket_stack(gstack, sock); + if (ns) { + /* convert the external gpu stack back to internal node stack data */ + node_data_from_gpu_stack(ns, &in[a]); + } + } } } } /* Copy internal results to the external outputs. */ -static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack) +static void group_gpu_move_outputs(bNode *gnode, GPUNodeStack *out, bNodeStack *gstack) { + bNodeTree *ngroup = (bNodeTree*)gnode->id; + bNode *node; bNodeSocket *sock; bNodeStack *ns; int a; - for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - /* convert the node stack data result back to gpu stack */ - node_gpu_stack_from_data(&out[a], sock->type, ns); + + for (node = ngroup->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) { + for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) { + ns = node_get_socket_stack(gstack, sock); + if (ns) { + /* convert the node stack data result back to gpu stack */ + node_gpu_stack_from_data(&out[a], sock->type, ns); + } + } + break; /* only one active output node */ } } } -static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_group_execute(GPUMaterial *mat, bNode *node, bNodeExecData *execdata, GPUNodeStack *in, GPUNodeStack *out) { - bNodeTreeExec *exec = (bNodeTreeExec *)nodedata; + bNodeTreeExec *exec = execdata->data; group_gpu_copy_inputs(node, in, exec->stack); + #if 0 /* XXX NODE_GROUP_EDIT is deprecated, depends on node space */ ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT)); + #else + ntreeExecGPUNodes(exec, mat, 0); + #endif group_gpu_move_outputs(node, out, exec->stack); return 1; } -void register_node_type_sh_group(bNodeTreeType *ttype) +void register_node_type_sh_group(void) { static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT); + + /* NB: cannot use sh_node_type_base for node group, because it would map the node type + * to the shared NODE_GROUP integer type id. + */ + node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); + ntype.type = NODE_GROUP; + ntype.poll = sh_node_poll_default; + ntype.update_internal_links = node_update_internal_links_default; + ntype.ext.srna = RNA_struct_find("ShaderNodeGroup"); + BLI_assert(ntype.ext.srna != NULL); + RNA_struct_blender_type_set(ntype.ext.srna, &ntype); + node_type_socket_templates(&ntype, NULL, NULL); node_type_size(&ntype, 120, 60, 200); node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_group_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_group_template); node_type_update(&ntype, NULL, node_group_verify); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute); - node_type_gpu_ext(&ntype, gpu_group_execute); + strcpy(ntype.group_tree_idname, "ShaderNodeTree"); + node_type_exec(&ntype, group_initexec, group_freeexec, group_execute); + node_type_gpu(&ntype, gpu_group_execute); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index 216e10a7e9a..b293b02cfe6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_curve_vec_out[] = { { -1, 0, "" } }; -static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_curve_vec(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { float vec[3]; @@ -55,12 +55,12 @@ static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeSta curvemapping_evaluate3F(node->storage, out[0]->vec, vec); } -static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); } -static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { float *array; int size; @@ -69,21 +69,20 @@ static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array)); } -void register_node_type_sh_curve_vec(bNodeTreeType *ttype) +void register_node_type_sh_curve_vec(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_curve_vec_in, sh_node_curve_vec_out); node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, node_shader_init_curve_vec); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - node_type_exec(&ntype, node_shader_exec_curve_vec); - node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */ + node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_vec); node_type_gpu(&ntype, gpu_shader_curve_vec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -99,7 +98,7 @@ static bNodeSocketTemplate sh_node_curve_rgb_out[] = { { -1, 0, "" } }; -static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_curve_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { float vec[3]; @@ -112,12 +111,12 @@ static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeSta } } -static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } -static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { float *array; int size; @@ -127,19 +126,18 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array)); } -void register_node_type_sh_curve_rgb(bNodeTreeType *ttype) +void register_node_type_sh_curve_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_curve_rgb_in, sh_node_curve_rgb_out); node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, node_shader_init_curve_rgb); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - node_type_exec(&ntype, node_shader_exec_curve_rgb); - node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */ + node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_rgb); node_type_gpu(&ntype, gpu_shader_curve_rgb); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.c index 0c4cb7ed51c..e11f199bbd0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_emission.c +++ b/source/blender/nodes/shader/nodes/node_shader_emission.c @@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_emission_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL)); } /* node type definition */ -void register_node_type_sh_emission(bNodeTreeType *ttype) +void register_node_type_sh_emission(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_emission_in, sh_node_emission_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_emission); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c index 80913e6b07a..d627edebfa7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c @@ -38,25 +38,24 @@ static bNodeSocketTemplate sh_node_fresnel_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { /* todo: is incoming vector normalized? */ return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_VIEW_POSITION)); } /* node type definition */ -void register_node_type_sh_fresnel(bNodeTreeType *ttype) +void register_node_type_sh_fresnel(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_fresnel_in, sh_node_fresnel_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_fresnel); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c index 365bac77004..c5dafbe55d1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.c +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c @@ -41,18 +41,16 @@ static bNodeSocketTemplate sh_node_gamma_out[] = { { -1, 0, "" } }; -void register_node_type_sh_gamma(bNodeTreeType *ttype) +void register_node_type_sh_gamma(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out); node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c index eb3d462d616..40ba2cca4e5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geom.c +++ b/source/blender/nodes/shader/nodes/node_shader_geom.c @@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_geom_out[] = { }; /* node execute callback */ -static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) +static void node_shader_exec_geom(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out) { if (data) { ShadeInput *shi= ((ShaderCallData *)data)->shi; @@ -120,12 +120,12 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(i } } -static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); } -static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_geom(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { NodeGeometry *ngeo= (NodeGeometry*)node->storage; GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); @@ -138,18 +138,18 @@ static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN } /* node type definition */ -void register_node_type_sh_geom(bNodeTreeType *ttype) +void register_node_type_sh_geom(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_geom_out); node_type_size(&ntype, 120, 80, 160); node_type_init(&ntype, node_shader_init_geometry); node_type_storage(&ntype, "NodeGeometry", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, node_shader_exec_geom); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_geom); node_type_gpu(&ntype, gpu_shader_geom); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c index acef885d2d4..c9626576833 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.c +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c @@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_geometry_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_geometry", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), @@ -48,18 +48,17 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), GPUNo } /* node type definition */ -void register_node_type_sh_geometry(bNodeTreeType *ttype) +void register_node_type_sh_geometry(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_geometry_out); node_type_size(&ntype, 120, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_geometry); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c index 5cd4c8bd1d3..86c31086190 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c @@ -36,18 +36,16 @@ static bNodeSocketTemplate outputs[] = { }; /* node type definition */ -void register_node_type_sh_hair_info(bNodeTreeType *ttype) +void register_node_type_sh_hair_info(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, outputs); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.c b/source/blender/nodes/shader/nodes/node_shader_holdout.c index 18ad4994c9b..9024cb507ed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_holdout.c +++ b/source/blender/nodes/shader/nodes/node_shader_holdout.c @@ -40,18 +40,16 @@ static bNodeSocketTemplate sh_node_holdout_out[] = { /* node type definition */ -void register_node_type_sh_holdout(bNodeTreeType *ttype) +void register_node_type_sh_holdout(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_holdout_in, sh_node_holdout_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c index b635ad1edd9..559d9289fb7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -69,27 +69,27 @@ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *s } } -static void node_shader_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_hue_sat(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec); } -static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "hue_sat", in, out); } -void register_node_type_sh_hue_sat(bNodeTreeType *ttype) +void register_node_type_sh_hue_sat(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out); node_type_size(&ntype, 150, 80, 250); - node_type_exec(&ntype, node_shader_exec_hue_sat); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat); node_type_gpu(&ntype, gpu_shader_hue_sat); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c index 2ea858f4e34..193ea93f54a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_invert.c +++ b/source/blender/nodes/shader/nodes/node_shader_invert.c @@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_invert_out[] = { { -1, 0, "" } }; -static void node_shader_exec_invert(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, +static void node_shader_exec_invert(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { float col[3], facm; @@ -67,21 +67,21 @@ bNodeStack **out) copy_v3_v3(out[0]->vec, col); } -static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "invert", in, out); } -void register_node_type_sh_invert(bNodeTreeType *ttype) +void register_node_type_sh_invert(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out); node_type_size(&ntype, 90, 80, 100); - node_type_exec(&ntype, node_shader_exec_invert); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert); node_type_gpu(&ntype, gpu_shader_invert); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c index 3058483ebef..f342cb07e30 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c @@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_layer_weight_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) +static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) { return 0; } /* node type definition */ -void register_node_type_sh_layer_weight(bNodeTreeType *ttype) +void register_node_type_sh_layer_weight(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_layer_weight_in, sh_node_layer_weight_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_layer_weight); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c index 2dec244ae3a..e30c59f6920 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c +++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c @@ -44,25 +44,24 @@ static bNodeSocketTemplate sh_node_light_falloff_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_light_falloff", in, out); } /* node type definition */ -void register_node_type_sh_light_falloff(bNodeTreeType *ttype) +void register_node_type_sh_light_falloff(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0); + sh_node_type_base(&ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_light_falloff_in, sh_node_light_falloff_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_light_falloff); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c index b4a3d4e01e1..0b1f34f6a02 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_path.c +++ b/source/blender/nodes/shader/nodes/node_shader_light_path.c @@ -41,24 +41,23 @@ static bNodeSocketTemplate sh_node_light_path_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_light_path", in, out); } /* node type definition */ -void register_node_type_sh_light_path(bNodeTreeType *ttype) +void register_node_type_sh_light_path(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_light_path_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_light_path); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index 396c1ac60bf..910bf06c068 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_mapping_out[] = { }; /* do the regular mapping options for blender textures */ -static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { TexMapping *texmap= node->storage; float *vec= out[0]->vec; @@ -67,12 +67,12 @@ static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack } -static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= add_tex_mapping(); } -static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { TexMapping *texmap= node->storage; float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; @@ -86,18 +86,18 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax); } -void register_node_type_sh_mapping(bNodeTreeType *ttype) +void register_node_type_sh_mapping(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out); node_type_size(&ntype, 240, 160, 320); node_type_init(&ntype, node_shader_init_mapping); node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, node_shader_exec_mapping); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_mapping); node_type_gpu(&ntype, gpu_shader_mapping); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c index a36f35c646d..aee280760ba 100644 --- a/source/blender/nodes/shader/nodes/node_shader_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_material.c @@ -29,7 +29,6 @@ * \ingroup shdnodes */ - #include "node_shader_util.h" /* **************** MATERIAL ******************** */ @@ -76,7 +75,7 @@ static bNodeSocketTemplate sh_node_material_ext_out[] = { { -1, 0, "" } }; -static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_material(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { if (data && node->id) { ShadeResult shrnode; @@ -92,7 +91,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, * we just want to know if a node input uses external data or the material setting. * this is an ugly hack, but so is this node as a whole. */ - for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) + for (sock = node->inputs.first, i=0; sock; sock = sock->next, ++i) hasinput[i] = (sock->link != NULL); shi= shcd->shi; @@ -170,7 +169,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, col[3] = shrnode.alpha; if (shi->do_preview) - nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage); + BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage); copy_v3_v3(out[MAT_OUT_COLOR]->vec, col); out[MAT_OUT_ALPHA]->vec[0] = shrnode.alpha; @@ -208,7 +207,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, } -static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; } @@ -224,7 +223,7 @@ static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) return GPU_uniform(in->vec); } -static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (node->id) { GPUShadeInput shi; @@ -237,7 +236,7 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, * the constant input stack values (e.g. in case material node is inside a group). * we just want to know if a node input uses external data or the material setting. */ - for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) + for (sock = node->inputs.first, i=0; sock; sock = sock->next, ++i) hasinput[i] = (sock->link != NULL); GPU_shadeinput_set(mat, (Material*)node->id, &shi); @@ -308,33 +307,33 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, return 0; } -void register_node_type_sh_material(bNodeTreeType *ttype) +void register_node_type_sh_material(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + sh_node_type_base(&ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_compatibility(&ntype, NODE_OLD_SHADING); node_type_socket_templates(&ntype, sh_node_material_in, sh_node_material_out); node_type_size(&ntype, 120, 80, 240); node_type_init(&ntype, node_shader_init_material); - node_type_exec(&ntype, node_shader_exec_material); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_material); node_type_gpu(&ntype, gpu_shader_material); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } -void register_node_type_sh_material_ext(bNodeTreeType *ttype) +void register_node_type_sh_material_ext(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + sh_node_type_base(&ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_compatibility(&ntype, NODE_OLD_SHADING); node_type_socket_templates(&ntype, sh_node_material_ext_in, sh_node_material_ext_out); node_type_size(&ntype, 120, 80, 240); node_type_init(&ntype, node_shader_init_material); - node_type_exec(&ntype, node_shader_exec_material); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_material); node_type_gpu(&ntype, gpu_shader_material); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 0b71a3f13b4..31a1501bc3f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -45,8 +45,7 @@ static bNodeSocketTemplate sh_node_math_out[] = { { -1, 0, "" } }; -static void node_shader_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, -bNodeStack **out) +static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { switch (node->custom1) { @@ -207,7 +206,7 @@ bNodeStack **out) } } -static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { static const char *names[] = {"math_add", "math_subtract", "math_multiply", "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin", @@ -256,18 +255,18 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN return 1; } -void register_node_type_sh_math(bNodeTreeType *ttype) +void register_node_type_sh_math(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); node_type_size(&ntype, 120, 110, 160); node_type_label(&ntype, node_math_label); node_type_storage(&ntype, "node_math", NULL, NULL); - node_type_exec(&ntype, node_shader_exec_math); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_math); node_type_gpu(&ntype, gpu_shader_math); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c index 18dcc8f7fef..982eaa228d1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_mix_rgb_out[] = { { -1, 0, "" } }; -static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_mix_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { /* stack order in: fac, col1, col2 */ /* stack order out: col */ @@ -62,7 +62,7 @@ static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack copy_v3_v3(out[0]->vec, col); } -static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", @@ -73,17 +73,17 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G } -void register_node_type_sh_mix_rgb(bNodeTreeType *ttype) +void register_node_type_sh_mix_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out); node_type_size(&ntype, 100, 60, 150); node_type_label(&ntype, node_blend_label); - node_type_exec(&ntype, node_shader_exec_mix_rgb); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_mix_rgb); node_type_gpu(&ntype, gpu_shader_mix_rgb); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c index 039e63a4dea..077fd71d191 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c +++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c @@ -41,24 +41,23 @@ static bNodeSocketTemplate sh_node_mix_shader_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_mix_shader", in, out); } /* node type definition */ -void register_node_type_sh_mix_shader(bNodeTreeType *ttype) +void register_node_type_sh_mix_shader(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_mix_shader_in, sh_node_mix_shader_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_mix_shader); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c index 0ad58d6af76..ba32a7e0924 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal.c @@ -39,26 +39,14 @@ static bNodeSocketTemplate sh_node_normal_in[] = { }; static bNodeSocketTemplate sh_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; -static void node_shader_init_normal(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) -{ - bNodeSocket *sock= node->outputs.first; - bNodeSocketValueVector *dval= (bNodeSocketValueVector*)sock->default_value; - - /* output value is used for normal vector */ - dval->value[0] = 0.0f; - dval->value[1] = 0.0f; - dval->value[2] = 1.0f; -} - /* generates normal, does dot product */ -static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_normal(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { - bNodeSocket *sock= node->outputs.first; float vec[3]; /* stack order input: normal */ @@ -66,29 +54,25 @@ static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack nodestack_get_vec(vec, SOCK_VECTOR, in[0]); - copy_v3_v3(out[0]->vec, ((bNodeSocketValueVector*)sock->default_value)->value); /* render normals point inside... the widget points outside */ - out[1]->vec[0] = -dot_v3v3(out[0]->vec, vec); + out[1]->vec[0] = -dot_v3v3(vec, out[0]->vec); } -static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_normal(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - bNodeSocket *sock= node->outputs.first; - GPUNodeLink *vec = GPU_uniform(((bNodeSocketValueVector*)sock->default_value)->value); - + GPUNodeLink *vec = GPU_uniform(out[0].vec); return GPU_stack_link(mat, "normal", in, out, vec); } -void register_node_type_sh_normal(bNodeTreeType *ttype) +void register_node_type_sh_normal(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_normal_in, sh_node_normal_out); - node_type_init(&ntype, node_shader_init_normal); - node_type_exec(&ntype, node_shader_exec_normal); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_normal); node_type_gpu(&ntype, gpu_shader_normal); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index 6a4eb9d81df..d971df215e9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -40,31 +40,30 @@ static bNodeSocketTemplate sh_node_normal_map_out[] = { { -1, 0, "" } }; -static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node) { NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap"); node->storage = attr; } -static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL)); } /* node type definition */ -void register_node_type_sh_normal_map(bNodeTreeType *ttype) +void register_node_type_sh_normal_map(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out); node_type_size(&ntype, 250, 60, 250); node_type_init(&ntype, node_shader_init_normal_map); node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, gpu_shader_normal_map); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index ef283004d46..d00037546ea 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -37,25 +37,24 @@ static bNodeSocketTemplate sh_node_object_info_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "node_object_info", in, out); } /* node type definition */ -void register_node_type_sh_object_info(bNodeTreeType *ttype) +void register_node_type_sh_object_info(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_object_info_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_object_info); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c index 6f7f900aecd..c317fe0f58a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output.c +++ b/source/blender/nodes/shader/nodes/node_shader_output.c @@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_output_in[] = { { -1, 0, "" } }; -static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) +static void node_shader_exec_output(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out)) { if (data) { ShadeInput *shi= ((ShaderCallData *)data)->shi; @@ -50,7 +50,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN nodestack_get_vec(col+3, SOCK_FLOAT, in[1]); if (shi->do_preview) { - nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage); + BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage); node->lasty= shi->ys; } @@ -65,7 +65,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN } } -static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { GPUNodeLink *outlink; @@ -80,19 +80,19 @@ static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack return 1; } -void register_node_type_sh_output(bNodeTreeType *ttype) +void register_node_type_sh_output(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW); + sh_node_type_base(&ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW); node_type_compatibility(&ntype, NODE_OLD_SHADING); node_type_socket_templates(&ntype, sh_node_output_in, NULL); node_type_size(&ntype, 80, 60, 200); - node_type_exec(&ntype, node_shader_exec_output); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_output); node_type_gpu(&ntype, gpu_shader_output); /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c index ce406a8f5a1..5bb45fe63f6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c @@ -35,21 +35,19 @@ static bNodeSocketTemplate sh_node_output_lamp_in[] = { }; /* node type definition */ -void register_node_type_sh_output_lamp(bNodeTreeType *ttype) +void register_node_type_sh_output_lamp(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_OUTPUT_LAMP, "Lamp Output", NODE_CLASS_OUTPUT, 0); + sh_node_type_base(&ntype, SH_NODE_OUTPUT_LAMP, "Lamp Output", NODE_CLASS_OUTPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_output_lamp_in, NULL); node_type_size(&ntype, 120, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c index f185e13010b..ddaee944f93 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c @@ -36,7 +36,7 @@ static bNodeSocketTemplate sh_node_output_material_in[] = { { -1, 0, "" } }; -static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { GPUNodeLink *outlink; @@ -48,21 +48,20 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node) /* node type definition */ -void register_node_type_sh_output_material(bNodeTreeType *ttype) +void register_node_type_sh_output_material(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0); + sh_node_type_base(&ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_output_material_in, NULL); node_type_size(&ntype, 120, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_output_material); /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c index 953197ab2cd..99663489635 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_world.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c @@ -36,21 +36,19 @@ static bNodeSocketTemplate sh_node_output_world_in[] = { }; /* node type definition */ -void register_node_type_sh_output_world(bNodeTreeType *ttype) +void register_node_type_sh_output_world(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0); + sh_node_type_base(&ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_output_world_in, NULL); node_type_size(&ntype, 120, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c index c7e31d117cc..e4d91d524d2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c @@ -42,15 +42,15 @@ static bNodeSocketTemplate outputs[] = { }; /* node type definition */ -void register_node_type_sh_particle_info(bNodeTreeType *ttype) +void register_node_type_sh_particle_info(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0); + sh_node_type_base(&ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, outputs); node_type_size(&ntype, 150, 60, 200); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.c index f37ff1d511b..f0c90b65823 100644 --- a/source/blender/nodes/shader/nodes/node_shader_rgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_rgb.c @@ -34,49 +34,25 @@ /* **************** RGB ******************** */ static bNodeSocketTemplate sh_node_rgb_out[] = { - { SOCK_RGBA, 0, N_("Color")}, + { SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f}, { -1, 0, "" } }; -static void node_shader_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static int gpu_shader_rgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - bNodeSocket *sock= node->outputs.first; - bNodeSocketValueRGBA *dval= (bNodeSocketValueRGBA*)sock->default_value; - /* uses the default value of the output socket, must be initialized here */ - dval->value[0] = 0.5f; - dval->value[1] = 0.5f; - dval->value[2] = 0.5f; - dval->value[3] = 1.0f; -} - -static void node_shader_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - bNodeSocket *sock= node->outputs.first; - float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; - - copy_v3_v3(out[0]->vec, col); -} - -static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - bNodeSocket *sock= node->outputs.first; - float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; - GPUNodeLink *vec = GPU_uniform(col); - + GPUNodeLink *vec = GPU_uniform(out[0].vec); return GPU_stack_link(mat, "set_rgba", in, out, vec); } -void register_node_type_sh_rgb(bNodeTreeType *ttype) +void register_node_type_sh_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_rgb_out); - node_type_init(&ntype, node_shader_init_rgb); node_type_size(&ntype, 140, 80, 140); - node_type_exec(&ntype, node_shader_exec_rgb); node_type_gpu(&ntype, gpu_shader_rgb); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c index b5563658a64..6666197770f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_script.c +++ b/source/blender/nodes/shader/nodes/node_shader_script.c @@ -35,7 +35,7 @@ /* **************** Script ******************** */ -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { NodeShaderScript *nss = MEM_callocN(sizeof(NodeShaderScript), "shader script node"); node->storage = nss; @@ -50,37 +50,29 @@ static void node_free_script(bNode *node) MEM_freeN(nss->bytecode); } - if (nss->prop) { - IDP_FreeProperty(nss->prop); - MEM_freeN(nss->prop); - } - MEM_freeN(nss); } } -static void node_copy_script(bNode *orig_node, bNode *new_node) +static void node_copy_script(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - NodeShaderScript *orig_nss = orig_node->storage; - NodeShaderScript *new_nss = MEM_dupallocN(orig_nss); - - if (orig_nss->bytecode) - new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode); + NodeShaderScript *src_nss = src_node->storage; + NodeShaderScript *dest_nss = MEM_dupallocN(src_nss); - if (orig_nss->prop) - new_nss->prop = IDP_CopyProperty(orig_nss->prop); + if (src_nss->bytecode) + dest_nss->bytecode = MEM_dupallocN(src_nss->bytecode); - new_node->storage = new_nss; + dest_node->storage = dest_nss; } -void register_node_type_sh_script(bNodeTreeType *ttype) +void register_node_type_sh_script(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_init(&ntype, init); node_type_storage(&ntype, "NodeShaderScript", node_free_script, node_copy_script); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c index 70fba161de9..c0ed9dc6a3e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c @@ -44,30 +44,30 @@ static bNodeSocketTemplate sh_node_seprgb_out[] = { { -1, 0, "" } }; -static void node_shader_exec_seprgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +static void node_shader_exec_seprgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { out[0]->vec[0] = in[0]->vec[0]; out[1]->vec[0] = in[0]->vec[1]; out[2]->vec[0] = in[0]->vec[2]; } -static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "separate_rgb", in, out); } -void register_node_type_sh_seprgb(bNodeTreeType *ttype) +void register_node_type_sh_seprgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); + sh_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out); node_type_size(&ntype, 80, 40, 140); - node_type_exec(&ntype, node_shader_exec_seprgb); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb); node_type_gpu(&ntype, gpu_shader_seprgb); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -84,28 +84,28 @@ static bNodeSocketTemplate sh_node_combrgb_out[] = { { -1, 0, "" } }; -static void node_shader_exec_combrgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +static void node_shader_exec_combrgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { out[0]->vec[0] = in[0]->vec[0]; out[0]->vec[1] = in[1]->vec[0]; out[0]->vec[2] = in[2]->vec[0]; } -static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "combine_rgb", in, out); } -void register_node_type_sh_combrgb(bNodeTreeType *ttype) +void register_node_type_sh_combrgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out); node_type_size(&ntype, 80, 40, 140); - node_type_exec(&ntype, node_shader_exec_combrgb); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb); node_type_gpu(&ntype, gpu_shader_combrgb); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c index 8073f4b01d2..ad2e7353ac8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c +++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_squeeze_out[] = { { -1, 0, "" } }; -static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +static void node_shader_exec_squeeze(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { float vec[3]; @@ -56,22 +56,22 @@ static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bN out[0]->vec[0] = 1.0f / (1.0f + powf(M_E, -((vec[0] - vec[2]) * vec[1]))); } -static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "squeeze", in, out); } -void register_node_type_sh_squeeze(bNodeTreeType *ttype) +void register_node_type_sh_squeeze(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING); node_type_socket_templates(&ntype, sh_node_squeeze_in, sh_node_squeeze_out); node_type_size(&ntype, 120, 110, 160); node_type_storage(&ntype, "node_squeeze", NULL, NULL); - node_type_exec(&ntype, node_shader_exec_squeeze); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_squeeze); node_type_gpu(&ntype, gpu_shader_squeeze); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c index 6c0d6d7cd9f..3f4c59f81ee 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.c +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -34,7 +34,7 @@ static bNodeSocketTemplate sh_node_tangent_out[] = { { -1, 0, "" } }; -static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node) { NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent"); attr->axis = SHD_TANGENT_AXIS_Z; @@ -42,19 +42,16 @@ static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNod } /* node type definition */ -void register_node_type_sh_tangent(bNodeTreeType *ttype) +void register_node_type_sh_tangent(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_tangent_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tangent); node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); - node_type_gpu(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } - diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c index 66bf0267586..dad74d324f8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c @@ -48,7 +48,7 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick"); default_tex_mapping(&tex->base.tex_mapping); @@ -62,7 +62,7 @@ static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bN node->storage = tex; } -static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -73,18 +73,17 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack } /* node type definition */ -void register_node_type_sh_tex_brick(bNodeTreeType *ttype) +void register_node_type_sh_tex_brick(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_brick_in, sh_node_tex_brick_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_brick); node_type_storage(&ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_brick); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c index 8a2ae2d40dc..dff533c4d80 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker"); default_tex_mapping(&tex->base.tex_mapping); @@ -52,7 +52,7 @@ static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node, node->storage = tex; } -static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -63,18 +63,17 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, GPUNodeSta } /* node type definition */ -void register_node_type_sh_tex_checker(bNodeTreeType *ttype) +void register_node_type_sh_tex_checker(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0); + sh_node_type_base(&ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_checker_in, sh_node_tex_checker_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_checker); node_type_storage(&ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_checker); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index dd717874951..5af5477e5c7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_coord_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ""); @@ -53,18 +53,17 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUN } /* node type definition */ -void register_node_type_sh_tex_coord(bNodeTreeType *ttype) +void register_node_type_sh_tex_coord(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_tex_coord_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_coord); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index d2d0870e2ed..05352e810c0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment"); default_tex_mapping(&tex->base.tex_mapping); @@ -56,7 +56,7 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *no node->storage = tex; } -static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Image *ima= (Image*)node->id; ImageUser *iuser= NULL; @@ -88,18 +88,17 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod } /* node type definition */ -void register_node_type_sh_tex_environment(bNodeTreeType *ttype) +void register_node_type_sh_tex_environment(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_environment_in, sh_node_tex_environment_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_environment); node_type_storage(&ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_environment); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c index 0802ecdea1d..5f559f9d0d6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c @@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient"); default_tex_mapping(&tex->base.tex_mapping); @@ -50,7 +50,7 @@ static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node, node->storage = tex; } -static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -61,18 +61,17 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, GPUNodeSt } /* node type definition */ -void register_node_type_sh_tex_gradient(bNodeTreeType *ttype) +void register_node_type_sh_tex_gradient(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_gradient_in, sh_node_tex_gradient_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_gradient); node_type_storage(&ntype, "NodeTexGradient", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_gradient); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 49b38434246..6a28414e8c4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage"); default_tex_mapping(&tex->base.tex_mapping); @@ -56,7 +56,7 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node, bN node->storage = tex; } -static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Image *ima= (Image*)node->id; ImageUser *iuser= NULL; @@ -88,18 +88,17 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack } /* node type definition */ -void register_node_type_sh_tex_image(bNodeTreeType *ttype) +void register_node_type_sh_tex_image(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_image_in, sh_node_tex_image_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_image); node_type_storage(&ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_image); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c index 86feabbcc2b..c7c29f2c17a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic"); default_tex_mapping(&tex->base.tex_mapping); @@ -52,7 +52,7 @@ static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node, bN node->storage = tex; } -static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { NodeTexMagic *tex = (NodeTexMagic*)node->storage; float depth = tex->depth; @@ -66,18 +66,17 @@ static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, GPUNodeStack } /* node type definition */ -void register_node_type_sh_tex_magic(bNodeTreeType *ttype) +void register_node_type_sh_tex_magic(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_magic_in, sh_node_tex_magic_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_magic); node_type_storage(&ntype, "NodeTexMagic", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_magic); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index cd4b5743e14..ae77c13c929 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave"); default_tex_mapping(&tex->base.tex_mapping); @@ -56,7 +56,7 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node, node->storage = tex; } -static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -67,18 +67,17 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, GPUNodeSt } /* node type definition */ -void register_node_type_sh_tex_musgrave(bNodeTreeType *ttype) +void register_node_type_sh_tex_musgrave(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_musgrave_in, sh_node_tex_musgrave_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_musgrave); node_type_storage(&ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_musgrave); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c index 18788f9e72c..3d3f4c86547 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise"); default_tex_mapping(&tex->base.tex_mapping); @@ -52,7 +52,7 @@ static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node, bN node->storage = tex; } -static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -63,18 +63,17 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, GPUNodeStack } /* node type definition */ -void register_node_type_sh_tex_noise(bNodeTreeType *ttype) +void register_node_type_sh_tex_noise(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); + sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_noise); node_type_storage(&ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_noise); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index 7a1b853a7f4..e92ff5ddade 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky"); default_tex_mapping(&tex->base.tex_mapping); @@ -52,7 +52,7 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node, bNod node->storage = tex; } -static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -63,18 +63,17 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, GPUNodeStack * } /* node type definition */ -void register_node_type_sh_tex_sky(bNodeTreeType *ttype) +void register_node_type_sh_tex_sky(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_sky_in, sh_node_tex_sky_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_sky); node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_sky); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c index d4cc24687b3..89856864036 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi"); default_tex_mapping(&tex->base.tex_mapping); @@ -51,7 +51,7 @@ static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node, node->storage = tex; } -static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -62,18 +62,17 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, GPUNodeSta } /* node type definition */ -void register_node_type_sh_tex_voronoi(bNodeTreeType *ttype) +void register_node_type_sh_tex_voronoi(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_voronoi_in, sh_node_tex_voronoi_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_voronoi); node_type_storage(&ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_voronoi); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c index 8b23de0310c..22edacd347d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = { { -1, 0, "" } }; -static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave"); default_tex_mapping(&tex->base.tex_mapping); @@ -54,7 +54,7 @@ static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node, bNo node->storage = tex; } -static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) in[0].link = GPU_attribute(CD_ORCO, ""); @@ -65,18 +65,17 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, GPUNodeStack } /* node type definition */ -void register_node_type_sh_tex_wave(bNodeTreeType *ttype) +void register_node_type_sh_tex_wave(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_wave_in, sh_node_tex_wave_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, node_shader_init_tex_wave); node_type_storage(&ntype, "NodeTexWave", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_tex_wave); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index ec238b62408..1ff315f6b80 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -48,7 +48,7 @@ static bNodeSocketTemplate sh_node_texture_out[] = { { -1, 0, "" } }; -static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_texture(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { if (data && node->id) { ShadeInput *shi= ((ShaderCallData *)data)->shi; @@ -113,13 +113,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b copy_v3_v3(out[2]->vec, nor); - if (shi->do_preview) - nodeAddToPreview(node, out[1]->vec, shi->xs, shi->ys, shi->do_manage); + if (shi->do_preview) { + BKE_node_preview_set_pixel(execdata->preview, out[1]->vec, shi->xs, shi->ys, shi->do_manage); + } } } -static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Tex *tex = (Tex*)node->id; @@ -143,16 +144,16 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G return 0; } -void register_node_type_sh_texture(bNodeTreeType *ttype) +void register_node_type_sh_texture(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); + sh_node_type_base(&ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_compatibility(&ntype, NODE_OLD_SHADING); node_type_socket_templates(&ntype, sh_node_texture_in, sh_node_texture_out); node_type_size(&ntype, 120, 80, 240); - node_type_exec(&ntype, node_shader_exec_texture); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_texture); node_type_gpu(&ntype, gpu_shader_texture); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c index 182487d343e..d5f0bf30966 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_valtorgb_out[] = { { -1, 0, "" } }; -static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_valtorgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { /* stack order in: fac */ /* stack order out: col, alpha */ @@ -57,12 +57,12 @@ static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStac } } -static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node) { - node->storage= add_colorband(1); + node->storage= add_colorband(true); } -static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { float *array; int size; @@ -71,20 +71,20 @@ static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array)); } -void register_node_type_sh_valtorgb(bNodeTreeType *ttype) +void register_node_type_sh_valtorgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out); node_type_size(&ntype, 240, 200, 300); node_type_init(&ntype, node_shader_init_valtorgb); node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, node_shader_exec_valtorgb); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_valtorgb); node_type_gpu(&ntype, gpu_shader_valtorgb); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } @@ -99,7 +99,7 @@ static bNodeSocketTemplate sh_node_rgbtobw_out[] = { }; -static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) +static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { /* stack order out: bw */ /* stack order in: col */ @@ -107,21 +107,21 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bN out[0]->vec[0] = rgb_to_bw(in[0]->vec); } -static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, "rgbtobw", in, out); } -void register_node_type_sh_rgbtobw(bNodeTreeType *ttype) +void register_node_type_sh_rgbtobw(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); + sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_rgbtobw_in, sh_node_rgbtobw_out); node_type_size(&ntype, 80, 40, 120); - node_type_exec(&ntype, node_shader_exec_rgbtobw); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_rgbtobw); node_type_gpu(&ntype, gpu_shader_rgbtobw); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.c index a3d1e5afec2..f4aef926f64 100644 --- a/source/blender/nodes/shader/nodes/node_shader_value.c +++ b/source/blender/nodes/shader/nodes/node_shader_value.c @@ -34,49 +34,25 @@ /* **************** VALUE ******************** */ static bNodeSocketTemplate sh_node_value_out[] = { - /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */ - { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + { SOCK_FLOAT, 0, N_("Value"), 0.5f, 0, 0, 0, -FLT_MAX, FLT_MAX, PROP_NONE}, { -1, 0, "" } }; -static void node_shader_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static int gpu_shader_value(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - bNodeSocket *sock= node->outputs.first; - bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value; - /* uses the default value of the output socket, must be initialized here */ - dval->value = 0.5f; - dval->min = -FLT_MAX; - dval->max = FLT_MAX; -} - -static void node_shader_exec_value(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - bNodeSocket *sock= node->outputs.first; - float val= ((bNodeSocketValueFloat*)sock->default_value)->value; - - out[0]->vec[0] = val; -} - -static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - bNodeSocket *sock= node->outputs.first; - float *val= &((bNodeSocketValueFloat*)sock->default_value)->value; - GPUNodeLink *vec = GPU_uniform(val); - + GPUNodeLink *vec = GPU_uniform(out[0].vec); return GPU_stack_link(mat, "set_value", in, out, vec); } -void register_node_type_sh_value(bNodeTreeType *ttype) +void register_node_type_sh_value(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_value_out); - node_type_init(&ntype, node_shader_init_value); node_type_size(&ntype, 80, 50, 120); - node_type_exec(&ntype, node_shader_exec_value); node_type_gpu(&ntype, gpu_shader_value); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c index 3e00421ddf0..9eb3c5a14e4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c @@ -47,7 +47,7 @@ static bNodeSocketTemplate sh_node_vect_math_out[] = { { -1, 0, "" } }; -static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_shader_exec_vect_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { float vec1[3], vec2[3]; @@ -102,7 +102,7 @@ static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeSta } -static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { static const char *names[] = {"vec_math_add", "vec_math_sub", "vec_math_average", "vec_math_dot", "vec_math_cross", @@ -139,18 +139,18 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, return 1; } -void register_node_type_sh_vect_math(bNodeTreeType *ttype) +void register_node_type_sh_vect_math(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + sh_node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out); node_type_size(&ntype, 80, 75, 140); node_type_label(&ntype, node_vect_math_label); node_type_storage(&ntype, "node_vect_math", NULL, NULL); - node_type_exec(&ntype, node_shader_exec_vect_math); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_math); node_type_gpu(&ntype, gpu_shader_vect_math); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c index 5451eb303cc..458fbf43625 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c @@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_volume_isotropic_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) +static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) { return 0; } /* node type definition */ -void register_node_type_sh_volume_isotropic(bNodeTreeType *ttype) +void register_node_type_sh_volume_isotropic(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_volume_isotropic_in, sh_node_volume_isotropic_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_volume_isotropic); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c index ad7d7fceda3..c9bac06cbb0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c @@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_volume_transparent_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) +static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) { return 0; } /* node type definition */ -void register_node_type_sh_volume_transparent(bNodeTreeType *ttype) +void register_node_type_sh_volume_transparent(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_volume_transparent_in, sh_node_volume_transparent_out); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL); node_type_gpu(&ntype, node_shader_gpu_volume_transparent); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index ba94531c259..e1a29a67446 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -34,6 +34,7 @@ #include "DNA_texture_types.h" #include "DNA_node_types.h" +#include "DNA_space_types.h" #include "BLI_listbase.h" #include "BLI_threads.h" @@ -41,9 +42,11 @@ #include "BLF_translation.h" +#include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_paint.h" #include "node_common.h" #include "node_exec.h" @@ -51,16 +54,57 @@ #include "NOD_texture.h" #include "node_texture_util.h" +#include "RNA_access.h" + #include "RE_pipeline.h" #include "RE_shader_ext.h" -static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) +static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from) { - Tex *tx; - for (tx = main->tex.first; tx; tx = tx->id.next) { - if (tx->nodetree) { - func(calldata, &tx->id, tx->nodetree); + SpaceNode *snode = CTX_wm_space_node(C); + Scene *scene = CTX_data_scene(C); + Object *ob = OBACT; + Tex *tx = NULL; + + if (snode->texfrom == SNODE_TEX_OBJECT) { + if (ob) { + tx = give_current_object_texture(ob); + if (tx) { + if (ob->type == OB_LAMP) + *r_from = (ID*)ob->data; + else + *r_from = (ID*)give_current_material(ob, ob->actcol); + + /* from is not set fully for material nodes, should be ID + Node then */ + *r_id = &tx->id; + *r_ntree = tx->nodetree; + } + } + } + else if (snode->texfrom == SNODE_TEX_WORLD) { + tx = give_current_world_texture(scene->world); + if (tx) { + *r_from = (ID *)scene->world; + *r_id = &tx->id; + *r_ntree = tx->nodetree; + } + } + else { + struct Brush *brush = NULL; + + if (ob && (ob->mode & OB_MODE_SCULPT)) + brush = paint_brush(&scene->toolsettings->sculpt->paint); + else + brush = paint_brush(&scene->toolsettings->imapaint.paint); + + if (brush) { + *r_from = (ID *)brush; + tx = give_current_brush_texture(brush); + if (tx) { + *r_id = &tx->id; + *r_ntree = tx->nodetree; + } } } } @@ -75,6 +119,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor")); func(calldata, NODE_CLASS_DISTORT, N_("Distort")); func(calldata, NODE_CLASS_GROUP, N_("Group")); + func(calldata, NODE_CLASS_INTERFACE, N_("Interface")); func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); } @@ -93,49 +138,42 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) } } -static void local_sync(bNodeTree *localtree, bNodeTree *ntree) +static void local_sync(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree)) { - bNode *lnode; - - /* copy over contents of previews */ - for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) { - if (ntreeNodeExists(ntree, lnode->new_node)) { - bNode *node = lnode->new_node; - - if (node->preview && node->preview->rect) { - if (lnode->preview && lnode->preview->rect) { - int xsize = node->preview->xsize; - int ysize = node->preview->ysize; - memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); - } - } - } - } } static void update(bNodeTree *ntree) { ntree_update_reroute_nodes(ntree); + + if (ntree->update & NTREE_UPDATE_NODES) { + /* clean up preview cache, in case nodes have been removed */ + BKE_node_preview_remove_unused(ntree); + } } -bNodeTreeType ntreeType_Texture = { - /* type */ NTREE_TEXTURE, - /* id_name */ "NTTexture Nodetree", +bNodeTreeType *ntreeType_Texture; + +void register_node_tree_type_tex(void) +{ + bNodeTreeType *tt = ntreeType_Texture = MEM_callocN(sizeof(bNodeTreeType), "texture node tree type"); - /* node_types */ { NULL, NULL }, + tt->type = NTREE_TEXTURE; + strcpy(tt->idname, "TextureNodeTree"); + strcpy(tt->ui_name, "Texture"); + tt->ui_icon = 0; /* defined in drawnode.c */ + strcpy(tt->ui_description, ""); - /* free_cache */ NULL, - /* free_node_cache */ NULL, - /* foreach_nodetree */ foreach_nodetree, - /* foreach_nodeclass */ foreach_nodeclass, - /* localize */ localize, - /* local_sync */ local_sync, - /* local_merge */ NULL, - /* update */ update, - /* update_node */ NULL, - /* validate_link */ NULL, - /* update_internal_links */ node_update_internal_links_default -}; + tt->foreach_nodeclass = foreach_nodeclass; + tt->update = update; + tt->localize = localize; + tt->local_sync = local_sync; + tt->get_from_context = texture_get_from_context; + + tt->ext.srna = &RNA_TextureNodeTree; + + ntreeTypeAdd(tt); +} int ntreeTexTagAnimated(bNodeTree *ntree) { @@ -158,24 +196,13 @@ int ntreeTexTagAnimated(bNodeTree *ntree) return 0; } -/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes. - * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. - */ -bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data) +bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) { bNodeTreeExec *exec; bNode *node; - if (use_tree_data) { - /* XXX hack: prevent exec data from being generated twice. - * this should be handled by the renderer! - */ - if (ntree->execdata) - return ntree->execdata; - } - /* common base initialization */ - exec = ntree_exec_begin(ntree); + exec = ntree_exec_begin(context, ntree, parent_key); /* allocate the thread stack listbase array */ exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); @@ -183,12 +210,28 @@ bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data) for (node = exec->nodetree->nodes.first; node; node = node->next) node->need_exec = 1; - if (use_tree_data) { - /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, - * which only store the ntree pointer. Should be fixed at some point! - */ - ntree->execdata = exec; - } + return exec; +} + +bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree) +{ + bNodeExecContext context; + bNodeTreeExec *exec; + + /* XXX hack: prevent exec data from being generated twice. + * this should be handled by the renderer! + */ + if (ntree->execdata) + return ntree->execdata; + + context.previews = ntree->previews; + + exec = ntreeTexBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE); + + /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, + * which only store the ntree pointer. Should be fixed at some point! + */ + ntree->execdata = exec; return exec; } @@ -207,35 +250,34 @@ static void tex_free_delegates(bNodeTreeExec *exec) MEM_freeN(ns->data); } -/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes. - * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. - */ -void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data) +void ntreeTexEndExecTree_internal(bNodeTreeExec *exec) { - if (exec) { - bNodeTree *ntree = exec->nodetree; - bNodeThreadStack *nts; - int a; + bNodeThreadStack *nts; + int a; + + if (exec->threadstack) { + tex_free_delegates(exec); - if (exec->threadstack) { - tex_free_delegates(exec); - - for (a = 0; a < BLENDER_MAX_THREADS; a++) { - for (nts = exec->threadstack[a].first; nts; nts = nts->next) - if (nts->stack) MEM_freeN(nts->stack); - BLI_freelistN(&exec->threadstack[a]); - } - - MEM_freeN(exec->threadstack); - exec->threadstack = NULL; + for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (nts = exec->threadstack[a].first; nts; nts = nts->next) + if (nts->stack) MEM_freeN(nts->stack); + BLI_freelistN(&exec->threadstack[a]); } - ntree_exec_end(exec); + MEM_freeN(exec->threadstack); + exec->threadstack = NULL; + } + + ntree_exec_end(exec); +} + +void ntreeTexEndExecTree(bNodeTreeExec *exec) +{ + if (exec) { + ntreeTexEndExecTree_internal(exec); - if (use_tree_data) { - /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ - ntree->execdata = NULL; - } + /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ + exec->nodetree->execdata = NULL; } } @@ -275,7 +317,7 @@ int ntreeTexExecTree( if (!exec) { BLI_lock_thread(LOCK_NODES); if (!nodes->execdata) - ntreeTexBeginExecTree(nodes, 1); + ntreeTexBeginExecTree(nodes); BLI_unlock_thread(LOCK_NODES); exec = nodes->execdata; diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c index 06473d800d0..80644157b02 100644 --- a/source/blender/nodes/texture/node_texture_util.c +++ b/source/blender/nodes/texture/node_texture_util.c @@ -49,13 +49,28 @@ #include <assert.h> #include "node_texture_util.h" + +int tex_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return (strcmp(ntree->idname, "TextureNodeTree")==0); +} + +void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + + ntype->poll = tex_node_poll_default; + ntype->update_internal_links = node_update_internal_links_default; +} + + static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread) { if (dg->node->need_exec) { dg->fn(out, params, dg->node, dg->in, thread); if (dg->cdata->do_preview) - tex_do_preview(dg->node, params->previewco, out); + tex_do_preview(dg->preview, params->previewco, out); } } @@ -112,19 +127,17 @@ void params_from_cdata(TexParams *out, TexCallData *in) out->mtex = in->mtex; } -void tex_do_preview(bNode *node, const float coord[2], const float col[4]) +void tex_do_preview(bNodePreview *preview, const float coord[2], const float col[4]) { - bNodePreview *preview = node->preview; - if (preview) { int xs = ((coord[0] + 1.0f) * 0.5f) * preview->xsize; int ys = ((coord[1] + 1.0f) * 0.5f) * preview->ysize; - - nodeAddToPreview(node, col, xs, ys, 0); /* 0 = no color management */ + + BKE_node_preview_set_pixel(preview, col, xs, ys, 0); /* 0 = no color management */ } } -void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata) +void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata) { TexDelegate *dg; if (!out->data) @@ -136,6 +149,7 @@ void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexC dg->cdata = cdata; dg->fn = texfn; dg->node = node; + dg->preview = execdata->preview; memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack *)); dg->type = out->sockettype; } diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h index 3b2a7e14f69..b81ea51ddff 100644 --- a/source/blender/nodes/texture/node_texture_util.h +++ b/source/blender/nodes/texture/node_texture_util.h @@ -65,6 +65,7 @@ #include "BKE_library.h" #include "node_util.h" +#include "NOD_texture.h" #include "NOD_texture.h" @@ -111,16 +112,21 @@ typedef struct TexDelegate { TexCallData *cdata; TexFn fn; bNode *node; + bNodePreview *preview; bNodeStack *in[MAX_SOCKET]; int type; } TexDelegate; + +int tex_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); +void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag); + void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread); void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread); float tex_input_value(bNodeStack *in, TexParams *params, short thread); -void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data); -void tex_do_preview(bNode *node, const float coord[2], const float col[4]); +void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data); +void tex_do_preview(bNodePreview *preview, const float coord[2], const float col[4]); void params_from_cdata(TexParams *out, TexCallData *in); diff --git a/source/blender/nodes/texture/nodes/node_texture_at.c b/source/blender/nodes/texture/nodes/node_texture_at.c index 4c2d276b902..aafb9793d2c 100644 --- a/source/blender/nodes/texture/nodes/node_texture_at.c +++ b/source/blender/nodes/texture/nodes/node_texture_at.c @@ -53,19 +53,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** tex_input_rgba(out, in[0], &np, thread); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_at(bNodeTreeType *ttype) +void register_node_type_tex_at(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_AT, "At", NODE_CLASS_DISTORT, 0); + tex_node_type_base(&ntype, TEX_NODE_AT, "At", NODE_CLASS_DISTORT, 0); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 140, 100, 320); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_bricks.c b/source/blender/nodes/texture/nodes/node_texture_bricks.c index b4f81f08e43..15cde299f35 100644 --- a/source/blender/nodes/texture/nodes/node_texture_bricks.c +++ b/source/blender/nodes/texture/nodes/node_texture_bricks.c @@ -50,7 +50,7 @@ static bNodeSocketTemplate outputs[] = { { -1, 0, "" } }; -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { node->custom3 = 0.5; /* offset */ node->custom4 = 1.0; /* squash */ @@ -116,20 +116,20 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_bricks(bNodeTreeType *ttype) +void register_node_type_tex_bricks(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_BRICKS, "Bricks", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_BRICKS, "Bricks", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 150, 60, 150); node_type_init(&ntype, init); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_checker.c b/source/blender/nodes/texture/nodes/node_texture_checker.c index 1f653d1f7b9..77c6a2e3010 100644 --- a/source/blender/nodes/texture/nodes/node_texture_checker.c +++ b/source/blender/nodes/texture/nodes/node_texture_checker.c @@ -65,19 +65,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** } } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_checker(bNodeTreeType *ttype) +void register_node_type_tex_checker(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_CHECKER, "Checker", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_CHECKER, "Checker", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 100, 60, 150); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c index aa427ff3587..e884d50dc05 100644 --- a/source/blender/nodes/texture/nodes/node_texture_common.c +++ b/source/blender/nodes/texture/nodes/node_texture_common.c @@ -38,9 +38,12 @@ #include "BKE_node.h" #include "node_texture_util.h" +#include "NOD_common.h" #include "node_common.h" #include "node_exec.h" +#include "RNA_access.h" + static void copy_stack(bNodeStack *to, bNodeStack *from) { if (to != from) { @@ -55,7 +58,7 @@ static void copy_stack(bNodeStack *to, bNodeStack *from) /**** GROUP ****/ -static void *group_initexec(bNode *node) +static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key) { bNodeTree *ngroup= (bNodeTree*)node->id; void *exec; @@ -64,7 +67,7 @@ static void *group_initexec(bNode *node) return NULL; /* initialize the internal node tree execution */ - exec = ntreeTexBeginExecTree(ngroup, 0); + exec = ntreeTexBeginExecTree_internal(context, ngroup, key); return exec; } @@ -73,43 +76,56 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata) { bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata; - ntreeTexEndExecTree(gexec, 0); + ntreeTexEndExecTree_internal(gexec); } /* Copy inputs to the internal stack. * This is a shallow copy, no buffers are duplicated here! */ -static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack) +static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack) { + bNodeTree *ngroup = (bNodeTree*)gnode->id; + bNode *node; bNodeSocket *sock; bNodeStack *ns; int a; - for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - copy_stack(ns, in[a]); + + for (node = ngroup->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP_INPUT) { + for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) { + ns = node_get_socket_stack(gstack, sock); + if (ns) + copy_stack(ns, in[a]); + } } } } /* Copy internal results to the external outputs. */ -static void group_copy_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack) +static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack) { + bNodeTree *ngroup = (bNodeTree*)gnode->id; + bNode *node; bNodeSocket *sock; bNodeStack *ns; int a; - for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - copy_stack(out[a], ns); + + for (node = ngroup->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) { + for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) { + ns = node_get_socket_stack(gstack, sock); + if (ns) + copy_stack(out[a], ns); + } + break; /* only one active output node */ } } } -static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) +static void group_execute(void *data, int thread, struct bNode *node, bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out) { - bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; + bNodeTreeExec *exec= execdata->data; bNodeThreadStack *nts; if (!exec) @@ -133,20 +149,27 @@ static void group_execute(void *data, int thread, struct bNode *node, void *node ntreeReleaseThreadStack(nts); } -void register_node_type_tex_group(bNodeTreeType *ttype) +void register_node_type_tex_group(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT); + /* NB: cannot use sh_node_type_base for node group, because it would map the node type + * to the shared NODE_GROUP integer type id. + */ + node_type_base_custom(&ntype, "TextureNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); + ntype.type = NODE_GROUP; + ntype.poll = tex_node_poll_default; + ntype.update_internal_links = node_update_internal_links_default; + ntype.ext.srna = RNA_struct_find("TextureNodeGroup"); + BLI_assert(ntype.ext.srna != NULL); + RNA_struct_blender_type_set(ntype.ext.srna, &ntype); + node_type_socket_templates(&ntype, NULL, NULL); node_type_size(&ntype, 120, 60, 200); node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_group_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_group_template); node_type_update(&ntype, NULL, node_group_verify); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute); + strcpy(ntype.group_tree_idname, "TextureNodeTree"); + node_type_exec(&ntype, group_initexec, group_freeexec, group_execute); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_compose.c b/source/blender/nodes/texture/nodes/node_texture_compose.c index 43a8ba1babf..065d16a5784 100644 --- a/source/blender/nodes/texture/nodes/node_texture_compose.c +++ b/source/blender/nodes/texture/nodes/node_texture_compose.c @@ -52,19 +52,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** out[i] = tex_input_value(in[i], p, thread); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_compose(bNodeTreeType *ttype) +void register_node_type_tex_compose(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_COMPOSE, "Combine RGBA", NODE_CLASS_OP_COLOR, 0); + tex_node_type_base(&ntype, TEX_NODE_COMPOSE, "Combine RGBA", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 100, 60, 150); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_coord.c b/source/blender/nodes/texture/nodes/node_texture_coord.c index 971520ebc38..b313e1f67ac 100644 --- a/source/blender/nodes/texture/nodes/node_texture_coord.c +++ b/source/blender/nodes/texture/nodes/node_texture_coord.c @@ -43,20 +43,20 @@ static void vectorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack * copy_v3_v3(out, p->co); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &vectorfn, data); + tex_output(node, execdata, in, out[0], &vectorfn, data); } -void register_node_type_tex_coord(bNodeTreeType *ttype) +void register_node_type_tex_coord(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_COORD, "Coordinates", NODE_CLASS_INPUT, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_COORD, "Coordinates", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, outputs); node_type_size(&ntype, 120, 110, 160); node_type_storage(&ntype, "node_coord", NULL, NULL); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_curves.c b/source/blender/nodes/texture/nodes/node_texture_curves.c index 5980f938938..1778eeaeffa 100644 --- a/source/blender/nodes/texture/nodes/node_texture_curves.c +++ b/source/blender/nodes/texture/nodes/node_texture_curves.c @@ -54,32 +54,31 @@ static void time_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNU out[0] = CLAMPIS(fac, 0.0f, 1.0f); } -static void time_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void time_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &time_colorfn, data); + tex_output(node, execdata, in, out[0], &time_colorfn, data); } -static void time_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void time_init(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1= 1; node->custom2= 250; node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } -void register_node_type_tex_curve_time(bNodeTreeType *ttype) +void register_node_type_tex_curve_time(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_CURVE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_CURVE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, time_outputs); node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, time_init); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - node_type_exec(&ntype, time_exec); - node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */ + node_type_exec(&ntype, node_initexec_curves, NULL, time_exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } /* **************** CURVE RGB ******************** */ @@ -102,27 +101,26 @@ static void rgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, out[3] = cin[3]; } -static void rgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void rgb_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &rgb_colorfn, data); + tex_output(node, execdata, in, out[0], &rgb_colorfn, data); } -static void rgb_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void rgb_init(bNodeTree *UNUSED(ntree), bNode *node) { node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } -void register_node_type_tex_curve_rgb(bNodeTreeType *ttype) +void register_node_type_tex_curve_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, rgb_inputs, rgb_outputs); node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, rgb_init); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - node_type_exec(&ntype, rgb_exec); - node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */ + node_type_exec(&ntype, node_initexec_curves, NULL, rgb_exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_decompose.c b/source/blender/nodes/texture/nodes/node_texture_decompose.c index 0866428ca6c..1207377d150 100644 --- a/source/blender/nodes/texture/nodes/node_texture_decompose.c +++ b/source/blender/nodes/texture/nodes/node_texture_decompose.c @@ -70,22 +70,22 @@ static void valuefn_a(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack *out = out[3]; } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &valuefn_r, data); - tex_output(node, in, out[1], &valuefn_g, data); - tex_output(node, in, out[2], &valuefn_b, data); - tex_output(node, in, out[3], &valuefn_a, data); + tex_output(node, execdata, in, out[0], &valuefn_r, data); + tex_output(node, execdata, in, out[1], &valuefn_g, data); + tex_output(node, execdata, in, out[2], &valuefn_b, data); + tex_output(node, execdata, in, out[3], &valuefn_a, data); } -void register_node_type_tex_decompose(bNodeTreeType *ttype) +void register_node_type_tex_decompose(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_DECOMPOSE, "Separate RGBA", NODE_CLASS_OP_COLOR, 0); + tex_node_type_base(&ntype, TEX_NODE_DECOMPOSE, "Separate RGBA", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 100, 60, 150); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_distance.c b/source/blender/nodes/texture/nodes/node_texture_distance.c index 8c3b1555d5d..f47f9260337 100644 --- a/source/blender/nodes/texture/nodes/node_texture_distance.c +++ b/source/blender/nodes/texture/nodes/node_texture_distance.c @@ -56,20 +56,20 @@ static void valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** *out = len_v3v3(co2, co1); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &valuefn, data); + tex_output(node, execdata, in, out[0], &valuefn, data); } -void register_node_type_tex_distance(bNodeTreeType *ttype) +void register_node_type_tex_distance(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 120, 110, 160); node_type_storage(&ntype, "node_distance", NULL, NULL); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c index b5e9969a830..56da4ad24c0 100644 --- a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c +++ b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c @@ -87,19 +87,19 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor out[3] = col[3]; } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_hue_sat(bNodeTreeType *ttype) +void register_node_type_tex_hue_sat(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 150, 80, 250); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index 2ef1669a266..57fa562ac0b 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -83,12 +83,12 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i } } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); node->storage= iuser; @@ -97,16 +97,16 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt iuser->ok= 1; } -void register_node_type_tex_image(bNodeTreeType *ttype) +void register_node_type_tex_image(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, outputs); node_type_size(&ntype, 120, 80, 300); node_type_init(&ntype, init); node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_invert.c b/source/blender/nodes/texture/nodes/node_texture_invert.c index 9c2963d2dc2..fd6e2144e0e 100644 --- a/source/blender/nodes/texture/nodes/node_texture_invert.c +++ b/source/blender/nodes/texture/nodes/node_texture_invert.c @@ -58,19 +58,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** out[3] = col[3]; } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_invert(bNodeTreeType *ttype) +void register_node_type_tex_invert(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 90, 80, 100); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c index 95d70ccc7d6..499412e750d 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.c +++ b/source/blender/nodes/texture/nodes/node_texture_math.c @@ -181,21 +181,21 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &valuefn, data); + tex_output(node, execdata, in, out[0], &valuefn, data); } -void register_node_type_tex_math(bNodeTreeType *ttype) +void register_node_type_tex_math(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 120, 110, 160); node_type_label(&ntype, node_math_label); node_type_storage(&ntype, "node_math", NULL, NULL); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c index fe04854c734..12ac27f26b7 100644 --- a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c +++ b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c @@ -59,20 +59,20 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor ramp_blend(node->custom1, out, fac, col2); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_mix_rgb(bNodeTreeType *ttype) +void register_node_type_tex_mix_rgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 100, 60, 150); node_type_label(&ntype, node_blend_label); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_output.c b/source/blender/nodes/texture/nodes/node_texture_output.c index 2f5efe8c45e..f4086ed1eec 100644 --- a/source/blender/nodes/texture/nodes/node_texture_output.c +++ b/source/blender/nodes/texture/nodes/node_texture_output.c @@ -41,7 +41,7 @@ static bNodeSocketTemplate inputs[] = { }; /* applies to render pipeline */ -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out)) { TexCallData *cdata = (TexCallData *)data; TexResult *target = cdata->target; @@ -54,7 +54,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o tex_input_rgba(&target->tr, in[1], ¶ms, cdata->thread); else tex_input_rgba(&target->tr, in[0], ¶ms, cdata->thread); - tex_do_preview(node, params.co, &target->tr); + tex_do_preview(execdata->preview, params.co, &target->tr); } else { /* 0 means don't care, so just use first */ @@ -141,7 +141,7 @@ static void assign_index(struct bNode *node) node->custom1 = index; } -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output"); node->storage= tno; @@ -151,26 +151,26 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt assign_index(node); } -static void copy(bNode *orig, bNode *new) +static void copy(bNodeTree *dest_ntree, bNode *dest_node, bNode *src_node) { - node_copy_standard_storage(orig, new); - unique_name(new); - assign_index(new); + node_copy_standard_storage(dest_ntree, dest_node, src_node); + unique_name(dest_node); + assign_index(dest_node); } -void register_node_type_tex_output(bNodeTreeType *ttype) +void register_node_type_tex_output(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, NULL); node_type_size(&ntype, 150, 60, 200); node_type_init(&ntype, init); node_type_storage(&ntype, "TexNodeOutput", node_free_standard_storage, copy); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); /* Do not allow muting output. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c index de2dac22d81..f7e7a585ae2 100644 --- a/source/blender/nodes/texture/nodes/node_texture_proc.c +++ b/source/blender/nodes/texture/nodes/node_texture_proc.c @@ -129,11 +129,11 @@ static int count_outputs(bNode *node) { \ texfn(result, p, node, in, 1, &name##_map_inputs, thread); \ } \ - static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \ + static void name##_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) \ { \ int outs = count_outputs(node); \ - if (outs >= 1) tex_output(node, in, out[0], &name##_colorfn, data); \ - if (outs >= 2) tex_output(node, in, out[1], &name##_normalfn, data); \ + if (outs >= 1) tex_output(node, execdata, in, out[0], &name##_colorfn, data); \ + if (outs >= 2) tex_output(node, execdata, in, out[1], &name##_normalfn, data); \ } @@ -281,7 +281,7 @@ ProcDef(stucci) /* --- */ -static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void init(bNodeTree *UNUSED(ntree), bNode *node) { Tex *tex = MEM_callocN(sizeof(Tex), "Tex"); node->storage= tex; @@ -296,18 +296,18 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt /* Node type definitions */ #define TexDef(TEXTYPE, outputs, name, Name) \ -void register_node_type_tex_proc_##name(bNodeTreeType *ttype) \ +void register_node_type_tex_proc_##name(void) \ { \ static bNodeType ntype; \ \ - node_type_base(ttype, &ntype, TEX_NODE_PROC+TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW|NODE_OPTIONS); \ + tex_node_type_base(&ntype, TEX_NODE_PROC+TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW | NODE_OPTIONS); \ node_type_socket_templates(&ntype, name##_inputs, outputs); \ node_type_size(&ntype, 140, 80, 140); \ node_type_init(&ntype, init); \ node_type_storage(&ntype, "Tex", node_free_standard_storage, node_copy_standard_storage); \ - node_type_exec(&ntype, name##_exec); \ + node_type_exec(&ntype, NULL, NULL, name##_exec); \ \ - nodeRegisterType(ttype, &ntype); \ + nodeRegisterType(&ntype); \ } #define C outputs_color_only diff --git a/source/blender/nodes/texture/nodes/node_texture_rotate.c b/source/blender/nodes/texture/nodes/node_texture_rotate.c index 1b1d57044a3..02a5a9e1a97 100644 --- a/source/blender/nodes/texture/nodes/node_texture_rotate.c +++ b/source/blender/nodes/texture/nodes/node_texture_rotate.c @@ -90,19 +90,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** tex_input_rgba(out, in[0], &np, thread); } } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_rotate(bNodeTreeType *ttype) +void register_node_type_tex_rotate(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 140, 100, 320); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_scale.c b/source/blender/nodes/texture/nodes/node_texture_scale.c index 56562724fb9..8eabdabc713 100644 --- a/source/blender/nodes/texture/nodes/node_texture_scale.c +++ b/source/blender/nodes/texture/nodes/node_texture_scale.c @@ -63,19 +63,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** tex_input_rgba(out, in[0], &np, thread); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_scale(bNodeTreeType *ttype) +void register_node_type_tex_scale(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 90, 80, 100); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_texture.c b/source/blender/nodes/texture/nodes/node_texture_texture.c index f839f485976..a42633cb2b4 100644 --- a/source/blender/nodes/texture/nodes/node_texture_texture.c +++ b/source/blender/nodes/texture/nodes/node_texture_texture.c @@ -90,19 +90,19 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_texture(bNodeTreeType *ttype) +void register_node_type_tex_texture(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 120, 80, 240); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_translate.c b/source/blender/nodes/texture/nodes/node_texture_translate.c index a95cb00a47d..55782fbecac 100644 --- a/source/blender/nodes/texture/nodes/node_texture_translate.c +++ b/source/blender/nodes/texture/nodes/node_texture_translate.c @@ -59,19 +59,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** tex_input_rgba(out, in[0], &np, thread); } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &colorfn, data); + tex_output(node, execdata, in, out[0], &colorfn, data); } -void register_node_type_tex_translate(bNodeTreeType *ttype) +void register_node_type_tex_translate(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 90, 80, 100); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_valToNor.c b/source/blender/nodes/texture/nodes/node_texture_valToNor.c index bbfc1fa616b..6be61c914db 100644 --- a/source/blender/nodes/texture/nodes/node_texture_valToNor.c +++ b/source/blender/nodes/texture/nodes/node_texture_valToNor.c @@ -75,19 +75,19 @@ static void normalfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack * out[1] = val-nor[1]; out[2] = val-nor[2]; } -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &normalfn, data); + tex_output(node, execdata, in, out[0], &normalfn, data); } -void register_node_type_tex_valtonor(bNodeTreeType *ttype) +void register_node_type_tex_valtonor(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 90, 80, 100); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c index 78635453fc1..871cdab384e 100644 --- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c +++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c @@ -52,28 +52,28 @@ static void valtorgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack * } } -static void valtorgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void valtorgb_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &valtorgb_colorfn, data); + tex_output(node, execdata, in, out[0], &valtorgb_colorfn, data); } -static void valtorgb_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void valtorgb_init(bNodeTree *UNUSED(ntree), bNode *node) { - node->storage = add_colorband(1); + node->storage = add_colorband(true); } -void register_node_type_tex_valtorgb(bNodeTreeType *ttype) +void register_node_type_tex_valtorgb(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); + tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out); node_type_size(&ntype, 240, 200, 300); node_type_init(&ntype, valtorgb_init); node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, valtorgb_exec); + node_type_exec(&ntype, NULL, NULL, valtorgb_exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } /* **************** RGBTOBW ******************** */ @@ -94,19 +94,19 @@ static void rgbtobw_valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNode *out = rgb_to_bw(cin); } -static void rgbtobw_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +static void rgbtobw_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) { - tex_output(node, in, out[0], &rgbtobw_valuefn, data); + tex_output(node, execdata, in, out[0], &rgbtobw_valuefn, data); } -void register_node_type_tex_rgbtobw(bNodeTreeType *ttype) +void register_node_type_tex_rgbtobw(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); + tex_node_type_base(&ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, rgbtobw_in, rgbtobw_out); node_type_size(&ntype, 80, 40, 120); - node_type_exec(&ntype, rgbtobw_exec); + node_type_exec(&ntype, NULL, NULL, rgbtobw_exec); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_viewer.c b/source/blender/nodes/texture/nodes/node_texture_viewer.c index 5cb8d8c438c..4f7d54ab833 100644 --- a/source/blender/nodes/texture/nodes/node_texture_viewer.c +++ b/source/blender/nodes/texture/nodes/node_texture_viewer.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate outputs[] = { { -1, 0, "" } }; -static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) +static void exec(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out)) { TexCallData *cdata = (TexCallData *)data; @@ -52,21 +52,21 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o params_from_cdata(¶ms, cdata); tex_input_rgba(col, in[0], ¶ms, cdata->thread); - tex_do_preview(node, params.previewco, col); + tex_do_preview(execdata->preview, params.previewco, col); } } -void register_node_type_tex_viewer(bNodeTreeType *ttype) +void register_node_type_tex_viewer(void) { static bNodeType ntype; - node_type_base(ttype, &ntype, TEX_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW); + tex_node_type_base(&ntype, TEX_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW); node_type_socket_templates(&ntype, inputs, outputs); node_type_size(&ntype, 100, 60, 150); - node_type_exec(&ntype, exec); + node_type_exec(&ntype, NULL, NULL, exec); /* Do not allow muting viewer node. */ node_type_internal_links(&ntype, NULL); - nodeRegisterType(ttype, &ntype); + nodeRegisterType(&ntype); } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 8fe75032a46..ebd38e672da 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -3119,6 +3119,33 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop)); } +PyDoc_STRVAR(pyrna_struct_property_unset_doc, +".. method:: property_unset(property)\n" +"\n" +" Unset a property, will use default value afterward.\n" +); +static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args) +{ + PropertyRNA *prop; + const char *name; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "s:property_unset", &name)) + return NULL; + + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.property_unset(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), name); + return NULL; + } + + RNA_property_unset(&self->ptr, prop); + + Py_RETURN_NONE; +} + PyDoc_STRVAR(pyrna_struct_is_property_hidden_doc, ".. method:: is_property_hidden(property)\n" "\n" @@ -4633,6 +4660,7 @@ static struct PyMethodDef pyrna_struct_methods[] = { {"driver_remove", (PyCFunction)pyrna_struct_driver_remove, METH_VARARGS, pyrna_struct_driver_remove_doc}, {"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, pyrna_struct_is_property_set_doc}, + {"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc}, {"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc}, {"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc}, {"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc}, diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 2ff612e7c0f..fbcab8c19d4 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -921,7 +921,7 @@ static void flag_render_node_material(Render *re, bNodeTree *ntree) { bNode *node; - for (node=ntree->nodes.first; node; node= node->next) { + for (node = ntree->nodes.first; node; node = node->next) { if (node->id) { if (GS(node->id->name)==ID_MA) { Material *ma= (Material *)node->id; @@ -5755,7 +5755,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned ok= 1; } if (ok==0) { - printf("speed table: missing object %s\n", obi->ob->id.name+2); + printf("speed table: missing object %s\n", obi->ob->id.name + 2); continue; } @@ -5771,7 +5771,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned if (obi->totvector==oldobi->totvector) calculate_speedvectors(re, obi, oldobi->vectors, step); else - printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name+2); + printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name + 2); } /* not fluidsim */ oldobi= oldobi->next; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 64598063a8f..4cb1297798e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1474,7 +1474,7 @@ static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node) for (sock = node->outputs.first; sock; sock = sock->next) { /* Weak! but how to make it better? */ - if (!strcmp(sock->name, "Alpha") && nodeCountSocketLinks(ntree, sock) > 0) + if (STREQ(sock->name, "Alpha") && nodeCountSocketLinks(ntree, sock) > 0) return true; } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 15ca865643b..96eaa656c36 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -121,7 +121,7 @@ static void init_render_texture(Render *re, Tex *tex) } if (tex->nodetree && tex->use_nodes) { - ntreeTexBeginExecTree(tex->nodetree, 1); /* has internal flag to detect it only does it once */ + ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */ } } @@ -141,7 +141,7 @@ void init_render_textures(Render *re) static void end_render_texture(Tex *tex) { if (tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata) - ntreeTexEndExecTree(tex->nodetree->execdata, 1); + ntreeTexEndExecTree(tex->nodetree->execdata); } void end_render_textures(Render *re) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 6e557647d12..d908a33c706 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -198,7 +198,7 @@ void WM_init(bContext *C, int argc, const char **argv) clear_matcopybuf(); ED_render_clear_mtex_copybuf(); - // glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ED_preview_init_dbase(); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index a289d182f1c..e4e529ace71 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -825,7 +825,7 @@ static void playanim_window_zoom(PlayState *ps, const float zoom_offset) sizey = ps->zoom * ps->ibufy; /* ofsx -= sizex / 2; */ /* UNUSED */ /* ofsy -= sizey / 2; */ /* UNUSED */ - // window_set_position(g_WS.ghost_window,sizex,sizey); + // window_set_position(g_WS.ghost_window, sizex, sizey); GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); } diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 61b5ecb45b3..fb877bda694 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -113,8 +113,11 @@ struct bConstraintOb; struct bConstraintTarget; struct bContextDataResult; struct bNode; +struct bNodeType; struct bNodeSocket; +struct bNodeSocketType; struct bNodeTree; +struct bNodeTreeType; struct bPoseChannel; struct bPythonConstraint; struct bTheme; @@ -232,7 +235,7 @@ void ED_armature_edit_bone_remove(struct bArmature *arm, struct EditBone *exBone void object_test_constraints(struct Object *owner) {} void ED_object_parent(struct Object *ob, struct Object *par, int type, const char *substr) {} void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con) {} -void ED_node_composit_default(struct Scene *sce) {} +void ED_node_composit_default(struct bContext *C, struct Scene *scene) {} void *ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *custumdata, int type) {return 0;} /* XXX this one looks weird */ void *ED_region_draw_cb_customdata(void *handle) {return 0;} /* XXX This one looks wrong also */ void ED_region_draw_cb_exit(struct ARegionType *art, void *handle) {} @@ -309,10 +312,21 @@ void ED_area_newspace(struct bContext *C, struct ScrArea *sa, int type) {} void ED_region_tag_redraw(struct ARegion *ar) {} void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op) {} void WM_cursor_wait(int val) {} -void ED_node_texture_default(struct Tex *tx) {} -void ED_node_changed_update(struct bContext *C, struct bNode *node) {} -void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) {} -void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene) {} +void ED_node_texture_default(struct bContext *C, struct Tex *tx) {} +void ED_node_tag_update_id(struct ID *id) {} +void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree) {} +void ED_node_tree_update(const struct bContext *C) {} +void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){} +void ED_init_custom_node_type(struct bNodeType *ntype){} +void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){} +void ED_init_standard_node_socket_type(struct bNodeSocketType *stype) {} +void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype) {} +int ED_node_tree_path_length(struct SpaceNode *snode){return 0;} +void ED_node_tree_path_get(struct SpaceNode *snode, char *value){} +void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){} +void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){} +void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){} +void ED_node_tree_pop(struct SpaceNode *snode){} void ED_view3d_scene_layers_update(struct Main *bmain, struct Scene *scene) {} int ED_view3d_scene_layer_set(int lay, const int *values) {return 0;} void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar) {} @@ -324,7 +338,7 @@ void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct AR float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {return 0.0f;} void view3d_apply_mat4(float mat[4][4], float *ofs, float *quat, float *dist) {} int text_file_modified(struct Text *text) {return 0;} -void ED_node_shader_default(struct Material *ma) {} +void ED_node_shader_default(struct bContext *C, struct ID *id) {} void ED_screen_animation_timer_update(struct bContext *C, int redraws) {} void ED_screen_animation_playing(struct wmWindowManager *wm) {} void ED_base_object_select(struct Base *base, short mode) {} @@ -463,6 +477,8 @@ void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const cha void uiTemplateImageSettings(struct uiLayout *layout, struct PointerRNA *imfptr) {} void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {} void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings) {} +void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name){} +void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) {} /* rna render */ struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h) {return (struct RenderResult *) NULL;} |