Blender  V2.93
versioning_cycles.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 /* allow readfile to use deprecated functionality */
22 #define DNA_DEPRECATED_ALLOW
23 
24 #include <float.h>
25 #include <string.h>
26 
27 #include "BLI_listbase.h"
28 #include "BLI_math.h"
29 #include "BLI_string.h"
30 #include "BLI_utildefines.h"
31 
32 #include "DNA_anim_types.h"
33 #include "DNA_camera_types.h"
34 #include "DNA_color_types.h"
35 #include "DNA_light_types.h"
36 #include "DNA_node_types.h"
37 #include "DNA_particle_types.h"
38 
39 #include "BKE_animsys.h"
40 #include "BKE_colortools.h"
41 #include "BKE_idprop.h"
42 #include "BKE_main.h"
43 #include "BKE_node.h"
44 
45 #include "MEM_guardedalloc.h"
46 
47 #include "IMB_colormanagement.h"
48 
49 #include "BLO_readfile.h"
50 #include "readfile.h"
51 
52 static bool socket_is_used(bNodeSocket *sock)
53 {
54  return sock->flag & SOCK_IN_USE;
55 }
56 
58 {
59  bNodeSocketValueFloat *socket_data = socket->default_value;
60  return &socket_data->value;
61 }
62 
64 {
65  bNodeSocketValueRGBA *socket_data = socket->default_value;
66  return socket_data->value;
67 }
68 
70 {
71  bNodeSocketValueVector *socket_data = socket->default_value;
72  return socket_data->value;
73 }
74 
76 {
77  IDProperty *idprop = IDP_GetProperties(id, false);
78  return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles", IDP_GROUP) : NULL;
79 }
80 
82 {
83  IDProperty *idprop = view_layer->id_properties;
84  return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles", IDP_GROUP) : NULL;
85 }
86 
87 static float cycles_property_float(IDProperty *idprop, const char *name, float default_value)
88 {
89  IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_FLOAT);
90  return (prop) ? IDP_Float(prop) : default_value;
91 }
92 
93 static int cycles_property_int(IDProperty *idprop, const char *name, int default_value)
94 {
95  IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
96  return (prop) ? IDP_Int(prop) : default_value;
97 }
98 
99 static void cycles_property_int_set(IDProperty *idprop, const char *name, int value)
100 {
101  IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
102  if (prop) {
103  IDP_Int(prop) = value;
104  }
105  else {
106  IDPropertyTemplate val = {0};
107  val.i = value;
108  IDP_AddToGroup(idprop, IDP_New(IDP_INT, &val, name));
109  }
110 }
111 
112 static bool cycles_property_boolean(IDProperty *idprop, const char *name, bool default_value)
113 {
114  return cycles_property_int(idprop, name, default_value);
115 }
116 
117 static void cycles_property_boolean_set(IDProperty *idprop, const char *name, bool value)
118 {
119  cycles_property_int_set(idprop, name, value);
120 }
121 
123 {
124  bool need_update = false;
125 
126  /* Iterate backwards from end so we don't encounter newly added links. */
127  bNodeLink *prevlink;
128  for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
129  prevlink = link->prev;
130 
131  /* Detect link to replace. */
132  bNode *fromnode = link->fromnode;
133  bNodeSocket *fromsock = link->fromsock;
134  bNode *tonode = link->tonode;
135  bNodeSocket *tosock = link->tosock;
136 
137  if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && fromnode->type != SH_NODE_DISPLACEMENT &&
138  STREQ(tosock->identifier, "Displacement"))) {
139  continue;
140  }
141 
142  /* Replace link with displacement node. */
143  nodeRemLink(ntree, link);
144 
145  /* Add displacement node. */
147  node->locx = 0.5f * (fromnode->locx + tonode->locx);
148  node->locy = 0.5f * (fromnode->locy + tonode->locy);
149 
150  bNodeSocket *scale_socket = nodeFindSocket(node, SOCK_IN, "Scale");
151  bNodeSocket *midlevel_socket = nodeFindSocket(node, SOCK_IN, "Midlevel");
152  bNodeSocket *height_socket = nodeFindSocket(node, SOCK_IN, "Height");
153  bNodeSocket *displacement_socket = nodeFindSocket(node, SOCK_OUT, "Displacement");
154 
155  /* Set default values for compatibility. */
156  *cycles_node_socket_float_value(scale_socket) = 0.1f;
157  *cycles_node_socket_float_value(midlevel_socket) = 0.0f;
158 
159  /* Link to input and material output node. */
160  nodeAddLink(ntree, fromnode, fromsock, node, height_socket);
161  nodeAddLink(ntree, node, displacement_socket, tonode, tosock);
162 
163  need_update = true;
164  }
165 
166  if (need_update) {
168  }
169 }
170 
172 {
173  if (node->type == SH_NODE_DISPLACEMENT) {
174  if (node->custom1 != SHD_SPACE_WORLD) {
175  node->custom1 = SHD_SPACE_OBJECT;
176  }
177  }
178  else if (node->type == SH_NODE_BSDF_PRINCIPLED) {
179  if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK) {
180  node->custom2 = SHD_SUBSURFACE_BURLEY;
181  }
182  }
183 }
184 
186 {
187  return ELEM(node->type,
192 }
193 
195 {
196  bool need_update = false;
197 
198  /* Update default values */
200  if (node_has_roughness(node)) {
201  bNodeSocket *roughness_input = nodeFindSocket(node, SOCK_IN, "Roughness");
202  float *roughness_value = cycles_node_socket_float_value(roughness_input);
203  *roughness_value = sqrtf(max_ff(*roughness_value, 0.0f));
204  }
205  }
206 
207  /* Iterate backwards from end so we don't encounter newly added links. */
208  bNodeLink *prevlink;
209  for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
210  prevlink = link->prev;
211 
212  /* Detect link to replace. */
213  bNode *fromnode = link->fromnode;
214  bNodeSocket *fromsock = link->fromsock;
215  bNode *tonode = link->tonode;
216  bNodeSocket *tosock = link->tosock;
217 
218  if (!(node_has_roughness(tonode) && STREQ(tosock->identifier, "Roughness"))) {
219  continue;
220  }
221 
222  /* Replace links with sqrt node */
223  nodeRemLink(ntree, link);
224 
225  /* Add sqrt node. */
227  node->custom1 = NODE_MATH_POWER;
228  node->locx = 0.5f * (fromnode->locx + tonode->locx);
229  node->locy = 0.5f * (fromnode->locy + tonode->locy);
230 
231  /* Link to input and material output node. */
232  *cycles_node_socket_float_value(node->inputs.last) = 0.5f;
233  nodeAddLink(ntree, fromnode, fromsock, node, node->inputs.first);
234  nodeAddLink(ntree, node, node->outputs.first, tonode, tosock);
235 
236  need_update = true;
237  }
238 
239  if (need_update) {
241  }
242 }
243 
245 {
246  /* Flip euler order of mapping shader node */
247  if (node->type == SH_NODE_MAPPING && node->storage) {
248  TexMapping *texmap = node->storage;
249 
250  float quat[4];
251  eulO_to_quat(quat, texmap->rot, EULER_ORDER_ZYX);
252  quat_to_eulO(texmap->rot, EULER_ORDER_XYZ, quat);
253  }
254 }
255 
257 {
258  /* Remap values of vector curve node from normalized to absolute values */
259  if (node->type == SH_NODE_CURVE_VEC && node->storage) {
260  CurveMapping *mapping = node->storage;
261  mapping->flag &= ~CUMA_DO_CLIP;
262 
263  for (int curve_index = 0; curve_index < CM_TOT; curve_index++) {
264  CurveMap *cm = &mapping->cm[curve_index];
265  if (cm->curve) {
266  for (int i = 0; i < cm->totpoint; i++) {
267  cm->curve[i].x = (cm->curve[i].x * 2.0f) - 1.0f;
268  cm->curve[i].y = (cm->curve[i].y - 0.5f) * 2.0f;
269  }
270  }
271  }
272 
274  }
275 }
276 
278 {
279  bool need_update = false;
280 
281  /* Set default values. */
283  if (node->type == SH_NODE_AMBIENT_OCCLUSION) {
284  node->custom1 = 1; /* samples */
285  node->custom2 &= ~SHD_AO_LOCAL;
286 
287  bNodeSocket *distance_socket = nodeFindSocket(node, SOCK_IN, "Distance");
288  *cycles_node_socket_float_value(distance_socket) = 0.0f;
289  }
290  }
291 
292  /* Iterate backwards from end so we don't encounter newly added links. */
293  bNodeLink *prevlink;
294  for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
295  prevlink = link->prev;
296 
297  /* Detect link to replace. */
298  bNode *fromnode = link->fromnode;
299  bNode *tonode = link->tonode;
300  bNodeSocket *tosock = link->tosock;
301 
302  if (!(fromnode->type == SH_NODE_AMBIENT_OCCLUSION)) {
303  continue;
304  }
305 
306  /* Replace links with color socket. */
307  nodeRemLink(ntree, link);
308  bNodeSocket *color_socket = nodeFindSocket(fromnode, SOCK_OUT, "Color");
309  nodeAddLink(ntree, fromnode, color_socket, tonode, tosock);
310 
311  need_update = true;
312  }
313 
314  if (need_update) {
316  }
317 }
318 
320 {
321  if (node->id == NULL) {
322  return;
323  }
324 
325  int color_space;
326  if (node->type == SH_NODE_TEX_IMAGE && node->storage) {
327  NodeTexImage *tex = node->storage;
328  color_space = tex->color_space;
329  }
330  else if (node->type == SH_NODE_TEX_ENVIRONMENT && node->storage) {
331  NodeTexEnvironment *tex = node->storage;
332  color_space = tex->color_space;
333  }
334  else {
335  return;
336  }
337 
338  const int SHD_COLORSPACE_NONE = 0;
339  Image *image = (Image *)node->id;
340  if (color_space == SHD_COLORSPACE_NONE) {
343  }
344 }
345 
346 static void light_emission_node_to_energy(Light *light, float *energy, float color[3])
347 {
348  *energy = 1.0;
349  copy_v3_fl(color, 1.0f);
350 
351  /* If nodetree has animation or drivers, don't try to convert. */
352  bNodeTree *ntree = light->nodetree;
353  if (ntree == NULL || ntree->adt) {
354  return;
355  }
356 
357  /* Find emission node */
359  if (output_node == NULL) {
360  return;
361  }
362 
363  bNode *emission_node = NULL;
364  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
365  if (link->tonode == output_node && link->fromnode->type == SH_NODE_EMISSION) {
366  emission_node = link->fromnode;
367  break;
368  }
369  }
370 
371  if (emission_node == NULL) {
372  return;
373  }
374 
375  /* Don't convert if anything is linked */
376  bNodeSocket *strength_socket = nodeFindSocket(emission_node, SOCK_IN, "Strength");
377  bNodeSocket *color_socket = nodeFindSocket(emission_node, SOCK_IN, "Color");
378 
379  if ((strength_socket->flag & SOCK_IN_USE) || (color_socket->flag & SOCK_IN_USE)) {
380  return;
381  }
382 
383  float *strength_value = cycles_node_socket_float_value(strength_socket);
384  float *color_value = cycles_node_socket_rgba_value(color_socket);
385 
386  *energy = *strength_value;
387  copy_v3_v3(color, color_value);
388 
389  *strength_value = 1.0f;
390  copy_v4_fl(color_value, 1.0f);
391  light->use_nodes = false;
392 }
393 
394 static void light_emission_unify(Light *light, const char *engine)
395 {
396  if (light->type != LA_SUN) {
397  light->energy *= 100.0f;
398  }
399 
400  /* Attempt to extract constant energy and color from nodes. */
401  bool use_nodes = light->use_nodes;
402  float energy, color[3];
403  light_emission_node_to_energy(light, &energy, color);
404 
405  if (STREQ(engine, "CYCLES")) {
406  if (use_nodes) {
407  /* Energy extracted from nodes */
408  light->energy = energy;
409  copy_v3_v3(&light->r, color);
410  }
411  else {
412  /* Default cycles multipliers if there are no nodes */
413  if (light->type == LA_SUN) {
414  light->energy = 1.0f;
415  }
416  else {
417  light->energy = 100.0f;
418  }
419  }
420  }
421  else {
422  /* Disable nodes if scene was configured for Eevee */
423  light->use_nodes = false;
424  }
425 }
426 
427 /* The B input of the Math node is no longer used for single-operand operators.
428  * Previously, if the B input was linked and the A input was not, the B input
429  * was used as the input of the operator. To correct this, we move the link
430  * from B to A if B is linked and A is not.
431  */
433 {
434  bool need_update = false;
435 
437  if (node->type == SH_NODE_MATH) {
438  if (ELEM(node->custom1,
451  bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
452  bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
453  if (!sockA->link && sockB->link) {
454  nodeAddLink(ntree, sockB->link->fromnode, sockB->link->fromsock, node, sockA);
455  nodeRemLink(ntree, sockB->link);
456  need_update = true;
457  }
458  }
459  }
460  }
461 
462  if (need_update) {
464  }
465 }
466 
467 /* The Value output of the Vector Math node is no longer available in the Add
468  * and Subtract operators. Previously, this Value output was computed from the
469  * Vector output V as follows:
470  *
471  * Value = (abs(V.x) + abs(V.y) + abs(V.z)) / 3
472  *
473  * Or more compactly using vector operators:
474  *
475  * Value = dot(abs(V), (1 / 3, 1 / 3, 1 / 3))
476  *
477  * To correct this, if the Value output was used, we are going to compute
478  * it using the second equation by adding an absolute and a dot node, and
479  * then connect them appropriately.
480  */
482 {
483  bool need_update = false;
484 
486  if (node->type == SH_NODE_VECTOR_MATH) {
487  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
488  if (socket_is_used(sockOutValue) &&
490 
493  absNode->locx = node->locx + node->width + 20.0f;
494  absNode->locy = node->locy;
495 
498  dotNode->locx = absNode->locx + absNode->width + 20.0f;
499  dotNode->locy = absNode->locy;
500  bNodeSocket *sockDotB = BLI_findlink(&dotNode->inputs, 1);
501  bNodeSocket *sockDotOutValue = nodeFindSocket(dotNode, SOCK_OUT, "Value");
502  copy_v3_fl(cycles_node_socket_vector_value(sockDotB), 1 / 3.0f);
503 
505  if (link->fromsock == sockOutValue) {
506  nodeAddLink(ntree, dotNode, sockDotOutValue, link->tonode, link->tosock);
507  nodeRemLink(ntree, link);
508  }
509  }
510 
511  bNodeSocket *sockAbsA = BLI_findlink(&absNode->inputs, 0);
512  bNodeSocket *sockDotA = BLI_findlink(&dotNode->inputs, 0);
513  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
514  bNodeSocket *sockAbsOutVector = nodeFindSocket(absNode, SOCK_OUT, "Vector");
515 
516  nodeAddLink(ntree, node, sockOutVector, absNode, sockAbsA);
517  nodeAddLink(ntree, absNode, sockAbsOutVector, dotNode, sockDotA);
518 
519  need_update = true;
520  }
521  }
522  }
523 
524  if (need_update) {
526  }
527 }
528 
529 /* The Vector output of the Vector Math node is no longer available in the Dot
530  * Product operator. Previously, this Vector was always zero initialized. To
531  * correct this, we zero out any socket the Vector Output was connected to.
532  */
534 {
535  bool need_update = false;
536 
538  if (node->type == SH_NODE_VECTOR_MATH) {
539  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
540  if (socket_is_used(sockOutVector) && node->custom1 == NODE_VECTOR_MATH_DOT_PRODUCT) {
542  if (link->fromsock == sockOutVector) {
543  switch (link->tosock->type) {
544  case SOCK_FLOAT:
545  *cycles_node_socket_float_value(link->tosock) = 0.0f;
546  break;
547  case SOCK_VECTOR:
548  copy_v3_fl(cycles_node_socket_vector_value(link->tosock), 0.0f);
549  break;
550  case SOCK_RGBA:
551  copy_v4_fl(cycles_node_socket_rgba_value(link->tosock), 0.0f);
552  break;
553  }
554  nodeRemLink(ntree, link);
555  }
556  }
557  need_update = true;
558  }
559  }
560  }
561 
562  if (need_update) {
564  }
565 }
566 
567 /* Previously, the Vector output of the cross product operator was normalized.
568  * To correct this, a Normalize node is added to normalize the output if used.
569  * Moreover, the Value output was removed. This Value was equal to the length
570  * of the cross product. To correct this, a Length node is added if needed.
571  */
573 {
574  bool need_update = false;
575 
577  if (node->type == SH_NODE_VECTOR_MATH) {
578  if (node->custom1 == NODE_VECTOR_MATH_CROSS_PRODUCT) {
579  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
580  if (socket_is_used(sockOutVector)) {
582  normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
583  normalizeNode->locx = node->locx + node->width + 20.0f;
584  normalizeNode->locy = node->locy;
585  bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
586 
588  if (link->fromsock == sockOutVector) {
589  nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
590  nodeRemLink(ntree, link);
591  }
592  }
593  bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
594  nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
595 
596  need_update = true;
597  }
598 
599  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
600  if (socket_is_used(sockOutValue)) {
602  lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
603  lengthNode->locx = node->locx + node->width + 20.0f;
604  if (socket_is_used(sockOutVector)) {
605  lengthNode->locy = node->locy - lengthNode->height - 20.0f;
606  }
607  else {
608  lengthNode->locy = node->locy;
609  }
610  bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
611 
613  if (link->fromsock == sockOutValue) {
614  nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
615  nodeRemLink(ntree, link);
616  }
617  }
618  bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
619  nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
620 
621  need_update = true;
622  }
623  }
624  }
625  }
626 
627  if (need_update) {
629  }
630 }
631 
632 /* The Value output of the Vector Math node is no longer available in the
633  * Normalize operator. This Value output was equal to the length of the
634  * the input vector A. To correct this, we either add a Length node or
635  * convert the Normalize node into a Length node, depending on if the
636  * Vector output is needed.
637  */
639 {
640  bool need_update = false;
641 
643  if (node->type == SH_NODE_VECTOR_MATH) {
644  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
645  if (node->custom1 == NODE_VECTOR_MATH_NORMALIZE && socket_is_used(sockOutValue)) {
646  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
647  if (socket_is_used(sockOutVector)) {
649  lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
650  lengthNode->locx = node->locx + node->width + 20.0f;
651  lengthNode->locy = node->locy;
652  bNodeSocket *sockLengthValue = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
653 
655  if (link->fromsock == sockOutValue) {
656  nodeAddLink(ntree, lengthNode, sockLengthValue, link->tonode, link->tosock);
657  nodeRemLink(ntree, link);
658  }
659  }
660  bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
661  bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
662  if (sockA->link) {
663  bNodeLink *link = sockA->link;
664  nodeAddLink(ntree, link->fromnode, link->fromsock, lengthNode, sockLengthA);
665  }
666  else {
669  }
670 
671  need_update = true;
672  }
673  else {
674  node->custom1 = NODE_VECTOR_MATH_LENGTH;
675  }
676  }
677  }
678  }
679  if (need_update) {
681  }
682 }
683 
684 /* The Vector Math operator types didn't have an enum, but rather, their
685  * values were hard coded into the code. After the enum was created and
686  * after more vector operators were added, the hard coded values needs
687  * to be remapped to their correct enum values. To fix this, we remap
688  * the values according to the following rules:
689  *
690  * Dot Product Operator : 3 -> 7
691  * Normalize Operator : 5 -> 11
692  *
693  * Additionally, since the Average operator was removed, it is assigned
694  * a value of -1 just to be identified later in the versioning code:
695  *
696  * Average Operator : 2 -> -1
697  *
698  */
700 {
702  if (node->type == SH_NODE_VECTOR_MATH) {
703  switch (node->custom1) {
704  case 2:
705  node->custom1 = -1;
706  break;
707  case 3:
708  node->custom1 = 7;
709  break;
710  case 5:
711  node->custom1 = 11;
712  break;
713  }
714  }
715  }
716 }
717 
718 /* The Average operator is no longer available in the Vector Math node.
719  * The Vector output was equal to the normalized sum of input vectors while
720  * the Value output was equal to the length of the sum of input vectors.
721  * To correct this, we convert the node into an Add node and add a length
722  * node or a normalize node if needed.
723  */
725 {
726  bool need_update = false;
727 
729  if (node->type == SH_NODE_VECTOR_MATH) {
730  /* See update_vector_math_node_operators_enum_mapping. */
731  if (node->custom1 == -1) {
732  node->custom1 = NODE_VECTOR_MATH_ADD;
733  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
734  if (socket_is_used(sockOutVector)) {
736  normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
737  normalizeNode->locx = node->locx + node->width + 20.0f;
738  normalizeNode->locy = node->locy;
739  bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
740 
742  if (link->fromsock == sockOutVector) {
743  nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
744  nodeRemLink(ntree, link);
745  }
746  }
747  bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
748  nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
749 
750  need_update = true;
751  }
752 
753  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
754  if (socket_is_used(sockOutValue)) {
756  lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
757  lengthNode->locx = node->locx + node->width + 20.0f;
758  if (socket_is_used(sockOutVector)) {
759  lengthNode->locy = node->locy - lengthNode->height - 20.0f;
760  }
761  else {
762  lengthNode->locy = node->locy;
763  }
764  bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
765 
767  if (link->fromsock == sockOutValue) {
768  nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
769  nodeRemLink(ntree, link);
770  }
771  }
772  bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
773  nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
774 
775  need_update = true;
776  }
777  }
778  }
779  }
780 
781  if (need_update) {
783  }
784 }
785 
786 /* The Noise node now have a dimension property. This property should be
787  * initialized to 3 by default.
788  */
790 {
792  if (node->type == SH_NODE_TEX_NOISE && node->storage) {
793  NodeTexNoise *tex = (NodeTexNoise *)node->storage;
794  tex->dimensions = 3;
795  }
796  }
797 }
798 
799 /* This structure is only used to pass data to
800  * update_mapping_node_fcurve_rna_path_callback.
801  */
802 typedef struct {
803  char *nodePath;
807 
808 /* This callback function is used by update_mapping_node_inputs_and_properties.
809  * It is executed on every fcurve in the nodetree id updating its RNA paths. The
810  * paths needs to be updated because the node properties became inputs.
811  *
812  * nodes["Mapping"].translation --> nodes["Mapping"].inputs[1].default_value
813  * nodes["Mapping"].rotation --> nodes["Mapping"].inputs[2].default_value
814  * nodes["Mapping"].scale --> nodes["Mapping"].inputs[3].default_value
815  * nodes["Mapping"].max --> nodes["Maximum"].inputs[1].default_value
816  * nodes["Mapping"].min --> nodes["Minimum"].inputs[1].default_value
817  *
818  * The fcurve can be that of any node or property in the nodetree, so we only
819  * update if the rna path starts with the rna path of the mapping node and
820  * doesn't end with "default_value", that is, not the Vector input.
821  */
823  FCurve *fcurve,
824  void *_data)
825 {
827  if (!STRPREFIX(fcurve->rna_path, data->nodePath) ||
828  BLI_str_endswith(fcurve->rna_path, "default_value")) {
829  return;
830  }
831  char *old_fcurve_rna_path = fcurve->rna_path;
832 
833  if (BLI_str_endswith(old_fcurve_rna_path, "translation")) {
834  fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[1].default_value");
835  }
836  else if (BLI_str_endswith(old_fcurve_rna_path, "rotation")) {
837  fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[2].default_value");
838  }
839  else if (BLI_str_endswith(old_fcurve_rna_path, "scale")) {
840  fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[3].default_value");
841  }
842  else if (data->minimumNode && BLI_str_endswith(old_fcurve_rna_path, "max")) {
843  char node_name_esc[sizeof(data->minimumNode->name) * 2];
844  BLI_str_escape(node_name_esc, data->minimumNode->name, sizeof(node_name_esc));
845  fcurve->rna_path = BLI_sprintfN("nodes[\"%s\"].%s", node_name_esc, "inputs[1].default_value");
846  }
847  else if (data->maximumNode && BLI_str_endswith(old_fcurve_rna_path, "min")) {
848  char node_name_esc[sizeof(data->maximumNode->name) * 2];
849  BLI_str_escape(node_name_esc, data->maximumNode->name, sizeof(node_name_esc));
850  fcurve->rna_path = BLI_sprintfN("nodes[\"%s\"].%s", node_name_esc, "inputs[1].default_value");
851  }
852 
853  if (fcurve->rna_path != old_fcurve_rna_path) {
854  MEM_freeN(old_fcurve_rna_path);
855  }
856 }
857 
858 /* The Mapping node has been rewritten to support dynamic inputs. Previously,
859  * the transformation information was stored in a TexMapping struct in the
860  * node->storage member of bNode. Currently, the transformation information
861  * is stored in input sockets. To correct this, we transfer the information
862  * from the TexMapping struct to the input sockets.
863  *
864  * Additionally, the Minimum and Maximum properties are no longer available
865  * in the node. To correct this, a Vector Minimum and/or a Vector Maximum
866  * nodes are added if needed.
867  *
868  * Finally, the TexMapping struct is freed and node->storage is set to NULL.
869  *
870  * Since the RNA paths of the properties changed, we also have to update the
871  * rna_path of the FCurves if they exist. To do that, we loop over FCurves
872  * and check if they control a property of the node, if they do, we update
873  * the path to be that of the corresponding socket in the node or the added
874  * minimum/maximum node.
875  *
876  */
878 {
879  bool need_update = false;
880 
882  /* If node->storage is NULL, then conversion has already taken place.
883  * This can happen if a file with the new mapping node [saved from (2, 81, 8) or newer]
884  * is opened in a blender version prior to (2, 81, 8) and saved from there again. */
885  if (node->type == SH_NODE_MAPPING && node->storage) {
886  TexMapping *mapping = (TexMapping *)node->storage;
887  node->custom1 = mapping->type;
888  node->width = 140.0f;
889 
890  bNodeSocket *sockLocation = nodeFindSocket(node, SOCK_IN, "Location");
891  copy_v3_v3(cycles_node_socket_vector_value(sockLocation), mapping->loc);
892  bNodeSocket *sockRotation = nodeFindSocket(node, SOCK_IN, "Rotation");
893  copy_v3_v3(cycles_node_socket_vector_value(sockRotation), mapping->rot);
894  bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
895  copy_v3_v3(cycles_node_socket_vector_value(sockScale), mapping->size);
896 
897  bNode *maximumNode = NULL;
898  if (mapping->flag & TEXMAP_CLIP_MIN) {
900  maximumNode->custom1 = NODE_VECTOR_MATH_MAXIMUM;
901  if (mapping->flag & TEXMAP_CLIP_MAX) {
902  maximumNode->locx = node->locx + (node->width + 20.0f) * 2.0f;
903  }
904  else {
905  maximumNode->locx = node->locx + node->width + 20.0f;
906  }
907  maximumNode->locy = node->locy;
908  bNodeSocket *sockMaximumB = BLI_findlink(&maximumNode->inputs, 1);
909  copy_v3_v3(cycles_node_socket_vector_value(sockMaximumB), mapping->min);
910  bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector");
911 
913  if (link->fromsock == sockMappingResult) {
914  bNodeSocket *sockMaximumResult = nodeFindSocket(maximumNode, SOCK_OUT, "Vector");
915  nodeAddLink(ntree, maximumNode, sockMaximumResult, link->tonode, link->tosock);
916  nodeRemLink(ntree, link);
917  }
918  }
919  if (!(mapping->flag & TEXMAP_CLIP_MAX)) {
920  bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0);
921  nodeAddLink(ntree, node, sockMappingResult, maximumNode, sockMaximumA);
922  }
923 
924  need_update = true;
925  }
926 
927  bNode *minimumNode = NULL;
928  if (mapping->flag & TEXMAP_CLIP_MAX) {
930  minimumNode->custom1 = NODE_VECTOR_MATH_MINIMUM;
931  minimumNode->locx = node->locx + node->width + 20.0f;
932  minimumNode->locy = node->locy;
933  bNodeSocket *sockMinimumB = BLI_findlink(&minimumNode->inputs, 1);
934  copy_v3_v3(cycles_node_socket_vector_value(sockMinimumB), mapping->max);
935 
936  bNodeSocket *sockMinimumResult = nodeFindSocket(minimumNode, SOCK_OUT, "Vector");
937  bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector");
938 
939  if (maximumNode) {
940  bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0);
941  nodeAddLink(ntree, minimumNode, sockMinimumResult, maximumNode, sockMaximumA);
942  }
943  else {
945  if (link->fromsock == sockMappingResult) {
946  nodeAddLink(ntree, minimumNode, sockMinimumResult, link->tonode, link->tosock);
947  nodeRemLink(ntree, link);
948  }
949  }
950  }
951  bNodeSocket *sockMinimumA = BLI_findlink(&minimumNode->inputs, 0);
952  nodeAddLink(ntree, node, sockMappingResult, minimumNode, sockMinimumA);
953 
954  need_update = true;
955  }
956 
957  MEM_freeN(node->storage);
958  node->storage = NULL;
959 
960  char node_name_esc[sizeof(node->name) * 2];
961  BLI_str_escape(node_name_esc, node->name, sizeof(node_name_esc));
962 
963  char *nodePath = BLI_sprintfN("nodes[\"%s\"]", node_name_esc);
964  MappingNodeFCurveCallbackData data = {nodePath, minimumNode, maximumNode};
966  MEM_freeN(nodePath);
967  }
968  }
969 
970  if (need_update) {
972  }
973 }
974 
975 /* The Musgrave node now has a dimension property. This property should
976  * be initialized to 3 by default.
977  */
979 {
981  if (node->type == SH_NODE_TEX_MUSGRAVE && node->storage) {
982  NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
983  tex->dimensions = 3;
984  }
985  }
986 }
987 
988 /* The Color output of the Musgrave node has been removed. Previously, this
989  * output was just equal to the Fac output. To correct this, we move links
990  * from the Color output to the Fac output if they exist.
991  */
993 {
994  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
995  if (link->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE) {
996  if (link->fromsock->type == SOCK_RGBA) {
997  link->fromsock = link->fromsock->next;
998  }
999  }
1000  }
1001 }
1002 
1003 /* The Voronoi node now have a dimension property. This property should be
1004  * initialized to 3 by default.
1005  */
1007 {
1009  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1010  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1011  tex->dimensions = 3;
1012  }
1013  }
1014 }
1015 
1016 /* The F3 and F4 features of the Voronoi node have been removed.
1017  * To correct this, we set the feature type to be F2 if it is F3
1018  * or F4. The SHD_VORONOI_F3 and SHD_VORONOI_F4 enum values were
1019  * 2 and 3 respectively.
1020  */
1022 {
1024  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1025  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1026  if (ELEM(tex->feature, 2, 3)) {
1027  tex->feature = SHD_VORONOI_F2;
1028  }
1029  }
1030  }
1031 }
1032 
1033 /* The Fac output of the Voronoi node has been removed. Previously, this
1034  * output was the voronoi distance in the Intensity mode and the Cell ID
1035  * in the Cell mode. To correct this, we update the identifier and name
1036  * of the Fac socket such that it gets mapped to the Distance socket.
1037  * This is supposed to work with update_voronoi_node_coloring.
1038  */
1040 {
1042  if (node->type == SH_NODE_TEX_VORONOI) {
1043  bNodeSocket *facOutput = BLI_findlink(&node->outputs, 1);
1044  strcpy(facOutput->identifier, "Distance");
1045  strcpy(facOutput->name, "Distance");
1046  }
1047  }
1048 }
1049 
1050 /* The Crackle feature of the Voronoi node has been removed. Previously,
1051  * this feature returned the F2 distance minus the F1 distance. The
1052  * crackle feature had an enum value of 4. To fix this we do the
1053  * following:
1054  *
1055  * 1. The node feature is set to F1.
1056  * 2. A new Voronoi node is added and its feature is set to F2.
1057  * 3. The properties, input values, and connections are copied
1058  * from the node to the new Voronoi node so that they match
1059  * exactly.
1060  * 4. A Subtract node is added.
1061  * 5. The outputs of the F1 and F2 voronoi are connected to
1062  * the inputs of the subtract node.
1063  * 6. The output of the subtract node is connected to the
1064  * appropriate sockets.
1065  *
1066  */
1068 {
1069  bool need_update = false;
1070 
1072  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1073  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1074  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1075  bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
1076  if (tex->feature == 4 && (socket_is_used(sockDistance) || socket_is_used(sockColor))) {
1077  tex->feature = SHD_VORONOI_F1;
1078 
1080  NodeTexVoronoi *texVoronoi = (NodeTexVoronoi *)voronoiNode->storage;
1081  texVoronoi->feature = SHD_VORONOI_F2;
1082  texVoronoi->distance = tex->distance;
1083  texVoronoi->dimensions = 3;
1084  voronoiNode->locx = node->locx + node->width + 20.0f;
1085  voronoiNode->locy = node->locy;
1086 
1087  bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
1088  bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
1089  bNodeSocket *sockExponent = nodeFindSocket(node, SOCK_IN, "Exponent");
1090  bNodeSocket *sockVoronoiVector = nodeFindSocket(voronoiNode, SOCK_IN, "Vector");
1091  bNodeSocket *sockVoronoiScale = nodeFindSocket(voronoiNode, SOCK_IN, "Scale");
1092  bNodeSocket *sockVoronoiExponent = nodeFindSocket(voronoiNode, SOCK_IN, "Exponent");
1093  if (sockVector->link) {
1095  sockVector->link->fromnode,
1096  sockVector->link->fromsock,
1097  voronoiNode,
1098  sockVoronoiVector);
1099  }
1101  sockScale);
1102  if (sockScale->link) {
1104  sockScale->link->fromnode,
1105  sockScale->link->fromsock,
1106  voronoiNode,
1107  sockVoronoiScale);
1108  }
1110  sockExponent);
1111  if (sockExponent->link) {
1113  sockExponent->link->fromnode,
1114  sockExponent->link->fromsock,
1115  voronoiNode,
1116  sockVoronoiExponent);
1117  }
1118 
1119  bNode *subtractNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
1120  subtractNode->custom1 = NODE_MATH_SUBTRACT;
1121  subtractNode->locx = voronoiNode->locx + voronoiNode->width + 20.0f;
1122  subtractNode->locy = voronoiNode->locy;
1123  bNodeSocket *sockSubtractOutValue = nodeFindSocket(subtractNode, SOCK_OUT, "Value");
1124 
1126  if (link->fromnode == node) {
1127  nodeAddLink(ntree, subtractNode, sockSubtractOutValue, link->tonode, link->tosock);
1128  nodeRemLink(ntree, link);
1129  }
1130  }
1131 
1132  bNodeSocket *sockDistanceF1 = nodeFindSocket(node, SOCK_OUT, "Distance");
1133  bNodeSocket *sockDistanceF2 = nodeFindSocket(voronoiNode, SOCK_OUT, "Distance");
1134  bNodeSocket *sockSubtractA = BLI_findlink(&subtractNode->inputs, 0);
1135  bNodeSocket *sockSubtractB = BLI_findlink(&subtractNode->inputs, 1);
1136 
1137  nodeAddLink(ntree, node, sockDistanceF1, subtractNode, sockSubtractB);
1138  nodeAddLink(ntree, voronoiNode, sockDistanceF2, subtractNode, sockSubtractA);
1139 
1140  need_update = true;
1141  }
1142  }
1143  }
1144 
1145  if (need_update) {
1147  }
1148 }
1149 
1159 {
1160  bool need_update = false;
1161 
1163  bNode *node = link->fromnode;
1164  if (node && node->type == SH_NODE_TEX_VORONOI && node->storage) {
1165  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1166  if (tex->coloring == 0) {
1167  bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
1168  if (link->fromsock == sockColor) {
1169  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1170  nodeAddLink(ntree, node, sockDistance, link->tonode, link->tosock);
1171  nodeRemLink(ntree, link);
1172  need_update = true;
1173  }
1174  }
1175  else {
1176  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1177  if (link->fromsock == sockDistance) {
1178  bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
1179  nodeAddLink(ntree, node, sockColor, link->tonode, link->tosock);
1180  nodeRemLink(ntree, link);
1181  need_update = true;
1182  }
1183  }
1184  }
1185  }
1186 
1187  if (need_update) {
1189  }
1190 }
1191 
1192 /* Previously, the output euclidean distance was actually the squared
1193  * euclidean distance. To fix this, we square the output distance
1194  * socket if the distance metric is set to SHD_VORONOI_EUCLIDEAN.
1195  */
1197 {
1198  bool need_update = false;
1199 
1201  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1202  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1203  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1204  if (tex->distance == SHD_VORONOI_EUCLIDEAN &&
1205  (ELEM(tex->feature, SHD_VORONOI_F1, SHD_VORONOI_F2)) && socket_is_used(sockDistance)) {
1206  bNode *multiplyNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
1207  multiplyNode->custom1 = NODE_MATH_MULTIPLY;
1208  multiplyNode->locx = node->locx + node->width + 20.0f;
1209  multiplyNode->locy = node->locy;
1210 
1211  bNodeSocket *sockValue = nodeFindSocket(multiplyNode, SOCK_OUT, "Value");
1213  if (link->fromsock == sockDistance) {
1214  nodeAddLink(ntree, multiplyNode, sockValue, link->tonode, link->tosock);
1215  nodeRemLink(ntree, link);
1216  }
1217  }
1218 
1219  bNodeSocket *sockMultiplyA = BLI_findlink(&multiplyNode->inputs, 0);
1220  bNodeSocket *sockMultiplyB = BLI_findlink(&multiplyNode->inputs, 1);
1221 
1222  nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyA);
1223  nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyB);
1224 
1225  need_update = true;
1226  }
1227  }
1228  }
1229 
1230  if (need_update) {
1232  }
1233 }
1234 
1235 /* Noise and Wave Texture nodes: Restore previous Distortion range.
1236  * In 2.81 we used noise() for distortion, now we use snoise() which has twice the range.
1237  * To fix this we halve distortion value, directly or by adding multiply node for used sockets.
1238  */
1240 {
1241  bool need_update = false;
1242 
1245 
1246  bNodeSocket *sockDistortion = nodeFindSocket(node, SOCK_IN, "Distortion");
1247  float *distortion = cycles_node_socket_float_value(sockDistortion);
1248 
1249  if (socket_is_used(sockDistortion) && sockDistortion->link != NULL) {
1250  bNode *distortionInputNode = sockDistortion->link->fromnode;
1251  bNodeSocket *distortionInputSock = sockDistortion->link->fromsock;
1252 
1254  mulNode->custom1 = NODE_MATH_MULTIPLY;
1255  mulNode->locx = node->locx;
1256  mulNode->locy = node->locy - 240.0f;
1257  mulNode->flag |= NODE_HIDDEN;
1258  bNodeSocket *mulSockA = BLI_findlink(&mulNode->inputs, 0);
1259  bNodeSocket *mulSockB = BLI_findlink(&mulNode->inputs, 1);
1260  *cycles_node_socket_float_value(mulSockB) = 0.5f;
1261  bNodeSocket *mulSockOut = nodeFindSocket(mulNode, SOCK_OUT, "Value");
1262 
1263  nodeRemLink(ntree, sockDistortion->link);
1264  nodeAddLink(ntree, distortionInputNode, distortionInputSock, mulNode, mulSockA);
1265  nodeAddLink(ntree, mulNode, mulSockOut, node, sockDistortion);
1266 
1267  need_update = true;
1268  }
1269  else if (*distortion != 0.0f) {
1270  *distortion = *distortion * 0.5f;
1271  }
1272  }
1273  }
1274 
1275  if (need_update) {
1277  }
1278 }
1279 
1291 {
1293  if (node->type == SH_NODE_TEX_WAVE) {
1294  NodeTexWave *tex = (NodeTexWave *)node->storage;
1295  tex->bands_direction = SHD_WAVE_BANDS_DIRECTION_DIAGONAL;
1296  tex->rings_direction = SHD_WAVE_RINGS_DIRECTION_SPHERICAL;
1297 
1298  if (tex->wave_profile == SHD_WAVE_PROFILE_SIN) {
1299  bNodeSocket *sockPhaseOffset = nodeFindSocket(node, SOCK_IN, "Phase Offset");
1300  *cycles_node_socket_float_value(sockPhaseOffset) = M_PI_2;
1301  }
1302  }
1303  }
1304 }
1305 
1307 {
1308  /* Particle shape shared with Eevee. */
1309  if (!MAIN_VERSION_ATLEAST(bmain, 280, 16)) {
1310  for (ParticleSettings *part = bmain->particles.first; part; part = part->id.next) {
1311  IDProperty *cpart = cycles_properties_from_ID(&part->id);
1312 
1313  if (cpart) {
1314  part->shape = cycles_property_float(cpart, "shape", 0.0);
1315  part->rad_root = cycles_property_float(cpart, "root_width", 1.0);
1316  part->rad_tip = cycles_property_float(cpart, "tip_width", 0.0);
1317  part->rad_scale = cycles_property_float(cpart, "radius_scale", 0.01);
1318  if (cycles_property_boolean(cpart, "use_closetip", true)) {
1319  part->shape_flag |= PART_SHAPE_CLOSE_TIP;
1320  }
1321  }
1322  }
1323  }
1324 
1325  if (!MAIN_VERSION_ATLEAST(bmain, 280, 68)) {
1326  /* Unify Cycles and Eevee film transparency. */
1327  for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
1330  if (cscene) {
1331  bool cycles_film_transparency = cycles_property_boolean(
1332  cscene, "film_transparent", false);
1333  scene->r.alphamode = cycles_film_transparency ? R_ALPHAPREMUL : R_ADDSKY;
1334  }
1335  }
1336  }
1337  }
1338 
1339  if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
1340  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1341  if (ntree->type == NTREE_SHADER) {
1343  }
1344  }
1346  }
1347 
1348  if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
1349  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1350  if (ntree->type == NTREE_SHADER) {
1352  }
1353  }
1355  }
1356 
1357  if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
1358  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1359  if (ntree->type == NTREE_SHADER) {
1362  }
1363  }
1365  }
1366 }
1367 
1369 {
1370  if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
1371  /* Shader node tree changes. After lib linking so we have all the typeinfo
1372  * pointers and updated sockets and we can use the high level node API to
1373  * manipulate nodes. */
1374  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1375  if (ntree->type != NTREE_SHADER) {
1376  continue;
1377  }
1378 
1379  if (!MAIN_VERSION_ATLEAST(bmain, 273, 5)) {
1380  /* Euler order was ZYX in previous versions. */
1383  }
1384  }
1385 
1386  if (!MAIN_VERSION_ATLEAST(bmain, 276, 6)) {
1389  }
1390  }
1391 
1392  if (!MAIN_VERSION_ATLEAST(bmain, 279, 2) ||
1393  (MAIN_VERSION_ATLEAST(bmain, 280, 0) && !MAIN_VERSION_ATLEAST(bmain, 280, 4))) {
1395  }
1396 
1397  if (!MAIN_VERSION_ATLEAST(bmain, 279, 3)) {
1400  }
1401  }
1402 
1403  if (!MAIN_VERSION_ATLEAST(bmain, 279, 4) ||
1404  (MAIN_VERSION_ATLEAST(bmain, 280, 0) && !MAIN_VERSION_ATLEAST(bmain, 280, 5))) {
1405  /* Switch to squared roughness convention */
1407  }
1408 
1409  if (!MAIN_VERSION_ATLEAST(bmain, 279, 5)) {
1411  }
1412 
1413  if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
1416  }
1417  }
1418  }
1420  }
1421 
1422  if (!MAIN_VERSION_ATLEAST(bmain, 280, 64)) {
1423  /* Unify Cycles and Eevee settings. */
1424  Scene *scene = bmain->scenes.first;
1425  const char *engine = (scene) ? scene->r.engine : "CYCLES";
1426 
1427  for (Light *light = bmain->lights.first; light; light = light->id.next) {
1428  light_emission_unify(light, engine);
1429  }
1430  }
1431 
1432  if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
1433  /* Unify Cycles and Eevee depth of field. */
1434  Scene *scene = bmain->scenes.first;
1435  const char *engine = (scene) ? scene->r.engine : "CYCLES";
1436 
1437  if (STREQ(engine, RE_engine_id_CYCLES)) {
1438  for (Camera *camera = bmain->cameras.first; camera; camera = camera->id.next) {
1439  IDProperty *ccamera = cycles_properties_from_ID(&camera->id);
1440  if (ccamera) {
1441  const bool is_fstop = cycles_property_int(ccamera, "aperture_type", 0) == 1;
1442 
1443  camera->dof.aperture_fstop = cycles_property_float(ccamera, "aperture_fstop", 5.6f);
1444  camera->dof.aperture_blades = cycles_property_int(ccamera, "aperture_blades", 0);
1445  camera->dof.aperture_rotation = cycles_property_float(ccamera, "aperture_rotation", 0.0);
1446  camera->dof.aperture_ratio = cycles_property_float(ccamera, "aperture_ratio", 1.0f);
1447  camera->dof.flag |= CAM_DOF_ENABLED;
1448 
1449  float aperture_size = cycles_property_float(ccamera, "aperture_size", 0.0f);
1450 
1451  if (is_fstop) {
1452  continue;
1453  }
1454  if (aperture_size > 0.0f) {
1455  if (camera->type == CAM_ORTHO) {
1456  camera->dof.aperture_fstop = 1.0f / (2.0f * aperture_size);
1457  }
1458  else {
1459  camera->dof.aperture_fstop = (camera->lens * 1e-3f) / (2.0f * aperture_size);
1460  }
1461 
1462  continue;
1463  }
1464  }
1465 
1466  /* No depth of field, set default settings. */
1467  camera->dof.aperture_fstop = 2.8f;
1468  camera->dof.aperture_blades = 0;
1469  camera->dof.aperture_rotation = 0.0f;
1470  camera->dof.aperture_ratio = 1.0f;
1471  camera->dof.flag &= ~CAM_DOF_ENABLED;
1472  }
1473  }
1474  }
1475 
1476  if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
1477  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1478  if (ntree->type == NTREE_SHADER) {
1480  }
1481  }
1483  }
1484 
1485  if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
1486  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1487  if (ntree->type == NTREE_SHADER) {
1493  }
1494  }
1496  }
1497 
1498  if (!MAIN_VERSION_ATLEAST(bmain, 281, 7)) {
1499  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1500  if (ntree->type == NTREE_SHADER) {
1502  }
1503  }
1505  }
1506 
1507  if (!MAIN_VERSION_ATLEAST(bmain, 281, 8)) {
1508  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1509  if (ntree->type == NTREE_SHADER) {
1511  }
1512  }
1514  }
1515 
1516  if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
1517  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1518  if (ntree->type == NTREE_SHADER) {
1520  }
1521  }
1523  }
1524 
1525  if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
1526  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1527  if (ntree->type == NTREE_SHADER) {
1532  }
1533  }
1535  }
1536 
1537  if (!MAIN_VERSION_ATLEAST(bmain, 282, 4)) {
1538  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1539  if (ntree->type == NTREE_SHADER) {
1541  }
1542  }
1544  }
1545 
1546  if (!MAIN_VERSION_ATLEAST(bmain, 283, 4)) {
1547  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1548  if (ntree->type == NTREE_SHADER) {
1550  }
1551  }
1553  }
1554 
1555  if (!MAIN_VERSION_ATLEAST(bmain, 290, 5)) {
1556  /* New denoiser settings. */
1557  for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
1559 
1560  /* Check if any view layers had (optix) denoising enabled. */
1561  bool use_optix = false;
1562  bool use_denoising = false;
1563  for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
1564  view_layer = view_layer->next) {
1565  IDProperty *cview_layer = cycles_properties_from_view_layer(view_layer);
1566  if (cview_layer) {
1567  use_denoising = use_denoising ||
1568  cycles_property_boolean(cview_layer, "use_denoising", false);
1569  use_optix = use_optix ||
1570  cycles_property_boolean(cview_layer, "use_optix_denoising", false);
1571  }
1572  }
1573 
1574  if (cscene) {
1575  const int DENOISER_AUTO = 0;
1576  const int DENOISER_NLM = 1;
1577  const int DENOISER_OPTIX = 2;
1578 
1579  /* Enable denoiser if it was enabled for one view layer before. */
1580  cycles_property_int_set(cscene, "denoiser", (use_optix) ? DENOISER_OPTIX : DENOISER_NLM);
1581  cycles_property_boolean_set(cscene, "use_denoising", use_denoising);
1582 
1583  /* Migrate Optix denoiser to new settings. */
1584  if (cycles_property_int(cscene, "preview_denoising", 0)) {
1585  cycles_property_boolean_set(cscene, "use_preview_denoising", true);
1586  cycles_property_int_set(cscene, "preview_denoiser", DENOISER_AUTO);
1587  }
1588  }
1589 
1590  /* Enable denoising in all view layer if there was no denoising before,
1591  * so that enabling the scene settings auto enables it for all view layers. */
1592  if (!use_denoising) {
1593  for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
1594  view_layer = view_layer->next) {
1595  IDProperty *cview_layer = cycles_properties_from_view_layer(view_layer);
1596  if (cview_layer) {
1597  cycles_property_boolean_set(cview_layer, "use_denoising", true);
1598  }
1599  }
1600  }
1601  }
1602  }
1603 }
void BKE_fcurves_id_cb(struct ID *id, ID_FCurve_Edit_Callback func, void *user_data)
Definition: anim_data.c:1278
void BKE_curvemapping_changed_all(struct CurveMapping *cumap)
Definition: colortools.c:954
#define IDP_Float(prop)
Definition: BKE_idprop.h:179
#define IDP_Int(prop)
Definition: BKE_idprop.h:154
struct IDProperty * IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop, const char *name, const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct IDProperty * IDP_GetProperties(struct ID *id, const bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:769
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:643
struct IDProperty * IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:907
#define MAIN_VERSION_ATLEAST(main, ver, subver)
Definition: BKE_main.h:269
#define SH_NODE_BSDF_PRINCIPLED
Definition: BKE_node.h:1058
#define SH_NODE_EMISSION
Definition: BKE_node.h:1009
struct bNode * ntreeShaderOutputNode(struct bNodeTree *ntree, int target)
#define SH_NODE_TEX_ENVIRONMENT
Definition: BKE_node.h:1022
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link)
Definition: node.cc:2231
#define SH_NODE_MATH
Definition: BKE_node.h:985
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree)
Definition: node.cc:4262
#define FOREACH_NODETREE_END
Definition: BKE_node.h:945
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2189
struct bNodeSocket * nodeFindSocket(const struct bNode *node, eNodeSocketInOut in_out, const char *identifier)
#define SH_NODE_BSDF_ANISOTROPIC
Definition: BKE_node.h:1002
#define SH_NODE_MAPPING
Definition: BKE_node.h:981
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition: BKE_node.h:935
#define SH_NODE_BSDF_GLASS
Definition: BKE_node.h:1005
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2004
#define SH_NODE_DISPLACEMENT
Definition: BKE_node.h:1062
#define SH_NODE_TEX_MUSGRAVE
Definition: BKE_node.h:1019
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list)
Definition: BLI_listbase.h:194
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
#define M_PI_2
Definition: BLI_math_base.h:41
void quat_to_eulO(float eul[3], const short order, const float quat[4])
void eulO_to_quat(float quat[4], const float eul[3], const short order)
@ EULER_ORDER_XYZ
@ EULER_ORDER_ZYX
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void copy_v4_fl(float r[4], float f)
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:333
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL()
Definition: string.c:1040
#define STRPREFIX(a, b)
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
external readfile function prototypes.
@ IDP_FLOAT
Definition: DNA_ID.h:99
@ IDP_INT
Definition: DNA_ID.h:98
@ IDP_GROUP
Definition: DNA_ID.h:101
@ CAM_DOF_ENABLED
@ CAM_ORTHO
#define CM_TOT
@ CUMA_DO_CLIP
#define LA_SUN
@ NODE_VECTOR_MATH_NORMALIZE
@ NODE_VECTOR_MATH_LENGTH
@ NODE_VECTOR_MATH_CROSS_PRODUCT
@ NODE_VECTOR_MATH_ADD
@ NODE_VECTOR_MATH_DOT_PRODUCT
@ NODE_VECTOR_MATH_ABSOLUTE
@ NODE_VECTOR_MATH_MAXIMUM
@ NODE_VECTOR_MATH_SUBTRACT
@ NODE_VECTOR_MATH_MINIMUM
#define SHD_SPACE_WORLD
@ NODE_MATH_ABSOLUTE
@ NODE_MATH_SINE
@ NODE_MATH_ARCCOSINE
@ NODE_MATH_POWER
@ NODE_MATH_ARCTANGENT
@ NODE_MATH_SQRT
@ NODE_MATH_CEIL
@ NODE_MATH_FRACTION
@ NODE_MATH_ARCSINE
@ NODE_MATH_MULTIPLY
@ NODE_MATH_ROUND
@ NODE_MATH_FLOOR
@ NODE_MATH_SUBTRACT
@ NODE_MATH_COSINE
@ NODE_MATH_TANGENT
@ SHD_OUTPUT_CYCLES
@ SHD_WAVE_RINGS_DIRECTION_SPHERICAL
@ SHD_WAVE_BANDS_DIRECTION_DIAGONAL
@ SHD_VORONOI_F2
@ SHD_VORONOI_F1
#define NODE_HIDDEN
@ SOCK_OUT
@ SOCK_IN
@ SHD_SUBSURFACE_BURLEY
@ SHD_SUBSURFACE_RANDOM_WALK
@ SOCK_IN_USE
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_RGBA
@ SHD_VORONOI_EUCLIDEAN
#define SHD_AO_LOCAL
#define NTREE_SHADER
@ SHD_WAVE_PROFILE_SIN
#define SHD_SPACE_OBJECT
@ PART_SHAPE_CLOSE_TIP
@ R_ADDSKY
@ R_ALPHAPREMUL
#define TEXMAP_CLIP_MIN
#define TEXMAP_CLIP_MAX
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_DATA
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky SH_NODE_TEX_NOISE
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy SH_NODE_BSDF_REFRACTION
Group RGB to Bright SH_NODE_CURVE_VEC
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise SH_NODE_TEX_WAVE
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave SH_NODE_TEX_VORONOI
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse SH_NODE_BSDF_GLOSSY
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add SH_NODE_AMBIENT_OCCLUSION
Group RGB to Bright Vector Camera SH_NODE_VECTOR_MATH
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume SH_NODE_TEX_IMAGE
Group RGB to Bright Vector Camera Vector Combine SH_NODE_OUTPUT_MATERIAL
ColorManagedColorspaceSettings colorspace_settings
OperationNode * node
Scene scene
@ DENOISER_OPTIX
Definition: device_task.h:37
@ DENOISER_NLM
Definition: device_task.h:36
bNodeTree * ntree
DRWShaderLibrary * lib
bNodeSocketValueRGBA * color_socket
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
const char * RE_engine_id_CYCLES
Definition: scene.c:1744
short totpoint
CurveMapPoint * curve
CurveMap cm[4]
char * rna_path
Definition: DNA_ID.h:273
void * next
Definition: DNA_ID.h:274
float r
float energy
short use_nodes
struct bNodeTree * nodetree
short type
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase scenes
Definition: BKE_main.h:146
ListBase lights
Definition: BKE_main.h:156
ListBase particles
Definition: BKE_main.h:172
ListBase cameras
Definition: BKE_main.h:157
char engine[32]
struct RenderData r
ListBase view_layers
struct IDProperty * id_properties
char name[64]
struct bNodeLink * link
void * default_value
char identifier[64]
ListBase nodes
ListBase links
struct AnimData * adt
short custom1
float locy
float width
ListBase inputs
float height
float locx
short type
void * storage
static int cycles_property_int(IDProperty *idprop, const char *name, int default_value)
static void update_musgrave_node_color_output(bNodeTree *ntree)
static void update_mapping_node_fcurve_rna_path_callback(ID *UNUSED(id), FCurve *fcurve, void *_data)
static bool cycles_property_boolean(IDProperty *idprop, const char *name, bool default_value)
static IDProperty * cycles_properties_from_ID(ID *id)
static void update_vector_math_node_average_operator(bNodeTree *ntree)
static IDProperty * cycles_properties_from_view_layer(ViewLayer *view_layer)
static void update_voronoi_node_f3_and_f4(bNodeTree *ntree)
static void light_emission_unify(Light *light, const char *engine)
static float * cycles_node_socket_rgba_value(bNodeSocket *socket)
static void update_voronoi_node_fac_output(bNodeTree *ntree)
static void ambient_occlusion_node_relink(bNodeTree *ntree)
static float cycles_property_float(IDProperty *idprop, const char *name, float default_value)
static void update_wave_node_directions_and_offset(bNodeTree *ntree)
static void light_emission_node_to_energy(Light *light, float *energy, float color[3])
static void displacement_node_insert(bNodeTree *ntree)
static bool node_has_roughness(bNode *node)
static void update_math_node_single_operand_operators(bNodeTree *ntree)
static void displacement_principled_nodes(bNode *node)
static void update_voronoi_node_dimensions(bNodeTree *ntree)
static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
void do_versions_after_linking_cycles(Main *bmain)
static void update_musgrave_node_dimensions(bNodeTree *ntree)
static void square_roughness_node_insert(bNodeTree *ntree)
static void update_vector_math_node_normalize_operator(bNodeTree *ntree)
static void update_vector_math_node_add_and_subtract_operators(bNodeTree *ntree)
static void vector_curve_node_remap(bNode *node)
static float * cycles_node_socket_float_value(bNodeSocket *socket)
static float * cycles_node_socket_vector_value(bNodeSocket *socket)
static void update_vector_math_node_operators_enum_mapping(bNodeTree *ntree)
static void cycles_property_boolean_set(IDProperty *idprop, const char *name, bool value)
static void image_node_colorspace(bNode *node)
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
static void update_vector_math_node_cross_product_operator(bNodeTree *ntree)
static void update_voronoi_node_square_distance(bNodeTree *ntree)
static void update_voronoi_node_coloring(bNodeTree *ntree)
static void cycles_property_int_set(IDProperty *idprop, const char *name, int value)
static void update_noise_and_wave_distortion(bNodeTree *ntree)
static void mapping_node_order_flip(bNode *node)
static void update_voronoi_node_crackle(bNodeTree *ntree)
static void update_noise_node_dimensions(bNodeTree *ntree)
static void update_vector_math_node_dot_product_operator(bNodeTree *ntree)
static bool socket_is_used(bNodeSocket *sock)