1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup blenloader
19  */
20 /* allow readfile to use deprecated functionality */
21 #define DNA_DEPRECATED_ALLOW
22 
23 #include "BLI_alloca.h"
24 #include "BLI_listbase.h"
25 #include "BLI_math.h"
26 #include "BLI_string.h"
27 #include "BLI_utildefines.h"
28 
29 #include "DNA_anim_types.h"
30 #include "DNA_brush_types.h"
31 #include "DNA_cachefile_types.h"
32 #include "DNA_constraint_types.h"
33 #include "DNA_fluid_types.h"
34 #include "DNA_genfile.h"
35 #include "DNA_gpencil_modifier_types.h"
36 #include "DNA_gpencil_types.h"
37 #include "DNA_hair_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_modifier_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_particle_types.h"
43 #include "DNA_pointcloud_types.h"
44 #include "DNA_rigidbody_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_shader_fx_types.h"
47 #include "DNA_workspace_types.h"
48 
49 #include "BKE_animsys.h"
50 #include "BKE_collection.h"
51 #include "BKE_colortools.h"
52 #include "BKE_gpencil.h"
53 #include "BKE_lib_id.h"
54 #include "BKE_main.h"
55 #include "BKE_mesh.h"
56 #include "BKE_node.h"
57 
58 #include "MEM_guardedalloc.h"
59 
60 #include "BLO_readfile.h"
61 #include "readfile.h"
62 
63 /* Make preferences read-only, use versioning_userdef.c. */
64 #define U (*((const UserDef *)&U))
65 
do_versions_after_linking_290(Main * bmain,ReportList * UNUSED (reports))66 void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
67 {
68   if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) {
69     /* Patch old grease pencil modifiers material filter. */
70     LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
71       LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
72         switch (md->type) {
73           case eGpencilModifierType_Array: {
74             ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md;
75             if (gpmd->materialname[0] != '\0') {
76               gpmd->material = BLI_findstring(
77                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
78               gpmd->materialname[0] = '\0';
79             }
80             break;
81           }
82           case eGpencilModifierType_Color: {
83             ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
84             if (gpmd->materialname[0] != '\0') {
85               gpmd->material = BLI_findstring(
86                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
87               gpmd->materialname[0] = '\0';
88             }
89             break;
90           }
91           case eGpencilModifierType_Hook: {
92             HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
93             if (gpmd->materialname[0] != '\0') {
94               gpmd->material = BLI_findstring(
95                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
96               gpmd->materialname[0] = '\0';
97             }
98             break;
99           }
100           case eGpencilModifierType_Lattice: {
101             LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md;
102             if (gpmd->materialname[0] != '\0') {
103               gpmd->material = BLI_findstring(
104                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
105               gpmd->materialname[0] = '\0';
106             }
107             break;
108           }
109           case eGpencilModifierType_Mirror: {
110             MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md;
111             if (gpmd->materialname[0] != '\0') {
112               gpmd->material = BLI_findstring(
113                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
114               gpmd->materialname[0] = '\0';
115             }
116             break;
117           }
118           case eGpencilModifierType_Multiply: {
119             MultiplyGpencilModifierData *gpmd = (MultiplyGpencilModifierData *)md;
120             if (gpmd->materialname[0] != '\0') {
121               gpmd->material = BLI_findstring(
122                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
123               gpmd->materialname[0] = '\0';
124             }
125             break;
126           }
127           case eGpencilModifierType_Noise: {
128             NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
129             if (gpmd->materialname[0] != '\0') {
130               gpmd->material = BLI_findstring(
131                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
132               gpmd->materialname[0] = '\0';
133             }
134             break;
135           }
136           case eGpencilModifierType_Offset: {
137             OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md;
138             if (gpmd->materialname[0] != '\0') {
139               gpmd->material = BLI_findstring(
140                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
141               gpmd->materialname[0] = '\0';
142             }
143             break;
144           }
145           case eGpencilModifierType_Opacity: {
146             OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
147             if (gpmd->materialname[0] != '\0') {
148               gpmd->material = BLI_findstring(
149                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
150               gpmd->materialname[0] = '\0';
151             }
152             break;
153           }
154           case eGpencilModifierType_Simplify: {
155             SimplifyGpencilModifierData *gpmd = (SimplifyGpencilModifierData *)md;
156             if (gpmd->materialname[0] != '\0') {
157               gpmd->material = BLI_findstring(
158                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
159               gpmd->materialname[0] = '\0';
160             }
161             break;
162           }
163           case eGpencilModifierType_Smooth: {
164             SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
165             if (gpmd->materialname[0] != '\0') {
166               gpmd->material = BLI_findstring(
167                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
168               gpmd->materialname[0] = '\0';
169             }
170             break;
171           }
172           case eGpencilModifierType_Subdiv: {
173             SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md;
174             if (gpmd->materialname[0] != '\0') {
175               gpmd->material = BLI_findstring(
176                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
177               gpmd->materialname[0] = '\0';
178             }
179             break;
180           }
181           case eGpencilModifierType_Texture: {
182             TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md;
183             if (gpmd->materialname[0] != '\0') {
184               gpmd->material = BLI_findstring(
185                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
186               gpmd->materialname[0] = '\0';
187             }
188             break;
189           }
190           case eGpencilModifierType_Thick: {
191             ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
192             if (gpmd->materialname[0] != '\0') {
193               gpmd->material = BLI_findstring(
194                   &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
195               gpmd->materialname[0] = '\0';
196             }
197             break;
198           }
199           default:
200             break;
201         }
202       }
203     }
204 
205     /* Patch first frame for old files. */
206     Scene *scene = bmain->scenes.first;
207     if (scene != NULL) {
208       LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
209         if (ob->type != OB_GPENCIL) {
210           continue;
211         }
212         bGPdata *gpd = ob->data;
213         LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
214           bGPDframe *gpf = gpl->frames.first;
215           if (gpf && gpf->framenum > scene->r.sfra) {
216             bGPDframe *gpf_dup = BKE_gpencil_frame_duplicate(gpf);
217             gpf_dup->framenum = scene->r.sfra;
218             BLI_addhead(&gpl->frames, gpf_dup);
219           }
220         }
221       }
222     }
223   }
224 
225   if (!MAIN_VERSION_ATLEAST(bmain, 291, 1)) {
226     LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
227       if (BKE_collection_cycles_fix(bmain, collection)) {
228         printf(
229             "WARNING: Cycle detected in collection '%s', fixed as best as possible.\n"
230             "You may have to reconstruct your View Layers...\n",
231             collection->id.name);
232       }
233     }
234   }
235 
236   if (!MAIN_VERSION_ATLEAST(bmain, 291, 8)) {
237     /**
238      * Make sure Emission Alpha fcurve and drivers is properly mapped after the Emission Strength
239      * got introduced.
240      * */
241 
242     /**
243      * Effectively we are replacing the (animation of) node socket input 18 with 19.
244      * Emission Strength is the new socket input 18, pushing Emission Alpha to input 19.
245      *
246      * To play safe we move all the inputs beyond 18 to their rightful new place.
247      * In case users are doing unexpected things with not-really supported keyframeable channels.
248      *
249      * The for loop for the input ids is at the top level otherwise we lose the animation
250      * keyframe data.
251      * */
252     for (int input_id = 21; input_id >= 18; input_id--) {
253       FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
254         if (ntree->type == NTREE_SHADER) {
255           LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
256             if (node->type != SH_NODE_BSDF_PRINCIPLED) {
257               continue;
258             }
259 
260             const size_t node_name_length = strlen(node->name);
261             const size_t node_name_escaped_max_length = (node_name_length * 2);
262             char *node_name_escaped = MEM_mallocN(node_name_escaped_max_length + 1,
263                                                   "escaped name");
264             BLI_strescape(node_name_escaped, node->name, node_name_escaped_max_length);
265             char *rna_path_prefix = BLI_sprintfN("nodes[\"%s\"].inputs", node_name_escaped);
266 
267             BKE_animdata_fix_paths_rename_all_ex(
268                 bmain, id, rna_path_prefix, NULL, NULL, input_id, input_id + 1, false);
269             MEM_freeN(rna_path_prefix);
270             MEM_freeN(node_name_escaped);
271           }
272         }
273       }
274       FOREACH_NODETREE_END;
275     }
276   }
277 
278   /**
279    * Versioning code until next subversion bump goes here.
280    *
281    * \note Be sure to check when bumping the version:
282    * - #blo_do_versions_290 in this file.
283    * - "versioning_userdef.c", #blo_do_versions_userdef
284    * - "versioning_userdef.c", #do_versions_theme
285    *
286    * \note Keep this message at the bottom of the function.
287    */
288   {
289 
290     /* Keep this block, even when empty. */
291   }
292 }
293 
panels_remove_x_closed_flag_recursive(Panel * panel)294 static void panels_remove_x_closed_flag_recursive(Panel *panel)
295 {
296   const bool was_closed_x = panel->flag & PNL_UNUSED_1;
297   const bool was_closed_y = panel->flag & PNL_CLOSED; /* That value was the Y closed flag. */
298 
299   SET_FLAG_FROM_TEST(panel->flag, was_closed_x || was_closed_y, PNL_CLOSED);
300 
301   /* Clear the old PNL_CLOSEDX flag. */
302   panel->flag &= ~PNL_UNUSED_1;
303 
304   LISTBASE_FOREACH (Panel *, child_panel, &panel->children) {
305     panels_remove_x_closed_flag_recursive(child_panel);
306   }
307 }
308 
do_versions_point_attributes(CustomData * pdata)309 static void do_versions_point_attributes(CustomData *pdata)
310 {
311   /* Change to generic named float/float3 attributes. */
312   const int CD_LOCATION = 43;
313   const int CD_RADIUS = 44;
314 
315   for (int i = 0; i < pdata->totlayer; i++) {
316     CustomDataLayer *layer = &pdata->layers[i];
317     if (layer->type == CD_LOCATION) {
318       STRNCPY(layer->name, "Position");
319       layer->type = CD_PROP_FLOAT3;
320     }
321     else if (layer->type == CD_RADIUS) {
322       STRNCPY(layer->name, "Radius");
323       layer->type = CD_PROP_FLOAT;
324     }
325   }
326 }
327 
328 /* Move FCurve handles towards the control point in such a way that the curve itself doesn't
329  * change. Since 2.91 FCurves are computed slightly differently, which requires this update to keep
330  * the same animation result. Previous versions scaled down overlapping handles during evaluation.
331  * This function applies the old correction to the actual animation data instead. */
do_versions_291_fcurve_handles_limit(FCurve * fcu)332 static void do_versions_291_fcurve_handles_limit(FCurve *fcu)
333 {
334   uint i = 1;
335   for (BezTriple *bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
336     /* Only adjust bezier keyframes. */
337     if (bezt->ipo != BEZT_IPO_BEZ) {
338       continue;
339     }
340 
341     BezTriple *nextbezt = bezt + 1;
342     const float v1[2] = {bezt->vec[1][0], bezt->vec[1][1]};
343     const float v2[2] = {bezt->vec[2][0], bezt->vec[2][1]};
344     const float v3[2] = {nextbezt->vec[0][0], nextbezt->vec[0][1]};
345     const float v4[2] = {nextbezt->vec[1][0], nextbezt->vec[1][1]};
346 
347     /* If the handles have no length, no need to do any corrections. */
348     if (v1[0] == v2[0] && v3[0] == v4[0]) {
349       continue;
350     }
351 
352     /* Calculate handle deltas. */
353     float delta1[2], delta2[2];
354     sub_v2_v2v2(delta1, v1, v2);
355     sub_v2_v2v2(delta2, v4, v3);
356 
357     const float len1 = fabsf(delta1[0]); /* Length of handle of first key. */
358     const float len2 = fabsf(delta2[0]); /* Length of handle of second key. */
359 
360     /* Overlapping handles used to be internally scaled down in previous versions.
361      * We bake the handles onto these previously virtual values. */
362     const float time_delta = v4[0] - v1[0];
363     const float total_len = len1 + len2;
364     if (total_len <= time_delta) {
365       continue;
366     }
367 
368     const float factor = time_delta / total_len;
369     /* Current keyframe's right handle: */
370     madd_v2_v2v2fl(bezt->vec[2], v1, delta1, -factor); /* vec[2] = v1 - factor * delta1 */
371     /* Next keyframe's left handle: */
372     madd_v2_v2v2fl(nextbezt->vec[0], v4, delta2, -factor); /* vec[0] = v4 - factor * delta2 */
373   }
374 }
375 
blo_do_versions_290(FileData * fd,Library * UNUSED (lib),Main * bmain)376 void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
377 {
378   UNUSED_VARS(fd);
379 
380   if (MAIN_VERSION_ATLEAST(bmain, 290, 2) && MAIN_VERSION_OLDER(bmain, 291, 1)) {
381     /* In this range, the extrude manifold could generate meshes with degenerated face. */
382     LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
383       for (MPoly *mp = me->mpoly, *mp_end = mp + me->totpoly; mp < mp_end; mp++) {
384         if (mp->totloop == 2) {
385           bool changed;
386           BKE_mesh_validate_arrays(me,
387                                    me->mvert,
388                                    me->totvert,
389                                    me->medge,
390                                    me->totedge,
391                                    me->mface,
392                                    me->totface,
393                                    me->mloop,
394                                    me->totloop,
395                                    me->mpoly,
396                                    me->totpoly,
397                                    me->dvert,
398                                    false,
399                                    true,
400                                    &changed);
401           break;
402         }
403       }
404     }
405   }
406 
407   /** Repair files from duplicate brushes added to blend files, see: T76738. */
408   if (!MAIN_VERSION_ATLEAST(bmain, 290, 2)) {
409     {
410       short id_codes[] = {ID_BR, ID_PAL};
411       for (int i = 0; i < ARRAY_SIZE(id_codes); i++) {
412         ListBase *lb = which_libbase(bmain, id_codes[i]);
413         BKE_main_id_repair_duplicate_names_listbase(lb);
414       }
415     }
416 
417     if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "float", "uv_opacity")) {
418       for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
419         LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
420           LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
421             if (sl->spacetype == SPACE_IMAGE) {
422               SpaceImage *sima = (SpaceImage *)sl;
423               sima->uv_opacity = 1.0f;
424             }
425           }
426         }
427       }
428     }
429 
430     /* Init Grease Pencil new random curves. */
431     if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "random_hue")) {
432       LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
433         if ((brush->gpencil_settings) && (brush->gpencil_settings->curve_rand_pressure == NULL)) {
434           brush->gpencil_settings->curve_rand_pressure = BKE_curvemapping_add(
435               1, 0.0f, 0.0f, 1.0f, 1.0f);
436           brush->gpencil_settings->curve_rand_strength = BKE_curvemapping_add(
437               1, 0.0f, 0.0f, 1.0f, 1.0f);
438           brush->gpencil_settings->curve_rand_uv = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
439           brush->gpencil_settings->curve_rand_hue = BKE_curvemapping_add(
440               1, 0.0f, 0.0f, 1.0f, 1.0f);
441           brush->gpencil_settings->curve_rand_saturation = BKE_curvemapping_add(
442               1, 0.0f, 0.0f, 1.0f, 1.0f);
443           brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add(
444               1, 0.0f, 0.0f, 1.0f, 1.0f);
445         }
446       }
447     }
448   }
449 
450   if (!MAIN_VERSION_ATLEAST(bmain, 290, 4)) {
451     /* Clear old deprecated bit-flag from edit weights modifiers, we now use it for something else.
452      */
453     LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
454       LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
455         if (md->type == eModifierType_WeightVGEdit) {
456           ((WeightVGEditModifierData *)md)->edit_flags &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE;
457         }
458       }
459     }
460 
461     /* Initialize parameters of the new Nishita sky model. */
462     if (!DNA_struct_elem_find(fd->filesdna, "NodeTexSky", "float", "sun_size")) {
463       FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
464         if (ntree->type == NTREE_SHADER) {
465           LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
466             if (node->type == SH_NODE_TEX_SKY && node->storage) {
467               NodeTexSky *tex = (NodeTexSky *)node->storage;
468               tex->sun_disc = true;
469               tex->sun_size = DEG2RADF(0.545);
470               tex->sun_elevation = M_PI_2;
471               tex->sun_rotation = 0.0f;
472               tex->altitude = 0.0f;
473               tex->air_density = 1.0f;
474               tex->dust_density = 1.0f;
475               tex->ozone_density = 1.0f;
476             }
477           }
478         }
479       }
480       FOREACH_NODETREE_END;
481     }
482   }
483 
484   if (!MAIN_VERSION_ATLEAST(bmain, 290, 6)) {
485     /* Transition to saving expansion for all of a modifier's sub-panels. */
486     if (!DNA_struct_elem_find(fd->filesdna, "ModifierData", "short", "ui_expand_flag")) {
487       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
488         LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
489           if (md->mode & eModifierMode_Expanded_DEPRECATED) {
490             md->ui_expand_flag = 1;
491           }
492           else {
493             md->ui_expand_flag = 0;
494           }
495         }
496       }
497     }
498 
499     /* EEVEE Motion blur new parameters. */
500     if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "motion_blur_depth_scale")) {
501       LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
502         scene->eevee.motion_blur_depth_scale = 100.0f;
503         scene->eevee.motion_blur_max = 32;
504       }
505     }
506 
507     if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "int", "motion_blur_steps")) {
508       LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
509         scene->eevee.motion_blur_steps = 1;
510       }
511     }
512 
513     /* Transition to saving expansion for all of a constraint's sub-panels. */
514     if (!DNA_struct_elem_find(fd->filesdna, "bConstraint", "short", "ui_expand_flag")) {
515       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
516         LISTBASE_FOREACH (bConstraint *, con, &object->constraints) {
517           if (con->flag & CONSTRAINT_EXPAND_DEPRECATED) {
518             con->ui_expand_flag = 1;
519           }
520           else {
521             con->ui_expand_flag = 0;
522           }
523         }
524       }
525     }
526 
527     /* Transition to saving expansion for all of grease pencil modifier's sub-panels. */
528     if (!DNA_struct_elem_find(fd->filesdna, "GpencilModifierData", "short", "ui_expand_flag")) {
529       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
530         LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) {
531           if (md->mode & eGpencilModifierMode_Expanded_DEPRECATED) {
532             md->ui_expand_flag = 1;
533           }
534           else {
535             md->ui_expand_flag = 0;
536           }
537         }
538       }
539     }
540 
541     /* Transition to saving expansion for all of an effect's sub-panels. */
542     if (!DNA_struct_elem_find(fd->filesdna, "ShaderFxData", "short", "ui_expand_flag")) {
543       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
544         LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
545           if (fx->mode & eShaderFxMode_Expanded_DEPRECATED) {
546             fx->ui_expand_flag = 1;
547           }
548           else {
549             fx->ui_expand_flag = 0;
550           }
551         }
552       }
553     }
554 
555     /* Refactor bevel profile type to use an enum. */
556     if (!DNA_struct_elem_find(fd->filesdna, "BevelModifierData", "short", "profile_type")) {
557       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
558         LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
559           if (md->type == eModifierType_Bevel) {
560             BevelModifierData *bmd = (BevelModifierData *)md;
561             bool use_custom_profile = bmd->flags & MOD_BEVEL_CUSTOM_PROFILE_DEPRECATED;
562             bmd->profile_type = use_custom_profile ? MOD_BEVEL_PROFILE_CUSTOM :
563                                                      MOD_BEVEL_PROFILE_SUPERELLIPSE;
564           }
565         }
566       }
567     }
568 
569     /* Change ocean modifier values from [0, 10] to [0, 1] ranges. */
570     for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
571       LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
572         if (md->type == eModifierType_Ocean) {
573           OceanModifierData *omd = (OceanModifierData *)md;
574           omd->wave_alignment *= 0.1f;
575           omd->sharpen_peak_jonswap *= 0.1f;
576         }
577       }
578     }
579   }
580 
581   if (!MAIN_VERSION_ATLEAST(bmain, 291, 1)) {
582 
583     /* Initialize additional parameter of the Nishita sky model and change altitude unit. */
584     if (!DNA_struct_elem_find(fd->filesdna, "NodeTexSky", "float", "sun_intensity")) {
585       FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
586         if (ntree->type == NTREE_SHADER) {
587           LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
588             if (node->type == SH_NODE_TEX_SKY && node->storage) {
589               NodeTexSky *tex = (NodeTexSky *)node->storage;
590               tex->sun_intensity = 1.0f;
591               tex->altitude *= 0.001f;
592             }
593           }
594         }
595       }
596       FOREACH_NODETREE_END;
597     }
598 
599     /* Refactor bevel affect type to use an enum. */
600     if (!DNA_struct_elem_find(fd->filesdna, "BevelModifierData", "char", "affect_type")) {
601       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
602         LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
603           if (md->type == eModifierType_Bevel) {
604             BevelModifierData *bmd = (BevelModifierData *)md;
605             const bool use_vertex_bevel = bmd->flags & MOD_BEVEL_VERT_DEPRECATED;
606             bmd->affect_type = use_vertex_bevel ? MOD_BEVEL_AFFECT_VERTICES :
607                                                   MOD_BEVEL_AFFECT_EDGES;
608           }
609         }
610       }
611     }
612 
613     /* Initialize additional velocity parameter for #CacheFile's. */
614     if (!DNA_struct_elem_find(
615             fd->filesdna, "MeshSeqCacheModifierData", "float", "velocity_scale")) {
616       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
617         LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
618           if (md->type == eModifierType_MeshSequenceCache) {
619             MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
620             mcmd->velocity_scale = 1.0f;
621             mcmd->vertex_velocities = NULL;
622             mcmd->num_vertices = 0;
623           }
624         }
625       }
626     }
627 
628     if (!DNA_struct_elem_find(fd->filesdna, "CacheFile", "char", "velocity_unit")) {
629       for (CacheFile *cache_file = bmain->cachefiles.first; cache_file != NULL;
630            cache_file = cache_file->id.next) {
631         BLI_strncpy(cache_file->velocity_name, ".velocities", sizeof(cache_file->velocity_name));
632         cache_file->velocity_unit = CACHEFILE_VELOCITY_UNIT_SECOND;
633       }
634     }
635 
636     if (!DNA_struct_elem_find(fd->filesdna, "OceanModifierData", "int", "viewport_resolution")) {
637       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
638         LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
639           if (md->type == eModifierType_Ocean) {
640             OceanModifierData *omd = (OceanModifierData *)md;
641             omd->viewport_resolution = omd->resolution;
642           }
643         }
644       }
645     }
646 
647     /* Remove panel X axis collapsing, a remnant of horizontal panel alignment. */
648     LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
649       LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
650         LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
651           LISTBASE_FOREACH (Panel *, panel, &region->panels) {
652             panels_remove_x_closed_flag_recursive(panel);
653           }
654         }
655       }
656     }
657   }
658 
659   if (!MAIN_VERSION_ATLEAST(bmain, 291, 2)) {
660     for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
661       RigidBodyWorld *rbw = scene->rigidbody_world;
662 
663       if (rbw == NULL) {
664         continue;
665       }
666 
667       /* The substep method changed from "per second" to "per frame".
668        * To get the new value simply divide the old bullet sim fps with the scene fps.
669        */
670       rbw->substeps_per_frame /= FPS;
671 
672       if (rbw->substeps_per_frame <= 0) {
673         rbw->substeps_per_frame = 1;
674       }
675     }
676 
677     /* Set the minimum sequence interpolate for grease pencil. */
678     if (!DNA_struct_elem_find(fd->filesdna, "GP_Interpolate_Settings", "int", "step")) {
679       LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
680         ToolSettings *ts = scene->toolsettings;
681         ts->gp_interpolate.step = 1;
682       }
683     }
684 
685     /* Hair and PointCloud attributes. */
686     for (Hair *hair = bmain->hairs.first; hair != NULL; hair = hair->id.next) {
687       do_versions_point_attributes(&hair->pdata);
688     }
689     for (PointCloud *pointcloud = bmain->pointclouds.first; pointcloud != NULL;
690          pointcloud = pointcloud->id.next) {
691       do_versions_point_attributes(&pointcloud->pdata);
692     }
693 
694     /* Show outliner mode column by default. */
695     LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
696       LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
697         LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
698           if (space->spacetype == SPACE_OUTLINER) {
699             SpaceOutliner *space_outliner = (SpaceOutliner *)space;
700 
701             space_outliner->flag |= SO_MODE_COLUMN;
702           }
703         }
704       }
705     }
706 
707     /* Solver and Collections for Boolean. */
708     for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
709       LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
710         if (md->type == eModifierType_Boolean) {
711           BooleanModifierData *bmd = (BooleanModifierData *)md;
712           bmd->solver = eBooleanModifierSolver_Fast;
713           bmd->flag = eBooleanModifierFlag_Object;
714         }
715       }
716     }
717   }
718 
719   if (!MAIN_VERSION_ATLEAST(bmain, 291, 4) && MAIN_VERSION_ATLEAST(bmain, 291, 1)) {
720     /* Due to a48d78ce07f4f, CustomData.totlayer and CustomData.maxlayer has been written
721      * incorrectly. Fortunately, the size of the layers array has been written to the .blend file
722      * as well, so we can reconstruct totlayer and maxlayer from that. */
723     LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
724       mesh->vdata.totlayer = mesh->vdata.maxlayer = MEM_allocN_len(mesh->vdata.layers) /
725                                                     sizeof(CustomDataLayer);
726       mesh->edata.totlayer = mesh->edata.maxlayer = MEM_allocN_len(mesh->edata.layers) /
727                                                     sizeof(CustomDataLayer);
728       /* We can be sure that mesh->fdata is empty for files written by 2.90. */
729       mesh->ldata.totlayer = mesh->ldata.maxlayer = MEM_allocN_len(mesh->ldata.layers) /
730                                                     sizeof(CustomDataLayer);
731       mesh->pdata.totlayer = mesh->pdata.maxlayer = MEM_allocN_len(mesh->pdata.layers) /
732                                                     sizeof(CustomDataLayer);
733     }
734   }
735 
736   if (!MAIN_VERSION_ATLEAST(bmain, 291, 5)) {
737     /* Fix fcurves to allow for new bezier handles behaviour (T75881 and D8752). */
738     for (bAction *act = bmain->actions.first; act; act = act->id.next) {
739       for (FCurve *fcu = act->curves.first; fcu; fcu = fcu->next) {
740         /* Only need to fix Bezier curves with at least 2 keyframes. */
741         if (fcu->totvert < 2 || fcu->bezt == NULL) {
742           continue;
743         }
744         do_versions_291_fcurve_handles_limit(fcu);
745       }
746     }
747 
748     LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
749       collection->color_tag = COLLECTION_COLOR_NONE;
750     }
751     LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
752       /* Old files do not have a master collection, but it will be created by
753        * `BKE_collection_master_add()`. */
754       if (scene->master_collection) {
755         scene->master_collection->color_tag = COLLECTION_COLOR_NONE;
756       }
757     }
758 
759     /* Add custom profile and bevel mode to curve bevels. */
760     if (!DNA_struct_elem_find(fd->filesdna, "Curve", "char", "bevel_mode")) {
761       LISTBASE_FOREACH (Curve *, curve, &bmain->curves) {
762         if (curve->bevobj != NULL) {
763           curve->bevel_mode = CU_BEV_MODE_OBJECT;
764         }
765         else {
766           curve->bevel_mode = CU_BEV_MODE_ROUND;
767         }
768       }
769     }
770 
771     /* Ensure that new viewport display fields are initialized correctly. */
772     LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
773       LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
774         if (md->type == eModifierType_Fluid) {
775           FluidModifierData *fmd = (FluidModifierData *)md;
776           if (fmd->domain != NULL) {
777             if (!fmd->domain->coba_field && fmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) {
778               fmd->domain->coba_field = FLUID_DOMAIN_FIELD_PHI;
779             }
780             fmd->domain->grid_scale = 1.0;
781             fmd->domain->gridlines_upper_bound = 1.0;
782             fmd->domain->vector_scale_with_magnitude = true;
783             const float grid_lines[4] = {1.0, 0.0, 0.0, 1.0};
784             copy_v4_v4(fmd->domain->gridlines_range_color, grid_lines);
785           }
786         }
787       }
788     }
789   }
790 
791   if (!MAIN_VERSION_ATLEAST(bmain, 291, 6)) {
792     /* Darken Inactive Overlay. */
793     if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "fade_alpha")) {
794       for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
795         LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
796           LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
797             if (sl->spacetype == SPACE_VIEW3D) {
798               View3D *v3d = (View3D *)sl;
799               v3d->overlay.fade_alpha = 0.40f;
800               v3d->overlay.flag |= V3D_OVERLAY_FADE_INACTIVE;
801             }
802           }
803         }
804       }
805     }
806 
807     /* Unify symmetry as a mesh property. */
808     if (!DNA_struct_elem_find(fd->filesdna, "Mesh", "char", "symmetry")) {
809       LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
810         /* The previous flags used to store mesh symmetry in edit-mode match the new ones that are
811          * used in #Mesh.symmetry. */
812         mesh->symmetry = mesh->editflag & (ME_SYMMETRY_X | ME_SYMMETRY_Y | ME_SYMMETRY_Z);
813       }
814     }
815 
816     /* Alembic importer: allow vertex interpolation by default. */
817     for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
818       LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
819         if (md->type != eModifierType_MeshSequenceCache) {
820           continue;
821         }
822 
823         MeshSeqCacheModifierData *data = (MeshSeqCacheModifierData *)md;
824         data->read_flag |= MOD_MESHSEQ_INTERPOLATE_VERTICES;
825       }
826     }
827   }
828 
829   if (!MAIN_VERSION_ATLEAST(bmain, 291, 7)) {
830     LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
831       scene->r.simplify_volumes = 1.0f;
832     }
833   }
834 
835   if (!MAIN_VERSION_ATLEAST(bmain, 291, 8)) {
836     if (!DNA_struct_elem_find(fd->filesdna, "WorkSpaceDataRelation", "int", "parentid")) {
837       LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
838         LISTBASE_FOREACH_MUTABLE (
839             WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
840           relation->parent = blo_read_get_new_globaldata_address(fd, relation->parent);
841           BLI_assert(relation->parentid == 0);
842           if (relation->parent != NULL) {
843             LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
844               wmWindow *win = BLI_findptr(
845                   &wm->windows, relation->parent, offsetof(wmWindow, workspace_hook));
846               if (win != NULL) {
847                 relation->parentid = win->winid;
848                 break;
849               }
850             }
851             if (relation->parentid == 0) {
852               BLI_assert(
853                   !"Found a valid parent for workspace data relation, but no valid parent id.");
854             }
855           }
856           if (relation->parentid == 0) {
857             BLI_freelinkN(&workspace->hook_layout_relations, relation);
858           }
859         }
860       }
861     }
862 
863     /* UV/Image show overlay option. */
864     if (!DNA_struct_find(fd->filesdna, "SpaceImageOverlay")) {
865       LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
866         LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
867           LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
868             if (space->spacetype == SPACE_IMAGE) {
869               SpaceImage *sima = (SpaceImage *)space;
870               sima->overlay.flag = SI_OVERLAY_SHOW_OVERLAYS;
871             }
872           }
873         }
874       }
875     }
876 
877     /* Ensure that particle systems generated by fluid modifier have correct phystype. */
878     LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
879       if (ELEM(
880               part->type, PART_FLUID_FLIP, PART_FLUID_SPRAY, PART_FLUID_BUBBLE, PART_FLUID_FOAM)) {
881         part->phystype = PART_PHYS_NO;
882       }
883     }
884   }
885 
886   if (!MAIN_VERSION_ATLEAST(bmain, 291, 9)) {
887     /* Remove options of legacy UV/Image editor */
888     for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
889       LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
890         LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
891           switch (sl->spacetype) {
892             case SPACE_IMAGE: {
893               SpaceImage *sima = (SpaceImage *)sl;
894               sima->flag &= ~(SI_FLAG_UNUSED_20);
895               break;
896             }
897           }
898         }
899       }
900     }
901 
902     if (!DNA_struct_elem_find(fd->filesdna, "FluidModifierData", "float", "fractions_distance")) {
903       LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
904         LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
905           if (md->type == eModifierType_Fluid) {
906             FluidModifierData *fmd = (FluidModifierData *)md;
907             if (fmd->domain) {
908               fmd->domain->fractions_distance = 0.5;
909             }
910           }
911         }
912       }
913     }
914   }
915 
916   /**
917    * Versioning code until next subversion bump goes here.
918    *
919    * \note Be sure to check when bumping the version:
920    * - "versioning_userdef.c", #blo_do_versions_userdef
921    * - "versioning_userdef.c", #do_versions_theme
922    *
923    * \note Keep this message at the bottom of the function.
924    */
925   {
926     /* Keep this block, even when empty. */
927   }
928 }
929