Blender  V3.3
versioning_cycles.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 /* allow readfile to use deprecated functionality */
8 #define DNA_DEPRECATED_ALLOW
9 
10 #include <float.h>
11 #include <string.h>
12 
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 #include "BLI_string.h"
16 #include "BLI_utildefines.h"
17 
18 #include "DNA_anim_types.h"
19 #include "DNA_camera_types.h"
20 #include "DNA_color_types.h"
21 #include "DNA_light_types.h"
22 #include "DNA_node_types.h"
23 #include "DNA_particle_types.h"
24 
25 #include "BKE_animsys.h"
26 #include "BKE_colortools.h"
27 #include "BKE_idprop.h"
28 #include "BKE_main.h"
29 #include "BKE_node.h"
30 
31 #include "NOD_shader.h"
32 
33 #include "MEM_guardedalloc.h"
34 
35 #include "IMB_colormanagement.h"
36 
37 #include "BLO_readfile.h"
38 #include "readfile.h"
39 #include "versioning_common.h"
40 
41 static bool socket_is_used(bNodeSocket *sock)
42 {
43  return sock->flag & SOCK_IN_USE;
44 }
45 
47 {
48  bNodeSocketValueFloat *socket_data = socket->default_value;
49  return &socket_data->value;
50 }
51 
53 {
54  bNodeSocketValueRGBA *socket_data = socket->default_value;
55  return socket_data->value;
56 }
57 
59 {
60  bNodeSocketValueVector *socket_data = socket->default_value;
61  return socket_data->value;
62 }
63 
65 {
66  IDProperty *idprop = IDP_GetProperties(id, false);
67  return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles", IDP_GROUP) : NULL;
68 }
69 
71 {
72  IDProperty *idprop = IDP_GetProperties(id, false);
73  return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles_visibility", IDP_GROUP) : NULL;
74 }
75 
77 {
78  IDProperty *idprop = view_layer->id_properties;
79  return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles", IDP_GROUP) : NULL;
80 }
81 
82 static float cycles_property_float(IDProperty *idprop, const char *name, float default_value)
83 {
84  IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_FLOAT);
85  return (prop) ? IDP_Float(prop) : default_value;
86 }
87 
88 static int cycles_property_int(IDProperty *idprop, const char *name, int default_value)
89 {
90  IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
91  return (prop) ? IDP_Int(prop) : default_value;
92 }
93 
94 static void cycles_property_int_set(IDProperty *idprop, const char *name, int value)
95 {
96  IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
97  if (prop) {
98  IDP_Int(prop) = value;
99  }
100  else {
101  IDPropertyTemplate val = {0};
102  val.i = value;
103  IDP_AddToGroup(idprop, IDP_New(IDP_INT, &val, name));
104  }
105 }
106 
107 static bool cycles_property_boolean(IDProperty *idprop, const char *name, bool default_value)
108 {
109  return cycles_property_int(idprop, name, default_value);
110 }
111 
112 static void cycles_property_boolean_set(IDProperty *idprop, const char *name, bool value)
113 {
114  cycles_property_int_set(idprop, name, value);
115 }
116 
118 {
119  bool need_update = false;
120 
121  /* Iterate backwards from end so we don't encounter newly added links. */
122  bNodeLink *prevlink;
123  for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
124  prevlink = link->prev;
125 
126  /* Detect link to replace. */
127  bNode *fromnode = link->fromnode;
128  bNodeSocket *fromsock = link->fromsock;
129  bNode *tonode = link->tonode;
130  bNodeSocket *tosock = link->tosock;
131 
132  if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && fromnode->type != SH_NODE_DISPLACEMENT &&
133  STREQ(tosock->identifier, "Displacement"))) {
134  continue;
135  }
136 
137  /* Replace link with displacement node. */
138  nodeRemLink(ntree, link);
139 
140  /* Add displacement node. */
142  node->locx = 0.5f * (fromnode->locx + tonode->locx);
143  node->locy = 0.5f * (fromnode->locy + tonode->locy);
144 
145  bNodeSocket *scale_socket = nodeFindSocket(node, SOCK_IN, "Scale");
146  bNodeSocket *midlevel_socket = nodeFindSocket(node, SOCK_IN, "Midlevel");
147  bNodeSocket *height_socket = nodeFindSocket(node, SOCK_IN, "Height");
148  bNodeSocket *displacement_socket = nodeFindSocket(node, SOCK_OUT, "Displacement");
149 
150  /* Set default values for compatibility. */
151  *cycles_node_socket_float_value(scale_socket) = 0.1f;
152  *cycles_node_socket_float_value(midlevel_socket) = 0.0f;
153 
154  /* Link to input and material output node. */
155  nodeAddLink(ntree, fromnode, fromsock, node, height_socket);
156  nodeAddLink(ntree, node, displacement_socket, tonode, tosock);
157 
158  need_update = true;
159  }
160 
161  if (need_update) {
163  }
164 }
165 
167 {
168  if (node->type == SH_NODE_DISPLACEMENT) {
169  if (node->custom1 != SHD_SPACE_WORLD) {
170  node->custom1 = SHD_SPACE_OBJECT;
171  }
172  }
173  else if (node->type == SH_NODE_BSDF_PRINCIPLED) {
174  if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK) {
175  node->custom2 = SHD_SUBSURFACE_BURLEY;
176  }
177  }
178 }
179 
180 static bool node_has_roughness(const bNode *node)
181 {
182  return ELEM(node->type,
187 }
188 
190 {
191  bool need_update = false;
192 
193  /* Update default values */
195  if (node_has_roughness(node)) {
196  bNodeSocket *roughness_input = nodeFindSocket(node, SOCK_IN, "Roughness");
197  float *roughness_value = cycles_node_socket_float_value(roughness_input);
198  *roughness_value = sqrtf(max_ff(*roughness_value, 0.0f));
199  }
200  }
201 
202  /* Iterate backwards from end so we don't encounter newly added links. */
203  bNodeLink *prevlink;
204  for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
205  prevlink = link->prev;
206 
207  /* Detect link to replace. */
208  bNode *fromnode = link->fromnode;
209  bNodeSocket *fromsock = link->fromsock;
210  bNode *tonode = link->tonode;
211  bNodeSocket *tosock = link->tosock;
212 
213  if (!(node_has_roughness(tonode) && STREQ(tosock->identifier, "Roughness"))) {
214  continue;
215  }
216 
217  /* Replace links with sqrt node */
218  nodeRemLink(ntree, link);
219 
220  /* Add sqrt node. */
222  node->custom1 = NODE_MATH_POWER;
223  node->locx = 0.5f * (fromnode->locx + tonode->locx);
224  node->locy = 0.5f * (fromnode->locy + tonode->locy);
225 
226  /* Link to input and material output node. */
227  *cycles_node_socket_float_value(node->inputs.last) = 0.5f;
228  nodeAddLink(ntree, fromnode, fromsock, node, node->inputs.first);
229  nodeAddLink(ntree, node, node->outputs.first, tonode, tosock);
230 
231  need_update = true;
232  }
233 
234  if (need_update) {
236  }
237 }
238 
240 {
241  /* Flip euler order of mapping shader node */
242  if (node->type == SH_NODE_MAPPING && node->storage) {
243  TexMapping *texmap = node->storage;
244 
245  float quat[4];
246  eulO_to_quat(quat, texmap->rot, EULER_ORDER_ZYX);
247  quat_to_eulO(texmap->rot, EULER_ORDER_XYZ, quat);
248  }
249 }
250 
252 {
253  /* Remap values of vector curve node from normalized to absolute values */
254  if (node->type == SH_NODE_CURVE_VEC && node->storage) {
255  CurveMapping *mapping = node->storage;
256  mapping->flag &= ~CUMA_DO_CLIP;
257 
258  for (int curve_index = 0; curve_index < CM_TOT; curve_index++) {
259  CurveMap *cm = &mapping->cm[curve_index];
260  if (cm->curve) {
261  for (int i = 0; i < cm->totpoint; i++) {
262  cm->curve[i].x = (cm->curve[i].x * 2.0f) - 1.0f;
263  cm->curve[i].y = (cm->curve[i].y - 0.5f) * 2.0f;
264  }
265  }
266  }
267 
269  }
270 }
271 
273 {
274  bool need_update = false;
275 
276  /* Set default values. */
278  if (node->type == SH_NODE_AMBIENT_OCCLUSION) {
279  node->custom1 = 1; /* samples */
280  node->custom2 &= ~SHD_AO_LOCAL;
281 
282  bNodeSocket *distance_socket = nodeFindSocket(node, SOCK_IN, "Distance");
283  *cycles_node_socket_float_value(distance_socket) = 0.0f;
284  }
285  }
286 
287  /* Iterate backwards from end so we don't encounter newly added links. */
288  bNodeLink *prevlink;
289  for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
290  prevlink = link->prev;
291 
292  /* Detect link to replace. */
293  bNode *fromnode = link->fromnode;
294  bNode *tonode = link->tonode;
295  bNodeSocket *tosock = link->tosock;
296 
297  if (!(fromnode->type == SH_NODE_AMBIENT_OCCLUSION)) {
298  continue;
299  }
300 
301  /* Replace links with color socket. */
302  nodeRemLink(ntree, link);
303  bNodeSocket *color_socket = nodeFindSocket(fromnode, SOCK_OUT, "Color");
304  nodeAddLink(ntree, fromnode, color_socket, tonode, tosock);
305 
306  need_update = true;
307  }
308 
309  if (need_update) {
311  }
312 }
313 
315 {
316  if (node->id == NULL) {
317  return;
318  }
319 
320  int color_space;
321  if (node->type == SH_NODE_TEX_IMAGE && node->storage) {
322  NodeTexImage *tex = node->storage;
323  color_space = tex->color_space;
324  }
325  else if (node->type == SH_NODE_TEX_ENVIRONMENT && node->storage) {
326  NodeTexEnvironment *tex = node->storage;
327  color_space = tex->color_space;
328  }
329  else {
330  return;
331  }
332 
333  enum { SHD_COLORSPACE_NONE = 0 };
334  Image *image = (Image *)node->id;
335  if (color_space == SHD_COLORSPACE_NONE) {
336  STRNCPY(image->colorspace_settings.name,
338  }
339 }
340 
341 static void light_emission_node_to_energy(Light *light, float *energy, float color[3])
342 {
343  *energy = 1.0;
344  copy_v3_fl(color, 1.0f);
345 
346  /* If nodetree has animation or drivers, don't try to convert. */
347  bNodeTree *ntree = light->nodetree;
348  if (ntree == NULL || ntree->adt) {
349  return;
350  }
351 
352  /* Find emission node */
354  if (output_node == NULL) {
355  return;
356  }
357 
358  bNode *emission_node = NULL;
359  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
360  if (link->tonode == output_node && link->fromnode->type == SH_NODE_EMISSION) {
361  emission_node = link->fromnode;
362  break;
363  }
364  }
365 
366  if (emission_node == NULL) {
367  return;
368  }
369 
370  /* Don't convert if anything is linked */
371  bNodeSocket *strength_socket = nodeFindSocket(emission_node, SOCK_IN, "Strength");
372  bNodeSocket *color_socket = nodeFindSocket(emission_node, SOCK_IN, "Color");
373 
374  if ((strength_socket->flag & SOCK_IN_USE) || (color_socket->flag & SOCK_IN_USE)) {
375  return;
376  }
377 
378  float *strength_value = cycles_node_socket_float_value(strength_socket);
379  float *color_value = cycles_node_socket_rgba_value(color_socket);
380 
381  *energy = *strength_value;
382  copy_v3_v3(color, color_value);
383 
384  *strength_value = 1.0f;
385  copy_v4_fl(color_value, 1.0f);
386  light->use_nodes = false;
387 }
388 
389 static void light_emission_unify(Light *light, const char *engine)
390 {
391  if (light->type != LA_SUN) {
392  light->energy *= 100.0f;
393  }
394 
395  /* Attempt to extract constant energy and color from nodes. */
396  bool use_nodes = light->use_nodes;
397  float energy, color[3];
398  light_emission_node_to_energy(light, &energy, color);
399 
400  if (STREQ(engine, "CYCLES")) {
401  if (use_nodes) {
402  /* Energy extracted from nodes */
403  light->energy = energy;
404  copy_v3_v3(&light->r, color);
405  }
406  else {
407  /* Default cycles multipliers if there are no nodes */
408  if (light->type == LA_SUN) {
409  light->energy = 1.0f;
410  }
411  else {
412  light->energy = 100.0f;
413  }
414  }
415  }
416  else {
417  /* Disable nodes if scene was configured for Eevee */
418  light->use_nodes = false;
419  }
420 }
421 
422 /* The B input of the Math node is no longer used for single-operand operators.
423  * Previously, if the B input was linked and the A input was not, the B input
424  * was used as the input of the operator. To correct this, we move the link
425  * from B to A if B is linked and A is not.
426  */
428 {
429  bool need_update = false;
430 
432  if (node->type == SH_NODE_MATH) {
433  if (ELEM(node->custom1,
446  bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
447  bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
448  if (!sockA->link && sockB->link) {
449  nodeAddLink(ntree, sockB->link->fromnode, sockB->link->fromsock, node, sockA);
450  nodeRemLink(ntree, sockB->link);
451  need_update = true;
452  }
453  }
454  }
455  }
456 
457  if (need_update) {
459  }
460 }
461 
462 /* The Value output of the Vector Math node is no longer available in the Add
463  * and Subtract operators. Previously, this Value output was computed from the
464  * Vector output V as follows:
465  *
466  * Value = (abs(V.x) + abs(V.y) + abs(V.z)) / 3
467  *
468  * Or more compactly using vector operators:
469  *
470  * Value = dot(abs(V), (1 / 3, 1 / 3, 1 / 3))
471  *
472  * To correct this, if the Value output was used, we are going to compute
473  * it using the second equation by adding an absolute and a dot node, and
474  * then connect them appropriately.
475  */
477 {
478  bool need_update = false;
479 
481  if (node->type == SH_NODE_VECTOR_MATH) {
482  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
483  if (socket_is_used(sockOutValue) &&
485 
488  absNode->locx = node->locx + node->width + 20.0f;
489  absNode->locy = node->locy;
490 
493  dotNode->locx = absNode->locx + absNode->width + 20.0f;
494  dotNode->locy = absNode->locy;
495  bNodeSocket *sockDotB = BLI_findlink(&dotNode->inputs, 1);
496  bNodeSocket *sockDotOutValue = nodeFindSocket(dotNode, SOCK_OUT, "Value");
497  copy_v3_fl(cycles_node_socket_vector_value(sockDotB), 1 / 3.0f);
498 
500  if (link->fromsock == sockOutValue) {
501  nodeAddLink(ntree, dotNode, sockDotOutValue, link->tonode, link->tosock);
502  nodeRemLink(ntree, link);
503  }
504  }
505 
506  bNodeSocket *sockAbsA = BLI_findlink(&absNode->inputs, 0);
507  bNodeSocket *sockDotA = BLI_findlink(&dotNode->inputs, 0);
508  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
509  bNodeSocket *sockAbsOutVector = nodeFindSocket(absNode, SOCK_OUT, "Vector");
510 
511  nodeAddLink(ntree, node, sockOutVector, absNode, sockAbsA);
512  nodeAddLink(ntree, absNode, sockAbsOutVector, dotNode, sockDotA);
513 
514  need_update = true;
515  }
516  }
517  }
518 
519  if (need_update) {
521  }
522 }
523 
524 /* The Vector output of the Vector Math node is no longer available in the Dot
525  * Product operator. Previously, this Vector was always zero initialized. To
526  * correct this, we zero out any socket the Vector Output was connected to.
527  */
529 {
530  bool need_update = false;
531 
533  if (node->type == SH_NODE_VECTOR_MATH) {
534  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
535  if (socket_is_used(sockOutVector) && node->custom1 == NODE_VECTOR_MATH_DOT_PRODUCT) {
537  if (link->fromsock == sockOutVector) {
538  switch (link->tosock->type) {
539  case SOCK_FLOAT:
540  *cycles_node_socket_float_value(link->tosock) = 0.0f;
541  break;
542  case SOCK_VECTOR:
543  copy_v3_fl(cycles_node_socket_vector_value(link->tosock), 0.0f);
544  break;
545  case SOCK_RGBA:
546  copy_v4_fl(cycles_node_socket_rgba_value(link->tosock), 0.0f);
547  break;
548  }
549  nodeRemLink(ntree, link);
550  }
551  }
552  need_update = true;
553  }
554  }
555  }
556 
557  if (need_update) {
559  }
560 }
561 
562 /* Previously, the Vector output of the cross product operator was normalized.
563  * To correct this, a Normalize node is added to normalize the output if used.
564  * Moreover, the Value output was removed. This Value was equal to the length
565  * of the cross product. To correct this, a Length node is added if needed.
566  */
568 {
569  bool need_update = false;
570 
572  if (node->type == SH_NODE_VECTOR_MATH) {
573  if (node->custom1 == NODE_VECTOR_MATH_CROSS_PRODUCT) {
574  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
575  if (socket_is_used(sockOutVector)) {
577  normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
578  normalizeNode->locx = node->locx + node->width + 20.0f;
579  normalizeNode->locy = node->locy;
580  bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
581 
583  if (link->fromsock == sockOutVector) {
584  nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
585  nodeRemLink(ntree, link);
586  }
587  }
588  bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
589  nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
590 
591  need_update = true;
592  }
593 
594  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
595  if (socket_is_used(sockOutValue)) {
597  lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
598  lengthNode->locx = node->locx + node->width + 20.0f;
599  if (socket_is_used(sockOutVector)) {
600  lengthNode->locy = node->locy - lengthNode->height - 20.0f;
601  }
602  else {
603  lengthNode->locy = node->locy;
604  }
605  bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
606 
608  if (link->fromsock == sockOutValue) {
609  nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
610  nodeRemLink(ntree, link);
611  }
612  }
613  bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
614  nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
615 
616  need_update = true;
617  }
618  }
619  }
620  }
621 
622  if (need_update) {
624  }
625 }
626 
627 /* The Value output of the Vector Math node is no longer available in the
628  * Normalize operator. This Value output was equal to the length of the
629  * the input vector A. To correct this, we either add a Length node or
630  * convert the Normalize node into a Length node, depending on if the
631  * Vector output is needed.
632  */
634 {
635  bool need_update = false;
636 
638  if (node->type == SH_NODE_VECTOR_MATH) {
639  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
640  if (node->custom1 == NODE_VECTOR_MATH_NORMALIZE && socket_is_used(sockOutValue)) {
641  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
642  if (socket_is_used(sockOutVector)) {
644  lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
645  lengthNode->locx = node->locx + node->width + 20.0f;
646  lengthNode->locy = node->locy;
647  bNodeSocket *sockLengthValue = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
648 
650  if (link->fromsock == sockOutValue) {
651  nodeAddLink(ntree, lengthNode, sockLengthValue, link->tonode, link->tosock);
652  nodeRemLink(ntree, link);
653  }
654  }
655  bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
656  bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
657  if (sockA->link) {
658  bNodeLink *link = sockA->link;
659  nodeAddLink(ntree, link->fromnode, link->fromsock, lengthNode, sockLengthA);
660  }
661  else {
664  }
665 
666  need_update = true;
667  }
668  else {
669  node->custom1 = NODE_VECTOR_MATH_LENGTH;
670  }
671  }
672  }
673  }
674  if (need_update) {
676  }
677 }
678 
679 /* The Vector Math operator types didn't have an enum, but rather, their
680  * values were hard coded into the code. After the enum was created and
681  * after more vector operators were added, the hard coded values needs
682  * to be remapped to their correct enum values. To fix this, we remap
683  * the values according to the following rules:
684  *
685  * Dot Product Operator : 3 -> 7
686  * Normalize Operator : 5 -> 11
687  *
688  * Additionally, since the Average operator was removed, it is assigned
689  * a value of -1 just to be identified later in the versioning code:
690  *
691  * Average Operator : 2 -> -1
692  *
693  */
695 {
697  if (node->type == SH_NODE_VECTOR_MATH) {
698  switch (node->custom1) {
699  case 2:
700  node->custom1 = -1;
701  break;
702  case 3:
703  node->custom1 = 7;
704  break;
705  case 5:
706  node->custom1 = 11;
707  break;
708  }
709  }
710  }
711 }
712 
713 /* The Average operator is no longer available in the Vector Math node.
714  * The Vector output was equal to the normalized sum of input vectors while
715  * the Value output was equal to the length of the sum of input vectors.
716  * To correct this, we convert the node into an Add node and add a length
717  * node or a normalize node if needed.
718  */
720 {
721  bool need_update = false;
722 
724  if (node->type == SH_NODE_VECTOR_MATH) {
725  /* See update_vector_math_node_operators_enum_mapping. */
726  if (node->custom1 == -1) {
727  node->custom1 = NODE_VECTOR_MATH_ADD;
728  bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
729  if (socket_is_used(sockOutVector)) {
731  normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
732  normalizeNode->locx = node->locx + node->width + 20.0f;
733  normalizeNode->locy = node->locy;
734  bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
735 
737  if (link->fromsock == sockOutVector) {
738  nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
739  nodeRemLink(ntree, link);
740  }
741  }
742  bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
743  nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
744 
745  need_update = true;
746  }
747 
748  bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
749  if (socket_is_used(sockOutValue)) {
751  lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
752  lengthNode->locx = node->locx + node->width + 20.0f;
753  if (socket_is_used(sockOutVector)) {
754  lengthNode->locy = node->locy - lengthNode->height - 20.0f;
755  }
756  else {
757  lengthNode->locy = node->locy;
758  }
759  bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
760 
762  if (link->fromsock == sockOutValue) {
763  nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
764  nodeRemLink(ntree, link);
765  }
766  }
767  bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
768  nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
769 
770  need_update = true;
771  }
772  }
773  }
774  }
775 
776  if (need_update) {
778  }
779 }
780 
781 /* The Noise node now have a dimension property. This property should be
782  * initialized to 3 by default.
783  */
785 {
787  if (node->type == SH_NODE_TEX_NOISE && node->storage) {
788  NodeTexNoise *tex = (NodeTexNoise *)node->storage;
789  tex->dimensions = 3;
790  }
791  }
792 }
793 
794 /* This structure is only used to pass data to
795  * update_mapping_node_fcurve_rna_path_callback.
796  */
797 typedef struct {
798  char *nodePath;
802 
803 /* This callback function is used by update_mapping_node_inputs_and_properties.
804  * It is executed on every fcurve in the nodetree id updating its RNA paths. The
805  * paths needs to be updated because the node properties became inputs.
806  *
807  * nodes["Mapping"].translation --> nodes["Mapping"].inputs[1].default_value
808  * nodes["Mapping"].rotation --> nodes["Mapping"].inputs[2].default_value
809  * nodes["Mapping"].scale --> nodes["Mapping"].inputs[3].default_value
810  * nodes["Mapping"].max --> nodes["Maximum"].inputs[1].default_value
811  * nodes["Mapping"].min --> nodes["Minimum"].inputs[1].default_value
812  *
813  * The fcurve can be that of any node or property in the nodetree, so we only
814  * update if the rna path starts with the rna path of the mapping node and
815  * doesn't end with "default_value", that is, not the Vector input.
816  */
818  FCurve *fcurve,
819  void *_data)
820 {
822  if (!STRPREFIX(fcurve->rna_path, data->nodePath) ||
823  BLI_str_endswith(fcurve->rna_path, "default_value")) {
824  return;
825  }
826  char *old_fcurve_rna_path = fcurve->rna_path;
827 
828  if (BLI_str_endswith(old_fcurve_rna_path, "translation")) {
829  fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[1].default_value");
830  }
831  else if (BLI_str_endswith(old_fcurve_rna_path, "rotation")) {
832  fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[2].default_value");
833  }
834  else if (BLI_str_endswith(old_fcurve_rna_path, "scale")) {
835  fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[3].default_value");
836  }
837  else if (data->minimumNode && BLI_str_endswith(old_fcurve_rna_path, "max")) {
838  char node_name_esc[sizeof(data->minimumNode->name) * 2];
839  BLI_str_escape(node_name_esc, data->minimumNode->name, sizeof(node_name_esc));
840  fcurve->rna_path = BLI_sprintfN("nodes[\"%s\"].%s", node_name_esc, "inputs[1].default_value");
841  }
842  else if (data->maximumNode && BLI_str_endswith(old_fcurve_rna_path, "min")) {
843  char node_name_esc[sizeof(data->maximumNode->name) * 2];
844  BLI_str_escape(node_name_esc, data->maximumNode->name, sizeof(node_name_esc));
845  fcurve->rna_path = BLI_sprintfN("nodes[\"%s\"].%s", node_name_esc, "inputs[1].default_value");
846  }
847 
848  if (fcurve->rna_path != old_fcurve_rna_path) {
849  MEM_freeN(old_fcurve_rna_path);
850  }
851 }
852 
853 /* The Mapping node has been rewritten to support dynamic inputs. Previously,
854  * the transformation information was stored in a TexMapping struct in the
855  * node->storage member of bNode. Currently, the transformation information
856  * is stored in input sockets. To correct this, we transfer the information
857  * from the TexMapping struct to the input sockets.
858  *
859  * Additionally, the Minimum and Maximum properties are no longer available
860  * in the node. To correct this, a Vector Minimum and/or a Vector Maximum
861  * nodes are added if needed.
862  *
863  * Finally, the TexMapping struct is freed and node->storage is set to NULL.
864  *
865  * Since the RNA paths of the properties changed, we also have to update the
866  * rna_path of the FCurves if they exist. To do that, we loop over FCurves
867  * and check if they control a property of the node, if they do, we update
868  * the path to be that of the corresponding socket in the node or the added
869  * minimum/maximum node.
870  *
871  */
873 {
874  bool need_update = false;
875 
877  /* If node->storage is NULL, then conversion has already taken place.
878  * This can happen if a file with the new mapping node [saved from (2, 81, 8) or newer]
879  * is opened in a blender version prior to (2, 81, 8) and saved from there again. */
880  if (node->type == SH_NODE_MAPPING && node->storage) {
881  TexMapping *mapping = (TexMapping *)node->storage;
882  node->custom1 = mapping->type;
883  node->width = 140.0f;
884 
885  bNodeSocket *sockLocation = nodeFindSocket(node, SOCK_IN, "Location");
886  copy_v3_v3(cycles_node_socket_vector_value(sockLocation), mapping->loc);
887  bNodeSocket *sockRotation = nodeFindSocket(node, SOCK_IN, "Rotation");
888  copy_v3_v3(cycles_node_socket_vector_value(sockRotation), mapping->rot);
889  bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
890  copy_v3_v3(cycles_node_socket_vector_value(sockScale), mapping->size);
891 
892  bNode *maximumNode = NULL;
893  if (mapping->flag & TEXMAP_CLIP_MIN) {
895  maximumNode->custom1 = NODE_VECTOR_MATH_MAXIMUM;
896  if (mapping->flag & TEXMAP_CLIP_MAX) {
897  maximumNode->locx = node->locx + (node->width + 20.0f) * 2.0f;
898  }
899  else {
900  maximumNode->locx = node->locx + node->width + 20.0f;
901  }
902  maximumNode->locy = node->locy;
903  bNodeSocket *sockMaximumB = BLI_findlink(&maximumNode->inputs, 1);
904  copy_v3_v3(cycles_node_socket_vector_value(sockMaximumB), mapping->min);
905  bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector");
906 
908  if (link->fromsock == sockMappingResult) {
909  bNodeSocket *sockMaximumResult = nodeFindSocket(maximumNode, SOCK_OUT, "Vector");
910  nodeAddLink(ntree, maximumNode, sockMaximumResult, link->tonode, link->tosock);
911  nodeRemLink(ntree, link);
912  }
913  }
914  if (!(mapping->flag & TEXMAP_CLIP_MAX)) {
915  bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0);
916  nodeAddLink(ntree, node, sockMappingResult, maximumNode, sockMaximumA);
917  }
918 
919  need_update = true;
920  }
921 
922  bNode *minimumNode = NULL;
923  if (mapping->flag & TEXMAP_CLIP_MAX) {
925  minimumNode->custom1 = NODE_VECTOR_MATH_MINIMUM;
926  minimumNode->locx = node->locx + node->width + 20.0f;
927  minimumNode->locy = node->locy;
928  bNodeSocket *sockMinimumB = BLI_findlink(&minimumNode->inputs, 1);
929  copy_v3_v3(cycles_node_socket_vector_value(sockMinimumB), mapping->max);
930 
931  bNodeSocket *sockMinimumResult = nodeFindSocket(minimumNode, SOCK_OUT, "Vector");
932  bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector");
933 
934  if (maximumNode) {
935  bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0);
936  nodeAddLink(ntree, minimumNode, sockMinimumResult, maximumNode, sockMaximumA);
937  }
938  else {
940  if (link->fromsock == sockMappingResult) {
941  nodeAddLink(ntree, minimumNode, sockMinimumResult, link->tonode, link->tosock);
942  nodeRemLink(ntree, link);
943  }
944  }
945  }
946  bNodeSocket *sockMinimumA = BLI_findlink(&minimumNode->inputs, 0);
947  nodeAddLink(ntree, node, sockMappingResult, minimumNode, sockMinimumA);
948 
949  need_update = true;
950  }
951 
952  MEM_freeN(node->storage);
953  node->storage = NULL;
954 
955  char node_name_esc[sizeof(node->name) * 2];
956  BLI_str_escape(node_name_esc, node->name, sizeof(node_name_esc));
957 
958  char *nodePath = BLI_sprintfN("nodes[\"%s\"]", node_name_esc);
959  MappingNodeFCurveCallbackData data = {nodePath, minimumNode, maximumNode};
961  MEM_freeN(nodePath);
962  }
963  }
964 
965  if (need_update) {
967  }
968 }
969 
970 /* The Musgrave node now has a dimension property. This property should
971  * be initialized to 3 by default.
972  */
974 {
976  if (node->type == SH_NODE_TEX_MUSGRAVE && node->storage) {
977  NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
978  tex->dimensions = 3;
979  }
980  }
981 }
982 
983 /* The Color output of the Musgrave node has been removed. Previously, this
984  * output was just equal to the Fac output. To correct this, we move links
985  * from the Color output to the Fac output if they exist.
986  */
988 {
989  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
990  if (link->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE) {
991  if (link->fromsock->type == SOCK_RGBA) {
992  link->fromsock = link->fromsock->next;
993  }
994  }
995  }
996 }
997 
998 /* The Voronoi node now have a dimension property. This property should be
999  * initialized to 3 by default.
1000  */
1002 {
1004  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1005  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1006  tex->dimensions = 3;
1007  }
1008  }
1009 }
1010 
1011 /* The F3 and F4 features of the Voronoi node have been removed.
1012  * To correct this, we set the feature type to be F2 if it is F3
1013  * or F4. The SHD_VORONOI_F3 and SHD_VORONOI_F4 enum values were
1014  * 2 and 3 respectively.
1015  */
1017 {
1019  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1020  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1021  if (ELEM(tex->feature, 2, 3)) {
1022  tex->feature = SHD_VORONOI_F2;
1023  }
1024  }
1025  }
1026 }
1027 
1028 /* The Fac output of the Voronoi node has been removed. Previously, this
1029  * output was the voronoi distance in the Intensity mode and the Cell ID
1030  * in the Cell mode. To correct this, we update the identifier and name
1031  * of the Fac socket such that it gets mapped to the Distance socket.
1032  * This is supposed to work with update_voronoi_node_coloring.
1033  */
1035 {
1037  if (node->type == SH_NODE_TEX_VORONOI) {
1038  bNodeSocket *facOutput = BLI_findlink(&node->outputs, 1);
1039  strcpy(facOutput->identifier, "Distance");
1040  strcpy(facOutput->name, "Distance");
1041  }
1042  }
1043 }
1044 
1045 /* The Crackle feature of the Voronoi node has been removed. Previously,
1046  * this feature returned the F2 distance minus the F1 distance. The
1047  * crackle feature had an enum value of 4. To fix this we do the
1048  * following:
1049  *
1050  * 1. The node feature is set to F1.
1051  * 2. A new Voronoi node is added and its feature is set to F2.
1052  * 3. The properties, input values, and connections are copied
1053  * from the node to the new Voronoi node so that they match
1054  * exactly.
1055  * 4. A Subtract node is added.
1056  * 5. The outputs of the F1 and F2 voronoi are connected to
1057  * the inputs of the subtract node.
1058  * 6. The output of the subtract node is connected to the
1059  * appropriate sockets.
1060  *
1061  */
1063 {
1064  bool need_update = false;
1065 
1067  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1068  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1069  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1070  bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
1071  if (tex->feature == 4 && (socket_is_used(sockDistance) || socket_is_used(sockColor))) {
1072  tex->feature = SHD_VORONOI_F1;
1073 
1075  NodeTexVoronoi *texVoronoi = (NodeTexVoronoi *)voronoiNode->storage;
1076  texVoronoi->feature = SHD_VORONOI_F2;
1077  texVoronoi->distance = tex->distance;
1078  texVoronoi->dimensions = 3;
1079  voronoiNode->locx = node->locx + node->width + 20.0f;
1080  voronoiNode->locy = node->locy;
1081 
1082  bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
1083  bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
1084  bNodeSocket *sockExponent = nodeFindSocket(node, SOCK_IN, "Exponent");
1085  bNodeSocket *sockVoronoiVector = nodeFindSocket(voronoiNode, SOCK_IN, "Vector");
1086  bNodeSocket *sockVoronoiScale = nodeFindSocket(voronoiNode, SOCK_IN, "Scale");
1087  bNodeSocket *sockVoronoiExponent = nodeFindSocket(voronoiNode, SOCK_IN, "Exponent");
1088  if (sockVector->link) {
1090  sockVector->link->fromnode,
1091  sockVector->link->fromsock,
1092  voronoiNode,
1093  sockVoronoiVector);
1094  }
1096  sockScale);
1097  if (sockScale->link) {
1099  sockScale->link->fromnode,
1100  sockScale->link->fromsock,
1101  voronoiNode,
1102  sockVoronoiScale);
1103  }
1105  sockExponent);
1106  if (sockExponent->link) {
1108  sockExponent->link->fromnode,
1109  sockExponent->link->fromsock,
1110  voronoiNode,
1111  sockVoronoiExponent);
1112  }
1113 
1114  bNode *subtractNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
1115  subtractNode->custom1 = NODE_MATH_SUBTRACT;
1116  subtractNode->locx = voronoiNode->locx + voronoiNode->width + 20.0f;
1117  subtractNode->locy = voronoiNode->locy;
1118  bNodeSocket *sockSubtractOutValue = nodeFindSocket(subtractNode, SOCK_OUT, "Value");
1119 
1121  if (link->fromnode == node) {
1122  nodeAddLink(ntree, subtractNode, sockSubtractOutValue, link->tonode, link->tosock);
1123  nodeRemLink(ntree, link);
1124  }
1125  }
1126 
1127  bNodeSocket *sockDistanceF1 = nodeFindSocket(node, SOCK_OUT, "Distance");
1128  bNodeSocket *sockDistanceF2 = nodeFindSocket(voronoiNode, SOCK_OUT, "Distance");
1129  bNodeSocket *sockSubtractA = BLI_findlink(&subtractNode->inputs, 0);
1130  bNodeSocket *sockSubtractB = BLI_findlink(&subtractNode->inputs, 1);
1131 
1132  nodeAddLink(ntree, node, sockDistanceF1, subtractNode, sockSubtractB);
1133  nodeAddLink(ntree, voronoiNode, sockDistanceF2, subtractNode, sockSubtractA);
1134 
1135  need_update = true;
1136  }
1137  }
1138  }
1139 
1140  if (need_update) {
1142  }
1143 }
1144 
1154 {
1155  bool need_update = false;
1156 
1158  bNode *node = link->fromnode;
1159  if (node && node->type == SH_NODE_TEX_VORONOI && node->storage) {
1160  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1161  if (tex->coloring == 0) {
1162  bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
1163  if (link->fromsock == sockColor) {
1164  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1165  nodeAddLink(ntree, node, sockDistance, link->tonode, link->tosock);
1166  nodeRemLink(ntree, link);
1167  need_update = true;
1168  }
1169  }
1170  else {
1171  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1172  if (link->fromsock == sockDistance) {
1173  bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
1174  nodeAddLink(ntree, node, sockColor, link->tonode, link->tosock);
1175  nodeRemLink(ntree, link);
1176  need_update = true;
1177  }
1178  }
1179  }
1180  }
1181 
1182  if (need_update) {
1184  }
1185 }
1186 
1187 /* Previously, the output euclidean distance was actually the squared
1188  * euclidean distance. To fix this, we square the output distance
1189  * socket if the distance metric is set to SHD_VORONOI_EUCLIDEAN.
1190  */
1192 {
1193  bool need_update = false;
1194 
1196  if (node->type == SH_NODE_TEX_VORONOI && node->storage) {
1197  NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
1198  bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
1199  if (tex->distance == SHD_VORONOI_EUCLIDEAN &&
1200  (ELEM(tex->feature, SHD_VORONOI_F1, SHD_VORONOI_F2)) && socket_is_used(sockDistance)) {
1201  bNode *multiplyNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
1202  multiplyNode->custom1 = NODE_MATH_MULTIPLY;
1203  multiplyNode->locx = node->locx + node->width + 20.0f;
1204  multiplyNode->locy = node->locy;
1205 
1206  bNodeSocket *sockValue = nodeFindSocket(multiplyNode, SOCK_OUT, "Value");
1208  if (link->fromsock == sockDistance) {
1209  nodeAddLink(ntree, multiplyNode, sockValue, link->tonode, link->tosock);
1210  nodeRemLink(ntree, link);
1211  }
1212  }
1213 
1214  bNodeSocket *sockMultiplyA = BLI_findlink(&multiplyNode->inputs, 0);
1215  bNodeSocket *sockMultiplyB = BLI_findlink(&multiplyNode->inputs, 1);
1216 
1217  nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyA);
1218  nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyB);
1219 
1220  need_update = true;
1221  }
1222  }
1223  }
1224 
1225  if (need_update) {
1227  }
1228 }
1229 
1230 /* Noise and Wave Texture nodes: Restore previous Distortion range.
1231  * In 2.81 we used noise() for distortion, now we use snoise() which has twice the range.
1232  * To fix this we halve distortion value, directly or by adding multiply node for used sockets.
1233  */
1235 {
1236  bool need_update = false;
1237 
1240 
1241  bNodeSocket *sockDistortion = nodeFindSocket(node, SOCK_IN, "Distortion");
1242  float *distortion = cycles_node_socket_float_value(sockDistortion);
1243 
1244  if (socket_is_used(sockDistortion) && sockDistortion->link != NULL) {
1245  bNode *distortionInputNode = sockDistortion->link->fromnode;
1246  bNodeSocket *distortionInputSock = sockDistortion->link->fromsock;
1247 
1249  mulNode->custom1 = NODE_MATH_MULTIPLY;
1250  mulNode->locx = node->locx;
1251  mulNode->locy = node->locy - 240.0f;
1252  mulNode->flag |= NODE_HIDDEN;
1253  bNodeSocket *mulSockA = BLI_findlink(&mulNode->inputs, 0);
1254  bNodeSocket *mulSockB = BLI_findlink(&mulNode->inputs, 1);
1255  *cycles_node_socket_float_value(mulSockB) = 0.5f;
1256  bNodeSocket *mulSockOut = nodeFindSocket(mulNode, SOCK_OUT, "Value");
1257 
1258  nodeRemLink(ntree, sockDistortion->link);
1259  nodeAddLink(ntree, distortionInputNode, distortionInputSock, mulNode, mulSockA);
1260  nodeAddLink(ntree, mulNode, mulSockOut, node, sockDistortion);
1261 
1262  need_update = true;
1263  }
1264  else if (*distortion != 0.0f) {
1265  *distortion = *distortion * 0.5f;
1266  }
1267  }
1268  }
1269 
1270  if (need_update) {
1272  }
1273 }
1274 
1286 {
1288  if (node->type == SH_NODE_TEX_WAVE) {
1289  NodeTexWave *tex = (NodeTexWave *)node->storage;
1290  tex->bands_direction = SHD_WAVE_BANDS_DIRECTION_DIAGONAL;
1291  tex->rings_direction = SHD_WAVE_RINGS_DIRECTION_SPHERICAL;
1292 
1293  if (tex->wave_profile == SHD_WAVE_PROFILE_SIN) {
1294  bNodeSocket *sockPhaseOffset = nodeFindSocket(node, SOCK_IN, "Phase Offset");
1295  *cycles_node_socket_float_value(sockPhaseOffset) = M_PI_2;
1296  }
1297  }
1298  }
1299 }
1300 
1302 {
1303  /* Particle shape shared with Eevee. */
1304  if (!MAIN_VERSION_ATLEAST(bmain, 280, 16)) {
1305  for (ParticleSettings *part = bmain->particles.first; part; part = part->id.next) {
1306  IDProperty *cpart = cycles_properties_from_ID(&part->id);
1307 
1308  if (cpart) {
1309  part->shape = cycles_property_float(cpart, "shape", 0.0);
1310  part->rad_root = cycles_property_float(cpart, "root_width", 1.0);
1311  part->rad_tip = cycles_property_float(cpart, "tip_width", 0.0);
1312  part->rad_scale = cycles_property_float(cpart, "radius_scale", 0.01);
1313  if (cycles_property_boolean(cpart, "use_closetip", true)) {
1314  part->shape_flag |= PART_SHAPE_CLOSE_TIP;
1315  }
1316  }
1317  }
1318  }
1319 
1320  if (!MAIN_VERSION_ATLEAST(bmain, 280, 68)) {
1321  /* Unify Cycles and Eevee film transparency. */
1322  for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
1325  if (cscene) {
1326  bool cycles_film_transparency = cycles_property_boolean(
1327  cscene, "film_transparent", false);
1328  scene->r.alphamode = cycles_film_transparency ? R_ALPHAPREMUL : R_ADDSKY;
1329  }
1330  }
1331  }
1332  }
1333 
1334  if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
1335  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1336  if (ntree->type == NTREE_SHADER) {
1338  }
1339  }
1341  }
1342 
1343  if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
1344  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1345  if (ntree->type == NTREE_SHADER) {
1347  }
1348  }
1350  }
1351 
1352  if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
1353  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1354  if (ntree->type == NTREE_SHADER) {
1357  }
1358  }
1360  }
1361 }
1362 
1364 {
1365  enum {
1366  DENOISER_AUTO = 0,
1367  DENOISER_NLM = 1,
1368  DENOISER_OPTIX = 2,
1370  };
1371 
1372  if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
1373  /* Shader node tree changes. After lib linking so we have all the typeinfo
1374  * pointers and updated sockets and we can use the high level node API to
1375  * manipulate nodes. */
1376  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1377  if (ntree->type != NTREE_SHADER) {
1378  continue;
1379  }
1380 
1381  if (!MAIN_VERSION_ATLEAST(bmain, 273, 5)) {
1382  /* Euler order was ZYX in previous versions. */
1385  }
1386  }
1387 
1388  if (!MAIN_VERSION_ATLEAST(bmain, 276, 6)) {
1391  }
1392  }
1393 
1394  if (!MAIN_VERSION_ATLEAST(bmain, 279, 2) ||
1395  (MAIN_VERSION_ATLEAST(bmain, 280, 0) && !MAIN_VERSION_ATLEAST(bmain, 280, 4))) {
1397  }
1398 
1399  if (!MAIN_VERSION_ATLEAST(bmain, 279, 3)) {
1402  }
1403  }
1404 
1405  if (!MAIN_VERSION_ATLEAST(bmain, 279, 4) ||
1406  (MAIN_VERSION_ATLEAST(bmain, 280, 0) && !MAIN_VERSION_ATLEAST(bmain, 280, 5))) {
1407  /* Switch to squared roughness convention */
1409  }
1410 
1411  if (!MAIN_VERSION_ATLEAST(bmain, 279, 5)) {
1413  }
1414 
1415  if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
1418  }
1419  }
1420  }
1422  }
1423 
1424  if (!MAIN_VERSION_ATLEAST(bmain, 280, 64)) {
1425  /* Unify Cycles and Eevee settings. */
1426  Scene *scene = bmain->scenes.first;
1427  const char *engine = (scene) ? scene->r.engine : "CYCLES";
1428 
1429  for (Light *light = bmain->lights.first; light; light = light->id.next) {
1430  light_emission_unify(light, engine);
1431  }
1432  }
1433 
1434  if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
1435  /* Unify Cycles and Eevee depth of field. */
1436  Scene *scene = bmain->scenes.first;
1437  const char *engine = (scene) ? scene->r.engine : "CYCLES";
1438 
1439  if (STREQ(engine, RE_engine_id_CYCLES)) {
1440  for (Camera *camera = bmain->cameras.first; camera; camera = camera->id.next) {
1441  IDProperty *ccamera = cycles_properties_from_ID(&camera->id);
1442  if (ccamera) {
1443  const bool is_fstop = cycles_property_int(ccamera, "aperture_type", 0) == 1;
1444 
1445  camera->dof.aperture_fstop = cycles_property_float(ccamera, "aperture_fstop", 5.6f);
1446  camera->dof.aperture_blades = cycles_property_int(ccamera, "aperture_blades", 0);
1447  camera->dof.aperture_rotation = cycles_property_float(ccamera, "aperture_rotation", 0.0);
1448  camera->dof.aperture_ratio = cycles_property_float(ccamera, "aperture_ratio", 1.0f);
1449  camera->dof.flag |= CAM_DOF_ENABLED;
1450 
1451  float aperture_size = cycles_property_float(ccamera, "aperture_size", 0.0f);
1452 
1453  if (is_fstop) {
1454  continue;
1455  }
1456  if (aperture_size > 0.0f) {
1457  if (camera->type == CAM_ORTHO) {
1458  camera->dof.aperture_fstop = 1.0f / (2.0f * aperture_size);
1459  }
1460  else {
1461  camera->dof.aperture_fstop = (camera->lens * 1e-3f) / (2.0f * aperture_size);
1462  }
1463 
1464  continue;
1465  }
1466  }
1467 
1468  /* No depth of field, set default settings. */
1469  camera->dof.aperture_fstop = 2.8f;
1470  camera->dof.aperture_blades = 0;
1471  camera->dof.aperture_rotation = 0.0f;
1472  camera->dof.aperture_ratio = 1.0f;
1473  camera->dof.flag &= ~CAM_DOF_ENABLED;
1474  }
1475  }
1476  }
1477 
1478  if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
1479  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1480  if (ntree->type == NTREE_SHADER) {
1482  }
1483  }
1485  }
1486 
1487  if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
1488  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1489  if (ntree->type == NTREE_SHADER) {
1495  }
1496  }
1498  }
1499 
1500  if (!MAIN_VERSION_ATLEAST(bmain, 281, 7)) {
1501  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1502  if (ntree->type == NTREE_SHADER) {
1504  }
1505  }
1507  }
1508 
1509  if (!MAIN_VERSION_ATLEAST(bmain, 281, 8)) {
1510  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1511  if (ntree->type == NTREE_SHADER) {
1513  }
1514  }
1516  }
1517 
1518  if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
1519  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1520  if (ntree->type == NTREE_SHADER) {
1522  }
1523  }
1525  }
1526 
1527  if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
1528  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1529  if (ntree->type == NTREE_SHADER) {
1534  }
1535  }
1537  }
1538 
1539  if (!MAIN_VERSION_ATLEAST(bmain, 282, 4)) {
1540  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1541  if (ntree->type == NTREE_SHADER) {
1543  }
1544  }
1546  }
1547 
1548  if (!MAIN_VERSION_ATLEAST(bmain, 283, 4)) {
1549  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1550  if (ntree->type == NTREE_SHADER) {
1552  }
1553  }
1555  }
1556 
1557  if (!MAIN_VERSION_ATLEAST(bmain, 290, 5)) {
1558  /* New denoiser settings. */
1559  for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
1561 
1562  /* Check if any view layers had (optix) denoising enabled. */
1563  bool use_optix = false;
1564  bool use_denoising = false;
1565  for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
1566  view_layer = view_layer->next) {
1567  IDProperty *cview_layer = cycles_properties_from_view_layer(view_layer);
1568  if (cview_layer) {
1569  use_denoising = use_denoising ||
1570  cycles_property_boolean(cview_layer, "use_denoising", false);
1571  use_optix = use_optix ||
1572  cycles_property_boolean(cview_layer, "use_optix_denoising", false);
1573  }
1574  }
1575 
1576  if (cscene) {
1577  /* Enable denoiser if it was enabled for one view layer before. */
1578  cycles_property_int_set(cscene, "denoiser", (use_optix) ? DENOISER_OPTIX : DENOISER_NLM);
1579  cycles_property_boolean_set(cscene, "use_denoising", use_denoising);
1580 
1581  /* Migrate Optix denoiser to new settings. */
1582  if (cycles_property_int(cscene, "preview_denoising", 0)) {
1583  cycles_property_boolean_set(cscene, "use_preview_denoising", true);
1584  cycles_property_int_set(cscene, "preview_denoiser", DENOISER_AUTO);
1585  }
1586  }
1587 
1588  /* Enable denoising in all view layer if there was no denoising before,
1589  * so that enabling the scene settings auto enables it for all view layers. */
1590  if (!use_denoising) {
1591  for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
1592  view_layer = view_layer->next) {
1593  IDProperty *cview_layer = cycles_properties_from_view_layer(view_layer);
1594  if (cview_layer) {
1595  cycles_property_boolean_set(cview_layer, "use_denoising", true);
1596  }
1597  }
1598  }
1599  }
1600  }
1601 
1602  /* Move visibility from Cycles to Blender. */
1603  if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) {
1604  LISTBASE_FOREACH (Object *, object, &bmain->objects) {
1605  IDProperty *cvisibility = cycles_visibility_properties_from_ID(&object->id);
1606  int flag = 0;
1607 
1608  if (cvisibility) {
1609  flag |= cycles_property_boolean(cvisibility, "camera", true) ? 0 : OB_HIDE_CAMERA;
1610  flag |= cycles_property_boolean(cvisibility, "diffuse", true) ? 0 : OB_HIDE_DIFFUSE;
1611  flag |= cycles_property_boolean(cvisibility, "glossy", true) ? 0 : OB_HIDE_GLOSSY;
1612  flag |= cycles_property_boolean(cvisibility, "transmission", true) ? 0 :
1614  flag |= cycles_property_boolean(cvisibility, "scatter", true) ? 0 : OB_HIDE_VOLUME_SCATTER;
1615  flag |= cycles_property_boolean(cvisibility, "shadow", true) ? 0 : OB_HIDE_SHADOW;
1616  }
1617 
1618  IDProperty *cobject = cycles_properties_from_ID(&object->id);
1619  if (cobject) {
1620  flag |= cycles_property_boolean(cobject, "is_holdout", false) ? OB_HOLDOUT : 0;
1621  flag |= cycles_property_boolean(cobject, "is_shadow_catcher", false) ? OB_SHADOW_CATCHER :
1622  0;
1623  }
1624 
1625  if (object->type == OB_LAMP) {
1627  }
1628 
1629  /* Clear unused bits from old version, and add new flags. */
1630  object->visibility_flag &= (OB_HIDE_VIEWPORT | OB_HIDE_SELECT | OB_HIDE_RENDER);
1631  object->visibility_flag |= flag;
1632  }
1633  }
1634 
1635  if (!MAIN_VERSION_ATLEAST(bmain, 300, 25)) {
1636  /* Removal of NLM denoiser. */
1637  for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
1639 
1640  if (cscene) {
1641  if (cycles_property_int(cscene, "denoiser", DENOISER_NLM) == DENOISER_NLM) {
1643  }
1644  }
1645  }
1646  }
1647 }
void BKE_fcurves_id_cb(struct ID *id, ID_FCurve_Edit_Callback func, void *user_data)
Definition: anim_data.c:1157
void BKE_curvemapping_changed_all(struct CurveMapping *cumap)
Definition: colortools.c:932
#define IDP_Float(prop)
Definition: BKE_idprop.h:269
#define IDP_Int(prop)
Definition: BKE_idprop.h:244
struct IDProperty * IDP_GetProperties(struct ID *id, bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:778
struct IDProperty * IDP_New(char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:887
struct IDProperty * IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop, const char *name, char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:631
#define MAIN_VERSION_ATLEAST(main, ver, subver)
Definition: BKE_main.h:427
#define SH_NODE_BSDF_PRINCIPLED
Definition: BKE_node.h:1164
#define SH_NODE_EMISSION
Definition: BKE_node.h:1115
#define SH_NODE_TEX_ENVIRONMENT
Definition: BKE_node.h:1128
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link)
Definition: node.cc:2338
#define SH_NODE_MATH
Definition: BKE_node.h:1092
#define SH_NODE_AMBIENT_OCCLUSION
Definition: BKE_node.h:1143
#define SH_NODE_OUTPUT_MATERIAL
Definition: BKE_node.h:1101
#define FOREACH_NODETREE_END
Definition: BKE_node.h:1058
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2296
struct bNodeSocket * nodeFindSocket(const struct bNode *node, eNodeSocketInOut in_out, const char *identifier)
#define SH_NODE_BSDF_ANISOTROPIC
Definition: BKE_node.h:1108
#define SH_NODE_BSDF_GLOSSY
Definition: BKE_node.h:1110
#define SH_NODE_MAPPING
Definition: BKE_node.h:1088
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition: BKE_node.h:1048
#define SH_NODE_BSDF_GLASS
Definition: BKE_node.h:1111
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2151
#define SH_NODE_DISPLACEMENT
Definition: BKE_node.h:1168
#define SH_NODE_BSDF_REFRACTION
Definition: BKE_node.h:1144
#define SH_NODE_TEX_MUSGRAVE
Definition: BKE_node.h:1125
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list)
Definition: BLI_listbase.h:362
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:23
@ EULER_ORDER_XYZ
@ EULER_ORDER_ZYX
void quat_to_eulO(float eul[3], short order, const float quat[4])
void eulO_to_quat(float quat[4], const float eul[3], short order)
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:483
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL()
Definition: string.c:887
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:250
#define STRPREFIX(a, b)
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
external readfile function prototypes.
@ IDP_FLOAT
Definition: DNA_ID.h:138
@ IDP_INT
Definition: DNA_ID.h:137
@ IDP_GROUP
Definition: DNA_ID.h:141
@ 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
@ SHD_SUBSURFACE_BURLEY
@ SHD_SUBSURFACE_RANDOM_WALK
@ 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_WAVE_PROFILE_SIN
@ SHD_OUTPUT_CYCLES
@ SHD_WAVE_BANDS_DIRECTION_DIAGONAL
@ SHD_VORONOI_F2
@ SHD_VORONOI_F1
@ SHD_WAVE_RINGS_DIRECTION_SPHERICAL
#define NODE_HIDDEN
@ SOCK_OUT
@ SOCK_IN
@ SHD_VORONOI_EUCLIDEAN
@ SOCK_IN_USE
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_RGBA
#define SHD_AO_LOCAL
#define NTREE_SHADER
#define SHD_SPACE_OBJECT
@ OB_HIDE_TRANSMISSION
@ OB_HOLDOUT
@ OB_HIDE_RENDER
@ OB_HIDE_CAMERA
@ OB_HIDE_SELECT
@ OB_HIDE_GLOSSY
@ OB_HIDE_SHADOW
@ OB_SHADOW_CATCHER
@ OB_HIDE_VIEWPORT
@ OB_HIDE_DIFFUSE
@ OB_HIDE_VOLUME_SCATTER
@ OB_LAMP
@ PART_SHAPE_CLOSE_TIP
@ R_ADDSKY
@ R_ALPHAPREMUL
#define TEXMAP_CLIP_MIN
#define TEXMAP_CLIP_MAX
@ COLOR_ROLE_DATA
const char * IMB_colormanagement_role_colorspace_name_get(int role)
Read Guarded memory(de)allocation.
struct bNode * ntreeShaderOutputNode(struct bNodeTree *ntree, int target)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color SH_NODE_CURVE_VEC
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise SH_NODE_TEX_VORONOI
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum SH_NODE_VECTOR_MATH
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture SH_NODE_TEX_NOISE
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block SH_NODE_TEX_IMAGE
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise SH_NODE_TEX_WAVE
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
OperationNode * node
Scene scene
@ DENOISER_OPTIX
Definition: denoise.h:13
@ DENOISER_OPENIMAGEDENOISE
Definition: denoise.h:14
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
bNodeTree * ntree
DRWShaderLibrary * lib
bNodeSocketValueRGBA * color_socket
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
#define sqrtf(x)
Definition: metal/compat.h:243
const char * RE_engine_id_CYCLES
Definition: scene.cc:1697
short totpoint
CurveMapPoint * curve
CurveMap cm[4]
char * rna_path
Definition: DNA_ID.h:368
void * next
Definition: DNA_ID.h:369
float r
float energy
short use_nodes
struct bNodeTree * nodetree
short type
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase scenes
Definition: BKE_main.h:168
ListBase lights
Definition: BKE_main.h:178
ListBase particles
Definition: BKE_main.h:194
ListBase cameras
Definition: BKE_main.h:179
ListBase objects
Definition: BKE_main.h:170
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
void version_socket_update_is_used(bNodeTree *ntree)
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_visibility_properties_from_ID(ID *id)
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 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 bool node_has_roughness(const bNode *node)
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)