Blender V4.3
versioning_400.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#include <algorithm>
12#include <cmath>
13
14/* Define macros in `DNA_genfile.h`. */
15#define DNA_GENFILE_VERSIONING_MACROS
16
17#include "DNA_anim_types.h"
18#include "DNA_brush_types.h"
19#include "DNA_camera_types.h"
22#include "DNA_curve_types.h"
23#include "DNA_defaults.h"
24#include "DNA_light_types.h"
26#include "DNA_material_types.h"
27#include "DNA_mesh_types.h"
28#include "DNA_modifier_types.h"
29#include "DNA_movieclip_types.h"
30#include "DNA_scene_types.h"
31#include "DNA_sequence_types.h"
32#include "DNA_workspace_types.h"
33#include "DNA_world_types.h"
34
35#include "DNA_defaults.h"
36#include "DNA_defs.h"
37#include "DNA_genfile.h"
38#include "DNA_particle_types.h"
39
40#undef DNA_GENFILE_VERSIONING_MACROS
41
42#include "BLI_assert.h"
43#include "BLI_listbase.h"
44#include "BLI_map.hh"
45#include "BLI_math_rotation.h"
46#include "BLI_math_vector.h"
47#include "BLI_set.hh"
48#include "BLI_string.h"
49#include "BLI_string_ref.hh"
50
51#include "BKE_anim_data.hh"
52#include "BKE_animsys.h"
53#include "BKE_armature.hh"
54#include "BKE_attribute.hh"
55#include "BKE_collection.hh"
56#include "BKE_colortools.hh"
57#include "BKE_context.hh"
58#include "BKE_curve.hh"
59#include "BKE_customdata.hh"
60#include "BKE_effect.h"
61#include "BKE_file_handler.hh"
62#include "BKE_grease_pencil.hh"
63#include "BKE_idprop.hh"
64#include "BKE_image_format.hh"
65#include "BKE_main.hh"
66#include "BKE_material.h"
68#include "BKE_nla.hh"
69#include "BKE_node_runtime.hh"
70#include "BKE_paint.hh"
71#include "BKE_scene.hh"
72#include "BKE_screen.hh"
73#include "BKE_tracking.h"
74
75#include "IMB_imbuf_enums.h"
76
77#include "SEQ_iterator.hh"
78#include "SEQ_retiming.hh"
79#include "SEQ_sequencer.hh"
80#include "SEQ_time.hh"
81
82#include "ANIM_action.hh"
84#include "ANIM_armature_iter.hh"
86
87#include "BLT_translation.hh"
88
89#include "BLO_read_write.hh"
90#include "BLO_readfile.hh"
91
92#include "readfile.hh"
93
94#include "versioning_common.hh"
95
96// static CLG_LogRef LOG = {"blo.readfile.doversion"};
97
99{
100 for (bNode *node : ntree->all_nodes()) {
101 if (node->id == nullptr && ((node->type == CMP_NODE_R_LAYERS) ||
102 (node->type == CMP_NODE_CRYPTOMATTE &&
103 node->custom1 == CMP_NODE_CRYPTOMATTE_SOURCE_RENDER)))
104 {
105 node->id = &scene->id;
106 }
107 }
108}
109
116
118{
119 using namespace blender::animrig;
120 if (action.is_action_layered()) {
121 return;
122 }
123 Slot &slot = action.slot_add();
124 slot.idtype = action.idroot;
125 action.idroot = 0;
126 Layer &layer = action.layer_add("Layer");
127 blender::animrig::Strip &strip = layer.strip_add(action,
128 blender::animrig::Strip::Type::Keyframe);
129 ChannelBag &bag = strip.data<StripKeyframeData>(action).channelbag_for_slot_ensure(slot);
130 const int fcu_count = BLI_listbase_count(&action.curves);
131 const int group_count = BLI_listbase_count(&action.groups);
132 bag.fcurve_array = MEM_cnew_array<FCurve *>(fcu_count, "Action versioning - fcurves");
133 bag.fcurve_array_num = fcu_count;
134 bag.group_array = MEM_cnew_array<bActionGroup *>(group_count, "Action versioning - groups");
135 bag.group_array_num = group_count;
136
137 int group_index = 0;
138 int fcurve_index = 0;
139 LISTBASE_FOREACH_INDEX (bActionGroup *, group, &action.groups, group_index) {
140 bag.group_array[group_index] = group;
141
142 group->channel_bag = &bag;
143 group->fcurve_range_start = fcurve_index;
144
145 LISTBASE_FOREACH (FCurve *, fcu, &group->channels) {
146 if (fcu->grp != group) {
147 break;
148 }
149 bag.fcurve_array[fcurve_index++] = fcu;
150 }
151
152 group->fcurve_range_length = fcurve_index - group->fcurve_range_start;
153 }
154
155 LISTBASE_FOREACH (FCurve *, fcu, &action.curves) {
156 /* Any fcurves with groups have already been added to the fcurve array. */
157 if (fcu->grp) {
158 continue;
159 }
160 bag.fcurve_array[fcurve_index++] = fcu;
161 }
162
163 BLI_assert(fcurve_index == fcu_count);
164
165 action.curves = {nullptr, nullptr};
166 action.groups = {nullptr, nullptr};
167}
168
170{
171 using namespace blender::animrig;
173 LISTBASE_FOREACH (bAction *, dna_action, &bmain->actions) {
174 Action &action = dna_action->wrap();
175 if (action.is_action_layered()) {
176 continue;
177 }
178 action_users.add(dna_action, {});
179 }
180
181 ID *id;
182 FOREACH_MAIN_ID_BEGIN (bmain, id) {
183 auto callback =
184 [&](bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name) -> bool {
185 blender::Vector<ActionUserInfo> *action_user_vector = action_users.lookup_ptr(
186 action_ptr_ref);
187 /* Only actions that need to be converted are in this map. */
188 if (!action_user_vector) {
189 return true;
190 }
191 ActionUserInfo user_info;
192 user_info.id = id;
193 user_info.action_ptr_ptr = &action_ptr_ref;
194 user_info.slot_handle = &slot_handle_ref;
195 user_info.slot_name = slot_name;
196 action_user_vector->append(user_info);
197 return true;
198 };
199
201 }
203
204 for (const auto &item : action_users.items()) {
205 Action &action = item.key->wrap();
207 blender::Vector<ActionUserInfo> &user_infos = item.value;
208 Slot &slot_to_assign = *action.slot(0);
209
210 if (user_infos.size() == 1) {
211 /* Rename the slot after its single user. If there are multiple users, the name is unchanged
212 * because there is no good way to determine a name. */
213 action.slot_name_set(*bmain, slot_to_assign, user_infos[0].id->name);
214 }
215 for (ActionUserInfo &action_user : user_infos) {
217 &slot_to_assign,
218 *action_user.id,
219 *action_user.action_ptr_ptr,
220 *action_user.slot_handle,
221 action_user.slot_name);
222 switch (result) {
224 break;
226 /* The slot assignment can fail in the following scenario, when dealing
227 * with "old Blender" (only supporting legacy Actions) and "new Blender"
228 * (versions supporting slotted/layered Actions).
229 *
230 * - New Blender: create an action with two slots, ME and KE, and assign
231 * to respectively a Mesh and a Shape Key. Save the file.
232 * - Old Blender: load the file. This will load the legacy data, but still
233 * keep the assignments. This means that the Shape Key will get a ME
234 * Action assigned, which is incompatible. Save the file.
235 * - New Blender: upgrades the Action (this code here), and tries to
236 * assign the first (and by now only) slot. This will fail for the shape
237 * key, as the ID type doesn't match.
238 *
239 * The failure is in itself okay, as there was actual data loss in this
240 * scenario, and so issuing a warning is the right way to go about this.
241 * The Action is still assigned, but the data-block won't get a slot
242 * assigned.
243 */
244 printf(
245 "Warning: while upgrading legacy Action \"%s\", its slot \"%s\" could not be "
246 "assigned to data-block \"%s\" because it was meant for ID type \"%s\". The Action "
247 "assignment will be kept, but \"%s\" will not be animated.\n",
248 action.id.name + 2,
249 slot_to_assign.name_without_prefix().c_str(),
250 action_user.id->name,
251 slot_to_assign.name_prefix_for_idtype().c_str(),
252 action_user.id->name);
253 break;
255 BLI_assert(!"SlotNotFromAction should not be returned here");
256 break;
258 BLI_assert(!"MissingAction should not be returned here");
259 break;
260 }
261 }
262 }
263}
264
265/* Move bone-group color to the individual bones. */
267{
268 using PoseSet = blender::Set<bPose *>;
270
271 /* Gather a mapping from armature to the poses that use it. */
272 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
273 if (ob->type != OB_ARMATURE || !ob->pose) {
274 continue;
275 }
276
277 bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
278 BLI_assert_msg(GS(arm->id.name) == ID_AR,
279 "Expected ARMATURE object to have an Armature as data");
280
281 /* There is no guarantee that the current state of poses is in sync with the Armature data.
282 *
283 * NOTE: No need to handle user reference-counting in readfile code. */
284 BKE_pose_ensure(bmain, ob, arm, false);
285
286 PoseSet &pose_set = armature_poses.lookup_or_add_default(arm);
287 pose_set.add(ob->pose);
288 }
289
290 /* Move colors from the pose's bone-group to either the armature bones or the
291 * pose bones, depending on how many poses use the Armature. */
292 for (const PoseSet &pose_set : armature_poses.values()) {
293 /* If the Armature is shared, the bone group colors might be different, and thus they have to
294 * be stored on the pose bones. If the Armature is NOT shared, the bone colors can be stored
295 * directly on the Armature bones. */
296 const bool store_on_armature = pose_set.size() == 1;
297
298 for (bPose *pose : pose_set) {
299 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
300 const bActionGroup *bgrp = (const bActionGroup *)BLI_findlink(&pose->agroups,
301 (pchan->agrp_index - 1));
302 if (!bgrp) {
303 continue;
304 }
305
306 BoneColor &bone_color = store_on_armature ? pchan->bone->color : pchan->color;
307 bone_color.palette_index = bgrp->customCol;
308 memcpy(&bone_color.custom, &bgrp->cs, sizeof(bone_color.custom));
309 }
310 }
311 }
312}
313
315{
316 char bcoll_name[MAX_NAME];
317 char custom_prop_name[MAX_NAME];
318
319 LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
320 IDProperty *arm_idprops = IDP_GetProperties(&arm->id);
321
322 BLI_assert_msg(arm->edbo == nullptr, "did not expect an Armature to be saved in edit mode");
323 const uint layer_used = arm->layer_used;
324
325 /* Construct a bone collection for each layer that contains at least one bone. */
327 for (uint layer = 0; layer < 32; ++layer) {
328 const uint layer_mask = 1u << layer;
329 if ((layer_used & layer_mask) == 0) {
330 /* Layer is empty, so no need to convert to collection. */
331 continue;
332 }
333
334 /* Construct a suitable name for this bone layer. */
335 bcoll_name[0] = '\0';
336 if (arm_idprops) {
337 /* See if we can use the layer name from the Bone Manager add-on. This is a popular add-on
338 * for managing bone layers and giving them names. */
339 SNPRINTF(custom_prop_name, "layer_name_%u", layer);
340 IDProperty *prop = IDP_GetPropertyFromGroup(arm_idprops, custom_prop_name);
341 if (prop != nullptr && prop->type == IDP_STRING && IDP_String(prop)[0] != '\0') {
342 SNPRINTF(bcoll_name, "Layer %u - %s", layer + 1, IDP_String(prop));
343 }
344 }
345 if (bcoll_name[0] == '\0') {
346 /* Either there was no name defined in the custom property, or
347 * it was the empty string. */
348 SNPRINTF(bcoll_name, "Layer %u", layer + 1);
349 }
350
351 /* Create a new bone collection for this layer. */
352 BoneCollection *bcoll = ANIM_armature_bonecoll_new(arm, bcoll_name);
353 layermask_collection.append(std::make_pair(layer_mask, bcoll));
354
355 if ((arm->layer & layer_mask) == 0) {
356 ANIM_bonecoll_hide(arm, bcoll);
357 }
358 }
359
360 /* Iterate over the bones to assign them to their layers. */
361 blender::animrig::ANIM_armature_foreach_bone(&arm->bonebase, [&](Bone *bone) {
362 for (auto layer_bcoll : layermask_collection) {
363 const uint layer_mask = layer_bcoll.first;
364 if ((bone->layer & layer_mask) == 0) {
365 continue;
366 }
367
368 BoneCollection *bcoll = layer_bcoll.second;
369 ANIM_armature_bonecoll_assign(bcoll, bone);
370 }
371 });
372 }
373}
374
376{
377 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
378 if (ob->type != OB_ARMATURE || !ob->pose) {
379 continue;
380 }
381
382 /* Convert the bone groups on a bone-by-bone basis. */
383 bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
384 bPose *pose = ob->pose;
385
387 /* Convert all bone groups, regardless of whether they contain any bones. */
388 LISTBASE_FOREACH (bActionGroup *, bgrp, &pose->agroups) {
389 BoneCollection *bcoll = ANIM_armature_bonecoll_new(arm, bgrp->name);
390 collections_by_group.add_new(bgrp, bcoll);
391
392 /* Before now, bone visibility was determined by armature layers, and bone
393 * groups did not have any impact on this. To retain the behavior, that
394 * hiding all layers a bone is on hides the bone, the
395 * bone-group-collections should be created hidden. */
396 ANIM_bonecoll_hide(arm, bcoll);
397 }
398
399 /* Assign the bones to their bone group based collection. */
400 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
401 /* Find the bone group of this pose channel. */
402 const bActionGroup *bgrp = (const bActionGroup *)BLI_findlink(&pose->agroups,
403 (pchan->agrp_index - 1));
404 if (!bgrp) {
405 continue;
406 }
407
408 /* Assign the bone. */
409 BoneCollection *bcoll = collections_by_group.lookup(bgrp);
410 ANIM_armature_bonecoll_assign(bcoll, pchan->bone);
411 }
412
413 /* The list of bone groups (pose->agroups) is intentionally left alone here. This will allow
414 * for older versions of Blender to open the file with bone groups intact. Of course the bone
415 * groups will not be updated any more, but this way the data at least survives an accidental
416 * save with Blender 4.0. */
417 }
418}
419
425{
426 const blender::StringRef rna_path(fcurve->rna_path);
427 constexpr char const *rna_path_prefix = "collections[";
428 if (!rna_path.startswith(rna_path_prefix)) {
429 return;
430 }
431
432 const std::string path_remainder(rna_path.drop_known_prefix(rna_path_prefix));
433 MEM_freeN(fcurve->rna_path);
434 fcurve->rna_path = BLI_sprintfN("collections_all[%s", path_remainder.c_str());
435}
436
438{
439 ID *id = &ntree->id;
441
442 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
443 if (node->type != SH_NODE_BSDF_PRINCIPLED) {
444 continue;
445 }
446
447 char node_name_escaped[MAX_NAME * 2];
448 BLI_str_escape(node_name_escaped, node->name, sizeof(node_name_escaped));
449 std::string prefix = "nodes[\"" + std::string(node_name_escaped) + "\"].inputs";
450
451 /* Remove animdata for inputs 18 (Transmission Roughness) and 3 (Subsurface Color). */
452 BKE_animdata_fix_paths_remove(id, (prefix + "[18]").c_str());
453 BKE_animdata_fix_paths_remove(id, (prefix + "[3]").c_str());
454
455 /* Order is important here: If we e.g. want to change A->B and B->C, but perform A->B first,
456 * then later we don't know whether a B entry is an original B (and therefore should be
457 * changed to C) or used to be A and was already handled.
458 * In practice, going reverse mostly works, the two notable dependency chains are:
459 * - 8->13, then 2->8, then 9->2 (13 was changed before)
460 * - 1->9, then 6->1 (9 was changed before)
461 * - 4->10, then 21->4 (10 was changed before)
462 *
463 * 0 (Base Color) and 17 (Transmission) are fine as-is. */
464 std::pair<int, int> remap_table[] = {
465 {20, 27}, /* Emission Strength */
466 {19, 26}, /* Emission */
467 {16, 3}, /* IOR */
468 {15, 19}, /* Clearcoat Roughness */
469 {14, 18}, /* Clearcoat */
470 {13, 25}, /* Sheen Tint */
471 {12, 23}, /* Sheen */
472 {11, 15}, /* Anisotropic Rotation */
473 {10, 14}, /* Anisotropic */
474 {8, 13}, /* Specular Tint */
475 {2, 8}, /* Subsurface Radius */
476 {9, 2}, /* Roughness */
477 {7, 12}, /* Specular */
478 {1, 9}, /* Subsurface Scale */
479 {6, 1}, /* Metallic */
480 {5, 11}, /* Subsurface Anisotropy */
481 {4, 10}, /* Subsurface IOR */
482 {21, 4} /* Alpha */
483 };
484 for (const auto &entry : remap_table) {
486 id, adt, owner_id, prefix.c_str(), nullptr, nullptr, entry.first, entry.second, false);
487 }
488 }
489}
490
492{
496
497 short *material_len = BKE_object_material_len_p(object);
498 if (!material_len) {
499 return;
500 }
501
502 using namespace blender;
503 bool hide_shadows = *material_len > 0;
504 for (int i : IndexRange(*material_len)) {
505 Material *material = BKE_object_material_get(object, i + 1);
506 if (!material || material->blend_shadow != MA_BS_NONE) {
507 hide_shadows = false;
508 }
509 }
510
511 /* Enable the hide_shadow flag only if there's not any shadow casting material. */
512 SET_FLAG_FROM_TEST(object->visibility_flag, hide_shadows, OB_HIDE_SHADOW);
513}
514
516{
517 if (!material->use_nodes || material->nodetree == nullptr) {
518 return;
519 }
520 bNodeTree *ntree = material->nodetree;
521
524 if (output_node == nullptr) {
525 return;
526 }
527
528 bNodeSocket *existing_out_sock = blender::bke::node_find_socket(output_node, SOCK_IN, "Surface");
529 bNodeSocket *volume_sock = blender::bke::node_find_socket(output_node, SOCK_IN, "Volume");
530 if (existing_out_sock->link == nullptr && volume_sock->link) {
531 /* Don't apply versioning to a material that only has a volumetric input as this makes the
532 * object surface opaque to the camera, hiding the volume inside. */
533 return;
534 }
535
536 if (output_node->custom1 == SHD_OUTPUT_ALL) {
537 /* We do not want to affect Cycles. So we split the output into two specific outputs. */
538 output_node->custom1 = SHD_OUTPUT_CYCLES;
539
540 bNode *new_output = blender::bke::node_add_node(nullptr, ntree, "ShaderNodeOutputMaterial");
541 new_output->custom1 = SHD_OUTPUT_EEVEE;
542 new_output->parent = output_node->parent;
543 new_output->locx = output_node->locx;
544 new_output->locy = output_node->locy - output_node->height - 120;
545
546 auto copy_link = [&](const char *socket_name) {
547 bNodeSocket *sock = blender::bke::node_find_socket(output_node, SOCK_IN, socket_name);
548 if (sock && sock->link) {
549 bNodeLink *link = sock->link;
550 bNodeSocket *to_sock = blender::bke::node_find_socket(new_output, SOCK_IN, socket_name);
551 blender::bke::node_add_link(ntree, link->fromnode, link->fromsock, new_output, to_sock);
552 }
553 };
554
555 /* Don't copy surface as that is handled later */
556 copy_link("Volume");
557 copy_link("Displacement");
558 copy_link("Thickness");
559
560 output_node = new_output;
561 }
562
563 bNodeSocket *out_sock = blender::bke::node_find_socket(output_node, SOCK_IN, "Surface");
564 bNodeSocket *old_out_sock = blender::bke::node_find_socket(old_output_node, SOCK_IN, "Surface");
565
566 /* Add mix node for mixing between original material, and transparent BSDF for shadows */
567 bNode *mix_node = blender::bke::node_add_node(nullptr, ntree, "ShaderNodeMixShader");
568 STRNCPY(mix_node->label, "Disable Shadow");
569 mix_node->flag |= NODE_HIDDEN;
570 mix_node->parent = output_node->parent;
571 mix_node->locx = output_node->locx;
572 mix_node->locy = output_node->locy - output_node->height - 120;
573 bNodeSocket *mix_fac = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->inputs, 0));
574 bNodeSocket *mix_in_1 = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->inputs, 1));
575 bNodeSocket *mix_in_2 = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->inputs, 2));
576 bNodeSocket *mix_out = static_cast<bNodeSocket *>(BLI_findlink(&mix_node->outputs, 0));
577 if (old_out_sock->link != nullptr) {
579 ntree, old_out_sock->link->fromnode, old_out_sock->link->fromsock, mix_node, mix_in_1);
580 if (out_sock->link != nullptr) {
581 blender::bke::node_remove_link(ntree, out_sock->link);
582 }
583 }
584 blender::bke::node_add_link(ntree, mix_node, mix_out, output_node, out_sock);
585
586 /* Add light path node to control shadow visibility */
587 bNode *lp_node = blender::bke::node_add_node(nullptr, ntree, "ShaderNodeLightPath");
588 lp_node->flag |= NODE_HIDDEN;
589 lp_node->parent = output_node->parent;
590 lp_node->locx = output_node->locx;
591 lp_node->locy = mix_node->locy + 35;
592 bNodeSocket *is_shadow = blender::bke::node_find_socket(lp_node, SOCK_OUT, "Is Shadow Ray");
593 blender::bke::node_add_link(ntree, lp_node, is_shadow, mix_node, mix_fac);
594 /* Hide unconnected sockets for cleaner look. */
595 LISTBASE_FOREACH (bNodeSocket *, sock, &lp_node->outputs) {
596 if (sock != is_shadow) {
597 sock->flag |= SOCK_HIDDEN;
598 }
599 }
600
601 /* Add transparent BSDF to make shadows transparent. */
602 bNode *bsdf_node = blender::bke::node_add_node(nullptr, ntree, "ShaderNodeBsdfTransparent");
603 bsdf_node->flag |= NODE_HIDDEN;
604 bsdf_node->parent = output_node->parent;
605 bsdf_node->locx = output_node->locx;
606 bsdf_node->locy = mix_node->locy - 35;
607 bNodeSocket *bsdf_out = blender::bke::node_find_socket(bsdf_node, SOCK_OUT, "BSDF");
608 blender::bke::node_add_link(ntree, bsdf_node, bsdf_out, mix_node, mix_in_2);
609}
610
619 /* Alpha input is 0. */
621 /* Alpha input is 1. */
623 /* Alpha is between 0 and 1, from a graph input or the result of one blending operation. */
625 /* Alpha is unknown and the result of more than one blending operation. */
627 };
628
629 /* Socket that is the source of the potential semi-transparency. */
630 bNodeSocket *socket = nullptr;
631 /* State of the source. */
633 /* True if socket is transparency instead of alpha (e.g: `1-alpha`). */
634 bool is_transparency = false;
635
636 static AlphaSource alpha_source(bNodeSocket *fac, bool inverted = false)
637 {
638 return {fac, ALPHA_SEMI_TRANSPARENT, inverted};
639 }
641 {
642 return {nullptr, ALPHA_OPAQUE, false};
643 }
644 static AlphaSource fully_transparent(bNodeSocket *socket = nullptr, bool inverted = false)
645 {
646 return {socket, ALPHA_FULLY_TRANSPARENT, inverted};
647 }
649 {
650 return {nullptr, ALPHA_COMPLEX_MIX, false};
651 }
652
653 bool is_opaque() const
654 {
655 return state == ALPHA_OPAQUE;
656 }
658 {
660 }
661 bool is_transparent() const
662 {
663 return state != ALPHA_OPAQUE;
664 }
666 {
668 }
669 bool is_complex() const
670 {
671 return state == ALPHA_COMPLEX_MIX;
672 }
673
674 /* Combine two source together with a blending parameter. */
675 static AlphaSource mix(const AlphaSource &a, const AlphaSource &b, bNodeSocket *fac)
676 {
677 if (a.is_complex() || b.is_complex()) {
678 return complex_alpha();
679 }
680 if (a.is_semi_transparent() || b.is_semi_transparent()) {
681 return complex_alpha();
682 }
683 if (a.is_fully_transparent() && b.is_fully_transparent()) {
684 return fully_transparent();
685 }
686 if (a.is_opaque() && b.is_opaque()) {
687 return opaque();
688 }
689 /* Only one of them is fully transparent. */
690 return alpha_source(fac, !a.is_transparent());
691 }
692
693 /* Combine two source together with an additive blending parameter. */
694 static AlphaSource add(const AlphaSource &a, const AlphaSource &b)
695 {
696 if (a.is_complex() || b.is_complex()) {
697 return complex_alpha();
698 }
699 if (a.is_semi_transparent() && b.is_transparent()) {
700 return complex_alpha();
701 }
702 if (a.is_transparent() && b.is_semi_transparent()) {
703 return complex_alpha();
704 }
705 /* Either one of them is opaque or they are both opaque. */
706 return a.is_transparent() ? a : b;
707 }
708};
709
714{
715 if (depth > 100) {
716 /* Protection against infinite / very long recursion.
717 * Also a node-tree with that much depth is likely to not be compatible. */
719 }
720
721 if (socket->link == nullptr) {
722 /* Unconnected closure socket is always opaque black. */
723 return AlphaSource::opaque();
724 }
725
726 bNode *node = socket->link->fromnode;
727
728 switch (node->type) {
729 case NODE_REROUTE: {
731 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0)), depth + 1);
732 }
733
734 case NODE_GROUP: {
736 }
737
739 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_IN, "Color");
740 if (socket->link == nullptr) {
741 float *socket_color_value = version_cycles_node_socket_rgba_value(socket);
742 if ((socket_color_value[0] == 0.0f) && (socket_color_value[1] == 0.0f) &&
743 (socket_color_value[2] == 0.0f))
744 {
745 return AlphaSource::opaque();
746 }
747 if ((socket_color_value[0] == 1.0f) && (socket_color_value[1] == 1.0f) &&
748 (socket_color_value[2] == 1.0f))
749 {
750 return AlphaSource::fully_transparent(socket, true);
751 }
752 }
753 return AlphaSource::alpha_source(socket, true);
754 }
755
756 case SH_NODE_MIX_SHADER: {
757 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_IN, "Fac");
759 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1)), depth + 1);
761 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2)), depth + 1);
762
763 if (socket->link == nullptr) {
764 float socket_float_value = *version_cycles_node_socket_float_value(socket);
765 if (socket_float_value == 0.0f) {
766 return src0;
767 }
768 if (socket_float_value == 1.0f) {
769 return src1;
770 }
771 }
772 return AlphaSource::mix(src0, src1, socket);
773 }
774
775 case SH_NODE_ADD_SHADER: {
777 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0)), depth + 1);
779 static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1)), depth + 1);
780 return AlphaSource::add(src0, src1);
781 }
782
784 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_IN, "Alpha");
785 if (socket->link == nullptr) {
786 float socket_value = *version_cycles_node_socket_float_value(socket);
787 if (socket_value == 0.0f) {
788 return AlphaSource::fully_transparent(socket);
789 }
790 if (socket_value == 1.0f) {
791 return AlphaSource::opaque();
792 }
793 }
794 return AlphaSource::alpha_source(socket);
795 }
796
798 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_IN, "Transparency");
799 if (socket->link == nullptr) {
800 float socket_value = *version_cycles_node_socket_float_value(socket);
801 if (socket_value == 0.0f) {
802 return AlphaSource::fully_transparent(socket, true);
803 }
804 if (socket_value == 1.0f) {
805 return AlphaSource::opaque();
806 }
807 }
808 return AlphaSource::alpha_source(socket, true);
809 }
810
811 default:
812 return AlphaSource::opaque();
813 }
814}
815
825{
827 if (output_node == nullptr) {
828 return true;
829 }
830 bNodeSocket *surface_socket = blender::bke::node_find_socket(output_node, SOCK_IN, "Surface");
831
832 AlphaSource alpha = versioning_eevee_alpha_source_get(surface_socket);
833
834 if (alpha.is_complex()) {
835 return false;
836 }
837 if (alpha.socket == nullptr) {
838 return true;
839 }
840
841 bool is_opaque = (threshold == 2.0f);
842 if (is_opaque) {
843 if (alpha.socket->link != nullptr) {
845 }
846
847 float value = (alpha.is_transparency) ? 0.0f : 1.0f;
848 float values[4] = {value, value, value, 1.0f};
849
850 /* Set default value to opaque. */
851 if (alpha.socket->type == SOCK_RGBA) {
853 }
854 else {
856 }
857 }
858 else {
859 if (alpha.socket->link != nullptr) {
860 /* Insert math node. */
861 bNode *to_node = alpha.socket->link->tonode;
862 bNode *from_node = alpha.socket->link->fromnode;
863 bNodeSocket *to_socket = alpha.socket->link->tosock;
864 bNodeSocket *from_socket = alpha.socket->link->fromsock;
866
867 bNode *math_node = blender::bke::node_add_node(nullptr, ntree, "ShaderNodeMath");
868 math_node->custom1 = NODE_MATH_GREATER_THAN;
869 math_node->flag |= NODE_HIDDEN;
870 math_node->parent = to_node->parent;
871 math_node->locx = to_node->locx - math_node->width - 30;
872 math_node->locy = min_ff(to_node->locy, from_node->locy);
873
874 bNodeSocket *input_1 = static_cast<bNodeSocket *>(BLI_findlink(&math_node->inputs, 0));
875 bNodeSocket *input_2 = static_cast<bNodeSocket *>(BLI_findlink(&math_node->inputs, 1));
876 bNodeSocket *output = static_cast<bNodeSocket *>(math_node->outputs.first);
877 bNodeSocket *alpha_sock = input_1;
878 bNodeSocket *threshold_sock = input_2;
879
880 blender::bke::node_add_link(ntree, from_node, from_socket, math_node, alpha_sock);
881 blender::bke::node_add_link(ntree, math_node, output, to_node, to_socket);
882
884 1.0f - threshold :
885 threshold;
886 }
887 else {
888 /* Modify alpha value directly. */
889 if (alpha.socket->type == SOCK_RGBA) {
890 float *default_value = version_cycles_node_socket_rgba_value(alpha.socket);
891 float sum = default_value[0] + default_value[1] + default_value[2];
892 /* Don't do the division if possible to avoid float imprecision. */
893 float avg = (sum >= 3.0f) ? 1.0f : (sum / 3.0f);
894 float value = float((alpha.is_transparency) ? (avg > 1.0f - threshold) :
895 (avg > threshold));
896 float values[4] = {value, value, value, 1.0f};
897 copy_v4_v4(default_value, values);
898 }
899 else {
900 float *default_value = version_cycles_node_socket_float_value(alpha.socket);
901 *default_value = float((alpha.is_transparency) ? (*default_value > 1.0f - threshold) :
902 (*default_value > threshold));
903 }
904 }
905 }
906 return true;
907}
908
910{
911 /* Split viewer was replaced with a regular split node, so add a viewer node,
912 * and link it to the new split node to achieve the same behavior of the split viewer node. */
913
914 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
915 if (node->type != CMP_NODE_SPLITVIEWER__DEPRECATED) {
916 continue;
917 }
918
919 STRNCPY(node->idname, "CompositorNodeSplit");
920 node->type = CMP_NODE_SPLIT;
921 MEM_freeN(node->storage);
922 node->storage = nullptr;
923
924 bNode *viewer_node = blender::bke::node_add_static_node(nullptr, ntree, CMP_NODE_VIEWER);
925 /* Nodes are created stacked on top of each other, so separate them a bit. */
926 viewer_node->locx = node->locx + node->width + viewer_node->width / 4.0f;
927 viewer_node->locy = node->locy;
928 viewer_node->flag &= ~NODE_PREVIEW;
929
931 ntree, node, SOCK_OUT, SOCK_IMAGE, PROP_NONE, "Image", "Image");
932 bNodeSocket *viewer_in_socket = blender::bke::node_find_socket(viewer_node, SOCK_IN, "Image");
933
934 blender::bke::node_add_link(ntree, node, split_out_socket, viewer_node, viewer_in_socket);
935 }
936}
937
950{
951 bool any_valid_tweakmode_left = false;
952
953 ID *id;
954 FOREACH_MAIN_ID_BEGIN (bmain, id) {
956 if (!adt || !(adt->flag & ADT_NLA_EDIT_ON)) {
957 continue;
958 }
959
960 if (adt->act_track && adt->actstrip) {
961 /* Expected case. */
962 any_valid_tweakmode_left = true;
963 continue;
964 }
965
966 /* Not enough info in the blend file to reliably stay in tweak mode. This is the most important
967 * part of this versioning code, as it prevents future nullptr access. */
968 BKE_nla_tweakmode_exit({*id, *adt});
969 }
971
972 if (any_valid_tweakmode_left) {
973 /* There are still NLA strips correctly in tweak mode. */
974 return;
975 }
976
977 /* Nothing is in a valid tweakmode, so just disable the corresponding flags on all scenes. */
978 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
979 scene->flag &= ~SCE_NLA_EDIT_ON;
980 }
981}
982
984{
985 const Scene *scene = static_cast<Scene *>(user_data);
986 const float speed_factor = seq->speed_factor;
987
988 if (speed_factor == 1.0f || !SEQ_retiming_is_allowed(seq) || SEQ_retiming_keys_count(seq) > 0) {
989 return true;
990 }
991
994
995 last_key->strip_frame_index = (seq->len) / speed_factor;
996
997 if (seq->type == SEQ_TYPE_SOUND_RAM) {
998 const int prev_length = seq->len - seq->startofs - seq->endofs;
999 const float left_handle = SEQ_time_left_handle_frame_get(scene, seq);
1000 SEQ_time_right_handle_frame_set(scene, seq, left_handle + prev_length);
1001 }
1002
1003 return true;
1004}
1005
1007{
1008 if (!bmain->scenes.first) {
1009 return false;
1010 }
1011
1012 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1013 bool match = false;
1014 for (const char *engine : engines) {
1015 if (STREQ(scene->r.engine, engine)) {
1016 match = true;
1017 }
1018 }
1019 if (!match) {
1020 return false;
1021 }
1022 }
1023
1024 return true;
1025}
1026
1028{
1029 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) {
1030 /* Fix area light scaling. */
1031 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
1032 light->energy = light->energy_deprecated;
1033 if (light->type == LA_AREA) {
1034 light->energy *= M_PI_4;
1035 }
1036 }
1037
1038 /* XXX This was added several years ago in 'lib_link` code of Scene... Should be safe enough
1039 * here. */
1040 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1041 if (scene->nodetree) {
1042 version_composite_nodetree_null_id(scene->nodetree, scene);
1043 }
1044 }
1045
1046 /* XXX This was added many years ago (1c19940198) in 'lib_link` code of particles as a bug-fix.
1047 * But this is actually versioning. Should be safe enough here. */
1048 LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
1049 if (!part->effector_weights) {
1050 part->effector_weights = BKE_effector_add_weights(part->force_group);
1051 }
1052 }
1053
1054 /* Object proxies have been deprecated sine 3.x era, so their update & sanity check can now
1055 * happen in do_versions code. */
1056 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1057 if (ob->proxy) {
1058 /* Paranoia check, actually a proxy_from pointer should never be written... */
1059 if (!ID_IS_LINKED(ob->proxy)) {
1060 ob->proxy->proxy_from = nullptr;
1061 ob->proxy = nullptr;
1062
1063 if (ob->id.lib) {
1065 RPT_INFO,
1066 RPT_("Proxy lost from object %s lib %s\n"),
1067 ob->id.name + 2,
1068 ob->id.lib->filepath);
1069 }
1070 else {
1072 RPT_INFO,
1073 RPT_("Proxy lost from object %s lib <NONE>\n"),
1074 ob->id.name + 2);
1075 }
1077 }
1078 else {
1079 /* This triggers object_update to always use a copy. */
1080 ob->proxy->proxy_from = ob;
1081 }
1082 }
1083 }
1084 }
1085
1086 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 21)) {
1087 if (!DNA_struct_member_exists(fd->filesdna, "bPoseChannel", "BoneColor", "color")) {
1089 }
1090
1091 if (!DNA_struct_member_exists(fd->filesdna, "bArmature", "ListBase", "collections")) {
1094 }
1095 }
1096
1097 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 24)) {
1098 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1099 if (ntree->type == NTREE_SHADER) {
1100 /* Convert animdata on the Principled BSDF sockets. */
1102 }
1103 }
1105 }
1106
1107 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 27)) {
1108 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1109 Editing *ed = SEQ_editing_get(scene);
1110 if (ed != nullptr) {
1112 }
1113 }
1114 }
1115
1116 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 34)) {
1118 }
1119
1120 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 23)) {
1122 }
1123
1124 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 15)) {
1125 /* Change drivers and animation on "armature.collections" to
1126 * ".collections_all", so that they are drawn correctly in the tree view,
1127 * and keep working when the collection is moved around in the hierarchy. */
1128 LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
1129 AnimData *adt = BKE_animdata_from_id(&arm->id);
1130 if (!adt) {
1131 continue;
1132 }
1133
1134 LISTBASE_FOREACH (FCurve *, fcurve, &adt->drivers) {
1136 }
1137 if (adt->action) {
1138 LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) {
1140 }
1141 }
1142 }
1143 }
1144
1145 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 23)) {
1146 /* Shift animation data to accommodate the new Roughness input. */
1149 }
1150
1151 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 50)) {
1153 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
1155 }
1156 }
1157 }
1158
1159 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 51)) {
1160 /* Convert blend method to math nodes. */
1162 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
1163 if (!material->use_nodes || material->nodetree == nullptr) {
1164 /* Nothing to version. */
1165 }
1166 else if (ELEM(material->blend_method, MA_BM_HASHED, MA_BM_BLEND)) {
1167 /* Compatible modes. Nothing to change. */
1168 }
1169 else if (material->blend_shadow == MA_BS_NONE) {
1170 /* No need to match the surface since shadows are disabled. */
1171 }
1172 else if (material->blend_shadow == MA_BS_SOLID) {
1173 /* This is already versioned an transferred to `transparent_shadows`. */
1174 }
1175 else if ((material->blend_shadow == MA_BS_CLIP && material->blend_method != MA_BM_CLIP) ||
1176 (material->blend_shadow == MA_BS_HASHED))
1177 {
1179 fd->reports,
1181 RPT_("Material %s could not be converted because of different Blend Mode "
1182 "and Shadow Mode (need manual adjustment)\n"),
1183 material->id.name + 2);
1184 }
1185 else {
1186 /* TODO(fclem): Check if threshold is driven or has animation. Bail out if needed? */
1187
1188 float threshold = (material->blend_method == MA_BM_CLIP) ? material->alpha_threshold :
1189 2.0f;
1190
1191 if (!versioning_eevee_material_blend_mode_settings(material->nodetree, threshold)) {
1194 RPT_("Material %s could not be converted because of non-trivial "
1195 "alpha blending (need manual adjustment)\n"),
1196 material->id.name + 2);
1197 }
1198 }
1199
1200 if (material->blend_shadow == MA_BS_NONE) {
1202 }
1203 /* Set blend_mode & blend_shadow for forward compatibility. */
1204 material->blend_method = (material->blend_method != MA_BM_BLEND) ? MA_BM_HASHED :
1206 material->blend_shadow = (material->blend_shadow == MA_BS_SOLID) ? MA_BS_SOLID :
1208 }
1209 }
1210 }
1211
1212 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 52)) {
1213 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1214 if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
1215 STRNCPY(scene->r.engine, RE_engine_id_BLENDER_EEVEE_NEXT);
1216 }
1217 }
1218 }
1219
1220 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 6)) {
1221 /* Shift animation data to accommodate the new Diffuse Roughness input. */
1223 }
1224
1225 /* Keeping this block is without a `MAIN_VERSION_FILE_ATLEAST` until the experimental flag is
1226 * removed. */
1227 if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
1229 }
1230
1237}
1238
1257
1259{
1260 MovieTracking &tracking = movieclip.tracking;
1261 MovieTrackingObject *active_tracking_object = BKE_tracking_object_get_active(&tracking);
1262 MovieTrackingObject *tracking_camera_object = BKE_tracking_object_get_camera(&tracking);
1263
1264 BLI_assert(tracking_camera_object != nullptr);
1265
1266 if (BLI_listbase_is_empty(&tracking_camera_object->tracks)) {
1267 tracking_camera_object->tracks = tracking.tracks_legacy;
1268 active_tracking_object->active_track = tracking.act_track_legacy;
1269 }
1270
1271 if (BLI_listbase_is_empty(&tracking_camera_object->plane_tracks)) {
1272 tracking_camera_object->plane_tracks = tracking.plane_tracks_legacy;
1273 active_tracking_object->active_plane_track = tracking.act_plane_track_legacy;
1274 }
1275
1276 if (tracking_camera_object->reconstruction.cameras == nullptr) {
1277 tracking_camera_object->reconstruction = tracking.reconstruction_legacy;
1278 }
1279
1280 /* Clear pointers in the legacy storage.
1281 * Always do it, in the case something got missed in the logic above, so that the legacy storage
1282 * is always ensured to be empty after load. */
1285 tracking.act_track_legacy = nullptr;
1286 tracking.act_plane_track_legacy = nullptr;
1287 memset(&tracking.reconstruction_legacy, 0, sizeof(tracking.reconstruction_legacy));
1288}
1289
1291{
1292 LISTBASE_FOREACH (MovieClip *, movieclip, &bmain->movieclips) {
1294 }
1295}
1296
1297/* Version VertexWeightEdit modifier to make existing weights exclusive of the threshold. */
1299{
1300 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1301 if (ob->type != OB_MESH) {
1302 continue;
1303 }
1304
1305 LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
1306 if (md->type == eModifierType_WeightVGEdit) {
1307 WeightVGEditModifierData *wmd = reinterpret_cast<WeightVGEditModifierData *>(md);
1308 wmd->add_threshold = nexttoward(wmd->add_threshold, 2.0);
1309 wmd->rem_threshold = nexttoward(wmd->rem_threshold, -1.0);
1310 }
1311 }
1312 }
1313}
1314
1316{
1317 LISTBASE_FOREACH (Mesh *, mesh, &bmain.meshes) {
1319 }
1320
1321 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain.nodetrees) {
1322 if (ntree->type == NTREE_GEOMETRY) {
1323 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1324 if (STR_ELEM(node->idname,
1325 "GeometryNodeStoreNamedAttribute",
1326 "GeometryNodeInputNamedAttribute"))
1327 {
1328 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_IN, "Name");
1329 if (STREQ(socket->default_value_typed<bNodeSocketValueString>()->value, "crease")) {
1330 STRNCPY(socket->default_value_typed<bNodeSocketValueString>()->value, "crease_edge");
1331 }
1332 }
1333 }
1334 }
1335 }
1336
1337 LISTBASE_FOREACH (Object *, object, &bmain.objects) {
1338 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
1339 if (md->type != eModifierType_Nodes) {
1340 continue;
1341 }
1342 if (IDProperty *settings = reinterpret_cast<NodesModifierData *>(md)->settings.properties) {
1343 LISTBASE_FOREACH (IDProperty *, prop, &settings->data.group) {
1344 if (blender::StringRef(prop->name).endswith("_attribute_name")) {
1345 if (STREQ(IDP_String(prop), "crease")) {
1346 IDP_AssignString(prop, "crease_edge");
1347 }
1348 }
1349 }
1350 }
1351 }
1352 }
1353}
1354
1356{
1357 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1358 if (node->type == SH_NODE_BSDF_GLOSSY_LEGACY) {
1359 STRNCPY(node->idname, "ShaderNodeBsdfAnisotropic");
1360 node->type = SH_NODE_BSDF_GLOSSY;
1361 }
1362 }
1363}
1364
1366{
1367 /* Find all glossy, glass and refraction BSDF nodes that have their distribution
1368 * set to SHARP and set them to GGX, disconnect any link to the Roughness input
1369 * and set its value to zero. */
1370 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1372 continue;
1373 }
1374 if (node->custom1 != SHD_GLOSSY_SHARP_DEPRECATED) {
1375 continue;
1376 }
1377
1378 node->custom1 = SHD_GLOSSY_GGX;
1379 LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
1380 if (!STREQ(socket->identifier, "Roughness")) {
1381 continue;
1382 }
1383
1384 if (socket->link != nullptr) {
1385 blender::bke::node_remove_link(ntree, socket->link);
1386 }
1387 bNodeSocketValueFloat *socket_value = (bNodeSocketValueFloat *)socket->default_value;
1388 socket_value->value = 0.0f;
1389
1390 break;
1391 }
1392 }
1393}
1394
1396{
1397 /* The normal of a spot light was set to the incoming light direction, replace with the
1398 * `Incoming` socket from the Geometry shader node. */
1399 bNode *geometry_node = nullptr;
1400 bNode *transform_node = nullptr;
1401 bNodeSocket *incoming_socket = nullptr;
1402 bNodeSocket *vec_in_socket = nullptr;
1403 bNodeSocket *vec_out_socket = nullptr;
1404
1405 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
1406 if (link->fromnode->type == SH_NODE_TEX_COORD && STREQ(link->fromsock->identifier, "Normal")) {
1407 if (geometry_node == nullptr) {
1408 geometry_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_NEW_GEOMETRY);
1409 incoming_socket = blender::bke::node_find_socket(geometry_node, SOCK_OUT, "Incoming");
1410
1411 transform_node = blender::bke::node_add_static_node(
1412 nullptr, ntree, SH_NODE_VECT_TRANSFORM);
1413 vec_in_socket = blender::bke::node_find_socket(transform_node, SOCK_IN, "Vector");
1414 vec_out_socket = blender::bke::node_find_socket(transform_node, SOCK_OUT, "Vector");
1415
1416 NodeShaderVectTransform *nodeprop = (NodeShaderVectTransform *)transform_node->storage;
1418
1420 ntree, geometry_node, incoming_socket, transform_node, vec_in_socket);
1421 }
1423 ntree, transform_node, vec_out_socket, link->tonode, link->tosock);
1424 blender::bke::node_remove_link(ntree, link);
1425 }
1426 }
1427}
1428
1430{
1431 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1432 if (node->type != SH_NODE_BSDF_PRINCIPLED) {
1433 continue;
1434 }
1435 bNodeSocket *sock = blender::bke::node_find_socket(node, SOCK_IN, "Transmission Roughness");
1436 if (sock != nullptr) {
1437 blender::bke::node_remove_socket(ntree, node, sock);
1438 }
1439 }
1440}
1441
1442/* Convert legacy Velvet BSDF nodes into the new Sheen BSDF node. */
1444{
1445 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1446 if (node->type == SH_NODE_BSDF_SHEEN) {
1447 STRNCPY(node->idname, "ShaderNodeBsdfSheen");
1448
1449 bNodeSocket *sigmaInput = blender::bke::node_find_socket(node, SOCK_IN, "Sigma");
1450 if (sigmaInput != nullptr) {
1451 node->custom1 = SHD_SHEEN_ASHIKHMIN;
1452 STRNCPY(sigmaInput->identifier, "Roughness");
1453 STRNCPY(sigmaInput->name, "Roughness");
1454 }
1455 }
1456 }
1457}
1458
1459/* Convert sheen inputs on the Principled BSDF. */
1461{
1462 auto check_node = [](const bNode *node) {
1463 return (node->type == SH_NODE_BSDF_PRINCIPLED) &&
1464 (blender::bke::node_find_socket(node, SOCK_IN, "Sheen Roughness") == nullptr);
1465 };
1466 auto update_input = [ntree](bNode *node, bNodeSocket *input) {
1467 /* Change socket type to Color. */
1469
1470 /* Account for the change in intensity between the old and new model.
1471 * If the Sheen input is set to a fixed value, adjust it and set the tint to white.
1472 * Otherwise, if it's connected, keep it as-is but set the tint to 0.2 instead. */
1474 if (sheen != nullptr && sheen->link == nullptr) {
1476
1477 static float default_value[] = {1.0f, 1.0f, 1.0f, 1.0f};
1479 }
1480 else {
1481 static float default_value[] = {0.2f, 0.2f, 0.2f, 1.0f};
1483 }
1484 };
1485 auto update_input_link = [](bNode *, bNodeSocket *, bNode *, bNodeSocket *) {
1486 /* Don't replace the link here, tint works differently enough now to make conversion
1487 * impractical. */
1488 };
1489
1490 version_update_node_input(ntree, check_node, "Sheen Tint", update_input, update_input_link);
1491}
1492
1493/* Convert EEVEE-Legacy refraction depth to EEVEE-Next thickness tree. */
1494static void version_refraction_depth_to_thickness_value(bNodeTree *ntree, float thickness)
1495{
1496 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1497 if (node->type != SH_NODE_OUTPUT_MATERIAL) {
1498 continue;
1499 }
1500
1501 bNodeSocket *thickness_socket = blender::bke::node_find_socket(node, SOCK_IN, "Thickness");
1502 if (thickness_socket == nullptr) {
1503 continue;
1504 }
1505
1506 bool has_link = false;
1507 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1508 if (link->tosock == thickness_socket) {
1509 /* Something is already plugged in. Don't modify anything. */
1510 has_link = true;
1511 }
1512 }
1513
1514 if (has_link) {
1515 continue;
1516 }
1517 bNode *value_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_VALUE);
1518 value_node->parent = node->parent;
1519 value_node->locx = node->locx;
1520 value_node->locy = node->locy - 160.0f;
1521 bNodeSocket *socket_value = blender::bke::node_find_socket(value_node, SOCK_OUT, "Value");
1522
1523 *version_cycles_node_socket_float_value(socket_value) = thickness;
1524
1525 blender::bke::node_add_link(ntree, value_node, socket_value, node, thickness_socket);
1526 }
1527
1529}
1530
1532{
1533 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1534 if (node->type != SH_NODE_TEX_NOISE) {
1535 continue;
1536 }
1537
1538 (static_cast<NodeTexNoise *>(node->storage))->type = SHD_NOISE_FBM;
1539
1540 bNodeSocket *roughness_socket = blender::bke::node_find_socket(node, SOCK_IN, "Roughness");
1541 if (roughness_socket == nullptr) {
1542 /* Noise Texture node was created before the Roughness input was added. */
1543 continue;
1544 }
1545
1546 float *roughness = version_cycles_node_socket_float_value(roughness_socket);
1547
1548 bNodeLink *roughness_link = nullptr;
1549 bNode *roughness_from_node = nullptr;
1550 bNodeSocket *roughness_from_socket = nullptr;
1551
1552 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1553 /* Find links, nodes and sockets. */
1554 if (link->tosock == roughness_socket) {
1555 roughness_link = link;
1556 roughness_from_node = link->fromnode;
1557 roughness_from_socket = link->fromsock;
1558 }
1559 }
1560
1561 if (roughness_link != nullptr) {
1562 /* Add Clamp node before Roughness input. */
1563
1564 bNode *clamp_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_CLAMP);
1565 clamp_node->parent = node->parent;
1566 clamp_node->custom1 = NODE_CLAMP_MINMAX;
1567 clamp_node->locx = node->locx;
1568 clamp_node->locy = node->locy - 300.0f;
1569 clamp_node->flag |= NODE_HIDDEN;
1570 bNodeSocket *clamp_socket_value = blender::bke::node_find_socket(
1571 clamp_node, SOCK_IN, "Value");
1572 bNodeSocket *clamp_socket_min = blender::bke::node_find_socket(clamp_node, SOCK_IN, "Min");
1573 bNodeSocket *clamp_socket_max = blender::bke::node_find_socket(clamp_node, SOCK_IN, "Max");
1574 bNodeSocket *clamp_socket_out = blender::bke::node_find_socket(
1575 clamp_node, SOCK_OUT, "Result");
1576
1577 *version_cycles_node_socket_float_value(clamp_socket_min) = 0.0f;
1578 *version_cycles_node_socket_float_value(clamp_socket_max) = 1.0f;
1579
1580 blender::bke::node_remove_link(ntree, roughness_link);
1582 ntree, roughness_from_node, roughness_from_socket, clamp_node, clamp_socket_value);
1583 blender::bke::node_add_link(ntree, clamp_node, clamp_socket_out, node, roughness_socket);
1584 }
1585 else {
1586 *roughness = std::clamp(*roughness, 0.0f, 1.0f);
1587 }
1588 }
1589
1591}
1592
1594{
1595 version_node_input_socket_name(ntree, SH_NODE_TEX_MUSGRAVE_DEPRECATED, "Dimension", "Roughness");
1596 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1597 if (node->type != SH_NODE_TEX_MUSGRAVE_DEPRECATED) {
1598 continue;
1599 }
1600
1601 STRNCPY(node->idname, "ShaderNodeTexNoise");
1602 node->type = SH_NODE_TEX_NOISE;
1603 NodeTexNoise *data = MEM_cnew<NodeTexNoise>(__func__);
1604 data->base = (static_cast<NodeTexMusgrave *>(node->storage))->base;
1605 data->dimensions = (static_cast<NodeTexMusgrave *>(node->storage))->dimensions;
1606 data->normalize = false;
1607 data->type = (static_cast<NodeTexMusgrave *>(node->storage))->musgrave_type;
1608 MEM_freeN(node->storage);
1609 node->storage = data;
1610
1611 bNodeLink *detail_link = nullptr;
1612 bNode *detail_from_node = nullptr;
1613 bNodeSocket *detail_from_socket = nullptr;
1614
1615 bNodeLink *roughness_link = nullptr;
1616 bNode *roughness_from_node = nullptr;
1617 bNodeSocket *roughness_from_socket = nullptr;
1618
1619 bNodeLink *lacunarity_link = nullptr;
1620 bNode *lacunarity_from_node = nullptr;
1621 bNodeSocket *lacunarity_from_socket = nullptr;
1622
1623 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1624 /* Find links, nodes and sockets. */
1625 if (link->tonode == node) {
1626 if (STREQ(link->tosock->identifier, "Detail")) {
1627 detail_link = link;
1628 detail_from_node = link->fromnode;
1629 detail_from_socket = link->fromsock;
1630 }
1631 if (STREQ(link->tosock->identifier, "Roughness")) {
1632 roughness_link = link;
1633 roughness_from_node = link->fromnode;
1634 roughness_from_socket = link->fromsock;
1635 }
1636 if (STREQ(link->tosock->identifier, "Lacunarity")) {
1637 lacunarity_link = link;
1638 lacunarity_from_node = link->fromnode;
1639 lacunarity_from_socket = link->fromsock;
1640 }
1641 }
1642 }
1643
1644 uint8_t noise_type = (static_cast<NodeTexNoise *>(node->storage))->type;
1645 float locy_offset = 0.0f;
1646
1647 bNodeSocket *fac_socket = blender::bke::node_find_socket(node, SOCK_OUT, "Fac");
1648 /* Clear label because Musgrave output socket label is set to "Height" instead of "Fac". */
1649 fac_socket->label[0] = '\0';
1650
1651 bNodeSocket *detail_socket = blender::bke::node_find_socket(node, SOCK_IN, "Detail");
1652 float *detail = version_cycles_node_socket_float_value(detail_socket);
1653
1654 if (detail_link != nullptr) {
1655 locy_offset -= 80.0f;
1656
1657 /* Add Minimum Math node and Subtract Math node before Detail input. */
1658
1659 bNode *min_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1660 min_node->parent = node->parent;
1661 min_node->custom1 = NODE_MATH_MINIMUM;
1662 min_node->locx = node->locx;
1663 min_node->locy = node->locy - 320.0f;
1664 min_node->flag |= NODE_HIDDEN;
1665 bNodeSocket *min_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&min_node->inputs, 0));
1666 bNodeSocket *min_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&min_node->inputs, 1));
1667 bNodeSocket *min_socket_out = blender::bke::node_find_socket(min_node, SOCK_OUT, "Value");
1668
1669 bNode *sub1_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1670 sub1_node->parent = node->parent;
1671 sub1_node->custom1 = NODE_MATH_SUBTRACT;
1672 sub1_node->locx = node->locx;
1673 sub1_node->locy = node->locy - 360.0f;
1674 sub1_node->flag |= NODE_HIDDEN;
1675 bNodeSocket *sub1_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&sub1_node->inputs, 0));
1676 bNodeSocket *sub1_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&sub1_node->inputs, 1));
1677 bNodeSocket *sub1_socket_out = blender::bke::node_find_socket(sub1_node, SOCK_OUT, "Value");
1678
1679 *version_cycles_node_socket_float_value(min_socket_B) = 14.0f;
1680 *version_cycles_node_socket_float_value(sub1_socket_B) = 1.0f;
1681
1682 blender::bke::node_remove_link(ntree, detail_link);
1684 ntree, detail_from_node, detail_from_socket, sub1_node, sub1_socket_A);
1685 blender::bke::node_add_link(ntree, sub1_node, sub1_socket_out, min_node, min_socket_A);
1686 blender::bke::node_add_link(ntree, min_node, min_socket_out, node, detail_socket);
1687
1689 locy_offset -= 40.0f;
1690
1691 /* Add Greater Than Math node before Subtract Math node. */
1692
1693 bNode *greater_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1694 greater_node->parent = node->parent;
1695 greater_node->custom1 = NODE_MATH_GREATER_THAN;
1696 greater_node->locx = node->locx;
1697 greater_node->locy = node->locy - 400.0f;
1698 greater_node->flag |= NODE_HIDDEN;
1699 bNodeSocket *greater_socket_A = static_cast<bNodeSocket *>(
1700 BLI_findlink(&greater_node->inputs, 0));
1701 bNodeSocket *greater_socket_B = static_cast<bNodeSocket *>(
1702 BLI_findlink(&greater_node->inputs, 1));
1703 bNodeSocket *greater_socket_out = blender::bke::node_find_socket(
1704 greater_node, SOCK_OUT, "Value");
1705
1706 *version_cycles_node_socket_float_value(greater_socket_B) = 1.0f;
1707
1709 ntree, detail_from_node, detail_from_socket, greater_node, greater_socket_A);
1711 ntree, greater_node, greater_socket_out, sub1_node, sub1_socket_B);
1712 }
1713 else {
1714 /* Add Clamp node and Multiply Math node behind Fac output. */
1715
1716 bNode *clamp_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_CLAMP);
1717 clamp_node->parent = node->parent;
1718 clamp_node->custom1 = NODE_CLAMP_MINMAX;
1719 clamp_node->locx = node->locx;
1720 clamp_node->locy = node->locy + 40.0f;
1721 clamp_node->flag |= NODE_HIDDEN;
1722 bNodeSocket *clamp_socket_value = blender::bke::node_find_socket(
1723 clamp_node, SOCK_IN, "Value");
1724 bNodeSocket *clamp_socket_min = blender::bke::node_find_socket(clamp_node, SOCK_IN, "Min");
1725 bNodeSocket *clamp_socket_max = blender::bke::node_find_socket(clamp_node, SOCK_IN, "Max");
1726 bNodeSocket *clamp_socket_out = blender::bke::node_find_socket(
1727 clamp_node, SOCK_OUT, "Result");
1728
1729 bNode *mul_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1730 mul_node->parent = node->parent;
1731 mul_node->custom1 = NODE_MATH_MULTIPLY;
1732 mul_node->locx = node->locx;
1733 mul_node->locy = node->locy + 80.0f;
1734 mul_node->flag |= NODE_HIDDEN;
1735 bNodeSocket *mul_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 0));
1736 bNodeSocket *mul_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 1));
1737 bNodeSocket *mul_socket_out = blender::bke::node_find_socket(mul_node, SOCK_OUT, "Value");
1738
1739 *version_cycles_node_socket_float_value(clamp_socket_min) = 0.0f;
1740 *version_cycles_node_socket_float_value(clamp_socket_max) = 1.0f;
1741
1742 if (noise_type == SHD_NOISE_MULTIFRACTAL) {
1743 /* Add Subtract Math node and Add Math node after Multiply Math node. */
1744
1745 bNode *sub2_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1746 sub2_node->parent = node->parent;
1747 sub2_node->custom1 = NODE_MATH_SUBTRACT;
1748 sub2_node->custom2 = SHD_MATH_CLAMP;
1749 sub2_node->locx = node->locx;
1750 sub2_node->locy = node->locy + 120.0f;
1751 sub2_node->flag |= NODE_HIDDEN;
1752 bNodeSocket *sub2_socket_A = static_cast<bNodeSocket *>(
1753 BLI_findlink(&sub2_node->inputs, 0));
1754 bNodeSocket *sub2_socket_B = static_cast<bNodeSocket *>(
1755 BLI_findlink(&sub2_node->inputs, 1));
1757 sub2_node, SOCK_OUT, "Value");
1758
1760 add_node->parent = node->parent;
1761 add_node->custom1 = NODE_MATH_ADD;
1762 add_node->locx = node->locx;
1763 add_node->locy = node->locy + 160.0f;
1764 add_node->flag |= NODE_HIDDEN;
1765 bNodeSocket *add_socket_A = static_cast<bNodeSocket *>(
1766 BLI_findlink(&add_node->inputs, 0));
1767 bNodeSocket *add_socket_B = static_cast<bNodeSocket *>(
1768 BLI_findlink(&add_node->inputs, 1));
1770 add_node, SOCK_OUT, "Value");
1771
1772 *version_cycles_node_socket_float_value(sub2_socket_A) = 1.0f;
1773
1775 if (link->fromsock == fac_socket) {
1777 ntree, add_node, add_socket_out, link->tonode, link->tosock);
1778 blender::bke::node_remove_link(ntree, link);
1779 }
1780 }
1781
1782 blender::bke::node_add_link(ntree, mul_node, mul_socket_out, add_node, add_socket_A);
1784 ntree, detail_from_node, detail_from_socket, sub2_node, sub2_socket_B);
1785 blender::bke::node_add_link(ntree, sub2_node, sub2_socket_out, add_node, add_socket_B);
1786 }
1787 else {
1789 if (link->fromsock == fac_socket) {
1791 ntree, mul_node, mul_socket_out, link->tonode, link->tosock);
1792 blender::bke::node_remove_link(ntree, link);
1793 }
1794 }
1795 }
1796
1797 blender::bke::node_add_link(ntree, node, fac_socket, mul_node, mul_socket_A);
1799 ntree, detail_from_node, detail_from_socket, clamp_node, clamp_socket_value);
1800 blender::bke::node_add_link(ntree, clamp_node, clamp_socket_out, mul_node, mul_socket_B);
1801 }
1802 }
1803 else {
1804 if (*detail < 1.0f) {
1806 /* Add Multiply Math node behind Fac output. */
1807
1808 bNode *mul_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1809 mul_node->parent = node->parent;
1810 mul_node->custom1 = NODE_MATH_MULTIPLY;
1811 mul_node->locx = node->locx;
1812 mul_node->locy = node->locy + 40.0f;
1813 mul_node->flag |= NODE_HIDDEN;
1814 bNodeSocket *mul_socket_A = static_cast<bNodeSocket *>(
1815 BLI_findlink(&mul_node->inputs, 0));
1816 bNodeSocket *mul_socket_B = static_cast<bNodeSocket *>(
1817 BLI_findlink(&mul_node->inputs, 1));
1819 mul_node, SOCK_OUT, "Value");
1820
1822
1823 if (noise_type == SHD_NOISE_MULTIFRACTAL) {
1824 /* Add an Add Math node after Multiply Math node. */
1825
1827 add_node->parent = node->parent;
1828 add_node->custom1 = NODE_MATH_ADD;
1829 add_node->locx = node->locx;
1830 add_node->locy = node->locy + 80.0f;
1831 add_node->flag |= NODE_HIDDEN;
1832 bNodeSocket *add_socket_A = static_cast<bNodeSocket *>(
1833 BLI_findlink(&add_node->inputs, 0));
1834 bNodeSocket *add_socket_B = static_cast<bNodeSocket *>(
1835 BLI_findlink(&add_node->inputs, 1));
1837 add_node, SOCK_OUT, "Value");
1838
1839 *version_cycles_node_socket_float_value(add_socket_B) = 1.0f - *detail;
1840
1842 if (link->fromsock == fac_socket) {
1844 ntree, add_node, add_socket_out, link->tonode, link->tosock);
1845 blender::bke::node_remove_link(ntree, link);
1846 }
1847 }
1848
1849 blender::bke::node_add_link(ntree, mul_node, mul_socket_out, add_node, add_socket_A);
1850 }
1851 else {
1853 if (link->fromsock == fac_socket) {
1855 ntree, mul_node, mul_socket_out, link->tonode, link->tosock);
1856 blender::bke::node_remove_link(ntree, link);
1857 }
1858 }
1859 }
1860
1861 blender::bke::node_add_link(ntree, node, fac_socket, mul_node, mul_socket_A);
1862
1863 *detail = 0.0f;
1864 }
1865 }
1866 else {
1867 *detail = std::fminf(*detail - 1.0f, 14.0f);
1868 }
1869 }
1870
1871 bNodeSocket *roughness_socket = blender::bke::node_find_socket(node, SOCK_IN, "Roughness");
1872 float *roughness = version_cycles_node_socket_float_value(roughness_socket);
1873 bNodeSocket *lacunarity_socket = blender::bke::node_find_socket(node, SOCK_IN, "Lacunarity");
1874 float *lacunarity = version_cycles_node_socket_float_value(lacunarity_socket);
1875
1876 *roughness = std::fmaxf(*roughness, 1e-5f);
1877 *lacunarity = std::fmaxf(*lacunarity, 1e-5f);
1878
1879 if (roughness_link != nullptr) {
1880 /* Add Maximum Math node after output of roughness_from_node. Add Multiply Math node and
1881 * Power Math node before Roughness input. */
1882
1883 bNode *max1_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1884 max1_node->parent = node->parent;
1885 max1_node->custom1 = NODE_MATH_MAXIMUM;
1886 max1_node->locx = node->locx;
1887 max1_node->locy = node->locy - 400.0f + locy_offset;
1888 max1_node->flag |= NODE_HIDDEN;
1889 bNodeSocket *max1_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&max1_node->inputs, 0));
1890 bNodeSocket *max1_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&max1_node->inputs, 1));
1891 bNodeSocket *max1_socket_out = blender::bke::node_find_socket(max1_node, SOCK_OUT, "Value");
1892
1893 bNode *mul_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1894 mul_node->parent = node->parent;
1895 mul_node->custom1 = NODE_MATH_MULTIPLY;
1896 mul_node->locx = node->locx;
1897 mul_node->locy = node->locy - 360.0f + locy_offset;
1898 mul_node->flag |= NODE_HIDDEN;
1899 bNodeSocket *mul_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 0));
1900 bNodeSocket *mul_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 1));
1901 bNodeSocket *mul_socket_out = blender::bke::node_find_socket(mul_node, SOCK_OUT, "Value");
1902
1903 bNode *pow_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1904 pow_node->parent = node->parent;
1905 pow_node->custom1 = NODE_MATH_POWER;
1906 pow_node->locx = node->locx;
1907 pow_node->locy = node->locy - 320.0f + locy_offset;
1908 pow_node->flag |= NODE_HIDDEN;
1909 bNodeSocket *pow_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 0));
1910 bNodeSocket *pow_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 1));
1911 bNodeSocket *pow_socket_out = blender::bke::node_find_socket(pow_node, SOCK_OUT, "Value");
1912
1913 *version_cycles_node_socket_float_value(max1_socket_B) = -1e-5f;
1914 *version_cycles_node_socket_float_value(mul_socket_B) = -1.0f;
1915 *version_cycles_node_socket_float_value(pow_socket_A) = *lacunarity;
1916
1917 blender::bke::node_remove_link(ntree, roughness_link);
1919 ntree, roughness_from_node, roughness_from_socket, max1_node, max1_socket_A);
1920 blender::bke::node_add_link(ntree, max1_node, max1_socket_out, mul_node, mul_socket_A);
1921 blender::bke::node_add_link(ntree, mul_node, mul_socket_out, pow_node, pow_socket_B);
1922 blender::bke::node_add_link(ntree, pow_node, pow_socket_out, node, roughness_socket);
1923
1924 if (lacunarity_link != nullptr) {
1925 /* Add Maximum Math node after output of lacunarity_from_node. */
1926
1927 bNode *max2_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1928 max2_node->parent = node->parent;
1929 max2_node->custom1 = NODE_MATH_MAXIMUM;
1930 max2_node->locx = node->locx;
1931 max2_node->locy = node->locy - 440.0f + locy_offset;
1932 max2_node->flag |= NODE_HIDDEN;
1933 bNodeSocket *max2_socket_A = static_cast<bNodeSocket *>(
1934 BLI_findlink(&max2_node->inputs, 0));
1935 bNodeSocket *max2_socket_B = static_cast<bNodeSocket *>(
1936 BLI_findlink(&max2_node->inputs, 1));
1938 max2_node, SOCK_OUT, "Value");
1939
1940 *version_cycles_node_socket_float_value(max2_socket_B) = -1e-5f;
1941
1942 blender::bke::node_remove_link(ntree, lacunarity_link);
1944 ntree, lacunarity_from_node, lacunarity_from_socket, max2_node, max2_socket_A);
1945 blender::bke::node_add_link(ntree, max2_node, max2_socket_out, pow_node, pow_socket_A);
1946 blender::bke::node_add_link(ntree, max2_node, max2_socket_out, node, lacunarity_socket);
1947 }
1948 }
1949 else if ((lacunarity_link != nullptr) && (roughness_link == nullptr)) {
1950 /* Add Maximum Math node after output of lacunarity_from_node. Add Power Math node before
1951 * Roughness input. */
1952
1953 bNode *max2_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1954 max2_node->parent = node->parent;
1955 max2_node->custom1 = NODE_MATH_MAXIMUM;
1956 max2_node->locx = node->locx;
1957 max2_node->locy = node->locy - 360.0f + locy_offset;
1958 max2_node->flag |= NODE_HIDDEN;
1959 bNodeSocket *max2_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&max2_node->inputs, 0));
1960 bNodeSocket *max2_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&max2_node->inputs, 1));
1961 bNodeSocket *max2_socket_out = blender::bke::node_find_socket(max2_node, SOCK_OUT, "Value");
1962
1963 bNode *pow_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
1964 pow_node->parent = node->parent;
1965 pow_node->custom1 = NODE_MATH_POWER;
1966 pow_node->locx = node->locx;
1967 pow_node->locy = node->locy - 320.0f + locy_offset;
1968 pow_node->flag |= NODE_HIDDEN;
1969 bNodeSocket *pow_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 0));
1970 bNodeSocket *pow_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 1));
1971 bNodeSocket *pow_socket_out = blender::bke::node_find_socket(pow_node, SOCK_OUT, "Value");
1972
1973 *version_cycles_node_socket_float_value(max2_socket_B) = -1e-5f;
1974 *version_cycles_node_socket_float_value(pow_socket_A) = *lacunarity;
1975 *version_cycles_node_socket_float_value(pow_socket_B) = -(*roughness);
1976
1977 blender::bke::node_remove_link(ntree, lacunarity_link);
1979 ntree, lacunarity_from_node, lacunarity_from_socket, max2_node, max2_socket_A);
1980 blender::bke::node_add_link(ntree, max2_node, max2_socket_out, pow_node, pow_socket_A);
1981 blender::bke::node_add_link(ntree, max2_node, max2_socket_out, node, lacunarity_socket);
1982 blender::bke::node_add_link(ntree, pow_node, pow_socket_out, node, roughness_socket);
1983 }
1984 else {
1985 *roughness = std::pow(*lacunarity, -(*roughness));
1986 }
1987 }
1988
1990}
1991
1992/* Convert subsurface inputs on the Principled BSDF. */
1994{
1995 /* - Create Subsurface Scale input
1996 * - If a node's Subsurface input was connected or nonzero:
1997 * - Make the Base Color a mix of old Base Color and Subsurface Color,
1998 * using Subsurface as the mix factor
1999 * - Move Subsurface link and default value to the new Subsurface Scale input
2000 * - Set the Subsurface input to 1.0
2001 * - Remove Subsurface Color input
2002 */
2003 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
2004 if (node->type != SH_NODE_BSDF_PRINCIPLED) {
2005 continue;
2006 }
2007 if (blender::bke::node_find_socket(node, SOCK_IN, "Subsurface Scale")) {
2008 /* Node is already updated. */
2009 continue;
2010 }
2011
2012 /* Add Scale input */
2014 ntree, node, SOCK_IN, SOCK_FLOAT, PROP_DISTANCE, "Subsurface Scale", "Subsurface Scale");
2015
2016 bNodeSocket *subsurf = blender::bke::node_find_socket(node, SOCK_IN, "Subsurface");
2017 float *subsurf_val = version_cycles_node_socket_float_value(subsurf);
2018
2019 if (!subsurf->link && *subsurf_val == 0.0f) {
2020 *version_cycles_node_socket_float_value(scale_in) = 0.05f;
2021 }
2022 else {
2023 *version_cycles_node_socket_float_value(scale_in) = *subsurf_val;
2024 }
2025
2026 if (subsurf->link == nullptr && *subsurf_val == 0.0f) {
2027 /* Node doesn't use Subsurf, we're done here. */
2028 continue;
2029 }
2030
2031 /* Fix up Subsurface Color input */
2032 bNodeSocket *base_col = blender::bke::node_find_socket(node, SOCK_IN, "Base Color");
2033 bNodeSocket *subsurf_col = blender::bke::node_find_socket(node, SOCK_IN, "Subsurface Color");
2034 float *base_col_val = version_cycles_node_socket_rgba_value(base_col);
2035 float *subsurf_col_val = version_cycles_node_socket_rgba_value(subsurf_col);
2036 /* If any of the three inputs is dynamic, we need a Mix node. */
2037 if (subsurf->link || subsurf_col->link || base_col->link) {
2039 static_cast<NodeShaderMix *>(mix->storage)->data_type = SOCK_RGBA;
2040 mix->locx = node->locx - 170;
2041 mix->locy = node->locy - 120;
2042
2045 bNodeSocket *fac_in = blender::bke::node_find_socket(mix, SOCK_IN, "Factor_Float");
2046 bNodeSocket *result_out = blender::bke::node_find_socket(mix, SOCK_OUT, "Result_Color");
2047
2049 copy_v4_v4(version_cycles_node_socket_rgba_value(b_in), subsurf_col_val);
2050 *version_cycles_node_socket_float_value(fac_in) = *subsurf_val;
2051
2052 if (base_col->link) {
2054 ntree, base_col->link->fromnode, base_col->link->fromsock, mix, a_in);
2055 blender::bke::node_remove_link(ntree, base_col->link);
2056 }
2057 if (subsurf_col->link) {
2059 ntree, subsurf_col->link->fromnode, subsurf_col->link->fromsock, mix, b_in);
2060 blender::bke::node_remove_link(ntree, subsurf_col->link);
2061 }
2062 if (subsurf->link) {
2064 ntree, subsurf->link->fromnode, subsurf->link->fromsock, mix, fac_in);
2066 ntree, subsurf->link->fromnode, subsurf->link->fromsock, node, scale_in);
2067 blender::bke::node_remove_link(ntree, subsurf->link);
2068 }
2069 blender::bke::node_add_link(ntree, mix, result_out, node, base_col);
2070 }
2071 /* Mix the fixed values. */
2072 interp_v4_v4v4(base_col_val, base_col_val, subsurf_col_val, *subsurf_val);
2073
2074 /* Set node to 100% subsurface, 0% diffuse. */
2075 *subsurf_val = 1.0f;
2076
2077 /* Delete Subsurface Color input */
2078 blender::bke::node_remove_socket(ntree, node, subsurf_col);
2079 }
2080}
2081
2082/* Convert emission inputs on the Principled BSDF. */
2084{
2085 /* Blender 3.x and before would default to Emission = 0.0, Emission Strength = 1.0.
2086 * Now we default the other way around (1.0 and 0.0), but because the Strength input was added
2087 * a bit later, a file that only has the Emission socket would now end up as (1.0, 0.0) instead
2088 * of (1.0, 1.0).
2089 * Therefore, set strength to 1.0 for those files.
2090 */
2091 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
2092 if (node->type != SH_NODE_BSDF_PRINCIPLED) {
2093 continue;
2094 }
2095 if (!blender::bke::node_find_socket(node, SOCK_IN, "Emission")) {
2096 /* Old enough to have neither, new defaults are fine. */
2097 continue;
2098 }
2099 if (blender::bke::node_find_socket(node, SOCK_IN, "Emission Strength")) {
2100 /* New enough to have both, no need to do anything. */
2101 continue;
2102 }
2104 ntree, node, SOCK_IN, SOCK_FLOAT, PROP_NONE, "Emission Strength", "Emission Strength");
2106 }
2107}
2108
2109/* Rename various Principled BSDF sockets. */
2111{
2112 version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Emission", "Emission Color");
2113 version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Specular", "Specular IOR Level");
2115 ntree, SH_NODE_BSDF_PRINCIPLED, "Subsurface", "Subsurface Weight");
2117 ntree, SH_NODE_BSDF_PRINCIPLED, "Transmission", "Transmission Weight");
2118 version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Coat", "Coat Weight");
2119 version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Sheen", "Sheen Weight");
2120}
2121
2122/* Replace old Principled Hair BSDF as a variant in the new Principled Hair BSDF. */
2124{
2125 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
2126 if (node->type != SH_NODE_BSDF_HAIR_PRINCIPLED) {
2127 continue;
2128 }
2129 NodeShaderHairPrincipled *data = MEM_cnew<NodeShaderHairPrincipled>(__func__);
2131 data->parametrization = node->custom1;
2132
2133 node->storage = data;
2134 }
2135}
2136
2138 bNode &node,
2139 bNodeSocket &socket)
2140{
2141 if (socket.type == SOCK_ROTATION) {
2142 return;
2143 }
2144 socket.type = SOCK_ROTATION;
2145 STRNCPY(socket.idname, "NodeSocketRotation");
2146 auto *old_value = static_cast<bNodeSocketValueVector *>(socket.default_value);
2147 auto *new_value = MEM_cnew<bNodeSocketValueRotation>(__func__);
2148 copy_v3_v3(new_value->value_euler, old_value->value);
2149 socket.default_value = new_value;
2150 MEM_freeN(old_value);
2151 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
2152 if (link->tosock != &socket) {
2153 continue;
2154 }
2155 if (ELEM(link->fromsock->type, SOCK_ROTATION, SOCK_VECTOR, SOCK_FLOAT) &&
2156 link->fromnode->type != NODE_REROUTE)
2157 {
2158 /* No need to add the conversion node when implicit conversions will work. */
2159 continue;
2160 }
2161 if (STREQ(link->fromnode->idname, "FunctionNodeEulerToRotation")) {
2162 /* Make versioning idempotent. */
2163 continue;
2164 }
2165 bNode *convert = blender::bke::node_add_node(nullptr, &ntree, "FunctionNodeEulerToRotation");
2166 convert->parent = node.parent;
2167 convert->locx = node.locx - 40;
2168 convert->locy = node.locy;
2169 link->tonode = convert;
2170 link->tosock = blender::bke::node_find_socket(convert, SOCK_IN, "Euler");
2171
2173 convert,
2174 blender::bke::node_find_socket(convert, SOCK_OUT, "Rotation"),
2175 &node,
2176 &socket);
2177 }
2178}
2179
2181 bNode &node,
2182 bNodeSocket &socket)
2183{
2184 /* Rely on generic node declaration update to change the socket type. */
2185 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
2186 if (link->fromsock != &socket) {
2187 continue;
2188 }
2189 if (ELEM(link->tosock->type, SOCK_ROTATION, SOCK_VECTOR) && link->tonode->type != NODE_REROUTE)
2190 {
2191 /* No need to add the conversion node when implicit conversions will work. */
2192 continue;
2193 }
2194 if (STREQ(link->tonode->idname, "FunctionNodeRotationToEuler"))
2195 { /* Make versioning idempotent. */
2196 continue;
2197 }
2198 bNode *convert = blender::bke::node_add_node(nullptr, &ntree, "FunctionNodeRotationToEuler");
2199 convert->parent = node.parent;
2200 convert->locx = node.locx + 40;
2201 convert->locy = node.locy;
2202 link->fromnode = convert;
2203 link->fromsock = blender::bke::node_find_socket(convert, SOCK_OUT, "Euler");
2204
2206 &node,
2207 &socket,
2208 convert,
2209 blender::bke::node_find_socket(convert, SOCK_IN, "Rotation"));
2210 }
2211}
2212
2214{
2215 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree.nodes) {
2216 if (STR_ELEM(node->idname,
2217 "GeometryNodeInstanceOnPoints",
2218 "GeometryNodeRotateInstances",
2219 "GeometryNodeTransform"))
2220 {
2221 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_IN, "Rotation");
2222 change_input_socket_to_rotation_type(ntree, *node, *socket);
2223 }
2224 if (STR_ELEM(node->idname,
2225 "GeometryNodeDistributePointsOnFaces",
2226 "GeometryNodeObjectInfo",
2227 "GeometryNodeInputInstanceRotation"))
2228 {
2229 bNodeSocket *socket = blender::bke::node_find_socket(node, SOCK_OUT, "Rotation");
2230 change_output_socket_to_rotation_type(ntree, *node, *socket);
2231 }
2232 }
2233}
2234
2235/* Find the base socket name for an idname that may include a subtype. */
2237{
2238 using string_pair = std::pair<const char *, const char *>;
2239 static const string_pair subtypes_map[] = {{"NodeSocketFloatUnsigned", "NodeSocketFloat"},
2240 {"NodeSocketFloatPercentage", "NodeSocketFloat"},
2241 {"NodeSocketFloatFactor", "NodeSocketFloat"},
2242 {"NodeSocketFloatAngle", "NodeSocketFloat"},
2243 {"NodeSocketFloatTime", "NodeSocketFloat"},
2244 {"NodeSocketFloatTimeAbsolute", "NodeSocketFloat"},
2245 {"NodeSocketFloatDistance", "NodeSocketFloat"},
2246 {"NodeSocketIntUnsigned", "NodeSocketInt"},
2247 {"NodeSocketIntPercentage", "NodeSocketInt"},
2248 {"NodeSocketIntFactor", "NodeSocketInt"},
2249 {"NodeSocketVectorTranslation", "NodeSocketVector"},
2250 {"NodeSocketVectorDirection", "NodeSocketVector"},
2251 {"NodeSocketVectorVelocity", "NodeSocketVector"},
2252 {"NodeSocketVectorAcceleration", "NodeSocketVector"},
2253 {"NodeSocketVectorEuler", "NodeSocketVector"},
2254 {"NodeSocketVectorXYZ", "NodeSocketVector"}};
2255 for (const string_pair &pair : subtypes_map) {
2256 if (pair.first == idname) {
2257 return pair.second;
2258 }
2259 }
2260 /* Unchanged socket idname. */
2261 return idname;
2262}
2263
2265 const eNodeSocketInOut in_out)
2266{
2267 bNodeTreeInterfaceSocket *new_socket = MEM_cnew<bNodeTreeInterfaceSocket>(__func__);
2268 new_socket->item.item_type = NODE_INTERFACE_SOCKET;
2269
2270 /* Move reusable data. */
2271 new_socket->name = BLI_strdup(legacy_socket.name);
2272 new_socket->identifier = BLI_strdup(legacy_socket.identifier);
2273 new_socket->description = BLI_strdup(legacy_socket.description);
2274 /* If the socket idname includes a subtype (e.g. "NodeSocketFloatFactor") this will convert it to
2275 * the base type name ("NodeSocketFloat"). */
2276 new_socket->socket_type = BLI_strdup(
2278 new_socket->flag = (in_out == SOCK_IN ? NODE_INTERFACE_SOCKET_INPUT :
2281 new_socket->flag, legacy_socket.flag & SOCK_HIDE_VALUE, NODE_INTERFACE_SOCKET_HIDE_VALUE);
2282 SET_FLAG_FROM_TEST(new_socket->flag,
2283 legacy_socket.flag & SOCK_HIDE_IN_MODIFIER,
2285 new_socket->attribute_domain = legacy_socket.attribute_domain;
2286
2287 /* The following data are stolen from the old data, the ownership of their memory is directly
2288 * transferred to the new data. */
2289 new_socket->default_attribute_name = legacy_socket.default_attribute_name;
2290 legacy_socket.default_attribute_name = nullptr;
2291 new_socket->socket_data = legacy_socket.default_value;
2292 legacy_socket.default_value = nullptr;
2293 new_socket->properties = legacy_socket.prop;
2294 legacy_socket.prop = nullptr;
2295
2296 /* Unused data. */
2297 MEM_delete(legacy_socket.runtime);
2298 legacy_socket.runtime = nullptr;
2299
2300 return &new_socket->item;
2301}
2302
2304{
2305 bNodeTreeInterface &tree_interface = ntree->tree_interface;
2306
2307 const int num_inputs = BLI_listbase_count(&ntree->inputs_legacy);
2308 const int num_outputs = BLI_listbase_count(&ntree->outputs_legacy);
2309 tree_interface.root_panel.items_num = num_inputs + num_outputs;
2310 tree_interface.root_panel.items_array = static_cast<bNodeTreeInterfaceItem **>(MEM_malloc_arrayN(
2311 tree_interface.root_panel.items_num, sizeof(bNodeTreeInterfaceItem *), __func__));
2312
2313 /* Convert outputs first to retain old outputs/inputs ordering. */
2314 int index;
2315 LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &ntree->outputs_legacy, index) {
2316 tree_interface.root_panel.items_array[index] = legacy_socket_move_to_interface(*socket,
2317 SOCK_OUT);
2318 }
2319 LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &ntree->inputs_legacy, index) {
2320 tree_interface.root_panel.items_array[num_outputs + index] = legacy_socket_move_to_interface(
2321 *socket, SOCK_IN);
2322 }
2323}
2324
2330{
2331 bNodeTreeInterface &tree_interface = ntree->tree_interface;
2332
2333 tree_interface.foreach_item([](bNodeTreeInterfaceItem &item) -> bool {
2334 if (item.item_type == NODE_INTERFACE_SOCKET) {
2335 bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
2337 socket.socket_type);
2338 if (socket.socket_type != corrected_socket_type) {
2339 MEM_freeN(socket.socket_type);
2340 socket.socket_type = BLI_strdup(corrected_socket_type.data());
2341 }
2342 }
2343 return true;
2344 });
2345}
2346
2347/* Convert coat inputs on the Principled BSDF. */
2349{
2350 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
2351 if (node->type != SH_NODE_BSDF_PRINCIPLED) {
2352 continue;
2353 }
2354 if (blender::bke::node_find_socket(node, SOCK_IN, "Coat IOR") != nullptr) {
2355 continue;
2356 }
2358 ntree, node, SOCK_IN, SOCK_FLOAT, PROP_NONE, "Coat IOR", "Coat IOR");
2359
2360 /* Adjust for 4x change in intensity. */
2361 bNodeSocket *coat_input = blender::bke::node_find_socket(node, SOCK_IN, "Clearcoat");
2362 *version_cycles_node_socket_float_value(coat_input) *= 0.25f;
2363 /* When the coat input is dynamic, instead of inserting a *0.25 math node, set the Coat IOR
2364 * to 1.2 instead - this also roughly quarters reflectivity compared to the 1.5 default. */
2365 *version_cycles_node_socket_float_value(coat_ior_input) = (coat_input->link) ? 1.2f : 1.5f;
2366 }
2367
2368 /* Rename sockets. */
2369 version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat", "Coat");
2371 ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat Roughness", "Coat Roughness");
2373 ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat Normal", "Coat Normal");
2374}
2375
2376/* Convert specular tint in Principled BSDF. */
2378{
2379 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
2380 if (node->type != SH_NODE_BSDF_PRINCIPLED) {
2381 continue;
2382 }
2383 bNodeSocket *specular_tint_sock = blender::bke::node_find_socket(
2384 node, SOCK_IN, "Specular Tint");
2385 if (specular_tint_sock->type == SOCK_RGBA) {
2386 /* Node is already updated. */
2387 continue;
2388 }
2389
2390 bNodeSocket *base_color_sock = blender::bke::node_find_socket(node, SOCK_IN, "Base Color");
2391 bNodeSocket *metallic_sock = blender::bke::node_find_socket(node, SOCK_IN, "Metallic");
2392 float specular_tint_old = *version_cycles_node_socket_float_value(specular_tint_sock);
2393 float *base_color = version_cycles_node_socket_rgba_value(base_color_sock);
2394 float metallic = *version_cycles_node_socket_float_value(metallic_sock);
2395
2396 /* Change socket type to Color. */
2397 blender::bke::node_modify_socket_type_static(ntree, node, specular_tint_sock, SOCK_RGBA, 0);
2398 float *specular_tint = version_cycles_node_socket_rgba_value(specular_tint_sock);
2399
2400 /* The conversion logic here is that the new Specular Tint should be
2401 * mix(one, mix(base_color, one, metallic), old_specular_tint).
2402 * This needs to be handled both for the fixed values, as well as for any potential connected
2403 * inputs. */
2404
2405 static float one[] = {1.0f, 1.0f, 1.0f, 1.0f};
2406
2407 /* Mix the fixed values. */
2408 float metallic_mix[4];
2409 interp_v4_v4v4(metallic_mix, base_color, one, metallic);
2410 interp_v4_v4v4(specular_tint, one, metallic_mix, specular_tint_old);
2411
2412 if (specular_tint_sock->link == nullptr && specular_tint_old <= 0.0f) {
2413 /* Specular Tint was fixed at zero, we don't need any conversion node setup. */
2414 continue;
2415 }
2416
2417 /* If the Metallic input is dynamic, or fixed > 0 and base color is dynamic,
2418 * we need to insert a node to compute the metallic_mix.
2419 * Otherwise, use whatever is connected to the base color, or the static value
2420 * if it's unconnected. */
2421 bNodeSocket *metallic_mix_out = nullptr;
2422 bNode *metallic_mix_node = nullptr;
2423 if (metallic_sock->link || (base_color_sock->link && metallic > 0.0f)) {
2424 /* Metallic Mix needs to be dynamically mixed. */
2426 static_cast<NodeShaderMix *>(mix->storage)->data_type = SOCK_RGBA;
2427 mix->locx = node->locx - 270;
2428 mix->locy = node->locy - 120;
2429
2432 bNodeSocket *fac_in = blender::bke::node_find_socket(mix, SOCK_IN, "Factor_Float");
2433 metallic_mix_out = blender::bke::node_find_socket(mix, SOCK_OUT, "Result_Color");
2434 metallic_mix_node = mix;
2435
2437 if (base_color_sock->link) {
2439 ntree, base_color_sock->link->fromnode, base_color_sock->link->fromsock, mix, a_in);
2440 }
2443 if (metallic_sock->link) {
2445 ntree, metallic_sock->link->fromnode, metallic_sock->link->fromsock, mix, fac_in);
2446 }
2447 }
2448 else if (base_color_sock->link) {
2449 /* Metallic Mix is a no-op and equivalent to Base Color. */
2450 metallic_mix_out = base_color_sock->link->fromsock;
2451 metallic_mix_node = base_color_sock->link->fromnode;
2452 }
2453
2454 /* Similar to above, if the Specular Tint input is dynamic, or fixed > 0 and metallic mix
2455 * is dynamic, we need to insert a node to compute the new specular tint. */
2456 if (specular_tint_sock->link || (metallic_mix_out && specular_tint_old > 0.0f)) {
2458 static_cast<NodeShaderMix *>(mix->storage)->data_type = SOCK_RGBA;
2459 mix->locx = node->locx - 170;
2460 mix->locy = node->locy - 120;
2461
2464 bNodeSocket *fac_in = blender::bke::node_find_socket(mix, SOCK_IN, "Factor_Float");
2465 bNodeSocket *result_out = blender::bke::node_find_socket(mix, SOCK_OUT, "Result_Color");
2466
2469 if (metallic_mix_out) {
2470 blender::bke::node_add_link(ntree, metallic_mix_node, metallic_mix_out, mix, b_in);
2471 }
2472 *version_cycles_node_socket_float_value(fac_in) = specular_tint_old;
2473 if (specular_tint_sock->link) {
2475 specular_tint_sock->link->fromnode,
2476 specular_tint_sock->link->fromsock,
2477 mix,
2478 fac_in);
2479 blender::bke::node_remove_link(ntree, specular_tint_sock->link);
2480 }
2481 blender::bke::node_add_link(ntree, mix, result_out, node, specular_tint_sock);
2482 }
2483 }
2484}
2485
2487 const bNodeTreeInterfaceSocket &src,
2488 char *identifier)
2489{
2490 /* Node socket copy function based on bNodeTreeInterface::item_copy to avoid using blenkernel. */
2491 dst.name = BLI_strdup_null(src.name);
2495 dst.identifier = identifier;
2496 if (src.properties) {
2498 }
2499 if (src.socket_data != nullptr) {
2501 /* No user count increment needed, gets reset after versioning. */
2502 }
2503}
2504
2506 const bNodeTreeInterfaceItem &item,
2507 const int initial_pos)
2508{
2509 const bool sockets_above_panels = !(panel.flag &
2512
2513 int pos = initial_pos;
2514
2515 if (sockets_above_panels) {
2516 if (item.item_type == NODE_INTERFACE_PANEL) {
2517 /* Find the closest valid position from the end, only panels at or after #position. */
2518 for (int test_pos = items.size() - 1; test_pos >= initial_pos; test_pos--) {
2519 if (test_pos < 0) {
2520 /* Initial position is out of range but valid. */
2521 break;
2522 }
2523 if (items[test_pos]->item_type != NODE_INTERFACE_PANEL) {
2524 /* Found valid position, insert after the last socket item. */
2525 pos = test_pos + 1;
2526 break;
2527 }
2528 }
2529 }
2530 else {
2531 /* Find the closest valid position from the start, no panels at or after #position. */
2532 for (int test_pos = 0; test_pos <= initial_pos; test_pos++) {
2533 if (test_pos >= items.size()) {
2534 /* Initial position is out of range but valid. */
2535 break;
2536 }
2537 if (items[test_pos]->item_type == NODE_INTERFACE_PANEL) {
2538 /* Found valid position, inserting moves the first panel. */
2539 pos = test_pos;
2540 break;
2541 }
2542 }
2543 }
2544 }
2545
2546 return pos;
2547}
2548
2551 int position)
2552{
2553 /* Apply any constraints on the item positions. */
2554 position = version_nodes_find_valid_insert_position_for_item(parent, socket.item, position);
2555 position = std::min(std::max(position, 0), parent.items_num);
2556
2558 parent.items_num};
2559 parent.items_num++;
2560 parent.items_array = MEM_cnew_array<bNodeTreeInterfaceItem *>(parent.items_num, __func__);
2561 parent.items().take_front(position).copy_from(old_items.take_front(position));
2562 parent.items().drop_front(position + 1).copy_from(old_items.drop_front(position));
2563 parent.items()[position] = &socket.item;
2564
2565 if (old_items.data()) {
2566 MEM_freeN(old_items.data());
2567 }
2568}
2569
2570/* Node group interface copy function based on bNodeTreeInterface::insert_item_copy. */
2574 int position)
2575{
2576 if (parent == nullptr) {
2577 parent = &tree_interface.root_panel;
2578 }
2579
2580 bNodeTreeInterfaceSocket *csocket = static_cast<bNodeTreeInterfaceSocket *>(
2581 MEM_dupallocN(&socket));
2582 /* Generate a new unique identifier.
2583 * This might break existing links, but the identifiers were duplicate anyway. */
2584 char *dst_identifier = BLI_sprintfN("Socket_%d", tree_interface.next_uid++);
2585 version_copy_socket(*csocket, socket, dst_identifier);
2586
2587 version_nodes_insert_item(*parent, *csocket, position);
2588
2589 /* Original socket becomes output. */
2591 /* Copied socket becomes input. */
2593}
2594
2596{
2597 /* True if item a should be above item b. */
2598 auto item_compare = [](const bNodeTreeInterfaceItem *a,
2599 const bNodeTreeInterfaceItem *b) -> bool {
2600 if (a->item_type != b->item_type) {
2601 /* Keep sockets above panels. */
2602 return a->item_type == NODE_INTERFACE_SOCKET;
2603 }
2604 else {
2605 /* Keep outputs above inputs. */
2606 if (a->item_type == NODE_INTERFACE_SOCKET) {
2607 const bNodeTreeInterfaceSocket *sa = reinterpret_cast<const bNodeTreeInterfaceSocket *>(a);
2608 const bNodeTreeInterfaceSocket *sb = reinterpret_cast<const bNodeTreeInterfaceSocket *>(b);
2609 const bool is_output_a = sa->flag & NODE_INTERFACE_SOCKET_OUTPUT;
2610 const bool is_output_b = sb->flag & NODE_INTERFACE_SOCKET_OUTPUT;
2611 if (is_output_a != is_output_b) {
2612 return is_output_a;
2613 }
2614 }
2615 }
2616 return false;
2617 };
2618
2619 /* Sort panel content. */
2620 std::stable_sort(panel.items().begin(), panel.items().end(), item_compare);
2621
2622 /* Sort any child panels too. */
2623 for (bNodeTreeInterfaceItem *item : panel.items()) {
2624 if (item->item_type == NODE_INTERFACE_PANEL) {
2626 *reinterpret_cast<bNodeTreeInterfacePanel *>(item));
2627 }
2628 }
2629}
2630
2632{
2633 /* Any node group with a first socket geometry output can potentially be a modifier. Previously
2634 * this wasn't an explicit option, so better to enable too many groups rather than too few. */
2635 LISTBASE_FOREACH (bNodeTree *, group, &bmain.nodetrees) {
2636 if (group->type != NTREE_GEOMETRY) {
2637 continue;
2638 }
2639 group->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) {
2640 if (item.item_type != NODE_INTERFACE_SOCKET) {
2641 return true;
2642 }
2643 const auto &socket = reinterpret_cast<const bNodeTreeInterfaceSocket &>(item);
2644 if ((socket.flag & NODE_INTERFACE_SOCKET_OUTPUT) == 0) {
2645 return true;
2646 }
2647 if (!STREQ(socket.socket_type, "NodeSocketGeometry")) {
2648 return true;
2649 }
2650 if (!group->geometry_node_asset_traits) {
2651 group->geometry_node_asset_traits = MEM_cnew<GeometryNodeAssetTraits>(__func__);
2652 }
2653 group->geometry_node_asset_traits->flag |= GEO_NODE_ASSET_MODIFIER;
2654 return false;
2655 });
2656 }
2657}
2658
2660 ListBase sockets, const char *separator, const std::optional<int> total = std::nullopt)
2661{
2662 int index = 0;
2663 LISTBASE_FOREACH (bNodeSocket *, socket, &sockets) {
2664 if (socket->is_available()) {
2665 if (char *pos = strstr(socket->identifier, separator)) {
2666 /* End the identifier at the separator so that the old suffix is ignored. */
2667 *pos = '\0';
2668
2669 if (total.has_value()) {
2670 index++;
2671 if (index == *total) {
2672 return;
2673 }
2674 }
2675 }
2676 }
2677 else {
2678 /* Rename existing identifiers so that they don't conflict with the renamed one. Those will
2679 * be removed after versioning code. */
2680 BLI_strncat(socket->identifier, "_deprecated", sizeof(socket->identifier));
2681 }
2682 }
2683}
2684
2686{
2687 LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
2688 switch (node->type) {
2690 /* This node requires the extra `total` parameter, because the `Group Index` identifier
2691 * also has a space in the name, that should not be treated as separator. */
2694 break;
2701 case GEO_NODE_RAYCAST:
2706 case GEO_NODE_VIEWER:
2709 break;
2710 }
2711 }
2712}
2713
2715{
2716 LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
2717 if (!ELEM(node->type, GEO_NODE_SWITCH, GEO_NODE_SAMPLE_CURVE)) {
2718 continue;
2719 }
2722 }
2723}
2724
2726{
2727 using namespace blender;
2728 for (GreasePencilDrawingBase *base : grease_pencil->drawings()) {
2729 if (base->type != GP_DRAWING) {
2730 continue;
2731 }
2732 bke::greasepencil::Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
2733 const int layer_index = CustomData_get_named_layer_index(
2734 &drawing.geometry.curve_data, CD_PROP_FLOAT, "hardness");
2735 if (layer_index == -1) {
2736 continue;
2737 }
2738 float *data = static_cast<float *>(CustomData_get_layer_named_for_write(
2739 &drawing.geometry.curve_data, CD_PROP_FLOAT, "hardness", drawing.geometry.curve_num));
2740 for (const int i : IndexRange(drawing.geometry.curve_num)) {
2741 data[i] = 1.0f - data[i];
2742 }
2743 /* Rename the layer. */
2744 STRNCPY(drawing.geometry.curve_data.layers[layer_index].name, "softness");
2745 }
2746}
2747
2749{
2750 using namespace blender;
2751 for (GreasePencilDrawingBase *base : grease_pencil->drawings()) {
2752 if (base->type != GP_DRAWING) {
2753 continue;
2754 }
2755 bke::greasepencil::Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
2756 MutableSpan<float> radii = drawing.radii_for_write();
2757 threading::parallel_for(radii.index_range(), 8192, [&](const IndexRange range) {
2758 for (const int i : range) {
2759 radii[i] *= bke::greasepencil::LEGACY_RADIUS_CONVERSION_FACTOR;
2760 }
2761 });
2762 }
2763}
2764
2766{
2767 using namespace blender;
2768 MultiValueMap<bNodeSocket *, bNodeLink *> out_links_per_socket;
2769 LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
2770 if (link->fromnode->type == GEO_NODE_OBJECT_INFO) {
2771 out_links_per_socket.add(link->fromsock, link);
2772 }
2773 }
2774
2775 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree.nodes) {
2776 if (node->type != GEO_NODE_OBJECT_INFO) {
2777 continue;
2778 }
2779 bNodeSocket *scale = blender::bke::node_find_socket(node, SOCK_OUT, "Scale");
2780 const Span<bNodeLink *> links = out_links_per_socket.lookup(scale);
2781 if (links.is_empty()) {
2782 continue;
2783 }
2784 bNode *absolute_value = blender::bke::node_add_node(nullptr, &ntree, "ShaderNodeVectorMath");
2785 absolute_value->custom1 = NODE_VECTOR_MATH_ABSOLUTE;
2786 absolute_value->parent = node->parent;
2787 absolute_value->locx = node->locx + 100;
2788 absolute_value->locy = node->locy - 50;
2790 node,
2791 scale,
2792 absolute_value,
2793 static_cast<bNodeSocket *>(absolute_value->inputs.first));
2794 for (bNodeLink *link : links) {
2795 link->fromnode = absolute_value;
2796 link->fromsock = static_cast<bNodeSocket *>(absolute_value->outputs.first);
2797 }
2798 }
2799}
2800
2801static bool seq_filter_bilinear_to_auto(Sequence *seq, void * /*user_data*/)
2802{
2803 StripTransform *transform = seq->strip->transform;
2804 if (transform != nullptr && transform->filter == SEQ_TRANSFORM_FILTER_BILINEAR) {
2806 }
2807 return true;
2808}
2809
2811{
2812 /* Replace paint brushes with a reference to the default brush asset for that mode. */
2813 LISTBASE_FOREACH (Scene *, scene, &bmain.scenes) {
2814 BKE_paint_brushes_set_default_references(scene->toolsettings);
2815 }
2816
2817 /* Replace persistent tool references with the new single builtin brush tool. */
2818 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain.workspaces) {
2819 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
2820 if (STREQ(tref->idname, "builtin_brush.Draw")) {
2821 /* Explicitly check against the old brush name, as the old texture paint image mode brush
2822 * tool has a non-paint related mode. */
2823 STRNCPY(tref->idname, "builtin.brush");
2824 continue;
2825 }
2826 if (tref->space_type != SPACE_VIEW3D) {
2827 continue;
2828 }
2829 if (!ELEM(tref->mode,
2843 {
2844 continue;
2845 }
2846 STRNCPY(tref->idname, "builtin.brush");
2847 }
2848 }
2849}
2850
2852{
2855 }
2856}
2857
2858/* The Hue Correct curve now wraps around by specifying CUMA_USE_WRAPPING, which means it no longer
2859 * makes sense to have curve maps outside of the [0, 1] range, so enable clipping and reset the
2860 * clip and view ranges. */
2861static void hue_correct_set_wrapping(CurveMapping *curve_mapping)
2862{
2863 curve_mapping->flag |= CUMA_DO_CLIP;
2864 curve_mapping->flag |= CUMA_USE_WRAPPING;
2865
2866 curve_mapping->clipr.xmin = 0.0f;
2867 curve_mapping->clipr.xmax = 1.0f;
2868 curve_mapping->clipr.ymin = 0.0f;
2869 curve_mapping->clipr.ymax = 1.0f;
2870
2871 curve_mapping->curr.xmin = 0.0f;
2872 curve_mapping->curr.xmax = 1.0f;
2873 curve_mapping->curr.ymin = 0.0f;
2874 curve_mapping->curr.ymax = 1.0f;
2875}
2876
2877static bool seq_hue_correct_set_wrapping(Sequence *seq, void * /*user_data*/)
2878{
2879 LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) {
2880 if (smd->type == seqModifierType_HueCorrect) {
2882 CurveMapping *cumap = (CurveMapping *)&hcmd->curve_mapping;
2884 }
2885 }
2886 return true;
2887}
2888
2889static void versioning_update_timecode(short int *tc)
2890{
2891 /* 2 = IMB_TC_FREE_RUN, 4 = IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN. */
2892 if (ELEM(*tc, 2, 4)) {
2893 *tc = IMB_TC_RECORD_RUN;
2894 }
2895}
2896
2897static bool seq_proxies_timecode_update(Sequence *seq, void * /*user_data*/)
2898{
2899 if (seq->strip == nullptr || seq->strip->proxy == nullptr) {
2900 return true;
2901 }
2902 StripProxy *proxy = seq->strip->proxy;
2904 return true;
2905}
2906
2907static bool seq_text_data_update(Sequence *seq, void * /*user_data*/)
2908{
2909 if (seq->type != SEQ_TYPE_TEXT || seq->effectdata == nullptr) {
2910 return true;
2911 }
2912
2913 TextVars *data = static_cast<TextVars *>(seq->effectdata);
2914 if (data->shadow_angle == 0.0f) {
2915 data->shadow_angle = DEG2RADF(65.0f);
2916 data->shadow_offset = 0.04f;
2917 data->shadow_blur = 0.0f;
2918 }
2919 if (data->outline_width == 0.0f) {
2920 data->outline_color[3] = 0.7f;
2921 data->outline_width = 0.05f;
2922 }
2923 return true;
2924}
2925
2927{
2928 if (ntree->type == NTREE_COMPOSIT) {
2929 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
2930
2931 if (node->type == CMP_NODE_HUECORRECT) {
2932 CurveMapping *cumap = (CurveMapping *)node->storage;
2934 }
2935 }
2936 }
2937}
2938
2940{
2941 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
2942 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2943 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
2944 if (sl->spacetype != SPACE_IMAGE) {
2945 continue;
2946 }
2947
2948 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
2949
2950 if (ARegion *new_shelf_region = do_versions_add_region_if_not_found(
2951 regionbase, RGN_TYPE_ASSET_SHELF, __func__, RGN_TYPE_TOOL_HEADER))
2952 {
2953 new_shelf_region->regiondata = MEM_cnew<RegionAssetShelf>(__func__);
2954 new_shelf_region->alignment = RGN_ALIGN_BOTTOM;
2955 new_shelf_region->flag |= RGN_FLAG_HIDDEN;
2956 }
2957 if (ARegion *new_shelf_header = do_versions_add_region_if_not_found(
2958 regionbase, RGN_TYPE_ASSET_SHELF_HEADER, __func__, RGN_TYPE_ASSET_SHELF))
2959 {
2960 new_shelf_header->alignment = RGN_ALIGN_BOTTOM | RGN_ALIGN_HIDE_WITH_PREV;
2961 }
2962 }
2963 }
2964 }
2965}
2966
2968{
2969 for (bNode *node : tree.all_nodes()) {
2970 if (node->is_reroute()) {
2971 if (node->storage != nullptr) {
2972 continue;
2973 }
2974
2975 bNodeSocket &input = *static_cast<bNodeSocket *>(node->inputs.first);
2976 bNodeSocket &output = *static_cast<bNodeSocket *>(node->outputs.first);
2977
2978 /* Use uniform identifier for sockets. In old Blender versions (<=2021, up to af0b7925), the
2979 * identifiers were sometimes all lower case. Fixing those wrong socket identifiers is
2980 * important because otherwise they loose links now that the reroute node also uses node
2981 * declarations. */
2982 STRNCPY(input.identifier, "Input");
2983 STRNCPY(output.identifier, "Output");
2984
2985 NodeReroute *data = MEM_cnew<NodeReroute>(__func__);
2986 STRNCPY(data->type_idname, input.idname);
2987 node->storage = data;
2988 }
2989 }
2990}
2991
2997{
2998 LISTBASE_FOREACH (Curves *, curves, &bmain->hair_curves) {
2999 const int curves_num = curves->geometry.curve_num;
3000 if (int *resolutions = static_cast<int *>(CustomData_get_layer_named_for_write(
3001 &curves->geometry.curve_data, CD_PROP_INT32, "resolution", curves_num)))
3002 {
3003 for (int &resolution : blender::MutableSpan{resolutions, curves_num}) {
3004 resolution = std::max(resolution, 1);
3005 }
3006 }
3007 if (int8_t *nurb_orders = static_cast<int8_t *>(CustomData_get_layer_named_for_write(
3008 &curves->geometry.curve_data, CD_PROP_INT8, "nurbs_order", curves_num)))
3009 {
3010 for (int8_t &nurbs_order : blender::MutableSpan{nurb_orders, curves_num}) {
3011 nurbs_order = std::max<int8_t>(nurbs_order, 1);
3012 }
3013 }
3014 }
3015}
3016
3018{
3019 LISTBASE_FOREACH (Object *, ob, &bmain.objects) {
3020 if (ob->type != OB_MESH) {
3021 continue;
3022 }
3023 LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
3024 if (md->type == eModifierType_Bevel) {
3025 BevelModifierData *bmd = reinterpret_cast<BevelModifierData *>(md);
3026 if (bmd->vertex_weight_name[0] == '\0') {
3027 STRNCPY(bmd->vertex_weight_name, "bevel_weight_vert");
3028 }
3029 if (bmd->edge_weight_name[0] == '\0') {
3030 STRNCPY(bmd->edge_weight_name, "bevel_weight_edge");
3031 }
3032 }
3033 }
3034 }
3035}
3036
3038{
3040 LISTBASE_FOREACH (bNode *, node, &tree->nodes) {
3041 if (node->type != GEO_NODE_SIMULATION_OUTPUT) {
3042 continue;
3043 }
3044 bNodeSocket *skip_input = static_cast<bNodeSocket *>(node->inputs.first);
3045 if (!skip_input || !STREQ(skip_input->identifier, "Skip")) {
3046 continue;
3047 }
3048 auto *default_value = static_cast<bNodeSocketValueBoolean *>(skip_input->default_value);
3049 if (!default_value->value) {
3050 continue;
3051 }
3052 bool is_linked = false;
3053 LISTBASE_FOREACH (bNodeLink *, link, &tree->links) {
3054 if (link->tosock == skip_input) {
3055 is_linked = true;
3056 }
3057 }
3058 if (is_linked) {
3059 continue;
3060 }
3061
3062 bNode &input_node = version_node_add_empty(*tree, "FunctionNodeInputBool");
3063 input_node.parent = node->parent;
3064 input_node.locx = node->locx - 25;
3065 input_node.locy = node->locy;
3066
3067 NodeInputBool *input_node_storage = MEM_cnew<NodeInputBool>(__func__);
3068 input_node.storage = input_node_storage;
3069 input_node_storage->boolean = true;
3070
3071 bNodeSocket &input_node_socket = version_node_add_socket(
3072 *tree, input_node, SOCK_OUT, "NodeSocketBool", "Boolean");
3073
3074 version_node_add_link(*tree, input_node, input_node_socket, *node, *skip_input);
3075
3076 /* Change the old socket value so that the versioning code is not run again. */
3077 default_value->value = false;
3078 }
3079 }
3080}
3081
3082void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
3083{
3084 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
3085 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
3087 }
3089 }
3090
3091 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 2)) {
3092 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
3094 }
3095 }
3096
3097 /* 400 4 did not require any do_version here. */
3098
3099 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 5)) {
3100 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3101 ToolSettings *ts = scene->toolsettings;
3102 if (ts->snap_mode_tools != SCE_SNAP_TO_NONE) {
3104 }
3105
3106#define SCE_SNAP_PROJECT (1 << 3)
3107 if (ts->snap_flag & SCE_SNAP_PROJECT) {
3108 ts->snap_mode &= ~(1 << 2); /* SCE_SNAP_TO_FACE */
3109 ts->snap_mode |= (1 << 8); /* SCE_SNAP_INDIVIDUAL_PROJECT */
3110 }
3111#undef SCE_SNAP_PROJECT
3112 }
3113 }
3114
3115 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 6)) {
3116 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3119 }
3121 }
3122
3123 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 7)) {
3125 }
3126
3127 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 8)) {
3128 LISTBASE_FOREACH (bAction *, act, &bmain->actions) {
3129 act->frame_start = max_ff(act->frame_start, MINAFRAMEF);
3130 act->frame_end = min_ff(act->frame_end, MAXFRAMEF);
3131 }
3132 }
3133
3134 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) {
3135 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
3136 if (light->type == LA_SPOT && light->nodetree) {
3138 }
3139 }
3140 }
3141
3142 /* Fix brush->tip_scale_x which should never be zero. */
3143 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
3144 if (brush->tip_scale_x == 0.0f) {
3145 brush->tip_scale_x = 1.0f;
3146 }
3147 }
3148
3149 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 10)) {
3150 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3151 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3152 LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
3153 if (space->spacetype == SPACE_NODE) {
3154 SpaceNode *snode = reinterpret_cast<SpaceNode *>(space);
3156 }
3157 }
3158 }
3159 }
3160 }
3161
3162 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 11)) {
3164 }
3165
3166 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 12)) {
3167 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "int", "grid_bake_samples")) {
3168 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
3169 lightprobe->grid_bake_samples = 2048;
3170 lightprobe->grid_normal_bias = 0.3f;
3171 lightprobe->grid_view_bias = 0.0f;
3172 lightprobe->grid_facing_bias = 0.5f;
3173 lightprobe->grid_dilation_threshold = 0.5f;
3174 lightprobe->grid_dilation_radius = 1.0f;
3175 }
3176 }
3177
3178 /* Set default bake resolution. */
3179 if (!DNA_struct_member_exists(fd->filesdna, "World", "int", "probe_resolution")) {
3180 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
3181 world->probe_resolution = LIGHT_PROBE_RESOLUTION_1024;
3182 }
3183 }
3184
3185 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "float", "grid_surface_bias")) {
3186 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
3187 lightprobe->grid_surface_bias = 0.05f;
3188 lightprobe->grid_escape_bias = 0.1f;
3189 }
3190 }
3191
3192 /* Clear removed "Z Buffer" flag. */
3193 {
3194 const int R_IMF_FLAG_ZBUF_LEGACY = 1 << 0;
3195 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3196 scene->r.im_format.flag &= ~R_IMF_FLAG_ZBUF_LEGACY;
3197 }
3198 }
3199
3200 /* Reset the layer opacity for all layers to 1. */
3201 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
3202 for (blender::bke::greasepencil::Layer *layer : grease_pencil->layers_for_write()) {
3203 layer->opacity = 1.0f;
3204 }
3205 }
3206
3207 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3208 if (ntree->type == NTREE_SHADER) {
3209 /* Remove Transmission Roughness from Principled BSDF. */
3211 /* Convert legacy Velvet BSDF nodes into the new Sheen BSDF node. */
3213 /* Convert sheen inputs on the Principled BSDF. */
3215 }
3216 }
3218
3219 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3220 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3221 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3222 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3223 &sl->regionbase;
3224
3225 /* Layout based regions used to also disallow resizing, now these are separate flags.
3226 * Make sure they are set together for old regions. */
3227 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3228 if (region->flag & RGN_FLAG_DYNAMIC_SIZE) {
3229 region->flag |= RGN_FLAG_NO_USER_RESIZE;
3230 }
3231 }
3232 }
3233 }
3234 }
3235 }
3236
3237 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 13)) {
3238 /* For the scenes configured to use the "None" display disable the color management
3239 * again. This will handle situation when the "None" display is removed and is replaced with
3240 * a "Raw" view instead.
3241 *
3242 * Note that this versioning will do nothing if the "None" display exists in the OCIO
3243 * configuration. */
3244 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3245 const ColorManagedDisplaySettings &display_settings = scene->display_settings;
3246 if (STREQ(display_settings.display_device, "None")) {
3248 }
3249 }
3250 }
3251
3252 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 14)) {
3253 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "ray_tracing_method")) {
3254 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3255 scene->eevee.ray_tracing_method = RAYTRACE_EEVEE_METHOD_SCREEN;
3256 }
3257 }
3258
3259 if (!DNA_struct_exists(fd->filesdna, "RegionAssetShelf")) {
3260 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3261 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3262 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3263 if (sl->spacetype != SPACE_VIEW3D) {
3264 continue;
3265 }
3266
3267 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3268 &sl->regionbase;
3269
3270 if (ARegion *new_shelf_region = do_versions_add_region_if_not_found(
3271 regionbase,
3273 "asset shelf for view3d (versioning)",
3275 {
3276 new_shelf_region->alignment = RGN_ALIGN_BOTTOM;
3277 }
3278 if (ARegion *new_shelf_header = do_versions_add_region_if_not_found(
3279 regionbase,
3281 "asset shelf header for view3d (versioning)",
3283 {
3284 new_shelf_header->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
3285 }
3286 }
3287 }
3288 }
3289 }
3290 }
3291
3292 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 16)) {
3293 /* Set Normalize property of Noise Texture node to true. */
3294 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3295 if (ntree->type != NTREE_CUSTOM) {
3296 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3297 if (node->type == SH_NODE_TEX_NOISE) {
3298 ((NodeTexNoise *)node->storage)->normalize = true;
3299 }
3300 }
3301 }
3302 }
3304 }
3305
3306 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 17)) {
3307 if (!DNA_struct_exists(fd->filesdna, "NodeShaderHairPrincipled")) {
3308 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3309 if (ntree->type == NTREE_SHADER) {
3311 }
3312 }
3314 }
3315
3316 /* Panorama properties shared with Eevee. */
3317 if (!DNA_struct_member_exists(fd->filesdna, "Camera", "float", "fisheye_fov")) {
3318 Camera default_cam = *DNA_struct_default_get(Camera);
3319 LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
3321 if (ccam) {
3322 camera->panorama_type = version_cycles_property_int(
3323 ccam, "panorama_type", default_cam.panorama_type);
3325 ccam, "fisheye_fov", default_cam.fisheye_fov);
3326 camera->fisheye_lens = version_cycles_property_float(
3327 ccam, "fisheye_lens", default_cam.fisheye_lens);
3328 camera->latitude_min = version_cycles_property_float(
3329 ccam, "latitude_min", default_cam.latitude_min);
3330 camera->latitude_max = version_cycles_property_float(
3331 ccam, "latitude_max", default_cam.latitude_max);
3332 camera->longitude_min = version_cycles_property_float(
3333 ccam, "longitude_min", default_cam.longitude_min);
3334 camera->longitude_max = version_cycles_property_float(
3335 ccam, "longitude_max", default_cam.longitude_max);
3336 /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */
3337 camera->fisheye_polynomial_k0 = version_cycles_property_float(
3338 ccam, "fisheye_polynomial_k0", default_cam.fisheye_polynomial_k0);
3339 camera->fisheye_polynomial_k1 = version_cycles_property_float(
3340 ccam, "fisheye_polynomial_k1", default_cam.fisheye_polynomial_k1);
3341 camera->fisheye_polynomial_k2 = version_cycles_property_float(
3342 ccam, "fisheye_polynomial_k2", default_cam.fisheye_polynomial_k2);
3343 camera->fisheye_polynomial_k3 = version_cycles_property_float(
3344 ccam, "fisheye_polynomial_k3", default_cam.fisheye_polynomial_k3);
3345 camera->fisheye_polynomial_k4 = version_cycles_property_float(
3346 ccam, "fisheye_polynomial_k4", default_cam.fisheye_polynomial_k4);
3347 }
3348 else {
3349 camera->panorama_type = default_cam.panorama_type;
3350 camera->fisheye_fov = default_cam.fisheye_fov;
3351 camera->fisheye_lens = default_cam.fisheye_lens;
3352 camera->latitude_min = default_cam.latitude_min;
3353 camera->latitude_max = default_cam.latitude_max;
3354 camera->longitude_min = default_cam.longitude_min;
3355 camera->longitude_max = default_cam.longitude_max;
3356 /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */
3357 camera->fisheye_polynomial_k0 = default_cam.fisheye_polynomial_k0;
3358 camera->fisheye_polynomial_k1 = default_cam.fisheye_polynomial_k1;
3359 camera->fisheye_polynomial_k2 = default_cam.fisheye_polynomial_k2;
3360 camera->fisheye_polynomial_k3 = default_cam.fisheye_polynomial_k3;
3361 camera->fisheye_polynomial_k4 = default_cam.fisheye_polynomial_k4;
3362 }
3363 }
3364 }
3365
3366 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "float", "grid_flag")) {
3367 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
3368 /* Keep old behavior of baking the whole lighting. */
3371 }
3372 }
3373
3374 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "gi_irradiance_pool_size")) {
3375 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3376 scene->eevee.gi_irradiance_pool_size = 16;
3377 }
3378 }
3379
3380 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3381 scene->toolsettings->snap_flag_anim |= SCE_SNAP;
3382 scene->toolsettings->snap_anim_mode |= (1 << 10); /* SCE_SNAP_TO_FRAME */
3383 }
3384 }
3385
3386 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 20)) {
3387 /* Convert old socket lists into new interface items. */
3388 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3390 /* Clear legacy sockets after conversion.
3391 * Internal data pointers have been moved or freed already. */
3392 BLI_freelistN(&ntree->inputs_legacy);
3393 BLI_freelistN(&ntree->outputs_legacy);
3394 }
3396 }
3397 else {
3398 /* Legacy node tree sockets are created for forward compatibility,
3399 * but have to be freed after loading and versioning. */
3400 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3401 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, legacy_socket, &ntree->inputs_legacy) {
3402 MEM_SAFE_FREE(legacy_socket->default_attribute_name);
3403 MEM_SAFE_FREE(legacy_socket->default_value);
3404 if (legacy_socket->prop) {
3405 IDP_FreeProperty(legacy_socket->prop);
3406 }
3407 MEM_delete(legacy_socket->runtime);
3408 MEM_freeN(legacy_socket);
3409 }
3410 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, legacy_socket, &ntree->outputs_legacy) {
3411 MEM_SAFE_FREE(legacy_socket->default_attribute_name);
3412 MEM_SAFE_FREE(legacy_socket->default_value);
3413 if (legacy_socket->prop) {
3414 IDP_FreeProperty(legacy_socket->prop);
3415 }
3416 MEM_delete(legacy_socket->runtime);
3417 MEM_freeN(legacy_socket);
3418 }
3419 BLI_listbase_clear(&ntree->inputs_legacy);
3420 BLI_listbase_clear(&ntree->outputs_legacy);
3421 }
3423 }
3424
3425 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 22)) {
3426 /* Initialize root panel flags in files created before these flags were added. */
3427 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3428 ntree->tree_interface.root_panel.flag |= NODE_INTERFACE_PANEL_ALLOW_CHILD_PANELS;
3429 }
3431 }
3432
3433 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 23)) {
3434 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3435 if (ntree->type == NTREE_GEOMETRY) {
3436 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3437 if (node->type == GEO_NODE_SET_SHADE_SMOOTH) {
3438 node->custom1 = int8_t(blender::bke::AttrDomain::Face);
3439 }
3440 }
3441 }
3442 }
3443 }
3444
3445 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 24)) {
3446 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3447 if (ntree->type == NTREE_SHADER) {
3448 /* Convert coat inputs on the Principled BSDF. */
3450 /* Convert subsurface inputs on the Principled BSDF. */
3452 /* Convert emission on the Principled BSDF. */
3454 }
3455 }
3457
3458 {
3459 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3460 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3461 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3462 const ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3463 &sl->regionbase;
3464 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3465 if (region->regiontype != RGN_TYPE_ASSET_SHELF) {
3466 continue;
3467 }
3468
3469 RegionAssetShelf *shelf_data = static_cast<RegionAssetShelf *>(region->regiondata);
3470 if (shelf_data && shelf_data->active_shelf &&
3471 (shelf_data->active_shelf->preferred_row_count == 0))
3472 {
3473 shelf_data->active_shelf->preferred_row_count = 1;
3474 }
3475 }
3476 }
3477 }
3478 }
3479 }
3480
3481 /* Convert sockets with both input and output flag into two separate sockets. */
3482 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3484 ntree->tree_interface.foreach_item([&](bNodeTreeInterfaceItem &item) {
3485 if (item.item_type == NODE_INTERFACE_SOCKET) {
3486 bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
3487 if ((socket.flag & NODE_INTERFACE_SOCKET_INPUT) &&
3489 {
3490 sockets_to_split.append(&socket);
3491 }
3492 }
3493 return true;
3494 });
3495
3496 for (bNodeTreeInterfaceSocket *socket : sockets_to_split) {
3497 const int position = ntree->tree_interface.find_item_position(socket->item);
3498 bNodeTreeInterfacePanel *parent = ntree->tree_interface.find_item_parent(socket->item);
3499 version_node_group_split_socket(ntree->tree_interface, *socket, parent, position + 1);
3500 }
3501 }
3503 }
3504
3505 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 25)) {
3506 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3507 if (ntree->type == NTREE_SHADER) {
3508 /* Convert specular tint on the Principled BSDF. */
3510 /* Rename some sockets. */
3512 }
3513 }
3515 }
3516
3517 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 26)) {
3519
3520 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3521 scene->simulation_frame_start = scene->r.sfra;
3522 scene->simulation_frame_end = scene->r.efra;
3523 }
3524 }
3525
3526 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 27)) {
3527 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3528 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3529 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3530 if (sl->spacetype == SPACE_SEQ) {
3531 SpaceSeq *sseq = (SpaceSeq *)sl;
3533 }
3534 }
3535 }
3536 }
3537
3538 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "shadow_step_count")) {
3539 SceneEEVEE default_scene_eevee = *DNA_struct_default_get(SceneEEVEE);
3540 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3541 scene->eevee.shadow_ray_count = default_scene_eevee.shadow_ray_count;
3542 scene->eevee.shadow_step_count = default_scene_eevee.shadow_step_count;
3543 }
3544 }
3545 }
3546
3547 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 28)) {
3548 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3549 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3550 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3551 const ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3552 &sl->regionbase;
3553 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3554 if (region->regiontype != RGN_TYPE_ASSET_SHELF) {
3555 continue;
3556 }
3557
3558 RegionAssetShelf *shelf_data = static_cast<RegionAssetShelf *>(region->regiondata);
3559 if (shelf_data && shelf_data->active_shelf) {
3560 AssetShelfSettings &settings = shelf_data->active_shelf->settings;
3563 }
3564
3565 region->flag |= RGN_FLAG_HIDDEN;
3566 }
3567 }
3568 }
3569 }
3570 }
3571
3572 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 29)) {
3573 /* Unhide all Reroute nodes. */
3574 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3575 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3576 if (node->is_reroute()) {
3577 static_cast<bNodeSocket *>(node->inputs.first)->flag &= ~SOCK_HIDDEN;
3578 static_cast<bNodeSocket *>(node->outputs.first)->flag &= ~SOCK_HIDDEN;
3579 }
3580 }
3581 }
3583 }
3584
3585 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 30)) {
3586 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3587 ToolSettings *ts = scene->toolsettings;
3588 enum { IS_DEFAULT = 0, IS_UV, IS_NODE, IS_ANIM };
3589 auto versioning_snap_to = [](short snap_to_old, int type) {
3590 eSnapMode snap_to_new = SCE_SNAP_TO_NONE;
3591 if (snap_to_old & (1 << 0)) {
3592 snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NODE_X :
3593 type == IS_ANIM ? SCE_SNAP_TO_FRAME :
3595 }
3596 if (snap_to_old & (1 << 1)) {
3597 snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NODE_Y :
3598 type == IS_ANIM ? SCE_SNAP_TO_SECOND :
3600 }
3601 if (ELEM(type, IS_DEFAULT, IS_ANIM) && snap_to_old & (1 << 2)) {
3602 snap_to_new |= type == IS_DEFAULT ? SCE_SNAP_TO_FACE : SCE_SNAP_TO_MARKERS;
3603 }
3604 if (type == IS_DEFAULT && snap_to_old & (1 << 3)) {
3605 snap_to_new |= SCE_SNAP_TO_VOLUME;
3606 }
3607 if (type == IS_DEFAULT && snap_to_old & (1 << 4)) {
3608 snap_to_new |= SCE_SNAP_TO_EDGE_MIDPOINT;
3609 }
3610 if (type == IS_DEFAULT && snap_to_old & (1 << 5)) {
3611 snap_to_new |= SCE_SNAP_TO_EDGE_PERPENDICULAR;
3612 }
3613 if (ELEM(type, IS_DEFAULT, IS_UV, IS_NODE) && snap_to_old & (1 << 6)) {
3614 snap_to_new |= SCE_SNAP_TO_INCREMENT;
3615 }
3616 if (ELEM(type, IS_DEFAULT, IS_UV, IS_NODE) && snap_to_old & (1 << 7)) {
3617 snap_to_new |= SCE_SNAP_TO_GRID;
3618 }
3619 if (type == IS_DEFAULT && snap_to_old & (1 << 8)) {
3620 snap_to_new |= SCE_SNAP_INDIVIDUAL_NEAREST;
3621 }
3622 if (type == IS_DEFAULT && snap_to_old & (1 << 9)) {
3623 snap_to_new |= SCE_SNAP_INDIVIDUAL_PROJECT;
3624 }
3625 if (snap_to_old & (1 << 10)) {
3626 snap_to_new |= SCE_SNAP_TO_FRAME;
3627 }
3628 if (snap_to_old & (1 << 11)) {
3629 snap_to_new |= SCE_SNAP_TO_SECOND;
3630 }
3631 if (snap_to_old & (1 << 12)) {
3632 snap_to_new |= SCE_SNAP_TO_MARKERS;
3633 }
3634
3635 if (!snap_to_new) {
3636 snap_to_new = eSnapMode(1 << 0);
3637 }
3638
3639 return snap_to_new;
3640 };
3641
3642 ts->snap_mode = versioning_snap_to(ts->snap_mode, IS_DEFAULT);
3643 ts->snap_uv_mode = versioning_snap_to(ts->snap_uv_mode, IS_UV);
3644 ts->snap_node_mode = versioning_snap_to(ts->snap_node_mode, IS_NODE);
3645 ts->snap_anim_mode = versioning_snap_to(ts->snap_anim_mode, IS_ANIM);
3646 }
3647 }
3648
3649 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 31)) {
3650 LISTBASE_FOREACH (Curve *, curve, &bmain->curves) {
3651 const int curvetype = BKE_curve_type_get(curve);
3652 if (curvetype == OB_FONT) {
3653 CharInfo *info = curve->strinfo;
3654 if (info != nullptr) {
3655 for (int i = curve->len_char32 - 1; i >= 0; i--, info++) {
3656 if (info->mat_nr > 0) {
3658 info->mat_nr--;
3659 }
3660 }
3661 }
3662 }
3663 }
3664 }
3665
3666 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 33)) {
3667 /* Fix node group socket order by sorting outputs and inputs. */
3668 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3669 versioning_node_group_sort_sockets_recursive(ntree->tree_interface.root_panel);
3670 }
3671 }
3672
3673 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 1)) {
3674 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
3676 }
3677 }
3678
3679 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 4)) {
3680 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3681 if (ntree->type != NTREE_CUSTOM) {
3682 /* versioning_update_noise_texture_node must be done before
3683 * versioning_replace_musgrave_texture_node. */
3685
3686 /* Convert Musgrave Texture nodes to Noise Texture nodes. */
3688 }
3689 }
3691 }
3692
3693 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
3694 /* Unify Material::blend_shadow and Cycles.use_transparent_shadows into the
3695 * Material::blend_flag. */
3696 bool is_eevee = all_scenes_use(bmain,
3698 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
3699 bool transparent_shadows = true;
3700 if (is_eevee) {
3701 transparent_shadows = material->blend_shadow != MA_BS_SOLID;
3702 }
3703 else if (IDProperty *cmat = version_cycles_properties_from_ID(&material->id)) {
3704 transparent_shadows = version_cycles_property_boolean(
3705 cmat, "use_transparent_shadow", true);
3706 }
3707 SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW);
3708 }
3709 }
3710
3711 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
3713 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3714 if (ntree->type == NTREE_COMPOSIT) {
3716 }
3717 }
3719 }
3720
3721 /* 401 6 did not require any do_version here. */
3722
3723 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 7)) {
3724 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "volumetric_ray_depth")) {
3726 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3727 scene->eevee.volumetric_ray_depth = default_eevee.volumetric_ray_depth;
3728 }
3729 }
3730
3731 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "surface_render_method")) {
3732 LISTBASE_FOREACH (Material *, mat, &bmain->materials) {
3733 mat->surface_render_method = (mat->blend_method == MA_BM_BLEND) ?
3736 }
3737 }
3738
3739 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3740 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3741 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3742 const ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3743 &sl->regionbase;
3744 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3745 if (region->regiontype != RGN_TYPE_ASSET_SHELF_HEADER) {
3746 continue;
3747 }
3748 region->alignment &= ~RGN_SPLIT_PREV;
3749 region->alignment |= RGN_ALIGN_HIDE_WITH_PREV;
3750 }
3751 }
3752 }
3753 }
3754
3755 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "float", "gtao_thickness")) {
3757 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3758 scene->eevee.gtao_thickness = default_eevee.gtao_thickness;
3759 scene->eevee.gtao_focus = default_eevee.gtao_focus;
3760 }
3761 }
3762
3763 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "float", "data_display_size")) {
3765 LISTBASE_FOREACH (LightProbe *, probe, &bmain->lightprobes) {
3766 probe->data_display_size = default_probe.data_display_size;
3767 }
3768 }
3769
3770 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
3771 mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
3772 }
3773 }
3774
3775 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 8)) {
3776 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3777 if (ntree->type != NTREE_GEOMETRY) {
3778 continue;
3779 }
3781 }
3782 }
3783
3784 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 9)) {
3785 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "displacement_method")) {
3786 /* Replace Cycles.displacement_method by Material::displacement_method. */
3787 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
3788 int displacement_method = MA_DISPLACEMENT_BUMP;
3789 if (IDProperty *cmat = version_cycles_properties_from_ID(&material->id)) {
3790 displacement_method = version_cycles_property_int(
3791 cmat, "displacement_method", MA_DISPLACEMENT_BUMP);
3792 }
3793 material->displacement_method = displacement_method;
3794 }
3795 }
3796
3797 /* Prevent custom bone colors from having alpha zero.
3798 * Part of the fix for issue #115434. */
3799 LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
3800 blender::animrig::ANIM_armature_foreach_bone(&arm->bonebase, [](Bone *bone) {
3801 bone->color.custom.solid[3] = 255;
3802 bone->color.custom.select[3] = 255;
3803 bone->color.custom.active[3] = 255;
3804 });
3805 if (arm->edbo) {
3806 LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
3807 ebone->color.custom.solid[3] = 255;
3808 ebone->color.custom.select[3] = 255;
3809 ebone->color.custom.active[3] = 255;
3810 }
3811 }
3812 }
3813 LISTBASE_FOREACH (Object *, obj, &bmain->objects) {
3814 if (obj->pose == nullptr) {
3815 continue;
3816 }
3817 LISTBASE_FOREACH (bPoseChannel *, pchan, &obj->pose->chanbase) {
3818 pchan->color.custom.solid[3] = 255;
3819 pchan->color.custom.select[3] = 255;
3820 pchan->color.custom.active[3] = 255;
3821 }
3822 }
3823 }
3824
3825 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 10)) {
3826 if (!DNA_struct_member_exists(
3827 fd->filesdna, "SceneEEVEE", "RaytraceEEVEE", "ray_tracing_options"))
3828 {
3829 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3830 scene->eevee.ray_tracing_options.flag = RAYTRACE_EEVEE_USE_DENOISE;
3831 scene->eevee.ray_tracing_options.denoise_stages = RAYTRACE_EEVEE_DENOISE_SPATIAL |
3834 scene->eevee.ray_tracing_options.screen_trace_quality = 0.25f;
3835 scene->eevee.ray_tracing_options.screen_trace_thickness = 0.2f;
3836 scene->eevee.ray_tracing_options.trace_max_roughness = 0.5f;
3837 scene->eevee.ray_tracing_options.resolution_scale = 2;
3838 }
3839 }
3840
3841 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3842 if (ntree->type == NTREE_GEOMETRY) {
3846 }
3847 }
3848 }
3849
3850 if (MAIN_VERSION_FILE_ATLEAST(bmain, 400, 20) && !MAIN_VERSION_FILE_ATLEAST(bmain, 401, 11)) {
3851 /* Convert old socket lists into new interface items. */
3852 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3854 }
3856 }
3857
3858 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 12)) {
3859 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3860 if (ntree->type == NTREE_COMPOSIT) {
3861 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3862 if (node->type == CMP_NODE_PIXELATE) {
3863 node->custom1 = 1;
3864 }
3865 }
3866 }
3867 }
3869 }
3870
3871 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 13)) {
3872 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3873 if (ntree->type == NTREE_COMPOSIT) {
3874 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3875 if (node->type == CMP_NODE_MAP_UV) {
3877 }
3878 }
3879 }
3880 }
3882 }
3883
3884 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 14)) {
3885 const Brush *default_brush = DNA_struct_default_get(Brush);
3886 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
3887 brush->automasking_start_normal_limit = default_brush->automasking_start_normal_limit;
3888 brush->automasking_start_normal_falloff = default_brush->automasking_start_normal_falloff;
3889
3890 brush->automasking_view_normal_limit = default_brush->automasking_view_normal_limit;
3891 brush->automasking_view_normal_falloff = default_brush->automasking_view_normal_falloff;
3892 }
3893 }
3894
3895 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 15)) {
3896 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3897 if (ntree->type == NTREE_COMPOSIT) {
3898 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3899 if (node->type == CMP_NODE_KEYING) {
3900 NodeKeyingData &keying_data = *static_cast<NodeKeyingData *>(node->storage);
3901 keying_data.edge_kernel_radius = max_ii(keying_data.edge_kernel_radius - 1, 0);
3902 }
3903 }
3904 }
3905 }
3907 }
3908
3909 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 16)) {
3910 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3911 Sculpt *sculpt = scene->toolsettings->sculpt;
3912 if (sculpt != nullptr) {
3913 Sculpt default_sculpt = *DNA_struct_default_get(Sculpt);
3916 }
3917 }
3918 }
3919
3920 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 17)) {
3921 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3922 ToolSettings *ts = scene->toolsettings;
3923 int input_sample_values[9];
3924
3925 input_sample_values[0] = ts->imapaint.paint.num_input_samples_deprecated;
3926 input_sample_values[1] = ts->sculpt != nullptr ?
3928 1;
3929 input_sample_values[2] = ts->curves_sculpt != nullptr ?
3931 1;
3932
3933 input_sample_values[3] = ts->gp_paint != nullptr ?
3935 1;
3936 input_sample_values[4] = ts->gp_vertexpaint != nullptr ?
3938 1;
3939 input_sample_values[5] = ts->gp_sculptpaint != nullptr ?
3941 1;
3942 input_sample_values[6] = ts->gp_weightpaint != nullptr ?
3944 1;
3945
3946 input_sample_values[7] = ts->vpaint != nullptr ?
3948 1;
3949 input_sample_values[8] = ts->wpaint != nullptr ?
3951 1;
3952
3953 int unified_value = 1;
3954 for (int i = 0; i < 9; i++) {
3955 if (input_sample_values[i] != 1) {
3956 if (unified_value == 1) {
3957 unified_value = input_sample_values[i];
3958 }
3959 else {
3960 /* In the case of a user having multiple tools with different num_input_value values
3961 * set we cannot support this in the single UnifiedPaintSettings value, so fallback
3962 * to 1 instead of deciding that one value is more canonical than the other.
3963 */
3964 break;
3965 }
3966 }
3967 }
3968
3969 ts->unified_paint_settings.input_samples = unified_value;
3970 }
3971 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
3972 brush->input_samples = 1;
3973 }
3974 }
3975
3976 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 18)) {
3977 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3978 if (scene->ed != nullptr) {
3979 SEQ_for_each_callback(&scene->ed->seqbase, seq_filter_bilinear_to_auto, nullptr);
3980 }
3981 }
3982 }
3983
3984 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 19)) {
3985 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3986 if (ntree->type == NTREE_GEOMETRY) {
3987 version_node_socket_name(ntree, FN_NODE_ROTATE_ROTATION, "Rotation 1", "Rotation");
3988 version_node_socket_name(ntree, FN_NODE_ROTATE_ROTATION, "Rotation 2", "Rotate By");
3989 }
3990 }
3991 }
3992
3993 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 20)) {
3994 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
3995 int uid = 1;
3996 LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
3997 /* These identifiers are not necessarily stable for linked data. If the linked data has a
3998 * new modifier inserted, the identifiers of other modifiers can change. */
3999 md->persistent_uid = uid++;
4000 }
4001 }
4002 }
4003
4004 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 21)) {
4005 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4006 /* The `sculpt_flag` was used to store the `BRUSH_DIR_IN`
4007 * With the fix for #115313 this is now just using the `brush->flag`. */
4008 if (brush->gpencil_settings && (brush->gpencil_settings->sculpt_flag & BRUSH_DIR_IN) != 0) {
4009 brush->flag |= BRUSH_DIR_IN;
4010 }
4011 }
4012 }
4013
4014 /* Keep point/spot light soft falloff for files created before 4.0. */
4015 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 0)) {
4016 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4017 if (ELEM(light->type, LA_LOCAL, LA_SPOT)) {
4018 light->mode |= LA_USE_SOFT_FALLOFF;
4019 }
4020 }
4021 }
4022
4023 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 1)) {
4024 using namespace blender::bke::greasepencil;
4025 /* Initialize newly added scale layer transform to one. */
4026 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
4027 for (Layer *layer : grease_pencil->layers_for_write()) {
4028 copy_v3_fl(layer->scale, 1.0f);
4029 }
4030 }
4031 }
4032
4033 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 2)) {
4034 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4035 bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES);
4036 if (is_cycles) {
4037 if (IDProperty *cscene = version_cycles_properties_from_ID(&scene->id)) {
4038 int cposition = version_cycles_property_int(cscene, "motion_blur_position", 1);
4039 BLI_assert(cposition >= 0 && cposition < 3);
4040 int order_conversion[3] = {SCE_MB_START, SCE_MB_CENTER, SCE_MB_END};
4041 scene->r.motion_blur_position = order_conversion[std::clamp(cposition, 0, 2)];
4042 }
4043 }
4044 else {
4046 scene->r.mode, scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED_DEPRECATED, R_MBLUR);
4047 scene->r.motion_blur_position = scene->eevee.motion_blur_position_deprecated;
4048 scene->r.motion_blur_shutter = scene->eevee.motion_blur_shutter_deprecated;
4049 }
4050 }
4051 }
4052
4053 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 3)) {
4054 constexpr int NTREE_EXECUTION_MODE_CPU = 0;
4055 constexpr int NTREE_EXECUTION_MODE_FULL_FRAME = 1;
4056
4057 constexpr int NTREE_COM_GROUPNODE_BUFFER = 1 << 3;
4058 constexpr int NTREE_COM_OPENCL = 1 << 1;
4059
4060 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4061 if (ntree->type != NTREE_COMPOSIT) {
4062 continue;
4063 }
4064
4065 ntree->flag &= ~(NTREE_COM_GROUPNODE_BUFFER | NTREE_COM_OPENCL);
4066
4067 if (ntree->execution_mode == NTREE_EXECUTION_MODE_FULL_FRAME) {
4068 ntree->execution_mode = NTREE_EXECUTION_MODE_CPU;
4069 }
4070 }
4072 }
4073
4074 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 4)) {
4075 if (!DNA_struct_member_exists(fd->filesdna, "SpaceImage", "float", "stretch_opacity")) {
4076 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4077 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4078 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4079 if (sl->spacetype == SPACE_IMAGE) {
4080 SpaceImage *sima = reinterpret_cast<SpaceImage *>(sl);
4081 sima->stretch_opacity = 0.9f;
4082 }
4083 }
4084 }
4085 }
4086 }
4087 }
4088
4089 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 5)) {
4090 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4092 }
4093 }
4094
4095 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 6)) {
4096 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4097 if (BrushCurvesSculptSettings *settings = brush->curves_sculpt_settings) {
4099 settings->curve_radius = 0.01f;
4100 }
4101 }
4102 }
4103
4104 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 8)) {
4105 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4106 light->shadow_filter_radius = 1.0f;
4107 }
4108 }
4109
4110 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 9)) {
4111 const float default_snap_angle_increment = DEG2RADF(5.0f);
4112 const float default_snap_angle_increment_precision = DEG2RADF(1.0f);
4113 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4114 scene->toolsettings->snap_angle_increment_2d = default_snap_angle_increment;
4115 scene->toolsettings->snap_angle_increment_3d = default_snap_angle_increment;
4116 scene->toolsettings->snap_angle_increment_2d_precision =
4117 default_snap_angle_increment_precision;
4118 scene->toolsettings->snap_angle_increment_3d_precision =
4119 default_snap_angle_increment_precision;
4120 }
4121 }
4122
4123 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 10)) {
4124 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "gtao_resolution")) {
4125 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4126 scene->eevee.gtao_resolution = 2;
4127 }
4128 }
4129 }
4130
4131 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 12)) {
4132 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4134 }
4136
4137 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4138 if (scene->ed != nullptr) {
4139 SEQ_for_each_callback(&scene->ed->seqbase, seq_hue_correct_set_wrapping, nullptr);
4140 }
4141 }
4142 }
4143
4144 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 14)) {
4145 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
4146 if (bMotionPath *mpath = ob->mpath) {
4147 mpath->color_post[0] = 0.1f;
4148 mpath->color_post[1] = 1.0f;
4149 mpath->color_post[2] = 0.1f;
4150 }
4151 if (!ob->pose) {
4152 continue;
4153 }
4154 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
4155 if (bMotionPath *mpath = pchan->mpath) {
4156 mpath->color_post[0] = 0.1f;
4157 mpath->color_post[1] = 1.0f;
4158 mpath->color_post[2] = 0.1f;
4159 }
4160 }
4161 }
4162 }
4163
4164 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 18)) {
4165 if (!DNA_struct_member_exists(fd->filesdna, "Light", "float", "transmission_fac")) {
4166 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4167 /* Refracted light was not supported in legacy EEVEE. Set it to zero for compatibility with
4168 * older files. */
4169 light->transmission_fac = 0.0f;
4170 }
4171 }
4172 }
4173
4174 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 19)) {
4175 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4176 /* Keep legacy EEVEE old behavior. */
4177 scene->eevee.flag |= SCE_EEVEE_VOLUME_CUSTOM_RANGE;
4178 }
4179
4180 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4181 scene->eevee.clamp_surface_indirect = 10.0f;
4182 /* Make contribution of indirect lighting very small (but non-null) to avoid world lighting
4183 * and volume lightprobe changing the appearance of volume objects. */
4184 scene->eevee.clamp_volume_indirect = 1e-8f;
4185 }
4186 }
4187
4188 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 20)) {
4189 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4190 SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
4191 sequencer_tool_settings->snap_mode |= SEQ_SNAP_TO_MARKERS;
4192 }
4193 }
4194
4195 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 21)) {
4197 }
4198
4199 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 22)) {
4200 /* Display missing media in sequencer by default. */
4201 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4202 if (scene->ed != nullptr) {
4203 scene->ed->show_missing_media_flag |= SEQ_EDIT_SHOW_MISSING_MEDIA;
4204 }
4205 }
4206 }
4207
4208 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 23)) {
4209 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4210 ToolSettings *ts = scene->toolsettings;
4211 if (!ts->uvsculpt.strength_curve) {
4212 ts->uvsculpt.size = 50;
4213 ts->uvsculpt.strength = 1.0f;
4215 ts->uvsculpt.strength_curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
4216 }
4217 }
4218 }
4219
4220 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 24)) {
4221 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "thickness_mode")) {
4222 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
4223 if (material->blend_flag & MA_BL_TRANSLUCENCY) {
4224 /* EEVEE Legacy used thickness from shadow map when translucency was on. */
4225 material->blend_flag |= MA_BL_THICKNESS_FROM_SHADOW;
4226 }
4227 if ((material->blend_flag & MA_BL_SS_REFRACTION) && material->use_nodes &&
4228 material->nodetree)
4229 {
4230 /* EEVEE Legacy used slab assumption. */
4231 material->thickness_mode = MA_THICKNESS_SLAB;
4232 version_refraction_depth_to_thickness_value(material->nodetree, material->refract_depth);
4233 }
4234 }
4235 }
4236 }
4237
4238 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 25)) {
4239 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4240 if (ntree->type != NTREE_COMPOSIT) {
4241 continue;
4242 }
4243 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4244 if (node->type != CMP_NODE_BLUR) {
4245 continue;
4246 }
4247
4248 NodeBlurData &blur_data = *static_cast<NodeBlurData *>(node->storage);
4249
4250 if (blur_data.filtertype != R_FILTER_FAST_GAUSS) {
4251 continue;
4252 }
4253
4254 /* The size of the Fast Gaussian mode of blur decreased by the following factor to match
4255 * other blur sizes. So increase it back. */
4256 const float size_factor = 3.0f / 2.0f;
4257 blur_data.sizex *= size_factor;
4258 blur_data.sizey *= size_factor;
4259 blur_data.percentx *= size_factor;
4260 blur_data.percenty *= size_factor;
4261 }
4262 }
4264 }
4265
4266 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 26)) {
4267 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "float", "shadow_resolution_scale"))
4268 {
4269 SceneEEVEE default_scene_eevee = *DNA_struct_default_get(SceneEEVEE);
4270 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4271 scene->eevee.shadow_resolution_scale = default_scene_eevee.shadow_resolution_scale;
4272 }
4273 }
4274 }
4275
4276 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 27)) {
4277 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4278 if (scene->ed != nullptr) {
4279 scene->ed->cache_flag &= ~(SEQ_CACHE_UNUSED_5 | SEQ_CACHE_UNUSED_6 | SEQ_CACHE_UNUSED_7 |
4281 }
4282 }
4283 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4284 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4285 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4286 if (sl->spacetype == SPACE_SEQ) {
4287 SpaceSeq *sseq = (SpaceSeq *)sl;
4289 }
4290 }
4291 }
4292 }
4293 }
4294
4295 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 28)) {
4296 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4297 if (scene->ed != nullptr) {
4298 SEQ_for_each_callback(&scene->ed->seqbase, seq_proxies_timecode_update, nullptr);
4299 }
4300 }
4301
4302 LISTBASE_FOREACH (MovieClip *, clip, &bmain->movieclips) {
4303 MovieClipProxy proxy = clip->proxy;
4305 }
4306 }
4307
4308 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 29)) {
4309 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4310 if (scene->ed) {
4311 SEQ_for_each_callback(&scene->ed->seqbase, seq_text_data_update, nullptr);
4312 }
4313 }
4314 }
4315
4316 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 30)) {
4317 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4318 if (scene->nodetree) {
4319 scene->nodetree->flag &= ~NTREE_UNUSED_2;
4320 }
4321 }
4322 }
4323
4324 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 31)) {
4325 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
4326 /* Guess a somewhat correct density given the resolution. But very low resolution need
4327 * a decent enough density to work. */
4328 lightprobe->grid_surfel_density = max_ii(20,
4329 2 * max_iii(lightprobe->grid_resolution_x,
4330 lightprobe->grid_resolution_y,
4331 lightprobe->grid_resolution_z));
4332 }
4333 }
4334
4335 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 31)) {
4336 bool only_uses_eevee_legacy_or_workbench = true;
4337 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4339 only_uses_eevee_legacy_or_workbench = false;
4340 }
4341 }
4342 /* Mark old EEVEE world volumes for showing conversion operator. */
4343 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
4344 if (world->nodetree) {
4346 if (output_node) {
4347 bNodeSocket *volume_input_socket = static_cast<bNodeSocket *>(
4348 BLI_findlink(&output_node->inputs, 1));
4349 if (volume_input_socket) {
4350 LISTBASE_FOREACH (bNodeLink *, node_link, &world->nodetree->links) {
4351 if (node_link->tonode == output_node && node_link->tosock == volume_input_socket) {
4353 /* Only display a warning message if we are sure this can be used by EEVEE. */
4354 if (only_uses_eevee_legacy_or_workbench) {
4357 RPT_("%s contains a volume shader that might need to be "
4358 "converted to object (see world volume panel)\n"),
4359 world->id.name + 2);
4360 }
4361 }
4362 }
4363 }
4364 }
4365 }
4366 }
4367 }
4368
4369 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 33)) {
4370 constexpr int NTREE_EXECUTION_MODE_GPU = 2;
4371
4372 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4373 if (scene->nodetree) {
4374 if (scene->nodetree->execution_mode == NTREE_EXECUTION_MODE_GPU) {
4375 scene->r.compositor_device = SCE_COMPOSITOR_DEVICE_GPU;
4376 }
4377 scene->r.compositor_precision = scene->nodetree->precision;
4378 }
4379 }
4380 }
4381
4382 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 34)) {
4383 float shadow_max_res_sun = 0.001f;
4384 float shadow_max_res_local = 0.001f;
4385 bool shadow_resolution_absolute = false;
4386 /* Try to get default resolution from scene setting. */
4387 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4388 shadow_max_res_local = (2.0f * M_SQRT2) / scene->eevee.shadow_cube_size_deprecated;
4389 /* Round to avoid weird numbers in the UI. */
4390 shadow_max_res_local = ceil(shadow_max_res_local * 1000.0f) / 1000.0f;
4391 shadow_resolution_absolute = true;
4392 break;
4393 }
4394
4395 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4396 if (light->type == LA_SUN) {
4397 /* Sun are too complex to convert. Need user interaction. */
4398 light->shadow_maximum_resolution = shadow_max_res_sun;
4399 SET_FLAG_FROM_TEST(light->mode, false, LA_SHAD_RES_ABSOLUTE);
4400 }
4401 else {
4402 light->shadow_maximum_resolution = shadow_max_res_local;
4403 SET_FLAG_FROM_TEST(light->mode, shadow_resolution_absolute, LA_SHAD_RES_ABSOLUTE);
4404 }
4405 }
4406 }
4407
4408 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 36)) {
4409 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4410 /* Only for grease pencil brushes. */
4411 if (brush->gpencil_settings) {
4412 /* Use the `Scene` radius unit by default (confusingly named `BRUSH_LOCK_SIZE`).
4413 * Convert the radius to be the same visual size as in GPv2. */
4414 brush->flag |= BRUSH_LOCK_SIZE;
4415 brush->unprojected_radius = brush->size *
4417 }
4418 }
4419 }
4420
4421 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 37)) {
4422 const World *default_world = DNA_struct_default_get(World);
4423 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
4424 world->sun_threshold = default_world->sun_threshold;
4425 world->sun_angle = default_world->sun_angle;
4426 world->sun_shadow_maximum_resolution = default_world->sun_shadow_maximum_resolution;
4427 /* Having the sun extracted is mandatory to keep the same look and avoid too much light
4428 * leaking compared to EEVEE-Legacy. But adding shadows might create performance overhead and
4429 * change the result in a very different way. So we disable shadows in older file. */
4430 world->flag &= ~WO_USE_SUN_SHADOW;
4431 }
4432 }
4433
4434 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 38)) {
4435 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
4437 }
4438 }
4439
4440 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 39)) {
4441 /* Unify cast shadow property with Cycles. */
4443 const Light *default_light = DNA_struct_default_get(Light);
4444 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4445 IDProperty *clight = version_cycles_properties_from_ID(&light->id);
4446 if (clight) {
4448 clight, "cast_shadow", default_light->mode & LA_SHADOW);
4449 SET_FLAG_FROM_TEST(light->mode, value, LA_SHADOW);
4450 }
4451 }
4452 }
4453 }
4454
4455 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 40)) {
4456 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
4457 version_node_input_socket_name(ntree, FN_NODE_COMBINE_TRANSFORM, "Location", "Translation");
4459 ntree, FN_NODE_SEPARATE_TRANSFORM, "Location", "Translation");
4460 }
4461 }
4462
4463 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 41)) {
4464 const Light *default_light = DNA_struct_default_get(Light);
4465 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4466 light->shadow_jitter_overblur = default_light->shadow_jitter_overblur;
4467 }
4468 }
4469
4470 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 43)) {
4471 const World *default_world = DNA_struct_default_get(World);
4472 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
4473 world->sun_shadow_maximum_resolution = default_world->sun_shadow_maximum_resolution;
4474 world->sun_shadow_filter_radius = default_world->sun_shadow_filter_radius;
4475 }
4476 }
4477
4478 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 44)) {
4479 const Scene *default_scene = DNA_struct_default_get(Scene);
4480 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4481 scene->eevee.fast_gi_step_count = default_scene->eevee.fast_gi_step_count;
4482 scene->eevee.fast_gi_ray_count = default_scene->eevee.fast_gi_ray_count;
4483 }
4484 }
4485
4486 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 45)) {
4487 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4488 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4489 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4490 if (sl->spacetype == SPACE_VIEW3D) {
4491 View3D *v3d = reinterpret_cast<View3D *>(sl);
4493 }
4494 }
4495 }
4496 }
4497 }
4498
4499 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 46)) {
4500 const Scene *default_scene = DNA_struct_default_get(Scene);
4501 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4502 scene->eevee.fast_gi_thickness_near = default_scene->eevee.fast_gi_thickness_near;
4503 scene->eevee.fast_gi_thickness_far = default_scene->eevee.fast_gi_thickness_far;
4504 }
4505 }
4506 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 48)) {
4507 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
4508 if (!ob->pose) {
4509 continue;
4510 }
4511 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
4512 pchan->custom_shape_wire_width = 1.0;
4513 }
4514 }
4515 }
4516
4517 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 49)) {
4518 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4519 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4520 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4521 if (sl->spacetype == SPACE_VIEW3D) {
4522 View3D *v3d = reinterpret_cast<View3D *>(sl);
4524 }
4525 }
4526 }
4527 }
4528 }
4529
4530 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 50)) {
4531 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
4532 if (ntree->type != NTREE_GEOMETRY) {
4533 continue;
4534 }
4535 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4536 if (node->type != GEO_NODE_CAPTURE_ATTRIBUTE) {
4537 continue;
4538 }
4540 node->storage);
4541 if (storage->next_identifier > 0) {
4542 continue;
4543 }
4544 storage->capture_items_num = 1;
4545 storage->capture_items = MEM_cnew_array<NodeGeometryAttributeCaptureItem>(
4546 storage->capture_items_num, __func__);
4548 item.data_type = storage->data_type_legacy;
4549 item.identifier = storage->next_identifier++;
4550 item.name = BLI_strdup("Value");
4551 }
4552 }
4553 }
4554
4555 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 53)) {
4556 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4557 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4558 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4559 if (sl->spacetype == SPACE_NODE) {
4560 SpaceNode *snode = reinterpret_cast<SpaceNode *>(sl);
4562 }
4563 }
4564 }
4565 }
4566 }
4567
4568 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 55)) {
4569 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4570 if (ntree->type != NTREE_COMPOSIT) {
4571 continue;
4572 }
4573 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4574 if (node->type != CMP_NODE_CURVE_RGB) {
4575 continue;
4576 }
4577
4578 CurveMapping &curve_mapping = *static_cast<CurveMapping *>(node->storage);
4579
4580 /* Film-like tone only works with the combined curve, which is the fourth curve, so make
4581 * the combined curve current, as we now hide the rest of the curves since they no longer
4582 * have an effect. */
4583 if (curve_mapping.tone == CURVE_TONE_FILMLIKE) {
4584 curve_mapping.cur = 3;
4585 }
4586 }
4587 }
4589 }
4590
4591 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 2)) {
4592 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4593 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4594 LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) {
4595 if (space_link->spacetype == SPACE_NODE) {
4596 SpaceNode *space_node = reinterpret_cast<SpaceNode *>(space_link);
4597 space_node->flag &= ~SNODE_FLAG_UNUSED_5;
4598 }
4599 }
4600 }
4601 }
4602 }
4603
4604 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 60) ||
4605 (bmain->versionfile == 403 && !MAIN_VERSION_FILE_ATLEAST(bmain, 403, 3)))
4606 {
4607 /* Limit Rotation constraints from old files should use the legacy Limit
4608 * Rotation behavior. */
4609 LISTBASE_FOREACH (Object *, obj, &bmain->objects) {
4610 LISTBASE_FOREACH (bConstraint *, constraint, &obj->constraints) {
4611 if (constraint->type != CONSTRAINT_TYPE_ROTLIMIT) {
4612 continue;
4613 }
4614 static_cast<bRotLimitConstraint *>(constraint->data)->flag |= LIMIT_ROT_LEGACY_BEHAVIOR;
4615 }
4616
4617 if (!obj->pose) {
4618 continue;
4619 }
4620 LISTBASE_FOREACH (bPoseChannel *, pbone, &obj->pose->chanbase) {
4621 LISTBASE_FOREACH (bConstraint *, constraint, &pbone->constraints) {
4622 if (constraint->type != CONSTRAINT_TYPE_ROTLIMIT) {
4623 continue;
4624 }
4625 static_cast<bRotLimitConstraint *>(constraint->data)->flag |= LIMIT_ROT_LEGACY_BEHAVIOR;
4626 }
4627 }
4628 }
4629 }
4630
4631 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 61)) {
4632 /* LIGHT_PROBE_RESOLUTION_64 has been removed in EEVEE-Next as the tedrahedral mapping is to
4633 * low res to be usable. */
4634 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4635 if (scene->eevee.gi_cubemap_resolution < 128) {
4636 scene->eevee.gi_cubemap_resolution = 128;
4637 }
4638 }
4639 }
4640
4641 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 64)) {
4643 /* Re-apply versioning made for EEVEE-Next in 4.1 before it got delayed. */
4644 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
4645 bool transparent_shadows = material->blend_shadow != MA_BS_SOLID;
4646 SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW);
4647 }
4648 LISTBASE_FOREACH (Material *, mat, &bmain->materials) {
4649 mat->surface_render_method = (mat->blend_method == MA_BM_BLEND) ?
4652 }
4653 }
4654 }
4655
4656 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 3)) {
4657 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4658 if (BrushGpencilSettings *settings = brush->gpencil_settings) {
4659 /* Copy the `draw_strength` value to the `alpha` value. */
4660 brush->alpha = settings->draw_strength;
4661
4662 /* We approximate the simplify pixel threshold by taking the previous threshold (world
4663 * space) and dividing by the legacy radius conversion factor. This should generally give
4664 * reasonable "pixel" threshold values, at least for previous GPv2 defaults. */
4665 settings->simplify_px = settings->simplify_f /
4667 }
4668 }
4669 }
4670
4671 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 4)) {
4672 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4673 scene->view_settings.temperature = 6500.0f;
4674 scene->view_settings.tint = 10.0f;
4675 }
4676 }
4677
4678 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 7)) {
4679 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4680 SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
4681 sequencer_tool_settings->snap_mode |= SEQ_SNAP_TO_PREVIEW_BORDERS |
4684 }
4685 }
4686
4687 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 8)) {
4689 }
4690
4691 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 9)) {
4693 }
4694
4695 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 10)) {
4696 /* Initialize Color Balance node white point settings. */
4697 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4698 if (ntree->type != NTREE_CUSTOM) {
4699 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4700 if (node->type == CMP_NODE_COLORBALANCE) {
4701 NodeColorBalance *n = static_cast<NodeColorBalance *>(node->storage);
4702 n->input_temperature = n->output_temperature = 6500.0f;
4703 n->input_tint = n->output_tint = 10.0f;
4704 }
4705 }
4706 }
4707 }
4709 }
4710
4711 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 11)) {
4713 curves->geometry.attributes_active_index = curves->attributes_active_index_legacy;
4714 }
4715 }
4716
4717 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 13)) {
4718 Camera default_cam = *DNA_struct_default_get(Camera);
4719 LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
4720 camera->central_cylindrical_range_u_min = default_cam.central_cylindrical_range_u_min;
4721 camera->central_cylindrical_range_u_max = default_cam.central_cylindrical_range_u_max;
4722 camera->central_cylindrical_range_v_min = default_cam.central_cylindrical_range_v_min;
4723 camera->central_cylindrical_range_v_max = default_cam.central_cylindrical_range_v_max;
4724 camera->central_cylindrical_radius = default_cam.central_cylindrical_radius;
4725 }
4726 }
4727
4728 /* The File Output node now uses the linear color space setting of its stored image formats. So
4729 * we need to ensure the color space value is initialized to some sane default based on the image
4730 * type. Furthermore, the node now gained a new Save As Render option that is global to the node,
4731 * which will be used if Use Node Format is enabled for each input, so we potentially need to
4732 * disable Use Node Format in case inputs had different Save As render options. */
4733 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 14)) {
4734 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4735 if (ntree->type != NTREE_COMPOSIT) {
4736 continue;
4737 }
4738
4739 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4740 if (node->type != CMP_NODE_OUTPUT_FILE) {
4741 continue;
4742 }
4743
4744 /* Initialize node format color space if it is not set. */
4745 NodeImageMultiFile *storage = static_cast<NodeImageMultiFile *>(node->storage);
4746 if (storage->format.linear_colorspace_settings.name[0] == '\0') {
4748 }
4749
4750 if (BLI_listbase_is_empty(&node->inputs)) {
4751 continue;
4752 }
4753
4754 /* Initialize input formats color space if it is not set. */
4755 LISTBASE_FOREACH (const bNodeSocket *, input, &node->inputs) {
4756 NodeImageMultiFileSocket *input_storage = static_cast<NodeImageMultiFileSocket *>(
4757 input->storage);
4758 if (input_storage->format.linear_colorspace_settings.name[0] == '\0') {
4760 }
4761 }
4762
4763 /* EXR images don't use Save As Render. */
4765 continue;
4766 }
4767
4768 /* Find out if all inputs have the same Save As Render option. */
4769 const bNodeSocket *first_input = static_cast<bNodeSocket *>(node->inputs.first);
4770 const NodeImageMultiFileSocket *first_input_storage =
4771 static_cast<NodeImageMultiFileSocket *>(first_input->storage);
4772 const bool first_save_as_render = first_input_storage->save_as_render;
4773 bool all_inputs_have_same_save_as_render = true;
4774 LISTBASE_FOREACH (const bNodeSocket *, input, &node->inputs) {
4775 const NodeImageMultiFileSocket *input_storage = static_cast<NodeImageMultiFileSocket *>(
4776 input->storage);
4777 if (bool(input_storage->save_as_render) != first_save_as_render) {
4778 all_inputs_have_same_save_as_render = false;
4779 break;
4780 }
4781 }
4782
4783 /* All inputs have the same save as render option, so we set the node Save As Render option
4784 * to that value, and we leave inputs as is. */
4785 if (all_inputs_have_same_save_as_render) {
4786 storage->save_as_render = first_save_as_render;
4787 continue;
4788 }
4789
4790 /* For inputs that have Use Node Format enabled, we need to disabled it because otherwise
4791 * they will use the node's Save As Render option. It follows that we need to copy the
4792 * node's format to the input format. */
4793 LISTBASE_FOREACH (const bNodeSocket *, input, &node->inputs) {
4794 NodeImageMultiFileSocket *input_storage = static_cast<NodeImageMultiFileSocket *>(
4795 input->storage);
4796
4797 if (!input_storage->use_node_format) {
4798 continue;
4799 }
4800
4801 input_storage->use_node_format = false;
4802 input_storage->format = storage->format;
4803 }
4804 }
4805 }
4807 }
4808
4809 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 15)) {
4810 using namespace blender;
4811
4812 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
4813 const ListBase *exporters = &collection->exporters;
4814 LISTBASE_FOREACH (CollectionExport *, data, exporters) {
4815 /* The name field should be empty at this point. */
4816 BLI_assert(data->name[0] == '\0');
4817
4819 BKE_collection_exporter_name_set(exporters, data, fh ? fh->label : DATA_("Undefined"));
4820 }
4821 }
4822 }
4823
4824 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 16)) {
4825 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4826 scene->eevee.flag |= SCE_EEVEE_FAST_GI_ENABLED;
4827 }
4828 }
4829
4830 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 17)) {
4831 FOREACH_NODETREE_BEGIN (bmain, tree, id) {
4832 if (tree->default_group_node_width == 0) {
4833 tree->default_group_node_width = GROUP_NODE_DEFAULT_WIDTH;
4834 }
4835 }
4837 }
4838
4839 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 20)) {
4840 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4841 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4842 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4843 if (sl->spacetype == SPACE_SEQ) {
4845 if (region != nullptr) {
4846 region->flag &= ~RGN_FLAG_HIDDEN;
4847 }
4848 }
4849 }
4850 }
4851 }
4852 }
4853
4854 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 21)) {
4855 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4856 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4857 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4858 if (sl->spacetype == SPACE_CLIP) {
4860 if (region != nullptr) {
4861 View2D *v2d = &region->v2d;
4863 }
4864 }
4865 }
4866 }
4867 }
4868 }
4869
4870 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 22)) {
4872 }
4873
4874 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 23)) {
4875 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
4876 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
4877 if (md->type != eModifierType_Nodes) {
4878 continue;
4879 }
4880 NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md);
4882 /* Use disk target for existing modifiers to avoid changing behavior. */
4884 }
4885 }
4886 }
4887 }
4888
4889 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 24)) {
4890 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4892 }
4894 }
4895
4896 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 26)) {
4898 }
4899
4900 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 28)) {
4901 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4902 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4903 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4904 if (sl->spacetype == SPACE_VIEW3D) {
4905 View3D *v3d = reinterpret_cast<View3D *>(sl);
4910 }
4911 }
4912 }
4913 }
4914 }
4915
4916 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 29)) {
4917 /* Open warnings panel by default. */
4918 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
4919 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
4920 if (md->type == eModifierType_Nodes) {
4921 md->layout_panel_open_flag |= 1 << NODES_MODIFIER_PANEL_WARNINGS;
4922 }
4923 }
4924 }
4925 }
4926
4927 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 31)) {
4928 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
4929 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
4930 if (tref->space_type != SPACE_SEQ) {
4931 continue;
4932 }
4933 STRNCPY(tref->idname, "builtin.select_box");
4934 }
4935 }
4936 }
4937
4938 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 34)) {
4939 /* #update_paint_modes_for_brush_assets() didn't handle image editor tools for some time. 4.3
4940 * files saved during that period could have invalid tool references stored. */
4941 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
4942 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
4943 if (tref->space_type == SPACE_IMAGE && tref->mode == SI_MODE_PAINT) {
4944 STRNCPY(tref->idname, "builtin.brush");
4945 }
4946 }
4947 }
4948 }
4949
4950 /* Always run this versioning; meshes are written with the legacy format which always needs to
4951 * be converted to the new format on file load. Can be moved to a subversion check in a larger
4952 * breaking release. */
4953 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
4955 }
4956
4963}
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
Iterators for armatures.
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
void ANIM_bonecoll_hide(bArmature *armature, BoneCollection *bcoll)
bool ANIM_armature_bonecoll_assign(BoneCollection *bcoll, Bone *bone)
BoneCollection * ANIM_armature_bonecoll_new(bArmature *armature, const char *name, int parent_index=-1)
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, struct ID *ref_id, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
bool BKE_animdata_fix_paths_remove(struct ID *id, const char *prefix)
void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
Definition armature.cc:2822
void BKE_collection_exporter_name_set(const ListBase *exporters, CollectionExport *data, const char *newname)
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition colortools.cc:90
@ CTX_MODE_VERTEX_GPENCIL_LEGACY
@ CTX_MODE_WEIGHT_GPENCIL_LEGACY
@ CTX_MODE_SCULPT_GPENCIL_LEGACY
@ CTX_MODE_PAINT_GREASE_PENCIL
@ CTX_MODE_PAINT_GPENCIL_LEGACY
@ CTX_MODE_PAINT_TEXTURE
@ CTX_MODE_SCULPT_GREASE_PENCIL
@ CTX_MODE_SCULPT
@ CTX_MODE_SCULPT_CURVES
@ CTX_MODE_WEIGHT_GREASE_PENCIL
@ CTX_MODE_VERTEX_GREASE_PENCIL
@ CTX_MODE_PAINT_VERTEX
@ CTX_MODE_PAINT_WEIGHT
short BKE_curve_type_get(const Curve *cu)
Definition curve.cc:416
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)
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:57
Low-level operations for grease pencil.
void IDP_AssignString(IDProperty *prop, const char *st) ATTR_NONNULL()
Definition idprop.cc:431
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:763
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1227
#define IDP_String(prop)
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:843
IDProperty * IDP_GetProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition idprop.cc:875
void BKE_image_format_update_color_space_for_type(ImageFormatData *format)
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:500
#define MAIN_VERSION_FILE_ATLEAST(main, ver, subver)
Definition BKE_main.hh:572
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:494
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
short * BKE_object_material_len_p(struct Object *ob)
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
void BKE_mesh_legacy_edge_crease_to_layers(Mesh *mesh)
void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
void BKE_mesh_legacy_sharp_faces_from_flags(Mesh *mesh)
void BKE_mesh_legacy_convert_edges_to_generic(Mesh *mesh)
void BKE_mesh_legacy_bevel_weight_to_generic(Mesh *mesh)
void BKE_mesh_legacy_face_map_to_generic(Main *bmain)
void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh)
void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh)
void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh)
void BKE_mesh_legacy_crease_to_generic(Mesh *mesh)
void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh)
void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
void BKE_mesh_legacy_uv_seam_from_flags(Mesh *mesh)
void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh)
void BKE_mesh_legacy_sharp_edges_from_flags(Mesh *mesh)
void BKE_mesh_legacy_attribute_flags_to_strings(Mesh *mesh)
void BKE_nla_tweakmode_exit(OwnedAnimData owned_adt)
#define SH_NODE_TEX_NOISE
Definition BKE_node.hh:936
#define SH_NODE_MIX_SHADER
Definition BKE_node.hh:917
#define GEO_NODE_OBJECT_INFO
Definition BKE_node.hh:1174
#define NODE_REROUTE
Definition BKE_node.hh:804
#define FN_NODE_SEPARATE_TRANSFORM
Definition BKE_node.hh:1420
#define GEO_NODE_STORE_NAMED_ATTRIBUTE
Definition BKE_node.hh:1285
#define SH_NODE_OUTPUT_WORLD
Definition BKE_node.hh:914
#define FN_NODE_ROTATE_ROTATION
Definition BKE_node.hh:1414
#define CMP_NODE_VIEWER
Definition BKE_node.hh:1012
#define GEO_NODE_SAMPLE_NEAREST_SURFACE
Definition BKE_node.hh:1305
#define GEO_NODE_EVALUATE_AT_INDEX
Definition BKE_node.hh:1277
constexpr int GROUP_NODE_DEFAULT_WIDTH
Definition BKE_node.hh:1810
#define SH_NODE_BSDF_PRINCIPLED
Definition BKE_node.hh:976
#define GEO_NODE_SET_SHADE_SMOOTH
Definition BKE_node.hh:1244
#define CMP_NODE_CRYPTOMATTE
Definition BKE_node.hh:1111
#define GEO_NODE_ATTRIBUTE_STATISTIC
Definition BKE_node.hh:1214
#define GEO_NODE_VIEWER
Definition BKE_node.hh:1201
#define SH_NODE_BSDF_SHEEN
Definition BKE_node.hh:926
#define SH_NODE_ADD_SHADER
Definition BKE_node.hh:939
#define SH_NODE_SUBSURFACE_SCATTERING
Definition BKE_node.hh:960
#define CMP_NODE_COLORBALANCE
Definition BKE_node.hh:1072
#define SH_NODE_TEX_COORD
Definition BKE_node.hh:938
#define SH_NODE_VALUE
Definition BKE_node.hh:892
#define CMP_NODE_HUECORRECT
Definition BKE_node.hh:1073
#define SH_NODE_MATH
Definition BKE_node.hh:904
#define GEO_NODE_INPUT_NAMED_ATTRIBUTE
Definition BKE_node.hh:1286
#define GEO_NODE_RAYCAST
Definition BKE_node.hh:1258
#define SH_NODE_BSDF_TRANSPARENT
Definition BKE_node.hh:925
#define CMP_NODE_SPLIT
Definition BKE_node.hh:1089
#define SH_NODE_VECT_TRANSFORM
Definition BKE_node.hh:965
#define GEO_NODE_SIMULATION_OUTPUT
Definition BKE_node.hh:1331
#define GEO_NODE_SWITCH
Definition BKE_node.hh:1188
#define GEO_NODE_EVALUATE_ON_DOMAIN
Definition BKE_node.hh:1292
#define CMP_NODE_MAP_UV
Definition BKE_node.hh:1054
#define SH_NODE_OUTPUT_MATERIAL
Definition BKE_node.hh:913
#define CMP_NODE_OUTPUT_FILE
Definition BKE_node.hh:1034
#define FOREACH_NODETREE_END
Definition BKE_node.hh:870
#define SH_NODE_BSDF_HAIR_PRINCIPLED
Definition BKE_node.hh:984
#define CMP_NODE_CURVE_RGB
Definition BKE_node.hh:1020
#define SH_NODE_BSDF_GLOSSY
Definition BKE_node.hh:920
#define GEO_NODE_ACCUMULATE_FIELD
Definition BKE_node.hh:1275
#define GEO_NODE_SAMPLE_CURVE
Definition BKE_node.hh:1215
#define SH_NODE_TEX_MUSGRAVE_DEPRECATED
Definition BKE_node.hh:937
#define CMP_NODE_PIXELATE
Definition BKE_node.hh:1102
#define SH_NODE_MIX
Definition BKE_node.hh:996
#define FN_NODE_COMBINE_TRANSFORM
Definition BKE_node.hh:1419
#define GEO_NODE_SAMPLE_UV_SURFACE
Definition BKE_node.hh:1316
#define SH_NODE_CLAMP
Definition BKE_node.hh:986
#define NODE_GROUP
Definition BKE_node.hh:800
#define SH_NODE_EEVEE_SPECULAR
Definition BKE_node.hh:978
#define GEO_NODE_CAPTURE_ATTRIBUTE
Definition BKE_node.hh:1210
#define CMP_NODE_SPLITVIEWER__DEPRECATED
Definition BKE_node.hh:1052
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition BKE_node.hh:860
#define CMP_NODE_KEYING
Definition BKE_node.hh:1083
#define SH_NODE_BSDF_GLASS
Definition BKE_node.hh:923
#define GEO_NODE_BLUR_ATTRIBUTE
Definition BKE_node.hh:1319
#define CMP_NODE_R_LAYERS
Definition BKE_node.hh:1032
#define SH_NODE_NEW_GEOMETRY
Definition BKE_node.hh:928
#define GEO_NODE_SAMPLE_INDEX
Definition BKE_node.hh:1303
#define SH_NODE_BSDF_GLOSSY_LEGACY
Definition BKE_node.hh:922
#define SH_NODE_BSDF_REFRACTION
Definition BKE_node.hh:956
#define CMP_NODE_BLUR
Definition BKE_node.hh:1022
void BKE_paint_brushes_set_default_references(ToolSettings *ts)
Definition paint.cc:1067
void BKE_scene_disable_color_management(Scene *scene)
Definition scene.cc:2826
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:815
struct MovieTrackingObject * BKE_tracking_object_get_camera(const struct MovieTracking *tracking)
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
#define M_SQRT2
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 M_PI_4
#define DEG2RADF(_deg)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v4_v4v4(float r[4], const float a[4], const float b[4], float t)
Definition math_vector.c:45
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void copy_v2_fl(float r[2], 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.c:40
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
Definition string.c:45
char char size_t char * BLI_strncat(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
#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
external readfile function prototypes.
#define RPT_(msgid)
#define DATA_(msgid)
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
@ ID_AR
@ IDP_STRING
@ ADT_NLA_EDIT_ON
@ ASSET_LIBRARY_ALL
@ BRUSH_CURVE_SMOOTH
@ BRUSH_DIR_IN
@ BRUSH_LOCK_SIZE
@ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_RADIUS
Object groups, one object can be in many groups at once.
@ CUMA_DO_CLIP
@ CUMA_USE_WRAPPING
@ CURVE_TONE_FILMLIKE
@ CONSTRAINT_TYPE_ROTLIMIT
@ LIMIT_ROT_LEGACY_BEHAVIOR
@ CD_PROP_FLOAT
@ CD_PROP_INT32
#define DNA_struct_default_get(struct_name)
#define MAX_NAME
Definition DNA_defs.h:50
blenloader genfile private function prototypes
@ LA_AREA
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ LA_SHAD_RES_ABSOLUTE
@ LA_SHADOW
@ LA_USE_SOFT_FALLOFF
@ LIGHTPROBE_GRID_CAPTURE_EMISSION
@ LIGHTPROBE_GRID_CAPTURE_WORLD
@ LIGHTPROBE_GRID_CAPTURE_INDIRECT
@ MA_DISPLACEMENT_BUMP
@ MA_BS_HASHED
@ MA_BS_CLIP
@ MA_BS_NONE
@ MA_BS_SOLID
@ MA_BL_TRANSPARENT_SHADOW
@ MA_BL_THICKNESS_FROM_SHADOW
@ MA_BL_TRANSLUCENCY
@ MA_BL_SS_REFRACTION
@ MA_SURFACE_METHOD_DEFERRED
@ MA_SURFACE_METHOD_FORWARD
@ MA_BM_CLIP
@ MA_BM_HASHED
@ MA_BM_BLEND
@ MA_THICKNESS_SLAB
@ ME_NO_OVERLAPPING_TOPOLOGY
@ NODES_MODIFIER_BAKE_TARGET_INHERIT
@ NODES_MODIFIER_BAKE_TARGET_DISK
@ NODES_MODIFIER_PANEL_WARNINGS
@ eModifierType_Nodes
@ eModifierType_Bevel
@ eModifierType_WeightVGEdit
@ NODE_INTERFACE_PANEL_ALLOW_CHILD_PANELS
@ NODE_INTERFACE_PANEL_ALLOW_SOCKETS_AFTER_PANELS
@ NODE_INTERFACE_SOCKET_HIDE_IN_MODIFIER
@ NODE_INTERFACE_SOCKET_HIDE_VALUE
@ NODE_VECTOR_MATH_ABSOLUTE
#define SHD_SHEEN_ASHIKHMIN
@ SHD_NOISE_FBM
@ SHD_NOISE_MULTIFRACTAL
@ SHD_NOISE_RIDGED_MULTIFRACTAL
@ SHD_NOISE_HETERO_TERRAIN
@ NODE_MATH_POWER
@ NODE_MATH_MINIMUM
@ NODE_MATH_GREATER_THAN
@ NODE_MATH_ADD
@ NODE_MATH_MAXIMUM
@ NODE_MATH_MULTIPLY
@ NODE_MATH_SUBTRACT
@ GEO_NODE_ASSET_MODIFIER
@ SHD_MATH_CLAMP
@ SHD_OUTPUT_CYCLES
@ SHD_OUTPUT_ALL
@ SHD_OUTPUT_EEVEE
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
@ NODE_HIDDEN
@ NODE_PREVIEW
@ SHD_PRINCIPLED_HAIR_CHIANG
@ CMP_NODE_MAP_UV_FILTERING_ANISOTROPIC
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
@ NTREE_UNUSED_2
@ SHD_GLOSSY_SHARP_DEPRECATED
@ SHD_GLOSSY_GGX
@ SHD_VECT_TRANSFORM_TYPE_NORMAL
@ SOCK_HIDE_VALUE
@ SOCK_HIDE_IN_MODIFIER
@ SOCK_HIDDEN
@ NTREE_CUSTOM
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
@ NODE_CLAMP_MINMAX
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_ROTATION
@ SOCK_RGBA
@ OB_HIDE_SHADOW
@ OB_FONT
@ OB_ARMATURE
@ OB_MESH
@ SCE_EEVEE_FAST_GI_ENABLED
@ SCE_EEVEE_VOLUME_CUSTOM_RANGE
@ SCE_EEVEE_MOTION_BLUR_ENABLED_DEPRECATED
@ RAYTRACE_EEVEE_METHOD_SCREEN
#define SCE_SNAP_TO_GEOM
@ R_IMF_IMTYPE_FFMPEG
@ R_IMF_IMTYPE_AVIJPEG
@ R_IMF_IMTYPE_AVIRAW
@ R_IMF_IMTYPE_OPENEXR
@ R_IMF_IMTYPE_MULTILAYER
@ R_MBLUR
@ SEQ_SNAP_TO_MARKERS
@ SEQ_SNAP_TO_PREVIEW_CENTER
@ SEQ_SNAP_TO_STRIPS_PREVIEW
@ SEQ_SNAP_TO_PREVIEW_BORDERS
@ RAYTRACE_EEVEE_USE_DENOISE
#define MAXFRAMEF
@ R_FILTER_FAST_GAUSS
#define SCE_SNAP_TO_VERTEX
@ SCE_SNAP
@ SCE_NLA_EDIT_ON
@ SCE_COMPOSITOR_DEVICE_GPU
@ SCE_MB_START
@ SCE_MB_END
@ SCE_MB_CENTER
#define MINAFRAMEF
@ RAYTRACE_EEVEE_DENOISE_BILATERAL
@ RAYTRACE_EEVEE_DENOISE_SPATIAL
@ RAYTRACE_EEVEE_DENOISE_TEMPORAL
@ SCE_SNAP_INDIVIDUAL_NEAREST
@ SCE_SNAP_TO_NODE_X
@ SCE_SNAP_TO_EDGE
@ SCE_SNAP_TO_FACE
@ SCE_SNAP_TO_MARKERS
@ SCE_SNAP_INDIVIDUAL_PROJECT
@ SCE_SNAP_TO_INCREMENT
@ SCE_SNAP_TO_GRID
@ SCE_SNAP_TO_EDGE_MIDPOINT
@ SCE_SNAP_TO_FRAME
@ SCE_SNAP_TO_SECOND
@ SCE_SNAP_TO_VOLUME
@ SCE_SNAP_TO_EDGE_PERPENDICULAR
@ SCE_SNAP_TO_NODE_Y
@ SCE_SNAP_TO_NONE
@ RGN_ALIGN_HIDE_WITH_PREV
@ RGN_ALIGN_BOTTOM
@ RGN_SPLIT_PREV
@ RGN_FLAG_DYNAMIC_SIZE
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_NO_USER_RESIZE
@ RGN_TYPE_TOOL_HEADER
@ RGN_TYPE_ASSET_SHELF_HEADER
@ RGN_TYPE_WINDOW
@ RGN_TYPE_ASSET_SHELF
@ RGN_TYPE_TOOLS
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_TEXT
@ SEQ_CACHE_UNUSED_8
@ SEQ_CACHE_UNUSED_5
@ SEQ_CACHE_UNUSED_7
@ SEQ_CACHE_UNUSED_6
@ SEQ_CACHE_UNUSED_9
@ seqModifierType_HueCorrect
@ SEQ_EDIT_SHOW_MISSING_MEDIA
@ SEQ_TRANSFORM_FILTER_AUTO
@ SEQ_TRANSFORM_FILTER_BILINEAR
@ SN_OVERLAY_SHOW_PREVIEWS
@ SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS
@ SNODE_FLAG_UNUSED_5
@ SPACE_CLIP
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ SEQ_TIMELINE_SHOW_STRIP_RETIMING
@ SEQ_CACHE_SHOW_FINAL_OUT
@ SI_MODE_PAINT
#define USER_EXPERIMENTAL_TEST(userdef, member)
@ V2D_VIEWSYNC_SCREEN_TIME
@ V3D_SHOW_CAMERA_PASSEPARTOUT
@ V3D_SHOW_CAMERA_GUIDES
@ WO_USE_SUN_SHADOW
@ WO_USE_EEVEE_FINITE_VOLUME
@ LIGHT_PROBE_RESOLUTION_1024
@ IMB_TC_RECORD_RUN
#define MEM_SAFE_FREE(v)
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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 world
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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
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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves 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 Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular Similar to the Principled BSDF node but uses the specular workflow instead of metallic
@ PROP_DISTANCE
Definition RNA_types.hh:159
@ PROP_NONE
Definition RNA_types.hh:136
#define U
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
#define output
static T sum(const btAlignedObjectArray< T > &items)
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr bool is_empty() const
Definition BLI_span.hh:261
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:484
Value & lookup_or_add_default(const Key &key)
Definition BLI_map.hh:601
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
ValueIterator values() const
Definition BLI_map.hh:846
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
ItemIterator items() const
Definition BLI_map.hh:864
constexpr T * data() const
Definition BLI_span.hh:540
constexpr MutableSpan drop_front(const int64_t n) const
Definition BLI_span.hh:608
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:630
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr bool startswith(StringRef prefix) const
constexpr bool endswith(StringRef suffix) const
constexpr const char * data() const
constexpr const char * c_str() const
constexpr StringRef drop_known_prefix(StringRef prefix) const
int64_t size() const
void append(const T &value)
const Slot * slot(int64_t index) const
void slot_name_set(Main &bmain, Slot &slot, StringRefNull new_name)
Layer & layer_add(std::optional< StringRefNull > name)
std::string name_prefix_for_idtype() const
StringRefNull name_without_prefix() const
const T & data(const Action &owning_action) const
MutableSpan< float > radii_for_write()
local_group_size(16, 16) .push_constant(Type b
#define printf
ListBase engines
KDTree_3d * tree
draw_view in_light_buf[] float
#define mix(a, b, c)
Definition hash.h:36
#define GS(x)
Definition iris.cc:202
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:43
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float3 ceil(const float3 a)
bool foreach_action_slot_use_with_references(ID &animated_id, FunctionRef< bool(bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name)> callback)
static void ANIM_armature_foreach_bone(ListBase *bones, CB callback)
ActionSlotAssignmentResult generic_assign_action_slot(Slot *slot_to_assign, ID &animated_id, bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name) ATTR_WARN_UNUSED_RESULT
decltype(::ActionSlot::handle) slot_handle_t
constexpr float LEGACY_RADIUS_CONVERSION_FACTOR
void node_modify_socket_type_static(bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype)
Definition node.cc:2082
void mesh_sculpt_mask_to_generic(Mesh &mesh)
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
FileHandlerType * file_handler_find(StringRef idname)
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
bNodeSocket * node_add_static_socket(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, int type, int subtype, const char *identifier, const char *name)
Definition node.cc:2359
bNode * node_add_node(const bContext *C, bNodeTree *ntree, const char *idname)
Definition node.cc:2617
void node_remove_socket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
Definition node.cc:2405
void node_remove_link(bNodeTree *ntree, bNodeLink *link)
Definition node.cc:2958
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
float wrap(float value, float max, float min)
Definition node_math.h:71
const char * RE_engine_id_CYCLES
Definition scene.cc:1612
const char * RE_engine_id_BLENDER_EEVEE_NEXT
Definition scene.cc:1610
const char * RE_engine_id_BLENDER_WORKBENCH
Definition scene.cc:1611
const char * RE_engine_id_BLENDER_EEVEE
Definition scene.cc:1609
SequencerToolSettings * SEQ_tool_settings_ensure(Scene *scene)
Definition sequencer.cc:358
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
closure color sheen(normal N, float roughness) BUILTIN
unsigned char uint8_t
Definition stdint.h:78
signed char int8_t
Definition stdint.h:75
MutableSpan< SeqRetimingKey > SEQ_retiming_keys_get(const Sequence *seq)
int SEQ_retiming_keys_count(const Sequence *seq)
bool SEQ_retiming_is_allowed(const Sequence *seq)
void SEQ_retiming_data_ensure(Sequence *seq)
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
struct FCurve ** fcurve_array
struct bActionGroup ** group_array
blender::animrig::slot_handle_t * slot_handle
bAction ** action_ptr_ptr
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
NlaStrip * actstrip
NlaTrack * act_track
ListBase drivers
AssetLibraryReference asset_library_reference
AssetShelfSettings settings
short preferred_row_count
struct BlendFileReadReport::@021165340246256112273314140153222370140145060352 count
ThemeWireColor custom
float automasking_view_normal_limit
float automasking_start_normal_limit
float automasking_start_normal_falloff
float automasking_view_normal_falloff
char panorama_type
float latitude_max
float central_cylindrical_range_v_min
float fisheye_polynomial_k3
float longitude_max
float central_cylindrical_range_u_min
float fisheye_polynomial_k1
float central_cylindrical_range_u_max
float latitude_min
float fisheye_polynomial_k2
float central_cylindrical_radius
float fisheye_fov
float fisheye_polynomial_k0
float fisheye_polynomial_k4
float fisheye_lens
float central_cylindrical_range_v_max
float longitude_min
CustomData curve_data
CustomDataLayer * layers
char * rna_path
BlendFileReadReport * reports
Definition readfile.hh:149
SDNA * filesdna
Definition readfile.hh:87
struct CurveMapping curve_mapping
ListBase group
Definition DNA_ID.h:146
IDPropertyData data
Definition DNA_ID.h:168
char type
Definition DNA_ID.h:154
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
ColorManagedColorspaceSettings linear_colorspace_settings
float shadow_jitter_overblur
void * first
ListBase lightprobes
Definition BKE_main.hh:229
ListBase brushes
Definition BKE_main.hh:235
ListBase scenes
Definition BKE_main.hh:210
ListBase grease_pencils
Definition BKE_main.hh:241
ListBase actions
Definition BKE_main.hh:233
ListBase meshes
Definition BKE_main.hh:213
ListBase movieclips
Definition BKE_main.hh:242
ListBase hair_curves
Definition BKE_main.hh:251
ListBase lights
Definition BKE_main.hh:220
ListBase nodetrees
Definition BKE_main.hh:234
ListBase particles
Definition BKE_main.hh:236
ListBase materials
Definition BKE_main.hh:216
ListBase cameras
Definition BKE_main.hh:221
ListBase armatures
Definition BKE_main.hh:232
ListBase curves
Definition BKE_main.hh:214
ListBase worlds
Definition BKE_main.hh:224
ListBase screens
Definition BKE_main.hh:225
short versionfile
Definition BKE_main.hh:137
ListBase workspaces
Definition BKE_main.hh:246
ListBase collections
Definition BKE_main.hh:231
ListBase objects
Definition BKE_main.hh:212
struct bNodeTree * nodetree
struct MovieTracking tracking
MovieTrackingPlaneTrack * active_plane_track
MovieTrackingReconstruction reconstruction
MovieTrackingTrack * active_track
struct MovieReconstructedCamera * cameras
MovieTrackingPlaneTrack * act_plane_track_legacy
MovieTrackingReconstruction reconstruction_legacy
ListBase plane_tracks_legacy
MovieTrackingTrack * act_track_legacy
NodeGeometryAttributeCaptureItem * capture_items
ImageFormatData format
short visibility_flag
int num_input_samples_deprecated
AssetShelf * active_shelf
struct ImageFormatData im_format
float fast_gi_thickness_near
float shadow_resolution_scale
float fast_gi_thickness_far
struct RenderData r
struct SceneEEVEE eevee
int automasking_boundary_edges_propagation_steps
SpaceNodeOverlay overlay
struct SequencerCacheOverlay cache_overlay
struct SequencerTimelineOverlay timeline_overlay
GpWeightPaint * gp_weightpaint
struct ImagePaintSettings imapaint
GpSculptPaint * gp_sculptpaint
struct UnifiedPaintSettings unified_paint_settings
CurvesSculpt * curves_sculpt
GpVertexPaint * gp_vertexpaint
int8_t curve_preset
struct CurveMapping * strength_curve
float gpencil_grid_color[3]
float gpencil_grid_scale[2]
float gpencil_grid_offset[2]
View3DOverlay overlay
float sun_angle
float sun_shadow_maximum_resolution
float sun_shadow_filter_radius
float sun_threshold
ThemeWireColor cs
struct ActionChannelBag * channel_bag
ListBase curves
ListBase groups
IDProperty * prop
bNodeSocketRuntimeHandle * runtime
struct bNodeLink * link
char description[64]
char * default_attribute_name
void * default_value
char identifier[64]
char idname[64]
bNodeTreeInterfaceItem ** items_array
bNodeTreeInterfacePanel root_panel
bNodeTreeInterface tree_interface
ListBase nodes
ListBase links
int16_t custom1
float locy
float width
ListBase inputs
float height
struct bNode * parent
float locx
void * storage
char label[64]
ListBase outputs
int16_t type
int16_t custom2
ListBase chanbase
ListBase agroups
float xmax
float xmin
float ymax
float ymin
static bNode * add_node(const bContext *C, bNodeTree *ntree, const int type, const float locx, const float locy)
static void version_principled_bsdf_subsurface(bNodeTree *ntree)
static void versioning_node_hue_correct_set_wrappng(bNodeTree *ntree)
static void versioning_eevee_material_shadow_none(Material *material)
static void versioning_remove_microfacet_sharp_distribution(bNodeTree *ntree)
static void version_replace_velvet_sheen_node(bNodeTree *ntree)
static bool versioning_eevee_material_blend_mode_settings(bNodeTree *ntree, float threshold)
static void versioning_nodes_dynamic_sockets_2(bNodeTree &ntree)
static bool seq_text_data_update(Sequence *seq, void *)
static void versioning_replace_musgrave_texture_node(bNodeTree *ntree)
static void version_principled_bsdf_emission(bNodeTree *ntree)
void do_versions_after_linking_400(FileData *fd, Main *bmain)
static void version_nla_tweakmode_incomplete(Main *bmain)
static void version_socket_identifier_suffixes_for_dynamic_types(ListBase sockets, const char *separator, const std::optional< int > total=std::nullopt)
static void version_bonecollection_anim(FCurve *fcurve)
static void image_settings_avi_to_ffmpeg(Scene *scene)
static void version_node_group_split_socket(bNodeTreeInterface &tree_interface, bNodeTreeInterfaceSocket &socket, bNodeTreeInterfacePanel *parent, int position)
static void update_paint_modes_for_brush_assets(Main &bmain)
static void versioning_fix_socket_subtype_idnames(bNodeTree *ntree)
static void version_principled_bsdf_specular_tint(bNodeTree *ntree)
static void convert_grease_pencil_stroke_hardness_to_softness(GreasePencil *grease_pencil)
static bool versioning_convert_strip_speed_factor(Sequence *seq, void *user_data)
static bool seq_proxies_timecode_update(Sequence *seq, void *)
static void version_principled_bsdf_update_animdata(ID *owner_id, bNodeTree *ntree)
static void version_composite_nodetree_null_id(bNodeTree *ntree, Scene *scene)
static void fix_geometry_nodes_object_info_scale(bNodeTree &ntree)
static void version_bonelayers_to_bonecollections(Main *bmain)
static bool all_scenes_use(Main *bmain, const blender::Span< const char * > engines)
static void versioning_replace_legacy_glossy_node(bNodeTree *ntree)
static void add_image_editor_asset_shelf(Main &bmain)
static void change_input_socket_to_rotation_type(bNodeTree &ntree, bNode &node, bNodeSocket &socket)
static void version_vertex_weight_edit_preserve_threshold_exclusivity(Main *bmain)
static void version_principled_transmission_roughness(bNodeTree *ntree)
static bool seq_filter_bilinear_to_auto(Sequence *seq, void *)
static void version_principled_bsdf_rename_sockets(bNodeTree *ntree)
static bNodeTreeInterfaceItem * legacy_socket_move_to_interface(bNodeSocket &legacy_socket, const eNodeSocketInOut in_out)
static void version_legacy_actions_to_layered(Main *bmain)
static void version_replace_texcoord_normal_socket(bNodeTree *ntree)
static blender::StringRef legacy_socket_idname_to_socket_type(blender::StringRef idname)
static void versioning_node_group_sort_sockets_recursive(bNodeTreeInterfacePanel &panel)
static void versioning_update_noise_texture_node(bNodeTree *ntree)
static void hide_simulation_node_skip_socket_value(Main &bmain)
static void version_movieclips_legacy_camera_object(Main *bmain)
static void hue_correct_set_wrapping(CurveMapping *curve_mapping)
static void version_copy_socket(bNodeTreeInterfaceSocket &dst, const bNodeTreeInterfaceSocket &src, char *identifier)
static void version_principled_bsdf_coat(bNodeTree *ntree)
static void add_bevel_modifier_attribute_name_defaults(Main &bmain)
static AlphaSource versioning_eevee_alpha_source_get(bNodeSocket *socket, int depth=0)
static void enable_geometry_nodes_is_modifier(Main &bmain)
static void version_nodes_insert_item(bNodeTreeInterfacePanel &parent, bNodeTreeInterfaceSocket &socket, int position)
static void version_refraction_depth_to_thickness_value(bNodeTree *ntree, float thickness)
static void version_motion_tracking_legacy_camera_object(MovieClip &movieclip)
static void versioning_convert_node_tree_socket_lists_to_interface(bNodeTree *ntree)
void blo_do_versions_400(FileData *fd, Library *, Main *bmain)
#define SCE_SNAP_PROJECT
static void node_reroute_add_storage(bNodeTree &tree)
static void fix_built_in_curve_attribute_defaults(Main *bmain)
static bool seq_hue_correct_set_wrapping(Sequence *seq, void *)
static void versioning_replace_splitviewer(bNodeTree *ntree)
static void change_output_socket_to_rotation_type(bNodeTree &ntree, bNode &node, bNodeSocket &socket)
static void version_replace_principled_hair_model(bNodeTree *ntree)
static void versioning_eevee_shadow_settings(Object *object)
static void version_principled_bsdf_sheen(bNodeTree *ntree)
static void versioning_update_timecode(short int *tc)
static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
static void version_geometry_nodes_use_rotation_socket(bNodeTree &ntree)
static void convert_action_in_place(blender::animrig::Action &action)
static void versioning_nodes_dynamic_sockets(bNodeTree &ntree)
static int version_nodes_find_valid_insert_position_for_item(const bNodeTreeInterfacePanel &panel, const bNodeTreeInterfaceItem &item, const int initial_pos)
static void version_bonegroups_to_bonecollections(Main *bmain)
static void version_mesh_crease_generic(Main &bmain)
static void version_bonegroup_migrate_color(Main *bmain)
static void versioning_grease_pencil_stroke_radii_scaling(GreasePencil *grease_pencil)
bNode * version_eevee_output_node_get(bNodeTree *ntree, int16_t node_type)
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)
ARegion * do_versions_add_region_if_not_found(ListBase *regionbase, int region_type, const char *allocname, int link_after_region_type)
bNodeSocket & version_node_add_socket(bNodeTree &ntree, bNode &node, const eNodeSocketInOut in_out, const char *idname, const char *identifier)
void version_update_node_input(bNodeTree *ntree, FunctionRef< bool(bNode *)> check_node, const char *socket_identifier, FunctionRef< void(bNode *, bNodeSocket *)> update_input, FunctionRef< void(bNode *, bNodeSocket *, bNode *, bNodeSocket *)> update_input_link)
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)
bNode & version_node_add_empty(bNodeTree &ntree, const char *idname)
void version_node_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)
bNodeLink & version_node_add_link(bNodeTree &ntree, bNode &node_a, bNodeSocket &socket_a, bNode &node_b, bNodeSocket &socket_b)
float version_cycles_property_float(IDProperty *idprop, const char *name, float default_value)
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:138