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
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
200 foreach_action_slot_use_with_references(*id, callback);
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) {
216 const ActionSlotAssignmentResult result = generic_assign_action_slot(
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) {
223 case ActionSlotAssignmentResult::OK:
224 break;
225 case ActionSlotAssignmentResult::SlotNotSuitable:
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;
254 case ActionSlotAssignmentResult::SlotNotFromAction:
255 BLI_assert(!"SlotNotFromAction should not be returned here");
256 break;
257 case ActionSlotAssignmentResult::MissingAction:
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{
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) {
844 blender::bke::node_remove_link(ntree, alpha.socket->link);
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 {
855 *version_cycles_node_socket_float_value(alpha.socket) = value;
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;
865 blender::bke::node_remove_link(ntree, alpha.socket->link);
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
883 *version_cycles_node_socket_float_value(threshold_sock) = alpha.is_transparency ?
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
983static bool versioning_convert_strip_speed_factor(Sequence *seq, void *user_data)
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
993 SeqRetimingKey *last_key = &SEQ_retiming_keys_get(seq)[1];
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. */
1148 bmain, NTREE_SHADER, SH_NODE_SUBSURFACE_SCATTERING, 4, 1, 5);
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. */
1222 version_node_socket_index_animdata(bmain, NTREE_SHADER, SH_NODE_BSDF_PRINCIPLED, 7, 1, 30);
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. */
1283 BLI_listbase_clear(&tracking.tracks_legacy);
1284 BLI_listbase_clear(&tracking.plane_tracks_legacy);
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) {
1371 if (!ELEM(node->type, SH_NODE_BSDF_GLOSSY, SH_NODE_BSDF_GLASS, SH_NODE_BSDF_REFRACTION)) {
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;
1762 add_node->locx = node->locx;
1763 add_node->locy = node->locy + 160.0f;
1765 bNodeSocket *add_socket_A = static_cast<bNodeSocket *>(
1767 bNodeSocket *add_socket_B = static_cast<bNodeSocket *>(
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
1821 *version_cycles_node_socket_float_value(mul_socket_B) = *detail;
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;
1829 add_node->locx = node->locx;
1830 add_node->locy = node->locy + 80.0f;
1832 bNodeSocket *add_socket_A = static_cast<bNodeSocket *>(
1834 bNodeSocket *add_socket_B = static_cast<bNodeSocket *>(
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) {
2038 bNode *mix = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MIX);
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__);
2130 data->model = SHD_PRINCIPLED_HAIR_CHIANG;
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);
2336 blender::StringRef corrected_socket_type = legacy_socket_idname_to_socket_type(
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. */
2425 bNode *mix = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MIX);
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)) {
2457 bNode *mix = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MIX);
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. */
2590 socket.flag &= ~NODE_INTERFACE_SOCKET_INPUT;
2591 /* Copied socket becomes input. */
2592 csocket->flag &= ~NODE_INTERFACE_SOCKET_OUTPUT;
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) {
2805 transform->filter = SEQ_TRANSFORM_FILTER_AUTO;
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 (tref->space_type != SPACE_VIEW3D) {
2821 continue;
2822 }
2823 if (!ELEM(tref->mode,
2837 {
2838 continue;
2839 }
2840 STRNCPY(tref->idname, "builtin.brush");
2841 }
2842 }
2843}
2844
2846{
2847 if (ELEM(scene->r.im_format.imtype, R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG)) {
2848 scene->r.im_format.imtype = R_IMF_IMTYPE_FFMPEG;
2849 }
2850}
2851
2852/* The Hue Correct curve now wraps around by specifying CUMA_USE_WRAPPING, which means it no longer
2853 * makes sense to have curve maps outside of the [0, 1] range, so enable clipping and reset the
2854 * clip and view ranges. */
2855static void hue_correct_set_wrapping(CurveMapping *curve_mapping)
2856{
2857 curve_mapping->flag |= CUMA_DO_CLIP;
2858 curve_mapping->flag |= CUMA_USE_WRAPPING;
2859
2860 curve_mapping->clipr.xmin = 0.0f;
2861 curve_mapping->clipr.xmax = 1.0f;
2862 curve_mapping->clipr.ymin = 0.0f;
2863 curve_mapping->clipr.ymax = 1.0f;
2864
2865 curve_mapping->curr.xmin = 0.0f;
2866 curve_mapping->curr.xmax = 1.0f;
2867 curve_mapping->curr.ymin = 0.0f;
2868 curve_mapping->curr.ymax = 1.0f;
2869}
2870
2871static bool seq_hue_correct_set_wrapping(Sequence *seq, void * /*user_data*/)
2872{
2874 if (smd->type == seqModifierType_HueCorrect) {
2876 CurveMapping *cumap = (CurveMapping *)&hcmd->curve_mapping;
2878 }
2879 }
2880 return true;
2881}
2882
2883static void versioning_update_timecode(short int *tc)
2884{
2885 /* 2 = IMB_TC_FREE_RUN, 4 = IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN. */
2886 if (ELEM(*tc, 2, 4)) {
2887 *tc = IMB_TC_RECORD_RUN;
2888 }
2889}
2890
2891static bool seq_proxies_timecode_update(Sequence *seq, void * /*user_data*/)
2892{
2893 if (seq->strip == nullptr || seq->strip->proxy == nullptr) {
2894 return true;
2895 }
2896 StripProxy *proxy = seq->strip->proxy;
2898 return true;
2899}
2900
2901static bool seq_text_data_update(Sequence *seq, void * /*user_data*/)
2902{
2903 if (seq->type != SEQ_TYPE_TEXT || seq->effectdata == nullptr) {
2904 return true;
2905 }
2906
2907 TextVars *data = static_cast<TextVars *>(seq->effectdata);
2908 if (data->shadow_angle == 0.0f) {
2909 data->shadow_angle = DEG2RADF(65.0f);
2910 data->shadow_offset = 0.04f;
2911 data->shadow_blur = 0.0f;
2912 }
2913 if (data->outline_width == 0.0f) {
2914 data->outline_color[3] = 0.7f;
2915 data->outline_width = 0.05f;
2916 }
2917 return true;
2918}
2919
2921{
2922 if (ntree->type == NTREE_COMPOSIT) {
2923 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
2924
2925 if (node->type == CMP_NODE_HUECORRECT) {
2926 CurveMapping *cumap = (CurveMapping *)node->storage;
2928 }
2929 }
2930 }
2931}
2932
2934{
2935 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
2936 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2937 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
2938 if (sl->spacetype != SPACE_IMAGE) {
2939 continue;
2940 }
2941
2942 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
2943
2944 if (ARegion *new_shelf_region = do_versions_add_region_if_not_found(
2945 regionbase, RGN_TYPE_ASSET_SHELF, __func__, RGN_TYPE_TOOL_HEADER))
2946 {
2947 new_shelf_region->regiondata = MEM_cnew<RegionAssetShelf>(__func__);
2948 new_shelf_region->alignment = RGN_ALIGN_BOTTOM;
2949 new_shelf_region->flag |= RGN_FLAG_HIDDEN;
2950 }
2951 if (ARegion *new_shelf_header = do_versions_add_region_if_not_found(
2952 regionbase, RGN_TYPE_ASSET_SHELF_HEADER, __func__, RGN_TYPE_ASSET_SHELF))
2953 {
2954 new_shelf_header->alignment = RGN_ALIGN_BOTTOM | RGN_ALIGN_HIDE_WITH_PREV;
2955 }
2956 }
2957 }
2958 }
2959}
2960
2962{
2963 for (bNode *node : tree.all_nodes()) {
2964 if (node->is_reroute()) {
2965 if (node->storage != nullptr) {
2966 continue;
2967 }
2968
2969 bNodeSocket &input = *static_cast<bNodeSocket *>(node->inputs.first);
2970 bNodeSocket &output = *static_cast<bNodeSocket *>(node->outputs.first);
2971
2972 /* Use uniform identifier for sockets. In old Blender versions (<=2021, up to af0b7925), the
2973 * identifiers were sometimes all lower case. Fixing those wrong socket identifiers is
2974 * important because otherwise they loose links now that the reroute node also uses node
2975 * declarations. */
2976 STRNCPY(input.identifier, "Input");
2977 STRNCPY(output.identifier, "Output");
2978
2979 NodeReroute *data = MEM_cnew<NodeReroute>(__func__);
2980 STRNCPY(data->type_idname, input.idname);
2981 node->storage = data;
2982 }
2983 }
2984}
2985
2991{
2992 LISTBASE_FOREACH (Curves *, curves, &bmain->hair_curves) {
2993 const int curves_num = curves->geometry.curve_num;
2994 if (int *resolutions = static_cast<int *>(CustomData_get_layer_named_for_write(
2995 &curves->geometry.curve_data, CD_PROP_INT32, "resolution", curves_num)))
2996 {
2997 for (int &resolution : blender::MutableSpan{resolutions, curves_num}) {
2998 resolution = std::max(resolution, 1);
2999 }
3000 }
3001 if (int8_t *nurb_orders = static_cast<int8_t *>(CustomData_get_layer_named_for_write(
3002 &curves->geometry.curve_data, CD_PROP_INT8, "nurbs_order", curves_num)))
3003 {
3004 for (int8_t &nurbs_order : blender::MutableSpan{nurb_orders, curves_num}) {
3005 nurbs_order = std::max<int8_t>(nurbs_order, 1);
3006 }
3007 }
3008 }
3009}
3010
3012{
3013 LISTBASE_FOREACH (Object *, ob, &bmain.objects) {
3014 if (ob->type != OB_MESH) {
3015 continue;
3016 }
3017 LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
3018 if (md->type == eModifierType_Bevel) {
3019 BevelModifierData *bmd = reinterpret_cast<BevelModifierData *>(md);
3020 if (bmd->vertex_weight_name[0] == '\0') {
3021 STRNCPY(bmd->vertex_weight_name, "bevel_weight_vert");
3022 }
3023 if (bmd->edge_weight_name[0] == '\0') {
3024 STRNCPY(bmd->edge_weight_name, "bevel_weight_edge");
3025 }
3026 }
3027 }
3028 }
3029}
3030
3032{
3034 LISTBASE_FOREACH (bNode *, node, &tree->nodes) {
3035 if (node->type != GEO_NODE_SIMULATION_OUTPUT) {
3036 continue;
3037 }
3038 bNodeSocket *skip_input = static_cast<bNodeSocket *>(node->inputs.first);
3039 if (!skip_input || !STREQ(skip_input->identifier, "Skip")) {
3040 continue;
3041 }
3042 auto *default_value = static_cast<bNodeSocketValueBoolean *>(skip_input->default_value);
3043 if (!default_value->value) {
3044 continue;
3045 }
3046 bool is_linked = false;
3047 LISTBASE_FOREACH (bNodeLink *, link, &tree->links) {
3048 if (link->tosock == skip_input) {
3049 is_linked = true;
3050 }
3051 }
3052 if (is_linked) {
3053 continue;
3054 }
3055
3056 bNode &input_node = version_node_add_empty(*tree, "FunctionNodeInputBool");
3057 input_node.parent = node->parent;
3058 input_node.locx = node->locx - 25;
3059 input_node.locy = node->locy;
3060
3061 NodeInputBool *input_node_storage = MEM_cnew<NodeInputBool>(__func__);
3062 input_node.storage = input_node_storage;
3063 input_node_storage->boolean = true;
3064
3065 bNodeSocket &input_node_socket = version_node_add_socket(
3066 *tree, input_node, SOCK_OUT, "NodeSocketBool", "Boolean");
3067
3068 version_node_add_link(*tree, input_node, input_node_socket, *node, *skip_input);
3069
3070 /* Change the old socket value so that the versioning code is not run again. */
3071 default_value->value = false;
3072 }
3073 }
3074}
3075
3076void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
3077{
3078 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
3079 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
3081 }
3083 }
3084
3085 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 2)) {
3086 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
3088 }
3089 }
3090
3091 /* 400 4 did not require any do_version here. */
3092
3093 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 5)) {
3094 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3095 ToolSettings *ts = scene->toolsettings;
3096 if (ts->snap_mode_tools != SCE_SNAP_TO_NONE) {
3098 }
3099
3100#define SCE_SNAP_PROJECT (1 << 3)
3101 if (ts->snap_flag & SCE_SNAP_PROJECT) {
3102 ts->snap_mode &= ~(1 << 2); /* SCE_SNAP_TO_FACE */
3103 ts->snap_mode |= (1 << 8); /* SCE_SNAP_INDIVIDUAL_PROJECT */
3104 }
3105#undef SCE_SNAP_PROJECT
3106 }
3107 }
3108
3109 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 6)) {
3110 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3113 }
3115 }
3116
3117 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 7)) {
3119 }
3120
3121 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 8)) {
3122 LISTBASE_FOREACH (bAction *, act, &bmain->actions) {
3123 act->frame_start = max_ff(act->frame_start, MINAFRAMEF);
3124 act->frame_end = min_ff(act->frame_end, MAXFRAMEF);
3125 }
3126 }
3127
3128 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) {
3129 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
3130 if (light->type == LA_SPOT && light->nodetree) {
3132 }
3133 }
3134 }
3135
3136 /* Fix brush->tip_scale_x which should never be zero. */
3137 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
3138 if (brush->tip_scale_x == 0.0f) {
3139 brush->tip_scale_x = 1.0f;
3140 }
3141 }
3142
3143 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 10)) {
3144 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3145 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3146 LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
3147 if (space->spacetype == SPACE_NODE) {
3148 SpaceNode *snode = reinterpret_cast<SpaceNode *>(space);
3150 }
3151 }
3152 }
3153 }
3154 }
3155
3156 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 11)) {
3158 }
3159
3160 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 12)) {
3161 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "int", "grid_bake_samples")) {
3162 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
3163 lightprobe->grid_bake_samples = 2048;
3164 lightprobe->grid_normal_bias = 0.3f;
3165 lightprobe->grid_view_bias = 0.0f;
3166 lightprobe->grid_facing_bias = 0.5f;
3167 lightprobe->grid_dilation_threshold = 0.5f;
3168 lightprobe->grid_dilation_radius = 1.0f;
3169 }
3170 }
3171
3172 /* Set default bake resolution. */
3173 if (!DNA_struct_member_exists(fd->filesdna, "World", "int", "probe_resolution")) {
3174 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
3175 world->probe_resolution = LIGHT_PROBE_RESOLUTION_1024;
3176 }
3177 }
3178
3179 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "float", "grid_surface_bias")) {
3180 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
3181 lightprobe->grid_surface_bias = 0.05f;
3182 lightprobe->grid_escape_bias = 0.1f;
3183 }
3184 }
3185
3186 /* Clear removed "Z Buffer" flag. */
3187 {
3188 const int R_IMF_FLAG_ZBUF_LEGACY = 1 << 0;
3189 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3190 scene->r.im_format.flag &= ~R_IMF_FLAG_ZBUF_LEGACY;
3191 }
3192 }
3193
3194 /* Reset the layer opacity for all layers to 1. */
3195 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
3196 for (blender::bke::greasepencil::Layer *layer : grease_pencil->layers_for_write()) {
3197 layer->opacity = 1.0f;
3198 }
3199 }
3200
3201 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3202 if (ntree->type == NTREE_SHADER) {
3203 /* Remove Transmission Roughness from Principled BSDF. */
3205 /* Convert legacy Velvet BSDF nodes into the new Sheen BSDF node. */
3207 /* Convert sheen inputs on the Principled BSDF. */
3209 }
3210 }
3212
3213 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3214 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3215 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3216 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3217 &sl->regionbase;
3218
3219 /* Layout based regions used to also disallow resizing, now these are separate flags.
3220 * Make sure they are set together for old regions. */
3221 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3222 if (region->flag & RGN_FLAG_DYNAMIC_SIZE) {
3223 region->flag |= RGN_FLAG_NO_USER_RESIZE;
3224 }
3225 }
3226 }
3227 }
3228 }
3229 }
3230
3231 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 13)) {
3232 /* For the scenes configured to use the "None" display disable the color management
3233 * again. This will handle situation when the "None" display is removed and is replaced with
3234 * a "Raw" view instead.
3235 *
3236 * Note that this versioning will do nothing if the "None" display exists in the OCIO
3237 * configuration. */
3238 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3239 const ColorManagedDisplaySettings &display_settings = scene->display_settings;
3240 if (STREQ(display_settings.display_device, "None")) {
3242 }
3243 }
3244 }
3245
3246 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 14)) {
3247 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "ray_tracing_method")) {
3248 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3249 scene->eevee.ray_tracing_method = RAYTRACE_EEVEE_METHOD_SCREEN;
3250 }
3251 }
3252
3253 if (!DNA_struct_exists(fd->filesdna, "RegionAssetShelf")) {
3254 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3255 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3256 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3257 if (sl->spacetype != SPACE_VIEW3D) {
3258 continue;
3259 }
3260
3261 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3262 &sl->regionbase;
3263
3264 if (ARegion *new_shelf_region = do_versions_add_region_if_not_found(
3265 regionbase,
3267 "asset shelf for view3d (versioning)",
3269 {
3270 new_shelf_region->alignment = RGN_ALIGN_BOTTOM;
3271 }
3272 if (ARegion *new_shelf_header = do_versions_add_region_if_not_found(
3273 regionbase,
3275 "asset shelf header for view3d (versioning)",
3277 {
3278 new_shelf_header->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
3279 }
3280 }
3281 }
3282 }
3283 }
3284 }
3285
3286 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 16)) {
3287 /* Set Normalize property of Noise Texture node to true. */
3288 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3289 if (ntree->type != NTREE_CUSTOM) {
3290 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3291 if (node->type == SH_NODE_TEX_NOISE) {
3292 ((NodeTexNoise *)node->storage)->normalize = true;
3293 }
3294 }
3295 }
3296 }
3298 }
3299
3300 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 17)) {
3301 if (!DNA_struct_exists(fd->filesdna, "NodeShaderHairPrincipled")) {
3302 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3303 if (ntree->type == NTREE_SHADER) {
3305 }
3306 }
3308 }
3309
3310 /* Panorama properties shared with Eevee. */
3311 if (!DNA_struct_member_exists(fd->filesdna, "Camera", "float", "fisheye_fov")) {
3312 Camera default_cam = *DNA_struct_default_get(Camera);
3313 LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
3314 IDProperty *ccam = version_cycles_properties_from_ID(&camera->id);
3315 if (ccam) {
3316 camera->panorama_type = version_cycles_property_int(
3317 ccam, "panorama_type", default_cam.panorama_type);
3318 camera->fisheye_fov = version_cycles_property_float(
3319 ccam, "fisheye_fov", default_cam.fisheye_fov);
3320 camera->fisheye_lens = version_cycles_property_float(
3321 ccam, "fisheye_lens", default_cam.fisheye_lens);
3322 camera->latitude_min = version_cycles_property_float(
3323 ccam, "latitude_min", default_cam.latitude_min);
3324 camera->latitude_max = version_cycles_property_float(
3325 ccam, "latitude_max", default_cam.latitude_max);
3326 camera->longitude_min = version_cycles_property_float(
3327 ccam, "longitude_min", default_cam.longitude_min);
3328 camera->longitude_max = version_cycles_property_float(
3329 ccam, "longitude_max", default_cam.longitude_max);
3330 /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */
3331 camera->fisheye_polynomial_k0 = version_cycles_property_float(
3332 ccam, "fisheye_polynomial_k0", default_cam.fisheye_polynomial_k0);
3333 camera->fisheye_polynomial_k1 = version_cycles_property_float(
3334 ccam, "fisheye_polynomial_k1", default_cam.fisheye_polynomial_k1);
3335 camera->fisheye_polynomial_k2 = version_cycles_property_float(
3336 ccam, "fisheye_polynomial_k2", default_cam.fisheye_polynomial_k2);
3337 camera->fisheye_polynomial_k3 = version_cycles_property_float(
3338 ccam, "fisheye_polynomial_k3", default_cam.fisheye_polynomial_k3);
3339 camera->fisheye_polynomial_k4 = version_cycles_property_float(
3340 ccam, "fisheye_polynomial_k4", default_cam.fisheye_polynomial_k4);
3341 }
3342 else {
3343 camera->panorama_type = default_cam.panorama_type;
3344 camera->fisheye_fov = default_cam.fisheye_fov;
3345 camera->fisheye_lens = default_cam.fisheye_lens;
3346 camera->latitude_min = default_cam.latitude_min;
3347 camera->latitude_max = default_cam.latitude_max;
3348 camera->longitude_min = default_cam.longitude_min;
3349 camera->longitude_max = default_cam.longitude_max;
3350 /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */
3351 camera->fisheye_polynomial_k0 = default_cam.fisheye_polynomial_k0;
3352 camera->fisheye_polynomial_k1 = default_cam.fisheye_polynomial_k1;
3353 camera->fisheye_polynomial_k2 = default_cam.fisheye_polynomial_k2;
3354 camera->fisheye_polynomial_k3 = default_cam.fisheye_polynomial_k3;
3355 camera->fisheye_polynomial_k4 = default_cam.fisheye_polynomial_k4;
3356 }
3357 }
3358 }
3359
3360 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "float", "grid_flag")) {
3361 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
3362 /* Keep old behavior of baking the whole lighting. */
3365 }
3366 }
3367
3368 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "gi_irradiance_pool_size")) {
3369 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3370 scene->eevee.gi_irradiance_pool_size = 16;
3371 }
3372 }
3373
3374 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3375 scene->toolsettings->snap_flag_anim |= SCE_SNAP;
3376 scene->toolsettings->snap_anim_mode |= (1 << 10); /* SCE_SNAP_TO_FRAME */
3377 }
3378 }
3379
3380 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 20)) {
3381 /* Convert old socket lists into new interface items. */
3382 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3384 /* Clear legacy sockets after conversion.
3385 * Internal data pointers have been moved or freed already. */
3386 BLI_freelistN(&ntree->inputs_legacy);
3387 BLI_freelistN(&ntree->outputs_legacy);
3388 }
3390 }
3391 else {
3392 /* Legacy node tree sockets are created for forward compatibility,
3393 * but have to be freed after loading and versioning. */
3394 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3395 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, legacy_socket, &ntree->inputs_legacy) {
3396 MEM_SAFE_FREE(legacy_socket->default_attribute_name);
3397 MEM_SAFE_FREE(legacy_socket->default_value);
3398 if (legacy_socket->prop) {
3399 IDP_FreeProperty(legacy_socket->prop);
3400 }
3401 MEM_delete(legacy_socket->runtime);
3402 MEM_freeN(legacy_socket);
3403 }
3404 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, legacy_socket, &ntree->outputs_legacy) {
3405 MEM_SAFE_FREE(legacy_socket->default_attribute_name);
3406 MEM_SAFE_FREE(legacy_socket->default_value);
3407 if (legacy_socket->prop) {
3408 IDP_FreeProperty(legacy_socket->prop);
3409 }
3410 MEM_delete(legacy_socket->runtime);
3411 MEM_freeN(legacy_socket);
3412 }
3413 BLI_listbase_clear(&ntree->inputs_legacy);
3414 BLI_listbase_clear(&ntree->outputs_legacy);
3415 }
3417 }
3418
3419 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 22)) {
3420 /* Initialize root panel flags in files created before these flags were added. */
3421 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3422 ntree->tree_interface.root_panel.flag |= NODE_INTERFACE_PANEL_ALLOW_CHILD_PANELS;
3423 }
3425 }
3426
3427 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 23)) {
3428 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3429 if (ntree->type == NTREE_GEOMETRY) {
3430 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3431 if (node->type == GEO_NODE_SET_SHADE_SMOOTH) {
3432 node->custom1 = int8_t(blender::bke::AttrDomain::Face);
3433 }
3434 }
3435 }
3436 }
3437 }
3438
3439 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 24)) {
3440 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3441 if (ntree->type == NTREE_SHADER) {
3442 /* Convert coat inputs on the Principled BSDF. */
3444 /* Convert subsurface inputs on the Principled BSDF. */
3446 /* Convert emission on the Principled BSDF. */
3448 }
3449 }
3451
3452 {
3453 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3454 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3455 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3456 const ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3457 &sl->regionbase;
3458 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3459 if (region->regiontype != RGN_TYPE_ASSET_SHELF) {
3460 continue;
3461 }
3462
3463 RegionAssetShelf *shelf_data = static_cast<RegionAssetShelf *>(region->regiondata);
3464 if (shelf_data && shelf_data->active_shelf &&
3465 (shelf_data->active_shelf->preferred_row_count == 0))
3466 {
3467 shelf_data->active_shelf->preferred_row_count = 1;
3468 }
3469 }
3470 }
3471 }
3472 }
3473 }
3474
3475 /* Convert sockets with both input and output flag into two separate sockets. */
3476 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3478 ntree->tree_interface.foreach_item([&](bNodeTreeInterfaceItem &item) {
3479 if (item.item_type == NODE_INTERFACE_SOCKET) {
3480 bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
3481 if ((socket.flag & NODE_INTERFACE_SOCKET_INPUT) &&
3482 (socket.flag & NODE_INTERFACE_SOCKET_OUTPUT))
3483 {
3484 sockets_to_split.append(&socket);
3485 }
3486 }
3487 return true;
3488 });
3489
3490 for (bNodeTreeInterfaceSocket *socket : sockets_to_split) {
3491 const int position = ntree->tree_interface.find_item_position(socket->item);
3492 bNodeTreeInterfacePanel *parent = ntree->tree_interface.find_item_parent(socket->item);
3493 version_node_group_split_socket(ntree->tree_interface, *socket, parent, position + 1);
3494 }
3495 }
3497 }
3498
3499 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 25)) {
3500 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3501 if (ntree->type == NTREE_SHADER) {
3502 /* Convert specular tint on the Principled BSDF. */
3504 /* Rename some sockets. */
3506 }
3507 }
3509 }
3510
3511 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 26)) {
3513
3514 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3515 scene->simulation_frame_start = scene->r.sfra;
3516 scene->simulation_frame_end = scene->r.efra;
3517 }
3518 }
3519
3520 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 27)) {
3521 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3522 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3523 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3524 if (sl->spacetype == SPACE_SEQ) {
3525 SpaceSeq *sseq = (SpaceSeq *)sl;
3527 }
3528 }
3529 }
3530 }
3531
3532 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "shadow_step_count")) {
3533 SceneEEVEE default_scene_eevee = *DNA_struct_default_get(SceneEEVEE);
3534 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3535 scene->eevee.shadow_ray_count = default_scene_eevee.shadow_ray_count;
3536 scene->eevee.shadow_step_count = default_scene_eevee.shadow_step_count;
3537 }
3538 }
3539 }
3540
3541 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 28)) {
3542 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3543 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3544 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3545 const ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3546 &sl->regionbase;
3547 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3548 if (region->regiontype != RGN_TYPE_ASSET_SHELF) {
3549 continue;
3550 }
3551
3552 RegionAssetShelf *shelf_data = static_cast<RegionAssetShelf *>(region->regiondata);
3553 if (shelf_data && shelf_data->active_shelf) {
3554 AssetShelfSettings &settings = shelf_data->active_shelf->settings;
3556 settings.asset_library_reference.type = ASSET_LIBRARY_ALL;
3557 }
3558
3559 region->flag |= RGN_FLAG_HIDDEN;
3560 }
3561 }
3562 }
3563 }
3564 }
3565
3566 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 29)) {
3567 /* Unhide all Reroute nodes. */
3568 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3569 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3570 if (node->is_reroute()) {
3571 static_cast<bNodeSocket *>(node->inputs.first)->flag &= ~SOCK_HIDDEN;
3572 static_cast<bNodeSocket *>(node->outputs.first)->flag &= ~SOCK_HIDDEN;
3573 }
3574 }
3575 }
3577 }
3578
3579 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 30)) {
3580 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3581 ToolSettings *ts = scene->toolsettings;
3582 enum { IS_DEFAULT = 0, IS_UV, IS_NODE, IS_ANIM };
3583 auto versioning_snap_to = [](short snap_to_old, int type) {
3584 eSnapMode snap_to_new = SCE_SNAP_TO_NONE;
3585 if (snap_to_old & (1 << 0)) {
3586 snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NODE_X :
3587 type == IS_ANIM ? SCE_SNAP_TO_FRAME :
3589 }
3590 if (snap_to_old & (1 << 1)) {
3591 snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NODE_Y :
3592 type == IS_ANIM ? SCE_SNAP_TO_SECOND :
3594 }
3595 if (ELEM(type, IS_DEFAULT, IS_ANIM) && snap_to_old & (1 << 2)) {
3596 snap_to_new |= type == IS_DEFAULT ? SCE_SNAP_TO_FACE : SCE_SNAP_TO_MARKERS;
3597 }
3598 if (type == IS_DEFAULT && snap_to_old & (1 << 3)) {
3599 snap_to_new |= SCE_SNAP_TO_VOLUME;
3600 }
3601 if (type == IS_DEFAULT && snap_to_old & (1 << 4)) {
3602 snap_to_new |= SCE_SNAP_TO_EDGE_MIDPOINT;
3603 }
3604 if (type == IS_DEFAULT && snap_to_old & (1 << 5)) {
3605 snap_to_new |= SCE_SNAP_TO_EDGE_PERPENDICULAR;
3606 }
3607 if (ELEM(type, IS_DEFAULT, IS_UV, IS_NODE) && snap_to_old & (1 << 6)) {
3608 snap_to_new |= SCE_SNAP_TO_INCREMENT;
3609 }
3610 if (ELEM(type, IS_DEFAULT, IS_UV, IS_NODE) && snap_to_old & (1 << 7)) {
3611 snap_to_new |= SCE_SNAP_TO_GRID;
3612 }
3613 if (type == IS_DEFAULT && snap_to_old & (1 << 8)) {
3614 snap_to_new |= SCE_SNAP_INDIVIDUAL_NEAREST;
3615 }
3616 if (type == IS_DEFAULT && snap_to_old & (1 << 9)) {
3617 snap_to_new |= SCE_SNAP_INDIVIDUAL_PROJECT;
3618 }
3619 if (snap_to_old & (1 << 10)) {
3620 snap_to_new |= SCE_SNAP_TO_FRAME;
3621 }
3622 if (snap_to_old & (1 << 11)) {
3623 snap_to_new |= SCE_SNAP_TO_SECOND;
3624 }
3625 if (snap_to_old & (1 << 12)) {
3626 snap_to_new |= SCE_SNAP_TO_MARKERS;
3627 }
3628
3629 if (!snap_to_new) {
3630 snap_to_new = eSnapMode(1 << 0);
3631 }
3632
3633 return snap_to_new;
3634 };
3635
3636 ts->snap_mode = versioning_snap_to(ts->snap_mode, IS_DEFAULT);
3637 ts->snap_uv_mode = versioning_snap_to(ts->snap_uv_mode, IS_UV);
3638 ts->snap_node_mode = versioning_snap_to(ts->snap_node_mode, IS_NODE);
3639 ts->snap_anim_mode = versioning_snap_to(ts->snap_anim_mode, IS_ANIM);
3640 }
3641 }
3642
3643 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 31)) {
3644 LISTBASE_FOREACH (Curve *, curve, &bmain->curves) {
3645 const int curvetype = BKE_curve_type_get(curve);
3646 if (curvetype == OB_FONT) {
3647 CharInfo *info = curve->strinfo;
3648 if (info != nullptr) {
3649 for (int i = curve->len_char32 - 1; i >= 0; i--, info++) {
3650 if (info->mat_nr > 0) {
3652 info->mat_nr--;
3653 }
3654 }
3655 }
3656 }
3657 }
3658 }
3659
3660 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 33)) {
3661 /* Fix node group socket order by sorting outputs and inputs. */
3662 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3663 versioning_node_group_sort_sockets_recursive(ntree->tree_interface.root_panel);
3664 }
3665 }
3666
3667 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 1)) {
3668 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
3670 }
3671 }
3672
3673 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 4)) {
3674 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3675 if (ntree->type != NTREE_CUSTOM) {
3676 /* versioning_update_noise_texture_node must be done before
3677 * versioning_replace_musgrave_texture_node. */
3679
3680 /* Convert Musgrave Texture nodes to Noise Texture nodes. */
3682 }
3683 }
3685 }
3686
3687 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
3688 /* Unify Material::blend_shadow and Cycles.use_transparent_shadows into the
3689 * Material::blend_flag. */
3690 bool is_eevee = all_scenes_use(bmain,
3692 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
3693 bool transparent_shadows = true;
3694 if (is_eevee) {
3695 transparent_shadows = material->blend_shadow != MA_BS_SOLID;
3696 }
3697 else if (IDProperty *cmat = version_cycles_properties_from_ID(&material->id)) {
3698 transparent_shadows = version_cycles_property_boolean(
3699 cmat, "use_transparent_shadow", true);
3700 }
3701 SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW);
3702 }
3703 }
3704
3705 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
3707 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3708 if (ntree->type == NTREE_COMPOSIT) {
3710 }
3711 }
3713 }
3714
3715 /* 401 6 did not require any do_version here. */
3716
3717 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 7)) {
3718 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "volumetric_ray_depth")) {
3720 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3721 scene->eevee.volumetric_ray_depth = default_eevee.volumetric_ray_depth;
3722 }
3723 }
3724
3725 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "surface_render_method")) {
3726 LISTBASE_FOREACH (Material *, mat, &bmain->materials) {
3727 mat->surface_render_method = (mat->blend_method == MA_BM_BLEND) ?
3730 }
3731 }
3732
3733 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
3734 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3735 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
3736 const ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
3737 &sl->regionbase;
3738 LISTBASE_FOREACH (ARegion *, region, regionbase) {
3739 if (region->regiontype != RGN_TYPE_ASSET_SHELF_HEADER) {
3740 continue;
3741 }
3742 region->alignment &= ~RGN_SPLIT_PREV;
3743 region->alignment |= RGN_ALIGN_HIDE_WITH_PREV;
3744 }
3745 }
3746 }
3747 }
3748
3749 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "float", "gtao_thickness")) {
3751 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3752 scene->eevee.gtao_thickness = default_eevee.gtao_thickness;
3753 scene->eevee.gtao_focus = default_eevee.gtao_focus;
3754 }
3755 }
3756
3757 if (!DNA_struct_member_exists(fd->filesdna, "LightProbe", "float", "data_display_size")) {
3759 LISTBASE_FOREACH (LightProbe *, probe, &bmain->lightprobes) {
3760 probe->data_display_size = default_probe.data_display_size;
3761 }
3762 }
3763
3764 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
3765 mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
3766 }
3767 }
3768
3769 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 8)) {
3770 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3771 if (ntree->type != NTREE_GEOMETRY) {
3772 continue;
3773 }
3775 }
3776 }
3777
3778 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 9)) {
3779 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "displacement_method")) {
3780 /* Replace Cycles.displacement_method by Material::displacement_method. */
3781 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
3782 int displacement_method = MA_DISPLACEMENT_BUMP;
3783 if (IDProperty *cmat = version_cycles_properties_from_ID(&material->id)) {
3784 displacement_method = version_cycles_property_int(
3785 cmat, "displacement_method", MA_DISPLACEMENT_BUMP);
3786 }
3787 material->displacement_method = displacement_method;
3788 }
3789 }
3790
3791 /* Prevent custom bone colors from having alpha zero.
3792 * Part of the fix for issue #115434. */
3793 LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
3794 blender::animrig::ANIM_armature_foreach_bone(&arm->bonebase, [](Bone *bone) {
3795 bone->color.custom.solid[3] = 255;
3796 bone->color.custom.select[3] = 255;
3797 bone->color.custom.active[3] = 255;
3798 });
3799 if (arm->edbo) {
3800 LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
3801 ebone->color.custom.solid[3] = 255;
3802 ebone->color.custom.select[3] = 255;
3803 ebone->color.custom.active[3] = 255;
3804 }
3805 }
3806 }
3807 LISTBASE_FOREACH (Object *, obj, &bmain->objects) {
3808 if (obj->pose == nullptr) {
3809 continue;
3810 }
3811 LISTBASE_FOREACH (bPoseChannel *, pchan, &obj->pose->chanbase) {
3812 pchan->color.custom.solid[3] = 255;
3813 pchan->color.custom.select[3] = 255;
3814 pchan->color.custom.active[3] = 255;
3815 }
3816 }
3817 }
3818
3819 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 10)) {
3820 if (!DNA_struct_member_exists(
3821 fd->filesdna, "SceneEEVEE", "RaytraceEEVEE", "ray_tracing_options"))
3822 {
3823 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3824 scene->eevee.ray_tracing_options.flag = RAYTRACE_EEVEE_USE_DENOISE;
3825 scene->eevee.ray_tracing_options.denoise_stages = RAYTRACE_EEVEE_DENOISE_SPATIAL |
3828 scene->eevee.ray_tracing_options.screen_trace_quality = 0.25f;
3829 scene->eevee.ray_tracing_options.screen_trace_thickness = 0.2f;
3830 scene->eevee.ray_tracing_options.trace_max_roughness = 0.5f;
3831 scene->eevee.ray_tracing_options.resolution_scale = 2;
3832 }
3833 }
3834
3835 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3836 if (ntree->type == NTREE_GEOMETRY) {
3840 }
3841 }
3842 }
3843
3844 if (MAIN_VERSION_FILE_ATLEAST(bmain, 400, 20) && !MAIN_VERSION_FILE_ATLEAST(bmain, 401, 11)) {
3845 /* Convert old socket lists into new interface items. */
3846 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3848 }
3850 }
3851
3852 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 12)) {
3853 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3854 if (ntree->type == NTREE_COMPOSIT) {
3855 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3856 if (node->type == CMP_NODE_PIXELATE) {
3857 node->custom1 = 1;
3858 }
3859 }
3860 }
3861 }
3863 }
3864
3865 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 13)) {
3866 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3867 if (ntree->type == NTREE_COMPOSIT) {
3868 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3869 if (node->type == CMP_NODE_MAP_UV) {
3871 }
3872 }
3873 }
3874 }
3876 }
3877
3878 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 14)) {
3879 const Brush *default_brush = DNA_struct_default_get(Brush);
3880 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
3881 brush->automasking_start_normal_limit = default_brush->automasking_start_normal_limit;
3882 brush->automasking_start_normal_falloff = default_brush->automasking_start_normal_falloff;
3883
3884 brush->automasking_view_normal_limit = default_brush->automasking_view_normal_limit;
3885 brush->automasking_view_normal_falloff = default_brush->automasking_view_normal_falloff;
3886 }
3887 }
3888
3889 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 15)) {
3890 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
3891 if (ntree->type == NTREE_COMPOSIT) {
3892 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3893 if (node->type == CMP_NODE_KEYING) {
3894 NodeKeyingData &keying_data = *static_cast<NodeKeyingData *>(node->storage);
3895 keying_data.edge_kernel_radius = max_ii(keying_data.edge_kernel_radius - 1, 0);
3896 }
3897 }
3898 }
3899 }
3901 }
3902
3903 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 16)) {
3904 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3905 Sculpt *sculpt = scene->toolsettings->sculpt;
3906 if (sculpt != nullptr) {
3907 Sculpt default_sculpt = *DNA_struct_default_get(Sculpt);
3908 sculpt->automasking_boundary_edges_propagation_steps =
3910 }
3911 }
3912 }
3913
3914 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 17)) {
3915 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3916 ToolSettings *ts = scene->toolsettings;
3917 int input_sample_values[9];
3918
3919 input_sample_values[0] = ts->imapaint.paint.num_input_samples_deprecated;
3920 input_sample_values[1] = ts->sculpt != nullptr ?
3922 1;
3923 input_sample_values[2] = ts->curves_sculpt != nullptr ?
3925 1;
3926
3927 input_sample_values[3] = ts->gp_paint != nullptr ?
3929 1;
3930 input_sample_values[4] = ts->gp_vertexpaint != nullptr ?
3932 1;
3933 input_sample_values[5] = ts->gp_sculptpaint != nullptr ?
3935 1;
3936 input_sample_values[6] = ts->gp_weightpaint != nullptr ?
3938 1;
3939
3940 input_sample_values[7] = ts->vpaint != nullptr ?
3942 1;
3943 input_sample_values[8] = ts->wpaint != nullptr ?
3945 1;
3946
3947 int unified_value = 1;
3948 for (int i = 0; i < 9; i++) {
3949 if (input_sample_values[i] != 1) {
3950 if (unified_value == 1) {
3951 unified_value = input_sample_values[i];
3952 }
3953 else {
3954 /* In the case of a user having multiple tools with different num_input_value values
3955 * set we cannot support this in the single UnifiedPaintSettings value, so fallback
3956 * to 1 instead of deciding that one value is more canonical than the other.
3957 */
3958 break;
3959 }
3960 }
3961 }
3962
3963 ts->unified_paint_settings.input_samples = unified_value;
3964 }
3965 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
3966 brush->input_samples = 1;
3967 }
3968 }
3969
3970 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 18)) {
3971 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3972 if (scene->ed != nullptr) {
3973 SEQ_for_each_callback(&scene->ed->seqbase, seq_filter_bilinear_to_auto, nullptr);
3974 }
3975 }
3976 }
3977
3978 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 19)) {
3979 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
3980 if (ntree->type == NTREE_GEOMETRY) {
3981 version_node_socket_name(ntree, FN_NODE_ROTATE_ROTATION, "Rotation 1", "Rotation");
3982 version_node_socket_name(ntree, FN_NODE_ROTATE_ROTATION, "Rotation 2", "Rotate By");
3983 }
3984 }
3985 }
3986
3987 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 20)) {
3988 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
3989 int uid = 1;
3990 LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
3991 /* These identifiers are not necessarily stable for linked data. If the linked data has a
3992 * new modifier inserted, the identifiers of other modifiers can change. */
3993 md->persistent_uid = uid++;
3994 }
3995 }
3996 }
3997
3998 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 21)) {
3999 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4000 /* The `sculpt_flag` was used to store the `BRUSH_DIR_IN`
4001 * With the fix for #115313 this is now just using the `brush->flag`. */
4002 if (brush->gpencil_settings && (brush->gpencil_settings->sculpt_flag & BRUSH_DIR_IN) != 0) {
4003 brush->flag |= BRUSH_DIR_IN;
4004 }
4005 }
4006 }
4007
4008 /* Keep point/spot light soft falloff for files created before 4.0. */
4009 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 0)) {
4010 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4011 if (ELEM(light->type, LA_LOCAL, LA_SPOT)) {
4012 light->mode |= LA_USE_SOFT_FALLOFF;
4013 }
4014 }
4015 }
4016
4017 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 1)) {
4018 using namespace blender::bke::greasepencil;
4019 /* Initialize newly added scale layer transform to one. */
4020 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
4021 for (Layer *layer : grease_pencil->layers_for_write()) {
4022 copy_v3_fl(layer->scale, 1.0f);
4023 }
4024 }
4025 }
4026
4027 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 2)) {
4028 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4029 bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES);
4030 if (is_cycles) {
4031 if (IDProperty *cscene = version_cycles_properties_from_ID(&scene->id)) {
4032 int cposition = version_cycles_property_int(cscene, "motion_blur_position", 1);
4033 BLI_assert(cposition >= 0 && cposition < 3);
4034 int order_conversion[3] = {SCE_MB_START, SCE_MB_CENTER, SCE_MB_END};
4035 scene->r.motion_blur_position = order_conversion[std::clamp(cposition, 0, 2)];
4036 }
4037 }
4038 else {
4040 scene->r.mode, scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED_DEPRECATED, R_MBLUR);
4041 scene->r.motion_blur_position = scene->eevee.motion_blur_position_deprecated;
4042 scene->r.motion_blur_shutter = scene->eevee.motion_blur_shutter_deprecated;
4043 }
4044 }
4045 }
4046
4047 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 3)) {
4048 constexpr int NTREE_EXECUTION_MODE_CPU = 0;
4049 constexpr int NTREE_EXECUTION_MODE_FULL_FRAME = 1;
4050
4051 constexpr int NTREE_COM_GROUPNODE_BUFFER = 1 << 3;
4052 constexpr int NTREE_COM_OPENCL = 1 << 1;
4053
4054 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4055 if (ntree->type != NTREE_COMPOSIT) {
4056 continue;
4057 }
4058
4059 ntree->flag &= ~(NTREE_COM_GROUPNODE_BUFFER | NTREE_COM_OPENCL);
4060
4061 if (ntree->execution_mode == NTREE_EXECUTION_MODE_FULL_FRAME) {
4062 ntree->execution_mode = NTREE_EXECUTION_MODE_CPU;
4063 }
4064 }
4066 }
4067
4068 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 4)) {
4069 if (!DNA_struct_member_exists(fd->filesdna, "SpaceImage", "float", "stretch_opacity")) {
4070 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4071 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4072 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4073 if (sl->spacetype == SPACE_IMAGE) {
4074 SpaceImage *sima = reinterpret_cast<SpaceImage *>(sl);
4075 sima->stretch_opacity = 0.9f;
4076 }
4077 }
4078 }
4079 }
4080 }
4081 }
4082
4083 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 5)) {
4084 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4086 }
4087 }
4088
4089 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 6)) {
4090 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4091 if (BrushCurvesSculptSettings *settings = brush->curves_sculpt_settings) {
4093 settings->curve_radius = 0.01f;
4094 }
4095 }
4096 }
4097
4098 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 8)) {
4099 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4100 light->shadow_filter_radius = 1.0f;
4101 }
4102 }
4103
4104 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 9)) {
4105 const float default_snap_angle_increment = DEG2RADF(5.0f);
4106 const float default_snap_angle_increment_precision = DEG2RADF(1.0f);
4107 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4108 scene->toolsettings->snap_angle_increment_2d = default_snap_angle_increment;
4109 scene->toolsettings->snap_angle_increment_3d = default_snap_angle_increment;
4110 scene->toolsettings->snap_angle_increment_2d_precision =
4111 default_snap_angle_increment_precision;
4112 scene->toolsettings->snap_angle_increment_3d_precision =
4113 default_snap_angle_increment_precision;
4114 }
4115 }
4116
4117 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 10)) {
4118 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "int", "gtao_resolution")) {
4119 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4120 scene->eevee.gtao_resolution = 2;
4121 }
4122 }
4123 }
4124
4125 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 12)) {
4126 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4128 }
4130
4131 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4132 if (scene->ed != nullptr) {
4133 SEQ_for_each_callback(&scene->ed->seqbase, seq_hue_correct_set_wrapping, nullptr);
4134 }
4135 }
4136 }
4137
4138 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 14)) {
4139 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
4140 if (bMotionPath *mpath = ob->mpath) {
4141 mpath->color_post[0] = 0.1f;
4142 mpath->color_post[1] = 1.0f;
4143 mpath->color_post[2] = 0.1f;
4144 }
4145 if (!ob->pose) {
4146 continue;
4147 }
4148 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
4149 if (bMotionPath *mpath = pchan->mpath) {
4150 mpath->color_post[0] = 0.1f;
4151 mpath->color_post[1] = 1.0f;
4152 mpath->color_post[2] = 0.1f;
4153 }
4154 }
4155 }
4156 }
4157
4158 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 18)) {
4159 if (!DNA_struct_member_exists(fd->filesdna, "Light", "float", "transmission_fac")) {
4160 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4161 /* Refracted light was not supported in legacy EEVEE. Set it to zero for compatibility with
4162 * older files. */
4163 light->transmission_fac = 0.0f;
4164 }
4165 }
4166 }
4167
4168 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 19)) {
4169 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4170 /* Keep legacy EEVEE old behavior. */
4171 scene->eevee.flag |= SCE_EEVEE_VOLUME_CUSTOM_RANGE;
4172 }
4173
4174 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4175 scene->eevee.clamp_surface_indirect = 10.0f;
4176 /* Make contribution of indirect lighting very small (but non-null) to avoid world lighting
4177 * and volume lightprobe changing the appearance of volume objects. */
4178 scene->eevee.clamp_volume_indirect = 1e-8f;
4179 }
4180 }
4181
4182 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 20)) {
4183 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4184 SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
4185 sequencer_tool_settings->snap_mode |= SEQ_SNAP_TO_MARKERS;
4186 }
4187 }
4188
4189 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 21)) {
4191 }
4192
4193 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 22)) {
4194 /* Display missing media in sequencer by default. */
4195 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4196 if (scene->ed != nullptr) {
4197 scene->ed->show_missing_media_flag |= SEQ_EDIT_SHOW_MISSING_MEDIA;
4198 }
4199 }
4200 }
4201
4202 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 23)) {
4203 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4204 ToolSettings *ts = scene->toolsettings;
4205 if (!ts->uvsculpt.strength_curve) {
4206 ts->uvsculpt.size = 50;
4207 ts->uvsculpt.strength = 1.0f;
4209 ts->uvsculpt.strength_curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
4210 }
4211 }
4212 }
4213
4214 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 24)) {
4215 if (!DNA_struct_member_exists(fd->filesdna, "Material", "char", "thickness_mode")) {
4216 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
4217 if (material->blend_flag & MA_BL_TRANSLUCENCY) {
4218 /* EEVEE Legacy used thickness from shadow map when translucency was on. */
4219 material->blend_flag |= MA_BL_THICKNESS_FROM_SHADOW;
4220 }
4221 if ((material->blend_flag & MA_BL_SS_REFRACTION) && material->use_nodes &&
4222 material->nodetree)
4223 {
4224 /* EEVEE Legacy used slab assumption. */
4225 material->thickness_mode = MA_THICKNESS_SLAB;
4226 version_refraction_depth_to_thickness_value(material->nodetree, material->refract_depth);
4227 }
4228 }
4229 }
4230 }
4231
4232 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 25)) {
4233 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4234 if (ntree->type != NTREE_COMPOSIT) {
4235 continue;
4236 }
4237 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4238 if (node->type != CMP_NODE_BLUR) {
4239 continue;
4240 }
4241
4242 NodeBlurData &blur_data = *static_cast<NodeBlurData *>(node->storage);
4243
4244 if (blur_data.filtertype != R_FILTER_FAST_GAUSS) {
4245 continue;
4246 }
4247
4248 /* The size of the Fast Gaussian mode of blur decreased by the following factor to match
4249 * other blur sizes. So increase it back. */
4250 const float size_factor = 3.0f / 2.0f;
4251 blur_data.sizex *= size_factor;
4252 blur_data.sizey *= size_factor;
4253 blur_data.percentx *= size_factor;
4254 blur_data.percenty *= size_factor;
4255 }
4256 }
4258 }
4259
4260 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 26)) {
4261 if (!DNA_struct_member_exists(fd->filesdna, "SceneEEVEE", "float", "shadow_resolution_scale"))
4262 {
4263 SceneEEVEE default_scene_eevee = *DNA_struct_default_get(SceneEEVEE);
4264 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4265 scene->eevee.shadow_resolution_scale = default_scene_eevee.shadow_resolution_scale;
4266 }
4267 }
4268 }
4269
4270 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 27)) {
4271 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4272 if (scene->ed != nullptr) {
4273 scene->ed->cache_flag &= ~(SEQ_CACHE_UNUSED_5 | SEQ_CACHE_UNUSED_6 | SEQ_CACHE_UNUSED_7 |
4275 }
4276 }
4277 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4278 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4279 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4280 if (sl->spacetype == SPACE_SEQ) {
4281 SpaceSeq *sseq = (SpaceSeq *)sl;
4283 }
4284 }
4285 }
4286 }
4287 }
4288
4289 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 28)) {
4290 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4291 if (scene->ed != nullptr) {
4292 SEQ_for_each_callback(&scene->ed->seqbase, seq_proxies_timecode_update, nullptr);
4293 }
4294 }
4295
4296 LISTBASE_FOREACH (MovieClip *, clip, &bmain->movieclips) {
4297 MovieClipProxy proxy = clip->proxy;
4299 }
4300 }
4301
4302 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 29)) {
4303 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4304 if (scene->ed) {
4305 SEQ_for_each_callback(&scene->ed->seqbase, seq_text_data_update, nullptr);
4306 }
4307 }
4308 }
4309
4310 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 30)) {
4311 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4312 if (scene->nodetree) {
4313 scene->nodetree->flag &= ~NTREE_UNUSED_2;
4314 }
4315 }
4316 }
4317
4318 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 31)) {
4319 LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) {
4320 /* Guess a somewhat correct density given the resolution. But very low resolution need
4321 * a decent enough density to work. */
4322 lightprobe->grid_surfel_density = max_ii(20,
4323 2 * max_iii(lightprobe->grid_resolution_x,
4324 lightprobe->grid_resolution_y,
4325 lightprobe->grid_resolution_z));
4326 }
4327 }
4328
4329 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 31)) {
4330 bool only_uses_eevee_legacy_or_workbench = true;
4331 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4333 only_uses_eevee_legacy_or_workbench = false;
4334 }
4335 }
4336 /* Mark old EEVEE world volumes for showing conversion operator. */
4337 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
4338 if (world->nodetree) {
4339 bNode *output_node = version_eevee_output_node_get(world->nodetree, SH_NODE_OUTPUT_WORLD);
4340 if (output_node) {
4341 bNodeSocket *volume_input_socket = static_cast<bNodeSocket *>(
4342 BLI_findlink(&output_node->inputs, 1));
4343 if (volume_input_socket) {
4344 LISTBASE_FOREACH (bNodeLink *, node_link, &world->nodetree->links) {
4345 if (node_link->tonode == output_node && node_link->tosock == volume_input_socket) {
4347 /* Only display a warning message if we are sure this can be used by EEVEE. */
4348 if (only_uses_eevee_legacy_or_workbench) {
4349 BLO_reportf_wrap(fd->reports,
4351 RPT_("%s contains a volume shader that might need to be "
4352 "converted to object (see world volume panel)\n"),
4353 world->id.name + 2);
4354 }
4355 }
4356 }
4357 }
4358 }
4359 }
4360 }
4361 }
4362
4363 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 33)) {
4364 constexpr int NTREE_EXECUTION_MODE_GPU = 2;
4365
4366 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4367 if (scene->nodetree) {
4368 if (scene->nodetree->execution_mode == NTREE_EXECUTION_MODE_GPU) {
4369 scene->r.compositor_device = SCE_COMPOSITOR_DEVICE_GPU;
4370 }
4371 scene->r.compositor_precision = scene->nodetree->precision;
4372 }
4373 }
4374 }
4375
4376 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 34)) {
4377 float shadow_max_res_sun = 0.001f;
4378 float shadow_max_res_local = 0.001f;
4379 bool shadow_resolution_absolute = false;
4380 /* Try to get default resolution from scene setting. */
4381 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4382 shadow_max_res_local = (2.0f * M_SQRT2) / scene->eevee.shadow_cube_size_deprecated;
4383 /* Round to avoid weird numbers in the UI. */
4384 shadow_max_res_local = ceil(shadow_max_res_local * 1000.0f) / 1000.0f;
4385 shadow_resolution_absolute = true;
4386 break;
4387 }
4388
4389 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4390 if (light->type == LA_SUN) {
4391 /* Sun are too complex to convert. Need user interaction. */
4392 light->shadow_maximum_resolution = shadow_max_res_sun;
4393 SET_FLAG_FROM_TEST(light->mode, false, LA_SHAD_RES_ABSOLUTE);
4394 }
4395 else {
4396 light->shadow_maximum_resolution = shadow_max_res_local;
4397 SET_FLAG_FROM_TEST(light->mode, shadow_resolution_absolute, LA_SHAD_RES_ABSOLUTE);
4398 }
4399 }
4400 }
4401
4402 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 36)) {
4403 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4404 /* Only for grease pencil brushes. */
4405 if (brush->gpencil_settings) {
4406 /* Use the `Scene` radius unit by default (confusingly named `BRUSH_LOCK_SIZE`).
4407 * Convert the radius to be the same visual size as in GPv2. */
4408 brush->flag |= BRUSH_LOCK_SIZE;
4409 brush->unprojected_radius = brush->size *
4411 }
4412 }
4413 }
4414
4415 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 37)) {
4416 const World *default_world = DNA_struct_default_get(World);
4417 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
4418 world->sun_threshold = default_world->sun_threshold;
4419 world->sun_angle = default_world->sun_angle;
4420 world->sun_shadow_maximum_resolution = default_world->sun_shadow_maximum_resolution;
4421 /* Having the sun extracted is mandatory to keep the same look and avoid too much light
4422 * leaking compared to EEVEE-Legacy. But adding shadows might create performance overhead and
4423 * change the result in a very different way. So we disable shadows in older file. */
4424 world->flag &= ~WO_USE_SUN_SHADOW;
4425 }
4426 }
4427
4428 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 38)) {
4429 LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
4431 }
4432 }
4433
4434 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 39)) {
4435 /* Unify cast shadow property with Cycles. */
4437 const Light *default_light = DNA_struct_default_get(Light);
4438 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4439 IDProperty *clight = version_cycles_properties_from_ID(&light->id);
4440 if (clight) {
4442 clight, "cast_shadow", default_light->mode & LA_SHADOW);
4443 SET_FLAG_FROM_TEST(light->mode, value, LA_SHADOW);
4444 }
4445 }
4446 }
4447 }
4448
4449 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 40)) {
4450 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
4451 version_node_input_socket_name(ntree, FN_NODE_COMBINE_TRANSFORM, "Location", "Translation");
4453 ntree, FN_NODE_SEPARATE_TRANSFORM, "Location", "Translation");
4454 }
4455 }
4456
4457 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 41)) {
4458 const Light *default_light = DNA_struct_default_get(Light);
4459 LISTBASE_FOREACH (Light *, light, &bmain->lights) {
4460 light->shadow_jitter_overblur = default_light->shadow_jitter_overblur;
4461 }
4462 }
4463
4464 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 43)) {
4465 const World *default_world = DNA_struct_default_get(World);
4466 LISTBASE_FOREACH (World *, world, &bmain->worlds) {
4467 world->sun_shadow_maximum_resolution = default_world->sun_shadow_maximum_resolution;
4468 world->sun_shadow_filter_radius = default_world->sun_shadow_filter_radius;
4469 }
4470 }
4471
4472 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 44)) {
4473 const Scene *default_scene = DNA_struct_default_get(Scene);
4474 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4475 scene->eevee.fast_gi_step_count = default_scene->eevee.fast_gi_step_count;
4476 scene->eevee.fast_gi_ray_count = default_scene->eevee.fast_gi_ray_count;
4477 }
4478 }
4479
4480 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 45)) {
4481 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4482 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4483 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4484 if (sl->spacetype == SPACE_VIEW3D) {
4485 View3D *v3d = reinterpret_cast<View3D *>(sl);
4487 }
4488 }
4489 }
4490 }
4491 }
4492
4493 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 46)) {
4494 const Scene *default_scene = DNA_struct_default_get(Scene);
4495 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4496 scene->eevee.fast_gi_thickness_near = default_scene->eevee.fast_gi_thickness_near;
4497 scene->eevee.fast_gi_thickness_far = default_scene->eevee.fast_gi_thickness_far;
4498 }
4499 }
4500 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 48)) {
4501 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
4502 if (!ob->pose) {
4503 continue;
4504 }
4505 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
4506 pchan->custom_shape_wire_width = 1.0;
4507 }
4508 }
4509 }
4510
4511 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 49)) {
4512 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4513 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4514 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4515 if (sl->spacetype == SPACE_VIEW3D) {
4516 View3D *v3d = reinterpret_cast<View3D *>(sl);
4518 }
4519 }
4520 }
4521 }
4522 }
4523
4524 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 50)) {
4525 LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
4526 if (ntree->type != NTREE_GEOMETRY) {
4527 continue;
4528 }
4529 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4530 if (node->type != GEO_NODE_CAPTURE_ATTRIBUTE) {
4531 continue;
4532 }
4534 node->storage);
4535 if (storage->next_identifier > 0) {
4536 continue;
4537 }
4538 storage->capture_items_num = 1;
4539 storage->capture_items = MEM_cnew_array<NodeGeometryAttributeCaptureItem>(
4540 storage->capture_items_num, __func__);
4542 item.data_type = storage->data_type_legacy;
4543 item.identifier = storage->next_identifier++;
4544 item.name = BLI_strdup("Value");
4545 }
4546 }
4547 }
4548
4549 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 53)) {
4550 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4551 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4552 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4553 if (sl->spacetype == SPACE_NODE) {
4554 SpaceNode *snode = reinterpret_cast<SpaceNode *>(sl);
4556 }
4557 }
4558 }
4559 }
4560 }
4561
4562 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 55)) {
4563 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4564 if (ntree->type != NTREE_COMPOSIT) {
4565 continue;
4566 }
4567 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4568 if (node->type != CMP_NODE_CURVE_RGB) {
4569 continue;
4570 }
4571
4572 CurveMapping &curve_mapping = *static_cast<CurveMapping *>(node->storage);
4573
4574 /* Film-like tone only works with the combined curve, which is the fourth curve, so make
4575 * the combined curve current, as we now hide the rest of the curves since they no longer
4576 * have an effect. */
4577 if (curve_mapping.tone == CURVE_TONE_FILMLIKE) {
4578 curve_mapping.cur = 3;
4579 }
4580 }
4581 }
4583 }
4584
4585 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 2)) {
4586 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4587 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4588 LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) {
4589 if (space_link->spacetype == SPACE_NODE) {
4590 SpaceNode *space_node = reinterpret_cast<SpaceNode *>(space_link);
4591 space_node->flag &= ~SNODE_FLAG_UNUSED_5;
4592 }
4593 }
4594 }
4595 }
4596 }
4597
4598 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 60) ||
4599 (bmain->versionfile == 403 && !MAIN_VERSION_FILE_ATLEAST(bmain, 403, 3)))
4600 {
4601 /* Limit Rotation constraints from old files should use the legacy Limit
4602 * Rotation behavior. */
4603 LISTBASE_FOREACH (Object *, obj, &bmain->objects) {
4604 LISTBASE_FOREACH (bConstraint *, constraint, &obj->constraints) {
4605 if (constraint->type != CONSTRAINT_TYPE_ROTLIMIT) {
4606 continue;
4607 }
4608 static_cast<bRotLimitConstraint *>(constraint->data)->flag |= LIMIT_ROT_LEGACY_BEHAVIOR;
4609 }
4610
4611 if (!obj->pose) {
4612 continue;
4613 }
4614 LISTBASE_FOREACH (bPoseChannel *, pbone, &obj->pose->chanbase) {
4615 LISTBASE_FOREACH (bConstraint *, constraint, &pbone->constraints) {
4616 if (constraint->type != CONSTRAINT_TYPE_ROTLIMIT) {
4617 continue;
4618 }
4619 static_cast<bRotLimitConstraint *>(constraint->data)->flag |= LIMIT_ROT_LEGACY_BEHAVIOR;
4620 }
4621 }
4622 }
4623 }
4624
4625 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 61)) {
4626 /* LIGHT_PROBE_RESOLUTION_64 has been removed in EEVEE-Next as the tedrahedral mapping is to
4627 * low res to be usable. */
4628 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4629 if (scene->eevee.gi_cubemap_resolution < 128) {
4630 scene->eevee.gi_cubemap_resolution = 128;
4631 }
4632 }
4633 }
4634
4635 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 64)) {
4637 /* Re-apply versioning made for EEVEE-Next in 4.1 before it got delayed. */
4638 LISTBASE_FOREACH (Material *, material, &bmain->materials) {
4639 bool transparent_shadows = material->blend_shadow != MA_BS_SOLID;
4640 SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW);
4641 }
4642 LISTBASE_FOREACH (Material *, mat, &bmain->materials) {
4643 mat->surface_render_method = (mat->blend_method == MA_BM_BLEND) ?
4646 }
4647 }
4648 }
4649
4650 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 3)) {
4651 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
4652 if (BrushGpencilSettings *settings = brush->gpencil_settings) {
4653 /* Copy the `draw_strength` value to the `alpha` value. */
4654 brush->alpha = settings->draw_strength;
4655
4656 /* We approximate the simplify pixel threshold by taking the previous threshold (world
4657 * space) and dividing by the legacy radius conversion factor. This should generally give
4658 * reasonable "pixel" threshold values, at least for previous GPv2 defaults. */
4659 settings->simplify_px = settings->simplify_f /
4661 }
4662 }
4663 }
4664
4665 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 4)) {
4666 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4667 scene->view_settings.temperature = 6500.0f;
4668 scene->view_settings.tint = 10.0f;
4669 }
4670 }
4671
4672 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 7)) {
4673 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4674 SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
4675 sequencer_tool_settings->snap_mode |= SEQ_SNAP_TO_PREVIEW_BORDERS |
4678 }
4679 }
4680
4681 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 8)) {
4683 }
4684
4685 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 9)) {
4687 }
4688
4689 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 10)) {
4690 /* Initialize Color Balance node white point settings. */
4691 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4692 if (ntree->type != NTREE_CUSTOM) {
4693 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4694 if (node->type == CMP_NODE_COLORBALANCE) {
4695 NodeColorBalance *n = static_cast<NodeColorBalance *>(node->storage);
4696 n->input_temperature = n->output_temperature = 6500.0f;
4697 n->input_tint = n->output_tint = 10.0f;
4698 }
4699 }
4700 }
4701 }
4703 }
4704
4705 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 11)) {
4706 LISTBASE_FOREACH (Curves *, curves, &bmain->hair_curves) {
4707 curves->geometry.attributes_active_index = curves->attributes_active_index_legacy;
4708 }
4709 }
4710
4711 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 13)) {
4712 Camera default_cam = *DNA_struct_default_get(Camera);
4713 LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
4714 camera->central_cylindrical_range_u_min = default_cam.central_cylindrical_range_u_min;
4715 camera->central_cylindrical_range_u_max = default_cam.central_cylindrical_range_u_max;
4716 camera->central_cylindrical_range_v_min = default_cam.central_cylindrical_range_v_min;
4717 camera->central_cylindrical_range_v_max = default_cam.central_cylindrical_range_v_max;
4718 camera->central_cylindrical_radius = default_cam.central_cylindrical_radius;
4719 }
4720 }
4721
4722 /* The File Output node now uses the linear color space setting of its stored image formats. So
4723 * we need to ensure the color space value is initialized to some sane default based on the image
4724 * type. Furthermore, the node now gained a new Save As Render option that is global to the node,
4725 * which will be used if Use Node Format is enabled for each input, so we potentially need to
4726 * disable Use Node Format in case inputs had different Save As render options. */
4727 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 14)) {
4728 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4729 if (ntree->type != NTREE_COMPOSIT) {
4730 continue;
4731 }
4732
4733 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4734 if (node->type != CMP_NODE_OUTPUT_FILE) {
4735 continue;
4736 }
4737
4738 /* Initialize node format color space if it is not set. */
4739 NodeImageMultiFile *storage = static_cast<NodeImageMultiFile *>(node->storage);
4740 if (storage->format.linear_colorspace_settings.name[0] == '\0') {
4742 }
4743
4744 if (BLI_listbase_is_empty(&node->inputs)) {
4745 continue;
4746 }
4747
4748 /* Initialize input formats color space if it is not set. */
4749 LISTBASE_FOREACH (const bNodeSocket *, input, &node->inputs) {
4750 NodeImageMultiFileSocket *input_storage = static_cast<NodeImageMultiFileSocket *>(
4751 input->storage);
4752 if (input_storage->format.linear_colorspace_settings.name[0] == '\0') {
4754 }
4755 }
4756
4757 /* EXR images don't use Save As Render. */
4759 continue;
4760 }
4761
4762 /* Find out if all inputs have the same Save As Render option. */
4763 const bNodeSocket *first_input = static_cast<bNodeSocket *>(node->inputs.first);
4764 const NodeImageMultiFileSocket *first_input_storage =
4765 static_cast<NodeImageMultiFileSocket *>(first_input->storage);
4766 const bool first_save_as_render = first_input_storage->save_as_render;
4767 bool all_inputs_have_same_save_as_render = true;
4768 LISTBASE_FOREACH (const bNodeSocket *, input, &node->inputs) {
4769 const NodeImageMultiFileSocket *input_storage = static_cast<NodeImageMultiFileSocket *>(
4770 input->storage);
4771 if (bool(input_storage->save_as_render) != first_save_as_render) {
4772 all_inputs_have_same_save_as_render = false;
4773 break;
4774 }
4775 }
4776
4777 /* All inputs have the same save as render option, so we set the node Save As Render option
4778 * to that value, and we leave inputs as is. */
4779 if (all_inputs_have_same_save_as_render) {
4780 storage->save_as_render = first_save_as_render;
4781 continue;
4782 }
4783
4784 /* For inputs that have Use Node Format enabled, we need to disabled it because otherwise
4785 * they will use the node's Save As Render option. It follows that we need to copy the
4786 * node's format to the input format. */
4787 LISTBASE_FOREACH (const bNodeSocket *, input, &node->inputs) {
4788 NodeImageMultiFileSocket *input_storage = static_cast<NodeImageMultiFileSocket *>(
4789 input->storage);
4790
4791 if (!input_storage->use_node_format) {
4792 continue;
4793 }
4794
4795 input_storage->use_node_format = false;
4796 input_storage->format = storage->format;
4797 }
4798 }
4799 }
4801 }
4802
4803 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 15)) {
4804 using namespace blender;
4805
4806 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
4807 const ListBase *exporters = &collection->exporters;
4808 LISTBASE_FOREACH (CollectionExport *, data, exporters) {
4809 /* The name field should be empty at this point. */
4810 BLI_assert(data->name[0] == '\0');
4811
4812 bke::FileHandlerType *fh = bke::file_handler_find(data->fh_idname);
4813 BKE_collection_exporter_name_set(exporters, data, fh ? fh->label : DATA_("Undefined"));
4814 }
4815 }
4816 }
4817
4818 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 16)) {
4819 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4820 scene->eevee.flag |= SCE_EEVEE_FAST_GI_ENABLED;
4821 }
4822 }
4823
4824 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 17)) {
4825 FOREACH_NODETREE_BEGIN (bmain, tree, id) {
4826 if (tree->default_group_node_width == 0) {
4827 tree->default_group_node_width = GROUP_NODE_DEFAULT_WIDTH;
4828 }
4829 }
4831 }
4832
4833 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 20)) {
4834 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4835 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4836 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4837 if (sl->spacetype == SPACE_SEQ) {
4839 if (region != nullptr) {
4840 region->flag &= ~RGN_FLAG_HIDDEN;
4841 }
4842 }
4843 }
4844 }
4845 }
4846 }
4847
4848 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 21)) {
4849 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4850 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4851 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4852 if (sl->spacetype == SPACE_CLIP) {
4854 if (region != nullptr) {
4855 View2D *v2d = &region->v2d;
4856 v2d->flag &= ~V2D_VIEWSYNC_SCREEN_TIME;
4857 }
4858 }
4859 }
4860 }
4861 }
4862 }
4863
4864 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 22)) {
4866 }
4867
4868 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 23)) {
4869 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
4870 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
4871 if (md->type != eModifierType_Nodes) {
4872 continue;
4873 }
4874 NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md);
4876 /* Use disk target for existing modifiers to avoid changing behavior. */
4878 }
4879 }
4880 }
4881 }
4882
4883 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 24)) {
4884 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
4886 }
4888 }
4889
4890 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 26)) {
4892 }
4893
4894 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 28)) {
4895 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
4896 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
4897 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
4898 if (sl->spacetype == SPACE_VIEW3D) {
4899 View3D *v3d = reinterpret_cast<View3D *>(sl);
4904 }
4905 }
4906 }
4907 }
4908 }
4909
4910 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 29)) {
4911 /* Open warnings panel by default. */
4912 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
4913 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
4914 if (md->type == eModifierType_Nodes) {
4915 md->layout_panel_open_flag |= 1 << NODES_MODIFIER_PANEL_WARNINGS;
4916 }
4917 }
4918 }
4919 }
4920
4921 if (!MAIN_VERSION_FILE_ATLEAST(bmain, 403, 31)) {
4922 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
4923 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
4924 if (tref->space_type != SPACE_SEQ) {
4925 continue;
4926 }
4927 STRNCPY(tref->idname, "builtin.select_box");
4928 }
4929 }
4930 }
4931
4932 /* Always run this versioning; meshes are written with the legacy format which always needs to
4933 * be converted to the new format on file load. Can be moved to a subversion check in a larger
4934 * breaking release. */
4935 LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
4937 }
4938
4945}
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 NODE_REROUTE
Definition BKE_node.hh:804
#define GEO_NODE_STORE_NAMED_ATTRIBUTE
Definition BKE_node.hh:1285
#define SH_NODE_OUTPUT_WORLD
Definition BKE_node.hh:914
#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_ATTRIBUTE_STATISTIC
Definition BKE_node.hh:1214
#define GEO_NODE_VIEWER
Definition BKE_node.hh:1201
#define SH_NODE_ADD_SHADER
Definition BKE_node.hh:939
#define SH_NODE_TEX_COORD
Definition BKE_node.hh:938
#define SH_NODE_VALUE
Definition BKE_node.hh:892
#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_EVALUATE_ON_DOMAIN
Definition BKE_node.hh:1292
#define SH_NODE_OUTPUT_MATERIAL
Definition BKE_node.hh:913
#define FOREACH_NODETREE_END
Definition BKE_node.hh:870
#define SH_NODE_BSDF_GLOSSY
Definition BKE_node.hh:920
#define GEO_NODE_ACCUMULATE_FIELD
Definition BKE_node.hh:1275
#define SH_NODE_TEX_MUSGRAVE_DEPRECATED
Definition BKE_node.hh:937
#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 GEO_NODE_BLUR_ATTRIBUTE
Definition BKE_node.hh:1319
#define GEO_NODE_SAMPLE_INDEX
Definition BKE_node.hh:1303
#define SH_NODE_BSDF_GLOSSY_LEGACY
Definition BKE_node.hh:922
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_SHAD_RES_ABSOLUTE
@ LA_SHADOW
@ LA_USE_SOFT_FALLOFF
@ LA_AREA
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ LIGHTPROBE_GRID_CAPTURE_EMISSION
@ LIGHTPROBE_GRID_CAPTURE_WORLD
@ LIGHTPROBE_GRID_CAPTURE_INDIRECT
@ 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_DISPLACEMENT_BUMP
@ MA_BS_HASHED
@ MA_BS_CLIP
@ MA_BS_NONE
@ MA_BS_SOLID
@ MA_THICKNESS_SLAB
@ MA_BM_CLIP
@ MA_BM_HASHED
@ MA_BM_BLEND
@ 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
@ NTREE_CUSTOM
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
@ NODE_VECTOR_MATH_ABSOLUTE
#define SHD_SHEEN_ASHIKHMIN
@ NODE_HIDDEN
@ 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_OUTPUT_CYCLES
@ SHD_OUTPUT_ALL
@ SHD_OUTPUT_EEVEE
@ NODE_CLAMP_MINMAX
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
@ SHD_MATH_CLAMP
@ SHD_PRINCIPLED_HAIR_CHIANG
@ CMP_NODE_MAP_UV_FILTERING_ANISOTROPIC
@ SHD_GLOSSY_SHARP_DEPRECATED
@ SHD_GLOSSY_GGX
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
@ SOCK_HIDE_VALUE
@ SOCK_HIDE_IN_MODIFIER
@ SOCK_HIDDEN
@ SHD_NOISE_FBM
@ SHD_NOISE_MULTIFRACTAL
@ SHD_NOISE_RIDGED_MULTIFRACTAL
@ SHD_NOISE_HETERO_TERRAIN
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_ROTATION
@ SOCK_RGBA
@ SHD_VECT_TRANSFORM_TYPE_NORMAL
@ OB_HIDE_SHADOW
@ OB_FONT
@ OB_ARMATURE
@ OB_MESH
@ RAYTRACE_EEVEE_METHOD_SCREEN
@ SEQ_SNAP_TO_MARKERS
@ SEQ_SNAP_TO_PREVIEW_CENTER
@ SEQ_SNAP_TO_STRIPS_PREVIEW
@ SEQ_SNAP_TO_PREVIEW_BORDERS
#define SCE_SNAP_TO_GEOM
@ SCE_MB_START
@ SCE_MB_END
@ SCE_MB_CENTER
@ R_FILTER_FAST_GAUSS
@ R_MBLUR
@ RAYTRACE_EEVEE_USE_DENOISE
#define MAXFRAMEF
@ R_IMF_IMTYPE_FFMPEG
@ R_IMF_IMTYPE_AVIJPEG
@ R_IMF_IMTYPE_AVIRAW
@ R_IMF_IMTYPE_OPENEXR
@ R_IMF_IMTYPE_MULTILAYER
#define SCE_SNAP_TO_VERTEX
@ SCE_SNAP
@ SCE_EEVEE_FAST_GI_ENABLED
@ SCE_EEVEE_VOLUME_CUSTOM_RANGE
@ SCE_EEVEE_MOTION_BLUR_ENABLED_DEPRECATED
@ SCE_COMPOSITOR_DEVICE_GPU
#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_TYPE_TOOL_HEADER
@ RGN_TYPE_ASSET_SHELF_HEADER
@ RGN_TYPE_WINDOW
@ RGN_TYPE_ASSET_SHELF
@ RGN_TYPE_TOOLS
@ RGN_FLAG_DYNAMIC_SIZE
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_NO_USER_RESIZE
@ SEQ_CACHE_UNUSED_8
@ SEQ_CACHE_UNUSED_5
@ SEQ_CACHE_UNUSED_7
@ SEQ_CACHE_UNUSED_6
@ SEQ_CACHE_UNUSED_9
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_TEXT
@ 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
@ SPACE_CLIP
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ SEQ_TIMELINE_SHOW_STRIP_RETIMING
@ SEQ_CACHE_SHOW_FINAL_OUT
#define USER_EXPERIMENTAL_TEST(userdef, member)
@ V3D_SHOW_CAMERA_PASSEPARTOUT
@ V3D_SHOW_CAMERA_GUIDES
@ WO_USE_EEVEE_FINITE_VOLUME
@ LIGHT_PROBE_RESOLUTION_1024
@ IMB_TC_RECORD_RUN
#define MEM_SAFE_FREE(v)
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
unsigned int U
Definition btGjkEpa3.h:78
static T sum(const btAlignedObjectArray< T > &items)
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
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
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 is_empty() const
Definition BLI_span.hh:261
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
OperationNode * node
DEGForeachIDComponentCallback callback
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)
static void ANIM_armature_foreach_bone(ListBase *bones, CB callback)
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
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
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::@128 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
ListBase seqbase
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 worlds
Definition BKE_main.hh:224
ListBase screens
Definition BKE_main.hh:225
ListBase workspaces
Definition BKE_main.hh:246
ListBase objects
Definition BKE_main.hh:212
struct MovieTracking tracking
MovieTrackingPlaneTrack * active_plane_track
MovieTrackingReconstruction reconstruction
MovieTrackingTrack * active_track
struct MovieReconstructedCamera * cameras
NodeGeometryAttributeCaptureItem * capture_items
ImageFormatData format
int num_input_samples_deprecated
AssetShelf * active_shelf
float fast_gi_thickness_near
float shadow_resolution_scale
float fast_gi_thickness_far
struct SceneEEVEE eevee
int automasking_boundary_edges_propagation_steps
ListBase modifiers
SpaceNodeOverlay overlay
struct SequencerCacheOverlay cache_overlay
struct SequencerTimelineOverlay timeline_overlay
StripProxy * proxy
StripTransform * transform
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 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