diff options
Diffstat (limited to 'intern/cycles/blender/blender_shader.cpp')
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 1148 |
1 files changed, 532 insertions, 616 deletions
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; |