2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup blenloader
|
2011-02-27 20:35:41 +00:00
|
|
|
*/
|
|
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
#include <cctype> /* for isdigit. */
|
|
|
|
|
#include <cerrno>
|
|
|
|
|
#include <climits>
|
|
|
|
|
#include <cstdarg> /* for va_start/end. */
|
|
|
|
|
#include <cstddef> /* for offsetof. */
|
|
|
|
|
#include <cstdlib> /* for atoi. */
|
|
|
|
|
#include <ctime> /* for gmtime. */
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <fcntl.h> /* for open flags (O_BINARY, O_RDONLY). */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2013-02-22 13:35:32 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2004-06-23 18:22:51 +00:00
|
|
|
#ifndef WIN32
|
2012-04-15 07:54:07 +00:00
|
|
|
# include <unistd.h> /* for read close */
|
2002-10-12 11:37:38 +00:00
|
|
|
#else
|
2012-04-15 07:54:07 +00:00
|
|
|
# include "BLI_winstuff.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
# include "winsock2.h"
|
|
|
|
|
# include <io.h> /* for open close read */
|
2002-10-12 11:37:38 +00:00
|
|
|
#endif
|
|
|
|
|
|
2021-06-23 14:23:54 +02:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
2011-12-04 06:05:48 +00:00
|
|
|
/* allow readfile to use deprecated functionality */
|
|
|
|
|
#define DNA_DEPRECATED_ALLOW
|
|
|
|
|
|
2009-01-18 10:41:45 +00:00
|
|
|
#include "DNA_anim_types.h"
|
2020-12-11 18:15:25 +01:00
|
|
|
#include "DNA_asset_types.h"
|
Basic Alembic support
All in all, this patch adds an Alembic importer, an Alembic exporter,
and a new CacheFile data block which, for now, wraps around an Alembic
archive. This data block is made available through a new modifier ("Mesh
Sequence Cache") as well as a new constraint ("Transform Cache") to
somewhat properly support respectively geometric and transformation data
streaming from alembic caches.
A more in-depth documentation is to be found on the wiki, as well as a
guide to compile alembic: https://wiki.blender.org/index.php/
User:Kevindietrich/AlembicBasicIo.
Many thanks to everyone involved in this little project, and huge shout
out to "cgstrive" for the thorough testings with Maya, 3ds Max, Houdini
and Realflow as well as @fjuhec, @jensverwiebe and @jasperge for the
custom builds and compile fixes.
Reviewers: sergey, campbellbarton, mont29
Reviewed By: sergey, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D2060
2016-08-06 06:20:37 +02:00
|
|
|
#include "DNA_cachefile_types.h"
|
2020-12-15 10:47:58 +11:00
|
|
|
#include "DNA_collection_types.h"
|
2005-05-02 13:28:13 +00:00
|
|
|
#include "DNA_fileglobal_types.h"
|
2008-10-31 23:50:02 +00:00
|
|
|
#include "DNA_genfile.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_key_types.h"
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
#include "DNA_layer_types.h"
|
Christmas coding work!
********* Node editor work:
- To enable Nodes for Materials, you have to set the "Use Nodes"
button, in the new Material buttons "Nodes" Panel or in header
of the Node editor. Doing this will disable Material-Layers.
- Nodes now execute materials ("shaders"), but still only using the
previewrender code.
- Nodes have (optional) previews for rendered images.
- Node headers allow to hide buttons and/or preview image
- Nodes can be dragged larger/smaller (right-bottom corner)
- Nodes can be hidden (minimized) with hotkey H
- CTRL+click on an Input Socket gives a popup with default values.
- Changing Material/Texture or Mix node will adjust Node title.
- Click-drag outside of a Node changes cursor to "Knife' and allows to
draw a rect where to cut Links.
- Added new node types RGBtoBW, Texture, In/Output, ColorRamp
- Material Nodes have options to ouput diffuse or specular, or to use
a negative normal. The input socket 'Normal' will force the material
to use that normal, otherwise it uses the normal from the Material
that has the node tree.
- When drawing a link between two not-matching sockets, Blender inserts
a converting node (now only for value/rgb combos)
- When drawing a link to an input socket that's already in use, the
old link will either disappear or flip to another unused socket.
- A click on a Material Node will activate it, and show all its settings
in the Material Buttons. Active Material Nodes draw the material icon
in red.
- A click on any node will show its options in the Node Panel in the
Material buttons.
- Multiple Output Nodes can be used, to sample contents of a tree, but
only one Output is the real one, which is indicated in a different
color and red material icon.
- Added ThemeColors for node types
- ALT+C will convert existing Material-Layers to Node... this currently
only adds the material/mix nodes and connects them. Dunno if this is
worth a lot of coding work to make perfect?
- Press C to call another "Solve order", which will show all possible
cyclic conflicts (if there are).
- Technical: nodes now use "Type" structs which define the
structure of nodes and in/output sockets. The Type structs store all
fixed info, callbacks, and allow to reconstruct saved Nodes to match
what is required by Blender.
- Defining (new) nodes now is as simple as filling in a fixed
Type struct, plus code some callbacks. A doc will be made!
- Node preview images are by default float
********* Icon drawing:
- Cleanup of how old icons were implemented in new system, making
them 16x16 too, correctly centered *and* scaled.
- Made drawing Icons use float coordinates
- Moved BIF_calcpreview_image() into interface_icons.c, renamed it
icon_from_image(). Removed a lot of unneeded Imbuf magic here! :)
- Skipped scaling and imbuf copying when icons are OK size
********* Preview render:
- Huge cleanup of code....
- renaming BIF_xxx calls that only were used internally
- BIF_previewrender() now accepts an argument for rendering method,
so it supports icons, buttonwindow previewrender and node editor
- Only a single BIF_preview_changed() call now exists, supporting all
signals as needed for buttos and node editor
********* More stuff:
- glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format
argument for GL_FLOAT rects
- Made the ColorBand become a built-in button for interface.c
Was a load of cleanup work in buttons_shading.c...
- removed a load of unneeded glBlendFunc() calls
- Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
|
|
|
#include "DNA_node_types.h"
|
2005-05-02 13:28:13 +00:00
|
|
|
#include "DNA_packedFile_types.h"
|
|
|
|
|
#include "DNA_sdna_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_sound_types.h"
|
2020-12-15 10:47:58 +11:00
|
|
|
#include "DNA_vfont_types.h"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "DNA_volume_types.h"
|
Main Workspace Integration
This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)
Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)
== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.
Opening files without UI and commandline rendering should work fine.
Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.
== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.
== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)
== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)
Reviewed By: campbellbarton, mont29
Tags: #user_interface, #bf_blender_2.8
Maniphest Tasks: T50521
Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
|
|
|
#include "DNA_workspace_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
2010-08-16 05:46:10 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BLI_blenlib.h"
|
2021-06-10 21:05:50 +10:00
|
|
|
#include "BLI_endian_defines.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_endian_switch.h"
|
|
|
|
|
#include "BLI_ghash.h"
|
2020-03-17 12:29:36 +01:00
|
|
|
#include "BLI_linklist.h"
|
2022-11-29 16:24:45 +01:00
|
|
|
#include "BLI_map.hh"
|
2020-07-03 11:36:27 +02:00
|
|
|
#include "BLI_memarena.h"
|
2013-08-03 11:35:09 +00:00
|
|
|
#include "BLI_mempool.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_threads.h"
|
2024-01-19 14:32:28 +01:00
|
|
|
#include "BLI_time.h"
|
2021-06-23 09:51:11 +02:00
|
|
|
|
2024-02-09 18:59:42 +01:00
|
|
|
#include "BLT_translation.hh"
|
2012-10-19 16:43:10 +00:00
|
|
|
|
2024-02-28 11:51:03 +01:00
|
|
|
#include "BKE_anim_data.hh"
|
2020-09-10 11:17:35 +02:00
|
|
|
#include "BKE_animsys.h"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_asset.hh"
|
2023-07-24 14:18:22 +02:00
|
|
|
#include "BKE_blender_version.h"
|
2024-02-09 19:42:38 +01:00
|
|
|
#include "BKE_collection.hh"
|
2024-02-10 18:25:14 +01:00
|
|
|
#include "BKE_global.hh" /* for G */
|
2024-03-26 12:57:30 -04:00
|
|
|
#include "BKE_idprop.hh"
|
2024-01-20 19:17:36 +01:00
|
|
|
#include "BKE_idtype.hh"
|
2024-01-23 15:18:09 -05:00
|
|
|
#include "BKE_layer.hh"
|
2024-01-15 12:44:04 -05:00
|
|
|
#include "BKE_lib_id.hh"
|
2023-08-02 15:00:40 +02:00
|
|
|
#include "BKE_lib_override.hh"
|
2024-01-18 12:20:42 +01:00
|
|
|
#include "BKE_lib_query.hh"
|
2023-11-30 19:51:22 +01:00
|
|
|
#include "BKE_lib_remap.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh" /* for Main */
|
2023-11-27 16:21:49 +01:00
|
|
|
#include "BKE_main_idmap.hh"
|
|
|
|
|
#include "BKE_main_namemap.hh"
|
2018-11-07 18:00:24 +01:00
|
|
|
#include "BKE_material.h"
|
2023-03-12 22:29:15 +01:00
|
|
|
#include "BKE_mesh.hh"
|
2023-11-14 09:30:40 +01:00
|
|
|
#include "BKE_modifier.hh"
|
2023-05-15 15:14:22 +02:00
|
|
|
#include "BKE_node.hh" /* for tree type defines */
|
2023-10-09 23:41:53 +02:00
|
|
|
#include "BKE_object.hh"
|
2020-09-10 14:35:09 +02:00
|
|
|
#include "BKE_packedFile.h"
|
2024-05-22 20:32:23 +10:00
|
|
|
#include "BKE_preferences.h"
|
2024-02-10 18:34:29 +01:00
|
|
|
#include "BKE_report.hh"
|
2024-02-10 19:16:25 +01:00
|
|
|
#include "BKE_scene.hh"
|
2023-09-25 17:48:21 -04:00
|
|
|
#include "BKE_screen.hh"
|
2024-01-15 12:26:09 -05:00
|
|
|
#include "BKE_undo_system.hh"
|
2024-04-12 17:03:18 -04:00
|
|
|
#include "BKE_workspace.hh"
|
2011-12-21 11:01:08 +00:00
|
|
|
|
2024-01-05 11:16:57 -05:00
|
|
|
#include "DRW_engine.hh"
|
2018-07-10 15:02:25 +02:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
2017-04-06 16:13:57 +02:00
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_blend_defs.hh"
|
|
|
|
|
#include "BLO_blend_validate.hh"
|
|
|
|
|
#include "BLO_read_write.hh"
|
2024-02-09 13:41:30 +01:00
|
|
|
#include "BLO_readfile.hh"
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_undofile.hh"
|
Biiig commit! Thanks to 2-3 weeks of cvs freeze...
Render:
- New; support for dual CPU render (SDL thread)
Currently only works with alternating scanlines, but gives excellent
performance. For both normal render as unified implemented.
Note the "mutex" locks on z-transp buffer render and imbuf loads.
- This has been made possible by major cleanups in render code, especially
getting rid of globals (example Tin Tr Tg Tb Ta for textures) or struct
OSA or using Materials or Texture data to write to.
- Made normal render fully 4x32 floats too, and removed all old optimizes
with chars or shorts.
- Made normal render and unified render use same code for sky and halo
render, giving equal (and better) results for halo render. Old render
now also uses PostProcess options (brightness, mul, gamma)
- Added option ("FBuf") in F10 Output Panel, this keeps a 4x32 bits buffer
after render. Using PostProcess menu you will note an immediate re-
display of image too (32 bits RGBA)
- Added "Hue" and "Saturation" sliders to PostProcess options
- Render module is still not having a "nice" API, but amount of dependencies
went down a lot. Next todo: remove abusive "previewrender" code.
The last main global in Render (struct Render) now can be re-used for fully
controlling a render, to allow multiple "instances" of render to open.
- Renderwindow now displays a smal bar on top with the stats, and keeps the
stats after render too. Including "spare" page support.
Not only easier visible that way, but also to remove the awkward code that
was drawing stats in the Info header (extreme slow on some ATIs too)
- Cleaned up blendef.h and BKE_utildefines.h, these two had overlapping
defines.
- I might have forgotten stuff... and will write a nice doc on the architecture!
2004-12-27 19:28:52 +00:00
|
|
|
|
2023-11-02 01:05:06 +01:00
|
|
|
#include "SEQ_iterator.hh"
|
|
|
|
|
#include "SEQ_modifier.hh"
|
|
|
|
|
#include "SEQ_sequencer.hh"
|
|
|
|
|
#include "SEQ_utils.hh"
|
2020-11-01 21:03:31 +01:00
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "readfile.hh"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-11-24 22:54:51 +11:00
|
|
|
/* Make preferences read-only. */
|
|
|
|
|
#define U (*((const UserDef *)&U))
|
|
|
|
|
|
2016-06-22 07:22:00 +10:00
|
|
|
/**
|
2012-06-30 22:49:33 +00:00
|
|
|
* READ
|
2016-06-22 07:22:00 +10:00
|
|
|
* ====
|
|
|
|
|
*
|
|
|
|
|
* - Existing Library (#Main) push or free
|
|
|
|
|
* - allocate new #Main
|
2012-06-30 22:49:33 +00:00
|
|
|
* - load file
|
2016-06-22 07:22:00 +10:00
|
|
|
* - read #SDNA
|
2012-06-30 22:49:33 +00:00
|
|
|
* - for each LibBlock
|
2016-06-22 07:22:00 +10:00
|
|
|
* - read LibBlock
|
|
|
|
|
* - if a Library
|
|
|
|
|
* - make a new #Main
|
|
|
|
|
* - attach ID's to it
|
|
|
|
|
* - else
|
|
|
|
|
* - read associated 'direct data'
|
|
|
|
|
* - link direct data (internal and to LibBlock)
|
|
|
|
|
* - read #FileGlobal
|
2023-06-08 10:33:50 +10:00
|
|
|
* - read #USER data, only when indicated (file is `~/.config/blender/X.X/config/userpref.blend`)
|
2012-06-30 22:49:33 +00:00
|
|
|
* - free file
|
2016-06-22 07:22:00 +10:00
|
|
|
* - per Library (per #Main)
|
|
|
|
|
* - read file
|
|
|
|
|
* - read #SDNA
|
|
|
|
|
* - find LibBlocks and attach #ID's to #Main
|
|
|
|
|
* - if external LibBlock
|
|
|
|
|
* - search all #Main's
|
|
|
|
|
* - or it's already read,
|
|
|
|
|
* - or not read yet
|
|
|
|
|
* - or make new #Main
|
|
|
|
|
* - per LibBlock
|
|
|
|
|
* - read recursive
|
|
|
|
|
* - read associated direct data
|
|
|
|
|
* - link direct data (internal and to LibBlock)
|
|
|
|
|
* - free file
|
2012-06-30 22:49:33 +00:00
|
|
|
* - per Library with unread LibBlocks
|
2016-06-22 07:22:00 +10:00
|
|
|
* - read file
|
|
|
|
|
* - read #SDNA
|
|
|
|
|
* - per LibBlock
|
|
|
|
|
* - read recursive
|
|
|
|
|
* - read associated direct data
|
|
|
|
|
* - link direct data (internal and to LibBlock)
|
|
|
|
|
* - free file
|
|
|
|
|
* - join all #Main's
|
2012-06-30 22:49:33 +00:00
|
|
|
* - link all LibBlocks and indirect pointers to libblocks
|
2016-06-22 07:22:00 +10:00
|
|
|
* - initialize #FileGlobal and copy pointers to #Global
|
|
|
|
|
*
|
2019-06-12 09:04:10 +10:00
|
|
|
* \note Still a weak point is the new-address function, that doesn't solve reading from
|
2016-06-22 07:22:00 +10:00
|
|
|
* multiple files at the same time.
|
|
|
|
|
* (added remark: oh, i thought that was solved? will look at that... (ton).
|
2012-10-04 13:26:15 +00:00
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-22 14:42:22 +11:00
|
|
|
/**
|
|
|
|
|
* Delay reading blocks we might not use (especially applies to library linking).
|
2019-02-25 08:54:10 +11:00
|
|
|
* which keeps large arrays in memory from data-blocks we may not even use.
|
|
|
|
|
*
|
|
|
|
|
* \note This is disabled when using compression,
|
2023-02-12 14:37:16 +11:00
|
|
|
* while ZLIB supports seek it's unusably slow, see: #61880.
|
2019-02-25 08:54:10 +11:00
|
|
|
*/
|
|
|
|
|
#define USE_BHEAD_READ_ON_DEMAND
|
2019-02-22 14:42:22 +11:00
|
|
|
|
2022-03-08 14:32:34 +11:00
|
|
|
/** Use #GHash for #BHead name-based lookups (speeds up linking). */
|
2015-03-11 00:33:44 +11:00
|
|
|
#define USE_GHASH_BHEAD
|
|
|
|
|
|
2022-03-08 14:32:34 +11:00
|
|
|
/** Use #GHash for restoring pointers by name. */
|
2016-06-07 16:07:13 +10:00
|
|
|
#define USE_GHASH_RESTORE_POINTER
|
|
|
|
|
|
2021-06-23 14:23:54 +02:00
|
|
|
static CLG_LogRef LOG = {"blo.readfile"};
|
|
|
|
|
static CLG_LogRef LOG_UNDO = {"blo.readfile.undo"};
|
2018-01-16 17:14:57 +01:00
|
|
|
|
2005-03-09 19:45:59 +00:00
|
|
|
/* local prototypes */
|
2019-02-22 18:15:56 +11:00
|
|
|
static void read_libraries(FileData *basefd, ListBase *mainlist);
|
2010-12-03 17:05:21 +00:00
|
|
|
static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
|
2015-03-11 00:33:44 +11:00
|
|
|
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
|
|
|
|
|
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
struct BHeadN {
|
2023-06-03 08:36:28 +10:00
|
|
|
BHeadN *next, *prev;
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
/** Use to read the data from the file directly into memory as needed. */
|
2019-03-19 20:04:23 +11:00
|
|
|
off64_t file_offset;
|
2019-02-22 14:42:22 +11:00
|
|
|
/** When set, the remainder of this allocation is the data, otherwise it needs to be read. */
|
|
|
|
|
bool has_data;
|
|
|
|
|
#endif
|
2020-03-17 12:29:36 +01:00
|
|
|
bool is_memchunk_identical;
|
2023-06-03 08:36:28 +10:00
|
|
|
BHead bhead;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2019-02-22 13:46:44 +11:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
#define BHEADN_FROM_BHEAD(bh) ((BHeadN *)POINTER_OFFSET(bh, -int(offsetof(BHeadN, bhead))))
|
2019-02-22 13:46:44 +11:00
|
|
|
|
2022-03-08 14:32:34 +11:00
|
|
|
/**
|
|
|
|
|
* We could change this in the future, for now it's simplest if only data is delayed
|
|
|
|
|
* because ID names are used in lookup tables.
|
|
|
|
|
*/
|
2023-04-08 12:42:40 +02:00
|
|
|
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == BLO_CODE_DATA)
|
2019-02-22 14:42:22 +11:00
|
|
|
|
2023-04-19 08:40:23 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Blend Loader Reporting Wrapper
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-10-19 18:33:42 +11:00
|
|
|
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format, ...)
|
2012-01-05 09:50:07 +00:00
|
|
|
{
|
|
|
|
|
char fixed_buf[1024]; /* should be long enough */
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-01-05 09:50:07 +00:00
|
|
|
va_list args;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-01-05 09:50:07 +00:00
|
|
|
va_start(args, format);
|
|
|
|
|
vsnprintf(fixed_buf, sizeof(fixed_buf), format, args);
|
|
|
|
|
va_end(args);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-01-05 09:50:07 +00:00
|
|
|
fixed_buf[sizeof(fixed_buf) - 1] = '\0';
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_report(reports->reports, type, fixed_buf);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
if (G.background == 0) {
|
2015-11-13 15:26:22 +01:00
|
|
|
printf("%s: %s\n", BKE_report_type_str(type), fixed_buf);
|
2012-01-05 09:50:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-19 12:49:01 +02:00
|
|
|
/* for reporting linking messages */
|
|
|
|
|
static const char *library_parent_filepath(Library *lib)
|
|
|
|
|
{
|
2024-04-08 13:08:36 +02:00
|
|
|
return lib->runtime.parent ? lib->runtime.parent->runtime.filepath_abs : "<direct>";
|
2014-10-19 12:49:01 +02:00
|
|
|
}
|
|
|
|
|
|
2023-04-19 08:40:23 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name OldNewMap API
|
|
|
|
|
* \{ */
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-11-29 16:24:45 +01:00
|
|
|
struct NewAddress {
|
2018-12-13 15:29:54 +01:00
|
|
|
void *newp;
|
2023-05-13 19:45:29 +02:00
|
|
|
|
|
|
|
|
/** `nr` is "user count" for data, and ID code for libdata. */
|
2018-12-13 15:29:54 +01:00
|
|
|
int nr;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
struct OldNewMap {
|
2022-11-29 16:24:45 +01:00
|
|
|
blender::Map<const void *, NewAddress> map;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2005-12-15 18:42:02 +00:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
static OldNewMap *oldnewmap_new()
|
2022-02-20 21:28:58 +11:00
|
|
|
{
|
2022-11-29 16:24:45 +01:00
|
|
|
return MEM_new<OldNewMap>(__func__);
|
2018-12-13 15:29:54 +01:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
if (oldaddr == nullptr || newaddr == nullptr) {
|
2018-12-13 15:29:54 +01:00
|
|
|
return;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-11-29 16:24:45 +01:00
|
|
|
onm->map.add_overwrite(oldaddr, NewAddress{newaddr, nr});
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-13 19:45:29 +02:00
|
|
|
static void oldnewmap_lib_insert(FileData *fd, const void *oldaddr, ID *newaddr, int id_code)
|
2022-07-28 16:26:02 +02:00
|
|
|
{
|
2023-05-13 19:45:29 +02:00
|
|
|
oldnewmap_insert(fd->libmap, oldaddr, newaddr, id_code);
|
2022-07-28 16:26:02 +02:00
|
|
|
}
|
|
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
|
2005-12-13 19:21:56 +00:00
|
|
|
{
|
2018-12-13 15:29:54 +01:00
|
|
|
oldnewmap_insert(onm, oldaddr, newaddr, nr);
|
|
|
|
|
}
|
2012-11-10 02:38:16 +00:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
static void *oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, bool increase_users)
|
|
|
|
|
{
|
2022-11-29 16:24:45 +01:00
|
|
|
NewAddress *entry = onm->map.lookup_ptr(addr);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (entry == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (increase_users) {
|
2018-12-13 15:29:54 +01:00
|
|
|
entry->nr++;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-12-13 15:29:54 +01:00
|
|
|
return entry->newp;
|
|
|
|
|
}
|
2012-11-10 02:38:16 +00:00
|
|
|
|
2022-11-29 16:24:45 +01:00
|
|
|
/* for libdata, NewAddress.nr has ID code, no increment */
|
2023-04-24 12:04:22 +02:00
|
|
|
static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const bool is_linked_only)
|
2018-12-13 15:29:54 +01:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
if (addr == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(oldnewmap_lookup_and_inc(onm, addr, false));
|
|
|
|
|
if (id == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2023-04-24 12:04:22 +02:00
|
|
|
if (!is_linked_only || ID_IS_LINKED(id)) {
|
2018-12-13 15:29:54 +01:00
|
|
|
return id;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
static void oldnewmap_clear(OldNewMap *onm)
|
2005-12-13 19:21:56 +00:00
|
|
|
{
|
2020-04-03 13:34:12 +02:00
|
|
|
/* Free unused data. */
|
2022-11-29 16:24:45 +01:00
|
|
|
for (NewAddress &new_addr : onm->map.values()) {
|
|
|
|
|
if (new_addr.nr == 0) {
|
|
|
|
|
MEM_freeN(new_addr.newp);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-09 12:07:40 +01:00
|
|
|
onm->map.clear_and_shrink();
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-17 17:06:07 +02:00
|
|
|
static void oldnewmap_free(OldNewMap *onm)
|
2005-12-13 19:21:56 +00:00
|
|
|
{
|
2022-11-29 16:24:45 +01:00
|
|
|
MEM_delete(onm);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Helper Functions
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
static void add_main_to_main(Main *mainvar, Main *from)
|
|
|
|
|
{
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX];
|
2002-10-12 11:37:38 +00:00
|
|
|
int a;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (from->is_read_invalid) {
|
|
|
|
|
mainvar->is_read_invalid = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-06 01:35:07 +00:00
|
|
|
set_listbasepointers(mainvar, lbarray);
|
2012-05-17 12:59:34 +00:00
|
|
|
a = set_listbasepointers(from, fromarray);
|
2012-03-24 07:52:14 +00:00
|
|
|
while (a--) {
|
2010-12-21 14:49:34 +00:00
|
|
|
BLI_movelisttolist(lbarray[a], fromarray[a]);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_join_main(ListBase *mainlist)
|
|
|
|
|
{
|
2006-12-01 10:12:41 +00:00
|
|
|
Main *tojoin, *mainl;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
mainl = static_cast<Main *>(mainlist->first);
|
2021-06-30 15:19:35 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (mainl->id_map != nullptr) {
|
2021-06-30 15:19:35 +02:00
|
|
|
/* Cannot keep this since we add some IDs from joined mains. */
|
|
|
|
|
BKE_main_idmap_destroy(mainl->id_map);
|
2022-09-15 19:13:01 +02:00
|
|
|
mainl->id_map = nullptr;
|
2021-06-30 15:19:35 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 12:43:43 +02:00
|
|
|
/* Will no longer be valid after joining. */
|
|
|
|
|
BKE_main_namemap_clear(mainl);
|
|
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
while ((tojoin = mainl->next)) {
|
2002-12-20 02:08:46 +00:00
|
|
|
add_main_to_main(mainl, tojoin);
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_remlink(mainlist, tojoin);
|
2023-03-01 15:14:11 +01:00
|
|
|
tojoin->next = tojoin->prev = nullptr;
|
2014-08-04 16:00:57 +02:00
|
|
|
BKE_main_free(tojoin);
|
2004-06-23 18:22:51 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2018-11-30 14:51:16 +11:00
|
|
|
static void split_libdata(ListBase *lb_src, Main **lib_main_array, const uint lib_main_array_len)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
for (ID *id = static_cast<ID *>(lb_src->first), *idnext; id; id = idnext) {
|
|
|
|
|
idnext = static_cast<ID *>(id->next);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (id->lib) {
|
2024-04-08 13:08:36 +02:00
|
|
|
if ((uint(id->lib->runtime.temp_index) < lib_main_array_len) &&
|
2019-08-17 00:54:22 +10:00
|
|
|
/* this check should never fail, just in case 'id->lib' is a dangling pointer. */
|
2024-04-08 13:08:36 +02:00
|
|
|
(lib_main_array[id->lib->runtime.temp_index]->curlib == id->lib))
|
2016-06-07 01:54:59 +10:00
|
|
|
{
|
2024-04-08 13:08:36 +02:00
|
|
|
Main *mainvar = lib_main_array[id->lib->runtime.temp_index];
|
2016-06-07 01:54:59 +10:00
|
|
|
ListBase *lb_dst = which_libbase(mainvar, GS(id->name));
|
|
|
|
|
BLI_remlink(lb_src, id);
|
|
|
|
|
BLI_addtail(lb_dst, id);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_ERROR(&LOG, "Invalid library for '%s'", id->name);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-25 13:07:28 +00:00
|
|
|
void blo_split_main(ListBase *mainlist, Main *main)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-17 12:59:34 +00:00
|
|
|
mainlist->first = mainlist->last = main;
|
2022-09-15 19:13:01 +02:00
|
|
|
main->next = nullptr;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (BLI_listbase_is_empty(&main->libraries)) {
|
2006-11-25 13:07:28 +00:00
|
|
|
return;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (main->id_map != nullptr) {
|
2021-06-30 15:19:35 +02:00
|
|
|
/* Cannot keep this since we remove some IDs from given main. */
|
|
|
|
|
BKE_main_idmap_destroy(main->id_map);
|
2022-09-15 19:13:01 +02:00
|
|
|
main->id_map = nullptr;
|
2021-06-30 15:19:35 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 12:43:43 +02:00
|
|
|
/* Will no longer be valid after splitting. */
|
|
|
|
|
BKE_main_namemap_clear(main);
|
|
|
|
|
|
2016-06-07 01:54:59 +10:00
|
|
|
/* (Library.temp_index -> Main), lookup table */
|
2019-03-08 09:29:17 +11:00
|
|
|
const uint lib_main_array_len = BLI_listbase_count(&main->libraries);
|
2022-09-15 19:13:01 +02:00
|
|
|
Main **lib_main_array = static_cast<Main **>(
|
|
|
|
|
MEM_malloc_arrayN(lib_main_array_len, sizeof(*lib_main_array), __func__));
|
2016-06-07 01:54:59 +10:00
|
|
|
|
|
|
|
|
int i = 0;
|
2022-09-15 19:13:01 +02:00
|
|
|
for (Library *lib = static_cast<Library *>(main->libraries.first); lib;
|
|
|
|
|
lib = static_cast<Library *>(lib->id.next), i++)
|
|
|
|
|
{
|
2013-12-26 17:24:42 +06:00
|
|
|
Main *libmain = BKE_main_new();
|
2012-05-17 12:59:34 +00:00
|
|
|
libmain->curlib = lib;
|
2024-04-08 13:08:36 +02:00
|
|
|
libmain->versionfile = lib->runtime.versionfile;
|
|
|
|
|
libmain->subversionfile = lib->runtime.subversionfile;
|
2023-07-24 14:18:22 +02:00
|
|
|
libmain->has_forward_compatibility_issues = !MAIN_VERSION_FILE_OLDER_OR_EQUAL(
|
|
|
|
|
libmain, BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION);
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_addtail(mainlist, libmain);
|
2024-04-08 13:08:36 +02:00
|
|
|
lib->runtime.temp_index = i;
|
2016-06-07 01:54:59 +10:00
|
|
|
lib_main_array[i] = libmain;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
2012-05-17 12:59:34 +00:00
|
|
|
i = set_listbasepointers(main, lbarray);
|
2016-06-07 01:54:59 +10:00
|
|
|
while (i--) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(lbarray[i]->first);
|
|
|
|
|
if (id == nullptr || GS(id->name) == ID_LI) {
|
2022-07-26 09:59:45 +02:00
|
|
|
/* No ID_LI data-block should ever be linked anyway, but just in case, better be explicit. */
|
2019-04-22 01:10:29 +10:00
|
|
|
continue;
|
2018-04-18 18:22:18 +02:00
|
|
|
}
|
2016-06-07 01:54:59 +10:00
|
|
|
split_libdata(lbarray[i], lib_main_array, lib_main_array_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(lib_main_array);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2007-11-30 15:12:31 +00:00
|
|
|
static void read_file_version(FileData *fd, Main *main)
|
|
|
|
|
{
|
|
|
|
|
BHead *bhead;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead->code == BLO_CODE_GLOB) {
|
2022-09-15 19:13:01 +02:00
|
|
|
FileGlobal *fg = static_cast<FileGlobal *>(read_struct(fd, bhead, "Global"));
|
2012-03-24 06:18:31 +00:00
|
|
|
if (fg) {
|
2018-11-30 14:51:16 +11:00
|
|
|
main->subversionfile = fg->subversion;
|
|
|
|
|
main->minversionfile = fg->minversion;
|
|
|
|
|
main->minsubversionfile = fg->minsubversion;
|
2007-11-30 15:12:31 +00:00
|
|
|
MEM_freeN(fg);
|
|
|
|
|
}
|
2023-04-08 12:42:40 +02:00
|
|
|
else if (bhead->code == BLO_CODE_ENDB) {
|
2007-11-30 15:12:31 +00:00
|
|
|
break;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2007-11-30 15:12:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-12-23 12:54:51 +01:00
|
|
|
if (main->curlib) {
|
2024-04-08 13:08:36 +02:00
|
|
|
main->curlib->runtime.versionfile = main->versionfile;
|
|
|
|
|
main->curlib->runtime.subversionfile = main->subversionfile;
|
2016-12-23 12:54:51 +01:00
|
|
|
}
|
2007-11-30 15:12:31 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-13 03:14:41 +11:00
|
|
|
static bool blo_bhead_is_id(const BHead *bhead)
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
{
|
|
|
|
|
/* BHead codes are four bytes (like 'ENDB', 'TEST', etc.), but if the two most-significant bytes
|
|
|
|
|
* are zero, the values actually indicate an ID type. */
|
|
|
|
|
return bhead->code <= 0xFFFF;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-13 03:14:41 +11:00
|
|
|
static bool blo_bhead_is_id_valid_type(const BHead *bhead)
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
{
|
|
|
|
|
if (!blo_bhead_is_id(bhead)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const short id_type_code = bhead->code & 0xFFFF;
|
|
|
|
|
return BKE_idtype_idcode_is_valid(id_type_code);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
|
|
|
|
static void read_file_bhead_idname_map_create(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
BHead *bhead;
|
|
|
|
|
|
|
|
|
|
/* dummy values */
|
|
|
|
|
bool is_link = false;
|
2023-04-08 12:42:40 +02:00
|
|
|
int code_prev = BLO_CODE_ENDB;
|
2018-11-30 14:51:16 +11:00
|
|
|
uint reserve = 0;
|
2015-03-11 00:33:44 +11:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2015-03-11 00:33:44 +11:00
|
|
|
if (code_prev != bhead->code) {
|
|
|
|
|
code_prev = bhead->code;
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
is_link = blo_bhead_is_id_valid_type(bhead) ?
|
2022-09-25 18:33:28 +10:00
|
|
|
BKE_idtype_idcode_is_linkable(short(code_prev)) :
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
false;
|
2015-03-11 00:33:44 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_link) {
|
|
|
|
|
reserve += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(fd->bhead_idname_hash == nullptr);
|
2015-03-11 00:33:44 +11:00
|
|
|
|
|
|
|
|
fd->bhead_idname_hash = BLI_ghash_str_new_ex(__func__, reserve);
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2015-03-11 00:33:44 +11:00
|
|
|
if (code_prev != bhead->code) {
|
|
|
|
|
code_prev = bhead->code;
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
is_link = blo_bhead_is_id_valid_type(bhead) ?
|
2022-09-25 18:33:28 +10:00
|
|
|
BKE_idtype_idcode_is_linkable(short(code_prev)) :
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
false;
|
2015-03-11 00:33:44 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_link) {
|
2019-02-22 10:31:17 +11:00
|
|
|
BLI_ghash_insert(fd->bhead_idname_hash, (void *)blo_bhead_id_name(fd, bhead), bhead);
|
2015-03-11 00:33:44 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-25 17:13:30 +00:00
|
|
|
static Main *blo_find_main(FileData *fd, const char *filepath, const char *relabase)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-25 17:13:30 +00:00
|
|
|
ListBase *mainlist = fd->mainlist;
|
2002-10-12 11:37:38 +00:00
|
|
|
Main *m;
|
|
|
|
|
Library *lib;
|
2023-05-03 14:13:27 +10:00
|
|
|
char filepath_abs[FILE_MAX];
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(filepath_abs, filepath);
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_path_abs(filepath_abs, relabase);
|
|
|
|
|
BLI_path_normalize(filepath_abs);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
// printf("blo_find_main: relabase %s\n", relabase);
|
|
|
|
|
// printf("blo_find_main: original in %s\n", filepath);
|
2023-05-03 14:13:27 +10:00
|
|
|
// printf("blo_find_main: converted to %s\n", filepath_abs);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (Main *, m, mainlist) {
|
2024-04-08 13:08:36 +02:00
|
|
|
const char *libname = (m->curlib) ? m->curlib->runtime.filepath_abs : m->filepath;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
if (BLI_path_cmp(filepath_abs, libname) == 0) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (G.debug & G_DEBUG) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG, 3, "Found library %s", libname);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
return m;
|
2005-12-14 13:21:32 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2013-12-26 17:24:42 +06:00
|
|
|
m = BKE_main_new();
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_addtail(mainlist, m);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Add library data-block itself to 'main' Main, since libraries are **never** linked data.
|
|
|
|
|
* Fixes bug where you could end with all ID_LI data-blocks having the same name... */
|
2022-09-15 19:13:01 +02:00
|
|
|
lib = static_cast<Library *>(BKE_libblock_alloc(
|
|
|
|
|
static_cast<Main *>(mainlist->first), ID_LI, BLI_path_basename(filepath), 0));
|
2019-08-14 23:29:46 +10:00
|
|
|
|
|
|
|
|
/* Important, consistency with main ID reading code from read_libblock(). */
|
|
|
|
|
lib->id.us = ID_FAKE_USERS(lib);
|
|
|
|
|
|
2020-05-28 12:13:16 +02:00
|
|
|
/* Matches direct_link_library(). */
|
2020-02-14 12:16:16 +01:00
|
|
|
id_us_ensure_real(&lib->id);
|
|
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(lib->filepath, filepath);
|
2024-04-08 13:08:36 +02:00
|
|
|
STRNCPY(lib->runtime.filepath_abs, filepath_abs);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
m->curlib = lib;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2007-11-30 15:12:31 +00:00
|
|
|
read_file_version(fd, m);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (G.debug & G_DEBUG) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG, 3, "Added new lib %s", filepath);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
void blo_readfile_invalidate(FileData *fd, Main *bmain, const char *message)
|
|
|
|
|
{
|
2023-07-31 10:15:30 +10:00
|
|
|
/* Tag given `bmain`, and 'root 'local' main one (in case given one is a library one) as invalid.
|
2023-02-22 16:37:15 +01:00
|
|
|
*/
|
|
|
|
|
bmain->is_read_invalid = true;
|
2023-09-12 14:48:20 +10:00
|
|
|
for (; bmain->prev != nullptr; bmain = bmain->prev) {
|
|
|
|
|
/* Pass. */
|
|
|
|
|
}
|
2023-02-22 16:37:15 +01:00
|
|
|
bmain->is_read_invalid = true;
|
|
|
|
|
|
|
|
|
|
BLO_reportf_wrap(fd->reports,
|
|
|
|
|
RPT_ERROR,
|
|
|
|
|
"A critical error happened (the blend file is likely corrupted): %s",
|
|
|
|
|
message);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name File Parsing
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
struct BlendDataReader {
|
2020-06-05 11:44:36 +02:00
|
|
|
FileData *fd;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2020-06-05 11:44:36 +02:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
struct BlendLibReader {
|
2020-06-05 11:44:36 +02:00
|
|
|
FileData *fd;
|
|
|
|
|
Main *main;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2020-06-05 11:44:36 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static void switch_endian_bh4(BHead4 *bhead)
|
|
|
|
|
{
|
2003-04-26 18:01:01 +00:00
|
|
|
/* the ID_.. codes */
|
2019-04-22 09:13:00 +10:00
|
|
|
if ((bhead->code & 0xFFFF) == 0) {
|
2018-11-30 14:51:16 +11:00
|
|
|
bhead->code >>= 16;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead->code != BLO_CODE_ENDB) {
|
2012-09-03 07:37:38 +00:00
|
|
|
BLI_endian_switch_int32(&bhead->len);
|
|
|
|
|
BLI_endian_switch_int32(&bhead->SDNAnr);
|
|
|
|
|
BLI_endian_switch_int32(&bhead->nr);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void switch_endian_bh8(BHead8 *bhead)
|
|
|
|
|
{
|
2003-04-26 18:01:01 +00:00
|
|
|
/* the ID_.. codes */
|
2019-04-22 09:13:00 +10:00
|
|
|
if ((bhead->code & 0xFFFF) == 0) {
|
2018-11-30 14:51:16 +11:00
|
|
|
bhead->code >>= 16;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead->code != BLO_CODE_ENDB) {
|
2012-09-03 07:37:38 +00:00
|
|
|
BLI_endian_switch_int32(&bhead->len);
|
|
|
|
|
BLI_endian_switch_int32(&bhead->SDNAnr);
|
|
|
|
|
BLI_endian_switch_int32(&bhead->nr);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 18:17:12 +02:00
|
|
|
static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, bool do_endian_swap)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
BHead4 *bhead4 = (BHead4 *)bhead;
|
2012-09-15 04:57:51 +00:00
|
|
|
int64_t old;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bhead4->code = bhead8->code;
|
|
|
|
|
bhead4->len = bhead8->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead4->code != BLO_CODE_ENDB) {
|
2012-05-17 12:59:34 +00:00
|
|
|
/* perform a endian swap on 64bit pointers, otherwise the pointer might map to zero
|
|
|
|
|
* 0x0000000000000000000012345678 would become 0x12345678000000000000000000000000
|
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
if (do_endian_swap) {
|
2020-09-29 12:29:01 +02:00
|
|
|
BLI_endian_switch_uint64(&bhead8->old);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-28 15:44:12 +10:00
|
|
|
/* this patch is to avoid `intptr_t` being read from not-eight aligned positions
|
2012-04-22 11:54:53 +00:00
|
|
|
* is necessary on any modern 64bit architecture) */
|
2002-10-12 11:37:38 +00:00
|
|
|
memcpy(&old, &bhead8->old, 8);
|
2022-09-25 18:33:28 +10:00
|
|
|
bhead4->old = int(old >> 3);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bhead4->SDNAnr = bhead8->SDNAnr;
|
|
|
|
|
bhead4->nr = bhead8->nr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void bh8_from_bh4(BHead *bhead, BHead4 *bhead4)
|
|
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
BHead8 *bhead8 = (BHead8 *)bhead;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bhead8->code = bhead4->code;
|
|
|
|
|
bhead8->len = bhead4->len;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead8->code != BLO_CODE_ENDB) {
|
2012-05-17 12:59:34 +00:00
|
|
|
bhead8->old = bhead4->old;
|
|
|
|
|
bhead8->SDNAnr = bhead4->SDNAnr;
|
2018-11-30 14:51:16 +11:00
|
|
|
bhead8->nr = bhead4->nr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BHeadN *get_bhead(FileData *fd)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BHeadN *new_bhead = nullptr;
|
2023-10-10 15:36:15 +02:00
|
|
|
int64_t readsize;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd) {
|
2019-02-22 09:21:23 +11:00
|
|
|
if (!fd->is_eof) {
|
2010-10-31 15:39:37 +00:00
|
|
|
/* initializing to zero isn't strictly needed but shuts valgrind up
|
2009-06-08 20:08:19 +00:00
|
|
|
* since uninitialized memory gets compared */
|
2012-05-17 12:59:34 +00:00
|
|
|
BHead8 bhead8 = {0};
|
|
|
|
|
BHead4 bhead4 = {0};
|
2018-11-30 14:51:16 +11:00
|
|
|
BHead bhead = {0};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
/* First read the bhead structure.
|
|
|
|
|
* Depending on the platform the file was written on this can
|
|
|
|
|
* be a big or little endian BHead4 or BHead8 structure.
|
|
|
|
|
*
|
|
|
|
|
* As usual 'ENDB' (the last *partial* bhead of the file)
|
|
|
|
|
* needs some special handling. We don't want to EOF just yet.
|
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd->flags & FD_FLAGS_FILE_POINTSIZE_IS_4) {
|
2023-04-08 12:42:40 +02:00
|
|
|
bhead4.code = BLO_CODE_DATA;
|
2021-08-19 23:57:00 +02:00
|
|
|
readsize = fd->file->read(fd->file, &bhead4, sizeof(bhead4));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
if (readsize == sizeof(bhead4) || bhead4.code == BLO_CODE_ENDB) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
|
|
|
|
|
switch_endian_bh4(&bhead4);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
|
|
|
|
|
bh8_from_bh4(&bhead, &bhead4);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2024-01-22 15:58:18 +01:00
|
|
|
/* std::min is only to quiet '-Warray-bounds' compiler warning. */
|
2018-05-08 13:32:52 +02:00
|
|
|
BLI_assert(sizeof(bhead) == sizeof(bhead4));
|
2023-11-07 16:33:19 +11:00
|
|
|
memcpy(&bhead, &bhead4, std::min(sizeof(bhead), sizeof(bhead4)));
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-22 09:21:23 +11:00
|
|
|
fd->is_eof = true;
|
2018-11-30 14:51:16 +11:00
|
|
|
bhead.len = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2023-04-08 12:42:40 +02:00
|
|
|
bhead8.code = BLO_CODE_DATA;
|
2021-08-19 23:57:00 +02:00
|
|
|
readsize = fd->file->read(fd->file, &bhead8, sizeof(bhead8));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
if (readsize == sizeof(bhead8) || bhead8.code == BLO_CODE_ENDB) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
|
|
|
|
|
switch_endian_bh8(&bhead8);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
|
2020-10-08 18:17:12 +02:00
|
|
|
bh4_from_bh8(&bhead, &bhead8, (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2024-01-22 15:58:18 +01:00
|
|
|
/* std::min is only to quiet `-Warray-bounds` compiler warning. */
|
2018-05-08 13:32:52 +02:00
|
|
|
BLI_assert(sizeof(bhead) == sizeof(bhead8));
|
2023-11-07 16:33:19 +11:00
|
|
|
memcpy(&bhead, &bhead8, std::min(sizeof(bhead), sizeof(bhead8)));
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-22 09:21:23 +11:00
|
|
|
fd->is_eof = true;
|
2018-11-30 14:51:16 +11:00
|
|
|
bhead.len = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2005-12-21 16:18:59 +00:00
|
|
|
/* make sure people are not trying to pass bad blend files */
|
2019-02-22 09:21:23 +11:00
|
|
|
if (bhead.len < 0) {
|
|
|
|
|
fd->is_eof = true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
/* bhead now contains the (converted) bhead structure. Now read
|
|
|
|
|
* the associated data and put everything in a BHeadN (creative naming !)
|
|
|
|
|
*/
|
2019-02-22 14:42:22 +11:00
|
|
|
if (fd->is_eof) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
2022-09-15 19:13:01 +02:00
|
|
|
else if (fd->file->seek != nullptr && BHEAD_USE_READ_ON_DEMAND(&bhead)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
/* Delay reading bhead content. */
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead = static_cast<BHeadN *>(MEM_mallocN(sizeof(BHeadN), "new_bhead"));
|
2019-02-22 14:42:22 +11:00
|
|
|
if (new_bhead) {
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead->next = new_bhead->prev = nullptr;
|
2021-08-19 23:57:00 +02:00
|
|
|
new_bhead->file_offset = fd->file->offset;
|
2019-02-22 14:42:22 +11:00
|
|
|
new_bhead->has_data = false;
|
2020-03-17 12:29:36 +01:00
|
|
|
new_bhead->is_memchunk_identical = false;
|
2019-02-22 14:42:22 +11:00
|
|
|
new_bhead->bhead = bhead;
|
2023-01-09 22:03:14 +11:00
|
|
|
const off64_t seek_new = fd->file->seek(fd->file, bhead.len, SEEK_CUR);
|
|
|
|
|
if (UNLIKELY(seek_new == -1)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
fd->is_eof = true;
|
|
|
|
|
MEM_freeN(new_bhead);
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead = nullptr;
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
2023-01-09 22:03:14 +11:00
|
|
|
else {
|
|
|
|
|
BLI_assert(fd->file->offset == seek_new);
|
|
|
|
|
}
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
fd->is_eof = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else {
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead = static_cast<BHeadN *>(
|
2022-09-25 18:33:28 +10:00
|
|
|
MEM_mallocN(sizeof(BHeadN) + size_t(bhead.len), "new_bhead"));
|
2002-10-12 11:37:38 +00:00
|
|
|
if (new_bhead) {
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead->next = new_bhead->prev = nullptr;
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
new_bhead->file_offset = 0; /* don't seek. */
|
|
|
|
|
new_bhead->has_data = true;
|
|
|
|
|
#endif
|
2020-03-17 12:29:36 +01:00
|
|
|
new_bhead->is_memchunk_identical = false;
|
2002-10-12 11:37:38 +00:00
|
|
|
new_bhead->bhead = bhead;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
readsize = fd->file->read(fd->file, new_bhead + 1, size_t(bhead.len));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
if (readsize != bhead.len) {
|
2019-02-22 09:21:23 +11:00
|
|
|
fd->is_eof = true;
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(new_bhead);
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead = nullptr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
|
|
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
|
|
|
|
new_bhead->is_memchunk_identical = ((UndoReader *)fd->file)->memchunk_identical;
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-22 09:21:23 +11:00
|
|
|
fd->is_eof = true;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-06-23 18:22:51 +00:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
/* We've read a new block. Now add it to the list
|
|
|
|
|
* of blocks.
|
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
if (new_bhead) {
|
2019-03-04 01:01:52 +11:00
|
|
|
BLI_addtail(&fd->bhead_list, new_bhead);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 09:21:23 +11:00
|
|
|
return new_bhead;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
BHead *blo_bhead_first(FileData *fd)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
BHeadN *new_bhead;
|
2022-09-15 19:13:01 +02:00
|
|
|
BHead *bhead = nullptr;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
/* Rewind the file
|
|
|
|
|
* Read in a new block if necessary
|
|
|
|
|
*/
|
2022-09-15 19:13:01 +02:00
|
|
|
new_bhead = static_cast<BHeadN *>(fd->bhead_list.first);
|
|
|
|
|
if (new_bhead == nullptr) {
|
2002-10-12 11:37:38 +00:00
|
|
|
new_bhead = get_bhead(fd);
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (new_bhead) {
|
|
|
|
|
bhead = &new_bhead->bhead;
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 09:21:23 +11:00
|
|
|
return bhead;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
BHead *blo_bhead_prev(FileData * /*fd*/, BHead *thisblock)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-02-22 13:46:44 +11:00
|
|
|
BHeadN *bheadn = BHEADN_FROM_BHEAD(thisblock);
|
2012-05-17 12:59:34 +00:00
|
|
|
BHeadN *prev = bheadn->prev;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
return (prev) ? &prev->bhead : nullptr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
BHead *blo_bhead_next(FileData *fd, BHead *thisblock)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BHeadN *new_bhead = nullptr;
|
|
|
|
|
BHead *bhead = nullptr;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (thisblock) {
|
2012-08-01 15:21:39 +00:00
|
|
|
/* bhead is actually a sub part of BHeadN
|
|
|
|
|
* We calculate the BHeadN pointer from the BHead pointer below */
|
2019-02-22 13:46:44 +11:00
|
|
|
new_bhead = BHEADN_FROM_BHEAD(thisblock);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-08-01 15:21:39 +00:00
|
|
|
/* get the next BHeadN. If it doesn't exist we read in the next one */
|
2002-10-12 11:37:38 +00:00
|
|
|
new_bhead = new_bhead->next;
|
2022-09-15 19:13:01 +02:00
|
|
|
if (new_bhead == nullptr) {
|
2002-10-12 11:37:38 +00:00
|
|
|
new_bhead = get_bhead(fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (new_bhead) {
|
2012-08-01 15:21:39 +00:00
|
|
|
/* here we do the reverse:
|
|
|
|
|
* go from the BHeadN pointer to the BHead pointer */
|
2002-10-12 11:37:38 +00:00
|
|
|
bhead = &new_bhead->bhead;
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 09:21:23 +11:00
|
|
|
return bhead;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
static bool blo_bhead_read_data(FileData *fd, BHead *thisblock, void *buf)
|
|
|
|
|
{
|
|
|
|
|
bool success = true;
|
|
|
|
|
BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock);
|
|
|
|
|
BLI_assert(new_bhead->has_data == false && new_bhead->file_offset != 0);
|
2021-08-19 23:57:00 +02:00
|
|
|
off64_t offset_backup = fd->file->offset;
|
|
|
|
|
if (UNLIKELY(fd->file->seek(fd->file, new_bhead->file_offset, SEEK_SET) == -1)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
success = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-09-25 18:33:28 +10:00
|
|
|
if (fd->file->read(fd->file, buf, size_t(new_bhead->bhead.len)) != new_bhead->bhead.len) {
|
2019-02-22 14:42:22 +11:00
|
|
|
success = false;
|
|
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
|
|
|
|
new_bhead->is_memchunk_identical = ((UndoReader *)fd->file)->memchunk_identical;
|
|
|
|
|
}
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->file->seek(fd->file, offset_backup, SEEK_SET) == -1) {
|
2019-02-22 14:42:22 +11:00
|
|
|
success = false;
|
|
|
|
|
}
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BHead *blo_bhead_read_full(FileData *fd, BHead *thisblock)
|
|
|
|
|
{
|
|
|
|
|
BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock);
|
2022-09-15 19:13:01 +02:00
|
|
|
BHeadN *new_bhead_data = static_cast<BHeadN *>(
|
|
|
|
|
MEM_mallocN(sizeof(BHeadN) + new_bhead->bhead.len, "new_bhead"));
|
2019-02-22 14:42:22 +11:00
|
|
|
new_bhead_data->bhead = new_bhead->bhead;
|
|
|
|
|
new_bhead_data->file_offset = new_bhead->file_offset;
|
|
|
|
|
new_bhead_data->has_data = true;
|
2020-03-17 12:29:36 +01:00
|
|
|
new_bhead_data->is_memchunk_identical = false;
|
2019-02-22 14:42:22 +11:00
|
|
|
if (!blo_bhead_read_data(fd, thisblock, new_bhead_data + 1)) {
|
|
|
|
|
MEM_freeN(new_bhead_data);
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
|
|
|
|
return &new_bhead_data->bhead;
|
|
|
|
|
}
|
|
|
|
|
#endif /* USE_BHEAD_READ_ON_DEMAND */
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead)
|
Fix T34446: Make Local on linked mesh object: object gets removed if redo function is used.
Root of the issue is that we do not re-read lib data blocks and ID placholders (ID_ID bheads)
in undo context (in `blo_read_file_internal`), because `BLO_read_from_memfile` copies
lib datablocks and Main data directly from oldmain.
The idea being, linked data do not change from undo/redo.
This is valid as long as linked data was not changed by the undo step - but if some
was deleted or localized, it will be missing from oldmain, leading to data loss
(note that does not only concern objects, all linkable data types can be affected,
at least in theory).
This commit addresses that issue by carefully mixing reuse of needed data from oldmain,
and "normal" re-reading of missing one. Makes us swimming in some rather dark waters,
and gives a rather non-easy-to-follow code, but it seems to work quite well,
and only other solution would be to get rid of that optimization
(not re-reading all libs on undo/redo), which is not acceptable.
Also, thanks to @carlosdp for initial investigation of the issue.
Differential Revision: https://developer.blender.org/D1485
2015-10-12 12:15:05 +02:00
|
|
|
{
|
2021-03-08 14:44:57 +11:00
|
|
|
return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offset);
|
Fix T34446: Make Local on linked mesh object: object gets removed if redo function is used.
Root of the issue is that we do not re-read lib data blocks and ID placholders (ID_ID bheads)
in undo context (in `blo_read_file_internal`), because `BLO_read_from_memfile` copies
lib datablocks and Main data directly from oldmain.
The idea being, linked data do not change from undo/redo.
This is valid as long as linked data was not changed by the undo step - but if some
was deleted or localized, it will be missing from oldmain, leading to data loss
(note that does not only concern objects, all linkable data types can be affected,
at least in theory).
This commit addresses that issue by carefully mixing reuse of needed data from oldmain,
and "normal" re-reading of missing one. Makes us swimming in some rather dark waters,
and gives a rather non-easy-to-follow code, but it seems to work quite well,
and only other solution would be to get rid of that optimization
(not re-reading all libs on undo/redo), which is not acceptable.
Also, thanks to @carlosdp for initial investigation of the issue.
Differential Revision: https://developer.blender.org/D1485
2015-10-12 12:15:05 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-11 18:15:25 +01:00
|
|
|
AssetMetaData *blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead)
|
|
|
|
|
{
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
BLI_assert(blo_bhead_is_id_valid_type(bhead));
|
2021-03-08 14:44:57 +11:00
|
|
|
return (fd->id_asset_data_offset >= 0) ?
|
|
|
|
|
*(AssetMetaData **)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_asset_data_offset) :
|
2022-09-15 19:13:01 +02:00
|
|
|
nullptr;
|
2020-12-11 18:15:25 +01:00
|
|
|
}
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static void decode_blender_header(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
char header[SIZEOFBLENDERHEADER], num[4];
|
2023-10-10 15:36:15 +02:00
|
|
|
int64_t readsize;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
/* read in the header data */
|
2021-08-19 23:57:00 +02:00
|
|
|
readsize = fd->file->read(fd->file, header, sizeof(header));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-01-16 20:00:13 +11:00
|
|
|
if (readsize == sizeof(header) && STREQLEN(header, "BLENDER", 7) && ELEM(header[7], '_', '-') &&
|
|
|
|
|
ELEM(header[8], 'v', 'V') &&
|
|
|
|
|
(isdigit(header[9]) && isdigit(header[10]) && isdigit(header[11])))
|
|
|
|
|
{
|
|
|
|
|
fd->flags |= FD_FLAGS_FILE_OK;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-01-16 20:00:13 +11:00
|
|
|
/* what size are pointers in the file ? */
|
|
|
|
|
if (header[7] == '_') {
|
|
|
|
|
fd->flags |= FD_FLAGS_FILE_POINTSIZE_IS_4;
|
|
|
|
|
if (sizeof(void *) != 4) {
|
|
|
|
|
fd->flags |= FD_FLAGS_POINTSIZE_DIFFERS;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-01-16 20:00:13 +11:00
|
|
|
else {
|
|
|
|
|
if (sizeof(void *) != 8) {
|
|
|
|
|
fd->flags |= FD_FLAGS_POINTSIZE_DIFFERS;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-01-16 20:00:13 +11:00
|
|
|
/* is the file saved in a different endian
|
|
|
|
|
* than we need ?
|
|
|
|
|
*/
|
|
|
|
|
if (((header[8] == 'v') ? L_ENDIAN : B_ENDIAN) != ENDIAN_ORDER) {
|
|
|
|
|
fd->flags |= FD_FLAGS_SWITCH_ENDIAN;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-01-16 20:00:13 +11:00
|
|
|
/* get the version number */
|
|
|
|
|
memcpy(num, header + 9, 3);
|
|
|
|
|
num[3] = 0;
|
|
|
|
|
fd->fileversion = atoi(num);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-12 12:23:48 +10:00
|
|
|
/**
|
|
|
|
|
* \return Success if the file is read correctly, else set \a r_error_message.
|
|
|
|
|
*/
|
|
|
|
|
static bool read_file_dna(FileData *fd, const char **r_error_message)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
BHead *bhead;
|
2019-02-12 09:29:18 +11:00
|
|
|
int subversion = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead->code == BLO_CODE_GLOB) {
|
2019-02-12 09:29:18 +11:00
|
|
|
/* Before this, the subversion didn't exist in 'FileGlobal' so the subversion
|
|
|
|
|
* value isn't accessible for the purpose of DNA versioning in this case. */
|
|
|
|
|
if (fd->fileversion <= 242) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* We can't use read_global because this needs 'DNA1' to be decoded,
|
|
|
|
|
* however the first 4 chars are _always_ the subversion. */
|
2024-05-28 13:35:25 +10:00
|
|
|
const FileGlobal *fg = reinterpret_cast<const FileGlobal *>(&bhead[1]);
|
2019-04-22 09:13:00 +10:00
|
|
|
BLI_STATIC_ASSERT(offsetof(FileGlobal, subvstr) == 0, "Must be first: subvstr")
|
2019-02-12 09:29:18 +11:00
|
|
|
char num[5];
|
|
|
|
|
memcpy(num, fg->subvstr, 4);
|
|
|
|
|
num[4] = 0;
|
|
|
|
|
subversion = atoi(num);
|
|
|
|
|
}
|
2023-04-08 12:42:40 +02:00
|
|
|
else if (bhead->code == BLO_CODE_DNA1) {
|
2013-02-22 13:35:32 +00:00
|
|
|
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
|
2023-09-25 12:25:48 +10:00
|
|
|
const bool do_alias = false; /* Postpone until after #blo_do_versions_dna runs. */
|
2016-07-12 12:23:48 +10:00
|
|
|
fd->filesdna = DNA_sdna_from_data(
|
2023-09-25 12:25:48 +10:00
|
|
|
&bhead[1], bhead->len, do_endian_swap, true, do_alias, r_error_message);
|
2007-04-28 16:15:00 +00:00
|
|
|
if (fd->filesdna) {
|
2019-02-12 09:29:18 +11:00
|
|
|
blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion);
|
2023-09-25 12:25:48 +10:00
|
|
|
/* Allow aliased lookups (must be after version patching DNA). */
|
|
|
|
|
DNA_sdna_alias_data_ensure_structs_map(fd->filesdna);
|
|
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
fd->compflags = DNA_struct_get_compareflags(fd->filesdna, fd->memsdna);
|
2020-09-29 12:29:01 +02:00
|
|
|
fd->reconstruct_info = DNA_reconstruct_info_create(
|
|
|
|
|
fd->filesdna, fd->memsdna, fd->compflags);
|
2007-04-28 16:15:00 +00:00
|
|
|
/* used to retrieve ID names from (bhead+1) */
|
2023-09-25 12:56:00 +10:00
|
|
|
fd->id_name_offset = DNA_struct_member_offset_by_name_with_alias(
|
2023-09-24 15:56:53 +10:00
|
|
|
fd->filesdna, "ID", "char", "name[]");
|
2021-03-08 14:44:57 +11:00
|
|
|
BLI_assert(fd->id_name_offset != -1);
|
2023-09-25 12:56:00 +10:00
|
|
|
fd->id_asset_data_offset = DNA_struct_member_offset_by_name_with_alias(
|
2020-12-11 18:15:25 +01:00
|
|
|
fd->filesdna, "ID", "AssetMetaData", "*asset_data");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-07-12 12:23:48 +10:00
|
|
|
return true;
|
|
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
|
|
|
|
|
return false;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2023-04-08 12:42:40 +02:00
|
|
|
else if (bhead->code == BLO_CODE_ENDB) {
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-07-12 12:23:48 +10:00
|
|
|
*r_error_message = "Missing DNA block";
|
|
|
|
|
return false;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2006-11-26 21:17:15 +00:00
|
|
|
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
static int *read_file_thumbnail(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
BHead *bhead;
|
2022-09-15 19:13:01 +02:00
|
|
|
int *blend_thumb = nullptr;
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead->code == BLO_CODE_TEST) {
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
|
|
|
|
|
int *data = (int *)(bhead + 1);
|
|
|
|
|
|
2022-10-07 22:52:53 +11:00
|
|
|
if (bhead->len < sizeof(int[2])) {
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (do_endian_swap) {
|
|
|
|
|
BLI_endian_switch_int32(&data[0]);
|
|
|
|
|
BLI_endian_switch_int32(&data[1]);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-11 19:09:27 +11:00
|
|
|
const int width = data[0];
|
|
|
|
|
const int height = data[1];
|
|
|
|
|
if (!BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
|
2018-01-14 23:26:31 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (bhead->len < BLEN_THUMB_MEMSIZE_FILE(width, height)) {
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
blend_thumb = data;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-04-08 12:42:40 +02:00
|
|
|
if (bhead->code != BLO_CODE_REND) {
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
/* Thumbnail is stored in TEST immediately after first REND... */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return blend_thumb;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name File Data API
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
static FileData *filedata_new(BlendFileReadReport *reports)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(reports != nullptr);
|
2021-06-23 09:51:11 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
FileData *fd = static_cast<FileData *>(MEM_callocN(sizeof(FileData), "FileData"));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2016-07-12 12:53:49 +10:00
|
|
|
fd->memsdna = DNA_sdna_current_get();
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
fd->datamap = oldnewmap_new();
|
|
|
|
|
fd->globmap = oldnewmap_new();
|
|
|
|
|
fd->libmap = oldnewmap_new();
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
fd->reports = reports;
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return fd;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-31 10:15:30 +10:00
|
|
|
/**
|
|
|
|
|
* Check if #FileGlobal::minversion of the file is older than current Blender,
|
|
|
|
|
* return false if it is not.
|
|
|
|
|
* Should only be called after #read_file_dna was successfully executed.
|
|
|
|
|
*/
|
2023-07-24 14:18:22 +02:00
|
|
|
static bool is_minversion_older_than_blender(FileData *fd, ReportList *reports)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(fd->filesdna != nullptr);
|
|
|
|
|
for (BHead *bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
|
|
|
|
if (bhead->code != BLO_CODE_GLOB) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileGlobal *fg = static_cast<FileGlobal *>(read_struct(fd, bhead, "Global"));
|
|
|
|
|
if ((fg->minversion > BLENDER_FILE_VERSION) ||
|
|
|
|
|
(fg->minversion == BLENDER_FILE_VERSION && fg->minsubversion > BLENDER_FILE_SUBVERSION))
|
|
|
|
|
{
|
|
|
|
|
char writer_ver_str[16];
|
|
|
|
|
char min_reader_ver_str[16];
|
|
|
|
|
if (fd->fileversion == fg->minversion) {
|
|
|
|
|
BKE_blender_version_blendfile_string_from_values(
|
|
|
|
|
writer_ver_str, sizeof(writer_ver_str), short(fd->fileversion), fg->subversion);
|
|
|
|
|
BKE_blender_version_blendfile_string_from_values(
|
|
|
|
|
min_reader_ver_str, sizeof(min_reader_ver_str), fg->minversion, fg->minsubversion);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_blender_version_blendfile_string_from_values(
|
|
|
|
|
writer_ver_str, sizeof(writer_ver_str), short(fd->fileversion), -1);
|
|
|
|
|
BKE_blender_version_blendfile_string_from_values(
|
|
|
|
|
min_reader_ver_str, sizeof(min_reader_ver_str), fg->minversion, -1);
|
|
|
|
|
}
|
|
|
|
|
BKE_reportf(reports,
|
|
|
|
|
RPT_ERROR,
|
2024-01-11 19:49:03 +01:00
|
|
|
"The file was saved by a newer version, open it with Blender %s or later",
|
2023-07-24 14:18:22 +02:00
|
|
|
min_reader_ver_str);
|
|
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"%s: File saved by a newer version of Blender (%s), Blender %s or later is "
|
|
|
|
|
"needed to open it.",
|
|
|
|
|
fd->relabase,
|
|
|
|
|
writer_ver_str,
|
|
|
|
|
min_reader_ver_str);
|
|
|
|
|
MEM_freeN(fg);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(fg);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-19 00:50:21 +00:00
|
|
|
static FileData *blo_decode_and_check(FileData *fd, ReportList *reports)
|
2005-07-25 18:35:49 +00:00
|
|
|
{
|
|
|
|
|
decode_blender_header(fd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2005-07-25 18:35:49 +00:00
|
|
|
if (fd->flags & FD_FLAGS_FILE_OK) {
|
2022-09-15 19:13:01 +02:00
|
|
|
const char *error_message = nullptr;
|
2016-07-12 12:23:48 +10:00
|
|
|
if (read_file_dna(fd, &error_message) == false) {
|
|
|
|
|
BKE_reportf(
|
|
|
|
|
reports, RPT_ERROR, "Failed to read blend file '%s': %s", fd->relabase, error_message);
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
2022-09-15 19:13:01 +02:00
|
|
|
fd = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2023-07-28 09:43:51 +10:00
|
|
|
else if (is_minversion_older_than_blender(fd, reports)) {
|
2023-07-24 14:18:22 +02:00
|
|
|
blo_filedata_free(fd);
|
|
|
|
|
fd = nullptr;
|
|
|
|
|
}
|
2005-07-25 18:35:49 +00:00
|
|
|
}
|
2006-11-26 21:17:15 +00:00
|
|
|
else {
|
2012-10-19 16:43:10 +00:00
|
|
|
BKE_reportf(
|
|
|
|
|
reports, RPT_ERROR, "Failed to read blend file '%s', not a blend file", fd->relabase);
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
2022-09-15 19:13:01 +02:00
|
|
|
fd = nullptr;
|
2005-07-25 18:35:49 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2005-07-25 18:35:49 +00:00
|
|
|
return fd;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-24 23:42:05 +11:00
|
|
|
static FileData *blo_filedata_from_file_descriptor(const char *filepath,
|
2021-06-23 09:51:11 +02:00
|
|
|
BlendFileReadReport *reports,
|
2021-08-19 23:57:00 +02:00
|
|
|
int filedes)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-02-24 12:34:41 +11:00
|
|
|
char header[7];
|
2021-08-19 23:57:00 +02:00
|
|
|
FileReader *rawfile = BLI_filereader_new_file(filedes);
|
2022-09-15 19:13:01 +02:00
|
|
|
FileReader *file = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
errno = 0;
|
2021-08-19 23:57:00 +02:00
|
|
|
/* If opening the file failed or we can't read the header, give up. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (rawfile == nullptr || rawfile->read(rawfile, header, sizeof(header)) != sizeof(header)) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_reportf(reports->reports,
|
2019-02-24 12:34:41 +11:00
|
|
|
RPT_WARNING,
|
|
|
|
|
"Unable to read '%s': %s",
|
|
|
|
|
filepath,
|
2024-01-11 19:49:03 +01:00
|
|
|
errno ? strerror(errno) : RPT_("insufficient content"));
|
2021-08-19 23:57:00 +02:00
|
|
|
if (rawfile) {
|
|
|
|
|
rawfile->close(rawfile);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
close(filedes);
|
|
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-02-24 12:34:41 +11:00
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
/* Rewind the file after reading the header. */
|
|
|
|
|
rawfile->seek(rawfile, 0, SEEK_SET);
|
2021-01-14 22:02:48 +01:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
/* Check if we have a regular file. */
|
|
|
|
|
if (memcmp(header, "BLENDER", sizeof(header)) == 0) {
|
|
|
|
|
/* Try opening the file with memory-mapped IO. */
|
|
|
|
|
file = BLI_filereader_new_mmap(filedes);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (file == nullptr) {
|
2023-07-31 10:15:30 +10:00
|
|
|
/* `mmap` failed, so just keep using `rawfile`. */
|
2021-08-19 23:57:00 +02:00
|
|
|
file = rawfile;
|
2022-09-15 19:13:01 +02:00
|
|
|
rawfile = nullptr;
|
2021-01-14 22:02:48 +01:00
|
|
|
}
|
2019-02-24 12:34:41 +11:00
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
else if (BLI_file_magic_is_gzip(header)) {
|
|
|
|
|
file = BLI_filereader_new_gzip(rawfile);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (file != nullptr) {
|
|
|
|
|
rawfile = nullptr; /* The `Gzip` #FileReader takes ownership of `rawfile`. */
|
2019-02-24 12:34:41 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Add support for Zstandard compression for .blend files
Compressing blendfiles can help save a lot of disk space, but the slowdown
while loading and saving is a major annoyance.
Currently Blender uses Zlib (aka gzip aka Deflate) for compression, but there
are now several more modern algorithms that outperform it in every way.
In this patch, I decided for Zstandard aka Zstd for several reasons:
- It is widely supported, both in other programs and libraries as well as in
general-purpose compression utilities on Unix
- It is extremely flexible - spanning several orders of magnitude of
compression speeds depending on the level setting.
- It is pretty much on the Pareto frontier for all of its configurations
(meaning that no other algorithm is both faster and more efficient).
One downside of course is that older versions of Blender will not be able to
read these files, but one can always just re-save them without compression or
decompress the file manually with an external tool.
The implementation here saves additional metadata into the compressed file in
order to allow for efficient seeking when loading. This is standard-compliant
and will be ignored by other tools that support Zstd.
If the metadata is not present (e.g. because you manually compressed a .blend
file with another tool), Blender will fall back to sequential reading.
Saving is multithreaded to improve performance. Loading is currently not
multithreaded since it's not easy to predict the access patterns of the
loading code when seeking is supported.
In the future, we might want to look into making this more predictable or
disabling seeking for the main .blend file, which would then allow for
multiple background threads that decompress data ahead of time.
The compression level was chosen to get sizes comparable to previous versions
at much higher speeds. In the future, this could be exposed as an option.
Reviewed By: campbellbarton, brecht, mont29
Differential Revision: https://developer.blender.org/D5799
2021-08-21 03:15:31 +02:00
|
|
|
else if (BLI_file_magic_is_zstd(header)) {
|
|
|
|
|
file = BLI_filereader_new_zstd(rawfile);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (file != nullptr) {
|
|
|
|
|
rawfile = nullptr; /* The `Zstd` #FileReader takes ownership of `rawfile`. */
|
Add support for Zstandard compression for .blend files
Compressing blendfiles can help save a lot of disk space, but the slowdown
while loading and saving is a major annoyance.
Currently Blender uses Zlib (aka gzip aka Deflate) for compression, but there
are now several more modern algorithms that outperform it in every way.
In this patch, I decided for Zstandard aka Zstd for several reasons:
- It is widely supported, both in other programs and libraries as well as in
general-purpose compression utilities on Unix
- It is extremely flexible - spanning several orders of magnitude of
compression speeds depending on the level setting.
- It is pretty much on the Pareto frontier for all of its configurations
(meaning that no other algorithm is both faster and more efficient).
One downside of course is that older versions of Blender will not be able to
read these files, but one can always just re-save them without compression or
decompress the file manually with an external tool.
The implementation here saves additional metadata into the compressed file in
order to allow for efficient seeking when loading. This is standard-compliant
and will be ignored by other tools that support Zstd.
If the metadata is not present (e.g. because you manually compressed a .blend
file with another tool), Blender will fall back to sequential reading.
Saving is multithreaded to improve performance. Loading is currently not
multithreaded since it's not easy to predict the access patterns of the
loading code when seeking is supported.
In the future, we might want to look into making this more predictable or
disabling seeking for the main .blend file, which would then allow for
multiple background threads that decompress data ahead of time.
The compression level was chosen to get sizes comparable to previous versions
at much higher speeds. In the future, this could be exposed as an option.
Reviewed By: campbellbarton, brecht, mont29
Differential Revision: https://developer.blender.org/D5799
2021-08-21 03:15:31 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
/* Clean up `rawfile` if it wasn't taken over. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (rawfile != nullptr) {
|
2021-08-19 23:57:00 +02:00
|
|
|
rawfile->close(rawfile);
|
|
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
if (file == nullptr) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_reportf(reports->reports, RPT_WARNING, "Unrecognized file format '%s'", filepath);
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-02-24 12:34:41 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
FileData *fd = filedata_new(reports);
|
2021-08-19 23:57:00 +02:00
|
|
|
fd->file = file;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-24 10:46:26 +11:00
|
|
|
return fd;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
static FileData *blo_filedata_from_file_open(const char *filepath, BlendFileReadReport *reports)
|
2019-02-24 23:42:05 +11:00
|
|
|
{
|
|
|
|
|
errno = 0;
|
|
|
|
|
const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
|
|
|
|
|
if (file == -1) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_reportf(reports->reports,
|
2019-02-24 23:42:05 +11:00
|
|
|
RPT_WARNING,
|
|
|
|
|
"Unable to open '%s': %s",
|
|
|
|
|
filepath,
|
2024-01-11 19:49:03 +01:00
|
|
|
errno ? strerror(errno) : RPT_("unknown error reading file"));
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-02-24 23:42:05 +11:00
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
return blo_filedata_from_file_descriptor(filepath, reports, file);
|
2019-02-24 23:42:05 +11:00
|
|
|
}
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
FileData *blo_filedata_from_file(const char *filepath, BlendFileReadReport *reports)
|
2019-02-24 10:46:26 +11:00
|
|
|
{
|
|
|
|
|
FileData *fd = blo_filedata_from_file_open(filepath, reports);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (fd != nullptr) {
|
2008-09-11 13:00:54 +00:00
|
|
|
/* needed for library_append and read_libraries */
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(fd->relabase, filepath);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
return blo_decode_and_check(fd, reports->reports);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
/**
|
2019-04-22 01:10:29 +10:00
|
|
|
* Same as blo_filedata_from_file(), but does not reads DNA data, only header.
|
|
|
|
|
* Use it for light access (e.g. thumbnail reading).
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
*/
|
2019-02-22 10:31:17 +11:00
|
|
|
static FileData *blo_filedata_from_file_minimal(const char *filepath)
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BlendFileReadReport read_report{};
|
|
|
|
|
FileData *fd = blo_filedata_from_file_open(filepath, &read_report);
|
|
|
|
|
if (fd != nullptr) {
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
decode_blender_header(fd);
|
|
|
|
|
if (fd->flags & FD_FLAGS_FILE_OK) {
|
|
|
|
|
return fd;
|
|
|
|
|
}
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
FileData *blo_filedata_from_memory(const void *mem, int memsize, BlendFileReadReport *reports)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
if (!mem || memsize < SIZEOFBLENDERHEADER) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_report(
|
2024-01-11 19:49:03 +01:00
|
|
|
reports->reports, RPT_WARNING, (mem) ? RPT_("Unable to read") : RPT_("Unable to open"));
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
FileReader *mem_file = BLI_filereader_new_memory(mem, memsize);
|
|
|
|
|
FileReader *file = mem_file;
|
2020-08-07 12:31:44 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (BLI_file_magic_is_gzip(static_cast<const char *>(mem))) {
|
2021-08-19 23:57:00 +02:00
|
|
|
file = BLI_filereader_new_gzip(mem_file);
|
2020-08-07 12:31:44 +02:00
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
else if (BLI_file_magic_is_zstd(static_cast<const char *>(mem))) {
|
Add support for Zstandard compression for .blend files
Compressing blendfiles can help save a lot of disk space, but the slowdown
while loading and saving is a major annoyance.
Currently Blender uses Zlib (aka gzip aka Deflate) for compression, but there
are now several more modern algorithms that outperform it in every way.
In this patch, I decided for Zstandard aka Zstd for several reasons:
- It is widely supported, both in other programs and libraries as well as in
general-purpose compression utilities on Unix
- It is extremely flexible - spanning several orders of magnitude of
compression speeds depending on the level setting.
- It is pretty much on the Pareto frontier for all of its configurations
(meaning that no other algorithm is both faster and more efficient).
One downside of course is that older versions of Blender will not be able to
read these files, but one can always just re-save them without compression or
decompress the file manually with an external tool.
The implementation here saves additional metadata into the compressed file in
order to allow for efficient seeking when loading. This is standard-compliant
and will be ignored by other tools that support Zstd.
If the metadata is not present (e.g. because you manually compressed a .blend
file with another tool), Blender will fall back to sequential reading.
Saving is multithreaded to improve performance. Loading is currently not
multithreaded since it's not easy to predict the access patterns of the
loading code when seeking is supported.
In the future, we might want to look into making this more predictable or
disabling seeking for the main .blend file, which would then allow for
multiple background threads that decompress data ahead of time.
The compression level was chosen to get sizes comparable to previous versions
at much higher speeds. In the future, this could be exposed as an option.
Reviewed By: campbellbarton, brecht, mont29
Differential Revision: https://developer.blender.org/D5799
2021-08-21 03:15:31 +02:00
|
|
|
file = BLI_filereader_new_zstd(mem_file);
|
|
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (file == nullptr) {
|
2021-08-19 23:57:00 +02:00
|
|
|
/* Compression initialization failed. */
|
|
|
|
|
mem_file->close(mem_file);
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2020-08-07 12:31:44 +02:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
FileData *fd = filedata_new(reports);
|
|
|
|
|
fd->file = file;
|
2013-03-26 09:59:43 +00:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
return blo_decode_and_check(fd, reports->reports);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-17 12:29:36 +01:00
|
|
|
FileData *blo_filedata_from_memfile(MemFile *memfile,
|
2022-10-05 13:44:02 -05:00
|
|
|
const BlendFileReadParams *params,
|
2021-06-23 09:51:11 +02:00
|
|
|
BlendFileReadReport *reports)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
|
|
|
|
if (!memfile) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_report(reports->reports, RPT_WARNING, "Unable to open blend <memory>");
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
FileData *fd = filedata_new(reports);
|
2021-08-19 23:57:00 +02:00
|
|
|
fd->file = BLO_memfile_new_filereader(memfile, params->undo_direction);
|
2020-08-07 12:31:44 +02:00
|
|
|
fd->undo_direction = params->undo_direction;
|
2021-08-19 23:57:00 +02:00
|
|
|
fd->flags |= FD_FLAGS_IS_MEMFILE;
|
2020-08-07 12:31:44 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
return blo_decode_and_check(fd, reports->reports);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
void blo_filedata_free(FileData *fd)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2024-04-25 22:54:23 +10:00
|
|
|
/* Free all BHeadN data blocks */
|
2024-05-08 18:45:34 +02:00
|
|
|
#ifdef NDEBUG
|
2024-04-25 22:54:23 +10:00
|
|
|
BLI_freelistN(&fd->bhead_list);
|
2019-02-22 14:42:22 +11:00
|
|
|
#else
|
2024-04-25 22:54:23 +10:00
|
|
|
/* Sanity check we're not keeping memory we don't need. */
|
|
|
|
|
LISTBASE_FOREACH_MUTABLE (BHeadN *, new_bhead, &fd->bhead_list) {
|
|
|
|
|
if (fd->file->seek != nullptr && BHEAD_USE_READ_ON_DEMAND(&new_bhead->bhead)) {
|
|
|
|
|
BLI_assert(new_bhead->has_data == 0);
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
2024-04-25 22:54:23 +10:00
|
|
|
MEM_freeN(new_bhead);
|
|
|
|
|
}
|
2019-02-22 14:42:22 +11:00
|
|
|
#endif
|
2024-04-25 22:54:23 +10:00
|
|
|
fd->file->close(fd->file);
|
2016-07-12 12:53:49 +10:00
|
|
|
|
2024-04-25 22:54:23 +10:00
|
|
|
if (fd->filesdna) {
|
|
|
|
|
DNA_sdna_free(fd->filesdna);
|
|
|
|
|
}
|
|
|
|
|
if (fd->compflags) {
|
|
|
|
|
MEM_freeN((void *)fd->compflags);
|
|
|
|
|
}
|
|
|
|
|
if (fd->reconstruct_info) {
|
|
|
|
|
DNA_reconstruct_info_free(fd->reconstruct_info);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-04-25 22:54:23 +10:00
|
|
|
if (fd->datamap) {
|
|
|
|
|
oldnewmap_free(fd->datamap);
|
|
|
|
|
}
|
|
|
|
|
if (fd->globmap) {
|
|
|
|
|
oldnewmap_free(fd->globmap);
|
|
|
|
|
}
|
|
|
|
|
if (fd->packedmap) {
|
|
|
|
|
oldnewmap_free(fd->packedmap);
|
|
|
|
|
}
|
|
|
|
|
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP)) {
|
|
|
|
|
oldnewmap_free(fd->libmap);
|
|
|
|
|
}
|
|
|
|
|
if (fd->old_idmap_uid != nullptr) {
|
|
|
|
|
BKE_main_idmap_destroy(fd->old_idmap_uid);
|
|
|
|
|
}
|
|
|
|
|
if (fd->new_idmap_uid != nullptr) {
|
|
|
|
|
BKE_main_idmap_destroy(fd->new_idmap_uid);
|
|
|
|
|
}
|
|
|
|
|
blo_cache_storage_end(fd);
|
|
|
|
|
if (fd->bheadmap) {
|
|
|
|
|
MEM_freeN(fd->bheadmap);
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
2024-04-25 22:54:23 +10:00
|
|
|
if (fd->bhead_idname_hash) {
|
|
|
|
|
BLI_ghash_free(fd->bhead_idname_hash, nullptr, nullptr);
|
|
|
|
|
}
|
2015-03-11 00:33:44 +11:00
|
|
|
#endif
|
|
|
|
|
|
2024-04-25 22:54:23 +10:00
|
|
|
MEM_freeN(fd);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2023-04-19 08:40:23 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read Thumbnail from Blend File
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BlendThumbnail *data = nullptr;
|
2024-04-25 22:54:23 +10:00
|
|
|
|
|
|
|
|
FileData *fd = blo_filedata_from_file_minimal(filepath);
|
|
|
|
|
if (fd) {
|
|
|
|
|
if (const int *fd_data = read_file_thumbnail(fd)) {
|
|
|
|
|
const int width = fd_data[0];
|
|
|
|
|
const int height = fd_data[1];
|
|
|
|
|
if (BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
|
|
|
|
|
const size_t data_size = BLEN_THUMB_MEMSIZE(width, height);
|
|
|
|
|
data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
|
|
|
|
|
if (data) {
|
|
|
|
|
BLI_assert((data_size - sizeof(*data)) ==
|
|
|
|
|
(BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*fd_data) * 2)));
|
|
|
|
|
data->width = width;
|
|
|
|
|
data->height = height;
|
|
|
|
|
memcpy(data->rect, &fd_data[2], data_size - sizeof(*data));
|
|
|
|
|
}
|
2018-01-14 23:26:31 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-25 22:54:23 +10:00
|
|
|
blo_filedata_free(fd);
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-03 03:56:12 +01:00
|
|
|
short BLO_version_from_file(const char *filepath)
|
|
|
|
|
{
|
|
|
|
|
short version = 0;
|
|
|
|
|
FileData *fd = blo_filedata_from_file_minimal(filepath);
|
|
|
|
|
if (fd) {
|
|
|
|
|
version = fd->fileversion;
|
|
|
|
|
blo_filedata_free(fd);
|
|
|
|
|
}
|
|
|
|
|
return version;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Old/New Pointer Map
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Only direct data-blocks. */
|
2019-07-10 14:41:19 +10:00
|
|
|
static void *newdataadr(FileData *fd, const void *adr)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2013-08-07 19:29:15 +00:00
|
|
|
return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Only direct data-blocks. */
|
2019-07-10 14:41:19 +10:00
|
|
|
static void *newdataadr_no_us(FileData *fd, const void *adr)
|
2013-08-07 19:29:15 +00:00
|
|
|
{
|
|
|
|
|
return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-09-30 14:49:42 +02:00
|
|
|
void *blo_read_get_new_globaldata_address(FileData *fd, const void *adr)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2013-08-07 19:29:15 +00:00
|
|
|
return oldnewmap_lookup_and_inc(fd->globmap, adr, true);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Used to restore packed data after undo. */
|
2019-07-10 14:41:19 +10:00
|
|
|
static void *newpackedadr(FileData *fd, const void *adr)
|
2012-12-27 15:07:19 +00:00
|
|
|
{
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->packedmap && adr) {
|
2013-08-07 19:29:15 +00:00
|
|
|
return oldnewmap_lookup_and_inc(fd->packedmap, adr, true);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2013-08-07 19:29:15 +00:00
|
|
|
return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-10 14:41:19 +10:00
|
|
|
/* only lib data */
|
2023-09-22 12:02:32 +10:00
|
|
|
static void *newlibadr(FileData *fd, ID * /*self_id*/, const bool is_linked_only, const void *adr)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2023-04-24 12:04:22 +02:00
|
|
|
return oldnewmap_liblookup(fd->libmap, adr, is_linked_only);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-04-24 12:04:22 +02:00
|
|
|
void *blo_do_versions_newlibadr(FileData *fd,
|
|
|
|
|
ID *self_id,
|
|
|
|
|
const bool is_linked_only,
|
|
|
|
|
const void *adr)
|
2012-05-04 15:42:49 +00:00
|
|
|
{
|
2023-04-24 12:04:22 +02:00
|
|
|
return newlibadr(fd, self_id, is_linked_only, adr);
|
2012-05-04 15:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-10 14:41:19 +10:00
|
|
|
/* increases user number */
|
2022-09-15 19:13:01 +02:00
|
|
|
static void change_link_placeholder_to_real_ID_pointer_fd(FileData *fd,
|
|
|
|
|
const void *old,
|
|
|
|
|
void *newp)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-11-29 16:24:45 +01:00
|
|
|
for (NewAddress &entry : fd->libmap->map.values()) {
|
|
|
|
|
if (old == entry.newp && entry.nr == ID_LINK_PLACEHOLDER) {
|
|
|
|
|
entry.newp = newp;
|
2022-09-15 19:13:01 +02:00
|
|
|
if (newp) {
|
2022-11-29 16:24:45 +01:00
|
|
|
entry.nr = GS(((ID *)newp)->name);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
static void change_link_placeholder_to_real_ID_pointer(ListBase *mainlist,
|
|
|
|
|
FileData *basefd,
|
|
|
|
|
void *old,
|
2022-09-15 19:13:01 +02:00
|
|
|
void *newp)
|
2005-12-16 17:35:38 +00:00
|
|
|
{
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Main *, mainptr, mainlist) {
|
2005-12-16 17:35:38 +00:00
|
|
|
FileData *fd;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (mainptr->curlib) {
|
2024-04-08 13:08:36 +02:00
|
|
|
fd = mainptr->curlib->runtime.filedata;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-17 12:59:34 +00:00
|
|
|
fd = basefd;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (fd) {
|
2022-09-15 19:13:01 +02:00
|
|
|
change_link_placeholder_to_real_ID_pointer_fd(fd, old, newp);
|
2005-12-16 17:35:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-04-22 01:10:29 +10:00
|
|
|
/* XXX disabled this feature - packed files also belong in temp saves and quit.blend,
|
|
|
|
|
* to make restore work. */
|
2013-01-13 12:25:56 +00:00
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
static void insert_packedmap(FileData *fd, PackedFile *pf)
|
|
|
|
|
{
|
|
|
|
|
oldnewmap_insert(fd->packedmap, pf, pf, 0);
|
|
|
|
|
oldnewmap_insert(fd->packedmap, pf->data, pf->data, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
|
|
|
|
|
{
|
|
|
|
|
fd->packedmap = oldnewmap_new();
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Image *, ima, &oldmain->images) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (ima->packedfile) {
|
2015-05-31 18:28:28 +02:00
|
|
|
insert_packedmap(fd, ima->packedfile);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2015-05-31 18:28:28 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (imapf->packedfile) {
|
2015-04-06 10:40:12 -03:00
|
|
|
insert_packedmap(fd, imapf->packedfile);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (VFont *, vfont, &oldmain->fonts) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (vfont->packedfile) {
|
2012-12-27 15:07:19 +00:00
|
|
|
insert_packedmap(fd, vfont->packedfile);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (bSound *, sound, &oldmain->sounds) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (sound->packedfile) {
|
2012-12-27 15:07:19 +00:00
|
|
|
insert_packedmap(fd, sound->packedfile);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Volume *, volume, &oldmain->volumes) {
|
2020-03-17 14:41:48 +01:00
|
|
|
if (volume->packedfile) {
|
|
|
|
|
insert_packedmap(fd, volume->packedfile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Library *, lib, &oldmain->libraries) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (lib->packedfile) {
|
2012-12-27 15:07:19 +00:00
|
|
|
insert_packedmap(fd, lib->packedfile);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
|
|
|
|
|
{
|
|
|
|
|
/* used entries were restored, so we put them to zero */
|
2022-11-29 16:24:45 +01:00
|
|
|
for (NewAddress &entry : fd->packedmap->map.values()) {
|
|
|
|
|
if (entry.nr > 0) {
|
|
|
|
|
entry.newp = nullptr;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Image *, ima, &oldmain->images) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ima->packedfile = static_cast<PackedFile *>(newpackedadr(fd, ima->packedfile));
|
2015-05-31 18:28:28 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
|
2022-09-15 19:13:01 +02:00
|
|
|
imapf->packedfile = static_cast<PackedFile *>(newpackedadr(fd, imapf->packedfile));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (VFont *, vfont, &oldmain->fonts) {
|
2022-09-15 19:13:01 +02:00
|
|
|
vfont->packedfile = static_cast<PackedFile *>(newpackedadr(fd, vfont->packedfile));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (bSound *, sound, &oldmain->sounds) {
|
2022-09-15 19:13:01 +02:00
|
|
|
sound->packedfile = static_cast<PackedFile *>(newpackedadr(fd, sound->packedfile));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Library *, lib, &oldmain->libraries) {
|
2022-09-15 19:13:01 +02:00
|
|
|
lib->packedfile = static_cast<PackedFile *>(newpackedadr(fd, lib->packedfile));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Volume *, volume, &oldmain->volumes) {
|
2022-09-15 19:13:01 +02:00
|
|
|
volume->packedfile = static_cast<PackedFile *>(newpackedadr(fd, volume->packedfile));
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-17 12:29:36 +01:00
|
|
|
void blo_make_old_idmap_from_main(FileData *fd, Main *bmain)
|
|
|
|
|
{
|
2024-01-22 13:47:13 +01:00
|
|
|
if (fd->old_idmap_uid != nullptr) {
|
|
|
|
|
BKE_main_idmap_destroy(fd->old_idmap_uid);
|
2020-03-17 12:29:36 +01:00
|
|
|
}
|
2024-01-22 13:47:13 +01:00
|
|
|
fd->old_idmap_uid = BKE_main_idmap_create(bmain, false, nullptr, MAIN_IDMAP_TYPE_UID);
|
2020-03-17 12:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
struct BLOCacheStorage {
|
2020-07-03 11:36:27 +02:00
|
|
|
GHash *cache_map;
|
|
|
|
|
MemArena *memarena;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2020-07-03 11:36:27 +02:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
struct BLOCacheStorageValue {
|
2022-04-06 10:48:33 +02:00
|
|
|
void *cache_v;
|
|
|
|
|
uint new_usage_count;
|
2022-10-05 13:44:02 -05:00
|
|
|
};
|
2022-04-06 10:48:33 +02:00
|
|
|
|
2020-07-03 11:36:27 +02:00
|
|
|
/** Register a cache data entry to be preserved when reading some undo memfile. */
|
2022-04-06 10:48:33 +02:00
|
|
|
static void blo_cache_storage_entry_register(
|
2022-10-03 17:37:25 -05:00
|
|
|
ID *id, const IDCacheKey *key, void **cache_p, uint /*flags*/, void *cache_storage_v)
|
2020-07-03 11:36:27 +02:00
|
|
|
{
|
2024-01-22 13:47:13 +01:00
|
|
|
BLI_assert(key->id_session_uid == id->session_uid);
|
2020-07-03 18:55:32 +02:00
|
|
|
UNUSED_VARS_NDEBUG(id);
|
2020-07-03 11:36:27 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
BLOCacheStorage *cache_storage = static_cast<BLOCacheStorage *>(cache_storage_v);
|
2020-07-03 11:36:27 +02:00
|
|
|
BLI_assert(!BLI_ghash_haskey(cache_storage->cache_map, key));
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
IDCacheKey *storage_key = static_cast<IDCacheKey *>(
|
|
|
|
|
BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_key)));
|
2020-07-03 11:36:27 +02:00
|
|
|
*storage_key = *key;
|
2022-09-15 19:13:01 +02:00
|
|
|
BLOCacheStorageValue *storage_value = static_cast<BLOCacheStorageValue *>(
|
|
|
|
|
BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_value)));
|
2022-04-06 10:48:33 +02:00
|
|
|
storage_value->cache_v = *cache_p;
|
|
|
|
|
storage_value->new_usage_count = 0;
|
|
|
|
|
BLI_ghash_insert(cache_storage->cache_map, storage_key, storage_value);
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Restore a cache data entry from old ID into new one, when reading some undo memfile. */
|
2020-08-27 15:33:33 +10:00
|
|
|
static void blo_cache_storage_entry_restore_in_new(
|
2023-01-06 11:01:11 +01:00
|
|
|
ID *id, const IDCacheKey *key, void **cache_p, uint flags, void *cache_storage_v)
|
2020-07-03 11:36:27 +02:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BLOCacheStorage *cache_storage = static_cast<BLOCacheStorage *>(cache_storage_v);
|
2020-07-03 11:36:27 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (cache_storage == nullptr) {
|
2020-07-06 15:07:12 +02:00
|
|
|
/* In non-undo case, only clear the pointer if it is a purely runtime one.
|
|
|
|
|
* If it may be stored in a persistent way in the .blend file, direct_link code is responsible
|
|
|
|
|
* to properly deal with it. */
|
|
|
|
|
if ((flags & IDTYPE_CACHE_CB_FLAGS_PERSISTENT) == 0) {
|
2022-09-15 19:13:01 +02:00
|
|
|
*cache_p = nullptr;
|
2020-07-06 15:07:12 +02:00
|
|
|
}
|
2020-07-03 11:36:27 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 11:01:11 +01:00
|
|
|
/* Assume that when ID source is tagged as changed, its caches need to be cleared.
|
|
|
|
|
* NOTE: This is mainly a work-around for some IDs, like Image, which use a non-depsgraph-handled
|
|
|
|
|
* process for part of their updates.
|
|
|
|
|
*/
|
|
|
|
|
if (id->recalc & ID_RECALC_SOURCE) {
|
|
|
|
|
*cache_p = nullptr;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
BLOCacheStorageValue *storage_value = static_cast<BLOCacheStorageValue *>(
|
|
|
|
|
BLI_ghash_lookup(cache_storage->cache_map, key));
|
|
|
|
|
if (storage_value == nullptr) {
|
|
|
|
|
*cache_p = nullptr;
|
2020-07-03 11:36:27 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2022-04-06 10:48:33 +02:00
|
|
|
storage_value->new_usage_count++;
|
|
|
|
|
*cache_p = storage_value->cache_v;
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Clear as needed a cache data entry from old ID, when reading some undo memfile. */
|
2022-10-03 17:37:25 -05:00
|
|
|
static void blo_cache_storage_entry_clear_in_old(
|
|
|
|
|
ID * /*id*/, const IDCacheKey *key, void **cache_p, uint /*flags*/, void *cache_storage_v)
|
2020-07-03 11:36:27 +02:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BLOCacheStorage *cache_storage = static_cast<BLOCacheStorage *>(cache_storage_v);
|
2020-07-03 11:36:27 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
BLOCacheStorageValue *storage_value = static_cast<BLOCacheStorageValue *>(
|
|
|
|
|
BLI_ghash_lookup(cache_storage->cache_map, key));
|
|
|
|
|
if (storage_value == nullptr) {
|
|
|
|
|
*cache_p = nullptr;
|
2020-07-03 11:36:27 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* If that cache has been restored into some new ID, we want to remove it from old one, otherwise
|
|
|
|
|
* keep it there so that it gets properly freed together with its ID. */
|
2022-04-06 10:48:33 +02:00
|
|
|
if (storage_value->new_usage_count != 0) {
|
2022-09-15 19:13:01 +02:00
|
|
|
*cache_p = nullptr;
|
2022-04-06 10:48:33 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert(*cache_p == storage_value->cache_v);
|
|
|
|
|
}
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_cache_storage_init(FileData *fd, Main *bmain)
|
|
|
|
|
{
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(fd->cache_storage == nullptr);
|
|
|
|
|
fd->cache_storage = static_cast<BLOCacheStorage *>(
|
|
|
|
|
MEM_mallocN(sizeof(*fd->cache_storage), __func__));
|
2020-07-03 11:36:27 +02:00
|
|
|
fd->cache_storage->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
|
|
|
|
fd->cache_storage->cache_map = BLI_ghash_new(
|
|
|
|
|
BKE_idtype_cache_key_hash, BKE_idtype_cache_key_cmp, __func__);
|
|
|
|
|
|
|
|
|
|
ListBase *lb;
|
|
|
|
|
FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(lb->first);
|
|
|
|
|
if (id == nullptr) {
|
2020-07-03 11:36:27 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (type_info->foreach_cache == nullptr) {
|
2020-07-03 11:36:27 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id) {
|
|
|
|
|
if (ID_IS_LINKED(id)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-07-06 16:21:41 +02:00
|
|
|
BKE_idtype_id_foreach_cache(id, blo_cache_storage_entry_register, fd->cache_storage);
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_LISTBASE_ID_END;
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_LISTBASE_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-09-15 19:13:01 +02:00
|
|
|
fd->cache_storage = nullptr;
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
if (fd->cache_storage != nullptr) {
|
2020-07-03 11:36:27 +02:00
|
|
|
ListBase *lb;
|
|
|
|
|
FOREACH_MAIN_LISTBASE_BEGIN (bmain_old, lb) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(lb->first);
|
|
|
|
|
if (id == nullptr) {
|
2020-07-03 11:36:27 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (type_info->foreach_cache == nullptr) {
|
2020-07-03 11:36:27 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id) {
|
|
|
|
|
if (ID_IS_LINKED(id)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-07-06 16:21:41 +02:00
|
|
|
BKE_idtype_id_foreach_cache(id, blo_cache_storage_entry_clear_in_old, fd->cache_storage);
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_LISTBASE_ID_END;
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_LISTBASE_END;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_cache_storage_end(FileData *fd)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
if (fd->cache_storage != nullptr) {
|
|
|
|
|
BLI_ghash_free(fd->cache_storage->cache_map, nullptr, nullptr);
|
2020-07-03 11:36:27 +02:00
|
|
|
BLI_memarena_free(fd->cache_storage->memarena);
|
|
|
|
|
MEM_freeN(fd->cache_storage);
|
2022-09-15 19:13:01 +02:00
|
|
|
fd->cache_storage = nullptr;
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
2006-11-25 13:07:28 +00:00
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name DNA Struct Loading
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
static void switch_endian_structs(const SDNA *filesdna, BHead *bhead)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
int blocksize, nblocks;
|
|
|
|
|
char *data;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-11-30 14:51:16 +11:00
|
|
|
data = (char *)(bhead + 1);
|
2020-09-29 12:12:09 +02:00
|
|
|
blocksize = filesdna->types_size[filesdna->structs[bhead->SDNAnr]->type];
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
nblocks = bhead->nr;
|
2012-03-24 07:52:14 +00:00
|
|
|
while (nblocks--) {
|
2008-10-31 23:50:02 +00:00
|
|
|
DNA_struct_switch_endian(filesdna, bhead->SDNAnr, data);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
data += blocksize;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
static void *read_struct(FileData *fd, BHead *bh, const char *blockname)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
void *temp = nullptr;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (bh->len) {
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
BHead *bh_orig = bh;
|
2019-02-26 14:31:14 +11:00
|
|
|
#endif
|
2019-02-22 14:42:22 +11:00
|
|
|
|
2007-04-28 16:15:00 +00:00
|
|
|
/* switch is based on file dna */
|
2019-02-22 14:42:22 +11:00
|
|
|
if (bh->SDNAnr && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
|
|
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
if (BHEADN_FROM_BHEAD(bh)->has_data == false) {
|
|
|
|
|
bh = blo_bhead_read_full(fd, bh);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (UNLIKELY(bh == nullptr)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
fd->flags &= ~FD_FLAGS_FILE_OK;
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
|
|
|
|
}
|
2019-02-26 14:31:14 +11:00
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
switch_endian_structs(fd->filesdna, bh);
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2016-01-16 15:00:22 +11:00
|
|
|
if (fd->compflags[bh->SDNAnr] != SDNA_CMP_REMOVED) {
|
|
|
|
|
if (fd->compflags[bh->SDNAnr] == SDNA_CMP_NOT_EQUAL) {
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
if (BHEADN_FROM_BHEAD(bh)->has_data == false) {
|
|
|
|
|
bh = blo_bhead_read_full(fd, bh);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (UNLIKELY(bh == nullptr)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
fd->flags &= ~FD_FLAGS_FILE_OK;
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2020-09-29 12:29:01 +02:00
|
|
|
temp = DNA_struct_reconstruct(fd->reconstruct_info, bh->SDNAnr, bh->nr, (bh + 1));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2016-01-16 15:00:22 +11:00
|
|
|
/* SDNA_CMP_EQUAL */
|
2012-05-17 12:59:34 +00:00
|
|
|
temp = MEM_mallocN(bh->len, blockname);
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
if (BHEADN_FROM_BHEAD(bh)->has_data) {
|
|
|
|
|
memcpy(temp, (bh + 1), bh->len);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Instead of allocating the bhead, then copying it,
|
|
|
|
|
* read the data from the file directly into the memory. */
|
|
|
|
|
if (UNLIKELY(!blo_bhead_read_data(fd, bh, temp))) {
|
|
|
|
|
fd->flags &= ~FD_FLAGS_FILE_OK;
|
|
|
|
|
MEM_freeN(temp);
|
2022-09-15 19:13:01 +02:00
|
|
|
temp = nullptr;
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
2018-11-30 14:51:16 +11:00
|
|
|
memcpy(temp, (bh + 1), bh->len);
|
2019-02-22 14:42:22 +11:00
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-03-17 12:29:36 +01:00
|
|
|
|
2019-02-22 14:42:22 +11:00
|
|
|
#ifdef USE_BHEAD_READ_ON_DEMAND
|
|
|
|
|
if (bh_orig != bh) {
|
|
|
|
|
MEM_freeN(BHEADN_FROM_BHEAD(bh));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2004-06-23 18:22:51 +00:00
|
|
|
|
|
|
|
|
return temp;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
/* Like read_struct, but gets a pointer without allocating. Only works for
|
|
|
|
|
* undo since DNA must match. */
|
|
|
|
|
static const void *peek_struct_undo(FileData *fd, BHead *bhead)
|
|
|
|
|
{
|
2021-08-19 23:57:00 +02:00
|
|
|
BLI_assert(fd->flags & FD_FLAGS_IS_MEMFILE);
|
2020-04-04 17:38:07 +02:00
|
|
|
UNUSED_VARS_NDEBUG(fd);
|
2022-09-15 19:13:01 +02:00
|
|
|
return (bhead->len) ? (const void *)(bhead + 1) : nullptr;
|
2020-04-04 17:38:07 +02:00
|
|
|
}
|
|
|
|
|
|
2018-11-30 14:51:16 +11:00
|
|
|
static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
Link *ln, *prev;
|
|
|
|
|
void *poin;
|
2004-06-23 18:22:51 +00:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (BLI_listbase_is_empty(lb)) {
|
2014-02-08 06:07:10 +11:00
|
|
|
return;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
poin = newdataadr(fd, lb->first);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (lb->first) {
|
2002-10-12 11:37:38 +00:00
|
|
|
oldnewmap_insert(fd->globmap, lb->first, poin, 0);
|
|
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
lb->first = poin;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
ln = static_cast<Link *>(lb->first);
|
|
|
|
|
prev = nullptr;
|
2012-03-24 07:52:14 +00:00
|
|
|
while (ln) {
|
2012-05-17 12:59:34 +00:00
|
|
|
poin = newdataadr(fd, ln->next);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ln->next) {
|
2002-10-12 11:37:38 +00:00
|
|
|
oldnewmap_insert(fd->globmap, ln->next, poin, 0);
|
|
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
ln->next = static_cast<Link *>(poin);
|
2012-05-17 12:59:34 +00:00
|
|
|
ln->prev = prev;
|
|
|
|
|
prev = ln;
|
|
|
|
|
ln = ln->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
lb->last = prev;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read ID
|
|
|
|
|
* \{ */
|
2012-10-23 12:38:47 +00:00
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
static void after_liblink_id_process(BlendLibReader *reader, ID *id);
|
2020-02-06 16:25:15 +01:00
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
static void after_liblink_id_embedded_id_process(BlendLibReader *reader, ID *id)
|
2020-02-06 16:25:15 +01:00
|
|
|
{
|
2020-06-26 13:56:14 +02:00
|
|
|
|
2020-02-06 16:25:15 +01:00
|
|
|
/* Handle 'private IDs'. */
|
2024-05-13 16:07:12 +02:00
|
|
|
bNodeTree *nodetree = blender::bke::ntreeFromID(id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (nodetree != nullptr) {
|
2023-03-11 18:07:59 +01:00
|
|
|
after_liblink_id_process(reader, &nodetree->id);
|
|
|
|
|
|
|
|
|
|
if (nodetree->owner_id == nullptr) {
|
|
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"NULL owner_id pointer for embedded NodeTree of %s, should never happen",
|
|
|
|
|
id->name);
|
|
|
|
|
nodetree->owner_id = id;
|
|
|
|
|
}
|
|
|
|
|
else if (nodetree->owner_id != id) {
|
|
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"Inconsistent owner_id pointer for embedded NodeTree of %s, should never happen",
|
|
|
|
|
id->name);
|
|
|
|
|
nodetree->owner_id = id;
|
|
|
|
|
}
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GS(id->name) == ID_SCE) {
|
|
|
|
|
Scene *scene = (Scene *)id;
|
2022-09-15 19:13:01 +02:00
|
|
|
if (scene->master_collection != nullptr) {
|
2023-03-11 18:07:59 +01:00
|
|
|
after_liblink_id_process(reader, &scene->master_collection->id);
|
|
|
|
|
|
2023-11-23 14:11:14 +01:00
|
|
|
if (scene->master_collection->owner_id == nullptr) {
|
2023-03-11 18:07:59 +01:00
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"NULL owner_id pointer for embedded Scene Collection of %s, should never happen",
|
|
|
|
|
id->name);
|
2023-11-23 14:11:14 +01:00
|
|
|
scene->master_collection->owner_id = id;
|
2023-03-11 18:07:59 +01:00
|
|
|
}
|
2023-11-23 14:11:14 +01:00
|
|
|
else if (scene->master_collection->owner_id != id) {
|
2023-03-11 18:07:59 +01:00
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"Inconsistent owner_id pointer for embedded Scene Collection of %s, should "
|
|
|
|
|
"never happen",
|
|
|
|
|
id->name);
|
2023-11-23 14:11:14 +01:00
|
|
|
scene->master_collection->owner_id = id;
|
2023-03-11 18:07:59 +01:00
|
|
|
}
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
static void after_liblink_id_process(BlendLibReader *reader, ID *id)
|
2017-11-29 15:05:03 +01:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
/* NOTE: WM IDProperties are never written to file, hence they should always be nullptr here. */
|
|
|
|
|
BLI_assert((GS(id->name) != ID_WM) || id->properties == nullptr);
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
after_liblink_id_embedded_id_process(reader, id);
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
if (id_type->blend_read_after_liblink != nullptr) {
|
|
|
|
|
id_type->blend_read_after_liblink(reader, id);
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
static void direct_link_id_override_property(BlendDataReader *reader,
|
|
|
|
|
IDOverrideLibraryProperty *op)
|
2017-11-29 15:05:03 +01:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_string(reader, &op->rna_path);
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
op->tag = 0; /* Runtime only. */
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, IDOverrideLibraryPropertyOperation, &op->operations);
|
2020-04-16 16:19:44 +02:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
|
|
|
|
|
BLO_read_string(reader, &opop->subitem_reference_name);
|
|
|
|
|
BLO_read_string(reader, &opop->subitem_local_name);
|
2020-04-16 16:19:44 +02:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
opop->tag = 0; /* Runtime only. */
|
|
|
|
|
}
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-15 17:57:13 +02:00
|
|
|
static void direct_link_id_common(
|
2023-05-13 19:45:29 +02:00
|
|
|
BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int id_tag);
|
2020-02-06 16:25:15 +01:00
|
|
|
|
2020-06-07 11:16:14 +02:00
|
|
|
static void direct_link_id_embedded_id(BlendDataReader *reader,
|
|
|
|
|
Library *current_library,
|
|
|
|
|
ID *id,
|
|
|
|
|
ID *id_old)
|
2020-02-06 16:25:15 +01:00
|
|
|
{
|
|
|
|
|
/* Handle 'private IDs'. */
|
2024-05-13 16:07:12 +02:00
|
|
|
bNodeTree **nodetree = blender::bke::BKE_ntree_ptr_from_id(id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (nodetree != nullptr && *nodetree != nullptr) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, bNodeTree, nodetree);
|
2020-06-07 11:16:14 +02:00
|
|
|
direct_link_id_common(reader,
|
2020-05-15 17:57:13 +02:00
|
|
|
current_library,
|
|
|
|
|
(ID *)*nodetree,
|
2024-05-13 16:07:12 +02:00
|
|
|
id_old != nullptr ? (ID *)blender::bke::ntreeFromID(id_old) : nullptr,
|
2020-05-15 17:57:13 +02:00
|
|
|
0);
|
2023-05-15 15:14:22 +02:00
|
|
|
blender::bke::ntreeBlendReadData(reader, id, *nodetree);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GS(id->name) == ID_SCE) {
|
|
|
|
|
Scene *scene = (Scene *)id;
|
2022-09-15 19:13:01 +02:00
|
|
|
if (scene->master_collection != nullptr) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, Collection, &scene->master_collection);
|
2020-06-07 11:16:14 +02:00
|
|
|
direct_link_id_common(reader,
|
2020-05-15 17:57:13 +02:00
|
|
|
current_library,
|
2020-04-03 13:34:12 +02:00
|
|
|
&scene->master_collection->id,
|
2022-09-15 19:13:01 +02:00
|
|
|
id_old != nullptr ? &((Scene *)id_old)->master_collection->id :
|
|
|
|
|
nullptr,
|
2020-04-03 13:34:12 +02:00
|
|
|
0);
|
2022-09-05 15:46:00 +02:00
|
|
|
BKE_collection_blend_read_data(reader, scene->master_collection, &scene->id);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 19:30:42 +02:00
|
|
|
static int direct_link_id_restore_recalc_exceptions(const ID *id_current)
|
|
|
|
|
{
|
|
|
|
|
/* Exception for armature objects, where the pose has direct points to the
|
2022-05-05 10:55:51 +10:00
|
|
|
* armature data-block. */
|
2020-04-04 19:30:42 +02:00
|
|
|
if (GS(id_current->name) == ID_OB && ((Object *)id_current)->pose) {
|
|
|
|
|
return ID_RECALC_GEOMETRY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int direct_link_id_restore_recalc(const FileData *fd,
|
|
|
|
|
const ID *id_target,
|
|
|
|
|
const ID *id_current,
|
|
|
|
|
const bool is_identical)
|
|
|
|
|
{
|
|
|
|
|
/* These are the evaluations that had not been performed yet at the time the
|
|
|
|
|
* target undo state was written. These need to be done again, since they may
|
|
|
|
|
* flush back changes to the original datablock. */
|
|
|
|
|
int recalc = id_target->recalc;
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id_current == nullptr) {
|
2020-04-04 19:30:42 +02:00
|
|
|
/* ID does not currently exist in the database, so also will not exist in
|
|
|
|
|
* the dependency graphs. That means it will be newly created and as a
|
|
|
|
|
* result also fully re-evaluated regardless of the recalc flag set here. */
|
|
|
|
|
recalc |= ID_RECALC_ALL;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* If the contents datablock changed, the depsgraph needs to copy the
|
|
|
|
|
* datablock again to ensure it matches the original datablock. */
|
|
|
|
|
if (!is_identical) {
|
2024-02-19 15:54:08 +01:00
|
|
|
recalc |= ID_RECALC_SYNC_TO_EVAL;
|
2020-04-04 19:30:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Special exceptions. */
|
|
|
|
|
recalc |= direct_link_id_restore_recalc_exceptions(id_current);
|
|
|
|
|
|
|
|
|
|
/* Evaluations for the current state that have not been performed yet
|
2020-04-08 10:33:56 +10:00
|
|
|
* by the time we are performing this undo step. */
|
2020-04-04 19:30:42 +02:00
|
|
|
recalc |= id_current->recalc;
|
|
|
|
|
|
|
|
|
|
/* Tags that were set between the target state and the current state,
|
|
|
|
|
* that we need to perform again. */
|
2021-02-04 22:03:39 +01:00
|
|
|
if (fd->undo_direction == STEP_UNDO) {
|
2020-04-04 19:30:42 +02:00
|
|
|
/* Undo: tags from target to the current state. */
|
2020-04-13 17:38:34 +02:00
|
|
|
recalc |= id_current->recalc_up_to_undo_push;
|
2020-04-04 19:30:42 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2021-02-04 22:03:39 +01:00
|
|
|
BLI_assert(fd->undo_direction == STEP_REDO);
|
2020-04-04 19:30:42 +02:00
|
|
|
/* Redo: tags from current to the target state. */
|
2020-04-13 17:38:34 +02:00
|
|
|
recalc |= id_target->recalc_up_to_undo_push;
|
2020-04-04 19:30:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return recalc;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-15 17:57:13 +02:00
|
|
|
static void direct_link_id_common(
|
2023-05-13 19:45:29 +02:00
|
|
|
BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int id_tag)
|
2012-10-23 12:38:47 +00:00
|
|
|
{
|
2020-08-28 16:29:55 +02:00
|
|
|
if (!BLO_read_data_is_undo(reader)) {
|
2024-01-22 13:47:13 +01:00
|
|
|
/* When actually reading a file, we do want to reset/re-generate session UIDS.
|
2020-05-15 17:57:13 +02:00
|
|
|
* In undo case, we want to re-use existing ones. */
|
2024-01-22 13:47:13 +01:00
|
|
|
id->session_uid = MAIN_ID_SESSION_UID_UNSET;
|
2020-05-15 17:57:13 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-13 19:45:29 +02:00
|
|
|
if ((id_tag & LIB_TAG_TEMP_MAIN) == 0) {
|
2024-01-22 13:47:13 +01:00
|
|
|
BKE_lib_libblock_session_uid_ensure(id);
|
2021-03-09 01:01:31 +11:00
|
|
|
}
|
2020-05-15 17:57:13 +02:00
|
|
|
|
|
|
|
|
id->lib = current_library;
|
2023-08-11 12:28:54 +02:00
|
|
|
if (id->lib) {
|
|
|
|
|
/* Always fully clear fake user flag for linked data. */
|
|
|
|
|
id->flag &= ~LIB_FAKEUSER;
|
|
|
|
|
}
|
2020-05-15 17:57:13 +02:00
|
|
|
id->us = ID_FAKE_USERS(id);
|
|
|
|
|
id->icon_id = 0;
|
2022-09-15 19:13:01 +02:00
|
|
|
id->newid = nullptr; /* Needed because .blend may have been saved with crap value here... */
|
|
|
|
|
id->orig_id = nullptr;
|
|
|
|
|
id->py_instance = nullptr;
|
2020-05-15 17:57:13 +02:00
|
|
|
|
|
|
|
|
/* Initialize with provided tag. */
|
2022-12-20 13:05:47 +09:00
|
|
|
if (BLO_read_data_is_undo(reader)) {
|
2023-05-13 19:45:29 +02:00
|
|
|
id->tag = (id_tag & ~LIB_TAG_KEEP_ON_UNDO) | (id->tag & LIB_TAG_KEEP_ON_UNDO);
|
2022-12-20 13:05:47 +09:00
|
|
|
}
|
|
|
|
|
else {
|
2023-05-13 19:45:29 +02:00
|
|
|
id->tag = id_tag;
|
2022-12-20 13:05:47 +09:00
|
|
|
}
|
2020-05-15 17:57:13 +02:00
|
|
|
|
2021-09-17 16:22:29 +02:00
|
|
|
if (ID_IS_LINKED(id)) {
|
2022-09-15 19:13:01 +02:00
|
|
|
id->library_weak_reference = nullptr;
|
2021-09-17 16:22:29 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, LibraryWeakReference, &id->library_weak_reference);
|
2021-09-17 16:22:29 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-13 19:45:29 +02:00
|
|
|
if (id_tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
|
2020-06-05 14:34:00 +10:00
|
|
|
/* For placeholder we only need to set the tag and properly initialize generic ID fields above,
|
|
|
|
|
* no further data to read. */
|
2020-05-15 17:57:13 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 16:26:11 +02:00
|
|
|
BKE_animdata_blend_read_data(reader, id);
|
|
|
|
|
|
2020-12-11 18:15:25 +01:00
|
|
|
if (id->asset_data) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, AssetMetaData, &id->asset_data);
|
2020-12-11 18:15:25 +01:00
|
|
|
BKE_asset_metadata_read(reader, id->asset_data);
|
2021-10-25 08:02:08 -03:00
|
|
|
/* Restore runtime asset type info. */
|
|
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
id->asset_data->local_type_info = id_type->asset_type_info;
|
2020-12-11 18:15:25 +01:00
|
|
|
}
|
|
|
|
|
|
2021-06-26 21:35:18 +10:00
|
|
|
/* Link direct data of ID properties. */
|
2012-10-23 12:38:47 +00:00
|
|
|
if (id->properties) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, IDProperty, &id->properties);
|
2013-09-30 13:44:16 +00:00
|
|
|
/* this case means the data was written incorrectly, it should not happen */
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &id->properties);
|
2012-10-23 12:38:47 +00:00
|
|
|
}
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2019-09-16 14:52:06 +02:00
|
|
|
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
|
2018-04-04 12:00:57 +02:00
|
|
|
|
2020-02-05 15:49:57 +01:00
|
|
|
/* NOTE: It is important to not clear the recalc flags for undo/redo.
|
|
|
|
|
* Preserving recalc flags on redo/undo is the only way to make dependency graph detect
|
|
|
|
|
* that animation is to be evaluated on undo/redo. If this is not enforced by the recalc
|
|
|
|
|
* flags dependency graph does not do animation update to avoid loss of unkeyed changes.,
|
|
|
|
|
* which conflicts with undo/redo of changes to animation data itself.
|
|
|
|
|
*
|
|
|
|
|
* But for regular file load we clear the flag, since the flags might have been changed since
|
|
|
|
|
* the version the file has been saved with. */
|
2020-08-28 16:29:55 +02:00
|
|
|
if (!BLO_read_data_is_undo(reader)) {
|
2020-02-05 15:49:57 +01:00
|
|
|
id->recalc = 0;
|
2020-04-13 17:38:34 +02:00
|
|
|
id->recalc_after_undo_push = 0;
|
2020-03-17 12:29:36 +01:00
|
|
|
}
|
2020-06-07 11:16:14 +02:00
|
|
|
else if ((reader->fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
|
|
|
|
|
id->recalc = direct_link_id_restore_recalc(reader->fd, id, id_old, false);
|
2020-04-13 17:38:34 +02:00
|
|
|
id->recalc_after_undo_push = 0;
|
2020-02-05 15:49:57 +01:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 15:05:03 +01:00
|
|
|
/* Link direct data of overrides. */
|
2019-06-14 23:16:04 +02:00
|
|
|
if (id->override_library) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, IDOverrideLibrary, &id->override_library);
|
2023-02-12 14:37:16 +11:00
|
|
|
/* Work around file corruption on writing, see #86853. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id->override_library != nullptr) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, IDOverrideLibraryProperty, &id->override_library->properties);
|
|
|
|
|
LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) {
|
|
|
|
|
direct_link_id_override_property(reader, op);
|
|
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
id->override_library->runtime = nullptr;
|
2021-03-25 11:21:15 +01:00
|
|
|
}
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
|
|
|
|
|
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
|
|
|
|
|
if (drawdata) {
|
|
|
|
|
BLI_listbase_clear((ListBase *)drawdata);
|
|
|
|
|
}
|
2020-02-06 16:25:15 +01:00
|
|
|
|
|
|
|
|
/* Handle 'private IDs'. */
|
2020-06-07 11:16:14 +02:00
|
|
|
direct_link_id_embedded_id(reader, current_library, id, id_old);
|
2012-10-23 12:38:47 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read Animation (legacy for version patching)
|
|
|
|
|
* \{ */
|
2009-01-19 02:26:46 +00:00
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read ID: Shape Keys
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2013-11-29 23:16:13 +06:00
|
|
|
void blo_do_versions_key_uidgen(Key *key)
|
2012-09-23 18:50:56 +00:00
|
|
|
{
|
|
|
|
|
key->uidgen = 1;
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (KeyBlock *, block, &key->block) {
|
2012-09-23 18:50:56 +00:00
|
|
|
block->uid = key->uidgen++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read ID: Scene
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2014-11-11 19:39:20 +01:00
|
|
|
#ifdef USE_SETSCENE_CHECK
|
|
|
|
|
/**
|
2022-09-28 09:41:31 +10:00
|
|
|
* A version of #BKE_scene_validate_setscene with special checks for linked libraries.
|
2014-11-11 19:39:20 +01:00
|
|
|
*/
|
|
|
|
|
static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
|
|
|
|
|
{
|
|
|
|
|
Scene *sce_iter;
|
|
|
|
|
int a;
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (sce->set == nullptr) {
|
2020-02-05 16:18:17 +01:00
|
|
|
return true;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2014-11-11 19:39:20 +01:00
|
|
|
|
|
|
|
|
for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) {
|
2020-08-06 17:12:45 +10:00
|
|
|
/* This runs per library (before each libraries #Main has been joined),
|
|
|
|
|
* so we can't step into other libraries since `totscene` is only for this library.
|
|
|
|
|
*
|
|
|
|
|
* Also, other libraries may not have been linked yet,
|
|
|
|
|
* while we could check #LIB_TAG_NEED_LINK the library pointer check is sufficient. */
|
|
|
|
|
if (sce->id.lib != sce_iter->id.lib) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-02-05 16:18:17 +01:00
|
|
|
if (sce_iter->flag & SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK) {
|
|
|
|
|
return true;
|
2014-11-11 19:39:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (a > totscene) {
|
2022-09-15 19:13:01 +02:00
|
|
|
sce->set = nullptr;
|
2020-02-05 16:18:17 +01:00
|
|
|
return false;
|
2014-11-11 19:39:20 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
return true;
|
2014-11-11 19:39:20 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
static void lib_link_scenes_check_set(Main *bmain)
|
|
|
|
|
{
|
2014-11-11 19:39:20 +01:00
|
|
|
#ifdef USE_SETSCENE_CHECK
|
2020-02-05 16:18:17 +01:00
|
|
|
const int totscene = BLI_listbase_count(&bmain->scenes);
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
|
2020-02-05 16:18:17 +01:00
|
|
|
if (sce->flag & SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK) {
|
|
|
|
|
sce->flag &= ~SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK;
|
|
|
|
|
if (!scene_validate_setscene__liblink(sce, totscene)) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_WARN(&LOG, "Found cyclic background scene when linking %s", sce->id.name + 2);
|
2014-11-11 19:39:20 +01:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-02-05 16:18:17 +01:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(bmain, totscene);
|
2014-11-11 19:39:20 +01:00
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2014-11-11 19:39:20 +01:00
|
|
|
#undef USE_SETSCENE_CHECK
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2019-09-23 11:02:58 +02:00
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \name Read ID: Library
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2005-12-14 09:59:22 +00:00
|
|
|
static void direct_link_library(FileData *fd, Library *lib, Main *main)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
Main *newmain;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2024-04-08 13:08:36 +02:00
|
|
|
/* Make sure we have full path in lib->runtime.filepath_abs */
|
2023-05-27 15:24:52 +10:00
|
|
|
/* NOTE: Since existing libraries are searched by their absolute path, this has to be generated
|
2023-05-26 16:44:08 +02:00
|
|
|
* before the lookup below. Otherwise, in case the stored absolute filepath is not 'correct' (may
|
|
|
|
|
* be empty, or have been stored in a different 'relative path context'), the comparison below
|
|
|
|
|
* will always fail, leading to creating duplicates IDs of a same library. */
|
2023-05-27 15:24:52 +10:00
|
|
|
/* TODO: May be worth checking whether comparison below could use `lib->filepath` instead? */
|
2024-04-08 13:08:36 +02:00
|
|
|
STRNCPY(lib->runtime.filepath_abs, lib->filepath);
|
|
|
|
|
BLI_path_abs(lib->runtime.filepath_abs, fd->relabase);
|
|
|
|
|
BLI_path_normalize(lib->runtime.filepath_abs);
|
2023-05-26 16:44:08 +02:00
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
/* check if the library was already read */
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (Main *, newmain, fd->mainlist) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (newmain->curlib) {
|
2024-04-08 13:08:36 +02:00
|
|
|
if (BLI_path_cmp(newmain->curlib->runtime.filepath_abs, lib->runtime.filepath_abs) == 0) {
|
2020-11-06 15:07:10 +01:00
|
|
|
BLO_reportf_wrap(fd->reports,
|
2013-11-29 23:16:13 +06:00
|
|
|
RPT_WARNING,
|
2024-01-11 19:49:03 +01:00
|
|
|
RPT_("Library '%s', '%s' had multiple instances, save and reload!"),
|
2020-06-23 09:54:14 +10:00
|
|
|
lib->filepath,
|
2024-04-08 13:08:36 +02:00
|
|
|
lib->runtime.filepath_abs);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
change_link_placeholder_to_real_ID_pointer(fd->mainlist, fd, lib, newmain->curlib);
|
2023-09-25 16:56:17 +10:00
|
|
|
// change_link_placeholder_to_real_ID_pointer_fd(fd, lib, newmain->curlib);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
BLI_remlink(&main->libraries, lib);
|
2005-12-14 09:59:22 +00:00
|
|
|
MEM_freeN(lib);
|
2018-02-13 20:58:40 +01:00
|
|
|
|
2019-04-22 01:10:29 +10:00
|
|
|
/* Now, since Blender always expect **latest** Main pointer from fd->mainlist
|
|
|
|
|
* to be the active library Main pointer,
|
|
|
|
|
* where to add all non-library data-blocks found in file next, we have to switch that
|
2018-02-13 20:58:40 +01:00
|
|
|
* 'dupli' found Main to latest position in the list!
|
2019-04-10 08:40:49 +02:00
|
|
|
* Otherwise, you get weird disappearing linked data on a rather inconsistent basis.
|
2023-02-12 14:37:16 +11:00
|
|
|
* See also #53977 for reproducible case. */
|
2018-02-13 20:58:40 +01:00
|
|
|
BLI_remlink(fd->mainlist, newmain);
|
|
|
|
|
BLI_addtail(fd->mainlist, newmain);
|
|
|
|
|
|
2005-12-14 09:59:22 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-13 20:58:40 +01:00
|
|
|
|
2020-06-23 09:54:14 +10:00
|
|
|
// printf("direct_link_library: filepath %s\n", lib->filepath);
|
2024-04-08 13:08:36 +02:00
|
|
|
// printf("direct_link_library: filepath_abs %s\n", lib->runtime.filepath_abs);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-06-07 11:55:27 +02:00
|
|
|
BlendDataReader reader = {fd};
|
2020-09-10 14:35:09 +02:00
|
|
|
BKE_packedfile_blend_read(&reader, &lib->packedfile);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2003-04-26 18:01:01 +00:00
|
|
|
/* new main */
|
2013-12-26 17:24:42 +06:00
|
|
|
newmain = BKE_main_new();
|
2012-05-25 17:13:30 +00:00
|
|
|
BLI_addtail(fd->mainlist, newmain);
|
2012-05-17 12:59:34 +00:00
|
|
|
newmain->curlib = lib;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2024-04-08 13:08:36 +02:00
|
|
|
lib->runtime.parent = nullptr;
|
2020-05-28 12:13:16 +02:00
|
|
|
|
|
|
|
|
id_us_ensure_real(&lib->id);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-22 01:10:29 +10:00
|
|
|
/* Always call this once you have loaded new library data to set the relative paths correctly
|
|
|
|
|
* in relation to the blend file. */
|
2008-02-02 11:19:34 +00:00
|
|
|
static void fix_relpaths_library(const char *basepath, Main *main)
|
|
|
|
|
{
|
2021-12-13 16:22:19 +11:00
|
|
|
/* #BLO_read_from_memory uses a blank file-path. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (basepath == nullptr || basepath[0] == '\0') {
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Library *, lib, &main->libraries) {
|
2011-05-18 05:21:44 +00:00
|
|
|
/* when loading a linked lib into a file which has not been saved,
|
|
|
|
|
* there is nothing we can be relative to, so instead we need to make
|
|
|
|
|
* it absolute. This can happen when appending an object with a relative
|
2023-02-12 14:37:16 +11:00
|
|
|
* link into an unsaved blend file. See #27405.
|
2011-05-18 05:21:44 +00:00
|
|
|
* The remap relative option will make it relative again on save - campbell */
|
2020-06-23 09:54:14 +10:00
|
|
|
if (BLI_path_is_rel(lib->filepath)) {
|
2024-04-08 13:08:36 +02:00
|
|
|
STRNCPY(lib->filepath, lib->runtime.filepath_abs);
|
2011-05-18 05:21:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Library *, lib, &main->libraries) {
|
2011-05-18 05:21:44 +00:00
|
|
|
/* Libraries store both relative and abs paths, recreate relative paths,
|
2022-09-28 09:41:31 +10:00
|
|
|
* relative to the blend file since indirectly linked libraries will be
|
2019-04-22 01:10:29 +10:00
|
|
|
* relative to their direct linked library. */
|
2020-06-23 09:54:14 +10:00
|
|
|
if (BLI_path_is_rel(lib->filepath)) { /* if this is relative to begin with? */
|
2024-04-08 13:08:36 +02:00
|
|
|
STRNCPY(lib->filepath, lib->runtime.filepath_abs);
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_path_rel(lib->filepath, basepath);
|
2011-05-18 05:21:44 +00:00
|
|
|
}
|
2008-01-31 21:19:40 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read Library Data Block
|
|
|
|
|
* \{ */
|
|
|
|
|
|
LibOverride: Restore local references to virtual linked liboverrides on resync.
When resyncing linked liboverride data, new IDs may be created that do
not exist in actual library file (since the lib file has not been resynced).
If such 'virtual linked liboverrides' data-blocks are used locally (e.g.
by adding such object to a local collection), on next file read they will be
detected as missing.
Now resync code will list such missing linked IDs that were
liboverrides, and try to re-use them when matching (by root name and
library) with newly generated virtual liboverrides.
The process may not be 100% perfect, especially a perfect one-to-one
remapping cannot be ensured if source data keep being changed over and
over (because of the order in which virtual linked liboverrides
generated by resync may change over time). However, in practice this
should fix the vast majority of issues, especially if sane naming
practices are used on IDs.
---------------
For the record, an attempt was made to write liboverride data together
with the placeholders for linked IDs in .blendfile. In theory, this
should ensure a perfect and fully valid re-usage of such IDs.
However, for this to work, not only the liboverride data of linked IDs need
to be written on disk, but also all ID references in this data has to be
considered as directly linked, to ensure that such liboverride data can
be re-read properly.
Otherwise, these placeholders would get a liboverride data with NULL ID
pointers, which is useless.
Such change feels way to intrusive for the very limited benefit, so for
now would consider current solution as the best option.
Pull Request: https://projects.blender.org/blender/blender/pulls/107144
2023-05-08 18:22:33 +02:00
|
|
|
static ID *create_placeholder(Main *mainvar,
|
|
|
|
|
const short idcode,
|
|
|
|
|
const char *idname,
|
|
|
|
|
const int tag,
|
|
|
|
|
const bool was_liboverride)
|
2019-08-12 11:54:37 +02:00
|
|
|
{
|
|
|
|
|
ListBase *lb = which_libbase(mainvar, idcode);
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *ph_id = static_cast<ID *>(BKE_libblock_alloc_notest(idcode));
|
2019-08-12 11:54:37 +02:00
|
|
|
|
|
|
|
|
*((short *)ph_id->name) = idcode;
|
|
|
|
|
BLI_strncpy(ph_id->name + 2, idname, sizeof(ph_id->name) - 2);
|
|
|
|
|
BKE_libblock_init_empty(ph_id);
|
|
|
|
|
ph_id->lib = mainvar->curlib;
|
|
|
|
|
ph_id->tag = tag | LIB_TAG_MISSING;
|
|
|
|
|
ph_id->us = ID_FAKE_USERS(ph_id);
|
|
|
|
|
ph_id->icon_id = 0;
|
|
|
|
|
|
LibOverride: Restore local references to virtual linked liboverrides on resync.
When resyncing linked liboverride data, new IDs may be created that do
not exist in actual library file (since the lib file has not been resynced).
If such 'virtual linked liboverrides' data-blocks are used locally (e.g.
by adding such object to a local collection), on next file read they will be
detected as missing.
Now resync code will list such missing linked IDs that were
liboverrides, and try to re-use them when matching (by root name and
library) with newly generated virtual liboverrides.
The process may not be 100% perfect, especially a perfect one-to-one
remapping cannot be ensured if source data keep being changed over and
over (because of the order in which virtual linked liboverrides
generated by resync may change over time). However, in practice this
should fix the vast majority of issues, especially if sane naming
practices are used on IDs.
---------------
For the record, an attempt was made to write liboverride data together
with the placeholders for linked IDs in .blendfile. In theory, this
should ensure a perfect and fully valid re-usage of such IDs.
However, for this to work, not only the liboverride data of linked IDs need
to be written on disk, but also all ID references in this data has to be
considered as directly linked, to ensure that such liboverride data can
be re-read properly.
Otherwise, these placeholders would get a liboverride data with NULL ID
pointers, which is useless.
Such change feels way to intrusive for the very limited benefit, so for
now would consider current solution as the best option.
Pull Request: https://projects.blender.org/blender/blender/pulls/107144
2023-05-08 18:22:33 +02:00
|
|
|
if (was_liboverride) {
|
|
|
|
|
/* 'Abuse' `LIB_TAG_LIBOVERRIDE_NEED_RESYNC` to mark that placeholder missing linked ID as
|
|
|
|
|
* being a liboverride.
|
|
|
|
|
*
|
|
|
|
|
* This will be used by the liboverride resync process, see #lib_override_library_resync. */
|
|
|
|
|
ph_id->tag |= LIB_TAG_LIBOVERRIDE_NEED_RESYNC;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-12 11:54:37 +02:00
|
|
|
BLI_addtail(lb, ph_id);
|
2022-09-15 19:13:01 +02:00
|
|
|
id_sort_by_name(lb, ph_id, nullptr);
|
2019-08-12 11:54:37 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (mainvar->id_map != nullptr) {
|
2021-06-30 15:19:35 +02:00
|
|
|
BKE_main_idmap_insert_id(mainvar->id_map, ph_id);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-09 01:01:31 +11:00
|
|
|
if ((tag & LIB_TAG_TEMP_MAIN) == 0) {
|
2024-01-22 13:47:13 +01:00
|
|
|
BKE_lib_libblock_session_uid_ensure(ph_id);
|
2021-03-09 01:01:31 +11:00
|
|
|
}
|
2020-03-05 16:17:14 +01:00
|
|
|
|
2019-08-12 11:54:37 +02:00
|
|
|
return ph_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void placeholders_ensure_valid(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
/* Placeholder ObData IDs won't have any material, we have to update their objects for that,
|
|
|
|
|
* otherwise the inconsistency between both will lead to crashes (especially in Eevee?). */
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *obdata = static_cast<ID *>(ob->data);
|
|
|
|
|
if (obdata != nullptr && obdata->tag & LIB_TAG_MISSING) {
|
2020-02-05 11:23:58 +01:00
|
|
|
BKE_object_materials_test(bmain, ob, obdata);
|
2019-08-12 11:54:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-09 16:04:53 +01:00
|
|
|
static const char *idtype_alloc_name_get(short id_code)
|
|
|
|
|
{
|
|
|
|
|
static const std::array<std::string, INDEX_ID_MAX> id_alloc_names = [] {
|
|
|
|
|
auto n = decltype(id_alloc_names)();
|
|
|
|
|
for (int idtype_index = 0; idtype_index < INDEX_ID_MAX; idtype_index++) {
|
|
|
|
|
const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_idtype_index(idtype_index);
|
|
|
|
|
BLI_assert(idtype_info);
|
|
|
|
|
if (idtype_index == INDEX_ID_NULL) {
|
|
|
|
|
/* #INDEX_ID_NULL returns the #IDType_ID_LINK_PLACEHOLDER type info, here we will rather
|
|
|
|
|
* use it for unknown/invalid ID types. */
|
|
|
|
|
n[size_t(idtype_index)] = "Data from UNKNWOWN ID Type";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
n[size_t(idtype_index)] = std::string("Data from '") + idtype_info->name + "'";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n;
|
|
|
|
|
}();
|
|
|
|
|
|
|
|
|
|
const int idtype_index = BKE_idtype_idcode_to_index(id_code);
|
|
|
|
|
if (LIKELY(idtype_index >= 0 && idtype_index < INDEX_ID_MAX)) {
|
|
|
|
|
return id_alloc_names[size_t(idtype_index)].c_str();
|
|
|
|
|
}
|
|
|
|
|
return id_alloc_names[INDEX_ID_NULL].c_str();
|
Orange: more noodle updates!
**** NEW: Group Nodes
Node trees usually become messy and confusing quickly, so we need
not only a way to collapse Nodes into single 'groups', but also a
way to re-use that data to create libraries of effects.
This has been done by making a new Library data type, the NodeTree.
Everything that has been grouped is stored here, and available for
re-use, appending or linking. These NodeTrees are fully generic,
i.e. can store shader trees, composit trees, and so on. The 'type'
value as stored in the NodeTree will keep track of internal type
definitions and execute/drawing callbacks. Needless to say, re-using
shader trees in a composit tree is a bit useless, and will be
prevented in the browsing code. :)
So; any NodeTree can become a "Goup Node" inside in a NodeTree. This
Group Node then works just like any Node.
To prevent the current code to become too complex, I've disabled
the possibility to insert Groups inside of Groups. That might be
enabled later, but is a real nasty piece of code to get OK.
Since Group Nodes are a dynamic Node type, a lot of work has been
done to ensure Node definitions can be dynamic too, but still allow
to be stored in files, and allow to be verified for type-definition
changes on reloading. This system needs a little bit maturing still,
so the Python gurus should better wait a little bit! (Also for me to
write the definite API docs for it).
What works now:
- Press CTRL+G to create a new Group. The grouping code checks for
impossible selections (like an unselected node between selected nodes).
Everthing that's selected then gets removed from the current tree, and
inserted in a new NodeTree library data block. A Group Node then is
added which links to this new NodeTree.
- Press ALT+G to ungroup. This will not delete the NodeTree library
data, but just duplicate the Group into the current tree.
- Press TAB, or click on the NodeTree icon to edit Groups. Note that
NodeTrees are instances, so editing one Group will also change the
other users.
This also means that when removing nodes in a Group (or hiding sockets
or changing internal links) this is immediately corrected for all users
of this Group, also in other Materials.
- While editing Groups, only the internal Nodes can be edited. A single
click outside of the Group boundary will close this 'edit mode'.
What needs to be done:
- SHIFT+A menu in toolbox style, also including a list of Groups
- Enable the single-user button in the Group Node
- Displaying all (visible) internal group UI elements in the Node Panel
- Enable Library linking and prevent editing of Groups then.
**** NEW: Socket Visibility control
Node types will be generated with a lot of possible inputs or outputs,
and drawing all sockets all the time isn't very useful then.
A new option in the Node header ('plus' icon) allows to either hide all
unused sockets (first keypress) or to reveil them (when there are hidden
sockets, the icon displays black, otherwise it's blended).
Hidden sockets in Nodes also are not exported to a Group, so this way
you can control what options (in/outputs) exactly are available.
To be done:
- a way to hide individual sockets, like with a RMB click on it.
**** NEW: Nodes now render!
This is still quite primitive, more on a level to replace the (now
obsolete and disabled) Material Layers.
What needs to be done:
- make the "Geometry" node work properly, also for AA textures
- make the Texture Node work (does very little at the moment)
- give Material Nodes all inputs as needed (like Map-to Panel)
- find a way to export more data from a Material Node, like the
shadow value, or light intensity only, etc
Very important also to separate from the Material Buttons the
"global" options, like "Ztransp" or "Wire" or "Halo". These can not
be set for each Material-Node individually.
Also note that the Preview Render (Buttons window) now renders a bit
differently. This was a horrid piece of antique code, using a totally
incompatible way of rendering. Target is to fully re-use internal
render code for previews.
OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *id_old)
|
|
|
|
|
{
|
2020-06-07 11:16:14 +02:00
|
|
|
BlendDataReader reader = {fd};
|
|
|
|
|
|
2020-05-15 17:57:13 +02:00
|
|
|
/* Read part of datablock that is common between real and embedded datablocks. */
|
2020-06-07 11:16:14 +02:00
|
|
|
direct_link_id_common(&reader, main->curlib, id, id_old, tag);
|
2020-04-03 13:34:12 +02:00
|
|
|
|
|
|
|
|
if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
|
|
|
|
|
/* For placeholder we only need to set the tag, no further data to read. */
|
|
|
|
|
id->tag = tag;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-03 11:36:27 +02:00
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id_type->blend_read_data != nullptr) {
|
2020-08-28 13:05:48 +02:00
|
|
|
id_type->blend_read_data(&reader, id);
|
|
|
|
|
}
|
2020-07-03 11:36:27 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
/* XXX Very weakly handled currently, see comment in read_libblock() before trying to
|
|
|
|
|
* use it for anything new. */
|
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
|
|
switch (GS(id->name)) {
|
|
|
|
|
case ID_SCR:
|
2020-11-06 18:41:03 +01:00
|
|
|
success = BKE_screen_blend_read_data(&reader, (bScreen *)id);
|
2020-04-03 13:34:12 +02:00
|
|
|
break;
|
|
|
|
|
case ID_LI:
|
|
|
|
|
direct_link_library(fd, (Library *)id, main);
|
|
|
|
|
break;
|
2020-11-06 18:41:03 +01:00
|
|
|
default:
|
2020-08-28 15:45:11 +02:00
|
|
|
/* Do nothing. Handled by IDTypeInfo callback. */
|
|
|
|
|
break;
|
2020-04-03 13:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-03 11:36:27 +02:00
|
|
|
/* try to restore (when undoing) or clear ID's cache pointers. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id_type->foreach_cache != nullptr) {
|
2020-07-06 16:21:41 +02:00
|
|
|
BKE_idtype_id_foreach_cache(
|
|
|
|
|
id, blo_cache_storage_entry_restore_in_new, reader.fd->cache_storage);
|
2020-07-03 11:36:27 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 16:01:56 +02:00
|
|
|
/* Read all data associated with a datablock into datamap. */
|
|
|
|
|
static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *allocname)
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
{
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
while (bhead && bhead->code == BLO_CODE_DATA) {
|
2020-07-21 12:24:50 +10:00
|
|
|
/* The code below is useful for debugging leaks in data read from the blend file.
|
|
|
|
|
* Without this the messages only tell us what ID-type the memory came from,
|
|
|
|
|
* eg: `Data from OB len 64`, see #dataname.
|
|
|
|
|
* With the code below we get the struct-name to help tracking down the leak.
|
|
|
|
|
* This is kept disabled as the #malloc for the text always leaks memory. */
|
2010-02-13 13:38:10 +00:00
|
|
|
#if 0
|
2022-09-09 13:16:13 +02:00
|
|
|
if (bhead->SDNAnr == 0) {
|
|
|
|
|
/* The data type here is unclear because #writedata sets SDNAnr to 0. */
|
|
|
|
|
allocname = "likely raw data";
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-09-09 12:36:51 +02:00
|
|
|
SDNA_Struct *sp = fd->filesdna->structs[bhead->SDNAnr];
|
|
|
|
|
allocname = fd->filesdna->types[sp->type];
|
2020-07-21 12:24:50 +10:00
|
|
|
size_t allocname_size = strlen(allocname) + 1;
|
2022-11-15 12:41:55 +01:00
|
|
|
char *allocname_buf = static_cast<char *>(malloc(allocname_size));
|
2020-07-21 12:24:50 +10:00
|
|
|
memcpy(allocname_buf, allocname, allocname_size);
|
|
|
|
|
allocname = allocname_buf;
|
|
|
|
|
}
|
2010-02-13 13:38:10 +00:00
|
|
|
#endif
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-07-21 12:24:50 +10:00
|
|
|
void *data = read_struct(fd, bhead, allocname);
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
if (data) {
|
|
|
|
|
oldnewmap_insert(fd->datamap, bhead->old, data, 0);
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 16:01:56 +02:00
|
|
|
/* Verify if the datablock and all associated data is identical. */
|
|
|
|
|
static bool read_libblock_is_identical(FileData *fd, BHead *bhead)
|
|
|
|
|
{
|
|
|
|
|
/* Test ID itself. */
|
|
|
|
|
if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Test any other data that is part of ID (logic must match read_data_into_datamap). */
|
|
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
|
|
|
|
|
2023-04-08 12:42:40 +02:00
|
|
|
while (bhead && bhead->code == BLO_CODE_DATA) {
|
2020-04-03 16:01:56 +02:00
|
|
|
if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* Re-use the whole 'noundo' local IDs by moving them from old to new main. Linked ones are handled
|
|
|
|
|
* separately together with their libraries.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: While in theory Library IDs (and their related linked IDs) are also 'noundo' data, in
|
|
|
|
|
* practice they need to be handled separately, to ensure that their order in the new bmain list
|
2023-09-03 16:13:08 +10:00
|
|
|
* matches the one from the read blend-file. Reading linked 'placeholder' entries in a memfile
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
* relies on current library being the last item in the new main list. */
|
|
|
|
|
static void read_undo_reuse_noundo_local_ids(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
Main *old_bmain = static_cast<Main *>(fd->old_mainlist->first);
|
|
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
|
|
|
|
|
|
|
|
|
BLI_assert(old_bmain->curlib == nullptr);
|
|
|
|
|
BLI_assert(BLI_listbase_count_at_most(fd->mainlist, 2) == 1);
|
|
|
|
|
|
|
|
|
|
int i = set_listbasepointers(old_bmain, lbarray);
|
|
|
|
|
while (i--) {
|
|
|
|
|
if (BLI_listbase_is_empty(lbarray[i])) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Only move 'noundo' local IDs. */
|
|
|
|
|
ID *id = static_cast<ID *>(lbarray[i]->first);
|
|
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
if ((id_type->flags & IDTYPE_FLAGS_NO_MEMFILE_UNDO) == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Main *new_bmain = static_cast<Main *>(fd->mainlist->first);
|
|
|
|
|
ListBase *new_lb = which_libbase(new_bmain, id_type->id_code);
|
|
|
|
|
BLI_assert(BLI_listbase_is_empty(new_lb));
|
|
|
|
|
BLI_movelisttolist(new_lb, lbarray[i]);
|
|
|
|
|
|
|
|
|
|
/* Update mappings accordingly. */
|
|
|
|
|
LISTBASE_FOREACH (ID *, id_iter, new_lb) {
|
2024-01-22 13:47:13 +01:00
|
|
|
BKE_main_idmap_insert_id(fd->new_idmap_uid, id_iter);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
id_iter->tag |= LIB_TAG_UNDO_OLD_ID_REUSED_NOUNDO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void read_undo_move_libmain_data(
|
|
|
|
|
FileData *fd, Main *new_main, Main *old_main, Main *libmain, BHead *bhead)
|
|
|
|
|
{
|
|
|
|
|
Library *curlib = libmain->curlib;
|
|
|
|
|
|
|
|
|
|
BLI_remlink(fd->old_mainlist, libmain);
|
|
|
|
|
BLI_remlink_safe(&old_main->libraries, libmain->curlib);
|
|
|
|
|
BLI_addtail(fd->mainlist, libmain);
|
|
|
|
|
BLI_addtail(&new_main->libraries, libmain->curlib);
|
|
|
|
|
|
|
|
|
|
curlib->id.tag |= LIB_TAG_UNDO_OLD_ID_REUSED_NOUNDO;
|
2024-01-22 13:47:13 +01:00
|
|
|
BKE_main_idmap_insert_id(fd->new_idmap_uid, &curlib->id);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (bhead != nullptr) {
|
|
|
|
|
oldnewmap_lib_insert(fd, bhead->old, &curlib->id, GS(curlib->id.name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID *id_iter;
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (libmain, id_iter) {
|
2024-01-22 13:47:13 +01:00
|
|
|
BKE_main_idmap_insert_id(fd->new_idmap_uid, id_iter);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
/* For undo, restore matching library datablock from the old main. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
static bool read_libblock_undo_restore_library(
|
|
|
|
|
FileData *fd, Main *new_main, const ID *id, ID *id_old, BHead *bhead)
|
2020-04-03 13:34:12 +02:00
|
|
|
{
|
2022-09-28 09:41:31 +10:00
|
|
|
/* In undo case, most libraries and linked data should be kept as is from previous state
|
2020-04-03 13:34:12 +02:00
|
|
|
* (see BLO_read_from_memfile).
|
|
|
|
|
* However, some needed by the snapshot being read may have been removed in previous one,
|
|
|
|
|
* and would go missing.
|
2023-02-12 14:37:16 +11:00
|
|
|
* This leads e.g. to disappearing objects in some undo/redo case, see #34446.
|
2020-04-03 13:34:12 +02:00
|
|
|
* That means we have to carefully check whether current lib or
|
|
|
|
|
* libdata already exits in old main, if it does we merely copy it over into new main area,
|
|
|
|
|
* otherwise we have to do a full read of that bhead... */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO, 2, "UNDO: restore library %s", id->name);
|
2020-04-03 13:34:12 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (id_old == nullptr) {
|
|
|
|
|
CLOG_INFO(&LOG_UNDO, 2, " -> NO match");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
Main *libmain = static_cast<Main *>(fd->old_mainlist->first);
|
2020-04-03 13:34:12 +02:00
|
|
|
/* Skip oldmain itself... */
|
|
|
|
|
for (libmain = libmain->next; libmain; libmain = libmain->next) {
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (&libmain->curlib->id == id_old) {
|
|
|
|
|
Main *old_main = static_cast<Main *>(fd->old_mainlist->first);
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
" compare with %s -> match (existing libpath: %s)",
|
|
|
|
|
libmain->curlib ? libmain->curlib->id.name : "<none>",
|
2024-04-08 13:08:36 +02:00
|
|
|
libmain->curlib ? libmain->curlib->runtime.filepath_abs : "<none>");
|
2020-04-03 13:34:12 +02:00
|
|
|
/* In case of a library, we need to re-add its main to fd->mainlist,
|
|
|
|
|
* because if we have later a missing ID_LINK_PLACEHOLDER,
|
|
|
|
|
* we need to get the correct lib it is linked to!
|
|
|
|
|
* Order is crucial, we cannot bulk-add it in BLO_read_from_memfile()
|
|
|
|
|
* like it used to be. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
read_undo_move_libmain_data(fd, new_main, old_main, libmain, bhead);
|
2020-04-03 13:34:12 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
static ID *library_id_is_yet_read(FileData *fd, Main *mainvar, BHead *bhead);
|
|
|
|
|
|
|
|
|
|
/* For undo, restore existing linked datablock from the old main.
|
|
|
|
|
*
|
|
|
|
|
* Note that IDs from existing libs have already been moved into the new main when their (local)
|
|
|
|
|
* ID_LI library ID was handled by #read_libblock_undo_restore_library, so this function has very
|
|
|
|
|
* little to do. */
|
|
|
|
|
static bool read_libblock_undo_restore_linked(
|
|
|
|
|
FileData *fd, Main *libmain, const ID *id, ID **r_id_old, BHead *bhead)
|
2020-04-03 13:34:12 +02:00
|
|
|
{
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO, 2, "UNDO: restore linked datablock %s", id->name);
|
2020-04-03 13:34:12 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (*r_id_old == nullptr) {
|
2024-01-22 13:47:13 +01:00
|
|
|
/* If the linked ID had to be re-read at some point, its session_uid may not be the same as
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
* its reference stored in the memfile anymore. Do a search by name then. */
|
|
|
|
|
*r_id_old = library_id_is_yet_read(fd, libmain, bhead);
|
|
|
|
|
|
|
|
|
|
if (*r_id_old == nullptr) {
|
|
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
" from %s (%s): NOT found",
|
|
|
|
|
libmain->curlib ? libmain->curlib->id.name : "<nullptr>",
|
|
|
|
|
libmain->curlib ? libmain->curlib->filepath : "<nullptr>");
|
|
|
|
|
return false;
|
2020-04-03 13:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
" from %s (%s): found by name",
|
|
|
|
|
libmain->curlib ? libmain->curlib->id.name : "<nullptr>",
|
|
|
|
|
libmain->curlib ? libmain->curlib->filepath : "<nullptr>");
|
|
|
|
|
/* The Library ID 'owning' this linked ID should already have been moved to new main by a call
|
|
|
|
|
* to #read_libblock_undo_restore_library. */
|
2024-01-22 13:47:13 +01:00
|
|
|
BLI_assert(*r_id_old == static_cast<ID *>(BKE_main_idmap_lookup_uid(
|
|
|
|
|
fd->new_idmap_uid, (*r_id_old)->session_uid)));
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
2024-01-22 13:47:13 +01:00
|
|
|
" from %s (%s): found by session_uid",
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
libmain->curlib ? libmain->curlib->id.name : "<nullptr>",
|
|
|
|
|
libmain->curlib ? libmain->curlib->filepath : "<nullptr>");
|
|
|
|
|
/* The Library ID 'owning' this linked ID should already have been moved to new main by a call
|
|
|
|
|
* to #read_libblock_undo_restore_library. */
|
2024-01-22 13:47:13 +01:00
|
|
|
BLI_assert(*r_id_old ==
|
|
|
|
|
static_cast<ID *>(BKE_main_idmap_lookup_uid(fd->new_idmap_uid, id->session_uid)));
|
2020-04-03 13:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
oldnewmap_lib_insert(fd, bhead->old, *r_id_old, GS((*r_id_old)->name));
|
|
|
|
|
|
|
|
|
|
/* No need to do anything else for ID_LINK_PLACEHOLDER, it's assumed
|
|
|
|
|
* already present in its lib's main. */
|
|
|
|
|
return true;
|
2020-04-03 13:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* For undo, restore unchanged local datablock from old main. */
|
2020-04-03 14:31:05 +02:00
|
|
|
static void read_libblock_undo_restore_identical(
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
FileData *fd, Main *main, const ID * /*id*/, ID *id_old, BHead *bhead, const int id_tag)
|
2020-04-03 14:31:05 +02:00
|
|
|
{
|
|
|
|
|
BLI_assert((fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0);
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(id_old != nullptr);
|
2020-04-03 14:31:05 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* Do not add LIB_TAG_NEW here, this should not be needed/used in undo case anyway (as
|
|
|
|
|
* this is only for do_version-like code), but for sake of consistency, and also because
|
|
|
|
|
* it will tell us which ID is re-used from old Main, and which one is actually newly read. */
|
|
|
|
|
/* Also do not add LIB_TAG_NEED_LINK, this ID will never be re-liblinked, hence that tag will
|
|
|
|
|
* never be cleared, leading to critical issue in link/append code. */
|
2020-05-20 10:39:50 +02:00
|
|
|
/* Some tags need to be preserved here. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
id_old->tag = ((id_tag | LIB_TAG_UNDO_OLD_ID_REUSED_UNCHANGED) & ~LIB_TAG_KEEP_ON_UNDO) |
|
|
|
|
|
(id_old->tag & LIB_TAG_KEEP_ON_UNDO);
|
2020-04-03 14:31:05 +02:00
|
|
|
id_old->lib = main->curlib;
|
|
|
|
|
id_old->us = ID_FAKE_USERS(id_old);
|
|
|
|
|
/* Do not reset id->icon_id here, memory allocated for it remains valid. */
|
|
|
|
|
/* Needed because .blend may have been saved with crap value here... */
|
2022-09-15 19:13:01 +02:00
|
|
|
id_old->newid = nullptr;
|
|
|
|
|
id_old->orig_id = nullptr;
|
2020-04-03 14:31:05 +02:00
|
|
|
|
|
|
|
|
const short idcode = GS(id_old->name);
|
2022-09-15 19:13:01 +02:00
|
|
|
Main *old_bmain = static_cast<Main *>(fd->old_mainlist->first);
|
2020-04-03 14:31:05 +02:00
|
|
|
ListBase *old_lb = which_libbase(old_bmain, idcode);
|
|
|
|
|
ListBase *new_lb = which_libbase(main, idcode);
|
|
|
|
|
BLI_remlink(old_lb, id_old);
|
|
|
|
|
BLI_addtail(new_lb, id_old);
|
|
|
|
|
|
2020-04-04 19:30:42 +02:00
|
|
|
/* Recalc flags, mostly these just remain as they are. */
|
|
|
|
|
id_old->recalc |= direct_link_id_restore_recalc_exceptions(id_old);
|
2020-04-13 17:38:34 +02:00
|
|
|
id_old->recalc_after_undo_push = 0;
|
2020-04-08 17:41:01 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* Insert into library map for lookup by newly read datablocks (with pointer value bhead->old).
|
|
|
|
|
* Note that existing datablocks in memory (which pointer value would be id_old) are not
|
|
|
|
|
* remapped, so no need to store this info here. */
|
|
|
|
|
oldnewmap_lib_insert(fd, bhead->old, id_old, bhead->code);
|
|
|
|
|
|
2024-01-22 13:47:13 +01:00
|
|
|
BKE_main_idmap_insert_id(fd->new_idmap_uid, id_old);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
|
2020-04-08 17:41:01 +02:00
|
|
|
if (GS(id_old->name) == ID_OB) {
|
|
|
|
|
Object *ob = (Object *)id_old;
|
2020-09-14 14:55:48 +02:00
|
|
|
/* For undo we stay in object mode during undo presses, so keep editmode disabled for re-used
|
|
|
|
|
* data-blocks too. */
|
|
|
|
|
ob->mode &= ~OB_MODE_EDIT;
|
2020-04-08 17:41:01 +02:00
|
|
|
}
|
2020-04-03 14:31:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* For undo, store changed datablock at old address. */
|
|
|
|
|
static void read_libblock_undo_restore_at_old_address(FileData *fd, Main *main, ID *id, ID *id_old)
|
|
|
|
|
{
|
|
|
|
|
/* During memfile undo, if an ID changed and we cannot directly re-use existing one from old
|
|
|
|
|
* bmain, we do a full read of the new id from the memfile, and then fully swap its content
|
|
|
|
|
* with the old id. This allows us to keep the same pointer even for modified data, which
|
|
|
|
|
* helps reducing further detected changes by the depsgraph (since unchanged IDs remain fully
|
|
|
|
|
* unchanged, even if they are using/pointing to a changed one). */
|
|
|
|
|
BLI_assert((fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0);
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(id_old != nullptr);
|
2020-04-03 14:31:05 +02:00
|
|
|
|
|
|
|
|
const short idcode = GS(id->name);
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
Main *old_bmain = static_cast<Main *>(fd->old_mainlist->first);
|
2020-04-03 14:31:05 +02:00
|
|
|
ListBase *old_lb = which_libbase(old_bmain, idcode);
|
|
|
|
|
ListBase *new_lb = which_libbase(main, idcode);
|
|
|
|
|
BLI_remlink(old_lb, id_old);
|
|
|
|
|
BLI_remlink(new_lb, id);
|
|
|
|
|
|
2023-04-17 17:17:02 +02:00
|
|
|
/* We do need remapping of internal pointers to the ID itself here.
|
|
|
|
|
*
|
2023-06-04 18:35:12 +10:00
|
|
|
* Passing a null #Main means that not all potential runtime data (like collections' parent
|
2023-04-17 17:17:02 +02:00
|
|
|
* pointers etc.) will be up-to-date. However, this should not be a problem here, since these
|
2023-04-19 08:02:41 +10:00
|
|
|
* data are re-generated later in file-read process anyway. */
|
2023-04-17 17:17:02 +02:00
|
|
|
BKE_lib_id_swap_full(nullptr,
|
|
|
|
|
id,
|
|
|
|
|
id_old,
|
|
|
|
|
true,
|
2023-04-24 15:30:04 +02:00
|
|
|
(ID_REMAP_NO_ORIG_POINTERS_ACCESS | ID_REMAP_SKIP_NEVER_NULL_USAGE |
|
2024-05-03 12:51:05 +02:00
|
|
|
ID_REMAP_SKIP_UPDATE_TAGGING | ID_REMAP_SKIP_USER_REFCOUNT |
|
|
|
|
|
ID_REMAP_SKIP_USER_CLEAR));
|
2020-04-03 14:31:05 +02:00
|
|
|
|
2020-11-03 11:39:36 +01:00
|
|
|
/* Special temporary usage of this pointer, necessary for the `undo_preserve` call after
|
|
|
|
|
* lib-linking to restore some data that should never be affected by undo, e.g. the 3D cursor of
|
|
|
|
|
* #Scene. */
|
|
|
|
|
id_old->orig_id = id;
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
id_old->tag |= LIB_TAG_UNDO_OLD_ID_REREAD_IN_PLACE | LIB_TAG_NEED_LINK;
|
2020-11-03 11:39:36 +01:00
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
BLI_addtail(new_lb, id_old);
|
|
|
|
|
BLI_addtail(old_lb, id);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
static bool read_libblock_undo_restore(
|
2023-05-13 19:45:29 +02:00
|
|
|
FileData *fd, Main *main, BHead *bhead, int id_tag, ID **r_id_old)
|
2020-04-04 17:38:07 +02:00
|
|
|
{
|
2024-01-22 13:47:13 +01:00
|
|
|
BLI_assert(fd->old_idmap_uid != nullptr);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
/* Get pointer to memory of new ID that we will be reading. */
|
2022-09-15 19:13:01 +02:00
|
|
|
const ID *id = static_cast<const ID *>(peek_struct_undo(fd, bhead));
|
2023-01-24 17:22:57 +01:00
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
2020-04-04 17:38:07 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
if (do_partial_undo && (bhead->code != ID_LINK_PLACEHOLDER)) {
|
|
|
|
|
/* This code should only ever be reached for local data-blocks. */
|
|
|
|
|
BLI_assert(main->curlib == nullptr);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Find the 'current' existing ID we want to reuse instead of the one we
|
|
|
|
|
* would read from the undo memfile. */
|
2024-01-22 13:47:13 +01:00
|
|
|
ID *id_old = (fd->old_idmap_uid != nullptr) ?
|
|
|
|
|
BKE_main_idmap_lookup_uid(fd->old_idmap_uid, id->session_uid) :
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
nullptr;
|
|
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
if (bhead->code == ID_LI) {
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* Restore library datablock, if possible. */
|
|
|
|
|
if (read_libblock_undo_restore_library(fd, main, id, id_old, bhead)) {
|
2020-04-04 17:38:07 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (bhead->code == ID_LINK_PLACEHOLDER) {
|
|
|
|
|
/* Restore linked datablock. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (read_libblock_undo_restore_linked(fd, main, id, &id_old, bhead)) {
|
2020-04-04 17:38:07 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
else if (id_type->flags & IDTYPE_FLAGS_NO_MEMFILE_UNDO) {
|
|
|
|
|
CLOG_INFO(
|
|
|
|
|
&LOG_UNDO, 2, "UNDO: skip restore datablock %s, 'NO_MEMFILE_UNDO' type of ID", id->name);
|
2020-04-04 17:38:07 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* If that local noundo ID still exists currently, the call to
|
|
|
|
|
* #read_undo_reuse_noundo_local_ids at the beginning of #blo_read_file_internal will already
|
2024-01-22 13:47:13 +01:00
|
|
|
* have moved it into the new main, and populated accordingly the new_idmap_uid.
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
*
|
|
|
|
|
* If this is the case, it can also be remapped for newly read data. Otherwise, this is 'lost'
|
|
|
|
|
* data that cannot be restored on undo, so no remapping should exist for it in the ID
|
|
|
|
|
* oldnewmap. */
|
|
|
|
|
if (id_old) {
|
2024-01-22 13:47:13 +01:00
|
|
|
BLI_assert(id_old ==
|
|
|
|
|
static_cast<ID *>(BKE_main_idmap_lookup_uid(fd->new_idmap_uid, id->session_uid)));
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
oldnewmap_lib_insert(fd, bhead->old, id_old, bhead->code);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-04-04 17:38:07 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (!do_partial_undo) {
|
|
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
2024-01-22 13:47:13 +01:00
|
|
|
"UNDO: read %s (uid %u) -> no partial undo, always read at new address",
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
id->name,
|
2024-01-22 13:47:13 +01:00
|
|
|
id->session_uid);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
return false;
|
2020-04-04 17:38:07 +02:00
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
/* Restore local datablocks. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id_old != nullptr && read_libblock_is_identical(fd, bhead)) {
|
2020-04-04 17:38:07 +02:00
|
|
|
/* Local datablock was unchanged, restore from the old main. */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
2024-01-22 13:47:13 +01:00
|
|
|
"UNDO: read %s (uid %u) -> keep identical datablock",
|
2021-06-23 14:23:54 +02:00
|
|
|
id->name,
|
2024-01-22 13:47:13 +01:00
|
|
|
id->session_uid);
|
2020-04-04 17:38:07 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
read_libblock_undo_restore_identical(fd, main, id, id_old, bhead, id_tag);
|
2020-04-04 17:38:07 +02:00
|
|
|
|
|
|
|
|
*r_id_old = id_old;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id_old != nullptr) {
|
2020-04-04 17:38:07 +02:00
|
|
|
/* Local datablock was changed. Restore at the address of the old datablock. */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
2024-01-22 13:47:13 +01:00
|
|
|
"UNDO: read %s (uid %u) -> read to old existing address",
|
2021-06-23 14:23:54 +02:00
|
|
|
id->name,
|
2024-01-22 13:47:13 +01:00
|
|
|
id->session_uid);
|
2020-04-04 17:38:07 +02:00
|
|
|
*r_id_old = id_old;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
|
|
|
|
|
/* Local datablock does not exist in the undo step, so read from scratch. */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(
|
2024-01-22 13:47:13 +01:00
|
|
|
&LOG_UNDO, 2, "UNDO: read %s (uid %u) -> read at new address", id->name, id->session_uid);
|
2020-08-07 12:31:44 +02:00
|
|
|
return false;
|
2020-04-04 17:38:07 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
/* This routine reads a datablock and its direct data, and advances bhead to
|
|
|
|
|
* the next datablock. For library linked datablocks, only a placeholder will
|
|
|
|
|
* be generated, to be replaced in read_library_linked_ids.
|
|
|
|
|
*
|
|
|
|
|
* When reading for undo, libraries, linked datablocks and unchanged datablocks
|
|
|
|
|
* will be restored from the old database. Only new or changed datablocks will
|
|
|
|
|
* actually be read. */
|
2019-09-16 14:52:06 +02:00
|
|
|
static BHead *read_libblock(FileData *fd,
|
|
|
|
|
Main *main,
|
|
|
|
|
BHead *bhead,
|
2023-05-13 19:45:29 +02:00
|
|
|
int id_tag,
|
2019-09-16 14:52:06 +02:00
|
|
|
const bool placeholder_set_indirect_extern,
|
|
|
|
|
ID **r_id)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
|
|
|
|
|
|
2020-04-08 10:33:56 +10:00
|
|
|
/* First attempt to restore existing datablocks for undo.
|
2020-04-04 17:38:07 +02:00
|
|
|
* When datablocks are changed but still exist, we restore them at the old
|
|
|
|
|
* address and inherit recalc flags for the dependency graph. */
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id_old = nullptr;
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
2023-05-13 19:45:29 +02:00
|
|
|
if (read_libblock_undo_restore(fd, main, bhead, id_tag, &id_old)) {
|
2020-04-04 17:38:07 +02:00
|
|
|
if (r_id) {
|
|
|
|
|
*r_id = id_old;
|
|
|
|
|
}
|
2023-01-24 17:53:27 +01:00
|
|
|
if (main->id_map != nullptr && id_old != nullptr) {
|
2021-06-30 15:19:35 +02:00
|
|
|
BKE_main_idmap_insert_id(main->id_map, id_old);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
return blo_bhead_next(fd, bhead);
|
|
|
|
|
}
|
2020-04-03 14:12:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read libblock struct. */
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(read_struct(fd, bhead, "lib block"));
|
|
|
|
|
if (id == nullptr) {
|
2020-04-04 17:38:07 +02:00
|
|
|
if (r_id) {
|
2022-09-15 19:13:01 +02:00
|
|
|
*r_id = nullptr;
|
2020-04-04 17:38:07 +02:00
|
|
|
}
|
2020-04-03 14:12:57 +02:00
|
|
|
return blo_bhead_next(fd, bhead);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
/* Determine ID type and add to main database list. */
|
2020-04-03 14:12:57 +02:00
|
|
|
const short idcode = GS(id->name);
|
|
|
|
|
ListBase *lb = which_libbase(main, idcode);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (lb == nullptr) {
|
2020-04-03 14:12:57 +02:00
|
|
|
/* Unknown ID type. */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_WARN(&LOG, "Unknown id code '%c%c'", (idcode & 0xff), (idcode >> 8));
|
2020-04-03 14:12:57 +02:00
|
|
|
MEM_freeN(id);
|
2020-04-04 17:38:07 +02:00
|
|
|
if (r_id) {
|
2022-09-15 19:13:01 +02:00
|
|
|
*r_id = nullptr;
|
2020-04-04 17:38:07 +02:00
|
|
|
}
|
2020-04-03 14:12:57 +02:00
|
|
|
return blo_bhead_next(fd, bhead);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-04 17:38:07 +02:00
|
|
|
/* NOTE: id must be added to the list before direct_link_id(), since
|
|
|
|
|
* direct_link_library() may remove it from there in case of duplicates. */
|
|
|
|
|
BLI_addtail(lb, id);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-22 11:22:31 +02:00
|
|
|
/* Insert into library map for lookup by newly read datablocks (with pointer value bhead->old).
|
|
|
|
|
* Note that existing datablocks in memory (which pointer value would be id_old) are not remapped
|
|
|
|
|
* remapped anymore, so no need to store this info here. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
ID *id_target = (do_partial_undo && id_old != nullptr) ? id_old : id;
|
2022-07-28 16:26:02 +02:00
|
|
|
oldnewmap_lib_insert(fd, bhead->old, id_target, bhead->code);
|
2020-04-03 14:12:57 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (r_id) {
|
2020-04-03 14:31:05 +02:00
|
|
|
*r_id = id_target;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
/* Set tag for new datablock to indicate lib linking and versioning needs
|
|
|
|
|
* to be done still. */
|
2023-05-13 19:45:29 +02:00
|
|
|
id_tag |= (LIB_TAG_NEED_LINK | LIB_TAG_NEW);
|
2019-07-22 17:07:46 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
if (bhead->code == ID_LINK_PLACEHOLDER) {
|
2020-04-03 14:31:05 +02:00
|
|
|
/* Read placeholder for linked datablock. */
|
2020-04-03 13:34:12 +02:00
|
|
|
id_tag |= LIB_TAG_ID_LINK_PLACEHOLDER;
|
2019-09-16 14:52:06 +02:00
|
|
|
|
|
|
|
|
if (placeholder_set_indirect_extern) {
|
|
|
|
|
if (id->flag & LIB_INDIRECT_WEAK_LINK) {
|
2020-04-03 13:34:12 +02:00
|
|
|
id_tag |= LIB_TAG_INDIRECT;
|
2019-09-16 14:52:06 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2020-04-03 13:34:12 +02:00
|
|
|
id_tag |= LIB_TAG_EXTERN;
|
2019-09-16 14:52:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
direct_link_id(fd, main, id_tag, id, id_old);
|
2021-06-30 15:19:35 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (main->id_map != nullptr) {
|
2021-06-30 15:19:35 +02:00
|
|
|
BKE_main_idmap_insert_id(main->id_map, id);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
return blo_bhead_next(fd, bhead);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
/* Read datablock contents.
|
|
|
|
|
* Use convenient malloc name for debugging and better memory link prints. */
|
2024-02-09 16:04:53 +01:00
|
|
|
const char *allocname = idtype_alloc_name_get(idcode);
|
2020-04-03 13:34:12 +02:00
|
|
|
bhead = read_data_into_datamap(fd, bhead, allocname);
|
|
|
|
|
const bool success = direct_link_id(fd, main, id_tag, id, id_old);
|
2002-10-12 11:37:38 +00:00
|
|
|
oldnewmap_clear(fd->datamap);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
if (!success) {
|
2020-01-28 15:46:51 +01:00
|
|
|
/* XXX This is probably working OK currently given the very limited scope of that flag.
|
|
|
|
|
* However, it is absolutely **not** handled correctly: it is freeing an ID pointer that has
|
|
|
|
|
* been added to the fd->libmap mapping, which in theory could lead to nice crashes...
|
|
|
|
|
* This should be properly solved at some point. */
|
2019-01-14 15:47:11 +01:00
|
|
|
BKE_id_free(main, id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (r_id != nullptr) {
|
|
|
|
|
*r_id = nullptr;
|
2020-01-28 15:46:51 +01:00
|
|
|
}
|
2013-05-06 11:23:13 +00:00
|
|
|
}
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
else {
|
|
|
|
|
if (do_partial_undo && id_old != nullptr) {
|
|
|
|
|
/* For undo, store contents read into id at id_old. */
|
|
|
|
|
read_libblock_undo_restore_at_old_address(fd, main, id, id_old);
|
|
|
|
|
}
|
2024-01-22 13:47:13 +01:00
|
|
|
if (fd->new_idmap_uid != nullptr) {
|
|
|
|
|
BKE_main_idmap_insert_id(fd->new_idmap_uid, id_target);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
}
|
2022-09-15 19:13:01 +02:00
|
|
|
if (main->id_map != nullptr) {
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
BKE_main_idmap_insert_id(main->id_map, id_target);
|
2021-06-30 15:19:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 13:34:12 +02:00
|
|
|
return bhead;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2020-12-11 18:15:25 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read Asset Data
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_asset_data)
|
|
|
|
|
{
|
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
2021-03-12 15:58:58 +01:00
|
|
|
BLI_assert(blo_bhead_is_id_valid_type(bhead));
|
2020-12-11 18:15:25 +01:00
|
|
|
|
|
|
|
|
bhead = read_data_into_datamap(fd, bhead, "asset-data read");
|
|
|
|
|
|
|
|
|
|
BlendDataReader reader = {fd};
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(&reader, AssetMetaData, r_asset_data);
|
2020-12-11 18:15:25 +01:00
|
|
|
BKE_asset_metadata_read(&reader, *r_asset_data);
|
|
|
|
|
|
|
|
|
|
oldnewmap_clear(fd->datamap);
|
|
|
|
|
|
|
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read Global Data
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: this has to be kept for reading older files... */
|
2007-12-24 18:53:37 +00:00
|
|
|
/* also version info is written here */
|
|
|
|
|
static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
FileGlobal *fg = static_cast<FileGlobal *>(read_struct(fd, bhead, "Global"));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-07-24 14:18:22 +02:00
|
|
|
/* NOTE: `bfd->main->versionfile` is supposed to have already been set from `fd->fileversion`
|
|
|
|
|
* beforehand by calling code. */
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->main->subversionfile = fg->subversion;
|
2023-07-24 14:18:22 +02:00
|
|
|
bfd->main->has_forward_compatibility_issues = !MAIN_VERSION_FILE_OLDER_OR_EQUAL(
|
|
|
|
|
bfd->main, BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION);
|
|
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->main->minversionfile = fg->minversion;
|
|
|
|
|
bfd->main->minsubversionfile = fg->minsubversion;
|
2023-07-24 14:18:22 +02:00
|
|
|
|
2013-11-15 17:11:59 +06:00
|
|
|
bfd->main->build_commit_timestamp = fg->build_commit_timestamp;
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(bfd->main->build_hash, fg->build_hash);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->fileflags = fg->fileflags;
|
|
|
|
|
bfd->globalf = fg->globalf;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2024-05-03 11:32:43 +10:00
|
|
|
/* NOTE: since 88b24bc6bb, `fg->filepath` is only written for crash recovery and autosave files,
|
2024-01-24 10:49:24 +01:00
|
|
|
* so only overwrite `fd->relabase` if it is not empty, in case a regular blendfile is opened
|
|
|
|
|
* through one of the 'recover' operators.
|
|
|
|
|
*
|
|
|
|
|
* In all other cases, the path is just set to the current path of the blendfile being read, so
|
|
|
|
|
* there is no need to handle anymore older files (pre-2.65) that did not store (correctly) their
|
|
|
|
|
* path. */
|
2021-03-15 13:30:26 +11:00
|
|
|
if (G.fileflags & G_FILE_RECOVER_READ) {
|
2024-01-24 10:49:24 +01:00
|
|
|
if (fg->filepath[0] != '\0') {
|
|
|
|
|
STRNCPY(fd->relabase, fg->filepath);
|
|
|
|
|
/* Used to set expected original filepath in read Main, instead of the path of the recovery
|
|
|
|
|
* file itself. */
|
|
|
|
|
STRNCPY(bfd->filepath, fg->filepath);
|
|
|
|
|
}
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->curscreen = fg->curscreen;
|
|
|
|
|
bfd->curscene = fg->curscene;
|
2017-11-22 10:52:39 -02:00
|
|
|
bfd->cur_view_layer = fg->cur_view_layer;
|
Main Workspace Integration
This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)
Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)
== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.
Opening files without UI and commandline rendering should work fine.
Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.
== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.
== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)
== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)
Reviewed By: campbellbarton, mont29
Tags: #user_interface, #bf_blender_2.8
Maniphest Tasks: T50521
Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
|
|
|
|
2007-12-24 18:53:37 +00:00
|
|
|
MEM_freeN(fg);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
fd->globalf = bfd->globalf;
|
|
|
|
|
fd->fileflags = bfd->fileflags;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
return blo_bhead_next(fd, bhead);
|
2007-12-24 18:53:37 +00:00
|
|
|
}
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: this has to be kept for reading older files... */
|
2007-12-24 18:53:37 +00:00
|
|
|
static void link_global(FileData *fd, BlendFileData *bfd)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
bfd->cur_view_layer = static_cast<ViewLayer *>(
|
|
|
|
|
blo_read_get_new_globaldata_address(fd, bfd->cur_view_layer));
|
2023-04-24 12:04:22 +02:00
|
|
|
bfd->curscreen = static_cast<bScreen *>(newlibadr(fd, nullptr, false, bfd->curscreen));
|
|
|
|
|
bfd->curscene = static_cast<Scene *>(newlibadr(fd, nullptr, false, bfd->curscene));
|
2004-09-05 13:43:51 +00:00
|
|
|
/* this happens in files older than 2.35 */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (bfd->curscene == nullptr) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (bfd->curscreen) {
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->curscene = bfd->curscreen->scene;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2024-04-22 17:24:38 +02:00
|
|
|
if (bfd->curscene == nullptr) {
|
|
|
|
|
bfd->curscene = static_cast<Scene *>(bfd->main->scenes.first);
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Versioning
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
static void do_versions_userdef(FileData * /*fd*/, BlendFileData *bfd)
|
2013-03-17 14:38:58 +00:00
|
|
|
{
|
|
|
|
|
UserDef *user = bfd->user;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (user == nullptr) {
|
2013-03-17 14:38:58 +00:00
|
|
|
return;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2020-10-02 23:23:57 +10:00
|
|
|
|
2020-10-02 23:36:05 +10:00
|
|
|
blo_do_versions_userdef(user);
|
2013-03-17 14:38:58 +00:00
|
|
|
}
|
2013-04-12 10:52:47 +00:00
|
|
|
|
2012-05-04 15:42:49 +00:00
|
|
|
static void do_versions(FileData *fd, Library *lib, Main *main)
|
2010-05-01 12:39:06 +00:00
|
|
|
{
|
2012-05-04 15:42:49 +00:00
|
|
|
/* WATCH IT!!!: pointers from libdata have not been converted */
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-05-15 16:53:43 +10:00
|
|
|
/* Don't allow versioning to create new data-blocks. */
|
|
|
|
|
main->is_locked_for_linking = true;
|
|
|
|
|
|
2013-11-04 13:21:39 +00:00
|
|
|
if (G.debug & G_DEBUG) {
|
2013-11-15 17:11:59 +06:00
|
|
|
char build_commit_datetime[32];
|
|
|
|
|
time_t temp_time = main->build_commit_timestamp;
|
2023-06-03 08:36:28 +10:00
|
|
|
tm *tm = (temp_time) ? gmtime(&temp_time) : nullptr;
|
2013-11-18 02:39:26 +11:00
|
|
|
if (LIKELY(tm)) {
|
|
|
|
|
strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(build_commit_datetime, "unknown");
|
2013-11-18 02:39:26 +11:00
|
|
|
}
|
2013-11-15 17:11:59 +06:00
|
|
|
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG, 0, "Read file %s", fd->relabase);
|
|
|
|
|
CLOG_INFO(&LOG,
|
|
|
|
|
0,
|
|
|
|
|
" Version %d sub %d date %s hash %s",
|
|
|
|
|
main->versionfile,
|
|
|
|
|
main->subversionfile,
|
|
|
|
|
build_commit_datetime,
|
|
|
|
|
main->build_hash);
|
2013-11-04 13:21:39 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_pre250(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_250(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_260(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_270(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_280(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_290(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_300(fd, lib, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
blo_do_versions_400(fd, lib, main);
|
|
|
|
|
}
|
2013-11-04 19:21:50 +00:00
|
|
|
|
2005-07-26 18:46:28 +00:00
|
|
|
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
2013-03-17 14:38:58 +00:00
|
|
|
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
|
2012-06-04 16:42:58 +00:00
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
/* don't forget to set version number in BKE_blender_version.h! */
|
2020-05-15 16:53:43 +10:00
|
|
|
|
|
|
|
|
main->is_locked_for_linking = false;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
static void do_versions_after_linking(FileData *fd, Main *main)
|
2010-06-19 10:50:23 +00:00
|
|
|
{
|
2023-09-01 17:58:18 +02:00
|
|
|
BLI_assert(fd != nullptr);
|
|
|
|
|
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG,
|
|
|
|
|
2,
|
|
|
|
|
"Processing %s (%s), %d.%d",
|
2021-12-13 16:22:19 +11:00
|
|
|
main->curlib ? main->curlib->filepath : main->filepath,
|
2021-06-23 14:23:54 +02:00
|
|
|
main->curlib ? "LIB" : "MAIN",
|
|
|
|
|
main->versionfile,
|
|
|
|
|
main->subversionfile);
|
2016-12-07 13:52:12 +01:00
|
|
|
|
2020-05-15 16:53:43 +10:00
|
|
|
/* Don't allow versioning to create new data-blocks. */
|
|
|
|
|
main->is_locked_for_linking = true;
|
|
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_250(main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_260(main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_270(main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_280(fd, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_290(fd, main);
|
|
|
|
|
}
|
|
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_300(fd, main);
|
|
|
|
|
}
|
2023-05-17 17:02:07 -04:00
|
|
|
if (!main->is_read_invalid) {
|
|
|
|
|
do_versions_after_linking_400(fd, main);
|
|
|
|
|
}
|
2020-05-15 16:53:43 +10:00
|
|
|
|
|
|
|
|
main->is_locked_for_linking = false;
|
2010-06-19 10:50:23 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read Library Data Block (all)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-08-29 16:43:20 +10:00
|
|
|
static int lib_link_cb(LibraryIDLinkCallbackData *cb_data)
|
2023-03-11 18:07:59 +01:00
|
|
|
{
|
|
|
|
|
/* Embedded IDs are not known by lib_link code, so they would be remapped to `nullptr`. But there
|
2023-08-25 08:56:58 +10:00
|
|
|
* is no need to process them anyway, as they are already handled during the 'read_data' phase.
|
2023-03-11 18:07:59 +01:00
|
|
|
*
|
2023-08-25 08:56:58 +10:00
|
|
|
* NOTE: Some external non-owning pointers to embedded IDs (like the node-tree pointers of the
|
2023-03-11 18:07:59 +01:00
|
|
|
* Node editor) will not be detected as embedded ones though at 'lib_link' stage (because their
|
|
|
|
|
* source data cannot be accessed). This is handled on a case-by-case basis in 'after_lib_link'
|
|
|
|
|
* validation code. */
|
|
|
|
|
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-25 08:56:58 +10:00
|
|
|
/* Explicitly requested to be ignored during readfile processing. Means the read_data code
|
2023-03-11 18:07:59 +01:00
|
|
|
* already handled this pointer. Typically, the 'owner_id' pointer of an embedded ID. */
|
|
|
|
|
if (cb_data->cb_flag & IDWALK_CB_READFILE_IGNORE) {
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BlendLibReader *reader = static_cast<BlendLibReader *>(cb_data->user_data);
|
|
|
|
|
ID **id_ptr = cb_data->id_pointer;
|
|
|
|
|
ID *owner_id = cb_data->owner_id;
|
|
|
|
|
|
|
|
|
|
*id_ptr = BLO_read_get_new_id_address(reader, owner_id, ID_IS_LINKED(owner_id), *id_ptr);
|
|
|
|
|
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
static void lib_link_all(FileData *fd, Main *bmain)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2020-06-23 17:53:40 +02:00
|
|
|
BlendLibReader reader = {fd, bmain};
|
|
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
ID *id;
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
Fix #108923: Serious issues in 'undo_preserve' process of Scene's toolsettings.
By removing the extra complete check/remapping of ID pointers in undo
case, ebb5643e59 merely revealed how broken the 'undo_preserve' code of
Scene was.
It cumulated a flock of issues, all more or less related to ID pointers:
* 'source of truth' should be the _old_ data (toolsettings), not the new
one, since this is the one kept at the end of the process;
* In some cases, some paint data may exist in one, but not the other
of the two 'old' and 'new' toolsettings data.
* Since this data is preserved to its latest version accross undos, its
ID pointers can become completely unrelated to these read from the
undo memfile, _even when the Scene itself is detected as unchanged_!
This implies that:
+ undo_preserve code has to be called even when there is no liblinking
(when the ID is detected as unchanged and re-used 'as-is').
+ Using existing ID addresses to find/validate an ID pointer in
undo_preserve process is like playing Russian roulette - invalid
memory access and crash is guaranteed at some point or another.
Use `session_uuid` value instead to ensure a valid ID pointer is set
(or null in case none can be found).
NOTE: while these issues also exist in previous releases (including both
latest LTSs), they were hidden by the code later in `setup_app_data`,
preventing any crash to happen. So backporting this fix would be far too
risky for a very minimal benefit imho.
2023-06-21 15:21:04 +02:00
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if ((id->tag & (LIB_TAG_UNDO_OLD_ID_REUSED_UNCHANGED | LIB_TAG_UNDO_OLD_ID_REUSED_NOUNDO)) !=
|
2024-01-02 18:12:54 +01:00
|
|
|
0)
|
|
|
|
|
{
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
BLI_assert(fd->flags & FD_FLAGS_IS_MEMFILE);
|
2020-03-18 22:28:54 +11:00
|
|
|
/* This ID has been re-used from 'old' bmain. Since it was therefore unchanged across
|
|
|
|
|
* current undo step, and old IDs re-use their old memory address, we do not need to liblink
|
|
|
|
|
* it at all. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
BLI_assert((id->tag & LIB_TAG_NEED_LINK) == 0);
|
Fix #108923: Serious issues in 'undo_preserve' process of Scene's toolsettings.
By removing the extra complete check/remapping of ID pointers in undo
case, ebb5643e59 merely revealed how broken the 'undo_preserve' code of
Scene was.
It cumulated a flock of issues, all more or less related to ID pointers:
* 'source of truth' should be the _old_ data (toolsettings), not the new
one, since this is the one kept at the end of the process;
* In some cases, some paint data may exist in one, but not the other
of the two 'old' and 'new' toolsettings data.
* Since this data is preserved to its latest version accross undos, its
ID pointers can become completely unrelated to these read from the
undo memfile, _even when the Scene itself is detected as unchanged_!
This implies that:
+ undo_preserve code has to be called even when there is no liblinking
(when the ID is detected as unchanged and re-used 'as-is').
+ Using existing ID addresses to find/validate an ID pointer in
undo_preserve process is like playing Russian roulette - invalid
memory access and crash is guaranteed at some point or another.
Use `session_uuid` value instead to ensure a valid ID pointer is set
(or null in case none can be found).
NOTE: while these issues also exist in previous releases (including both
latest LTSs), they were hidden by the code later in `setup_app_data`,
preventing any crash to happen. So backporting this fix would be far too
risky for a very minimal benefit imho.
2023-06-21 15:21:04 +02:00
|
|
|
|
|
|
|
|
/* Some data that should be persistent, like the 3DCursor or the tool settings, are
|
|
|
|
|
* stored in IDs affected by undo, like Scene. So this requires some specific handling. */
|
|
|
|
|
/* NOTE: even though the ID may have been detected as unchanged, the 'undo_preserve' may have
|
2023-09-08 16:58:00 +10:00
|
|
|
* to actually change some of its ID pointers, it's e.g. the case with Scene's tool-settings
|
Fix #108923: Serious issues in 'undo_preserve' process of Scene's toolsettings.
By removing the extra complete check/remapping of ID pointers in undo
case, ebb5643e59 merely revealed how broken the 'undo_preserve' code of
Scene was.
It cumulated a flock of issues, all more or less related to ID pointers:
* 'source of truth' should be the _old_ data (toolsettings), not the new
one, since this is the one kept at the end of the process;
* In some cases, some paint data may exist in one, but not the other
of the two 'old' and 'new' toolsettings data.
* Since this data is preserved to its latest version accross undos, its
ID pointers can become completely unrelated to these read from the
undo memfile, _even when the Scene itself is detected as unchanged_!
This implies that:
+ undo_preserve code has to be called even when there is no liblinking
(when the ID is detected as unchanged and re-used 'as-is').
+ Using existing ID addresses to find/validate an ID pointer in
undo_preserve process is like playing Russian roulette - invalid
memory access and crash is guaranteed at some point or another.
Use `session_uuid` value instead to ensure a valid ID pointer is set
(or null in case none can be found).
NOTE: while these issues also exist in previous releases (including both
latest LTSs), they were hidden by the code later in `setup_app_data`,
preventing any crash to happen. So backporting this fix would be far too
risky for a very minimal benefit imho.
2023-06-21 15:21:04 +02:00
|
|
|
* Brush/Palette pointers. This is the case where both new and old ID may be the same. */
|
|
|
|
|
if (id_type->blend_read_undo_preserve != nullptr) {
|
|
|
|
|
BLI_assert(fd->flags & FD_FLAGS_IS_MEMFILE);
|
|
|
|
|
id_type->blend_read_undo_preserve(&reader, id, id->orig_id ? id->orig_id : id);
|
|
|
|
|
}
|
2020-03-17 12:29:36 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if ((id->tag & LIB_TAG_NEED_LINK) != 0) {
|
2023-03-11 18:07:59 +01:00
|
|
|
/* Not all original pointer values can be considered as valid.
|
|
|
|
|
* Handling of DNA deprecated data should never be needed in undo case. */
|
|
|
|
|
const int flag = IDWALK_NO_ORIG_POINTERS_ACCESS | IDWALK_INCLUDE_UI |
|
|
|
|
|
((fd->flags & FD_FLAGS_IS_MEMFILE) ? 0 : IDWALK_DO_DEPRECATED_POINTERS);
|
|
|
|
|
BKE_library_foreach_ID_link(nullptr, id, lib_link_cb, &reader, flag);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
after_liblink_id_process(&reader, id);
|
2020-02-05 16:18:17 +01:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
id->tag &= ~LIB_TAG_NEED_LINK;
|
|
|
|
|
}
|
2020-11-03 11:39:36 +01:00
|
|
|
|
|
|
|
|
/* Some data that should be persistent, like the 3DCursor or the tool settings, are
|
|
|
|
|
* stored in IDs affected by undo, like Scene. So this requires some specific handling. */
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id_type->blend_read_undo_preserve != nullptr && id->orig_id != nullptr) {
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
BLI_assert(fd->flags & FD_FLAGS_IS_MEMFILE);
|
2020-11-03 11:39:36 +01:00
|
|
|
id_type->blend_read_undo_preserve(&reader, id, id->orig_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
|
2024-02-19 15:54:08 +01:00
|
|
|
/* Cleanup `ID.orig_id`, this is now reserved for depsgraph/copy-on-eval usage only. */
|
2020-11-03 11:39:36 +01:00
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
2022-09-15 19:13:01 +02:00
|
|
|
id->orig_id = nullptr;
|
2020-02-05 16:18:17 +01:00
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
|
2021-02-04 15:21:29 +01:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
/* Double check we do not have any 'need link' tag remaining, this should never be the case once
|
|
|
|
|
* this function has run. */
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
|
|
|
|
BLI_assert((id->tag & LIB_TAG_NEED_LINK) == 0);
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:42:00 +11:00
|
|
|
/**
|
|
|
|
|
* Checks to perform after `lib_link_all`.
|
|
|
|
|
* Those operations cannot perform properly in a split bmain case, since some data from other
|
|
|
|
|
* bmain's (aka libraries) may not have been processed yet.
|
|
|
|
|
*/
|
2023-08-28 13:10:22 +02:00
|
|
|
static void after_liblink_merged_bmain_process(Main *bmain, BlendFileReadReport *reports)
|
2021-02-04 15:21:29 +01:00
|
|
|
{
|
|
|
|
|
/* We only expect a merged Main here, not a split one. */
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert((bmain->prev == nullptr) && (bmain->next == nullptr));
|
2021-02-04 15:21:29 +01:00
|
|
|
|
2023-08-28 13:10:22 +02:00
|
|
|
if (!BKE_main_namemap_validate_and_fix(bmain)) {
|
|
|
|
|
BKE_report(
|
|
|
|
|
reports ? reports->reports : nullptr,
|
|
|
|
|
RPT_ERROR,
|
2023-09-03 16:13:08 +10:00
|
|
|
"Critical blend-file corruption: Conflicts and/or otherwise invalid data-blocks names "
|
2023-08-28 13:10:22 +02:00
|
|
|
"(see console for details)");
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
/* Check for possible cycles in scenes' 'set' background property. */
|
|
|
|
|
lib_link_scenes_check_set(bmain);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-25 17:42:43 +01:00
|
|
|
/* We could integrate that to mesh/curve/lattice lib_link, but this is really cheap process,
|
|
|
|
|
* so simpler to just use it directly in this single call. */
|
2023-08-28 13:10:22 +02:00
|
|
|
BLO_main_validate_shapekeys(bmain, reports ? reports->reports : nullptr);
|
2019-05-22 22:57:16 +02:00
|
|
|
|
2024-03-23 12:55:57 +09:00
|
|
|
BLO_main_validate_embedded_flag(bmain, reports ? reports->reports : nullptr);
|
2024-03-01 10:41:21 +01:00
|
|
|
BLO_main_validate_embedded_liboverrides(bmain, reports ? reports->reports : nullptr);
|
|
|
|
|
|
2020-06-15 16:30:46 +02:00
|
|
|
/* We have to rebuild that runtime information *after* all data-blocks have been properly linked.
|
|
|
|
|
*/
|
|
|
|
|
BKE_main_collections_parent_relations_rebuild(bmain);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read User Preferences
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-06-07 11:30:32 +02:00
|
|
|
static void direct_link_keymapitem(BlendDataReader *reader, wmKeyMapItem *kmi)
|
KEYMAP REFACTORING
Diff Keymaps
User edited keymaps now no longer override the builtin keymaps entirely, but
rather save only the difference and reapply those changes. This means they can
stay better in sync when the builtin keymaps change. The diff/patch algorithm
is not perfect, but better for the common case where only a few items are changed
rather than entire keymaps The main weakness is that if a builtin keymap item
changes, user modification of that item may need to be redone in some cases.
Keymap Editor
The most noticeable change here is that there is no longer an "Edit" button for
keymaps, all are editable immediately, but a "Restore" buttons shows for keymaps
and items that have been edited. Shortcuts for addons can also be edited in the
keymap editor.
Addons
Addons now should only modify the new addon keyconfiguration, the keymap items
there will be added to the builtin ones for handling events, and not get lost
when starting new files. Example code of register/unregister:
km = wm.keyconfigs.addon.keymaps.new("3D View", space_type="VIEW_3D")
km.keymap_items.new('my.operator', 'ESC', 'PRESS')
km = wm.keyconfigs.addon.keymaps["3D View"]
km.keymap_items.remove(km.keymap_items["my.operator"])
Compatibility
The changes made are not forward compatible, i.e. if you save user preferences
with newer versions, older versions will not have key configuration changes that
were made.
2011-08-05 20:45:26 +00:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, IDProperty, &kmi->properties);
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &kmi->properties);
|
2022-09-15 19:13:01 +02:00
|
|
|
kmi->ptr = nullptr;
|
KEYMAP REFACTORING
Diff Keymaps
User edited keymaps now no longer override the builtin keymaps entirely, but
rather save only the difference and reapply those changes. This means they can
stay better in sync when the builtin keymaps change. The diff/patch algorithm
is not perfect, but better for the common case where only a few items are changed
rather than entire keymaps The main weakness is that if a builtin keymap item
changes, user modification of that item may need to be redone in some cases.
Keymap Editor
The most noticeable change here is that there is no longer an "Edit" button for
keymaps, all are editable immediately, but a "Restore" buttons shows for keymaps
and items that have been edited. Shortcuts for addons can also be edited in the
keymap editor.
Addons
Addons now should only modify the new addon keyconfiguration, the keymap items
there will be added to the builtin ones for handling events, and not get lost
when starting new files. Example code of register/unregister:
km = wm.keyconfigs.addon.keymaps.new("3D View", space_type="VIEW_3D")
km.keymap_items.new('my.operator', 'ESC', 'PRESS')
km = wm.keyconfigs.addon.keymaps["3D View"]
km.keymap_items.remove(km.keymap_items["my.operator"])
Compatibility
The changes made are not forward compatible, i.e. if you save user preferences
with newer versions, older versions will not have key configuration changes that
were made.
2011-08-05 20:45:26 +00:00
|
|
|
kmi->flag &= ~KMI_UPDATE;
|
|
|
|
|
}
|
2007-12-24 18:53:37 +00:00
|
|
|
|
- The basic layer for Themes in place!
- currently only implemented for 3d window
- create as many themes you like, and name them
- default theme is not editable, and always will be defined at startup
(initTheme)
- saves in .B.blend
- themes for spaces can become local too, so you can set individual
3d windows at theme 'Maya' or so. (to be implemented)
- it uses alpha as well...!
API:
This doesnt use the old method with BFCOLORID blahblah. The API is copied
from OpenGL conventions (naming) as much as possible:
- void BIF_ThemeColor(ScrArea *sa, int colorid)
sets a color... id's are in BIF_resources.h (TH_GRID, TH_WIRE, etc)
- void BIF_ThemeColorShade(ScrArea *sa, int colorid, int offset)
sets a color with offset, no more weird COLORSHADE_LGREY stuff
- void BIF_GetThemeColor3fv(ScrArea *sa, int colorid, float *col)
like opengl, this gives you in *col the three rgb values
- void BIF_GetThemeColor4ubv(ScrArea *sa, int colorid, char *col)
or the one to get 4 bytes
ThemeColor calls for globals (UI etc) can also call NULL for *sa... this
is to be implemented still.
Next step: cleaning up interface.c for all weird colorcalls.
2003-10-17 14:02:08 +00:00
|
|
|
static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
|
|
|
|
|
{
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
UserDef *user;
|
2022-09-15 19:13:01 +02:00
|
|
|
bfd->user = user = static_cast<UserDef *>(read_struct(fd, bhead, "user def"));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2013-02-13 16:52:14 +00:00
|
|
|
/* User struct has separate do-version handling */
|
|
|
|
|
user->versionfile = bfd->main->versionfile;
|
|
|
|
|
user->subversionfile = bfd->main->subversionfile;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
/* read all data into fd->datamap */
|
2020-04-03 16:01:56 +02:00
|
|
|
bhead = read_data_into_datamap(fd, bhead, "user def");
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-06-07 11:30:32 +02:00
|
|
|
BlendDataReader reader_ = {fd};
|
|
|
|
|
BlendDataReader *reader = &reader_;
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, bTheme, &user->themes);
|
|
|
|
|
BLO_read_struct_list(reader, wmKeyMap, &user->user_keymaps);
|
|
|
|
|
BLO_read_struct_list(reader, wmKeyConfigPref, &user->user_keyconfig_prefs);
|
|
|
|
|
BLO_read_struct_list(reader, bUserMenu, &user->user_menus);
|
|
|
|
|
BLO_read_struct_list(reader, bAddon, &user->addons);
|
|
|
|
|
BLO_read_struct_list(reader, bPathCompare, &user->autoexec_paths);
|
|
|
|
|
BLO_read_struct_list(reader, bUserScriptDirectory, &user->script_directories);
|
|
|
|
|
BLO_read_struct_list(reader, bUserAssetLibrary, &user->asset_libraries);
|
|
|
|
|
BLO_read_struct_list(reader, bUserExtensionRepo, &user->extension_repos);
|
2024-05-03 10:20:01 -04:00
|
|
|
BLO_read_struct_list(reader, bUserAssetShelfSettings, &user->asset_shelves_settings);
|
2015-04-06 10:40:12 -03:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (wmKeyMap *, keymap, &user->user_keymaps) {
|
2022-09-15 19:13:01 +02:00
|
|
|
keymap->modal_items = nullptr;
|
|
|
|
|
keymap->poll = nullptr;
|
KEYMAP REFACTORING
Diff Keymaps
User edited keymaps now no longer override the builtin keymaps entirely, but
rather save only the difference and reapply those changes. This means they can
stay better in sync when the builtin keymaps change. The diff/patch algorithm
is not perfect, but better for the common case where only a few items are changed
rather than entire keymaps The main weakness is that if a builtin keymap item
changes, user modification of that item may need to be redone in some cases.
Keymap Editor
The most noticeable change here is that there is no longer an "Edit" button for
keymaps, all are editable immediately, but a "Restore" buttons shows for keymaps
and items that have been edited. Shortcuts for addons can also be edited in the
keymap editor.
Addons
Addons now should only modify the new addon keyconfiguration, the keymap items
there will be added to the builtin ones for handling events, and not get lost
when starting new files. Example code of register/unregister:
km = wm.keyconfigs.addon.keymaps.new("3D View", space_type="VIEW_3D")
km.keymap_items.new('my.operator', 'ESC', 'PRESS')
km = wm.keyconfigs.addon.keymaps["3D View"]
km.keymap_items.remove(km.keymap_items["my.operator"])
Compatibility
The changes made are not forward compatible, i.e. if you save user preferences
with newer versions, older versions will not have key configuration changes that
were made.
2011-08-05 20:45:26 +00:00
|
|
|
keymap->flag &= ~KEYMAP_UPDATE;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, wmKeyMapDiffItem, &keymap->diff_items);
|
|
|
|
|
BLO_read_struct_list(reader, wmKeyMapItem, &keymap->items);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, wmKeyMapItem, &kmdi->remove_item);
|
|
|
|
|
BLO_read_struct(reader, wmKeyMapItem, &kmdi->add_item);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (kmdi->remove_item) {
|
2020-06-07 11:30:32 +02:00
|
|
|
direct_link_keymapitem(reader, kmdi->remove_item);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (kmdi->add_item) {
|
2020-06-07 11:30:32 +02:00
|
|
|
direct_link_keymapitem(reader, kmdi->add_item);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
|
2020-06-07 11:30:32 +02:00
|
|
|
direct_link_keymapitem(reader, kmi);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
- The basic layer for Themes in place!
- currently only implemented for 3d window
- create as many themes you like, and name them
- default theme is not editable, and always will be defined at startup
(initTheme)
- saves in .B.blend
- themes for spaces can become local too, so you can set individual
3d windows at theme 'Maya' or so. (to be implemented)
- it uses alpha as well...!
API:
This doesnt use the old method with BFCOLORID blahblah. The API is copied
from OpenGL conventions (naming) as much as possible:
- void BIF_ThemeColor(ScrArea *sa, int colorid)
sets a color... id's are in BIF_resources.h (TH_GRID, TH_WIRE, etc)
- void BIF_ThemeColorShade(ScrArea *sa, int colorid, int offset)
sets a color with offset, no more weird COLORSHADE_LGREY stuff
- void BIF_GetThemeColor3fv(ScrArea *sa, int colorid, float *col)
like opengl, this gives you in *col the three rgb values
- void BIF_GetThemeColor4ubv(ScrArea *sa, int colorid, char *col)
or the one to get 4 bytes
ThemeColor calls for globals (UI etc) can also call NULL for *sa... this
is to be implemented still.
Next step: cleaning up interface.c for all weird colorcalls.
2003-10-17 14:02:08 +00:00
|
|
|
}
|
2013-03-26 09:59:43 +00:00
|
|
|
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (wmKeyConfigPref *, kpt, &user->user_keyconfig_prefs) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, IDProperty, &kpt->prop);
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &kpt->prop);
|
2018-11-16 11:24:49 +11:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (bUserMenu *, um, &user->user_menus) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, bUserMenuItem, &um->items);
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (bUserMenuItem *, umi, &um->items) {
|
2018-06-24 16:07:34 +02:00
|
|
|
if (umi->type == USER_MENU_TYPE_OPERATOR) {
|
|
|
|
|
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, IDProperty, &umi_op->prop);
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &umi_op->prop);
|
2018-06-24 16:07:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (bAddon *, addon, &user->addons) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, IDProperty, &addon->prop);
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &addon->prop);
|
2012-12-29 10:24:42 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-22 20:32:23 +10:00
|
|
|
LISTBASE_FOREACH (bUserExtensionRepo *, repo_ref, &user->extension_repos) {
|
|
|
|
|
BKE_preferences_extension_repo_read_data(reader, repo_ref);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-03 10:20:01 -04:00
|
|
|
LISTBASE_FOREACH (bUserAssetShelfSettings *, shelf_settings, &user->asset_shelves_settings) {
|
|
|
|
|
BKE_asset_catalog_path_list_blend_read_data(reader, shelf_settings->enabled_catalog_paths);
|
|
|
|
|
}
|
|
|
|
|
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
/* XXX */
|
2022-09-15 19:13:01 +02:00
|
|
|
user->uifonts.first = user->uifonts.last = nullptr;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, uiStyle, &user->uistyles);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-08-28 15:12:14 +02:00
|
|
|
/* Don't read the active app template, use the default one. */
|
|
|
|
|
user->app_template[0] = '\0';
|
|
|
|
|
|
2019-05-13 10:52:14 +02:00
|
|
|
/* Clear runtime data. */
|
|
|
|
|
user->runtime.is_dirty = false;
|
2019-05-31 18:09:38 +02:00
|
|
|
user->edit_studio_light = 0;
|
2019-05-13 10:52:14 +02:00
|
|
|
|
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
|
|
|
/* free fd->datamap again */
|
|
|
|
|
oldnewmap_clear(fd->datamap);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
- The basic layer for Themes in place!
- currently only implemented for 3d window
- create as many themes you like, and name them
- default theme is not editable, and always will be defined at startup
(initTheme)
- saves in .B.blend
- themes for spaces can become local too, so you can set individual
3d windows at theme 'Maya' or so. (to be implemented)
- it uses alpha as well...!
API:
This doesnt use the old method with BFCOLORID blahblah. The API is copied
from OpenGL conventions (naming) as much as possible:
- void BIF_ThemeColor(ScrArea *sa, int colorid)
sets a color... id's are in BIF_resources.h (TH_GRID, TH_WIRE, etc)
- void BIF_ThemeColorShade(ScrArea *sa, int colorid, int offset)
sets a color with offset, no more weird COLORSHADE_LGREY stuff
- void BIF_GetThemeColor3fv(ScrArea *sa, int colorid, float *col)
like opengl, this gives you in *col the three rgb values
- void BIF_GetThemeColor4ubv(ScrArea *sa, int colorid, char *col)
or the one to get 4 bytes
ThemeColor calls for globals (UI etc) can also call NULL for *sa... this
is to be implemented still.
Next step: cleaning up interface.c for all weird colorcalls.
2003-10-17 14:02:08 +00:00
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read File (Internal)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
static int read_undo_remap_noundo_data_cb(LibraryIDLinkCallbackData *cb_data)
|
|
|
|
|
{
|
|
|
|
|
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-22 13:47:13 +01:00
|
|
|
IDNameLib_Map *new_idmap_uid = static_cast<IDNameLib_Map *>(cb_data->user_data);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
ID **id_pointer = cb_data->id_pointer;
|
|
|
|
|
if (*id_pointer != nullptr) {
|
2024-01-22 13:47:13 +01:00
|
|
|
*id_pointer = BKE_main_idmap_lookup_uid(new_idmap_uid, (*id_pointer)->session_uid);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remap 'no undo' ID usages to matching IDs in new main.
|
|
|
|
|
*
|
|
|
|
|
* 'no undo' IDs have simply be moved from old to new main so far. However, unlike the other
|
|
|
|
|
* re-used IDs (the 'unchanged' ones), there is no guarantee that all the ID pointers they use are
|
|
|
|
|
* still valid.
|
|
|
|
|
*
|
2024-01-22 13:47:13 +01:00
|
|
|
* This code performs a remapping based on the session_uid. */
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
static void read_undo_remap_noundo_data(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
Main *new_bmain = static_cast<Main *>(fd->mainlist->first);
|
|
|
|
|
ID *id_iter;
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (new_bmain, id_iter) {
|
|
|
|
|
if (ID_IS_LINKED(id_iter)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((id_iter->tag & LIB_TAG_UNDO_OLD_ID_REUSED_NOUNDO) == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_library_foreach_ID_link(
|
2024-01-22 13:47:13 +01:00
|
|
|
new_bmain, id_iter, read_undo_remap_noundo_data_cb, fd->new_idmap_uid, IDWALK_INCLUDE_UI);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 14:15:11 +11:00
|
|
|
/**
|
|
|
|
|
* Contains sanity/debug checks to be performed at the very end of the reading process (i.e. after
|
|
|
|
|
* data, liblink, linked data, etc. has been done).
|
|
|
|
|
*/
|
2023-01-27 15:32:44 +01:00
|
|
|
static void blo_read_file_checks(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
#ifndef NDEBUG
|
2023-02-22 16:37:15 +01:00
|
|
|
BLI_assert(bmain->next == nullptr);
|
|
|
|
|
BLI_assert(!bmain->is_read_invalid);
|
|
|
|
|
|
2023-01-27 15:32:44 +01:00
|
|
|
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
|
|
|
|
|
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
|
|
|
|
/* This pointer is deprecated and should always be nullptr. */
|
|
|
|
|
BLI_assert(win->screen == nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2023-01-27 09:59:38 -06:00
|
|
|
UNUSED_VARS_NDEBUG(bmain);
|
2023-01-27 15:32:44 +01:00
|
|
|
}
|
|
|
|
|
|
2011-05-18 06:27:32 +00:00
|
|
|
BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-02-22 10:31:17 +11:00
|
|
|
BHead *bhead = blo_bhead_first(fd);
|
2002-10-12 11:37:38 +00:00
|
|
|
BlendFileData *bfd;
|
2022-09-15 19:13:01 +02:00
|
|
|
ListBase mainlist = {nullptr, nullptr};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
const bool is_undo = (fd->flags & FD_FLAGS_IS_MEMFILE) != 0;
|
|
|
|
|
if (is_undo) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO, 2, "UNDO: read step");
|
2020-04-04 19:30:42 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
bfd = static_cast<BlendFileData *>(MEM_callocN(sizeof(BlendFileData), "blendfiledata"));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
bfd->main = BKE_main_new();
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->main->versionfile = fd->fileversion;
|
2024-01-24 10:49:24 +01:00
|
|
|
STRNCPY(bfd->filepath, filepath);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->type = BLENFILETYPE_BLEND;
|
2019-05-13 12:36:14 +10:00
|
|
|
|
|
|
|
|
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
|
|
|
|
|
BLI_addtail(&mainlist, bfd->main);
|
|
|
|
|
fd->mainlist = &mainlist;
|
2021-12-13 16:22:19 +11:00
|
|
|
STRNCPY(bfd->main->filepath, filepath);
|
2019-05-13 12:36:14 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
if (G.background) {
|
|
|
|
|
/* We only read & store .blend thumbnail in background mode
|
|
|
|
|
* (because we cannot re-generate it, no OpenGL available).
|
|
|
|
|
*/
|
|
|
|
|
const int *data = read_file_thumbnail(fd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
if (data) {
|
2019-02-11 19:09:27 +11:00
|
|
|
const int width = data[0];
|
|
|
|
|
const int height = data[1];
|
|
|
|
|
if (BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
|
2022-05-11 13:37:10 +10:00
|
|
|
const size_t data_size = BLEN_THUMB_MEMSIZE(width, height);
|
2022-09-15 19:13:01 +02:00
|
|
|
bfd->main->blen_thumb = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-05-11 13:37:10 +10:00
|
|
|
BLI_assert((data_size - sizeof(*bfd->main->blen_thumb)) ==
|
2018-01-14 23:26:31 +01:00
|
|
|
(BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*data) * 2)));
|
|
|
|
|
bfd->main->blen_thumb->width = width;
|
|
|
|
|
bfd->main->blen_thumb->height = height;
|
2022-05-11 13:37:10 +10:00
|
|
|
memcpy(bfd->main->blen_thumb->rect, &data[2], data_size - sizeof(*bfd->main->blen_thumb));
|
2018-01-14 23:26:31 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Make .blend file thumbnail reading simpler and more coherent, read/store them when reading in background mode.
Primary goal of this commit is to fix an annoying issue - when processing and saving .blend
files in background mode you lose their thumbnails, since it can only be generated with
an OpenGL context.
Solution to that is to read .blend thumbnail while reading .blend file (only done in background
mode currently), and store it in Main struct.
Also, this lead to removing .blend file reading code from thumb_blend (no need to have doublons).
We now have a small interface in regular reading code area, which keeps it reasonbaly light
by only reading/parsing header info, and first few BHead blocks.
This makes code reading .blend thumbnail about 3 to 4 times slower than previous highly specialized
one in blend_thumb.c, but overall thumbnail generation of a big .blend files folder only grows
of about 1%, think we can bare with it.
Finally, since thumbnail is now optionally stored in Main struct, it makes it easy to allow user
to define their own custom one (instead of auto-generated one). RNA API for this was not added though,
accessing that kind of .blend meta-data has to be rethought a bit on a bigger level first.
Reviewers: sergey, campbellbarton
Subscribers: Severin, psy-fi
Differential Revision: https://developer.blender.org/D1469
2015-08-27 15:53:23 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (is_undo) {
|
2024-01-22 13:47:13 +01:00
|
|
|
/* This idmap will store uids of all IDs ending up in the new main, whether they are newly
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
* read, or re-used from the old main. */
|
2024-01-22 13:47:13 +01:00
|
|
|
fd->new_idmap_uid = BKE_main_idmap_create(
|
|
|
|
|
static_cast<Main *>(fd->mainlist->first), false, nullptr, MAIN_IDMAP_TYPE_UID);
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
|
|
|
|
|
/* Copy all 'no undo' local data from old to new bmain. */
|
|
|
|
|
read_undo_reuse_noundo_local_ids(fd);
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 07:52:14 +00:00
|
|
|
while (bhead) {
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (bhead->code) {
|
2023-04-08 12:42:40 +02:00
|
|
|
case BLO_CODE_DATA:
|
|
|
|
|
case BLO_CODE_DNA1:
|
|
|
|
|
case BLO_CODE_TEST: /* used as preview since 2.5x */
|
|
|
|
|
case BLO_CODE_REND:
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
2018-08-30 01:31:20 +10:00
|
|
|
break;
|
2023-04-08 12:42:40 +02:00
|
|
|
case BLO_CODE_GLOB:
|
2018-08-30 01:31:20 +10:00
|
|
|
bhead = read_global(bfd, fd, bhead);
|
|
|
|
|
break;
|
2023-04-08 12:42:40 +02:00
|
|
|
case BLO_CODE_USER:
|
2018-08-30 01:31:20 +10:00
|
|
|
if (fd->skip_flags & BLO_READ_SKIP_USERDEF) {
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
2018-08-30 01:31:20 +10:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
bhead = read_userdef(bfd, fd, bhead);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2023-04-08 12:42:40 +02:00
|
|
|
case BLO_CODE_ENDB:
|
2022-09-15 19:13:01 +02:00
|
|
|
bhead = nullptr;
|
2018-08-30 01:31:20 +10:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
case ID_LINK_PLACEHOLDER:
|
2018-08-30 01:31:20 +10:00
|
|
|
if (fd->skip_flags & BLO_READ_SKIP_DATA) {
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
2018-08-30 01:31:20 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Add link placeholder to the main of the library it belongs to.
|
|
|
|
|
* The library is the most recently loaded ID_LI block, according
|
|
|
|
|
* to the file format definition. So we can use the entry at the
|
|
|
|
|
* end of mainlist, added in direct_link_library. */
|
2022-09-15 19:13:01 +02:00
|
|
|
Main *libmain = static_cast<Main *>(mainlist.last);
|
|
|
|
|
bhead = read_libblock(fd, libmain, bhead, 0, true, nullptr);
|
2018-08-30 01:31:20 +10:00
|
|
|
}
|
|
|
|
|
break;
|
2020-03-09 16:27:24 +01:00
|
|
|
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
|
2018-08-30 01:31:20 +10:00
|
|
|
case ID_SCRN:
|
|
|
|
|
bhead->code = ID_SCR;
|
|
|
|
|
/* pass on to default */
|
|
|
|
|
ATTR_FALLTHROUGH;
|
|
|
|
|
default:
|
|
|
|
|
if (fd->skip_flags & BLO_READ_SKIP_DATA) {
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
2018-08-30 01:31:20 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2022-09-15 19:13:01 +02:00
|
|
|
bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, false, nullptr);
|
2018-08-30 01:31:20 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2023-02-22 16:37:15 +01:00
|
|
|
|
|
|
|
|
if (bfd->main->is_read_invalid) {
|
|
|
|
|
return bfd;
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (is_undo) {
|
|
|
|
|
/* Move the remaining Library IDs and their linked data to the new main.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: These linked IDs have not been detected as used in newly read main. However, they
|
|
|
|
|
* could be dependencies from some 'no undo' IDs that were unconditionally moved from the old
|
|
|
|
|
* to the new main.
|
|
|
|
|
*
|
|
|
|
|
* While there could be some more refined check here to detect such cases and only move these
|
|
|
|
|
* into the new bmain, in practice it is simpler to systematically move all linked data. The
|
|
|
|
|
* handling of libraries already moves all their linked IDs too, regardless of whether they are
|
|
|
|
|
* effectively used or not. */
|
|
|
|
|
|
|
|
|
|
Main *new_main = bfd->main;
|
|
|
|
|
Main *old_main = static_cast<Main *>(fd->old_mainlist->first);
|
|
|
|
|
BLI_assert(old_main != nullptr);
|
|
|
|
|
BLI_assert(old_main->curlib == nullptr);
|
2024-02-27 17:28:29 +01:00
|
|
|
Main *libmain, *libmain_next;
|
|
|
|
|
for (libmain = old_main->next; libmain != nullptr; libmain = libmain_next) {
|
|
|
|
|
libmain_next = libmain->next;
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
read_undo_move_libmain_data(fd, new_main, old_main, libmain, nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do versioning before read_libraries, but skip in undo case. */
|
|
|
|
|
if (!is_undo) {
|
2019-05-13 12:36:14 +10:00
|
|
|
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
|
2022-09-15 19:13:01 +02:00
|
|
|
do_versions(fd, nullptr, bfd->main);
|
2019-05-13 12:36:14 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((fd->skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
|
|
|
|
|
do_versions_userdef(fd, bfd);
|
|
|
|
|
}
|
2015-08-28 14:06:01 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (bfd->main->is_read_invalid) {
|
|
|
|
|
return bfd;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
|
2024-02-15 13:15:56 +11:00
|
|
|
fd->reports->duration.libraries = BLI_time_now_seconds();
|
2019-05-13 12:36:14 +10:00
|
|
|
read_libraries(fd, &mainlist);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
blo_join_main(&mainlist);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
lib_link_all(fd, bfd->main);
|
2023-08-28 13:10:22 +02:00
|
|
|
after_liblink_merged_bmain_process(bfd->main, fd->reports);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
if (is_undo) {
|
|
|
|
|
/* Ensure ID usages of reused 'no undo' IDs remain valid. */
|
|
|
|
|
/* Although noundo data was reused as-is from the old main, it may have ID pointers to data
|
|
|
|
|
* that has been removed, or that have a new address. */
|
|
|
|
|
read_undo_remap_noundo_data(fd);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-15 13:15:56 +11:00
|
|
|
fd->reports->duration.libraries = BLI_time_now_seconds() - fd->reports->duration.libraries;
|
2021-06-23 09:51:11 +02:00
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Skip in undo case. */
|
2024-02-27 17:07:36 +01:00
|
|
|
if (!is_undo) {
|
2020-03-07 00:05:27 +11:00
|
|
|
/* Note that we can't recompute user-counts at this point in undo case, we play too much with
|
2020-02-20 11:28:23 +01:00
|
|
|
* IDs from different memory realms, and Main database is not in a fully valid state yet.
|
|
|
|
|
*/
|
2020-03-07 00:05:27 +11:00
|
|
|
/* Some versioning code does expect some proper user-reference-counting, e.g. in conversion
|
|
|
|
|
* from groups to collections... We could optimize out that first call when we are reading a
|
|
|
|
|
* current version file, but again this is really not a bottle neck currently.
|
|
|
|
|
* So not worth it. */
|
2020-02-20 11:28:23 +01:00
|
|
|
BKE_main_id_refcount_recompute(bfd->main, false);
|
|
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Yep, second splitting... but this is a very cheap operation, so no big deal. */
|
|
|
|
|
blo_split_main(&mainlist, bfd->main);
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (Main *, mainvar, &mainlist) {
|
2019-05-13 12:36:14 +10:00
|
|
|
BLI_assert(mainvar->versionfile != 0);
|
2024-04-08 13:08:36 +02:00
|
|
|
do_versions_after_linking((mainvar->curlib && mainvar->curlib->runtime.filedata) ?
|
|
|
|
|
mainvar->curlib->runtime.filedata :
|
|
|
|
|
fd,
|
|
|
|
|
mainvar);
|
2019-05-13 12:36:14 +10:00
|
|
|
}
|
|
|
|
|
blo_join_main(&mainlist);
|
2019-04-20 20:25:22 +02:00
|
|
|
|
2020-03-07 00:05:27 +11:00
|
|
|
/* And we have to compute those user-reference-counts again, as `do_versions_after_linking()`
|
|
|
|
|
* does not always properly handle user counts, and/or that function does not take into
|
|
|
|
|
* account old, deprecated data. */
|
readfile: Move ID refcounting to libquery.
Having that extra ID users handling at readfile level, besides generic
one ensured by libquery, has been something bothering me for a long time
(had to fix my share of bugs due to mismatches between those two areas).
Further more, work on undo speedup will require even more complex ID
refcount management if we want to keep it in readfile.c area.
So idea is instead to generalize what we did for linked data already
when undoing: recompute properly usercount numbers after liblink step,
for all IDs.
Note that extra time required here is neglectable in a whole .blend file
reading (few extra milliseconds when loading a full production scene
e.g.).
Notes:
* Some deprecated data (IPOs) are not refcounted at all anymore, this
should not be an issue in pratice since the are supposed to get deleted
after doversion anyway.
* Refcounting happens after `do_versions_after_linking`, i.e those
functions won't get valid ID usercounts currently. Again, this is not a
problem in current code, if needed we could recompute refcount before,
and then ensure `do_versions_after_linoiing()` actually handles properly
usercount, which it does not currently.
Differential Revision: https://developer.blender.org/D6881
2020-02-19 12:50:04 +01:00
|
|
|
BKE_main_id_refcount_recompute(bfd->main, false);
|
2019-05-13 12:36:14 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-09-01 17:58:18 +02:00
|
|
|
LISTBASE_FOREACH (Library *, lib, &bfd->main->libraries) {
|
|
|
|
|
/* Now we can clear this runtime library filedata, it is not needed anymore. */
|
2024-04-08 13:08:36 +02:00
|
|
|
if (lib->runtime.filedata) {
|
|
|
|
|
blo_filedata_free(lib->runtime.filedata);
|
|
|
|
|
lib->runtime.filedata = nullptr;
|
2023-09-01 17:58:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (bfd->main->is_read_invalid) {
|
|
|
|
|
return bfd;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-12 15:38:56 -05:00
|
|
|
/* After all data has been read and versioned, uses LIB_TAG_NEW. Theoretically this should
|
|
|
|
|
* not be calculated in the undo case, but it is currently needed even on undo to recalculate
|
|
|
|
|
* a cache. */
|
2023-05-15 15:14:22 +02:00
|
|
|
blender::bke::ntreeUpdateAllNew(bfd->main);
|
2021-10-12 15:38:56 -05:00
|
|
|
|
2019-08-12 11:54:37 +02:00
|
|
|
placeholders_ensure_valid(bfd->main);
|
|
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-24 17:37:42 +02:00
|
|
|
/* Must happen before applying liboverrides, as this process may fully invalidate e.g. view
|
|
|
|
|
* layer pointers in case a Scene is a liboverride. */
|
|
|
|
|
link_global(fd, bfd);
|
|
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Now that all our data-blocks are loaded,
|
|
|
|
|
* we can re-generate overrides from their references. */
|
2024-02-27 17:07:36 +01:00
|
|
|
if (!is_undo) {
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Do not apply in undo case! */
|
2024-02-15 13:15:56 +11:00
|
|
|
fd->reports->duration.lib_overrides = BLI_time_now_seconds();
|
2021-06-23 09:51:11 +02:00
|
|
|
|
2023-05-24 17:37:42 +02:00
|
|
|
std::string cur_view_layer_name = bfd->cur_view_layer != nullptr ?
|
|
|
|
|
bfd->cur_view_layer->name :
|
|
|
|
|
"";
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_lib_override_library_main_validate(bfd->main, fd->reports->reports);
|
2020-02-10 18:05:19 +01:00
|
|
|
BKE_lib_override_library_main_update(bfd->main);
|
2021-06-23 09:51:11 +02:00
|
|
|
|
2023-05-24 17:37:42 +02:00
|
|
|
/* In case the current scene is a liboverride, while the ID pointer itself remains valid,
|
|
|
|
|
* above update of liboverrides will have completely invalidated its old content, so the
|
2023-05-25 22:47:24 +10:00
|
|
|
* current view-layer needs to be searched for again. */
|
2023-05-24 17:37:42 +02:00
|
|
|
if (bfd->cur_view_layer != nullptr) {
|
|
|
|
|
bfd->cur_view_layer = BKE_view_layer_find(bfd->curscene, cur_view_layer_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-26 20:24:16 +09:00
|
|
|
/* FIXME Temporary 'fix' to a problem in how temp ID are copied in
|
2023-02-12 14:37:16 +11:00
|
|
|
* `BKE_lib_override_library_main_update`, see #103062.
|
|
|
|
|
* Proper fix involves first addressing #90610. */
|
2022-12-26 20:24:16 +09:00
|
|
|
BKE_main_collections_parent_relations_rebuild(bfd->main);
|
|
|
|
|
|
2024-02-15 13:15:56 +11:00
|
|
|
fd->reports->duration.lib_overrides = BLI_time_now_seconds() -
|
2021-06-23 09:51:11 +02:00
|
|
|
fd->reports->duration.lib_overrides;
|
2019-05-13 12:36:14 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
BKE_collections_after_lib_link(bfd->main);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Make all relative paths, relative to the open blend file. */
|
|
|
|
|
fix_relpaths_library(fd->relabase, bfd->main);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
fd->mainlist = nullptr; /* Safety, this is local variable, shall not be used afterward. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(bfd->main->id_map == nullptr);
|
2021-06-30 15:19:35 +02:00
|
|
|
|
2023-01-27 15:32:44 +01:00
|
|
|
/* Sanity checks. */
|
|
|
|
|
blo_read_file_checks(bfd->main);
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return bfd;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Library Linking
|
|
|
|
|
*
|
|
|
|
|
* Also used for append.
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-08-04 19:34:38 +00:00
|
|
|
struct BHeadSort {
|
2008-01-30 18:18:33 +00:00
|
|
|
BHead *bhead;
|
2016-06-22 08:44:26 +10:00
|
|
|
const void *old;
|
2008-01-30 18:18:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int verg_bheadsort(const void *v1, const void *v2)
|
|
|
|
|
{
|
2022-10-05 13:44:02 -05:00
|
|
|
const BHeadSort *x1 = static_cast<const BHeadSort *>(v1),
|
|
|
|
|
*x2 = static_cast<const BHeadSort *>(v2);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (x1->old > x2->old) {
|
2012-05-17 12:59:34 +00:00
|
|
|
return 1;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
if (x1->old < x2->old) {
|
2012-05-17 12:59:34 +00:00
|
|
|
return -1;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2008-01-30 18:18:33 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sort_bhead_old_map(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
BHead *bhead;
|
2022-10-05 13:44:02 -05:00
|
|
|
BHeadSort *bhs;
|
2012-05-17 12:59:34 +00:00
|
|
|
int tot = 0;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2008-01-30 18:18:33 +00:00
|
|
|
tot++;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
fd->tot_bheadmap = tot;
|
2019-04-22 09:13:00 +10:00
|
|
|
if (tot == 0) {
|
2012-05-17 12:59:34 +00:00
|
|
|
return;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
bhs = fd->bheadmap = static_cast<BHeadSort *>(
|
2022-10-05 13:44:02 -05:00
|
|
|
MEM_malloc_arrayN(tot, sizeof(BHeadSort), "BHeadSort"));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead), bhs++) {
|
2012-05-17 12:59:34 +00:00
|
|
|
bhs->bhead = bhead;
|
|
|
|
|
bhs->old = bhead->old;
|
2008-01-30 18:18:33 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
qsort(fd->bheadmap, tot, sizeof(BHeadSort), verg_bheadsort);
|
2008-01-30 18:18:33 +00:00
|
|
|
}
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static BHead *find_previous_lib(FileData *fd, BHead *bhead)
|
|
|
|
|
{
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Skip library data-blocks in undo, see comment in read_libblock. */
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2009-10-20 16:43:25 +00:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (; bhead; bhead = blo_bhead_prev(fd, bhead)) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (bhead->code == ID_LI) {
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
}
|
2004-06-23 18:22:51 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BHead *find_bhead(FileData *fd, void *old)
|
|
|
|
|
{
|
2008-02-03 18:50:03 +00:00
|
|
|
#if 0
|
2023-07-12 14:18:59 +02:00
|
|
|
BHead *bhead;
|
2008-02-03 18:50:03 +00:00
|
|
|
#endif
|
2022-10-05 13:44:02 -05:00
|
|
|
BHeadSort *bhs, bhs_s;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (!old) {
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2004-06-23 18:22:51 +00:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (fd->bheadmap == nullptr) {
|
2008-01-30 18:18:33 +00:00
|
|
|
sort_bhead_old_map(fd);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bhs_s.old = old;
|
2022-09-15 19:13:01 +02:00
|
|
|
bhs = static_cast<BHeadSort *>(
|
2022-10-05 13:44:02 -05:00
|
|
|
bsearch(&bhs_s, fd->bheadmap, fd->tot_bheadmap, sizeof(BHeadSort), verg_bheadsort));
|
2008-01-30 18:18:33 +00:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (bhs) {
|
2008-01-30 18:18:33 +00:00
|
|
|
return bhs->bhead;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2008-02-03 18:50:03 +00:00
|
|
|
#if 0
|
2020-05-26 12:04:16 +02:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
|
|
|
|
if (bhead->old == old) {
|
|
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-02-03 18:50:03 +00:00
|
|
|
#endif
|
2004-06-23 18:22:51 +00:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-11 00:05:14 +11:00
|
|
|
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name)
|
|
|
|
|
{
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
|
|
|
|
|
|
|
|
|
char idname_full[MAX_ID_NAME];
|
|
|
|
|
|
|
|
|
|
*((short *)idname_full) = idcode;
|
|
|
|
|
BLI_strncpy(idname_full + 2, name, sizeof(idname_full) - 2);
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
return static_cast<BHead *>(BLI_ghash_lookup(fd->bhead_idname_hash, idname_full));
|
2015-03-11 00:33:44 +11:00
|
|
|
|
|
|
|
|
#else
|
2015-03-11 00:05:14 +11:00
|
|
|
BHead *bhead;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2015-03-11 00:05:14 +11:00
|
|
|
if (bhead->code == idcode) {
|
2019-02-22 10:31:17 +11:00
|
|
|
const char *idname_test = blo_bhead_id_name(fd, bhead);
|
2015-03-11 00:05:14 +11:00
|
|
|
if (STREQ(idname_test + 2, name)) {
|
|
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (bhead->code == ENDB) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
return nullptr;
|
2015-03-11 00:33:44 +11:00
|
|
|
#endif
|
2015-03-11 00:05:14 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BHead *find_bhead_from_idname(FileData *fd, const char *idname)
|
|
|
|
|
{
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
2022-09-15 19:13:01 +02:00
|
|
|
return static_cast<BHead *>(BLI_ghash_lookup(fd->bhead_idname_hash, idname));
|
2015-03-11 00:33:44 +11:00
|
|
|
#else
|
2015-03-11 00:05:14 +11:00
|
|
|
return find_bhead_from_code_name(fd, GS(idname), idname + 2);
|
2015-03-11 00:33:44 +11:00
|
|
|
#endif
|
2015-03-11 00:05:14 +11:00
|
|
|
}
|
|
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
static ID *library_id_is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
if (mainvar->id_map == nullptr) {
|
|
|
|
|
mainvar->id_map = BKE_main_idmap_create(mainvar, false, nullptr, MAIN_IDMAP_TYPE_NAME);
|
2021-06-30 15:19:35 +02:00
|
|
|
}
|
|
|
|
|
BLI_assert(BKE_main_idmap_main_get(mainvar->id_map) == mainvar);
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
const char *idname = blo_bhead_id_name(fd, bhead);
|
2021-06-30 15:19:35 +02:00
|
|
|
|
|
|
|
|
ID *id = BKE_main_idmap_lookup_name(mainvar->id_map, GS(idname), idname + 2, mainvar->curlib);
|
|
|
|
|
BLI_assert(id == BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name)));
|
|
|
|
|
return id;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Library Linking (expand pointers)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-08-23 12:36:56 +02:00
|
|
|
struct BlendExpander {
|
|
|
|
|
FileData *fd;
|
|
|
|
|
Main *main;
|
2024-05-10 17:22:25 +02:00
|
|
|
BLOExpandDoitCallback callback;
|
2023-08-23 12:36:56 +02:00
|
|
|
};
|
|
|
|
|
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
FileData *fd = static_cast<FileData *>(fdhandle);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (mainvar->is_read_invalid) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
BHead *bhead = find_bhead(fd, old);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (bhead == nullptr) {
|
2019-02-27 19:25:21 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (bhead->code == ID_LINK_PLACEHOLDER) {
|
2022-07-26 09:59:45 +02:00
|
|
|
/* Placeholder link to data-block in another library. */
|
2019-02-27 19:25:21 +01:00
|
|
|
BHead *bheadlib = find_previous_lib(fd, bhead);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (bheadlib == nullptr) {
|
2019-02-27 19:25:21 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
Library *lib = static_cast<Library *>(read_struct(fd, bheadlib, "Library"));
|
2020-06-23 09:54:14 +10:00
|
|
|
Main *libmain = blo_find_main(fd, lib->filepath, fd->relabase);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (libmain->curlib == nullptr) {
|
2019-02-27 19:25:21 +01:00
|
|
|
const char *idname = blo_bhead_id_name(fd, bhead);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-06 15:07:10 +01:00
|
|
|
BLO_reportf_wrap(fd->reports,
|
2019-02-27 19:25:21 +01:00
|
|
|
RPT_WARNING,
|
2024-01-11 19:49:03 +01:00
|
|
|
RPT_("LIB: Data refers to main .blend file: '%s' from %s"),
|
2019-02-27 19:25:21 +01:00
|
|
|
idname,
|
2024-04-08 13:08:36 +02:00
|
|
|
mainvar->curlib->runtime.filepath_abs);
|
2019-02-27 19:25:21 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
ID *id = library_id_is_yet_read(fd, libmain, bhead);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id == nullptr) {
|
2019-02-27 19:25:21 +01:00
|
|
|
/* ID has not been read yet, add placeholder to the main of the
|
|
|
|
|
* library it belongs to, so that it will be read later. */
|
2021-06-04 11:40:27 +02:00
|
|
|
read_libblock(fd, libmain, bhead, fd->id_tag_extra | LIB_TAG_INDIRECT, false, &id);
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(id != nullptr);
|
|
|
|
|
id_sort_by_name(which_libbase(libmain, GS(id->name)), id, static_cast<ID *>(id->prev));
|
2021-06-04 11:40:27 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* commented because this can print way too much */
|
2020-06-23 09:54:14 +10:00
|
|
|
// if (G.debug & G_DEBUG) printf("expand_doit: other lib %s\n", lib->filepath);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* for outliner dependency only */
|
2024-04-08 13:08:36 +02:00
|
|
|
libmain->curlib->runtime.parent = mainvar->curlib;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-09-16 14:52:06 +02:00
|
|
|
/* Convert any previously read weak link to regular link
|
2019-10-10 10:25:46 +11:00
|
|
|
* to signal that we want to read this data-block. */
|
2019-09-16 14:52:06 +02:00
|
|
|
if (id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
|
|
|
|
|
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* "id" is either a placeholder or real ID that is already in the
|
|
|
|
|
* main of the library (A) it belongs to. However it might have been
|
|
|
|
|
* put there by another library (C) which only updated its own
|
|
|
|
|
* fd->libmap. In that case we also need to update the fd->libmap
|
|
|
|
|
* of the current library (B) so we can find it for lookups.
|
|
|
|
|
*
|
|
|
|
|
* An example of such a setup is:
|
|
|
|
|
* (A) tree.blend: contains Tree object.
|
|
|
|
|
* (B) forest.blend: contains Forest collection linking in Tree from tree.blend.
|
|
|
|
|
* (C) shot.blend: links in both Tree from tree.blend and Forest from forest.blend.
|
|
|
|
|
*/
|
2022-07-28 16:26:02 +02:00
|
|
|
oldnewmap_lib_insert(fd, bhead->old, id, bhead->code);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 01:10:29 +10:00
|
|
|
/* Commented because this can print way too much. */
|
|
|
|
|
#if 0
|
2020-05-26 12:04:16 +02:00
|
|
|
if (G.debug & G_DEBUG) {
|
2020-06-23 09:54:14 +10:00
|
|
|
printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->filepath);
|
2020-05-26 12:04:16 +02:00
|
|
|
}
|
2019-04-22 01:10:29 +10:00
|
|
|
#endif
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
MEM_freeN(lib);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2019-06-17 12:51:53 +10:00
|
|
|
/* Data-block in same library. */
|
2019-02-27 19:25:21 +01:00
|
|
|
/* In 2.50+ file identifier for screens is patched, forward compatibility. */
|
|
|
|
|
if (bhead->code == ID_SCRN) {
|
|
|
|
|
bhead->code = ID_SCR;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
ID *id = library_id_is_yet_read(fd, mainvar, bhead);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id == nullptr) {
|
2021-03-09 00:53:13 +11:00
|
|
|
read_libblock(fd,
|
|
|
|
|
mainvar,
|
|
|
|
|
bhead,
|
|
|
|
|
fd->id_tag_extra | LIB_TAG_NEED_EXPAND | LIB_TAG_INDIRECT,
|
|
|
|
|
false,
|
2021-06-04 11:40:27 +02:00
|
|
|
&id);
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_assert(id != nullptr);
|
|
|
|
|
id_sort_by_name(which_libbase(mainvar, GS(id->name)), id, static_cast<ID *>(id->prev));
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2019-09-16 14:52:06 +02:00
|
|
|
/* Convert any previously read weak link to regular link
|
2019-10-10 10:25:46 +11:00
|
|
|
* to signal that we want to read this data-block. */
|
2019-09-16 14:52:06 +02:00
|
|
|
if (id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
|
|
|
|
|
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-22 01:10:29 +10:00
|
|
|
/* this is actually only needed on UI call? when ID was already read before,
|
|
|
|
|
* and another append happens which invokes same ID...
|
|
|
|
|
* in that case the lookup table needs this entry */
|
2022-07-28 16:26:02 +02:00
|
|
|
oldnewmap_lib_insert(fd, bhead->old, id, bhead->code);
|
2019-02-27 19:25:21 +01:00
|
|
|
/* commented because this can print way too much */
|
|
|
|
|
// if (G.debug & G_DEBUG) printf("expand: already read %s\n", id->name);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-23 12:36:56 +02:00
|
|
|
static int expand_cb(LibraryIDLinkCallbackData *cb_data)
|
2020-02-06 16:25:15 +01:00
|
|
|
{
|
2023-08-23 12:36:56 +02:00
|
|
|
/* Embedded IDs are not known by lib_link code, so they would be remapped to `nullptr`. But there
|
2023-08-24 10:43:45 +10:00
|
|
|
* is no need to process them anyway, as they are already handled during the 'read_data' phase.
|
2023-08-23 12:36:56 +02:00
|
|
|
*/
|
|
|
|
|
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
2023-08-11 14:43:05 +02:00
|
|
|
|
2023-08-24 10:43:45 +10:00
|
|
|
/* Explicitly requested to be ignored during readfile processing. Means the read_data code
|
2023-08-23 12:36:56 +02:00
|
|
|
* already handled this pointer. Typically, the 'owner_id' pointer of an embedded ID. */
|
|
|
|
|
if (cb_data->cb_flag & IDWALK_CB_READFILE_IGNORE) {
|
|
|
|
|
return IDWALK_RET_NOP;
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-24 10:43:45 +10:00
|
|
|
/* Expand process can be re-entrant or have other complex interactions that will not work well
|
2023-08-23 12:36:56 +02:00
|
|
|
* with loop-back pointers. Further more, processing such data should not be needed here anyway.
|
|
|
|
|
*/
|
|
|
|
|
if (cb_data->cb_flag & (IDWALK_CB_LOOPBACK)) {
|
|
|
|
|
return IDWALK_RET_NOP;
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-23 12:36:56 +02:00
|
|
|
BlendExpander *expander = static_cast<BlendExpander *>(cb_data->user_data);
|
|
|
|
|
ID *id = *(cb_data->id_pointer);
|
2020-02-06 16:25:15 +01:00
|
|
|
|
2024-05-10 17:22:25 +02:00
|
|
|
expander->callback(expander->fd, expander->main, id);
|
2023-08-23 12:36:56 +02:00
|
|
|
|
|
|
|
|
return IDWALK_RET_NOP;
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-10 17:22:25 +02:00
|
|
|
void BLO_expand_main(void *fdhandle, Main *mainvar, BLOExpandDoitCallback callback)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
FileData *fd = static_cast<FileData *>(fdhandle);
|
2024-05-10 17:22:25 +02:00
|
|
|
BlendExpander expander = {fd, mainvar, callback};
|
2020-06-26 16:52:44 +02:00
|
|
|
|
2023-08-13 11:19:37 +02:00
|
|
|
for (bool do_it = true; do_it;) {
|
2014-04-01 11:34:00 +11:00
|
|
|
do_it = false;
|
2023-08-13 11:19:37 +02:00
|
|
|
ID *id_iter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-13 11:19:37 +02:00
|
|
|
FOREACH_MAIN_ID_BEGIN (mainvar, id_iter) {
|
|
|
|
|
if ((id_iter->tag & LIB_TAG_NEED_EXPAND) == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-23 12:36:56 +02:00
|
|
|
/* Original (current) ID pointer can be considered as valid, but _not_ its own pointers to
|
|
|
|
|
* other IDs - the already loaded ones will be valid, but the yet-to-be-read ones will not.
|
|
|
|
|
* Expanding should _not_ require processing of UI ID pointers.
|
|
|
|
|
* Expanding should never modify ID pointers themselves.
|
|
|
|
|
* Handling of DNA deprecated data should never be needed in undo case. */
|
|
|
|
|
const int flag = IDWALK_READONLY | IDWALK_NO_ORIG_POINTERS_ACCESS |
|
2023-08-25 11:01:46 +02:00
|
|
|
((!fd || (fd->flags & FD_FLAGS_IS_MEMFILE)) ?
|
|
|
|
|
0 :
|
|
|
|
|
IDWALK_DO_DEPRECATED_POINTERS);
|
2023-08-23 12:36:56 +02:00
|
|
|
BKE_library_foreach_ID_link(nullptr, id_iter, expand_cb, &expander, flag);
|
2023-08-13 11:19:37 +02:00
|
|
|
|
|
|
|
|
do_it = true;
|
|
|
|
|
id_iter->tag &= ~LIB_TAG_NEED_EXPAND;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2023-08-13 11:19:37 +02:00
|
|
|
FOREACH_MAIN_ID_END;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Library Linking (helper functions)
|
|
|
|
|
* \{ */
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
|
2011-03-13 01:15:14 +00:00
|
|
|
/* returns true if the item was found
|
2012-04-22 11:54:53 +00:00
|
|
|
* but it may already have already been appended/linked */
|
2016-06-22 18:05:55 +02:00
|
|
|
static ID *link_named_part(
|
2017-12-04 13:09:13 +01:00
|
|
|
Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2015-10-15 16:04:04 +02:00
|
|
|
BHead *bhead = find_bhead_from_code_name(fd, idcode, name);
|
2015-03-11 00:05:14 +11:00
|
|
|
ID *id;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-12-04 13:09:13 +01:00
|
|
|
const bool use_placeholders = (flag & BLO_LIBLINK_USE_PLACEHOLDERS) != 0;
|
|
|
|
|
const bool force_indirect = (flag & BLO_LIBLINK_FORCE_INDIRECT) != 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-19 19:37:00 +01:00
|
|
|
BLI_assert(BKE_idtype_idcode_is_linkable(idcode) && BKE_idtype_idcode_is_valid(idcode));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-11 00:05:14 +11:00
|
|
|
if (bhead) {
|
Readfile: Refactor several parts of the process
This commit affects:
* Reading undo steps from memfile (aka 'Global Undo');
* Handling of UI IDs (WindowManager, Workspaces and Screens) when
opening a .blend file.
While no major changes are expected from a user PoV, there may be some
unexpected changes in rare edge-cases. None has been identified so far.
Undo step loading should be marginally faster (`setup_app_data` itself
is 2-3 times faster, as it does not do remapping anymore, which makes the
whole 'read undo step' process about 20% faster - but the most
time-consuming step on undo is the depsgraph processing, which remains
unchanged here).
This commit also solves some bugs (crashes) in some relatively uncommon
cases, like e.g. if the WM had an IDProperty pointing at an object and
UI is not loaded when opening a new .blend file with the 'Load UI' option
enabled (as in previous code on file opening WM ID would never be
remapped).
From a more technical side, this commit aims mainly at cleaning things
up, in preparation for the introduction of new 'no undo, no readfile'
type of handling (as part of the Brush Assets project):
- Prevent WM code from doing (too much) horrible ID 'management' on
its WM when opening a new file. It used to remove current WM from
the Main database, store it in a temporary own list, and then free
it itself...
- Trying to make the complex logic behind WM handling on file reading a
bit more easy to follow, at least way more documented in code.
- Keep the handling of 'IDs being re-used from old Main' in a single
place, as much as possible:
-- Readfile code itself in undo case (because it's more efficient,
and undo case is in a way simpler than actual .blend file
reading case). The whole `blo_lib_link_restore` block of code
is also removed.
-- (Mostly) setup_app_data code in actual file reading case.
- Sanitize the usage of the 'libmap' in readfile code in undo case
(waaaaay too many pointers were added there, which was hiding some
other issues in the related code, and potentially causing (in
rare cases) memory addresses collisions.
Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
|
|
|
id = library_id_is_yet_read(fd, mainl, bhead);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (id == nullptr) {
|
2015-03-11 00:05:14 +11:00
|
|
|
/* not read yet */
|
2021-03-09 00:53:13 +11:00
|
|
|
const int tag = ((force_indirect ? LIB_TAG_INDIRECT : LIB_TAG_EXTERN) | fd->id_tag_extra);
|
2019-09-16 14:52:06 +02:00
|
|
|
read_libblock(fd, mainl, bhead, tag | LIB_TAG_NEED_EXPAND, false, &id);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-11 00:05:14 +11:00
|
|
|
if (id) {
|
|
|
|
|
/* sort by name in list */
|
|
|
|
|
ListBase *lb = which_libbase(mainl, idcode);
|
2022-09-15 19:13:01 +02:00
|
|
|
id_sort_by_name(lb, id, nullptr);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-11 00:05:14 +11:00
|
|
|
else {
|
|
|
|
|
/* already linked */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_WARN(&LOG, "Append: ID '%s' is already linked", id->name);
|
2022-07-28 16:26:02 +02:00
|
|
|
oldnewmap_lib_insert(fd, bhead->old, id, bhead->code);
|
2016-06-22 18:05:55 +02:00
|
|
|
if (!force_indirect && (id->tag & LIB_TAG_INDIRECT)) {
|
Split id->flag in two, persistent flags and runtime tags.
This is purely internal sanitizing/cleanup, no change in behavior is expected at all.
This change was also needed because we were getting short on ID flags, and
future enhancement of 'user_one' ID behavior requires two new ones.
id->flag remains for persistent data (fakeuser only, so far!), this also allows us
100% backward & forward compatibility.
New id->tag is used for most flags. Though written in .blend files, its content
is cleared at read time.
Note that .blend file version was bumped, so that we can clear runtimeflags from
old .blends, important in case we add new persistent flags in future.
Also, behavior of tags (either status ones, or whether they need to be cleared before/after use)
has been added as comments to their declaration.
Reviewers: sergey, campbellbarton
Differential Revision: https://developer.blender.org/D1683
2015-12-27 11:53:50 +01:00
|
|
|
id->tag &= ~LIB_TAG_INDIRECT;
|
2019-09-16 14:52:06 +02:00
|
|
|
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
|
Split id->flag in two, persistent flags and runtime tags.
This is purely internal sanitizing/cleanup, no change in behavior is expected at all.
This change was also needed because we were getting short on ID flags, and
future enhancement of 'user_one' ID behavior requires two new ones.
id->flag remains for persistent data (fakeuser only, so far!), this also allows us
100% backward & forward compatibility.
New id->tag is used for most flags. Though written in .blend files, its content
is cleared at read time.
Note that .blend file version was bumped, so that we can clear runtimeflags from
old .blends, important in case we add new persistent flags in future.
Also, behavior of tags (either status ones, or whether they need to be cleared before/after use)
has been added as comments to their declaration.
Reviewers: sergey, campbellbarton
Differential Revision: https://developer.blender.org/D1683
2015-12-27 11:53:50 +01:00
|
|
|
id->tag |= LIB_TAG_EXTERN;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-03-11 00:05:14 +11:00
|
|
|
}
|
2011-05-26 20:45:19 +00:00
|
|
|
}
|
2016-06-22 18:05:55 +02:00
|
|
|
else if (use_placeholders) {
|
|
|
|
|
/* XXX flag part is weak! */
|
|
|
|
|
id = create_placeholder(
|
LibOverride: Restore local references to virtual linked liboverrides on resync.
When resyncing linked liboverride data, new IDs may be created that do
not exist in actual library file (since the lib file has not been resynced).
If such 'virtual linked liboverrides' data-blocks are used locally (e.g.
by adding such object to a local collection), on next file read they will be
detected as missing.
Now resync code will list such missing linked IDs that were
liboverrides, and try to re-use them when matching (by root name and
library) with newly generated virtual liboverrides.
The process may not be 100% perfect, especially a perfect one-to-one
remapping cannot be ensured if source data keep being changed over and
over (because of the order in which virtual linked liboverrides
generated by resync may change over time). However, in practice this
should fix the vast majority of issues, especially if sane naming
practices are used on IDs.
---------------
For the record, an attempt was made to write liboverride data together
with the placeholders for linked IDs in .blendfile. In theory, this
should ensure a perfect and fully valid re-usage of such IDs.
However, for this to work, not only the liboverride data of linked IDs need
to be written on disk, but also all ID references in this data has to be
considered as directly linked, to ensure that such liboverride data can
be re-read properly.
Otherwise, these placeholders would get a liboverride data with NULL ID
pointers, which is useless.
Such change feels way to intrusive for the very limited benefit, so for
now would consider current solution as the best option.
Pull Request: https://projects.blender.org/blender/blender/pulls/107144
2023-05-08 18:22:33 +02:00
|
|
|
mainl, idcode, name, force_indirect ? LIB_TAG_INDIRECT : LIB_TAG_EXTERN, false);
|
2016-06-22 18:05:55 +02:00
|
|
|
}
|
2015-03-11 00:05:14 +11:00
|
|
|
else {
|
2022-09-15 19:13:01 +02:00
|
|
|
id = nullptr;
|
2015-03-11 00:05:14 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
/* if we found the id but the id is nullptr, this is really bad */
|
|
|
|
|
BLI_assert(!((bhead != nullptr) && (id == nullptr)));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-11 00:05:14 +11:00
|
|
|
return id;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-15 16:04:04 +02:00
|
|
|
ID *BLO_library_link_named_part(Main *mainl,
|
|
|
|
|
BlendHandle **bh,
|
|
|
|
|
const short idcode,
|
2020-09-08 15:32:43 +10:00
|
|
|
const char *name,
|
2022-10-05 13:44:02 -05:00
|
|
|
const LibraryLink_Params *params)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)(*bh);
|
2023-02-22 16:37:15 +01:00
|
|
|
|
|
|
|
|
ID *ret_id = nullptr;
|
|
|
|
|
if (!mainl->is_read_invalid) {
|
|
|
|
|
ret_id = link_named_part(mainl, fd, idcode, name, params->flag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mainl->is_read_invalid) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return ret_id;
|
2011-05-26 20:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
2020-09-08 15:32:43 +10:00
|
|
|
/* common routine to append/link something from a library */
|
|
|
|
|
|
2021-11-30 17:52:58 +01:00
|
|
|
static Main *library_link_begin(Main *mainvar,
|
2023-09-01 17:34:28 +02:00
|
|
|
FileData *fd,
|
2021-11-30 17:52:58 +01:00
|
|
|
const char *filepath,
|
|
|
|
|
const int id_tag_extra)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2002-12-20 02:08:46 +00:00
|
|
|
Main *mainl;
|
2012-05-25 17:13:30 +00:00
|
|
|
|
2021-03-09 01:01:31 +11:00
|
|
|
/* Only allow specific tags to be set as extra,
|
|
|
|
|
* otherwise this could conflict with library loading logic.
|
|
|
|
|
* Other flags can be added here, as long as they are safe. */
|
|
|
|
|
BLI_assert((id_tag_extra & ~LIB_TAG_TEMP_MAIN) == 0);
|
|
|
|
|
|
2023-09-01 17:34:28 +02:00
|
|
|
fd->id_tag_extra = id_tag_extra;
|
2021-03-09 00:53:13 +11:00
|
|
|
|
2023-09-01 17:34:28 +02:00
|
|
|
fd->mainlist = static_cast<ListBase *>(MEM_callocN(sizeof(ListBase), "FileData.mainlist"));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2003-04-26 18:01:01 +00:00
|
|
|
/* make mains */
|
2023-09-01 17:34:28 +02:00
|
|
|
blo_split_main(fd->mainlist, mainvar);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2003-04-26 18:01:01 +00:00
|
|
|
/* which one do we need? */
|
2023-09-01 17:34:28 +02:00
|
|
|
mainl = blo_find_main(fd, filepath, BKE_main_blendfile_path(mainvar));
|
2023-09-01 17:58:18 +02:00
|
|
|
if (mainl->curlib) {
|
2024-04-08 13:08:36 +02:00
|
|
|
mainl->curlib->runtime.filedata = fd;
|
2023-09-01 17:58:18 +02:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2010-05-05 14:59:22 +00:00
|
|
|
/* needed for do_version */
|
2023-09-01 17:34:28 +02:00
|
|
|
mainl->versionfile = short(fd->fileversion);
|
|
|
|
|
read_file_version(fd, mainl);
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
2023-09-01 17:34:28 +02:00
|
|
|
read_file_bhead_idname_map_create(fd);
|
2015-03-11 00:33:44 +11:00
|
|
|
#endif
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2009-09-12 19:54:39 +00:00
|
|
|
return mainl;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
void BLO_library_link_params_init(LibraryLink_Params *params,
|
|
|
|
|
Main *bmain,
|
2021-03-09 00:53:13 +11:00
|
|
|
const int flag,
|
|
|
|
|
const int id_tag_extra)
|
2020-09-08 15:32:43 +10:00
|
|
|
{
|
|
|
|
|
memset(params, 0, sizeof(*params));
|
|
|
|
|
params->bmain = bmain;
|
|
|
|
|
params->flag = flag;
|
2021-03-09 00:53:13 +11:00
|
|
|
params->id_tag_extra = id_tag_extra;
|
2020-09-08 15:32:43 +10:00
|
|
|
}
|
|
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
void BLO_library_link_params_init_with_context(LibraryLink_Params *params,
|
|
|
|
|
Main *bmain,
|
2020-09-08 15:32:43 +10:00
|
|
|
const int flag,
|
2021-03-09 00:53:13 +11:00
|
|
|
const int id_tag_extra,
|
2020-09-08 15:32:43 +10:00
|
|
|
/* Context arguments. */
|
2022-10-05 13:44:02 -05:00
|
|
|
Scene *scene,
|
|
|
|
|
ViewLayer *view_layer,
|
|
|
|
|
const View3D *v3d)
|
2020-09-08 15:32:43 +10:00
|
|
|
{
|
2021-03-09 00:53:13 +11:00
|
|
|
BLO_library_link_params_init(params, bmain, flag, id_tag_extra);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (scene != nullptr) {
|
2020-09-08 15:32:43 +10:00
|
|
|
params->context.scene = scene;
|
|
|
|
|
params->context.view_layer = view_layer;
|
|
|
|
|
params->context.v3d = v3d;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Main *BLO_library_link_begin(BlendHandle **bh,
|
|
|
|
|
const char *filepath,
|
2022-10-05 13:44:02 -05:00
|
|
|
const LibraryLink_Params *params)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2023-09-01 17:34:28 +02:00
|
|
|
FileData *fd = reinterpret_cast<FileData *>(*bh);
|
|
|
|
|
return library_link_begin(params->bmain, fd, filepath, params->id_tag_extra);
|
2009-09-12 19:54:39 +00:00
|
|
|
}
|
|
|
|
|
|
2016-12-23 12:54:51 +01:00
|
|
|
static void split_main_newid(Main *mainptr, Main *main_newid)
|
|
|
|
|
{
|
|
|
|
|
/* We only copy the necessary subset of data in this temp main. */
|
|
|
|
|
main_newid->versionfile = mainptr->versionfile;
|
|
|
|
|
main_newid->subversionfile = mainptr->subversionfile;
|
2021-12-13 16:22:19 +11:00
|
|
|
STRNCPY(main_newid->filepath, mainptr->filepath);
|
2016-12-23 12:54:51 +01:00
|
|
|
main_newid->curlib = mainptr->curlib;
|
|
|
|
|
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
|
|
|
|
ListBase *lbarray_newid[INDEX_ID_MAX];
|
2016-12-23 12:54:51 +01:00
|
|
|
int i = set_listbasepointers(mainptr, lbarray);
|
|
|
|
|
set_listbasepointers(main_newid, lbarray_newid);
|
|
|
|
|
while (i--) {
|
|
|
|
|
BLI_listbase_clear(lbarray_newid[i]);
|
|
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (ID *, id, lbarray[i]) {
|
2016-12-23 12:54:51 +01:00
|
|
|
if (id->tag & LIB_TAG_NEW) {
|
|
|
|
|
BLI_remlink(lbarray[i], id);
|
|
|
|
|
BLI_addtail(lbarray_newid[i], id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-30 17:52:58 +01:00
|
|
|
static void library_link_end(Main *mainl, FileData **fd, const int flag)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2011-01-06 01:35:07 +00:00
|
|
|
Main *mainvar;
|
2010-10-07 21:25:05 +00:00
|
|
|
Library *curlib;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (mainl->id_map == nullptr) {
|
|
|
|
|
mainl->id_map = BKE_main_idmap_create(mainl, false, nullptr, MAIN_IDMAP_TYPE_NAME);
|
2021-06-30 15:19:35 +02:00
|
|
|
}
|
|
|
|
|
|
2010-01-26 14:00:13 +00:00
|
|
|
/* make main consistent */
|
2024-05-10 17:22:25 +02:00
|
|
|
BLO_expand_main(*fd, mainl, expand_doit_library);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-28 09:41:31 +10:00
|
|
|
/* Do this when expand found other libraries. */
|
2012-05-25 17:13:30 +00:00
|
|
|
read_libraries(*fd, (*fd)->mainlist);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
curlib = mainl->curlib;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-09-12 19:54:39 +00:00
|
|
|
/* make the lib path relative if required */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flag & FILE_RELPATH) {
|
2006-01-04 19:05:24 +00:00
|
|
|
/* use the full path, this could have been read by other library even */
|
2024-04-08 13:08:36 +02:00
|
|
|
STRNCPY(curlib->filepath, curlib->runtime.filepath_abs);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-01-04 19:05:24 +00:00
|
|
|
/* uses current .blend file as reference */
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_path_rel(curlib->filepath, BKE_main_blendfile_path_from_global());
|
2005-10-25 20:19:31 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-25 17:13:30 +00:00
|
|
|
blo_join_main((*fd)->mainlist);
|
2022-09-15 19:13:01 +02:00
|
|
|
mainvar = static_cast<Main *>((*fd)->mainlist->first);
|
|
|
|
|
mainl = nullptr; /* blo_join_main free's mainl, can't use anymore */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-22 16:37:15 +01:00
|
|
|
if (mainvar->is_read_invalid) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-19 16:36:15 +00:00
|
|
|
lib_link_all(*fd, mainvar);
|
2023-08-28 13:10:22 +02:00
|
|
|
after_liblink_merged_bmain_process(mainvar, (*fd)->reports);
|
2020-02-20 11:28:23 +01:00
|
|
|
|
|
|
|
|
/* Some versioning code does expect some proper userrefcounting, e.g. in conversion from
|
|
|
|
|
* groups to collections... We could optimize out that first call when we are reading a
|
2023-05-13 19:45:29 +02:00
|
|
|
* current version file, but again this is really not a bottle neck currently. So not worth
|
2020-02-20 11:28:23 +01:00
|
|
|
* it. */
|
|
|
|
|
BKE_main_id_refcount_recompute(mainvar, false);
|
|
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
BKE_collections_after_lib_link(mainvar);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-23 12:54:51 +01:00
|
|
|
/* Yep, second splitting... but this is a very cheap operation, so no big deal. */
|
|
|
|
|
blo_split_main((*fd)->mainlist, mainvar);
|
2018-05-15 13:23:01 +02:00
|
|
|
Main *main_newid = BKE_main_new();
|
2016-12-23 12:54:51 +01:00
|
|
|
for (mainvar = ((Main *)(*fd)->mainlist->first)->next; mainvar; mainvar = mainvar->next) {
|
|
|
|
|
BLI_assert(mainvar->versionfile != 0);
|
2019-04-22 01:10:29 +10:00
|
|
|
/* We need to split out IDs already existing,
|
|
|
|
|
* or they will go again through do_versions - bad, very bad! */
|
2018-05-15 13:23:01 +02:00
|
|
|
split_main_newid(mainvar, main_newid);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-04-08 13:08:36 +02:00
|
|
|
do_versions_after_linking((main_newid->curlib && main_newid->curlib->runtime.filedata) ?
|
|
|
|
|
main_newid->curlib->runtime.filedata :
|
|
|
|
|
*fd,
|
|
|
|
|
main_newid);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-15 13:23:01 +02:00
|
|
|
add_main_to_main(mainvar, main_newid);
|
2023-02-22 16:37:15 +01:00
|
|
|
|
|
|
|
|
if (mainvar->is_read_invalid) {
|
2023-03-01 15:14:11 +01:00
|
|
|
break;
|
2023-02-22 16:37:15 +01:00
|
|
|
}
|
2016-12-23 12:54:51 +01:00
|
|
|
}
|
readfile: Move ID refcounting to libquery.
Having that extra ID users handling at readfile level, besides generic
one ensured by libquery, has been something bothering me for a long time
(had to fix my share of bugs due to mismatches between those two areas).
Further more, work on undo speedup will require even more complex ID
refcount management if we want to keep it in readfile.c area.
So idea is instead to generalize what we did for linked data already
when undoing: recompute properly usercount numbers after liblink step,
for all IDs.
Note that extra time required here is neglectable in a whole .blend file
reading (few extra milliseconds when loading a full production scene
e.g.).
Notes:
* Some deprecated data (IPOs) are not refcounted at all anymore, this
should not be an issue in pratice since the are supposed to get deleted
after doversion anyway.
* Refcounting happens after `do_versions_after_linking`, i.e those
functions won't get valid ID usercounts currently. Again, this is not a
problem in current code, if needed we could recompute refcount before,
and then ensure `do_versions_after_linoiing()` actually handles properly
usercount, which it does not currently.
Differential Revision: https://developer.blender.org/D6881
2020-02-19 12:50:04 +01:00
|
|
|
|
2016-12-23 12:54:51 +01:00
|
|
|
blo_join_main((*fd)->mainlist);
|
2022-09-15 19:13:01 +02:00
|
|
|
mainvar = static_cast<Main *>((*fd)->mainlist->first);
|
2016-12-23 12:54:51 +01:00
|
|
|
MEM_freeN((*fd)->mainlist);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-01 15:14:11 +01:00
|
|
|
if (mainvar->is_read_invalid) {
|
|
|
|
|
BKE_main_free(main_newid);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-20 11:28:23 +01:00
|
|
|
/* This does not take into account old, deprecated data, so we also have to do it after
|
readfile: Move ID refcounting to libquery.
Having that extra ID users handling at readfile level, besides generic
one ensured by libquery, has been something bothering me for a long time
(had to fix my share of bugs due to mismatches between those two areas).
Further more, work on undo speedup will require even more complex ID
refcount management if we want to keep it in readfile.c area.
So idea is instead to generalize what we did for linked data already
when undoing: recompute properly usercount numbers after liblink step,
for all IDs.
Note that extra time required here is neglectable in a whole .blend file
reading (few extra milliseconds when loading a full production scene
e.g.).
Notes:
* Some deprecated data (IPOs) are not refcounted at all anymore, this
should not be an issue in pratice since the are supposed to get deleted
after doversion anyway.
* Refcounting happens after `do_versions_after_linking`, i.e those
functions won't get valid ID usercounts currently. Again, this is not a
problem in current code, if needed we could recompute refcount before,
and then ensure `do_versions_after_linoiing()` actually handles properly
usercount, which it does not currently.
Differential Revision: https://developer.blender.org/D6881
2020-02-19 12:50:04 +01:00
|
|
|
* `do_versions_after_linking()`. */
|
|
|
|
|
BKE_main_id_refcount_recompute(mainvar, false);
|
|
|
|
|
|
2019-04-20 20:25:22 +02:00
|
|
|
/* After all data has been read and versioned, uses LIB_TAG_NEW. */
|
2023-05-15 15:14:22 +02:00
|
|
|
blender::bke::ntreeUpdateAllNew(mainvar);
|
2019-04-20 20:25:22 +02:00
|
|
|
|
2019-08-12 11:54:37 +02:00
|
|
|
placeholders_ensure_valid(mainvar);
|
|
|
|
|
|
2021-10-06 16:41:47 +02:00
|
|
|
/* Apply overrides of newly linked data if needed. Already existing IDs need to split out, to
|
|
|
|
|
* avoid re-applying their own overrides. */
|
|
|
|
|
BLI_assert(BKE_main_is_empty(main_newid));
|
|
|
|
|
split_main_newid(mainvar, main_newid);
|
|
|
|
|
BKE_lib_override_library_main_validate(main_newid, (*fd)->reports->reports);
|
|
|
|
|
BKE_lib_override_library_main_update(main_newid);
|
|
|
|
|
add_main_to_main(mainvar, main_newid);
|
|
|
|
|
BKE_main_free(main_newid);
|
|
|
|
|
|
2016-12-19 16:28:41 +01:00
|
|
|
BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-12-26 20:24:16 +09:00
|
|
|
/* FIXME Temporary 'fix' to a problem in how temp ID are copied in
|
2023-02-12 14:37:16 +11:00
|
|
|
* `BKE_lib_override_library_main_update`, see #103062.
|
|
|
|
|
* Proper fix involves first addressing #90610. */
|
2022-12-26 20:24:16 +09:00
|
|
|
BKE_main_collections_parent_relations_rebuild(mainvar);
|
|
|
|
|
|
2019-08-14 23:29:46 +10:00
|
|
|
/* Make all relative paths, relative to the open blend file. */
|
|
|
|
|
fix_relpaths_library(BKE_main_blendfile_path(mainvar), mainvar);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2003-04-26 18:01:01 +00:00
|
|
|
/* patch to prevent switch_endian happens twice */
|
2024-05-08 18:39:19 +02:00
|
|
|
/* FIXME This is extremely bad design, #library_link_end should probably _always_ free the file
|
|
|
|
|
* data? */
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(*fd);
|
2022-09-15 19:13:01 +02:00
|
|
|
*fd = nullptr;
|
2012-12-11 22:00:22 +00:00
|
|
|
}
|
2023-01-27 15:32:44 +01:00
|
|
|
|
|
|
|
|
/* Sanity checks. */
|
|
|
|
|
blo_read_file_checks(mainvar);
|
2009-09-12 19:54:39 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-05 13:44:02 -05:00
|
|
|
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const LibraryLink_Params *params)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2023-02-22 16:37:15 +01:00
|
|
|
FileData *fd = reinterpret_cast<FileData *>(*bh);
|
|
|
|
|
|
|
|
|
|
if (!mainl->is_read_invalid) {
|
|
|
|
|
library_link_end(mainl, &fd, params->flag);
|
|
|
|
|
}
|
2023-09-01 17:58:18 +02:00
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (Library *, lib, ¶ms->bmain->libraries) {
|
|
|
|
|
/* Now we can clear this runtime library filedata, it is not needed anymore. */
|
2024-04-08 13:08:36 +02:00
|
|
|
if (lib->runtime.filedata == reinterpret_cast<FileData *>(*bh)) {
|
2023-09-03 16:13:08 +10:00
|
|
|
/* The filedata is owned and managed by caller code, only clear matching library pointer. */
|
2024-04-08 13:08:36 +02:00
|
|
|
lib->runtime.filedata = nullptr;
|
2023-09-01 17:58:18 +02:00
|
|
|
}
|
2024-04-08 13:08:36 +02:00
|
|
|
else if (lib->runtime.filedata) {
|
2023-09-01 17:58:18 +02:00
|
|
|
/* In case other libraries had to be read as dependencies of the main linked one, they need
|
|
|
|
|
* to be cleared here.
|
|
|
|
|
*
|
|
|
|
|
* TODO: In the future, could be worth keeping them in case data are linked from several
|
|
|
|
|
* libraries at once? To avoid closing and re-opening the same file several times. Would need
|
|
|
|
|
* a global cleanup callback then once all linking is done, though. */
|
2024-04-08 13:08:36 +02:00
|
|
|
blo_filedata_free(lib->runtime.filedata);
|
|
|
|
|
lib->runtime.filedata = nullptr;
|
2023-09-01 17:58:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*bh = reinterpret_cast<BlendHandle *>(fd);
|
2007-03-16 05:39:30 +00:00
|
|
|
}
|
|
|
|
|
|
2011-05-18 19:42:30 +00:00
|
|
|
void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
|
2007-03-16 05:39:30 +00:00
|
|
|
{
|
2011-05-18 19:42:30 +00:00
|
|
|
return read_struct(fd, bh, blockname);
|
2007-03-16 05:39:30 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Library Reading
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
static int has_linked_ids_to_read(Main *mainvar)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
2019-02-27 19:25:21 +01:00
|
|
|
int a = set_listbasepointers(mainvar, lbarray);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 07:52:14 +00:00
|
|
|
while (a--) {
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (ID *, id, lbarray[a]) {
|
2019-09-16 14:52:06 +02:00
|
|
|
if ((id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) && !(id->flag & LIB_INDIRECT_WEAK_LINK)) {
|
2016-06-06 19:03:09 +10:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-06 19:03:09 +10:00
|
|
|
return false;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
static void read_library_linked_id(
|
2021-02-27 13:10:27 +01:00
|
|
|
FileData *basefd, FileData *fd, Main *mainvar, ID *id, ID **r_id)
|
2019-02-27 19:25:21 +01:00
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
BHead *bhead = nullptr;
|
2020-03-19 19:37:00 +01:00
|
|
|
const bool is_valid = BKE_idtype_idcode_is_linkable(GS(id->name)) ||
|
|
|
|
|
((id->tag & LIB_TAG_EXTERN) == 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (fd) {
|
|
|
|
|
bhead = find_bhead_from_idname(fd, id->name);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (!is_valid) {
|
2021-02-27 13:10:27 +01:00
|
|
|
BLO_reportf_wrap(basefd->reports,
|
2019-02-27 19:25:21 +01:00
|
|
|
RPT_ERROR,
|
2024-01-11 19:49:03 +01:00
|
|
|
RPT_("LIB: %s: '%s' is directly linked from '%s' (parent '%s'), but is a "
|
2019-02-27 19:25:21 +01:00
|
|
|
"non-linkable data type"),
|
2020-03-19 19:37:00 +01:00
|
|
|
BKE_idtype_idcode_to_name(GS(id->name)),
|
2019-02-27 19:25:21 +01:00
|
|
|
id->name + 2,
|
2024-04-08 13:08:36 +02:00
|
|
|
mainvar->curlib->runtime.filepath_abs,
|
2019-02-27 19:25:21 +01:00
|
|
|
library_parent_filepath(mainvar->curlib));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
id->tag &= ~LIB_TAG_ID_LINK_PLACEHOLDER;
|
2019-09-16 14:52:06 +02:00
|
|
|
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (bhead) {
|
|
|
|
|
id->tag |= LIB_TAG_NEED_EXPAND;
|
|
|
|
|
// printf("read lib block %s\n", id->name);
|
2019-09-16 14:52:06 +02:00
|
|
|
read_libblock(fd, mainvar, bhead, id->tag, false, r_id);
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2024-02-21 17:21:25 +01:00
|
|
|
CLOG_INFO(&LOG,
|
|
|
|
|
3,
|
|
|
|
|
"LIB: %s: '%s' missing from '%s', parent '%s'",
|
|
|
|
|
BKE_idtype_idcode_to_name(GS(id->name)),
|
|
|
|
|
id->name + 2,
|
2024-04-08 13:08:36 +02:00
|
|
|
mainvar->curlib->runtime.filepath_abs,
|
2024-02-21 17:21:25 +01:00
|
|
|
library_parent_filepath(mainvar->curlib));
|
2021-06-23 09:51:11 +02:00
|
|
|
basefd->reports->count.missing_linked_id++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Generate a placeholder for this ID (simplified version of read_libblock actually...). */
|
|
|
|
|
if (r_id) {
|
LibOverride: Restore local references to virtual linked liboverrides on resync.
When resyncing linked liboverride data, new IDs may be created that do
not exist in actual library file (since the lib file has not been resynced).
If such 'virtual linked liboverrides' data-blocks are used locally (e.g.
by adding such object to a local collection), on next file read they will be
detected as missing.
Now resync code will list such missing linked IDs that were
liboverrides, and try to re-use them when matching (by root name and
library) with newly generated virtual liboverrides.
The process may not be 100% perfect, especially a perfect one-to-one
remapping cannot be ensured if source data keep being changed over and
over (because of the order in which virtual linked liboverrides
generated by resync may change over time). However, in practice this
should fix the vast majority of issues, especially if sane naming
practices are used on IDs.
---------------
For the record, an attempt was made to write liboverride data together
with the placeholders for linked IDs in .blendfile. In theory, this
should ensure a perfect and fully valid re-usage of such IDs.
However, for this to work, not only the liboverride data of linked IDs need
to be written on disk, but also all ID references in this data has to be
considered as directly linked, to ensure that such liboverride data can
be re-read properly.
Otherwise, these placeholders would get a liboverride data with NULL ID
pointers, which is useless.
Such change feels way to intrusive for the very limited benefit, so for
now would consider current solution as the best option.
Pull Request: https://projects.blender.org/blender/blender/pulls/107144
2023-05-08 18:22:33 +02:00
|
|
|
*r_id = is_valid ? create_placeholder(mainvar,
|
|
|
|
|
GS(id->name),
|
|
|
|
|
id->name + 2,
|
|
|
|
|
id->tag,
|
|
|
|
|
id->override_library != nullptr) :
|
2022-09-15 19:13:01 +02:00
|
|
|
nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
static void read_library_linked_ids(FileData *basefd,
|
|
|
|
|
FileData *fd,
|
|
|
|
|
ListBase *mainlist,
|
|
|
|
|
Main *mainvar)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2018-02-16 10:31:03 +01:00
|
|
|
GHash *loaded_ids = BLI_ghash_str_new(__func__);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
2019-02-27 19:25:21 +01:00
|
|
|
int a = set_listbasepointers(mainvar, lbarray);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
while (a--) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(lbarray[a]->first);
|
|
|
|
|
ListBase pending_free_ids = {nullptr};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
while (id) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id_next = static_cast<ID *>(id->next);
|
2019-09-16 14:52:06 +02:00
|
|
|
if ((id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) && !(id->flag & LIB_INDIRECT_WEAK_LINK)) {
|
2019-02-27 19:25:21 +01:00
|
|
|
BLI_remlink(lbarray[a], id);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (mainvar->id_map != nullptr) {
|
2021-06-30 15:19:35 +02:00
|
|
|
BKE_main_idmap_remove_id(mainvar->id_map, id);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* When playing with lib renaming and such, you may end with cases where
|
|
|
|
|
* you have more than one linked ID of the same data-block from same
|
|
|
|
|
* library. This is absolutely horrible, hence we use a ghash to ensure
|
|
|
|
|
* we go back to a single linked data when loading the file. */
|
2022-09-15 19:13:01 +02:00
|
|
|
ID **realid = nullptr;
|
2019-02-27 19:25:21 +01:00
|
|
|
if (!BLI_ghash_ensure_p(loaded_ids, id->name, (void ***)&realid)) {
|
2021-02-27 13:10:27 +01:00
|
|
|
read_library_linked_id(basefd, fd, mainvar, id, realid);
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
/* `realid` shall never be nullptr - unless some source file/lib is broken
|
2022-09-16 18:13:19 +10:00
|
|
|
* (known case: some directly linked shape-key from a missing lib...). */
|
2022-09-15 19:13:01 +02:00
|
|
|
// BLI_assert(*realid != nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Now that we have a real ID, replace all pointers to placeholders in
|
2019-06-12 09:04:10 +10:00
|
|
|
* fd->libmap with pointers to the real data-blocks. We do this for all
|
2019-02-27 19:25:21 +01:00
|
|
|
* libraries since multiple might be referencing this ID. */
|
|
|
|
|
change_link_placeholder_to_real_ID_pointer(mainlist, basefd, id, *realid);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* We cannot free old lib-ref placeholder ID here anymore, since we use
|
|
|
|
|
* its name as key in loaded_ids hash. */
|
|
|
|
|
BLI_addtail(&pending_free_ids, id);
|
|
|
|
|
}
|
|
|
|
|
id = id_next;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Clear GHash and free link placeholder IDs of the current type. */
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_ghash_clear(loaded_ids, nullptr, nullptr);
|
2019-02-27 19:25:21 +01:00
|
|
|
BLI_freelistN(&pending_free_ids);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
BLI_ghash_free(loaded_ids, nullptr, nullptr);
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-16 14:52:06 +02:00
|
|
|
static void read_library_clear_weak_links(FileData *basefd, ListBase *mainlist, Main *mainvar)
|
|
|
|
|
{
|
|
|
|
|
/* Any remaining weak links at this point have been lost, silently drop
|
2022-09-15 19:13:01 +02:00
|
|
|
* those by setting them to nullptr pointers. */
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
2019-09-16 14:52:06 +02:00
|
|
|
int a = set_listbasepointers(mainvar, lbarray);
|
|
|
|
|
|
|
|
|
|
while (a--) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id = static_cast<ID *>(lbarray[a]->first);
|
2019-09-16 14:52:06 +02:00
|
|
|
|
|
|
|
|
while (id) {
|
2022-09-15 19:13:01 +02:00
|
|
|
ID *id_next = static_cast<ID *>(id->next);
|
2019-09-16 14:52:06 +02:00
|
|
|
if ((id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) && (id->flag & LIB_INDIRECT_WEAK_LINK)) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG, 3, "Dropping weak link to '%s'", id->name);
|
2022-09-15 19:13:01 +02:00
|
|
|
change_link_placeholder_to_real_ID_pointer(mainlist, basefd, id, nullptr);
|
2019-09-16 14:52:06 +02:00
|
|
|
BLI_freelinkN(lbarray[a], id);
|
|
|
|
|
}
|
|
|
|
|
id = id_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
static FileData *read_library_file_data(FileData *basefd,
|
|
|
|
|
ListBase *mainlist,
|
|
|
|
|
Main *mainl,
|
|
|
|
|
Main *mainptr)
|
|
|
|
|
{
|
2024-04-08 13:08:36 +02:00
|
|
|
FileData *fd = mainptr->curlib->runtime.filedata;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (fd != nullptr) {
|
2019-02-27 19:25:21 +01:00
|
|
|
/* File already open. */
|
|
|
|
|
return fd;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (mainptr->curlib->packedfile) {
|
|
|
|
|
/* Read packed file. */
|
2024-04-16 12:27:47 +10:00
|
|
|
const PackedFile *pf = mainptr->curlib->packedfile;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-06 15:07:10 +01:00
|
|
|
BLO_reportf_wrap(basefd->reports,
|
2019-02-27 19:25:21 +01:00
|
|
|
RPT_INFO,
|
2024-04-15 20:02:38 +02:00
|
|
|
RPT_("Read packed library: '%s', parent '%s'"),
|
2020-06-23 09:54:14 +10:00
|
|
|
mainptr->curlib->filepath,
|
2019-02-27 19:25:21 +01:00
|
|
|
library_parent_filepath(mainptr->curlib));
|
2021-06-22 19:11:06 +02:00
|
|
|
fd = blo_filedata_from_memory(pf->data, pf->size, basefd->reports);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Needed for library_append and read_libraries. */
|
2024-04-08 13:08:36 +02:00
|
|
|
STRNCPY(fd->relabase, mainptr->curlib->runtime.filepath_abs);
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Read file on disk. */
|
2020-11-06 15:07:10 +01:00
|
|
|
BLO_reportf_wrap(basefd->reports,
|
2019-02-27 19:25:21 +01:00
|
|
|
RPT_INFO,
|
2024-04-15 20:02:38 +02:00
|
|
|
RPT_("Read library: '%s', '%s', parent '%s'"),
|
2024-04-08 13:08:36 +02:00
|
|
|
mainptr->curlib->runtime.filepath_abs,
|
2020-06-23 09:54:14 +10:00
|
|
|
mainptr->curlib->filepath,
|
2019-02-27 19:25:21 +01:00
|
|
|
library_parent_filepath(mainptr->curlib));
|
2024-04-08 13:08:36 +02:00
|
|
|
fd = blo_filedata_from_file(mainptr->curlib->runtime.filepath_abs, basefd->reports);
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (fd) {
|
|
|
|
|
/* Share the mainlist, so all libraries are added immediately in a
|
|
|
|
|
* single list. It used to be that all FileData's had their own list,
|
|
|
|
|
* but with indirectly linking this meant we didn't catch duplicate
|
|
|
|
|
* libraries properly. */
|
|
|
|
|
fd->mainlist = mainlist;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
fd->reports = basefd->reports;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->libmap) {
|
2019-02-27 19:25:21 +01:00
|
|
|
oldnewmap_free(fd->libmap);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
fd->libmap = oldnewmap_new();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-04-08 13:08:36 +02:00
|
|
|
mainptr->curlib->runtime.filedata = fd;
|
2019-02-27 19:25:21 +01:00
|
|
|
mainptr->versionfile = fd->fileversion;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* subversion */
|
|
|
|
|
read_file_version(fd, mainptr);
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
2019-02-27 19:25:21 +01:00
|
|
|
read_file_bhead_idname_map_create(fd);
|
2015-03-11 00:33:44 +11:00
|
|
|
#endif
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2024-04-08 13:08:36 +02:00
|
|
|
mainptr->curlib->runtime.filedata = nullptr;
|
2019-02-27 19:25:21 +01:00
|
|
|
mainptr->curlib->id.tag |= LIB_TAG_MISSING;
|
|
|
|
|
/* Set lib version to current main one... Makes assert later happy. */
|
2024-04-08 13:08:36 +02:00
|
|
|
mainptr->versionfile = mainptr->curlib->runtime.versionfile = mainl->versionfile;
|
|
|
|
|
mainptr->subversionfile = mainptr->curlib->runtime.subversionfile = mainl->subversionfile;
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (fd == nullptr) {
|
2024-04-08 13:08:36 +02:00
|
|
|
BLO_reportf_wrap(basefd->reports,
|
|
|
|
|
RPT_INFO,
|
|
|
|
|
RPT_("Cannot find lib '%s'"),
|
|
|
|
|
mainptr->curlib->runtime.filepath_abs);
|
2021-06-23 09:51:11 +02:00
|
|
|
basefd->reports->count.missing_libraries++;
|
2019-02-27 19:25:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
|
}
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
static void read_libraries(FileData *basefd, ListBase *mainlist)
|
|
|
|
|
{
|
2022-09-15 19:13:01 +02:00
|
|
|
Main *mainl = static_cast<Main *>(mainlist->first);
|
2019-02-27 19:25:21 +01:00
|
|
|
bool do_it = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* At this point the base blend file has been read, and each library blend
|
2019-06-12 09:04:10 +10:00
|
|
|
* encountered so far has a main with placeholders for linked data-blocks.
|
2019-02-27 19:25:21 +01:00
|
|
|
*
|
|
|
|
|
* Now we will read the library blend files and replace the placeholders
|
2019-06-12 09:04:10 +10:00
|
|
|
* with actual data-blocks. We loop over library mains multiple times in
|
|
|
|
|
* case a library needs to link additional data-blocks from another library
|
2019-02-27 19:25:21 +01:00
|
|
|
* that had been read previously. */
|
|
|
|
|
while (do_it) {
|
|
|
|
|
do_it = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Loop over mains of all library blend files encountered so far. Note
|
|
|
|
|
* this list gets longer as more indirectly library blends are found. */
|
|
|
|
|
for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Does this library have any more linked data-blocks we need to read? */
|
2019-02-27 19:25:21 +01:00
|
|
|
if (has_linked_ids_to_read(mainptr)) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG,
|
|
|
|
|
3,
|
|
|
|
|
"Reading linked data-blocks from %s (%s)",
|
|
|
|
|
mainptr->curlib->id.name,
|
|
|
|
|
mainptr->curlib->filepath);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Open file if it has not been done yet. */
|
|
|
|
|
FileData *fd = read_library_file_data(basefd, mainlist, mainl, mainptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (fd) {
|
|
|
|
|
do_it = true;
|
2021-06-30 15:19:35 +02:00
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
if (mainptr->id_map == nullptr) {
|
|
|
|
|
mainptr->id_map = BKE_main_idmap_create(mainptr, false, nullptr, MAIN_IDMAP_TYPE_NAME);
|
2021-06-30 15:19:35 +02:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-07-26 09:59:45 +02:00
|
|
|
/* Read linked data-blocks for each link placeholder, and replace
|
|
|
|
|
* the placeholder with the real data-block. */
|
2019-02-27 19:25:21 +01:00
|
|
|
read_library_linked_ids(basefd, fd, mainlist, mainptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-07-26 09:59:45 +02:00
|
|
|
/* Test if linked data-blocks need to read further linked data-blocks
|
2019-02-27 19:25:21 +01:00
|
|
|
* and create link placeholders for them. */
|
2024-05-10 17:22:25 +02:00
|
|
|
BLO_expand_main(fd, mainptr, expand_doit_library);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
|
2022-07-28 16:16:34 +02:00
|
|
|
/* Drop weak links for which no data-block was found.
|
|
|
|
|
* Since this can remap pointers in `libmap` of all libraries, it needs to be performed in its
|
|
|
|
|
* own loop, before any call to `lib_link_all` (and the freeing of the libraries' filedata). */
|
2019-09-16 14:52:06 +02:00
|
|
|
read_library_clear_weak_links(basefd, mainlist, mainptr);
|
2022-07-28 16:16:34 +02:00
|
|
|
}
|
2019-09-16 14:52:06 +02:00
|
|
|
|
2022-07-28 16:16:34 +02:00
|
|
|
Main *main_newid = BKE_main_new();
|
|
|
|
|
for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
|
2022-07-26 09:59:45 +02:00
|
|
|
/* Do versioning for newly added linked data-blocks. If no data-blocks
|
2019-02-27 19:25:21 +01:00
|
|
|
* were read from a library versionfile will still be zero and we can
|
|
|
|
|
* skip it. */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (mainptr->versionfile) {
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Split out already existing IDs to avoid them going through
|
|
|
|
|
* do_versions multiple times, which would have bad consequences. */
|
2018-05-15 13:23:01 +02:00
|
|
|
split_main_newid(mainptr, main_newid);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-09-03 16:13:08 +10:00
|
|
|
/* `filedata` can be NULL when loading linked data from nonexistent or invalid library
|
2023-09-01 17:58:18 +02:00
|
|
|
* reference. Or during linking/appending, when processing data from a library not involved
|
|
|
|
|
* in the current linking/appending operation.
|
|
|
|
|
*
|
|
|
|
|
* Skip versioning in these cases, since the only IDs here will be placeholders (missing
|
|
|
|
|
* lib), or already existing IDs (linking/appending). */
|
2024-04-08 13:08:36 +02:00
|
|
|
if (mainptr->curlib->runtime.filedata) {
|
|
|
|
|
do_versions(mainptr->curlib->runtime.filedata, mainptr->curlib, main_newid);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-15 13:23:01 +02:00
|
|
|
add_main_to_main(mainptr, main_newid);
|
2005-07-14 22:04:57 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Lib linking. */
|
2024-04-08 13:08:36 +02:00
|
|
|
if (mainptr->curlib->runtime.filedata) {
|
|
|
|
|
lib_link_all(mainptr->curlib->runtime.filedata, mainptr);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute()
|
2020-08-21 14:39:18 +02:00
|
|
|
* here, as this function is only called for library 'subset' data handling, as part of
|
2023-09-03 16:13:08 +10:00
|
|
|
* either full blend-file reading (#blo_read_file_internal()), or library-data linking
|
2023-09-01 17:58:18 +02:00
|
|
|
* (#library_link_end()).
|
|
|
|
|
*
|
2024-04-08 13:08:36 +02:00
|
|
|
* For this to work reliably, `mainptr->curlib->runtime.filedata` also needs to be freed after
|
|
|
|
|
* said versioning code has run. */
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-05-15 13:23:01 +02:00
|
|
|
BKE_main_free(main_newid);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-02-22 18:15:56 +11:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
static void *blo_verify_data_address(void *new_address,
|
|
|
|
|
const void * /*old_address*/,
|
|
|
|
|
const size_t expected_size)
|
|
|
|
|
{
|
|
|
|
|
if (new_address != nullptr) {
|
|
|
|
|
/* Not testing equality, since size might have been aligned up,
|
|
|
|
|
* or might be passed the size of a base struct with inheritance. */
|
|
|
|
|
BLI_assert_msg(MEM_allocN_len(new_address) >= expected_size,
|
|
|
|
|
"Corrupt .blend file, unexpected data size.");
|
2024-04-25 12:09:31 +10:00
|
|
|
UNUSED_VARS_NDEBUG(expected_size);
|
2024-04-24 17:01:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new_address;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
|
|
|
|
|
{
|
|
|
|
|
return newdataadr(reader->fd, old_address);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader,
|
|
|
|
|
const void *old_address,
|
|
|
|
|
const size_t expected_size)
|
2020-10-30 15:27:57 +01:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
void *new_address = newdataadr_no_us(reader->fd, old_address);
|
|
|
|
|
return blo_verify_data_address(new_address, old_address, expected_size);
|
2020-10-30 15:27:57 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-28 16:57:28 +02:00
|
|
|
void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address)
|
|
|
|
|
{
|
|
|
|
|
return newpackedadr(reader->fd, old_address);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void *BLO_read_struct_array_with_size(BlendDataReader *reader,
|
|
|
|
|
const void *old_address,
|
|
|
|
|
const size_t expected_size)
|
|
|
|
|
{
|
|
|
|
|
void *new_address = newdataadr(reader->fd, old_address);
|
|
|
|
|
return blo_verify_data_address(new_address, old_address, expected_size);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-24 12:04:22 +02:00
|
|
|
ID *BLO_read_get_new_id_address(BlendLibReader *reader,
|
|
|
|
|
ID *self_id,
|
|
|
|
|
const bool is_linked_only,
|
|
|
|
|
ID *id)
|
2020-06-05 11:44:36 +02:00
|
|
|
{
|
2023-04-24 12:04:22 +02:00
|
|
|
return static_cast<ID *>(newlibadr(reader->fd, self_id, is_linked_only, id));
|
2020-06-05 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-22 13:47:13 +01:00
|
|
|
ID *BLO_read_get_new_id_address_from_session_uid(BlendLibReader *reader, uint session_uid)
|
2023-06-21 15:10:13 +02:00
|
|
|
{
|
2024-01-22 13:47:13 +01:00
|
|
|
return BKE_main_idmap_lookup_uid(reader->fd->new_idmap_uid, session_uid);
|
2023-06-21 15:10:13 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-08 16:55:46 +02:00
|
|
|
int BLO_read_fileversion_get(BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
return reader->fd->fileversion;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void BLO_read_struct_list_with_size(BlendDataReader *reader,
|
|
|
|
|
const size_t expected_elem_size,
|
|
|
|
|
ListBase *list)
|
2020-06-05 11:44:36 +02:00
|
|
|
{
|
|
|
|
|
if (BLI_listbase_is_empty(list)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
list->first = BLO_read_struct_array_with_size(reader, list->first, expected_elem_size);
|
2022-09-15 19:13:01 +02:00
|
|
|
Link *ln = static_cast<Link *>(list->first);
|
|
|
|
|
Link *prev = nullptr;
|
2020-06-05 11:44:36 +02:00
|
|
|
while (ln) {
|
2024-04-24 17:01:22 +02:00
|
|
|
ln->next = static_cast<Link *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, ln->next, expected_elem_size));
|
2020-06-05 11:44:36 +02:00
|
|
|
ln->prev = prev;
|
|
|
|
|
prev = ln;
|
|
|
|
|
ln = ln->next;
|
|
|
|
|
}
|
|
|
|
|
list->last = prev;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void BLO_read_char_array(BlendDataReader *reader, int array_size, char **ptr_p)
|
2020-06-06 12:53:36 +02:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
*ptr_p = reinterpret_cast<char *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(char) * array_size));
|
2020-06-06 12:53:36 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void BLO_read_uint8_array(BlendDataReader *reader, int array_size, uint8_t **ptr_p)
|
2020-06-05 11:44:36 +02:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
*ptr_p = reinterpret_cast<uint8_t *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint8_t) * array_size));
|
2020-06-05 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void BLO_read_int8_array(BlendDataReader *reader, int array_size, int8_t **ptr_p)
|
2023-01-13 12:31:27 -06:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
*ptr_p = reinterpret_cast<int8_t *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int8_t) * array_size));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
*ptr_p = reinterpret_cast<int32_t *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int32_t) * array_size));
|
|
|
|
|
|
|
|
|
|
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
BLI_endian_switch_int32_array(*ptr_p, array_size);
|
|
|
|
|
}
|
2023-01-13 12:31:27 -06:00
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p)
|
|
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
*ptr_p = reinterpret_cast<uint32_t *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint32_t) * array_size));
|
|
|
|
|
|
|
|
|
|
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
|
2020-06-05 11:44:36 +02:00
|
|
|
BLI_endian_switch_uint32_array(*ptr_p, array_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
|
|
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
*ptr_p = reinterpret_cast<float *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(float) * array_size));
|
|
|
|
|
|
|
|
|
|
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
|
2020-06-05 11:44:36 +02:00
|
|
|
BLI_endian_switch_float_array(*ptr_p, array_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_float_array(reader, array_size * 3, ptr_p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr_p)
|
|
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
*ptr_p = reinterpret_cast<double *>(
|
|
|
|
|
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(double) * array_size));
|
|
|
|
|
|
|
|
|
|
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
|
2020-06-05 11:44:36 +02:00
|
|
|
BLI_endian_switch_double_array(*ptr_p, array_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_data_address(reader, ptr_p);
|
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const char *str = *ptr_p;
|
|
|
|
|
if (str) {
|
|
|
|
|
/* Verify that we have a null terminator. */
|
|
|
|
|
for (size_t len = MEM_allocN_len(str); len > 0; len--) {
|
|
|
|
|
if (str[len - 1] == '\0') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert_msg(0, "Corrupt .blend file, expected string to be null terminated.");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_string(BlendDataReader *reader, char *const *ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_string(reader, const_cast<char **>(ptr_p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_string(BlendDataReader *reader, const char **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_string(reader, const_cast<char **>(ptr_p));
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
static void convert_pointer_array_64_to_32(BlendDataReader *reader,
|
|
|
|
|
uint array_size,
|
|
|
|
|
const uint64_t *src,
|
|
|
|
|
uint32_t *dst)
|
|
|
|
|
{
|
|
|
|
|
/* Match pointer conversion rules from bh4_from_bh8 and cast_pointer. */
|
|
|
|
|
if (BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
for (int i = 0; i < array_size; i++) {
|
|
|
|
|
uint64_t ptr = src[i];
|
|
|
|
|
BLI_endian_switch_uint64(&ptr);
|
2022-09-30 14:16:14 +10:00
|
|
|
dst[i] = uint32_t(ptr >> 3);
|
2020-06-05 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (int i = 0; i < array_size; i++) {
|
2022-09-30 14:16:14 +10:00
|
|
|
dst[i] = uint32_t(src[i] >> 3);
|
2020-06-05 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
static void convert_pointer_array_32_to_64(BlendDataReader * /*reader*/,
|
2020-06-05 11:44:36 +02:00
|
|
|
uint array_size,
|
|
|
|
|
const uint32_t *src,
|
|
|
|
|
uint64_t *dst)
|
|
|
|
|
{
|
2020-09-29 12:29:01 +02:00
|
|
|
/* Match pointer conversion rules from bh8_from_bh4 and cast_pointer_32_to_64. */
|
2020-06-05 11:44:36 +02:00
|
|
|
for (int i = 0; i < array_size; i++) {
|
|
|
|
|
dst[i] = src[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
FileData *fd = reader->fd;
|
|
|
|
|
|
|
|
|
|
void *orig_array = newdataadr(fd, *ptr_p);
|
2022-09-15 19:13:01 +02:00
|
|
|
if (orig_array == nullptr) {
|
|
|
|
|
*ptr_p = nullptr;
|
2020-06-05 11:44:36 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int file_pointer_size = fd->filesdna->pointer_size;
|
|
|
|
|
int current_pointer_size = fd->memsdna->pointer_size;
|
|
|
|
|
|
2020-06-27 14:34:16 +10:00
|
|
|
/* Over-allocation is fine, but might be better to pass the length as parameter. */
|
2020-06-05 11:44:36 +02:00
|
|
|
int array_size = MEM_allocN_len(orig_array) / file_pointer_size;
|
|
|
|
|
|
2022-09-15 19:13:01 +02:00
|
|
|
void *final_array = nullptr;
|
2020-06-05 11:44:36 +02:00
|
|
|
|
|
|
|
|
if (file_pointer_size == current_pointer_size) {
|
|
|
|
|
/* No pointer conversion necessary. */
|
|
|
|
|
final_array = orig_array;
|
|
|
|
|
}
|
|
|
|
|
else if (file_pointer_size == 8 && current_pointer_size == 4) {
|
|
|
|
|
/* Convert pointers from 64 to 32 bit. */
|
|
|
|
|
final_array = MEM_malloc_arrayN(array_size, 4, "new pointer array");
|
|
|
|
|
convert_pointer_array_64_to_32(
|
|
|
|
|
reader, array_size, (uint64_t *)orig_array, (uint32_t *)final_array);
|
|
|
|
|
MEM_freeN(orig_array);
|
|
|
|
|
}
|
|
|
|
|
else if (file_pointer_size == 4 && current_pointer_size == 8) {
|
|
|
|
|
/* Convert pointers from 32 to 64 bit. */
|
|
|
|
|
final_array = MEM_malloc_arrayN(array_size, 8, "new pointer array");
|
|
|
|
|
convert_pointer_array_32_to_64(
|
|
|
|
|
reader, array_size, (uint32_t *)orig_array, (uint64_t *)final_array);
|
|
|
|
|
MEM_freeN(orig_array);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ptr_p = final_array;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-29 17:14:58 +01:00
|
|
|
void blo_read_shared_impl(
|
|
|
|
|
BlendDataReader *reader,
|
|
|
|
|
void *data,
|
|
|
|
|
const blender::ImplicitSharingInfo **r_sharing_info,
|
|
|
|
|
const blender::FunctionRef<const blender::ImplicitSharingInfo *()> read_fn)
|
|
|
|
|
{
|
|
|
|
|
if (BLO_read_data_is_undo(reader)) {
|
|
|
|
|
if (reader->fd->flags & FD_FLAGS_IS_MEMFILE) {
|
|
|
|
|
UndoReader *undo_reader = reinterpret_cast<UndoReader *>(reader->fd->file);
|
|
|
|
|
MemFile &memfile = *undo_reader->memfile;
|
|
|
|
|
if (memfile.shared_storage) {
|
|
|
|
|
/* Check if the data was saved with sharing-info. */
|
|
|
|
|
if (const blender::ImplicitSharingInfo *sharing_info =
|
|
|
|
|
memfile.shared_storage->map.lookup_default(data, nullptr))
|
|
|
|
|
{
|
|
|
|
|
/* Add a new owner of the data that is passed to the caller. */
|
|
|
|
|
sharing_info->add_user();
|
|
|
|
|
*r_sharing_info = sharing_info;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*r_sharing_info = read_fn();
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 16:29:55 +02:00
|
|
|
bool BLO_read_data_is_undo(BlendDataReader *reader)
|
|
|
|
|
{
|
2021-08-19 23:57:00 +02:00
|
|
|
return (reader->fd->flags & FD_FLAGS_IS_MEMFILE);
|
2020-08-28 16:29:55 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-06 13:04:44 +01:00
|
|
|
void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr)
|
|
|
|
|
{
|
|
|
|
|
oldnewmap_insert(reader->fd->globmap, oldaddr, newaddr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 14:57:36 +01:00
|
|
|
void BLO_read_glob_list(BlendDataReader *reader, ListBase *list)
|
|
|
|
|
{
|
|
|
|
|
link_glob_list(reader->fd, list);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
BlendFileReadReport *BLO_read_data_reports(BlendDataReader *reader)
|
2020-11-06 15:13:31 +01:00
|
|
|
{
|
|
|
|
|
return reader->fd->reports;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 16:29:55 +02:00
|
|
|
bool BLO_read_lib_is_undo(BlendLibReader *reader)
|
|
|
|
|
{
|
2021-08-19 23:57:00 +02:00
|
|
|
return (reader->fd->flags & FD_FLAGS_IS_MEMFILE);
|
2020-08-28 16:29:55 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-30 16:32:19 +01:00
|
|
|
Main *BLO_read_lib_get_main(BlendLibReader *reader)
|
|
|
|
|
{
|
|
|
|
|
return reader->main;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
BlendFileReadReport *BLO_read_lib_reports(BlendLibReader *reader)
|
2020-11-06 15:13:31 +01:00
|
|
|
{
|
|
|
|
|
return reader->fd->reports;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|