diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 4f02e2dfc60..f5555852c08 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 0 +#define BLENDER_FILE_SUBVERSION 1 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/BKE_material.hh b/source/blender/blenkernel/BKE_material.hh index d455560507b..5e5f01a39ab 100644 --- a/source/blender/blenkernel/BKE_material.hh +++ b/source/blender/blenkernel/BKE_material.hh @@ -209,7 +209,7 @@ void BKE_id_material_eval_ensure_default_slot(ID *id); * \param col: new value. * \param fac: Zero for is no change. */ -void ramp_blend(int type, float r_col[3], float fac, const float col[3]); +void ramp_blend(int type, float r_col[4], float fac, const float col[4]); /** \} */ diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc index 7048f2776f6..face1a0a1b5 100644 --- a/source/blender/blenkernel/intern/material.cc +++ b/source/blender/blenkernel/intern/material.cc @@ -1779,7 +1779,7 @@ bNode *BKE_texpaint_slot_material_find_node(Material *ma, short texpaint_slot) return find_data.r_node; } -void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) +void ramp_blend(int type, float r_col[4], const float fac, const float col[4]) { float tmp, facm = 1.0f - fac; @@ -1788,6 +1788,7 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) r_col[0] = facm * (r_col[0]) + fac * col[0]; r_col[1] = facm * (r_col[1]) + fac * col[1]; r_col[2] = facm * (r_col[2]) + fac * col[2]; + r_col[3] = facm * (r_col[3]) + fac * col[3]; break; case MA_RAMP_ADD: r_col[0] += fac * col[0]; diff --git a/source/blender/blenloader/intern/versioning_510.cc b/source/blender/blenloader/intern/versioning_510.cc index ee02c61cee7..526854289d8 100644 --- a/source/blender/blenloader/intern/versioning_510.cc +++ b/source/blender/blenloader/intern/versioning_510.cc @@ -9,10 +9,17 @@ #define DNA_DEPRECATED_ALLOW #include "DNA_ID.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "BLI_listbase.h" +#include "BLI_math_vector.h" #include "BLI_sys_types.h" #include "BKE_main.hh" +#include "BKE_node.hh" +#include "BKE_node_legacy_types.hh" +#include "BKE_node_runtime.hh" #include "readfile.hh" @@ -21,6 +28,197 @@ // #include "CLG_log.h" // static CLG_LogRef LOG = {"blend.doversion"}; +/* The Mix mode of the Mix node previously assumed the alpha of the first input as opposed to + * mixing the alpha as well. So we add a separate color node to get the alpha of the first input + * and set it to the result using a set alpha node. */ +static void do_version_mix_node_mix_mode_compositor(bNodeTree &node_tree, bNode &node) +{ + const NodeShaderMix *data = reinterpret_cast(node.storage); + if (data->data_type != SOCK_RGBA) { + return; + } + + if (data->blend_type != MA_RAMP_BLEND) { + return; + } + + bNodeSocket *first_input = blender::bke::node_find_socket(node, SOCK_IN, "A_Color"); + bNodeSocket *output = blender::bke::node_find_socket(node, SOCK_OUT, "Result_Color"); + + /* Find the link going into the inputs of the node. */ + bNodeLink *first_link = nullptr; + LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { + if (link->tosock == first_input) { + first_link = link; + } + } + + bNode &separate_node = version_node_add_empty(node_tree, "CompositorNodeSeparateColor"); + separate_node.parent = node.parent; + separate_node.location[0] = node.location[0] - 10.0f; + separate_node.location[1] = node.location[1]; + NodeCMPCombSepColor *storage = MEM_callocN(__func__); + storage->mode = CMP_NODE_COMBSEP_COLOR_RGB; + separate_node.storage = storage; + + bNodeSocket &separate_input = version_node_add_socket( + node_tree, separate_node, SOCK_IN, "NodeSocketColor", "Image"); + bNodeSocket &separate_alpha_output = version_node_add_socket( + node_tree, separate_node, SOCK_OUT, "NodeSocketFloat", "Alpha"); + + copy_v4_v4(separate_input.default_value_typed()->value, + first_input->default_value_typed()->value); + if (first_link) { + version_node_add_link( + node_tree, *first_link->fromnode, *first_link->fromsock, separate_node, separate_input); + } + + bNode &set_alpha_node = version_node_add_empty(node_tree, "CompositorNodeSetAlpha"); + set_alpha_node.parent = node.parent; + set_alpha_node.location[0] = node.location[0] - 10.0f; + set_alpha_node.location[1] = node.location[1]; + set_alpha_node.storage = MEM_callocN(__func__); + + bNodeSocket &set_alpha_image_input = version_node_add_socket( + node_tree, set_alpha_node, SOCK_IN, "NodeSocketColor", "Image"); + bNodeSocket &set_alpha_alpha_input = version_node_add_socket( + node_tree, set_alpha_node, SOCK_IN, "NodeSocketFloat", "Alpha"); + bNodeSocket &set_alpha_type_input = version_node_add_socket( + node_tree, set_alpha_node, SOCK_IN, "NodeSocketMenu", "Type"); + bNodeSocket &set_alpha_output = version_node_add_socket( + node_tree, set_alpha_node, SOCK_OUT, "NodeSocketColor", "Image"); + + set_alpha_type_input.default_value_typed()->value = + CMP_NODE_SETALPHA_MODE_REPLACE_ALPHA; + version_node_add_link(node_tree, node, *output, set_alpha_node, set_alpha_image_input); + version_node_add_link( + node_tree, separate_node, separate_alpha_output, set_alpha_node, set_alpha_alpha_input); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &node_tree.links) { + if (link->fromsock == output && link->tonode != &set_alpha_node) { + version_node_add_link( + node_tree, set_alpha_node, set_alpha_output, *link->tonode, *link->tosock); + blender::bke::node_remove_link(&node_tree, *link); + } + } +} + +/* The Mix mode of the Mix node previously assumed the alpha of the first input as opposed to + * mixing the alpha as well. So we add a separate color node to get the alpha of the first input + * and set it to the result using a pair of separate and combine color nodes. */ +static void do_version_mix_node_mix_mode_geometry(bNodeTree &node_tree, bNode &node) +{ + const NodeShaderMix *data = reinterpret_cast(node.storage); + if (data->data_type != SOCK_RGBA) { + return; + } + + if (data->blend_type != MA_RAMP_BLEND) { + return; + } + + bNodeSocket *first_input = blender::bke::node_find_socket(node, SOCK_IN, "A_Color"); + bNodeSocket *output = blender::bke::node_find_socket(node, SOCK_OUT, "Result_Color"); + + /* Find the link going into the inputs of the node. */ + bNodeLink *first_link = nullptr; + LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { + if (link->tosock == first_input) { + first_link = link; + } + } + + bNode &separate_alpha_node = version_node_add_empty(node_tree, "FunctionNodeSeparateColor"); + separate_alpha_node.parent = node.parent; + separate_alpha_node.location[0] = node.location[0] - 10.0f; + separate_alpha_node.location[1] = node.location[1]; + NodeCombSepColor *separate_alpha_storage = MEM_callocN(__func__); + separate_alpha_storage->mode = NODE_COMBSEP_COLOR_RGB; + separate_alpha_node.storage = separate_alpha_storage; + + bNodeSocket &separate_alpha_input = version_node_add_socket( + node_tree, separate_alpha_node, SOCK_IN, "NodeSocketColor", "Color"); + bNodeSocket &separate_alpha_output = version_node_add_socket( + node_tree, separate_alpha_node, SOCK_OUT, "NodeSocketFloat", "Alpha"); + + copy_v4_v4(separate_alpha_input.default_value_typed()->value, + first_input->default_value_typed()->value); + if (first_link) { + version_node_add_link(node_tree, + *first_link->fromnode, + *first_link->fromsock, + separate_alpha_node, + separate_alpha_input); + } + + bNode &separate_color_node = version_node_add_empty(node_tree, "FunctionNodeSeparateColor"); + separate_color_node.parent = node.parent; + separate_color_node.location[0] = node.location[0] - 10.0f; + separate_color_node.location[1] = node.location[1]; + NodeCombSepColor *separate_color_storage = MEM_callocN(__func__); + separate_color_storage->mode = NODE_COMBSEP_COLOR_RGB; + separate_color_node.storage = separate_color_storage; + + bNodeSocket &separate_color_input = version_node_add_socket( + node_tree, separate_color_node, SOCK_IN, "NodeSocketColor", "Color"); + bNodeSocket &separate_color_red_output = version_node_add_socket( + node_tree, separate_color_node, SOCK_OUT, "NodeSocketFloat", "Red"); + bNodeSocket &separate_color_green_output = version_node_add_socket( + node_tree, separate_color_node, SOCK_OUT, "NodeSocketFloat", "Green"); + bNodeSocket &separate_color_blue_output = version_node_add_socket( + node_tree, separate_color_node, SOCK_OUT, "NodeSocketFloat", "Blue"); + + version_node_add_link(node_tree, node, *output, separate_color_node, separate_color_input); + + bNode &combine_color_node = version_node_add_empty(node_tree, "FunctionNodeCombineColor"); + combine_color_node.parent = node.parent; + combine_color_node.location[0] = node.location[0] - 10.0f; + combine_color_node.location[1] = node.location[1]; + NodeCombSepColor *combine_color_storage = MEM_callocN(__func__); + combine_color_storage->mode = NODE_COMBSEP_COLOR_RGB; + combine_color_node.storage = combine_color_storage; + + bNodeSocket &combine_color_red_input = version_node_add_socket( + node_tree, combine_color_node, SOCK_IN, "NodeSocketFloat", "Red"); + bNodeSocket &combine_color_green_input = version_node_add_socket( + node_tree, combine_color_node, SOCK_IN, "NodeSocketFloat", "Green"); + bNodeSocket &combine_color_blue_input = version_node_add_socket( + node_tree, combine_color_node, SOCK_IN, "NodeSocketFloat", "Blue"); + bNodeSocket &combine_color_alpha_input = version_node_add_socket( + node_tree, combine_color_node, SOCK_IN, "NodeSocketFloat", "Alpha"); + bNodeSocket &combine_color_output = version_node_add_socket( + node_tree, combine_color_node, SOCK_OUT, "NodeSocketColor", "Color"); + + version_node_add_link(node_tree, + separate_color_node, + separate_color_red_output, + combine_color_node, + combine_color_red_input); + version_node_add_link(node_tree, + separate_color_node, + separate_color_green_output, + combine_color_node, + combine_color_green_input); + version_node_add_link(node_tree, + separate_color_node, + separate_color_blue_output, + combine_color_node, + combine_color_blue_input); + version_node_add_link(node_tree, + separate_alpha_node, + separate_alpha_output, + combine_color_node, + combine_color_alpha_input); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &node_tree.links) { + if (link->fromsock == output && link->tonode != &separate_color_node) { + version_node_add_link( + node_tree, combine_color_node, combine_color_output, *link->tonode, *link->tosock); + blender::bke::node_remove_link(&node_tree, *link); + } + } +} + void do_versions_after_linking_510(FileData * /*fd*/, Main * /*bmain*/) { /** @@ -31,8 +229,28 @@ void do_versions_after_linking_510(FileData * /*fd*/, Main * /*bmain*/) */ } -void blo_do_versions_510(FileData * /*fd*/, Library * /*lib*/, Main * /*bmain*/) +void blo_do_versions_510(FileData * /*fd*/, Library * /*lib*/, Main *bmain) { + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 501, 1)) { + FOREACH_NODETREE_BEGIN (bmain, node_tree, id) { + if (node_tree->type == NTREE_COMPOSIT) { + LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + if (node->type_legacy == SH_NODE_MIX) { + do_version_mix_node_mix_mode_compositor(*node_tree, *node); + } + } + } + else if (node_tree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + if (node->type_legacy == SH_NODE_MIX) { + do_version_mix_node_mix_mode_geometry(*node_tree, *node); + } + } + } + } + FOREACH_NODETREE_END; + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index e5060e07b06..e24b0e88a69 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -156,7 +156,7 @@ static PyObject *Freestyle_blendRamp(PyObject * /*self*/, PyObject *args) PyObject *obj1, *obj2; char *s; int type; - float a[3], fac, b[3]; + float a[4], fac, b[4]; if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2)) { return nullptr; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl index c82f3fb3a1c..d05231b767b 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl @@ -17,7 +17,6 @@ void node_mix_blend(float fac, out float4 outcol) { outcol = mix(col1, col2, fac); - outcol.a = col1.a; } void node_mix_add(float fac, diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc index cdc7a30b698..8d4400f5583 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc @@ -465,7 +465,7 @@ class MixColorFunction : public mf::MultiFunction { if (clamp_result_) { mask.foreach_index_optimized( - [&](const int64_t i) { clamp_v3(results[i], 0.0f, 1.0f); }); + [&](const int64_t i) { clamp_v4(results[i], 0.0f, 1.0f); }); } } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc index 9541c9ac45a..3f0fc5520d3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc @@ -141,7 +141,7 @@ class MixRGBFunction : public mf::MultiFunction { }); if (clamp_) { - mask.foreach_index([&](const int64_t i) { clamp_v3(results[i], 0.0f, 1.0f); }); + mask.foreach_index([&](const int64_t i) { clamp_v4(results[i], 0.0f, 1.0f); }); } } };