Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenloader/intern/versioning_cycles.c')
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c480
1 files changed, 480 insertions, 0 deletions
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index a3e9b8dc206..2c4ba4a1102 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -34,12 +34,16 @@
#include "DNA_node_types.h"
#include "DNA_particle_types.h"
#include "DNA_camera_types.h"
+#include "DNA_anim_types.h"
#include "BKE_colortools.h"
+#include "BKE_animsys.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "MEM_guardedalloc.h"
+
#include "IMB_colormanagement.h"
#include "BLO_readfile.h"
@@ -756,6 +760,424 @@ static void update_vector_math_node_average_operator(bNodeTree *ntree)
}
}
+/* The Noise node now have a dimension property. This property should be
+ * initialized to 3 by default.
+ */
+static void update_noise_node_dimensions(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_NOISE) {
+ NodeTexNoise *tex = (NodeTexNoise *)node->storage;
+ tex->dimensions = 3;
+ }
+ }
+}
+
+/* The Mapping node has been rewritten to support dynamic inputs. Previously,
+ * the transformation information was stored in a TexMapping struct in the
+ * node->storage member of bNode. Currently, the transformation information
+ * is stored in input sockets. To correct this, we transfer the information
+ * from the TexMapping struct to the input sockets.
+ *
+ * Additionally, the Minimum and Maximum properties are no longer available
+ * in the node. To correct this, a Vector Minimum and/or a Vector Maximum
+ * nodes are added if needed.
+ *
+ * Finally, the TexMapping struct is freed and node->storage is set to NULL.
+ *
+ * Since the RNA paths of the properties changed, we also have to update the
+ * rna_path of the FCurves if they exist. To do that, we loop over FCurves
+ * and check if they control a property of the node, if they do, we update
+ * the path to be that of the corresponding socket in the node or the added
+ * minimum/maximum node.
+ *
+ */
+static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ /* If node->storage is NULL, then conversion has already taken place.
+ * This can happen if a file with the new mapping node [saved from (2, 81, 8) or newer]
+ * is opened in a blender version prior to (2, 81, 8) and saved from there again. */
+ if (node->type == SH_NODE_MAPPING && node->storage) {
+ TexMapping *mapping = (TexMapping *)node->storage;
+ node->custom1 = mapping->type;
+ node->width = 140.0f;
+
+ bNodeSocket *sockLocation = nodeFindSocket(node, SOCK_IN, "Location");
+ copy_v3_v3(cycles_node_socket_vector_value(sockLocation), mapping->loc);
+ bNodeSocket *sockRotation = nodeFindSocket(node, SOCK_IN, "Rotation");
+ copy_v3_v3(cycles_node_socket_vector_value(sockRotation), mapping->rot);
+ bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
+ copy_v3_v3(cycles_node_socket_vector_value(sockScale), mapping->size);
+
+ bNode *maximumNode = NULL;
+ if (mapping->flag & TEXMAP_CLIP_MIN) {
+ maximumNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ maximumNode->custom1 = NODE_VECTOR_MATH_MAXIMUM;
+ if (mapping->flag & TEXMAP_CLIP_MAX) {
+ maximumNode->locx = node->locx + (node->width + 20.0f) * 2.0f;
+ }
+ else {
+ maximumNode->locx = node->locx + node->width + 20.0f;
+ }
+ maximumNode->locy = node->locy;
+ bNodeSocket *sockMaximumB = BLI_findlink(&maximumNode->inputs, 1);
+ copy_v3_v3(cycles_node_socket_vector_value(sockMaximumB), mapping->min);
+ bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockMappingResult) {
+ bNodeSocket *sockMaximumResult = nodeFindSocket(maximumNode, SOCK_OUT, "Vector");
+ nodeAddLink(ntree, maximumNode, sockMaximumResult, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ if (!(mapping->flag & TEXMAP_CLIP_MAX)) {
+ bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0);
+ nodeAddLink(ntree, node, sockMappingResult, maximumNode, sockMaximumA);
+ }
+
+ need_update = true;
+ }
+
+ bNode *minimumNode = NULL;
+ if (mapping->flag & TEXMAP_CLIP_MAX) {
+ minimumNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ minimumNode->custom1 = NODE_VECTOR_MATH_MINIMUM;
+ minimumNode->locx = node->locx + node->width + 20.0f;
+ minimumNode->locy = node->locy;
+ bNodeSocket *sockMinimumB = BLI_findlink(&minimumNode->inputs, 1);
+ copy_v3_v3(cycles_node_socket_vector_value(sockMinimumB), mapping->max);
+
+ bNodeSocket *sockMinimumResult = nodeFindSocket(minimumNode, SOCK_OUT, "Vector");
+ bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector");
+
+ if (maximumNode) {
+ bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0);
+ nodeAddLink(ntree, minimumNode, sockMinimumResult, maximumNode, sockMaximumA);
+ }
+ else {
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockMappingResult) {
+ nodeAddLink(ntree, minimumNode, sockMinimumResult, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ }
+ bNodeSocket *sockMinimumA = BLI_findlink(&minimumNode->inputs, 0);
+ nodeAddLink(ntree, node, sockMappingResult, minimumNode, sockMinimumA);
+
+ need_update = true;
+ }
+
+ MEM_freeN(node->storage);
+ node->storage = NULL;
+
+ AnimData *animData = BKE_animdata_from_id(&ntree->id);
+ if (animData && animData->action) {
+ char *nodePath = BLI_sprintfN("nodes[\"%s\"]", node->name);
+ for (FCurve *fcu = animData->action->curves.first; fcu; fcu = fcu->next) {
+ if (STRPREFIX(fcu->rna_path, nodePath) &&
+ !BLI_str_endswith(fcu->rna_path, "default_value")) {
+ char *old_fcu_rna_path = fcu->rna_path;
+
+ if (BLI_str_endswith(old_fcu_rna_path, "translation")) {
+ fcu->rna_path = BLI_sprintfN("%s.%s", nodePath, "inputs[1].default_value");
+ }
+ else if (BLI_str_endswith(old_fcu_rna_path, "rotation")) {
+ fcu->rna_path = BLI_sprintfN("%s.%s", nodePath, "inputs[2].default_value");
+ }
+ else if (BLI_str_endswith(old_fcu_rna_path, "scale")) {
+ fcu->rna_path = BLI_sprintfN("%s.%s", nodePath, "inputs[3].default_value");
+ }
+ else if (minimumNode && BLI_str_endswith(old_fcu_rna_path, "max")) {
+ fcu->rna_path = BLI_sprintfN(
+ "nodes[\"%s\"].%s", minimumNode->name, "inputs[1].default_value");
+ }
+ else if (maximumNode && BLI_str_endswith(old_fcu_rna_path, "min")) {
+ fcu->rna_path = BLI_sprintfN(
+ "nodes[\"%s\"].%s", maximumNode->name, "inputs[1].default_value");
+ }
+
+ if (fcu->rna_path != old_fcu_rna_path) {
+ MEM_freeN(old_fcu_rna_path);
+ }
+ }
+ }
+
+ MEM_freeN(nodePath);
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Musgrave node now has a dimension property. This property should
+ * be initialized to 3 by default.
+ */
+static void update_musgrave_node_dimensions(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_MUSGRAVE) {
+ NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
+ tex->dimensions = 3;
+ }
+ }
+}
+
+/* The Color output of the Musgrave node has been removed. Previously, this
+ * output was just equal to the Fac output. To correct this, we move links
+ * from the Color output to the Fac output if they exist.
+ */
+static void update_musgrave_node_color_output(bNodeTree *ntree)
+{
+ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
+ if (link->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE) {
+ if (link->fromsock->type == SOCK_RGBA) {
+ link->fromsock = link->fromsock->next;
+ }
+ }
+ }
+}
+
+/* The Voronoi node now have a dimension property. This property should be
+ * initialized to 3 by default.
+ */
+static void update_voronoi_node_dimensions(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_VORONOI) {
+ NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
+ tex->dimensions = 3;
+ }
+ }
+}
+
+/* The F3 and F4 features of the Voronoi node have been removed.
+ * To correct this, we set the feature type to be F2 if it is F3
+ * or F4. The SHD_VORONOI_F3 and SHD_VORONOI_F4 enum values were
+ * 2 and 3 respectively.
+ */
+static void update_voronoi_node_f3_and_f4(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_VORONOI) {
+ NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
+ if (ELEM(tex->feature, 2, 3)) {
+ tex->feature = SHD_VORONOI_F2;
+ }
+ }
+ }
+}
+
+/* The Fac output of the Voronoi node has been removed. Previously, this
+ * output was the voronoi distance in the Intensity mode and the Cell ID
+ * in the Cell mode. To correct this, we update the identifier and name
+ * of the Fac socket such that it gets mapped to the Distance socket.
+ * This is supposed to work with update_voronoi_node_coloring.
+ */
+static void update_voronoi_node_fac_output(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_VORONOI) {
+ bNodeSocket *facOutput = BLI_findlink(&node->outputs, 1);
+ strcpy(facOutput->identifier, "Distance");
+ strcpy(facOutput->name, "Distance");
+ }
+ }
+}
+
+/* The Crackle feature of the Voronoi node has been removed. Previously,
+ * this feature returned the F2 distance minus the F1 distance. The
+ * crackle feature had an enum value of 4. To fix this we do the
+ * following:
+ *
+ * 1. The node feature is set to F1.
+ * 2. A new Voronoi node is added and its feature is set to F2.
+ * 3. The properties, input values, and connections are copied
+ * from the node to the new Voronoi node so that they match
+ * exactly.
+ * 4. A Subtract node is added.
+ * 5. The outputs of the F1 and F2 voronoi are connected to
+ * the inputs of the subtract node.
+ * 6. The output of the subtract node is connected to the
+ * appropriate sockets.
+ *
+ */
+static void update_voronoi_node_crackle(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_VORONOI) {
+ NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
+ bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
+ bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
+ if (tex->feature == 4 && (socket_is_used(sockDistance) || socket_is_used(sockColor))) {
+ tex->feature = SHD_VORONOI_F1;
+
+ bNode *voronoiNode = nodeAddStaticNode(NULL, ntree, SH_NODE_TEX_VORONOI);
+ NodeTexVoronoi *texVoronoi = (NodeTexVoronoi *)voronoiNode->storage;
+ texVoronoi->feature = SHD_VORONOI_F2;
+ texVoronoi->distance = tex->distance;
+ texVoronoi->dimensions = 3;
+ voronoiNode->locx = node->locx + node->width + 20.0f;
+ voronoiNode->locy = node->locy;
+
+ bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
+ bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
+ bNodeSocket *sockExponent = nodeFindSocket(node, SOCK_IN, "Exponent");
+ bNodeSocket *sockVoronoiVector = nodeFindSocket(voronoiNode, SOCK_IN, "Vector");
+ bNodeSocket *sockVoronoiScale = nodeFindSocket(voronoiNode, SOCK_IN, "Scale");
+ bNodeSocket *sockVoronoiExponent = nodeFindSocket(voronoiNode, SOCK_IN, "Exponent");
+ if (sockVector->link) {
+ nodeAddLink(ntree,
+ sockVector->link->fromnode,
+ sockVector->link->fromsock,
+ voronoiNode,
+ sockVoronoiVector);
+ }
+ *cycles_node_socket_float_value(sockVoronoiScale) = *cycles_node_socket_float_value(
+ sockScale);
+ if (sockScale->link) {
+ nodeAddLink(ntree,
+ sockScale->link->fromnode,
+ sockScale->link->fromsock,
+ voronoiNode,
+ sockVoronoiScale);
+ }
+ *cycles_node_socket_float_value(sockVoronoiExponent) = *cycles_node_socket_float_value(
+ sockExponent);
+ if (sockExponent->link) {
+ nodeAddLink(ntree,
+ sockExponent->link->fromnode,
+ sockExponent->link->fromsock,
+ voronoiNode,
+ sockVoronoiExponent);
+ }
+
+ bNode *subtractNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
+ subtractNode->custom1 = NODE_MATH_SUBTRACT;
+ subtractNode->locx = voronoiNode->locx + voronoiNode->width + 20.0f;
+ subtractNode->locy = voronoiNode->locy;
+ bNodeSocket *sockSubtractOutValue = nodeFindSocket(subtractNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromnode == node) {
+ nodeAddLink(ntree, subtractNode, sockSubtractOutValue, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+
+ bNodeSocket *sockDistanceF1 = nodeFindSocket(node, SOCK_OUT, "Distance");
+ bNodeSocket *sockDistanceF2 = nodeFindSocket(voronoiNode, SOCK_OUT, "Distance");
+ bNodeSocket *sockSubtractA = BLI_findlink(&subtractNode->inputs, 0);
+ bNodeSocket *sockSubtractB = BLI_findlink(&subtractNode->inputs, 1);
+
+ nodeAddLink(ntree, node, sockDistanceF1, subtractNode, sockSubtractB);
+ nodeAddLink(ntree, voronoiNode, sockDistanceF2, subtractNode, sockSubtractA);
+
+ need_update = true;
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/**
+ * The coloring property of the Voronoi node was removed. Previously,
+ * if the coloring enum was set to Intensity (0), the voronoi distance
+ * was returned in all outputs, otherwise, the Cell ID was returned.
+ * Since we remapped the Fac output in update_voronoi_node_fac_output,
+ * then to fix this, we relink the Color output to the Distance
+ * output if coloring was set to 0, and the other way around otherwise.
+ */
+static void update_voronoi_node_coloring(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ bNode *node = link->fromnode;
+ if (node && node->type == SH_NODE_TEX_VORONOI) {
+ NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
+ if (tex->coloring == 0) {
+ bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
+ if (link->fromsock == sockColor) {
+ bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
+ nodeAddLink(ntree, node, sockDistance, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ need_update = true;
+ }
+ }
+ else {
+ bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
+ if (link->fromsock == sockDistance) {
+ bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
+ nodeAddLink(ntree, node, sockColor, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ need_update = true;
+ }
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* Previously, the output euclidean distance was actually the squared
+ * euclidean distance. To fix this, we square the the output distance
+ * socket if the distance metric is set to SHD_VORONOI_EUCLIDEAN.
+ */
+static void update_voronoi_node_square_distance(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_VORONOI) {
+ NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
+ bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
+ if (tex->distance == SHD_VORONOI_EUCLIDEAN &&
+ (tex->feature == SHD_VORONOI_F1 || tex->feature == SHD_VORONOI_F2) &&
+ socket_is_used(sockDistance)) {
+ bNode *multiplyNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
+ multiplyNode->custom1 = NODE_MATH_MULTIPLY;
+ multiplyNode->locx = node->locx + node->width + 20.0f;
+ multiplyNode->locy = node->locy;
+
+ bNodeSocket *sockValue = nodeFindSocket(multiplyNode, SOCK_OUT, "Value");
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockDistance) {
+ nodeAddLink(ntree, multiplyNode, sockValue, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+
+ bNodeSocket *sockMultiplyA = BLI_findlink(&multiplyNode->inputs, 0);
+ bNodeSocket *sockMultiplyB = BLI_findlink(&multiplyNode->inputs, 1);
+
+ nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyA);
+ nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyB);
+
+ need_update = true;
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
{
/* Particle shape shared with Eevee. */
@@ -797,6 +1219,25 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
}
FOREACH_NODETREE_END;
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_musgrave_node_color_output(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_voronoi_node_f3_and_f4(ntree);
+ update_voronoi_node_fac_output(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}
void do_versions_after_linking_cycles(Main *bmain)
@@ -928,4 +1369,43 @@ void do_versions_after_linking_cycles(Main *bmain)
}
FOREACH_NODETREE_END;
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 7)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_noise_node_dimensions(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 8)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_mapping_node_inputs_and_properties(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_musgrave_node_dimensions(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_voronoi_node_dimensions(ntree);
+ update_voronoi_node_crackle(ntree);
+ update_voronoi_node_coloring(ntree);
+ update_voronoi_node_square_distance(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}