Blender V4.5
versioning_420.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#define DNA_DEPRECATED_ALLOW
10
11/* Define macros in `DNA_genfile.h`. */
12#define DNA_GENFILE_VERSIONING_MACROS
13
14#include "DNA_anim_types.h"
15#include "DNA_brush_types.h"
17#include "DNA_defaults.h"
18#include "DNA_genfile.h"
19#include "DNA_light_types.h"
21#include "DNA_material_types.h"
22#include "DNA_sequence_types.h"
24#include "DNA_world_types.h"
25
26#undef DNA_GENFILE_VERSIONING_MACROS
27
28#include "BLI_listbase.h"
29#include "BLI_math_vector.h"
30#include "BLI_string.h"
31
32#include "BKE_anim_data.hh"
33#include "BKE_colortools.hh"
34#include "BKE_customdata.hh"
35#include "BKE_grease_pencil.hh"
36#include "BKE_main.hh"
37#include "BKE_material.hh"
38#include "BKE_node.hh"
40
41#include "MOV_enums.hh"
42
43#include "SEQ_iterator.hh"
44#include "SEQ_sequencer.hh"
45
46#include "BLT_translation.hh"
47
48#include "BLO_read_write.hh"
49
50#include "readfile.hh"
51
52#include "versioning_common.hh"
53
59{
60 const blender::StringRef rna_path(fcurve->rna_path);
61 constexpr char const *rna_path_prefix = "collections[";
62 if (!rna_path.startswith(rna_path_prefix)) {
63 return;
64 }
65
66 const std::string path_remainder(rna_path.drop_known_prefix(rna_path_prefix));
67 MEM_freeN(fcurve->rna_path);
68 fcurve->rna_path = BLI_sprintfN("collections_all[%s", path_remainder.c_str());
69}
70
72{
76
77 short *material_len = BKE_object_material_len_p(object);
78 if (!material_len) {
79 return;
80 }
81
82 using namespace blender;
83 bool hide_shadows = *material_len > 0;
84 for (int i : IndexRange(*material_len)) {
85 Material *material = BKE_object_material_get(object, i + 1);
86 if (!material || material->blend_shadow != MA_BS_NONE) {
87 hide_shadows = false;
88 }
89 }
90
91 /* Enable the hide_shadow flag only if there's not any shadow casting material. */
93}
94
103 /* Alpha input is 0. */
105 /* Alpha input is 1. */
107 /* Alpha is between 0 and 1, from a graph input or the result of one blending operation. */
109 /* Alpha is unknown and the result of more than one blending operation. */
111 };
112
113 /* Socket that is the source of the potential semi-transparency. */
114 bNodeSocket *socket = nullptr;
115 /* State of the source. */
117 /* True if socket is transparency instead of alpha (e.g: `1-alpha`). */
118 bool is_transparency = false;
119
120 static AlphaSource alpha_source(bNodeSocket *fac, bool inverted = false)
121 {
122 return {fac, ALPHA_SEMI_TRANSPARENT, inverted};
123 }
125 {
126 return {nullptr, ALPHA_OPAQUE, false};
127 }
128 static AlphaSource fully_transparent(bNodeSocket *socket = nullptr, bool inverted = false)
129 {
130 return {socket, ALPHA_FULLY_TRANSPARENT, inverted};
131 }
133 {
134 return {nullptr, ALPHA_COMPLEX_MIX, false};
135 }
136
137 bool is_opaque() const
138 {
139 return state == ALPHA_OPAQUE;
140 }
142 {
144 }
145 bool is_transparent() const
146 {
147 return state != ALPHA_OPAQUE;
148 }
150 {
152 }
153 bool is_complex() const
154 {
155 return state == ALPHA_COMPLEX_MIX;
156 }
157
158 /* Combine two source together with a blending parameter. */
159 static AlphaSource mix(const AlphaSource &a, const AlphaSource &b, bNodeSocket *fac)
160 {
161 if (a.is_complex() || b.is_complex()) {
162 return complex_alpha();
163 }
164 if (a.is_semi_transparent() || b.is_semi_transparent()) {
165 return complex_alpha();
166 }
167 if (a.is_fully_transparent() && b.is_fully_transparent()) {
168 return fully_transparent();
169 }
170 if (a.is_opaque() && b.is_opaque()) {
171 return opaque();
172 }
173 /* Only one of them is fully transparent. */
174 return alpha_source(fac, !a.is_transparent());
175 }
176
177 /* Combine two source together with an additive blending parameter. */
178 static AlphaSource add(const AlphaSource &a, const AlphaSource &b)
179 {
180 if (a.is_complex() || b.is_complex()) {
181 return complex_alpha();
182 }
183 if (a.is_semi_transparent() && b.is_transparent()) {
184 return complex_alpha();
185 }
186 if (a.is_transparent() && b.is_semi_transparent()) {
187 return complex_alpha();
188 }
189 /* Either one of them is opaque or they are both opaque. */
190 return a.is_transparent() ? a : b;
191 }
192};
193
198{
199 if (depth > 100) {
200 /* Protection against infinite / very long recursion.
201 * Also a node-tree with that much depth is likely to not be compatible. */
203 }
204
205 if (socket->link == nullptr) {
206 /* Unconnected closure socket is always opaque black. */
207 return AlphaSource::opaque();
208 }
209
210 bNode *node = socket->link->fromnode;
211
212 switch (node->type_legacy) {
213 case NODE_REROUTE: {
215 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0)), depth + 1);
216 }
217
218 case NODE_GROUP: {
220 }
221
223 bNodeSocket *socket = blender::bke::node_find_socket(*node, SOCK_IN, "Color");
224 if (socket->link == nullptr) {
225 float *socket_color_value = version_cycles_node_socket_rgba_value(socket);
226 if ((socket_color_value[0] == 0.0f) && (socket_color_value[1] == 0.0f) &&
227 (socket_color_value[2] == 0.0f))
228 {
229 return AlphaSource::opaque();
230 }
231 if ((socket_color_value[0] == 1.0f) && (socket_color_value[1] == 1.0f) &&
232 (socket_color_value[2] == 1.0f))
233 {
234 return AlphaSource::fully_transparent(socket, true);
235 }
236 }
237 return AlphaSource::alpha_source(socket, true);
238 }
239
240 case SH_NODE_MIX_SHADER: {
241 bNodeSocket *socket = blender::bke::node_find_socket(*node, SOCK_IN, "Fac");
243 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1)), depth + 1);
245 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2)), depth + 1);
246
247 if (socket->link == nullptr) {
248 float socket_float_value = *version_cycles_node_socket_float_value(socket);
249 if (socket_float_value == 0.0f) {
250 return src0;
251 }
252 if (socket_float_value == 1.0f) {
253 return src1;
254 }
255 }
256 return AlphaSource::mix(src0, src1, socket);
257 }
258
259 case SH_NODE_ADD_SHADER: {
261 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0)), depth + 1);
263 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1)), depth + 1);
264 return AlphaSource::add(src0, src1);
265 }
266
268 bNodeSocket *socket = blender::bke::node_find_socket(*node, SOCK_IN, "Alpha");
269 if (socket->link == nullptr) {
270 float socket_value = *version_cycles_node_socket_float_value(socket);
271 if (socket_value == 0.0f) {
272 return AlphaSource::fully_transparent(socket);
273 }
274 if (socket_value == 1.0f) {
275 return AlphaSource::opaque();
276 }
277 }
278 return AlphaSource::alpha_source(socket);
279 }
280
282 bNodeSocket *socket = blender::bke::node_find_socket(*node, SOCK_IN, "Transparency");
283 if (socket->link == nullptr) {
284 float socket_value = *version_cycles_node_socket_float_value(socket);
285 if (socket_value == 0.0f) {
286 return AlphaSource::fully_transparent(socket, true);
287 }
288 if (socket_value == 1.0f) {
289 return AlphaSource::opaque();
290 }
291 }
292 return AlphaSource::alpha_source(socket, true);
293 }
294
295 default:
296 return AlphaSource::opaque();
297 }
298}
299
309{
311 if (output_node == nullptr) {
312 return true;
313 }
314 bNodeSocket *surface_socket = blender::bke::node_find_socket(*output_node, SOCK_IN, "Surface");
315
316 AlphaSource alpha = versioning_eevee_alpha_source_get(surface_socket);
317
318 if (alpha.is_complex()) {
319 return false;
320 }
321 if (alpha.socket == nullptr) {
322 return true;
323 }
324
325 bool is_opaque = (threshold == 2.0f);
326 if (is_opaque) {
327 if (alpha.socket->link != nullptr) {
329 }
330
331 float value = (alpha.is_transparency) ? 0.0f : 1.0f;
332 float values[4] = {value, value, value, 1.0f};
333
334 /* Set default value to opaque. */
335 if (alpha.socket->type == SOCK_RGBA) {
337 }
338 else {
340 }
341 }
342 else {
343 if (alpha.socket->link != nullptr) {
344 /* Insert math node. */
345 bNode *to_node = alpha.socket->link->tonode;
346 bNode *from_node = alpha.socket->link->fromnode;
347 bNodeSocket *to_socket = alpha.socket->link->tosock;
348 bNodeSocket *from_socket = alpha.socket->link->fromsock;
350
351 bNode *math_node = blender::bke::node_add_node(nullptr, *ntree, "ShaderNodeMath");
352 math_node->custom1 = NODE_MATH_GREATER_THAN;
353 math_node->flag |= NODE_HIDDEN;
354 math_node->parent = to_node->parent;
355 math_node->locx_legacy = to_node->locx_legacy - math_node->width - 30;
356 math_node->locy_legacy = min_ff(to_node->locy_legacy, from_node->locy_legacy);
357
358 bNodeSocket *input_1 = static_cast<bNodeSocket *>(BLI_findlink(&math_node->inputs, 0));
359 bNodeSocket *input_2 = static_cast<bNodeSocket *>(BLI_findlink(&math_node->inputs, 1));
360 bNodeSocket *output = static_cast<bNodeSocket *>(math_node->outputs.first);
361 bNodeSocket *alpha_sock = input_1;
362 bNodeSocket *threshold_sock = input_2;
363
364 blender::bke::node_add_link(*ntree, *from_node, *from_socket, *math_node, *alpha_sock);
365 blender::bke::node_add_link(*ntree, *math_node, *output, *to_node, *to_socket);
366
368 1.0f - threshold :
369 threshold;
370 }
371 else {
372 /* Modify alpha value directly. */
373 if (alpha.socket->type == SOCK_RGBA) {
374 float *default_value = version_cycles_node_socket_rgba_value(alpha.socket);
375 float sum = default_value[0] + default_value[1] + default_value[2];
376 /* Don't do the division if possible to avoid float imprecision. */
377 float avg = (sum >= 3.0f) ? 1.0f : (sum / 3.0f);
378 float value = float((alpha.is_transparency) ? (avg > 1.0f - threshold) :
379 (avg > threshold));
380 float values[4] = {value, value, value, 1.0f};
381 copy_v4_v4(default_value, values);
382 }
383 else {
384 float *default_value = version_cycles_node_socket_float_value(alpha.socket);
385 *default_value = float((alpha.is_transparency) ? (*default_value > 1.0f - threshold) :
386 (*default_value > threshold));
387 }
388 }
389 }
390 return true;
391}
392
394{
395 if (!material->use_nodes || material->nodetree == nullptr) {
396 return;
397 }
398 bNodeTree *ntree = material->nodetree;
399
402 if (output_node == nullptr) {
403 return;
404 }
405
406 bNodeSocket *existing_out_sock = blender::bke::node_find_socket(
407 *output_node, SOCK_IN, "Surface");
408 bNodeSocket *volume_sock = blender::bke::node_find_socket(*output_node, SOCK_IN, "Volume");
409 if (existing_out_sock->link == nullptr && volume_sock->link) {
410 /* Don't apply versioning to a material that only has a volumetric input as this makes the
411 * object surface opaque to the camera, hiding the volume inside. */
412 return;
413 }
414
415 if (output_node->custom1 == SHD_OUTPUT_ALL) {
416 /* We do not want to affect Cycles. So we split the output into two specific outputs. */
417 output_node->custom1 = SHD_OUTPUT_CYCLES;
418
419 bNode *new_output = blender::bke::node_add_node(nullptr, *ntree, "ShaderNodeOutputMaterial");
420 new_output->custom1 = SHD_OUTPUT_EEVEE;
421 new_output->parent = output_node->parent;
422 new_output->locx_legacy = output_node->locx_legacy;
423 new_output->locy_legacy = output_node->locy_legacy - output_node->height - 120;
424
425 auto copy_link = [&](const char *socket_name) {
426 bNodeSocket *sock = blender::bke::node_find_socket(*output_node, SOCK_IN, socket_name);
427 if (sock && sock->link) {
428 bNodeLink *link = sock->link;
429 bNodeSocket *to_sock = blender::bke::node_find_socket(*new_output, SOCK_IN, socket_name);
431 *ntree, *link->fromnode, *link->fromsock, *new_output, *to_sock);
432 }
433 };
434
435 /* Don't copy surface as that is handled later */
436 copy_link("Volume");
437 copy_link("Displacement");
438 copy_link("Thickness");
439
440 output_node = new_output;
441 }
442
443 bNodeSocket *out_sock = blender::bke::node_find_socket(*output_node, SOCK_IN, "Surface");
444 bNodeSocket *old_out_sock = blender::bke::node_find_socket(*old_output_node, SOCK_IN, "Surface");
445
446 /* Add mix node for mixing between original material, and transparent BSDF for shadows */
447 bNode *mix_node = blender::bke::node_add_node(nullptr, *ntree, "ShaderNodeMixShader");
448 STRNCPY(mix_node->label, "Disable Shadow");
449 mix_node->flag |= NODE_HIDDEN;
450 mix_node->parent = output_node->parent;
451 mix_node->locx_legacy = output_node->locx_legacy;
452 mix_node->locy_legacy = output_node->locy_legacy - output_node->height - 120;
453 bNodeSocket *mix_fac = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->inputs, 0));
454 bNodeSocket *mix_in_1 = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->inputs, 1));
455 bNodeSocket *mix_in_2 = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->inputs, 2));
456 bNodeSocket *mix_out = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->outputs, 0));
457 if (old_out_sock->link != nullptr) {
459 *old_out_sock->link->fromnode,
460 *old_out_sock->link->fromsock,
461 *mix_node,
462 *mix_in_1);
463 if (out_sock->link != nullptr) {
464 blender::bke::node_remove_link(ntree, *out_sock->link);
465 }
466 }
467 blender::bke::node_add_link(*ntree, *mix_node, *mix_out, *output_node, *out_sock);
468
469 /* Add light path node to control shadow visibility */
470 bNode *lp_node = blender::bke::node_add_node(nullptr, *ntree, "ShaderNodeLightPath");
471 lp_node->flag |= NODE_HIDDEN;
472 lp_node->parent = output_node->parent;
473 lp_node->locx_legacy = output_node->locx_legacy;
474 lp_node->locy_legacy = mix_node->locy_legacy + 35;
475 bNodeSocket *is_shadow = blender::bke::node_find_socket(*lp_node, SOCK_OUT, "Is Shadow Ray");
476 blender::bke::node_add_link(*ntree, *lp_node, *is_shadow, *mix_node, *mix_fac);
477 /* Hide unconnected sockets for cleaner look. */
478 LISTBASE_FOREACH (bNodeSocket *, sock, &lp_node->outputs) {
479 if (sock != is_shadow) {
480 sock->flag |= SOCK_HIDDEN;
481 }
482 }
483
484 /* Add transparent BSDF to make shadows transparent. */
485 bNode *bsdf_node = blender::bke::node_add_node(nullptr, *ntree, "ShaderNodeBsdfTransparent");
486 bsdf_node->flag |= NODE_HIDDEN;
487 bsdf_node->parent = output_node->parent;
488 bsdf_node->locx_legacy = output_node->locx_legacy;
489 bsdf_node->locy_legacy = mix_node->locy_legacy - 35;
490 bNodeSocket *bsdf_out = blender::bke::node_find_socket(*bsdf_node, SOCK_OUT, "BSDF");
491 blender::bke::node_add_link(*ntree, *bsdf_node, *bsdf_out, *mix_node, *mix_in_2);
492}
493
495{
496 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 15)) {
497 /* Change drivers and animation on "armature.collections" to
498 * ".collections_all", so that they are drawn correctly in the tree view,
499 * and keep working when the collection is moved around in the hierarchy. */
500 LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
501 AnimData *adt = BKE_animdata_from_id(&arm->id);
502 if (!adt) {
503 continue;
504 }
505
506 LISTBASE_FOREACH (FCurve *, fcurve, &adt->drivers) {
508 }
509 if (adt->action) {
510 LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) {
512 }
513 }
514 }
515 }
516
517 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 23)) {
518 /* Shift animation data to accommodate the new Roughness input. */
521 }
522
523 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 50)) {
525 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
527 }
528 }
529 }
530
531 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 51)) {
532 /* Convert blend method to math nodes. */
534 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
535 if (!material->use_nodes || material->nodetree == nullptr) {
536 /* Nothing to version. */
537 }
538 else if (ELEM(material->blend_method, MA_BM_HASHED, MA_BM_BLEND)) {
539 /* Compatible modes. Nothing to change. */
540 }
541 else if (material->blend_shadow == MA_BS_NONE) {
542 /* No need to match the surface since shadows are disabled. */
543 }
544 else if (material->blend_shadow == MA_BS_SOLID) {
545 /* This is already versioned an transferred to `transparent_shadows`. */
546 }
547 else if ((material->blend_shadow == MA_BS_CLIP && material->blend_method != MA_BM_CLIP) ||
548 (material->blend_shadow == MA_BS_HASHED))
549 {
551 fd->reports,
553 RPT_("Material %s could not be converted because of different Blend Mode "
554 "and Shadow Mode (need manual adjustment)\n"),
555 material->id.name + 2);
556 }
557 else {
558 /* TODO(fclem): Check if threshold is driven or has animation. Bail out if needed? */
559
560 float threshold = (material->blend_method == MA_BM_CLIP) ? material->alpha_threshold :
561 2.0f;
562
563 if (!versioning_eevee_material_blend_mode_settings(material->nodetree, threshold)) {
566 RPT_("Material %s could not be converted because of non-trivial "
567 "alpha blending (need manual adjustment)\n"),
568 material->id.name + 2);
569 }
570 }
571
572 if (material->blend_shadow == MA_BS_NONE) {
574 }
575 /* Set blend_mode & blend_shadow for forward compatibility. */
576 material->blend_method = (material->blend_method != MA_BM_BLEND) ? MA_BM_HASHED :
578 material->blend_shadow = (material->blend_shadow == MA_BS_SOLID) ? MA_BS_SOLID :
580 }
581 }
582 }
583
584 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 52)) {
585 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
586 if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
588 }
589 }
590 }
591}
592
599
600/* The Hue Correct curve now wraps around by specifying CUMA_USE_WRAPPING, which means it no longer
601 * makes sense to have curve maps outside of the [0, 1] range, so enable clipping and reset the
602 * clip and view ranges. */
603static void hue_correct_set_wrapping(CurveMapping *curve_mapping)
604{
605 curve_mapping->flag |= CUMA_DO_CLIP;
606 curve_mapping->flag |= CUMA_USE_WRAPPING;
607
608 curve_mapping->clipr.xmin = 0.0f;
609 curve_mapping->clipr.xmax = 1.0f;
610 curve_mapping->clipr.ymin = 0.0f;
611 curve_mapping->clipr.ymax = 1.0f;
612
613 curve_mapping->curr.xmin = 0.0f;
614 curve_mapping->curr.xmax = 1.0f;
615 curve_mapping->curr.ymin = 0.0f;
616 curve_mapping->curr.ymax = 1.0f;
617}
618
619static bool strip_hue_correct_set_wrapping(Strip *strip, void * /*user_data*/)
620{
622 if (smd->type == seqModifierType_HueCorrect) {
624 CurveMapping *cumap = (CurveMapping *)&hcmd->curve_mapping;
626 }
627 }
628 return true;
629}
630
632{
633 if (ntree->type == NTREE_COMPOSIT) {
634 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
635
636 if (node->type_legacy == CMP_NODE_HUECORRECT) {
637 CurveMapping *cumap = (CurveMapping *)node->storage;
639 }
640 }
641 }
642}
643
645{
646 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
647 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
648 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
649 if (sl->spacetype != SPACE_IMAGE) {
650 continue;
651 }
652
653 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
654
655 if (ARegion *new_shelf_region = do_versions_add_region_if_not_found(
656 regionbase, RGN_TYPE_ASSET_SHELF, __func__, RGN_TYPE_TOOL_HEADER))
657 {
658 new_shelf_region->regiondata = MEM_callocN<RegionAssetShelf>(__func__);
659 new_shelf_region->alignment = RGN_ALIGN_BOTTOM;
660 new_shelf_region->flag |= RGN_FLAG_HIDDEN;
661 }
662 if (ARegion *new_shelf_header = do_versions_add_region_if_not_found(
664 {
665 new_shelf_header->alignment = RGN_ALIGN_BOTTOM | RGN_ALIGN_HIDE_WITH_PREV;
666 }
667 }
668 }
669 }
670}
671
672/* Convert EEVEE-Legacy refraction depth to EEVEE-Next thickness tree. */
673static void version_refraction_depth_to_thickness_value(bNodeTree *ntree, float thickness)
674{
675 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
676 if (node->type_legacy != SH_NODE_OUTPUT_MATERIAL) {
677 continue;
678 }
679
680 bNodeSocket *thickness_socket = blender::bke::node_find_socket(*node, SOCK_IN, "Thickness");
681 if (thickness_socket == nullptr) {
682 continue;
683 }
684
685 bool has_link = false;
686 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
687 if (link->tosock == thickness_socket) {
688 /* Something is already plugged in. Don't modify anything. */
689 has_link = true;
690 }
691 }
692
693 if (has_link) {
694 continue;
695 }
696 bNode *value_node = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_VALUE);
697 value_node->parent = node->parent;
698 value_node->locx_legacy = node->locx_legacy;
699 value_node->locy_legacy = node->locy_legacy - 160.0f;
700 bNodeSocket *socket_value = blender::bke::node_find_socket(*value_node, SOCK_OUT, "Value");
701
702 *version_cycles_node_socket_float_value(socket_value) = thickness;
703
704 blender::bke::node_add_link(*ntree, *value_node, *socket_value, *node, *thickness_socket);
705 }
706
708}
709
710static void versioning_update_timecode(short int *tc)
711{
712 /* 2 = IMB_TC_FREE_RUN, 4 = IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN. */
713 if (ELEM(*tc, 2, 4)) {
714 *tc = IMB_TC_RECORD_RUN;
715 }
716}
717
718static bool strip_proxies_timecode_update(Strip *strip, void * /*user_data*/)
719{
720 if (strip->data == nullptr || strip->data->proxy == nullptr) {
721 return true;
722 }
723 StripProxy *proxy = strip->data->proxy;
725 return true;
726}
727
728static bool strip_text_data_update(Strip *strip, void * /*user_data*/)
729{
730 if (strip->type != STRIP_TYPE_TEXT || strip->effectdata == nullptr) {
731 return true;
732 }
733
734 TextVars *data = static_cast<TextVars *>(strip->effectdata);
735 if (data->shadow_angle == 0.0f) {
736 data->shadow_angle = DEG2RADF(65.0f);
737 data->shadow_offset = 0.04f;
738 data->shadow_blur = 0.0f;
739 }
740 if (data->outline_width == 0.0f) {
741 data->outline_color[3] = 0.7f;
742 data->outline_width = 0.05f;
743 }
744 return true;
745}
746
748{
749 using namespace blender;
750 for (GreasePencilDrawingBase *base : grease_pencil->drawings()) {
751 if (base->type != GP_DRAWING) {
752 continue;
753 }
754 bke::greasepencil::Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
755 const int layer_index = CustomData_get_named_layer_index(
756 &drawing.geometry.curve_data, CD_PROP_FLOAT, "hardness");
757 if (layer_index == -1) {
758 continue;
759 }
760 float *data = static_cast<float *>(CustomData_get_layer_named_for_write(
761 &drawing.geometry.curve_data, CD_PROP_FLOAT, "hardness", drawing.geometry.curve_num));
762 for (const int i : IndexRange(drawing.geometry.curve_num)) {
763 data[i] = 1.0f - data[i];
764 }
765 /* Rename the layer. */
766 STRNCPY(drawing.geometry.curve_data.layers[layer_index].name, "softness");
767 }
768}
769
770void blo_do_versions_420(FileData *fd, Library * /*lib*/, Main *bmain)
771{
772 /* Keep point/spot light soft falloff for files created before 4.0. */
773 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 0)) {
774 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
775 if (ELEM(light->type, LA_LOCAL, LA_SPOT)) {
776 light->mode |= LA_USE_SOFT_FALLOFF;
777 }
778 }
779 }
780
781 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 1)) {
782 using namespace blender::bke::greasepencil;
783 /* Initialize newly added scale layer transform to one. */
784 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
785 for (Layer *layer : grease_pencil->layers_for_write()) {
786 copy_v3_fl(layer->scale, 1.0f);
787 }
788 }
789 }
790
791 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 2)) {
792 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
793 bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES);
794 if (is_cycles) {
795 if (IDProperty *cscene = version_cycles_properties_from_ID(&scene->id)) {
796 int cposition = version_cycles_property_int(cscene, "motion_blur_position", 1);
797 BLI_assert(cposition >= 0 && cposition < 3);
798 int order_conversion[3] = {SCE_MB_START, SCE_MB_CENTER, SCE_MB_END};
799 scene->r.motion_blur_position = order_conversion[std::clamp(cposition, 0, 2)];
800 }
801 }
802 else {
804 scene->r.mode, scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED_DEPRECATED, R_MBLUR);
805 scene->r.motion_blur_position = scene->eevee.motion_blur_position_deprecated;
806 scene->r.motion_blur_shutter = scene->eevee.motion_blur_shutter_deprecated;
807 }
808 }
809 }
810
811 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 3)) {
812 constexpr int NTREE_EXECUTION_MODE_CPU = 0;
813 constexpr int NTREE_EXECUTION_MODE_FULL_FRAME = 1;
814
815 constexpr int NTREE_COM_GROUPNODE_BUFFER = 1 << 3;
816 constexpr int NTREE_COM_OPENCL = 1 << 1;
817
818 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
819 if (ntree->type != NTREE_COMPOSIT) {
820 continue;
821 }
822
823 ntree->flag &= ~(NTREE_COM_GROUPNODE_BUFFER | NTREE_COM_OPENCL);
824
825 if (ntree->execution_mode == NTREE_EXECUTION_MODE_FULL_FRAME) {
826 ntree->execution_mode = NTREE_EXECUTION_MODE_CPU;
827 }
828 }
830 }
831
832 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 4)) {
833 if (!DNA_struct_member_exists(fd->filesdna, "SpaceImage", "float", "stretch_opacity")) {
834 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
835 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
836 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
837 if (sl->spacetype == SPACE_IMAGE) {
838 SpaceImage *sima = reinterpret_cast<SpaceImage *>(sl);
839 sima->stretch_opacity = 0.9f;
840 }
841 }
842 }
843 }
844 }
845 }
846
847 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 5)) {
848 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
850 }
851 }
852
853 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 6)) {
854 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
855 if (BrushCurvesSculptSettings *settings = brush->curves_sculpt_settings) {
857 settings->curve_radius = 0.01f;
858 }
859 }
860 }
861
862 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 8)) {
863 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
864 light->shadow_filter_radius = 1.0f;
865 }
866 }
867
868 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 9)) {
869 const float default_snap_angle_increment = DEG2RADF(5.0f);
870 const float default_snap_angle_increment_precision = DEG2RADF(1.0f);
871 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
872 scene->toolsettings->snap_angle_increment_2d = default_snap_angle_increment;
873 scene->toolsettings->snap_angle_increment_3d = default_snap_angle_increment;
874 scene->toolsettings->snap_angle_increment_2d_precision =
875 default_snap_angle_increment_precision;
876 scene->toolsettings->snap_angle_increment_3d_precision =
877 default_snap_angle_increment_precision;
878 }
879 }
880
881 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 10)) {
882 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "gtao_resolution")) {
883 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
884 scene->eevee.gtao_resolution = 2;
885 }
886 }
887 }
888
889 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 12)) {
890 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
892 }
894
895 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
896 if (scene->ed != nullptr) {
898 &scene->ed->seqbase, strip_hue_correct_set_wrapping, nullptr);
899 }
900 }
901 }
902
903 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 14)) {
904 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
905 if (bMotionPath *mpath = ob->mpath) {
906 mpath->color_post[0] = 0.1f;
907 mpath->color_post[1] = 1.0f;
908 mpath->color_post[2] = 0.1f;
909 }
910 if (!ob->pose) {
911 continue;
912 }
913 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
914 if (bMotionPath *mpath = pchan->mpath) {
915 mpath->color_post[0] = 0.1f;
916 mpath->color_post[1] = 1.0f;
917 mpath->color_post[2] = 0.1f;
918 }
919 }
920 }
921 }
922
923 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 18)) {
924 if (!DNA_struct_member_exists(fd->filesdna, "Light", "float", "transmission_fac")) {
925 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
926 /* Refracted light was not supported in legacy EEVEE. Set it to zero for compatibility with
927 * older files. */
928 light->transmission_fac = 0.0f;
929 }
930 }
931 }
932
933 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 19)) {
934 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
935 /* Keep legacy EEVEE old behavior. */
936 scene->eevee.flag |= SCE_EEVEE_VOLUME_CUSTOM_RANGE;
937 }
938
939 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
940 scene->eevee.clamp_surface_indirect = 10.0f;
941 /* Make contribution of indirect lighting very small (but non-null) to avoid world lighting
942 * and volume lightprobe changing the appearance of volume objects. */
943 scene->eevee.clamp_volume_indirect = 1e-8f;
944 }
945 }
946
947 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 20)) {
948 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
949 SequencerToolSettings *sequencer_tool_settings = blender::seq::tool_settings_ensure(scene);
950 sequencer_tool_settings->snap_mode |= SEQ_SNAP_TO_MARKERS;
951 }
952 }
953
954 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 21)) {
956 }
957
958 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 22)) {
959 /* Display missing media in sequencer by default. */
960 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
961 if (scene->ed != nullptr) {
962 scene->ed->show_missing_media_flag |= SEQ_EDIT_SHOW_MISSING_MEDIA;
963 }
964 }
965 }
966
967 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 24)) {
968 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "thickness_mode")) {
969 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
970 if (material->blend_flag & MA_BL_TRANSLUCENCY) {
971 /* EEVEE Legacy used thickness from shadow map when translucency was on. */
972 material->blend_flag |= MA_BL_THICKNESS_FROM_SHADOW;
973 }
974 if ((material->blend_flag & MA_BL_SS_REFRACTION) && material->use_nodes &&
975 material->nodetree)
976 {
977 /* EEVEE Legacy used slab assumption. */
978 material->thickness_mode = MA_THICKNESS_SLAB;
979 version_refraction_depth_to_thickness_value(material->nodetree, material->refract_depth);
980 }
981 }
982 }
983 }
984
985 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 25)) {
986 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
987 if (ntree->type != NTREE_COMPOSIT) {
988 continue;
989 }
990 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
991 if (node->type_legacy != CMP_NODE_BLUR) {
992 continue;
993 }
994
995 NodeBlurData &blur_data = *static_cast<NodeBlurData *>(node->storage);
996
997 if (blur_data.filtertype != R_FILTER_FAST_GAUSS) {
998 continue;
999 }
1000
1001 /* The size of the Fast Gaussian mode of blur decreased by the following factor to match
1002 * other blur sizes. So increase it back. */
1003 const float size_factor = 3.0f / 2.0f;
1004 blur_data.sizex *= size_factor;
1005 blur_data.sizey *= size_factor;
1006 blur_data.percentx *= size_factor;
1007 blur_data.percenty *= size_factor;
1008 }
1009 }
1011 }
1012
1013 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 26)) {
1014 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "float", "shadow_resolution_scale"))
1015 {
1016 SceneEEVEE default_scene_eevee = *DNA_struct_default_get(SceneEEVEE);
1017 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1018 scene->eevee.shadow_resolution_scale = default_scene_eevee.shadow_resolution_scale;
1019 }
1020 }
1021 }
1022
1023 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 27)) {
1024 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1025 if (scene->ed != nullptr) {
1026 scene->ed->cache_flag &= ~(SEQ_CACHE_UNUSED_5 | SEQ_CACHE_UNUSED_6 | SEQ_CACHE_UNUSED_7 |
1028 }
1029 }
1030 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1031 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1032 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1033 if (sl->spacetype == SPACE_SEQ) {
1034 SpaceSeq *sseq = (SpaceSeq *)sl;
1036 }
1037 }
1038 }
1039 }
1040 }
1041
1042 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 28)) {
1043 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1044 if (scene->ed != nullptr) {
1046 &scene->ed->seqbase, strip_proxies_timecode_update, nullptr);
1047 }
1048 }
1049
1050 LISTBASE_FOREACH (MovieClip *, clip, &bmain->movieclips) {
1051 MovieClipProxy proxy = clip->proxy;
1053 }
1054 }
1055
1056 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 29)) {
1057 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1058 if (scene->ed) {
1059 blender::seq::for_each_callback(&scene->ed->seqbase, strip_text_data_update, nullptr);
1060 }
1061 }
1062 }
1063
1064 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 30)) {
1065 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1066 if (scene->nodetree) {
1067 scene->nodetree->flag &= ~NTREE_UNUSED_2;
1068 }
1069 }
1070 }
1071
1072 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 31)) {
1073 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
1074 /* Guess a somewhat correct density given the resolution. But very low resolution need
1075 * a decent enough density to work. */
1076 lightprobe->grid_surfel_density = max_ii(20,
1077 2 * max_iii(lightprobe->grid_resolution_x,
1078 lightprobe->grid_resolution_y,
1079 lightprobe->grid_resolution_z));
1080 }
1081 }
1082
1083 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 31)) {
1084 bool only_uses_eevee_legacy_or_workbench = true;
1085 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1087 only_uses_eevee_legacy_or_workbench = false;
1088 }
1089 }
1090 /* Mark old EEVEE world volumes for showing conversion operator. */
1091 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
1092 if (world->nodetree) {
1093 bNode *output_node = version_eevee_output_node_get(world->nodetree, SH_NODE_OUTPUT_WORLD);
1094 if (output_node) {
1095 bNodeSocket *volume_input_socket = static_cast<bNodeSocket *>(
1096 BLI_findlink(&output_node->inputs, 1));
1097 if (volume_input_socket) {
1098 LISTBASE_FOREACH (bNodeLink *, node_link, &world->nodetree->links) {
1099 if (node_link->tonode == output_node && node_link->tosock == volume_input_socket) {
1100 world->flag |= WO_USE_EEVEE_FINITE_VOLUME;
1101 /* Only display a warning message if we are sure this can be used by EEVEE. */
1102 if (only_uses_eevee_legacy_or_workbench) {
1105 RPT_("%s contains a volume shader that might need to be "
1106 "converted to object (see world volume panel)\n"),
1107 world->id.name + 2);
1108 }
1109 }
1110 }
1111 }
1112 }
1113 }
1114 }
1115 }
1116
1117 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 33)) {
1118 constexpr int NTREE_EXECUTION_MODE_GPU = 2;
1119
1120 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1121 if (scene->nodetree) {
1122 if (scene->nodetree->execution_mode == NTREE_EXECUTION_MODE_GPU) {
1123 scene->r.compositor_device = SCE_COMPOSITOR_DEVICE_GPU;
1124 }
1125 scene->r.compositor_precision = scene->nodetree->precision;
1126 }
1127 }
1128 }
1129
1130 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 34)) {
1131 float shadow_max_res_sun = 0.001f;
1132 float shadow_max_res_local = 0.001f;
1133 bool shadow_resolution_absolute = false;
1134 /* Try to get default resolution from scene setting. */
1135 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1136 shadow_max_res_local = (2.0f * M_SQRT2) / scene->eevee.shadow_cube_size_deprecated;
1137 /* Round to avoid weird numbers in the UI. */
1138 shadow_max_res_local = ceil(shadow_max_res_local * 1000.0f) / 1000.0f;
1139 shadow_resolution_absolute = true;
1140 break;
1141 }
1142
1143 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
1144 if (light->type == LA_SUN) {
1145 /* Sun are too complex to convert. Need user interaction. */
1146 light->shadow_maximum_resolution = shadow_max_res_sun;
1147 SET_FLAG_FROM_TEST(light->mode, false, LA_SHAD_RES_ABSOLUTE);
1148 }
1149 else {
1150 light->shadow_maximum_resolution = shadow_max_res_local;
1151 SET_FLAG_FROM_TEST(light->mode, shadow_resolution_absolute, LA_SHAD_RES_ABSOLUTE);
1152 }
1153 }
1154 }
1155
1156 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 36)) {
1157 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
1158 /* Only for grease pencil brushes. */
1159 if (brush->gpencil_settings) {
1160 /* Use the `Scene` radius unit by default (confusingly named `BRUSH_LOCK_SIZE`).
1161 * Convert the radius to be the same visual size as in GPv2. */
1162 brush->flag |= BRUSH_LOCK_SIZE;
1163 brush->unprojected_radius = brush->size *
1165 }
1166 }
1167 }
1168
1169 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 37)) {
1170 const World *default_world = DNA_struct_default_get(World);
1171 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
1172 world->sun_threshold = default_world->sun_threshold;
1173 world->sun_angle = default_world->sun_angle;
1174 world->sun_shadow_maximum_resolution = default_world->sun_shadow_maximum_resolution;
1175 /* Having the sun extracted is mandatory to keep the same look and avoid too much light
1176 * leaking compared to EEVEE-Legacy. But adding shadows might create performance overhead and
1177 * change the result in a very different way. So we disable shadows in older file. */
1178 world->flag &= ~WO_USE_SUN_SHADOW;
1179 }
1180 }
1181
1182 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 38)) {
1183 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
1185 }
1186 }
1187
1188 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 39)) {
1189 /* Unify cast shadow property with Cycles. */
1191 const Light *default_light = DNA_struct_default_get(Light);
1192 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
1193 IDProperty *clight = version_cycles_properties_from_ID(&light->id);
1194 if (clight) {
1196 clight, "cast_shadow", default_light->mode & LA_SHADOW);
1197 SET_FLAG_FROM_TEST(light->mode, value, LA_SHADOW);
1198 }
1199 }
1200 }
1201 }
1202
1203 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 40)) {
1204 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
1205 version_node_input_socket_name(ntree, FN_NODE_COMBINE_TRANSFORM, "Location", "Translation");
1207 ntree, FN_NODE_SEPARATE_TRANSFORM, "Location", "Translation");
1208 }
1209 }
1210
1211 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 41)) {
1212 const Light *default_light = DNA_struct_default_get(Light);
1213 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
1214 light->shadow_jitter_overblur = default_light->shadow_jitter_overblur;
1215 }
1216 }
1217
1218 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 43)) {
1219 const World *default_world = DNA_struct_default_get(World);
1220 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
1221 world->sun_shadow_maximum_resolution = default_world->sun_shadow_maximum_resolution;
1222 world->sun_shadow_filter_radius = default_world->sun_shadow_filter_radius;
1223 }
1224 }
1225
1226 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 44)) {
1227 const Scene *default_scene = DNA_struct_default_get(Scene);
1228 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1229 scene->eevee.fast_gi_step_count = default_scene->eevee.fast_gi_step_count;
1230 scene->eevee.fast_gi_ray_count = default_scene->eevee.fast_gi_ray_count;
1231 }
1232 }
1233
1234 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 45)) {
1235 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1236 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1237 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1238 if (sl->spacetype == SPACE_VIEW3D) {
1239 View3D *v3d = reinterpret_cast<View3D *>(sl);
1241 }
1242 }
1243 }
1244 }
1245 }
1246
1247 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 46)) {
1248 const Scene *default_scene = DNA_struct_default_get(Scene);
1249 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1250 scene->eevee.fast_gi_thickness_near = default_scene->eevee.fast_gi_thickness_near;
1251 scene->eevee.fast_gi_thickness_far = default_scene->eevee.fast_gi_thickness_far;
1252 }
1253 }
1254 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 48)) {
1255 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1256 if (!ob->pose) {
1257 continue;
1258 }
1259 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1260 pchan->custom_shape_wire_width = 1.0;
1261 }
1262 }
1263 }
1264
1265 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 49)) {
1266 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1267 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1268 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1269 if (sl->spacetype == SPACE_VIEW3D) {
1270 View3D *v3d = reinterpret_cast<View3D *>(sl);
1272 }
1273 }
1274 }
1275 }
1276 }
1277
1278 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 50)) {
1279 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
1280 if (ntree->type != NTREE_GEOMETRY) {
1281 continue;
1282 }
1283 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1284 if (node->type_legacy != GEO_NODE_CAPTURE_ATTRIBUTE) {
1285 continue;
1286 }
1288 node->storage);
1289 if (storage->next_identifier > 0) {
1290 continue;
1291 }
1292 storage->capture_items_num = 1;
1294 storage->capture_items_num, __func__);
1296 item.data_type = storage->data_type_legacy;
1297 item.identifier = storage->next_identifier++;
1298 item.name = BLI_strdup("Value");
1299 }
1300 }
1301 }
1302
1303 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 53)) {
1304 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1305 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1306 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1307 if (sl->spacetype == SPACE_NODE) {
1308 SpaceNode *snode = reinterpret_cast<SpaceNode *>(sl);
1310 }
1311 }
1312 }
1313 }
1314 }
1315
1316 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 55)) {
1317 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1318 if (ntree->type != NTREE_COMPOSIT) {
1319 continue;
1320 }
1321 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1322 if (node->type_legacy != CMP_NODE_CURVE_RGB) {
1323 continue;
1324 }
1325
1326 CurveMapping &curve_mapping = *static_cast<CurveMapping *>(node->storage);
1327
1328 /* Film-like tone only works with the combined curve, which is the fourth curve, so make
1329 * the combined curve current, as we now hide the rest of the curves since they no longer
1330 * have an effect. */
1331 if (curve_mapping.tone == CURVE_TONE_FILMLIKE) {
1332 curve_mapping.cur = 3;
1333 }
1334 }
1335 }
1337 }
1338
1339 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 60) ||
1340 (bmain->versionfile == 403 && !MAIN_VERSION_FILE_ATLEAST(bmain, 403, 3)))
1341 {
1342 /* Limit Rotation constraints from old files should use the legacy Limit
1343 * Rotation behavior. */
1344 LISTBASE_FOREACH (Object *, obj, &bmain->objects) {
1345 LISTBASE_FOREACH (bConstraint *, constraint, &obj->constraints) {
1346 if (constraint->type != CONSTRAINT_TYPE_ROTLIMIT) {
1347 continue;
1348 }
1349 static_cast<bRotLimitConstraint *>(constraint->data)->flag |= LIMIT_ROT_LEGACY_BEHAVIOR;
1350 }
1351
1352 if (!obj->pose) {
1353 continue;
1354 }
1355 LISTBASE_FOREACH (bPoseChannel *, pbone, &obj->pose->chanbase) {
1356 LISTBASE_FOREACH (bConstraint *, constraint, &pbone->constraints) {
1357 if (constraint->type != CONSTRAINT_TYPE_ROTLIMIT) {
1358 continue;
1359 }
1360 static_cast<bRotLimitConstraint *>(constraint->data)->flag |= LIMIT_ROT_LEGACY_BEHAVIOR;
1361 }
1362 }
1363 }
1364 }
1365
1366 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 61)) {
1367 /* LIGHT_PROBE_RESOLUTION_64 has been removed in EEVEE-Next as the tedrahedral mapping is to
1368 * low res to be usable. */
1369 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1370 scene->eevee.gi_cubemap_resolution = std::max(scene->eevee.gi_cubemap_resolution, 128);
1371 }
1372 }
1373
1374 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 64)) {
1376 /* Re-apply versioning made for EEVEE-Next in 4.1 before it got delayed. */
1377 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
1378 bool transparent_shadows = material->blend_shadow != MA_BS_SOLID;
1379 SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW);
1380 }
1381 LISTBASE_FOREACH (Material *, mat, &bmain->materials) {
1382 mat->surface_render_method = (mat->blend_method == MA_BM_BLEND) ?
1385 }
1386 }
1387 }
1388
1389 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 65)) {
1390 FOREACH_NODETREE_BEGIN (bmain, node_tree, id) {
1391 if (node_tree->type != NTREE_COMPOSIT) {
1392 continue;
1393 }
1394 LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) {
1395 if (node->type_legacy == CMP_NODE_DENOISE) {
1396 if (node->storage == nullptr) {
1397 /* Some known files were saved without a valid storage. These are likely corrupt files
1398 * that have been produced by a non official blender release. The node type will be set
1399 * to Undefined during linking, see #ntree_set_typeinfo. However, a valid storage might
1400 * be needed for future versioning (before linking), see
1401 * #do_version_denoise_menus_to_inputs so we set a valid storage at this stage such
1402 * that the node becomes well defined. */
1403 NodeDenoise *ndg = MEM_callocN<NodeDenoise>(__func__);
1404 ndg->hdr = true;
1406 node->storage = ndg;
1407 }
1408 }
1409 }
1410 }
1412 }
1413}
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:82
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer_named_for_write(CustomData *data, eCustomDataType type, blender::StringRef name, int totelem)
int CustomData_get_named_layer_index(const CustomData *data, eCustomDataType type, blender::StringRef name)
Low-level operations for grease pencil.
#define MAIN_VERSION_FILE_ATLEAST(main, ver, subver)
Definition BKE_main.hh:634
General operations, lookup, etc. for materials.
short * BKE_object_material_len_p(Object *ob)
Material * BKE_object_material_get(Object *ob, short act)
#define NODE_REROUTE
Definition BKE_node.hh:798
#define FOREACH_NODETREE_END
Definition BKE_node.hh:866
#define NODE_GROUP
Definition BKE_node.hh:796
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition BKE_node.hh:856
#define SH_NODE_MIX_SHADER
#define CMP_NODE_DENOISE
#define FN_NODE_SEPARATE_TRANSFORM
#define SH_NODE_OUTPUT_WORLD
#define SH_NODE_BSDF_PRINCIPLED
#define SH_NODE_ADD_SHADER
#define SH_NODE_SUBSURFACE_SCATTERING
#define SH_NODE_VALUE
#define CMP_NODE_HUECORRECT
#define SH_NODE_BSDF_TRANSPARENT
#define SH_NODE_OUTPUT_MATERIAL
#define CMP_NODE_CURVE_RGB
#define FN_NODE_COMBINE_TRANSFORM
#define SH_NODE_EEVEE_SPECULAR
#define GEO_NODE_CAPTURE_ATTRIBUTE
#define CMP_NODE_BLUR
#define BLI_assert(a)
Definition BLI_assert.h:46
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE int max_iii(int a, int b, int c)
#define DEG2RADF(_deg)
#define M_SQRT2
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_fl(float r[3], float f)
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define STR_ELEM(...)
Definition BLI_string.h:656
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define RPT_(msgid)
@ BRUSH_LOCK_SIZE
@ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_RADIUS
@ CUMA_DO_CLIP
@ CUMA_USE_WRAPPING
@ CURVE_TONE_FILMLIKE
@ CONSTRAINT_TYPE_ROTLIMIT
@ LIMIT_ROT_LEGACY_BEHAVIOR
@ CD_PROP_FLOAT
#define DNA_struct_default_get(struct_name)
blenloader genfile private function prototypes
@ LA_SHAD_RES_ABSOLUTE
@ LA_SHADOW
@ LA_USE_SOFT_FALLOFF
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ MA_BM_CLIP
@ MA_BM_HASHED
@ MA_BM_BLEND
@ MA_THICKNESS_SLAB
@ MA_BS_HASHED
@ MA_BS_CLIP
@ MA_BS_NONE
@ MA_BS_SOLID
@ MA_SURFACE_METHOD_DEFERRED
@ MA_SURFACE_METHOD_FORWARD
@ MA_BL_TRANSPARENT_SHADOW
@ MA_BL_THICKNESS_FROM_SHADOW
@ MA_BL_TRANSLUCENCY
@ MA_BL_SS_REFRACTION
@ NODE_HIDDEN
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
@ NTREE_UNUSED_2
@ NODE_MATH_GREATER_THAN
@ SHD_OUTPUT_CYCLES
@ SHD_OUTPUT_ALL
@ SHD_OUTPUT_EEVEE
@ SOCK_OUT
@ SOCK_IN
@ SOCK_HIDDEN
@ SOCK_RGBA
@ CMP_NODE_DENOISE_PREFILTER_ACCURATE
@ OB_HIDE_SHADOW
@ R_FILTER_FAST_GAUSS
@ SEQ_SNAP_TO_MARKERS
@ SCE_MB_START
@ SCE_MB_END
@ SCE_MB_CENTER
@ R_IMF_IMTYPE_FFMPEG
@ R_IMF_IMTYPE_AVIJPEG
@ R_IMF_IMTYPE_AVIRAW
@ R_MBLUR
@ SCE_COMPOSITOR_DEVICE_GPU
@ SCE_EEVEE_VOLUME_CUSTOM_RANGE
@ SCE_EEVEE_MOTION_BLUR_ENABLED_DEPRECATED
@ RGN_FLAG_HIDDEN
@ RGN_TYPE_TOOL_HEADER
@ RGN_TYPE_ASSET_SHELF_HEADER
@ RGN_TYPE_ASSET_SHELF
@ RGN_ALIGN_HIDE_WITH_PREV
@ RGN_ALIGN_BOTTOM
@ STRIP_TYPE_TEXT
@ seqModifierType_HueCorrect
@ SEQ_EDIT_SHOW_MISSING_MEDIA
@ SEQ_CACHE_UNUSED_8
@ SEQ_CACHE_UNUSED_5
@ SEQ_CACHE_UNUSED_7
@ SEQ_CACHE_UNUSED_6
@ SEQ_CACHE_UNUSED_9
@ SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ SEQ_CACHE_SHOW_FINAL_OUT
@ V3D_SHOW_CAMERA_PASSEPARTOUT
@ V3D_SHOW_CAMERA_GUIDES
@ WO_USE_SUN_SHADOW
@ WO_USE_EEVEE_FINITE_VOLUME
@ IMB_TC_RECORD_RUN
Definition MOV_enums.hh:54
BMesh const char void * data
static T sum(const btAlignedObjectArray< T > &items)
constexpr bool startswith(StringRef prefix) const
constexpr StringRef drop_known_prefix(StringRef prefix) const
#define ceil
#define output
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
constexpr float LEGACY_RADIUS_CONVERSION_FACTOR
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2864
bNode * node_add_node(const bContext *C, bNodeTree &ntree, StringRef idname)
Definition node.cc:3788
void node_remove_link(bNodeTree *ntree, bNodeLink &link)
Definition node.cc:4124
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3804
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:4087
void for_each_callback(ListBase *seqbase, ForEachFunc callback, void *user_data)
Definition iterator.cc:59
SequencerToolSettings * tool_settings_ensure(Scene *scene)
Definition sequencer.cc:362
float wrap(float value, float max, float min)
Definition node_math.h:71
const char * RE_engine_id_CYCLES
Definition scene.cc:1628
const char * RE_engine_id_BLENDER_EEVEE_NEXT
Definition scene.cc:1626
const char * RE_engine_id_BLENDER_WORKBENCH
Definition scene.cc:1627
const char * RE_engine_id_BLENDER_EEVEE
Definition scene.cc:1625
bool is_complex() const
static AlphaSource alpha_source(bNodeSocket *fac, bool inverted=false)
bool is_opaque() const
bool is_fully_transparent() const
bool is_transparent() const
static AlphaSource opaque()
AlphaState state
bool is_semi_transparent() const
bNodeSocket * socket
static AlphaSource mix(const AlphaSource &a, const AlphaSource &b, bNodeSocket *fac)
static AlphaSource fully_transparent(bNodeSocket *socket=nullptr, bool inverted=false)
static AlphaSource complex_alpha()
static AlphaSource add(const AlphaSource &a, const AlphaSource &b)
bAction * action
ListBase drivers
CustomData curve_data
CustomDataLayer * layers
char * rna_path
BlendFileReadReport * reports
Definition readfile.hh:165
SDNA * filesdna
Definition readfile.hh:103
struct CurveMapping curve_mapping
float shadow_jitter_overblur
void * first
ListBase lightprobes
Definition BKE_main.hh:265
ListBase brushes
Definition BKE_main.hh:271
ListBase scenes
Definition BKE_main.hh:245
ListBase grease_pencils
Definition BKE_main.hh:279
ListBase movieclips
Definition BKE_main.hh:280
ListBase lights
Definition BKE_main.hh:255
ListBase nodetrees
Definition BKE_main.hh:270
ListBase materials
Definition BKE_main.hh:251
ListBase armatures
Definition BKE_main.hh:268
ListBase worlds
Definition BKE_main.hh:260
ListBase screens
Definition BKE_main.hh:261
short versionfile
Definition BKE_main.hh:156
ListBase objects
Definition BKE_main.hh:247
struct bNodeTree * nodetree
NodeGeometryAttributeCaptureItem * capture_items
short visibility_flag
struct ImageFormatData im_format
float fast_gi_thickness_near
float shadow_resolution_scale
float fast_gi_thickness_far
struct RenderData r
struct SceneEEVEE eevee
float stretch_opacity
SpaceNodeOverlay overlay
struct SequencerCacheOverlay cache_overlay
StripProxy * proxy
StripData * data
void * effectdata
ListBase modifiers
float sun_angle
float sun_shadow_maximum_resolution
float sun_shadow_filter_radius
float sun_threshold
ListBase curves
struct bNodeLink * link
ListBase nodes
ListBase links
int16_t custom1
float width
ListBase inputs
float height
float locx_legacy
struct bNode * parent
int16_t type_legacy
float locy_legacy
char label[64]
ListBase outputs
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230
static bool strip_text_data_update(Strip *strip, void *)
static void versioning_node_hue_correct_set_wrappng(bNodeTree *ntree)
static void versioning_eevee_material_shadow_none(Material *material)
void blo_do_versions_420(FileData *fd, Library *, Main *bmain)
static bool versioning_eevee_material_blend_mode_settings(bNodeTree *ntree, float threshold)
static void version_bonecollection_anim(FCurve *fcurve)
static void image_settings_avi_to_ffmpeg(Scene *scene)
void do_versions_after_linking_420(FileData *fd, Main *bmain)
static void convert_grease_pencil_stroke_hardness_to_softness(GreasePencil *grease_pencil)
static void add_image_editor_asset_shelf(Main &bmain)
static bool strip_hue_correct_set_wrapping(Strip *strip, void *)
static void hue_correct_set_wrapping(CurveMapping *curve_mapping)
static bool strip_proxies_timecode_update(Strip *strip, void *)
static AlphaSource versioning_eevee_alpha_source_get(bNodeSocket *socket, int depth=0)
static void version_refraction_depth_to_thickness_value(bNodeTree *ntree, float thickness)
static void versioning_eevee_shadow_settings(Object *object)
static void versioning_update_timecode(short int *tc)
bNode * version_eevee_output_node_get(bNodeTree *ntree, int16_t node_type)
bool all_scenes_use(Main *bmain, const blender::Span< const char * > engines)
float * version_cycles_node_socket_float_value(bNodeSocket *socket)
IDProperty * version_cycles_properties_from_ID(ID *id)
int version_cycles_property_int(IDProperty *idprop, const char *name, int default_value)
float * version_cycles_node_socket_rgba_value(bNodeSocket *socket)
void version_node_socket_index_animdata(Main *bmain, const int node_tree_type, const int node_type, const int socket_index_orig, const int socket_index_offset, const int total_number_of_sockets)
void version_node_input_socket_name(bNodeTree *ntree, const int node_type, const char *old_name, const char *new_name)
bool version_cycles_property_boolean(IDProperty *idprop, const char *name, bool default_value)
void version_socket_update_is_used(bNodeTree *ntree)
ARegion * do_versions_add_region_if_not_found(ListBase *regionbase, int region_type, const char *, int link_after_region_type)
void version_node_output_socket_name(bNodeTree *ntree, const int node_type, const char *old_name, const char *new_name)
uint8_t flag
Definition wm_window.cc:139