2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
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
|
|
|
*/
|
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <ctype.h> /* for isdigit. */
|
|
|
|
|
#include <fcntl.h> /* for open flags (O_BINARY, O_RDONLY). */
|
2008-09-22 15:59:50 +00:00
|
|
|
#include <limits.h>
|
2019-09-18 13:19:29 +10:00
|
|
|
#include <stdarg.h> /* for va_start/end. */
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <stddef.h> /* for offsetof. */
|
|
|
|
|
#include <stdlib.h> /* for atoi. */
|
2019-09-18 13:19:29 +10:00
|
|
|
#include <time.h> /* for gmtime. */
|
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"
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
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"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
#include "PIL_time.h"
|
|
|
|
|
|
2015-08-16 17:32:01 +10:00
|
|
|
#include "BLT_translation.h"
|
2012-10-19 16:43:10 +00:00
|
|
|
|
2020-04-03 13:07:36 +02:00
|
|
|
#include "BKE_anim_data.h"
|
2020-09-10 11:17:35 +02:00
|
|
|
#include "BKE_animsys.h"
|
2020-12-11 18:15:25 +01:00
|
|
|
#include "BKE_asset.h"
|
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
|
|
|
#include "BKE_collection.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_global.h" /* for G */
|
2018-11-07 18:00:24 +01:00
|
|
|
#include "BKE_idprop.h"
|
2020-03-19 19:37:00 +01:00
|
|
|
#include "BKE_idtype.h"
|
2017-02-17 11:02:25 +01:00
|
|
|
#include "BKE_layer.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
|
|
|
|
#include "BKE_lib_override.h"
|
|
|
|
|
#include "BKE_lib_query.h"
|
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
|
|
|
#include "BKE_main.h" /* for Main */
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_main_idmap.h"
|
2018-11-07 18:00:24 +01:00
|
|
|
#include "BKE_material.h"
|
2005-07-20 04:14:21 +00:00
|
|
|
#include "BKE_modifier.h"
|
Orange:
- New UI element: the "Curve Button".
For mapping ranges (like 0 - 1) to another range, the curve button can be
used for proportional falloff, bone influences, painting density, etc.
Most evident use is of course to map RGB color with curves.
To be able to use it, you have to allocate a CurveMapping struct and pass
this on to the button. The CurveMapping API is in the new C file
blenkernel/intern/colortools.c
It's as simple as calling:
curvemap= curvemapping_add(3, 0, 0, 1, 1)
Which will create 3 curves, and sets a default 0-1 range. The current code
only supports up to 4 curves maximum per mapping struct.
The CurveMap button in Blender than handles allmost all editing.
Evaluating a single channel:
float newvalue= curvemapping_evaluateF(curvemap, 0, oldval);
Where the second argument is the channel index, here 0-1-2 are possible.
Or mapping a vector:
curvemapping_evaluate3F(curvemap, newvec, oldvec);
Optimized versions for byte or short mapping is possible too, not done yet.
In butspace.c I've added a template wrapper for buttons around the curve, to
reveil settings or show tools; check this screenie:
http://www.blender.org/bf/curves.jpg
- Buttons R, G, B: select channel
- icons + and -: zoom in, out
- icon 'wrench': menu with tools, like clear curve, set handle type
- icon 'clipping': menu with clip values, and to dis/enable clipping
- icon 'x': delete selection
In the curve button itself, only LMB clicks are handled (like all UI elements
in Blender).
- click on point: select
- shift+click on point: swap select
- click on point + drag: select point (if not selected) and move it
- click outside point + drag: translate view
- CTRL+click: add new point
- hold SHIFT while dragging to snap to grid
(Yes I know... either one of these can be Blender compliant, not both!)
- if you drag a point exactly on top of another, it merges them
Other fixes:
- Icons now draw using "Safe RasterPos", so they align with pixel boundary.
the old code made ints from the raster pos coordinate, which doesn't work
well for zoom in/out situations
- bug in Node editing: buttons could not get freed, causing in memory error
prints at end of a Blender session. That one was a very simple, but nasty
error causing me all evening last night to find!
(Hint; check diff of editnode.c, where uiDoButtons is called)
Last note: this adds 3 new files in our tree, I did scons, but not MSVC!
2006-01-08 11:41:06 +00:00
|
|
|
#include "BKE_node.h" /* for tree type defines */
|
2004-09-13 06:57:24 +00:00
|
|
|
#include "BKE_object.h"
|
2020-09-10 14:35:09 +02:00
|
|
|
#include "BKE_packedFile.h"
|
2008-12-19 00:50:21 +00:00
|
|
|
#include "BKE_report.h"
|
2004-09-13 06:57:24 +00:00
|
|
|
#include "BKE_scene.h"
|
2009-12-19 22:40:45 +00:00
|
|
|
#include "BKE_screen.h"
|
2021-02-04 22:03:39 +01:00
|
|
|
#include "BKE_undo_system.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 "BKE_workspace.h"
|
2011-12-21 11:01:08 +00:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
#include "DRW_engine.h"
|
|
|
|
|
|
2017-04-06 16:13:57 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
|
2019-01-25 17:31:32 +01:00
|
|
|
#include "BLO_blend_defs.h"
|
2019-01-25 17:42:43 +01:00
|
|
|
#include "BLO_blend_validate.h"
|
2020-06-05 11:44:36 +02:00
|
|
|
#include "BLO_read_write.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BLO_readfile.h"
|
2004-09-05 13:43:51 +00:00
|
|
|
#include "BLO_undofile.h"
|
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
|
|
|
|
2020-12-19 06:44:57 +01:00
|
|
|
#include "SEQ_clipboard.h"
|
|
|
|
|
#include "SEQ_iterator.h"
|
|
|
|
|
#include "SEQ_modifier.h"
|
2020-11-01 21:03:31 +01:00
|
|
|
#include "SEQ_sequencer.h"
|
2021-05-06 05:53:17 +02:00
|
|
|
#include "SEQ_utils.h"
|
2020-11-01 21:03:31 +01:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "readfile.h"
|
|
|
|
|
|
Patch provided by Shaul Kedem: Compressed files are back!
He even made a nice doc in wiki:
http://wiki.blender.org/bin/view.pl/Blenderdev/Blendgz
Usage: set the option "Compress File" in the main "File" pulldown menu.
This setting is a user-def, meaning it is not changed on reading files.
If you want it default, save it with CTRL+U.
The longest debate went over the file naming convention. Shaul started
with .blend.gz files, which gave issues in Blender because of the code
hanging out everywhere that detects blender files, and that appends the
.blend extension if needed.
Daniel Dunbar proposed to just save it as .blend, and not bother users
with such details. This is indeed the most elegant solution, with as
only drawback that old Blender executables cannot read it.
This drawback isn't very relevant at the moment, since we're heading
towards a release that isn't upward compatible anyway... the recode
going on on Meshes, Modfiers, Armatures, Poses, Actions, NLA already
have upward compatibility issues.
We might check - during the next month(s) - on a builtin system to
warn users in the future when we change things that make a file risky
to read in an older release.
2005-07-27 19:46:06 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
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
|
2019-09-18 13:19:29 +10:00
|
|
|
* - read #USER data, only when indicated (file is `~/.config/blender/X.XX/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,
|
2022-03-08 14:32:34 +11:00
|
|
|
* while ZLIB supports seek it's unusably slow, see: T61880.
|
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
|
|
|
|
2019-02-22 13:46:44 +11:00
|
|
|
typedef struct BHeadN {
|
|
|
|
|
struct 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;
|
2019-02-22 13:46:44 +11:00
|
|
|
struct BHead bhead;
|
|
|
|
|
} BHeadN;
|
|
|
|
|
|
2020-10-01 11:55:14 +05:30
|
|
|
#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.
|
|
|
|
|
*/
|
2019-02-22 14:42:22 +11:00
|
|
|
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA)
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2020-06-23 09:54:07 +10:00
|
|
|
return lib->parent ? lib->parent->filepath_abs : "<direct>";
|
2014-10-19 12:49:01 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name OldNewMap API
|
|
|
|
|
* \{ */
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
typedef struct OldNew {
|
|
|
|
|
const void *oldp;
|
|
|
|
|
void *newp;
|
|
|
|
|
/* `nr` is "user count" for data, and ID code for libdata. */
|
|
|
|
|
int nr;
|
|
|
|
|
} OldNew;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
typedef struct OldNewMap {
|
|
|
|
|
/* Array that stores the actual entries. */
|
|
|
|
|
OldNew *entries;
|
|
|
|
|
int nentries;
|
2022-01-06 13:54:52 +11:00
|
|
|
/* Hash-map that stores indices into the `entries` array. */
|
2018-12-13 15:29:54 +01:00
|
|
|
int32_t *map;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
int capacity_exp;
|
|
|
|
|
} OldNewMap;
|
2005-12-15 18:42:02 +00:00
|
|
|
|
2019-05-27 07:54:56 -06:00
|
|
|
#define ENTRIES_CAPACITY(onm) (1ll << (onm)->capacity_exp)
|
|
|
|
|
#define MAP_CAPACITY(onm) (1ll << ((onm)->capacity_exp + 1))
|
2018-12-13 15:29:54 +01:00
|
|
|
#define SLOT_MASK(onm) (MAP_CAPACITY(onm) - 1)
|
|
|
|
|
#define DEFAULT_SIZE_EXP 6
|
|
|
|
|
#define PERTURB_SHIFT 5
|
|
|
|
|
|
|
|
|
|
/* based on the probing algorithm used in Python dicts. */
|
|
|
|
|
#define ITER_SLOTS(onm, KEY, SLOT_NAME, INDEX_NAME) \
|
|
|
|
|
uint32_t hash = BLI_ghashutil_ptrhash(KEY); \
|
|
|
|
|
uint32_t mask = SLOT_MASK(onm); \
|
|
|
|
|
uint perturb = hash; \
|
|
|
|
|
int SLOT_NAME = mask & hash; \
|
|
|
|
|
int INDEX_NAME = onm->map[SLOT_NAME]; \
|
|
|
|
|
for (;; SLOT_NAME = mask & ((5 * SLOT_NAME) + 1 + perturb), \
|
|
|
|
|
perturb >>= PERTURB_SHIFT, \
|
|
|
|
|
INDEX_NAME = onm->map[SLOT_NAME])
|
|
|
|
|
|
|
|
|
|
static void oldnewmap_insert_index_in_map(OldNewMap *onm, const void *ptr, int index)
|
|
|
|
|
{
|
2019-04-21 04:40:16 +10:00
|
|
|
ITER_SLOTS (onm, ptr, slot, stored_index) {
|
2018-12-13 15:29:54 +01:00
|
|
|
if (stored_index == -1) {
|
|
|
|
|
onm->map[slot] = index;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-12-15 18:42:02 +00:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
static void oldnewmap_insert_or_replace(OldNewMap *onm, OldNew entry)
|
2005-12-15 18:42:02 +00:00
|
|
|
{
|
2019-04-21 04:40:16 +10:00
|
|
|
ITER_SLOTS (onm, entry.oldp, slot, index) {
|
2018-12-13 15:29:54 +01:00
|
|
|
if (index == -1) {
|
|
|
|
|
onm->entries[onm->nentries] = entry;
|
|
|
|
|
onm->map[slot] = onm->nentries;
|
|
|
|
|
onm->nentries++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
if (onm->entries[index].oldp == entry.oldp) {
|
2018-12-13 15:29:54 +01:00
|
|
|
onm->entries[index] = entry;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-12-15 18:42:02 +00:00
|
|
|
}
|
|
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
static OldNew *oldnewmap_lookup_entry(const OldNewMap *onm, const void *addr)
|
2005-12-13 19:21:56 +00:00
|
|
|
{
|
2019-04-21 04:40:16 +10:00
|
|
|
ITER_SLOTS (onm, addr, slot, index) {
|
2018-12-13 15:29:54 +01:00
|
|
|
if (index >= 0) {
|
|
|
|
|
OldNew *entry = &onm->entries[index];
|
|
|
|
|
if (entry->oldp == addr) {
|
|
|
|
|
return entry;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
static void oldnewmap_clear_map(OldNewMap *onm)
|
2012-05-04 15:42:49 +00:00
|
|
|
{
|
2018-12-13 15:29:54 +01:00
|
|
|
memset(onm->map, 0xFF, MAP_CAPACITY(onm) * sizeof(*onm->map));
|
2012-05-04 15:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
static void oldnewmap_increase_size(OldNewMap *onm)
|
2015-08-18 11:22:07 +10:00
|
|
|
{
|
2018-12-13 15:29:54 +01:00
|
|
|
onm->capacity_exp++;
|
|
|
|
|
onm->entries = MEM_reallocN(onm->entries, sizeof(*onm->entries) * ENTRIES_CAPACITY(onm));
|
|
|
|
|
onm->map = MEM_reallocN(onm->map, sizeof(*onm->map) * MAP_CAPACITY(onm));
|
|
|
|
|
oldnewmap_clear_map(onm);
|
|
|
|
|
for (int i = 0; i < onm->nentries; i++) {
|
|
|
|
|
oldnewmap_insert_index_in_map(onm, onm->entries[i].oldp, i);
|
2015-08-18 11:22:07 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
/* Public OldNewMap API */
|
|
|
|
|
|
2022-02-20 21:28:58 +11:00
|
|
|
static void oldnewmap_init_data(OldNewMap *onm, const int capacity_exp)
|
2005-12-13 19:21:56 +00:00
|
|
|
{
|
2022-02-20 21:28:58 +11:00
|
|
|
memset(onm, 0x0, sizeof(*onm));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2022-02-20 21:28:58 +11:00
|
|
|
onm->capacity_exp = capacity_exp;
|
2018-12-13 15:29:54 +01:00
|
|
|
onm->entries = MEM_malloc_arrayN(
|
|
|
|
|
ENTRIES_CAPACITY(onm), sizeof(*onm->entries), "OldNewMap.entries");
|
|
|
|
|
onm->map = MEM_malloc_arrayN(MAP_CAPACITY(onm), sizeof(*onm->map), "OldNewMap.map");
|
|
|
|
|
oldnewmap_clear_map(onm);
|
2022-02-20 21:28:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static OldNewMap *oldnewmap_new(void)
|
|
|
|
|
{
|
|
|
|
|
OldNewMap *onm = MEM_mallocN(sizeof(*onm), "OldNewMap");
|
|
|
|
|
|
|
|
|
|
oldnewmap_init_data(onm, DEFAULT_SIZE_EXP);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
return onm;
|
|
|
|
|
}
|
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)
|
|
|
|
|
{
|
2019-04-22 09:13:00 +10:00
|
|
|
if (oldaddr == NULL || newaddr == NULL) {
|
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
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
if (UNLIKELY(onm->nentries == ENTRIES_CAPACITY(onm))) {
|
|
|
|
|
oldnewmap_increase_size(onm);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
OldNew entry;
|
|
|
|
|
entry.oldp = oldaddr;
|
|
|
|
|
entry.newp = newaddr;
|
|
|
|
|
entry.nr = nr;
|
|
|
|
|
oldnewmap_insert_or_replace(onm, entry);
|
2002-10-12 11:37:38 +00: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)
|
|
|
|
|
{
|
|
|
|
|
OldNew *entry = oldnewmap_lookup_entry(onm, addr);
|
2019-04-22 09:13:00 +10:00
|
|
|
if (entry == NULL) {
|
2018-12-13 15:29:54 +01:00
|
|
|
return NULL;
|
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
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
/* for libdata, OldNew.nr has ID code, no increment */
|
|
|
|
|
static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *lib)
|
|
|
|
|
{
|
2019-04-22 09:13:00 +10:00
|
|
|
if (addr == NULL) {
|
2018-12-13 15:29:54 +01:00
|
|
|
return NULL;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
ID *id = oldnewmap_lookup_and_inc(onm, addr, false);
|
2019-04-22 09:13:00 +10:00
|
|
|
if (id == NULL) {
|
2018-12-13 15:29:54 +01:00
|
|
|
return NULL;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (!lib || id->lib) {
|
2018-12-13 15:29:54 +01:00
|
|
|
return id;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
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. */
|
2018-12-13 15:29:54 +01:00
|
|
|
for (int i = 0; i < onm->nentries; i++) {
|
2012-05-17 12:59:34 +00:00
|
|
|
OldNew *entry = &onm->entries[i];
|
|
|
|
|
if (entry->nr == 0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(entry->newp);
|
2012-05-17 12:59:34 +00:00
|
|
|
entry->newp = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-20 21:28:58 +11:00
|
|
|
MEM_freeN(onm->entries);
|
|
|
|
|
MEM_freeN(onm->map);
|
|
|
|
|
|
|
|
|
|
oldnewmap_init_data(onm, DEFAULT_SIZE_EXP);
|
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
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(onm->entries);
|
2018-12-13 15:29:54 +01:00
|
|
|
MEM_freeN(onm->map);
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(onm);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-13 15:29:54 +01:00
|
|
|
#undef ENTRIES_CAPACITY
|
|
|
|
|
#undef MAP_CAPACITY
|
|
|
|
|
#undef SLOT_MASK
|
|
|
|
|
#undef DEFAULT_SIZE_EXP
|
|
|
|
|
#undef PERTURB_SHIFT
|
|
|
|
|
#undef ITER_SLOTS
|
|
|
|
|
|
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
|
|
|
|
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
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
mainl = mainlist->first;
|
2021-06-30 15:19:35 +02:00
|
|
|
|
|
|
|
|
if (mainl->id_map != NULL) {
|
|
|
|
|
/* Cannot keep this since we add some IDs from joined mains. */
|
|
|
|
|
BKE_main_idmap_destroy(mainl->id_map);
|
|
|
|
|
mainl->id_map = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
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
|
|
|
{
|
2016-06-07 01:54:59 +10:00
|
|
|
for (ID *id = lb_src->first, *idnext; id; id = idnext) {
|
2012-05-17 12:59:34 +00:00
|
|
|
idnext = id->next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (id->lib) {
|
2018-11-30 14:51:16 +11:00
|
|
|
if (((uint)id->lib->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. */
|
2016-06-07 01:54:59 +10:00
|
|
|
(lib_main_array[id->lib->temp_index]->curlib == id->lib)) {
|
|
|
|
|
Main *mainvar = lib_main_array[id->lib->temp_index];
|
|
|
|
|
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;
|
|
|
|
|
main->next = NULL;
|
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
|
|
|
|
2021-06-30 15:19:35 +02:00
|
|
|
if (main->id_map != NULL) {
|
|
|
|
|
/* Cannot keep this since we remove some IDs from given main. */
|
|
|
|
|
BKE_main_idmap_destroy(main->id_map);
|
|
|
|
|
main->id_map = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
2018-11-30 14:51:16 +11:00
|
|
|
Main **lib_main_array = MEM_malloc_arrayN(lib_main_array_len, sizeof(*lib_main_array), __func__);
|
2016-06-07 01:54:59 +10:00
|
|
|
|
|
|
|
|
int i = 0;
|
2019-03-08 09:29:17 +11:00
|
|
|
for (Library *lib = main->libraries.first; lib; lib = 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;
|
2016-12-23 12:54:51 +01:00
|
|
|
libmain->versionfile = lib->versionfile;
|
|
|
|
|
libmain->subversionfile = lib->subversionfile;
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_addtail(mainlist, libmain);
|
2016-06-07 01:54:59 +10:00
|
|
|
lib->temp_index = i;
|
|
|
|
|
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--) {
|
2018-04-18 18:22:18 +02:00
|
|
|
ID *id = lbarray[i]->first;
|
|
|
|
|
if (id == NULL || GS(id->name) == ID_LI) {
|
2019-06-17 12:51:53 +10:00
|
|
|
/* No ID_LI data-lock 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)) {
|
2012-05-17 12:59:34 +00:00
|
|
|
if (bhead->code == GLOB) {
|
2018-11-30 14:51:16 +11:00
|
|
|
FileGlobal *fg = 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);
|
|
|
|
|
}
|
2019-04-22 09:13:00 +10:00
|
|
|
else if (bhead->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) {
|
|
|
|
|
main->curlib->versionfile = main->versionfile;
|
|
|
|
|
main->curlib->subversionfile = main->subversionfile;
|
|
|
|
|
}
|
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;
|
|
|
|
|
int code_prev = 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) ?
|
|
|
|
|
BKE_idtype_idcode_is_linkable((short)code_prev) :
|
|
|
|
|
false;
|
2015-03-11 00:33:44 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_link) {
|
|
|
|
|
reserve += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert(fd->bhead_idname_hash == NULL);
|
|
|
|
|
|
|
|
|
|
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) ?
|
|
|
|
|
BKE_idtype_idcode_is_linkable((short)code_prev) :
|
|
|
|
|
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;
|
2011-11-26 13:11:55 +00:00
|
|
|
char name1[FILE_MAX];
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2011-05-18 06:27:32 +00:00
|
|
|
BLI_strncpy(name1, filepath, sizeof(name1));
|
2020-04-07 12:02:21 +10:00
|
|
|
BLI_path_normalize(relabase, name1);
|
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);
|
2006-01-04 19:05:24 +00:00
|
|
|
// printf("blo_find_main: converted to %s\n", name1);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
for (m = mainlist->first; m; m = m->next) {
|
2021-12-13 16:22:19 +11:00
|
|
|
const char *libname = (m->curlib) ? m->curlib->filepath_abs : m->filepath;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2011-04-06 06:03:48 +00:00
|
|
|
if (BLI_path_cmp(name1, 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... */
|
2018-10-31 12:41:38 +01:00
|
|
|
lib = BKE_libblock_alloc(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);
|
|
|
|
|
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_strncpy(lib->filepath, filepath, sizeof(lib->filepath));
|
2020-06-23 09:54:07 +10:00
|
|
|
BLI_strncpy(lib->filepath_abs, name1, sizeof(lib->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;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
typedef struct BlendDataReader {
|
|
|
|
|
FileData *fd;
|
|
|
|
|
} BlendDataReader;
|
|
|
|
|
|
|
|
|
|
typedef struct BlendLibReader {
|
|
|
|
|
FileData *fd;
|
|
|
|
|
Main *main;
|
|
|
|
|
} BlendLibReader;
|
|
|
|
|
|
|
|
|
|
typedef struct BlendExpander {
|
|
|
|
|
FileData *fd;
|
|
|
|
|
Main *main;
|
|
|
|
|
} BlendExpander;
|
|
|
|
|
|
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
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (bhead->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
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (bhead->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
|
|
|
|
|
|
|
|
if (bhead4->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);
|
2018-11-30 14:51:16 +11: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
|
|
|
|
2004-06-23 18:22:51 +00:00
|
|
|
if (bhead8->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)
|
|
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
BHeadN *new_bhead = NULL;
|
2020-09-20 18:41:50 +02:00
|
|
|
ssize_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) {
|
|
|
|
|
bhead4.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
|
|
|
|
2004-06-23 18:22:51 +00:00
|
|
|
if (readsize == sizeof(bhead4) || bhead4.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 {
|
2018-05-08 13:32:52 +02:00
|
|
|
/* MIN2 is only to quiet '-Warray-bounds' compiler warning. */
|
|
|
|
|
BLI_assert(sizeof(bhead) == sizeof(bhead4));
|
|
|
|
|
memcpy(&bhead, &bhead4, MIN2(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 {
|
2002-10-12 11:37:38 +00:00
|
|
|
bhead8.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
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (readsize == sizeof(bhead8) || bhead8.code == ENDB) {
|
|
|
|
|
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 {
|
2018-05-08 13:32:52 +02:00
|
|
|
/* MIN2 is only to quiet '-Warray-bounds' compiler warning. */
|
|
|
|
|
BLI_assert(sizeof(bhead) == sizeof(bhead8));
|
|
|
|
|
memcpy(&bhead, &bhead8, MIN2(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
|
2021-08-19 23:57:00 +02:00
|
|
|
else if (fd->file->seek != NULL && BHEAD_USE_READ_ON_DEMAND(&bhead)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
/* Delay reading bhead content. */
|
|
|
|
|
new_bhead = MEM_mallocN(sizeof(BHeadN), "new_bhead");
|
|
|
|
|
if (new_bhead) {
|
|
|
|
|
new_bhead->next = new_bhead->prev = NULL;
|
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;
|
2021-08-19 23:57:00 +02:00
|
|
|
off64_t seek_new = fd->file->seek(fd->file, bhead.len, SEEK_CUR);
|
2019-02-22 14:42:22 +11:00
|
|
|
if (seek_new == -1) {
|
|
|
|
|
fd->is_eof = true;
|
|
|
|
|
MEM_freeN(new_bhead);
|
|
|
|
|
new_bhead = NULL;
|
|
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
BLI_assert(fd->file->offset == seek_new);
|
2019-02-22 14:42:22 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
fd->is_eof = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else {
|
2020-09-20 18:41:50 +02:00
|
|
|
new_bhead = MEM_mallocN(sizeof(BHeadN) + (size_t)bhead.len, "new_bhead");
|
2002-10-12 11:37:38 +00:00
|
|
|
if (new_bhead) {
|
2011-02-13 10:52:18 +00:00
|
|
|
new_bhead->next = new_bhead->prev = NULL;
|
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
|
|
|
|
2021-08-19 23:57:00 +02: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);
|
2011-02-13 10:52:18 +00:00
|
|
|
new_bhead = NULL;
|
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;
|
2011-02-13 10:52:18 +00:00
|
|
|
BHead *bhead = NULL;
|
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
|
|
|
|
|
*/
|
2019-03-04 01:01:52 +11:00
|
|
|
new_bhead = fd->bhead_list.first;
|
2011-02-13 10:52:18 +00:00
|
|
|
if (new_bhead == NULL) {
|
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
|
|
|
}
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
BHead *blo_bhead_prev(FileData *UNUSED(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
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
return (prev) ? &prev->bhead : NULL;
|
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
|
|
|
{
|
2008-01-30 18:18:33 +00:00
|
|
|
BHeadN *new_bhead = NULL;
|
|
|
|
|
BHead *bhead = NULL;
|
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;
|
2011-02-13 10:52:18 +00:00
|
|
|
if (new_bhead == NULL) {
|
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 {
|
2021-08-19 23:57:00 +02: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);
|
|
|
|
|
BHeadN *new_bhead_data = MEM_mallocN(sizeof(BHeadN) + new_bhead->bhead.len, "new_bhead");
|
|
|
|
|
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);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
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) :
|
2020-12-11 18:15:25 +01:00
|
|
|
NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static void decode_blender_header(FileData *fd)
|
|
|
|
|
{
|
|
|
|
|
char header[SIZEOFBLENDERHEADER], num[4];
|
2020-09-20 18:41:50 +02:00
|
|
|
ssize_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)) {
|
2019-02-12 09:29:18 +11:00
|
|
|
if (bhead->code == GLOB) {
|
|
|
|
|
/* 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. */
|
|
|
|
|
FileGlobal *fg = (void *)&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);
|
|
|
|
|
}
|
|
|
|
|
else if (bhead->code == DNA1) {
|
2013-02-22 13:35:32 +00:00
|
|
|
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-07-12 12:23:48 +10:00
|
|
|
fd->filesdna = DNA_sdna_from_data(
|
|
|
|
|
&bhead[1], bhead->len, do_endian_swap, true, 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);
|
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) */
|
2021-03-08 14:44:57 +11:00
|
|
|
fd->id_name_offset = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]");
|
|
|
|
|
BLI_assert(fd->id_name_offset != -1);
|
|
|
|
|
fd->id_asset_data_offset = DNA_elem_offset(
|
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
|
|
|
}
|
2019-04-22 09:13:00 +10:00
|
|
|
else if (bhead->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;
|
|
|
|
|
int *blend_thumb = NULL;
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
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 (bhead->code == TEST) {
|
|
|
|
|
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
|
|
|
|
|
int *data = (int *)(bhead + 1);
|
|
|
|
|
|
2020-08-08 13:29:21 +10: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;
|
|
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
if (bhead->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
|
|
|
{
|
2021-06-23 09:51:11 +02:00
|
|
|
BLI_assert(reports != NULL);
|
|
|
|
|
|
2005-05-26 13:17:12 +00:00
|
|
|
FileData *fd = 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;
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2016-07-12 12:23:48 +10:00
|
|
|
const char *error_message = NULL;
|
|
|
|
|
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);
|
2012-05-17 12:59:34 +00:00
|
|
|
fd = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
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);
|
2012-05-17 12:59:34 +00:00
|
|
|
fd = NULL;
|
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);
|
|
|
|
|
FileReader *file = NULL;
|
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. */
|
|
|
|
|
if (rawfile == NULL || 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,
|
|
|
|
|
errno ? strerror(errno) : TIP_("insufficient content"));
|
2021-08-19 23:57:00 +02:00
|
|
|
if (rawfile) {
|
|
|
|
|
rawfile->close(rawfile);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
close(filedes);
|
|
|
|
|
}
|
2019-02-24 12:34:41 +11:00
|
|
|
return NULL;
|
|
|
|
|
}
|
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);
|
|
|
|
|
if (file == NULL) {
|
|
|
|
|
/* mmap failed, so just keep using rawfile. */
|
|
|
|
|
file = rawfile;
|
|
|
|
|
rawfile = NULL;
|
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);
|
|
|
|
|
if (file != NULL) {
|
2021-10-18 11:16:24 +11:00
|
|
|
rawfile = NULL; /* 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);
|
|
|
|
|
if (file != NULL) {
|
2021-10-18 11:16:24 +11:00
|
|
|
rawfile = NULL; /* 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. */
|
|
|
|
|
if (rawfile != NULL) {
|
|
|
|
|
rawfile->close(rawfile);
|
|
|
|
|
}
|
|
|
|
|
if (file == NULL) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_reportf(reports->reports, RPT_WARNING, "Unrecognized file format '%s'", filepath);
|
2019-02-24 12:34:41 +11:00
|
|
|
return NULL;
|
|
|
|
|
}
|
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,
|
|
|
|
|
errno ? strerror(errno) : TIP_("unknown error reading file"));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
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);
|
|
|
|
|
if (fd != NULL) {
|
2008-09-11 13:00:54 +00:00
|
|
|
/* needed for library_append and read_libraries */
|
2011-05-18 06:27:32 +00:00
|
|
|
BLI_strncpy(fd->relabase, filepath, sizeof(fd->relabase));
|
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
|
|
|
}
|
2019-02-24 10:46:26 +11:00
|
|
|
return NULL;
|
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
|
|
|
{
|
2021-06-23 09:51:11 +02:00
|
|
|
FileData *fd = blo_filedata_from_file_open(filepath, &(BlendFileReadReport){.reports = NULL});
|
2019-02-24 10:46:26 +11:00
|
|
|
if (fd != NULL) {
|
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
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
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(
|
|
|
|
|
reports->reports, RPT_WARNING, (mem) ? TIP_("Unable to read") : TIP_("Unable to open"));
|
2002-10-12 11:37:38 +00:00
|
|
|
return NULL;
|
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
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
if (BLI_file_magic_is_gzip(mem)) {
|
|
|
|
|
file = BLI_filereader_new_gzip(mem_file);
|
2020-08-07 12:31:44 +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(mem)) {
|
|
|
|
|
file = BLI_filereader_new_zstd(mem_file);
|
|
|
|
|
}
|
2021-08-19 23:57:00 +02:00
|
|
|
|
|
|
|
|
if (file == NULL) {
|
|
|
|
|
/* Compression initialization failed. */
|
|
|
|
|
mem_file->close(mem_file);
|
|
|
|
|
return NULL;
|
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,
|
|
|
|
|
const struct 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>");
|
2004-09-05 13:43:51 +00:00
|
|
|
return NULL;
|
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
|
|
|
{
|
|
|
|
|
if (fd) {
|
2021-01-14 22:02:48 +01:00
|
|
|
|
2019-02-22 14:42:22 +11:00
|
|
|
/* Free all BHeadN data blocks */
|
|
|
|
|
#ifndef NDEBUG
|
2019-03-04 01:01:52 +11:00
|
|
|
BLI_freelistN(&fd->bhead_list);
|
2019-02-22 14:42:22 +11:00
|
|
|
#else
|
|
|
|
|
/* Sanity check we're not keeping memory we don't need. */
|
2019-04-21 04:40:16 +10:00
|
|
|
LISTBASE_FOREACH_MUTABLE (BHeadN *, new_bhead, &fd->bhead_list) {
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->file->seek != NULL && BHEAD_USE_READ_ON_DEMAND(&new_bhead->bhead)) {
|
2019-02-22 14:42:22 +11:00
|
|
|
BLI_assert(new_bhead->has_data == 0);
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(new_bhead);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2021-11-01 21:43:18 +11:00
|
|
|
fd->file->close(fd->file);
|
2016-07-12 12:53:49 +10:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->filesdna) {
|
2008-10-31 23:50:02 +00:00
|
|
|
DNA_sdna_free(fd->filesdna);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (fd->compflags) {
|
2016-07-22 04:05:38 +10:00
|
|
|
MEM_freeN((void *)fd->compflags);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2020-09-29 12:29:01 +02:00
|
|
|
if (fd->reconstruct_info) {
|
|
|
|
|
DNA_reconstruct_info_free(fd->reconstruct_info);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->datamap) {
|
2002-10-12 11:37:38 +00:00
|
|
|
oldnewmap_free(fd->datamap);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (fd->globmap) {
|
2002-10-12 11:37:38 +00:00
|
|
|
oldnewmap_free(fd->globmap);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (fd->packedmap) {
|
2012-12-27 17:09:27 +00:00
|
|
|
oldnewmap_free(fd->packedmap);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
oldnewmap_free(fd->libmap);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2020-03-17 12:29:36 +01:00
|
|
|
if (fd->old_idmap != NULL) {
|
|
|
|
|
BKE_main_idmap_destroy(fd->old_idmap);
|
|
|
|
|
}
|
2020-07-03 11:36:27 +02:00
|
|
|
blo_cache_storage_end(fd);
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->bheadmap) {
|
2008-01-30 18:18:33 +00:00
|
|
|
MEM_freeN(fd->bheadmap);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
|
|
|
|
if (fd->bhead_idname_hash) {
|
|
|
|
|
BLI_ghash_free(fd->bhead_idname_hash, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Public Utilities
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2014-01-31 03:09:01 +11:00
|
|
|
bool BLO_has_bfile_extension(const char *str)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2014-01-31 03:09:01 +11:00
|
|
|
const char *ext_test[4] = {".blend", ".ble", ".blend.gz", NULL};
|
2018-06-17 16:13:24 +02:00
|
|
|
return BLI_path_extension_check_array(str, ext_test);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2019-04-22 01:10:29 +10:00
|
|
|
/* We might get some data names with slashes,
|
|
|
|
|
* so we have to go up in path until we find blend file itself,
|
2015-08-18 13:18:50 +02:00
|
|
|
* then we know next path item is group, and everything else is data name. */
|
|
|
|
|
char *slash = NULL, *prev_slash = NULL, c = '\0';
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
r_dir[0] = '\0';
|
|
|
|
|
if (r_group) {
|
|
|
|
|
*r_group = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (r_name) {
|
|
|
|
|
*r_name = NULL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
/* if path leads to an existing directory, we can be sure we're not (in) a library */
|
|
|
|
|
if (BLI_is_dir(path)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
strcpy(r_dir, path);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-07 12:02:21 +10:00
|
|
|
while ((slash = (char *)BLI_path_slash_rfind(r_dir))) {
|
2015-08-18 13:18:50 +02:00
|
|
|
char tc = *slash;
|
|
|
|
|
*slash = '\0';
|
2015-11-26 15:39:29 +11:00
|
|
|
if (BLO_has_bfile_extension(r_dir) && BLI_is_file(r_dir)) {
|
2015-08-18 13:18:50 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
if (STREQ(r_dir, BLO_EMBEDDED_STARTUP_BLEND)) {
|
2018-08-20 13:52:50 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
if (prev_slash) {
|
|
|
|
|
*prev_slash = c;
|
|
|
|
|
}
|
|
|
|
|
prev_slash = slash;
|
|
|
|
|
c = tc;
|
2009-09-12 19:54:39 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
if (!slash) {
|
|
|
|
|
return false;
|
2009-09-12 19:54:39 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
if (slash[1] != '\0') {
|
|
|
|
|
BLI_assert(strlen(slash + 1) < BLO_GROUP_MAX);
|
|
|
|
|
if (r_group) {
|
|
|
|
|
*r_group = slash + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
if (prev_slash && (prev_slash[1] != '\0')) {
|
|
|
|
|
BLI_assert(strlen(prev_slash + 1) < MAX_ID_NAME - 2);
|
|
|
|
|
if (r_name) {
|
|
|
|
|
*r_name = prev_slash + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-18 13:18:50 +02:00
|
|
|
return true;
|
2009-09-12 19:54:39 +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
|
|
|
BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
|
|
|
|
|
{
|
|
|
|
|
FileData *fd;
|
2018-01-14 23:26:31 +01:00
|
|
|
BlendThumbnail *data = NULL;
|
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
|
|
|
int *fd_data;
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
fd = blo_filedata_from_file_minimal(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
|
|
|
fd_data = fd ? read_file_thumbnail(fd) : NULL;
|
|
|
|
|
|
|
|
|
|
if (fd_data) {
|
2019-02-11 19:09:27 +11:00
|
|
|
const int width = fd_data[0];
|
|
|
|
|
const int height = fd_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);
|
|
|
|
|
data = MEM_mallocN(data_size, __func__);
|
2018-01-14 23:26:31 +01:00
|
|
|
if (data) {
|
2022-05-11 13:37:10 +10:00
|
|
|
BLI_assert((data_size - sizeof(*data)) ==
|
2018-01-14 23:26:31 +01:00
|
|
|
(BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*fd_data) * 2)));
|
|
|
|
|
data->width = width;
|
|
|
|
|
data->height = height;
|
2022-05-11 13:37:10 +10:00
|
|
|
memcpy(data->rect, &fd_data[2], data_size - sizeof(*data));
|
2018-01-14 23:26:31 +01: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-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
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
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 */
|
|
|
|
|
static void *newlibadr(FileData *fd, const void *lib, const void *adr)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2005-12-15 18:42:02 +00:00
|
|
|
return oldnewmap_liblookup(fd->libmap, adr, lib);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-10 14:41:19 +10:00
|
|
|
void *blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr)
|
2012-05-04 15:42:49 +00:00
|
|
|
{
|
|
|
|
|
return newlibadr(fd, lib, adr);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-10 14:41:19 +10:00
|
|
|
/* increases user number */
|
2019-02-27 19:25:21 +01:00
|
|
|
static void change_link_placeholder_to_real_ID_pointer_fd(FileData *fd, const void *old, void *new)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2018-12-13 15:29:54 +01:00
|
|
|
for (int i = 0; i < fd->libmap->nentries; i++) {
|
2012-05-17 12:59:34 +00:00
|
|
|
OldNew *entry = &fd->libmap->entries[i];
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (old == entry->newp && entry->nr == ID_LINK_PLACEHOLDER) {
|
2012-05-17 12:59:34 +00:00
|
|
|
entry->newp = new;
|
2019-04-22 09:13:00 +10:00
|
|
|
if (new) {
|
2018-11-30 14:51:16 +11:00
|
|
|
entry->nr = GS(((ID *)new)->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,
|
|
|
|
|
void *new)
|
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) {
|
2012-05-17 12:59:34 +00:00
|
|
|
fd = mainptr->curlib->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) {
|
2019-02-27 19:25:21 +01:00
|
|
|
change_link_placeholder_to_real_ID_pointer_fd(fd, old, new);
|
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)
|
|
|
|
|
{
|
|
|
|
|
OldNew *entry = fd->packedmap->entries;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
/* used entries were restored, so we put them to zero */
|
2020-08-21 14:39:18 +02:00
|
|
|
for (int i = 0; i < fd->packedmap->nentries; i++, entry++) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (entry->nr > 0) {
|
2012-12-27 15:07:19 +00:00
|
|
|
entry->newp = NULL;
|
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) {
|
2015-05-31 18:28:28 +02:00
|
|
|
ima->packedfile = newpackedadr(fd, ima->packedfile);
|
|
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
|
2015-04-06 10:40:12 -03:00
|
|
|
imapf->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) {
|
2012-12-27 15:07:19 +00:00
|
|
|
vfont->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) {
|
2012-12-27 15:07:19 +00:00
|
|
|
sound->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) {
|
2012-12-27 15:07:19 +00:00
|
|
|
lib->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) {
|
2020-03-17 14:41:48 +01:00
|
|
|
volume->packedfile = newpackedadr(fd, volume->packedfile);
|
|
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
|
2006-11-25 13:07:28 +00:00
|
|
|
{
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (Main *, ptr, old_mainlist) {
|
2012-05-17 12:59:34 +00:00
|
|
|
int i = set_listbasepointers(ptr, lbarray);
|
2012-03-24 07:52:14 +00:00
|
|
|
while (i--) {
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (ID *, id, lbarray[i]) {
|
2006-11-25 13:07:28 +00:00
|
|
|
oldnewmap_insert(fd->libmap, id, id, GS(id->name));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2006-11-25 13:07:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
|
|
|
|
|
fd->old_mainlist = old_mainlist;
|
2006-11-25 13:07:28 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
|
2020-03-17 12:29:36 +01:00
|
|
|
void blo_make_old_idmap_from_main(FileData *fd, Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
if (fd->old_idmap != NULL) {
|
|
|
|
|
BKE_main_idmap_destroy(fd->old_idmap);
|
|
|
|
|
}
|
|
|
|
|
fd->old_idmap = BKE_main_idmap_create(bmain, false, NULL, MAIN_IDMAP_TYPE_UUID);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-03 11:36:27 +02:00
|
|
|
typedef struct BLOCacheStorage {
|
|
|
|
|
GHash *cache_map;
|
|
|
|
|
MemArena *memarena;
|
|
|
|
|
} BLOCacheStorage;
|
|
|
|
|
|
2022-04-06 10:48:33 +02:00
|
|
|
typedef struct BLOCacheStorageValue {
|
|
|
|
|
void *cache_v;
|
|
|
|
|
uint new_usage_count;
|
|
|
|
|
} BLOCacheStorageValue;
|
|
|
|
|
|
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(
|
|
|
|
|
ID *id, const IDCacheKey *key, void **cache_p, uint UNUSED(flags), void *cache_storage_v)
|
2020-07-03 11:36:27 +02:00
|
|
|
{
|
|
|
|
|
BLI_assert(key->id_session_uuid == id->session_uuid);
|
2020-07-03 18:55:32 +02:00
|
|
|
UNUSED_VARS_NDEBUG(id);
|
2020-07-03 11:36:27 +02:00
|
|
|
|
|
|
|
|
BLOCacheStorage *cache_storage = cache_storage_v;
|
|
|
|
|
BLI_assert(!BLI_ghash_haskey(cache_storage->cache_map, key));
|
|
|
|
|
|
|
|
|
|
IDCacheKey *storage_key = BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_key));
|
|
|
|
|
*storage_key = *key;
|
2022-04-06 10:48:33 +02:00
|
|
|
BLOCacheStorageValue *storage_value = BLI_memarena_alloc(cache_storage->memarena,
|
|
|
|
|
sizeof(*storage_value));
|
|
|
|
|
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(
|
|
|
|
|
ID *UNUSED(id), const IDCacheKey *key, void **cache_p, uint flags, void *cache_storage_v)
|
2020-07-03 11:36:27 +02:00
|
|
|
{
|
|
|
|
|
BLOCacheStorage *cache_storage = cache_storage_v;
|
|
|
|
|
|
|
|
|
|
if (cache_storage == NULL) {
|
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) {
|
|
|
|
|
*cache_p = NULL;
|
|
|
|
|
}
|
2020-07-03 11:36:27 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-06 10:48:33 +02:00
|
|
|
BLOCacheStorageValue *storage_value = BLI_ghash_lookup(cache_storage->cache_map, key);
|
|
|
|
|
if (storage_value == NULL) {
|
2020-07-03 11:36:27 +02:00
|
|
|
*cache_p = NULL;
|
|
|
|
|
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. */
|
|
|
|
|
static void blo_cache_storage_entry_clear_in_old(ID *UNUSED(id),
|
|
|
|
|
const IDCacheKey *key,
|
|
|
|
|
void **cache_p,
|
2020-08-26 19:14:17 -06:00
|
|
|
uint UNUSED(flags),
|
2020-07-03 11:36:27 +02:00
|
|
|
void *cache_storage_v)
|
|
|
|
|
{
|
|
|
|
|
BLOCacheStorage *cache_storage = cache_storage_v;
|
|
|
|
|
|
2022-04-06 10:48:33 +02:00
|
|
|
BLOCacheStorageValue *storage_value = BLI_ghash_lookup(cache_storage->cache_map, key);
|
|
|
|
|
if (storage_value == NULL) {
|
2020-07-03 11:36:27 +02:00
|
|
|
*cache_p = NULL;
|
|
|
|
|
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) {
|
|
|
|
|
*cache_p = NULL;
|
|
|
|
|
}
|
|
|
|
|
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) {
|
2020-07-03 11:36:27 +02:00
|
|
|
BLI_assert(fd->cache_storage == NULL);
|
|
|
|
|
fd->cache_storage = MEM_mallocN(sizeof(*fd->cache_storage), __func__);
|
|
|
|
|
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) {
|
|
|
|
|
ID *id = lb->first;
|
|
|
|
|
if (id == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
if (type_info->foreach_cache == NULL) {
|
|
|
|
|
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 {
|
|
|
|
|
fd->cache_storage = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old)
|
|
|
|
|
{
|
|
|
|
|
if (fd->cache_storage != NULL) {
|
|
|
|
|
ListBase *lb;
|
|
|
|
|
FOREACH_MAIN_LISTBASE_BEGIN (bmain_old, lb) {
|
|
|
|
|
ID *id = lb->first;
|
|
|
|
|
if (id == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
if (type_info->foreach_cache == NULL) {
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
if (fd->cache_storage != NULL) {
|
|
|
|
|
BLI_ghash_free(fd->cache_storage->cache_map, NULL, NULL);
|
|
|
|
|
BLI_memarena_free(fd->cache_storage->memarena);
|
|
|
|
|
MEM_freeN(fd->cache_storage);
|
|
|
|
|
fd->cache_storage = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2016-07-12 11:48:04 +10:00
|
|
|
static void switch_endian_structs(const struct 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
|
|
|
{
|
2012-05-17 12:59:34 +00:00
|
|
|
void *temp = NULL;
|
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);
|
|
|
|
|
if (UNLIKELY(bh == NULL)) {
|
|
|
|
|
fd->flags &= ~FD_FLAGS_FILE_OK;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
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);
|
|
|
|
|
if (UNLIKELY(bh == NULL)) {
|
|
|
|
|
fd->flags &= ~FD_FLAGS_FILE_OK;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#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);
|
|
|
|
|
temp = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#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);
|
|
|
|
|
return (bhead->len) ? (const void *)(bhead + 1) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
ln = lb->first;
|
|
|
|
|
prev = NULL;
|
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);
|
|
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
ln->next = poin;
|
|
|
|
|
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
|
|
|
|
2020-06-26 14:40:47 +02:00
|
|
|
static void lib_link_id(BlendLibReader *reader, ID *id);
|
2020-02-06 16:25:15 +01:00
|
|
|
|
2020-06-26 14:40:47 +02:00
|
|
|
static void lib_link_id_embedded_id(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'. */
|
|
|
|
|
bNodeTree *nodetree = ntreeFromID(id);
|
|
|
|
|
if (nodetree != NULL) {
|
2020-06-26 14:40:47 +02:00
|
|
|
lib_link_id(reader, &nodetree->id);
|
2020-09-10 13:33:29 +02:00
|
|
|
ntreeBlendReadLib(reader, nodetree);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GS(id->name) == ID_SCE) {
|
|
|
|
|
Scene *scene = (Scene *)id;
|
|
|
|
|
if (scene->master_collection != NULL) {
|
2020-06-26 14:40:47 +02:00
|
|
|
lib_link_id(reader, &scene->master_collection->id);
|
2020-10-29 19:28:21 +01:00
|
|
|
BKE_collection_blend_read_lib(reader, scene->master_collection);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 14:40:47 +02:00
|
|
|
static void lib_link_id(BlendLibReader *reader, ID *id)
|
2017-11-29 15:05:03 +01:00
|
|
|
{
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: WM IDProperties are never written to file, hence they should always be NULL here. */
|
2020-02-05 16:18:17 +01:00
|
|
|
BLI_assert((GS(id->name) != ID_WM) || id->properties == NULL);
|
2020-08-28 13:18:24 +02:00
|
|
|
IDP_BlendReadLib(reader, id->properties);
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
AnimData *adt = BKE_animdata_from_id(id);
|
|
|
|
|
if (adt != NULL) {
|
2020-08-28 13:18:24 +02:00
|
|
|
BKE_animdata_blend_read_lib(reader, id, adt);
|
2020-02-05 16:18:17 +01:00
|
|
|
}
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2020-02-05 16:18:17 +01:00
|
|
|
if (id->override_library) {
|
2020-06-26 14:40:47 +02:00
|
|
|
BLO_read_id_address(reader, id->lib, &id->override_library->reference);
|
|
|
|
|
BLO_read_id_address(reader, id->lib, &id->override_library->storage);
|
2022-01-12 10:43:42 +01:00
|
|
|
BLO_read_id_address(reader, id->lib, &id->override_library->hierarchy_root);
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
2020-02-06 16:25:15 +01:00
|
|
|
|
2020-06-26 14:40:47 +02:00
|
|
|
lib_link_id_embedded_id(reader, id);
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-07 11:16:14 +02:00
|
|
|
static void direct_link_id_override_property_operation_cb(BlendDataReader *reader, void *data)
|
2017-11-29 15:05:03 +01:00
|
|
|
{
|
2019-06-14 23:16:04 +02:00
|
|
|
IDOverrideLibraryPropertyOperation *opop = data;
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_data_address(reader, &opop->subitem_reference_name);
|
|
|
|
|
BLO_read_data_address(reader, &opop->subitem_local_name);
|
2020-04-16 16:19:44 +02:00
|
|
|
|
|
|
|
|
opop->tag = 0; /* Runtime only. */
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-07 11:16:14 +02:00
|
|
|
static void direct_link_id_override_property_cb(BlendDataReader *reader, void *data)
|
2017-11-29 15:05:03 +01:00
|
|
|
{
|
2019-06-14 23:16:04 +02:00
|
|
|
IDOverrideLibraryProperty *op = data;
|
2017-11-29 15:05:03 +01:00
|
|
|
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_data_address(reader, &op->rna_path);
|
2020-04-16 16:19:44 +02:00
|
|
|
|
|
|
|
|
op->tag = 0; /* Runtime only. */
|
|
|
|
|
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_list_cb(reader, &op->operations, direct_link_id_override_property_operation_cb);
|
2017-11-29 15:05:03 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-15 17:57:13 +02:00
|
|
|
static void direct_link_id_common(
|
2020-06-07 11:16:14 +02:00
|
|
|
BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int 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'. */
|
|
|
|
|
bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
|
|
|
|
|
if (nodetree != NULL && *nodetree != NULL) {
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_data_address(reader, nodetree);
|
|
|
|
|
direct_link_id_common(reader,
|
2020-05-15 17:57:13 +02:00
|
|
|
current_library,
|
|
|
|
|
(ID *)*nodetree,
|
|
|
|
|
id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL,
|
|
|
|
|
0);
|
2020-09-10 13:33:29 +02:00
|
|
|
ntreeBlendReadData(reader, *nodetree);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GS(id->name) == ID_SCE) {
|
|
|
|
|
Scene *scene = (Scene *)id;
|
|
|
|
|
if (scene->master_collection != NULL) {
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_data_address(reader, &scene->master_collection);
|
|
|
|
|
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,
|
|
|
|
|
id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL,
|
|
|
|
|
0);
|
2020-10-29 19:28:21 +01:00
|
|
|
BKE_collection_blend_read_data(reader, scene->master_collection);
|
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;
|
|
|
|
|
|
|
|
|
|
if (id_current == NULL) {
|
|
|
|
|
/* 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) {
|
|
|
|
|
recalc |= ID_RECALC_COPY_ON_WRITE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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(
|
2020-06-07 11:16:14 +02:00
|
|
|
BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag)
|
2012-10-23 12:38:47 +00:00
|
|
|
{
|
2020-08-28 16:29:55 +02:00
|
|
|
if (!BLO_read_data_is_undo(reader)) {
|
2021-07-23 16:56:00 +10:00
|
|
|
/* When actually reading a file, we do want to reset/re-generate session uuids.
|
2020-05-15 17:57:13 +02:00
|
|
|
* In undo case, we want to re-use existing ones. */
|
|
|
|
|
id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-09 01:01:31 +11:00
|
|
|
if ((tag & LIB_TAG_TEMP_MAIN) == 0) {
|
|
|
|
|
BKE_lib_libblock_session_uuid_ensure(id);
|
|
|
|
|
}
|
2020-05-15 17:57:13 +02:00
|
|
|
|
|
|
|
|
id->lib = current_library;
|
|
|
|
|
id->us = ID_FAKE_USERS(id);
|
|
|
|
|
id->icon_id = 0;
|
|
|
|
|
id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */
|
|
|
|
|
id->orig_id = NULL;
|
|
|
|
|
id->py_instance = NULL;
|
|
|
|
|
|
|
|
|
|
/* Initialize with provided tag. */
|
|
|
|
|
id->tag = tag;
|
|
|
|
|
|
2021-09-17 16:22:29 +02:00
|
|
|
if (ID_IS_LINKED(id)) {
|
|
|
|
|
id->library_weak_reference = NULL;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLO_read_data_address(reader, &id->library_weak_reference);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-15 17:57:13 +02:00
|
|
|
if (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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 18:15:25 +01:00
|
|
|
if (id->asset_data) {
|
|
|
|
|
BLO_read_data_address(reader, &id->asset_data);
|
|
|
|
|
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) {
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_data_address(reader, &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) {
|
2020-06-07 11:16:14 +02:00
|
|
|
BLO_read_data_address(reader, &id->override_library);
|
2021-03-25 11:21:15 +01:00
|
|
|
/* Work around file corruption on writing, see T86853. */
|
|
|
|
|
if (id->override_library != NULL) {
|
|
|
|
|
BLO_read_list_cb(
|
|
|
|
|
reader, &id->override_library->properties, direct_link_id_override_property_cb);
|
|
|
|
|
id->override_library->runtime = NULL;
|
|
|
|
|
}
|
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
|
|
|
|
|
/**
|
|
|
|
|
* A version of #BKE_scene_validate_setscene with special checks for linked libs.
|
|
|
|
|
*/
|
|
|
|
|
static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
|
|
|
|
|
{
|
|
|
|
|
Scene *sce_iter;
|
|
|
|
|
int a;
|
|
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (sce->set == NULL) {
|
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) {
|
|
|
|
|
sce->set = NULL;
|
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
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Read ID: Screen
|
|
|
|
|
* \{ */
|
2008-12-29 13:38:08 +00:00
|
|
|
|
2014-02-21 10:29:08 +01:00
|
|
|
/* how to handle user count on pointer restore */
|
|
|
|
|
typedef enum ePointerUserMode {
|
2014-08-12 16:03:17 +02:00
|
|
|
USER_IGNORE = 0, /* ignore user count */
|
2015-11-09 16:04:51 +01:00
|
|
|
USER_REAL = 1, /* ensure at least one real user (fake user ignored) */
|
2014-02-21 10:29:08 +01:00
|
|
|
} ePointerUserMode;
|
|
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
static void restore_pointer_user(ID *id, ID *newid, ePointerUserMode user)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(STREQ(newid->name + 2, id->name + 2));
|
|
|
|
|
BLI_assert(newid->lib == id->lib);
|
|
|
|
|
UNUSED_VARS_NDEBUG(id);
|
|
|
|
|
|
|
|
|
|
if (user == USER_REAL) {
|
|
|
|
|
id_us_ensure_real(newid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef USE_GHASH_RESTORE_POINTER
|
|
|
|
|
/**
|
|
|
|
|
* A version of #restore_pointer_by_name that performs a full search (slow!).
|
|
|
|
|
* Use only for limited lookups, when the overhead of
|
|
|
|
|
* creating a #IDNameLib_Map for a single lookup isn't worthwhile.
|
|
|
|
|
*/
|
|
|
|
|
static void *restore_pointer_by_name_main(Main *mainp, ID *id, ePointerUserMode user)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2016-06-07 16:07:13 +10:00
|
|
|
if (id) {
|
|
|
|
|
ListBase *lb = which_libbase(mainp, GS(id->name));
|
|
|
|
|
if (lb) { /* there's still risk of checking corrupt mem (freed Ids in oops) */
|
|
|
|
|
ID *idn = lb->first;
|
|
|
|
|
for (; idn; idn = idn->next) {
|
|
|
|
|
if (STREQ(idn->name + 2, id->name + 2)) {
|
|
|
|
|
if (idn->lib == id->lib) {
|
|
|
|
|
restore_pointer_user(id, idn, user);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2016-06-07 16:07:13 +10:00
|
|
|
return idn;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-06-07 16:07:13 +10:00
|
|
|
return NULL;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2016-06-07 16:07:13 +10:00
|
|
|
#endif
|
2013-03-18 16:34:57 +00:00
|
|
|
|
2013-01-14 12:02:10 +00:00
|
|
|
/**
|
|
|
|
|
* Only for undo files, or to restore a screen after reading without UI...
|
|
|
|
|
*
|
2016-06-07 16:07:13 +10:00
|
|
|
* \param user:
|
2020-03-03 22:06:52 +11:00
|
|
|
* - USER_IGNORE: no user-count change.
|
|
|
|
|
* - USER_REAL: ensure a real user (even if a fake one is set).
|
2016-06-07 16:07:13 +10:00
|
|
|
* \param id_map: lookup table, use when performing many lookups.
|
2016-06-29 20:37:54 +10:00
|
|
|
* this could be made an optional argument (falling back to a full lookup),
|
2016-06-07 16:07:13 +10:00
|
|
|
* however at the moment it's always available.
|
2013-01-14 12:02:10 +00:00
|
|
|
*/
|
2016-06-07 16:07:13 +10:00
|
|
|
static void *restore_pointer_by_name(struct IDNameLib_Map *id_map, ID *id, ePointerUserMode user)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2016-06-07 16:07:13 +10:00
|
|
|
#ifdef USE_GHASH_RESTORE_POINTER
|
2012-03-24 06:18:31 +00:00
|
|
|
if (id) {
|
2016-06-07 16:07:13 +10:00
|
|
|
/* use fast lookup when available */
|
|
|
|
|
ID *idn = BKE_main_idmap_lookup_id(id_map, id);
|
|
|
|
|
if (idn) {
|
|
|
|
|
restore_pointer_user(id, idn, user);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2016-06-07 16:07:13 +10:00
|
|
|
return idn;
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2006-11-29 08:57:32 +00:00
|
|
|
return NULL;
|
2016-06-07 16:07:13 +10:00
|
|
|
#else
|
|
|
|
|
Main *mainp = BKE_main_idmap_main_get(id_map);
|
|
|
|
|
return restore_pointer_by_name_main(mainp, id, user);
|
|
|
|
|
#endif
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
|
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
static void lib_link_seq_clipboard_pt_restore(ID *id, struct IDNameLib_Map *id_map)
|
2013-07-24 06:51:04 +00:00
|
|
|
{
|
|
|
|
|
if (id) {
|
|
|
|
|
/* clipboard must ensure this */
|
|
|
|
|
BLI_assert(id->newid != NULL);
|
2016-06-07 16:07:13 +10:00
|
|
|
id->newid = restore_pointer_by_name(id_map, id->newid, USER_REAL);
|
2013-07-24 06:51:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
2021-08-20 16:30:34 +02:00
|
|
|
static bool lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
|
2012-02-03 13:08:44 +00:00
|
|
|
{
|
2016-06-07 16:07:13 +10:00
|
|
|
struct IDNameLib_Map *id_map = arg_pt;
|
2013-07-24 06:51:04 +00:00
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
lib_link_seq_clipboard_pt_restore((ID *)seq->scene, id_map);
|
|
|
|
|
lib_link_seq_clipboard_pt_restore((ID *)seq->scene_camera, id_map);
|
|
|
|
|
lib_link_seq_clipboard_pt_restore((ID *)seq->clip, id_map);
|
|
|
|
|
lib_link_seq_clipboard_pt_restore((ID *)seq->mask, id_map);
|
|
|
|
|
lib_link_seq_clipboard_pt_restore((ID *)seq->sound, id_map);
|
2021-08-20 16:30:34 +02:00
|
|
|
return true;
|
2012-02-03 13:08:44 +00:00
|
|
|
}
|
|
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map)
|
2012-02-03 13:08:44 +00:00
|
|
|
{
|
|
|
|
|
/* update IDs stored in sequencer clipboard */
|
2021-08-20 16:30:34 +02:00
|
|
|
SEQ_for_each_callback(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
|
2012-02-03 13:08:44 +00:00
|
|
|
}
|
|
|
|
|
|
2020-02-13 12:56:10 +01:00
|
|
|
static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data)
|
2019-09-23 11:02:58 +02:00
|
|
|
{
|
2020-02-13 12:56:10 +01:00
|
|
|
const int cb_flag = cb_data->cb_flag;
|
|
|
|
|
ID **id_pointer = cb_data->id_pointer;
|
2020-03-11 12:47:25 +01:00
|
|
|
if (cb_flag & IDWALK_CB_EMBEDDED || *id_pointer == NULL) {
|
2019-09-23 11:02:58 +02:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Special ugly case here, thanks again for those non-IDs IDs... */
|
|
|
|
|
/* We probably need to add more cases here (hint: nodetrees),
|
|
|
|
|
* but will wait for changes from D5559 to get in first. */
|
|
|
|
|
if (GS((*id_pointer)->name) == ID_GR) {
|
|
|
|
|
Collection *collection = (Collection *)*id_pointer;
|
|
|
|
|
if (collection->flag & COLLECTION_IS_MASTER) {
|
2020-02-13 14:26:27 +01:00
|
|
|
/* We should never reach that point anymore, since master collection private ID should be
|
2020-03-11 12:47:25 +01:00
|
|
|
* properly tagged with IDWALK_CB_EMBEDDED. */
|
2022-05-17 15:11:30 +02:00
|
|
|
BLI_assert_unreachable();
|
2019-09-23 11:02:58 +02:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-13 12:56:10 +01:00
|
|
|
struct IDNameLib_Map *id_map = cb_data->user_data;
|
2019-09-23 11:02:58 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: Handling of usercount here is really bad, defining its own system...
|
2019-09-23 11:02:58 +02:00
|
|
|
* Will have to be refactored at some point, but that is not top priority task for now.
|
2020-03-07 00:05:27 +11:00
|
|
|
* And all user-counts are properly recomputed at the end of the undo management code anyway. */
|
2019-09-23 11:02:58 +02:00
|
|
|
*id_pointer = restore_pointer_by_name(
|
|
|
|
|
id_map, *id_pointer, (cb_flag & IDWALK_CB_USER_ONE) ? USER_REAL : USER_IGNORE);
|
|
|
|
|
|
|
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void lib_link_main_data_restore(struct IDNameLib_Map *id_map, Main *newmain)
|
|
|
|
|
{
|
|
|
|
|
ID *id;
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (newmain, id) {
|
|
|
|
|
BKE_library_foreach_ID_link(newmain, id, lib_link_main_data_restore_cb, id_map, IDWALK_NOP);
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
}
|
|
|
|
|
|
VR: Initial Virtual Reality support - Milestone 1, Scene Inspection
NOTE: While most of the milestone 1 goals are there, a few smaller features and
improvements are still to be done.
Big picture of this milestone: Initial, OpenXR-based virtual reality support
for users and foundation for advanced use cases.
Maniphest Task: https://developer.blender.org/T71347
The tasks contains more information about this milestone.
To be clear: This is not a feature rich VR implementation, it's focused on the
initial scene inspection use case. We intentionally focused on that, further
features like controller support are part of the next milestone.
- How to use?
Instructions on how to use this are here:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/How_to_Test
These will be updated and moved to a more official place (likely the manual) soon.
Currently Windows Mixed Reality and Oculus devices are usable. Valve/HTC
headsets don't support the OpenXR standard yet and hence, do not work with this
implementation.
---------------
This is the C-side implementation of the features added for initial VR
support as per milestone 1. A "VR Scene Inspection" Add-on will be
committed separately, to expose the VR functionality in the UI. It also
adds some further features for milestone 1, namely a landmarking system
(stored view locations in the VR space)
Main additions/features:
* Support for rendering viewports to an HMD, with good performance.
* Option to sync the VR view perspective with a fully interactive,
regular 3D View (VR-Mirror).
* Option to disable positional tracking. Keeps the current position (calculated
based on the VR eye center pose) when enabled while a VR session is running.
* Some regular viewport settings for the VR view
* RNA/Python-API to query and set VR session state information.
* WM-XR: Layer tying Ghost-XR to the Blender specific APIs/data
* wmSurface API: drawable, non-window container (manages Ghost-OpenGL and GPU
context)
* DNA/RNA for management of VR session settings
* `--debug-xr` and `--debug-xr-time` commandline options
* Utility batch & config file for using the Oculus runtime on Windows.
* Most VR data is runtime only. The exception is user settings which are saved
to files (`XrSessionSettings`).
* VR support can be disabled through the `WITH_XR_OPENXR` compiler flag.
For architecture and code documentation, see
https://wiki.blender.org/wiki/Source/Interface/XR.
---------------
A few thank you's:
* A huge shoutout to Ray Molenkamp for his help during the project - it would
have not been that successful without him!
* Sebastian Koenig and Simeon Conzendorf for testing and feedback!
* The reviewers, especially Brecht Van Lommel!
* Dalai Felinto for pushing and managing me to get this done ;)
* The OpenXR working group for providing an open standard. I think we're the
first bigger application to adopt OpenXR. Congratulations to them and
ourselves :)
This project started as a Google Summer of Code 2019 project - "Core Support of
Virtual Reality Headsets through OpenXR" (see
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/).
Some further information, including ideas for further improvements can be found
in the final GSoC report:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/Final_Report
Differential Revisions: D6193, D7098
Reviewed by: Brecht Van Lommel, Jeroen Bakker
2020-03-17 20:20:55 +01:00
|
|
|
static void lib_link_wm_xr_data_restore(struct IDNameLib_Map *id_map, wmXrData *xr_data)
|
|
|
|
|
{
|
|
|
|
|
xr_data->session_settings.base_pose_object = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)xr_data->session_settings.base_pose_object, USER_REAL);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-27 16:42:56 -02:00
|
|
|
static void lib_link_window_scene_data_restore(wmWindow *win, Scene *scene, ViewLayer *view_layer)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
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
|
|
|
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
|
|
|
|
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
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
|
|
|
if (sl->spacetype == SPACE_VIEW3D) {
|
|
|
|
|
View3D *v3d = (View3D *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
if (v3d->camera == NULL || v3d->scenelock) {
|
|
|
|
|
v3d->camera = scene->camera;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
if (v3d->localvd) {
|
2018-11-27 16:42:56 -02:00
|
|
|
Base *base = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
v3d->localvd->camera = scene->camera;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-13 17:44:51 +11:00
|
|
|
/* Local-view can become invalid during undo/redo steps,
|
2019-04-22 01:10:29 +10:00
|
|
|
* so we exit it when no could be found. */
|
2018-11-27 16:42:56 -02:00
|
|
|
for (base = view_layer->object_bases.first; base; base = base->next) {
|
2018-11-25 09:50:34 -02:00
|
|
|
if (base->local_view_bits & v3d->local_view_uuid) {
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
}
|
|
|
|
|
if (base == NULL) {
|
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
|
|
|
MEM_freeN(v3d->localvd);
|
2018-11-25 09:50:34 -02:00
|
|
|
v3d->localvd = NULL;
|
|
|
|
|
v3d->local_view_uuid = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-13 17:44:51 +11:00
|
|
|
/* Region-base storage is different depending if the space is active. */
|
2019-03-01 00:34:25 +01:00
|
|
|
ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
|
|
|
|
|
&sl->regionbase;
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (ARegion *, region, regionbase) {
|
2020-03-06 16:56:42 +01:00
|
|
|
if (region->regiontype == RGN_TYPE_WINDOW) {
|
|
|
|
|
RegionView3D *rv3d = region->regiondata;
|
2018-11-27 16:42:56 -02:00
|
|
|
if (rv3d->localvd) {
|
|
|
|
|
MEM_freeN(rv3d->localvd);
|
|
|
|
|
rv3d->localvd = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
}
|
2008-12-31 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map,
|
|
|
|
|
Main *newmain,
|
|
|
|
|
WorkSpaceLayout *layout)
|
|
|
|
|
{
|
|
|
|
|
bScreen *screen = BKE_workspace_layout_screen_get(layout);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
/* avoid conflicts with 2.8x branch */
|
|
|
|
|
{
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
|
|
|
|
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
2012-05-17 12:59:34 +00:00
|
|
|
if (sl->spacetype == SPACE_VIEW3D) {
|
|
|
|
|
View3D *v3d = (View3D *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL);
|
2020-03-17 11:32:03 +11:00
|
|
|
v3d->ob_center = restore_pointer_by_name(id_map, (ID *)v3d->ob_center, USER_REAL);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2019-02-16 16:42:11 +11:00
|
|
|
else if (sl->spacetype == SPACE_GRAPH) {
|
2019-02-16 10:16:16 +11:00
|
|
|
SpaceGraph *sipo = (SpaceGraph *)sl;
|
2012-05-17 12:59:34 +00:00
|
|
|
bDopeSheet *ads = sipo->ads;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-01-27 23:20:32 +00:00
|
|
|
if (ads) {
|
2016-06-07 16:07:13 +10:00
|
|
|
ads->source = restore_pointer_by_name(id_map, (ID *)ads->source, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (ads->filter_grp) {
|
2016-06-07 16:07:13 +10:00
|
|
|
ads->filter_grp = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)ads->filter_grp, USER_IGNORE);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2010-01-25 17:24:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-03 13:47:13 +00:00
|
|
|
/* force recalc of list of channels (i.e. includes calculating F-Curve colors)
|
|
|
|
|
* thus preventing the "black curves" problem post-undo
|
|
|
|
|
*/
|
2018-12-10 12:30:41 +11:00
|
|
|
sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR;
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2019-02-16 10:44:15 +11:00
|
|
|
else if (sl->spacetype == SPACE_PROPERTIES) {
|
|
|
|
|
SpaceProperties *sbuts = (SpaceProperties *)sl;
|
2016-06-07 16:07:13 +10:00
|
|
|
sbuts->pinid = restore_pointer_by_name(id_map, sbuts->pinid, USER_IGNORE);
|
2015-05-04 16:12:12 +10:00
|
|
|
if (sbuts->pinid == NULL) {
|
|
|
|
|
sbuts->flag &= ~SB_PIN_CONTEXT;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-05-08 19:44:53 +10:00
|
|
|
/* TODO: restore path pointers: T40046
|
2021-06-26 21:35:18 +10:00
|
|
|
* (complicated because this contains data pointers too, not just ID). */
|
2014-05-08 19:44:53 +10:00
|
|
|
MEM_SAFE_FREE(sbuts->path);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_FILE) {
|
|
|
|
|
SpaceFile *sfile = (SpaceFile *)sl;
|
|
|
|
|
sfile->op = NULL;
|
2020-12-14 13:50:36 +01:00
|
|
|
sfile->tags = FILE_TAG_REBUILD_MAIN_FILES;
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_ACTION) {
|
|
|
|
|
SpaceAction *saction = (SpaceAction *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
saction->action = restore_pointer_by_name(id_map, (ID *)saction->action, USER_REAL);
|
|
|
|
|
saction->ads.source = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)saction->ads.source, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (saction->ads.filter_grp) {
|
2016-06-07 16:07:13 +10:00
|
|
|
saction->ads.filter_grp = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)saction->ads.filter_grp, USER_IGNORE);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-17 17:06:07 +02:00
|
|
|
/* force recalc of list of channels, potentially updating the active action
|
2020-09-30 20:09:02 +10:00
|
|
|
* while we're at it (as it can only be updated that way) T28962.
|
2012-06-11 04:13:39 +00:00
|
|
|
*/
|
2018-12-10 11:46:36 +11:00
|
|
|
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_IMAGE) {
|
|
|
|
|
SpaceImage *sima = (SpaceImage *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
sima->image = restore_pointer_by_name(id_map, (ID *)sima->image, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-26 08:06:13 +00:00
|
|
|
/* this will be freed, not worth attempting to find same scene,
|
|
|
|
|
* since it gets initialized later */
|
|
|
|
|
sima->iuser.scene = NULL;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2016-08-26 12:54:49 +02:00
|
|
|
#if 0
|
2020-05-26 12:04:16 +02:00
|
|
|
/* Those are allocated and freed by space code, no need to handle them here. */
|
|
|
|
|
MEM_SAFE_FREE(sima->scopes.waveform_1);
|
|
|
|
|
MEM_SAFE_FREE(sima->scopes.waveform_2);
|
|
|
|
|
MEM_SAFE_FREE(sima->scopes.waveform_3);
|
|
|
|
|
MEM_SAFE_FREE(sima->scopes.vecscope);
|
2016-08-26 12:54:49 +02:00
|
|
|
#endif
|
2010-04-06 02:05:54 +00:00
|
|
|
sima->scopes.ok = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-04-05 06:52:27 +00:00
|
|
|
/* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
|
|
|
|
|
* so assume that here we're doing for undo only...
|
|
|
|
|
*/
|
2016-06-07 16:07:13 +10:00
|
|
|
sima->gpd = restore_pointer_by_name(id_map, (ID *)sima->gpd, USER_REAL);
|
|
|
|
|
sima->mask_info.mask = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)sima->mask_info.mask, USER_REAL);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2012-06-11 03:03:36 +00:00
|
|
|
else if (sl->spacetype == SPACE_SEQ) {
|
|
|
|
|
SpaceSeq *sseq = (SpaceSeq *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-11 03:03:36 +00:00
|
|
|
/* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
|
|
|
|
|
* so assume that here we're doing for undo only...
|
|
|
|
|
*/
|
2016-06-07 16:07:13 +10:00
|
|
|
sseq->gpd = restore_pointer_by_name(id_map, (ID *)sseq->gpd, USER_REAL);
|
2012-06-11 03:03:36 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_NLA) {
|
|
|
|
|
SpaceNla *snla = (SpaceNla *)sl;
|
|
|
|
|
bDopeSheet *ads = snla->ads;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-01-27 23:20:32 +00:00
|
|
|
if (ads) {
|
2016-06-07 16:07:13 +10:00
|
|
|
ads->source = restore_pointer_by_name(id_map, (ID *)ads->source, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (ads->filter_grp) {
|
2016-06-07 16:07:13 +10:00
|
|
|
ads->filter_grp = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)ads->filter_grp, USER_IGNORE);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_TEXT) {
|
|
|
|
|
SpaceText *st = (SpaceText *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-04 14:46:32 +02:00
|
|
|
st->text = restore_pointer_by_name(id_map, (ID *)st->text, USER_IGNORE);
|
2019-04-22 09:13:00 +10:00
|
|
|
if (st->text == NULL) {
|
2019-03-08 09:29:17 +11:00
|
|
|
st->text = newmain->texts.first;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_SCRIPT) {
|
|
|
|
|
SpaceScript *scpt = (SpaceScript *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
scpt->script = restore_pointer_by_name(id_map, (ID *)scpt->script, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-13 13:46:22 +10:00
|
|
|
// screen->script = NULL; /* 2.45 set to null, better re-run the script. */
|
2008-03-06 21:25:15 +00:00
|
|
|
if (scpt->script) {
|
2012-03-28 01:06:43 +00:00
|
|
|
SCRIPT_SET_NULL(scpt->script);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_OUTLINER) {
|
2020-08-07 11:47:23 -06:00
|
|
|
SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-07 11:47:23 -06:00
|
|
|
space_outliner->search_tse.id = restore_pointer_by_name(
|
|
|
|
|
id_map, space_outliner->search_tse.id, USER_IGNORE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-07 11:47:23 -06:00
|
|
|
if (space_outliner->treestore) {
|
2013-08-03 11:35:09 +00:00
|
|
|
TreeStoreElem *tselem;
|
|
|
|
|
BLI_mempool_iter iter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-07 11:47:23 -06:00
|
|
|
BLI_mempool_iternew(space_outliner->treestore, &iter);
|
2013-08-03 11:35:09 +00:00
|
|
|
while ((tselem = BLI_mempool_iterstep(&iter))) {
|
2019-04-29 22:05:11 +10:00
|
|
|
/* Do not try to restore pointers to drivers/sequence/etc.,
|
|
|
|
|
* can crash in undo case! */
|
2015-09-09 16:26:53 +02:00
|
|
|
if (TSE_IS_REAL_ID(tselem)) {
|
2016-06-07 16:07:13 +10:00
|
|
|
tselem->id = restore_pointer_by_name(id_map, tselem->id, USER_IGNORE);
|
2015-09-09 16:26:53 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tselem->id = NULL;
|
|
|
|
|
}
|
Version 1.0 of the new Outliner
The outliner is a hierarchical diagram displaying a list of data in Blender
and its dependencies. The 'databrowse' doesn't really show it, and Oops is
too chaotic still. And most of all, the former two don't offer much tools.
After discussions on irc, Matt came with this design proposal;
http://mke3.net/blender/interface/layout/outliner/
Which is closely followed for the implementation.
The current version only shows all 'library data' in Blender (objects,
meshes, ipos, etc) and not the 'direct data' such as vertex groups or NLA.
I decided to make it inside the Oopw window, as an option. You can find the
option in the "View" pulldown, or directly invoke it with ALT+SHIFT+F9
Here's a quick overview of the Outliner GUI:
- Header pulldown has options what it can show (Visible = in current layers)
- click on triangle arrow to open/close
- press AKEY to open/close all
- Leftmouse click on an item activates; and does based on type a couple of
extra things:
- activates a scene
- selects/activates the Object
- enters editmode (if clicked on Mesh, Curve, etc)
- shows the appropriate Shading buttons (Lamp, Material, Texture)
- sets the IpoWindow to the current IPO
- activates the Ipo-channel in an Action
- Selected and Active objects are drawn in its Theme selection color
- SHIFT+click on Object does extend-select
- Press DOTkey to get the current active data in center of view
TODO;
- rightmouse selection; for indicating operations like delete or duplicate
- showing more data types
- icon (re)design...
- lotsof options as described in Matts paper still...
2004-10-06 18:55:00 +00:00
|
|
|
}
|
2020-12-04 19:43:33 +01:00
|
|
|
/* rebuild hash table, because it depends on ids too */
|
|
|
|
|
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
|
Version 1.0 of the new Outliner
The outliner is a hierarchical diagram displaying a list of data in Blender
and its dependencies. The 'databrowse' doesn't really show it, and Oops is
too chaotic still. And most of all, the former two don't offer much tools.
After discussions on irc, Matt came with this design proposal;
http://mke3.net/blender/interface/layout/outliner/
Which is closely followed for the implementation.
The current version only shows all 'library data' in Blender (objects,
meshes, ipos, etc) and not the 'direct data' such as vertex groups or NLA.
I decided to make it inside the Oopw window, as an option. You can find the
option in the "View" pulldown, or directly invoke it with ALT+SHIFT+F9
Here's a quick overview of the Outliner GUI:
- Header pulldown has options what it can show (Visible = in current layers)
- click on triangle arrow to open/close
- press AKEY to open/close all
- Leftmouse click on an item activates; and does based on type a couple of
extra things:
- activates a scene
- selects/activates the Object
- enters editmode (if clicked on Mesh, Curve, etc)
- shows the appropriate Shading buttons (Lamp, Material, Texture)
- sets the IpoWindow to the current IPO
- activates the Ipo-channel in an Action
- Selected and Active objects are drawn in its Theme selection color
- SHIFT+click on Object does extend-select
- Press DOTkey to get the current active data in center of view
TODO;
- rightmouse selection; for indicating operations like delete or duplicate
- showing more data types
- icon (re)design...
- lotsof options as described in Matts paper still...
2004-10-06 18:55:00 +00:00
|
|
|
}
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_NODE) {
|
2018-11-30 14:51:16 +11:00
|
|
|
SpaceNode *snode = (SpaceNode *)sl;
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeTreePath *path, *path_next;
|
2013-04-17 15:55:10 +00:00
|
|
|
bNodeTree *ntree;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-04-17 15:55:10 +00:00
|
|
|
/* node tree can be stored locally in id too, link this first */
|
2016-06-07 16:07:13 +10:00
|
|
|
snode->id = restore_pointer_by_name(id_map, snode->id, USER_REAL);
|
|
|
|
|
snode->from = restore_pointer_by_name(id_map, snode->from, USER_IGNORE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-07-31 20:07:33 +02:00
|
|
|
ntree = snode->id ? ntreeFromID(snode->id) : NULL;
|
|
|
|
|
snode->nodetree = ntree ?
|
|
|
|
|
ntree :
|
|
|
|
|
restore_pointer_by_name(id_map, (ID *)snode->nodetree, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-04-17 15:55:10 +00:00
|
|
|
for (path = snode->treepath.first; path; path = path->next) {
|
|
|
|
|
if (path == snode->treepath.first) {
|
|
|
|
|
/* first nodetree in path is same as snode->nodetree */
|
|
|
|
|
path->nodetree = snode->nodetree;
|
|
|
|
|
}
|
2019-04-22 09:13:00 +10:00
|
|
|
else {
|
2018-11-30 14:51:16 +11:00
|
|
|
path->nodetree = restore_pointer_by_name(id_map, (ID *)path->nodetree, USER_REAL);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (!path->nodetree) {
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* remaining path entries are invalid, remove */
|
|
|
|
|
for (; path; path = path_next) {
|
|
|
|
|
path_next = path->next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_remlink(&snode->treepath, path);
|
|
|
|
|
MEM_freeN(path);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* edittree is just the last in the path,
|
|
|
|
|
* set this directly since the path may have been shortened above */
|
|
|
|
|
if (snode->treepath.last) {
|
|
|
|
|
path = snode->treepath.last;
|
|
|
|
|
snode->edittree = path->nodetree;
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
2019-04-22 09:13:00 +10:00
|
|
|
else {
|
2013-03-18 16:34:57 +00:00
|
|
|
snode->edittree = NULL;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
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
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
else if (sl->spacetype == SPACE_CLIP) {
|
|
|
|
|
SpaceClip *sclip = (SpaceClip *)sl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-07 16:07:13 +10:00
|
|
|
sclip->clip = restore_pointer_by_name(id_map, (ID *)sclip->clip, USER_REAL);
|
|
|
|
|
sclip->mask_info.mask = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)sclip->mask_info.mask, USER_REAL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
sclip->scopes.ok = 0;
|
|
|
|
|
}
|
2021-03-11 13:28:06 +01:00
|
|
|
else if (sl->spacetype == SPACE_SPREADSHEET) {
|
|
|
|
|
SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
|
|
|
|
|
|
2021-04-15 08:57:10 +02:00
|
|
|
LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
|
|
|
|
|
if (context->type == SPREADSHEET_CONTEXT_OBJECT) {
|
|
|
|
|
SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context;
|
|
|
|
|
object_context->object = restore_pointer_by_name(
|
|
|
|
|
id_map, (ID *)object_context->object, USER_IGNORE);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-11 13:28:06 +01:00
|
|
|
}
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
Fix (unreported) crash when undoing after ID deletion.
Yes, we do can undo an ID deletion now.
However, this requires extra care in UI 'remapping' to new IDs step
(when undoing, we do not fully reload the UI from saved .blend).
Otherwise, new UI (i.e. one from saved .blend file) might reference
IDs that where freed in old bmain (the one before the undo), we cannot
use those to get ID name then, that would be a nasty use-after-free!
To prevent this, we generate a GSet of all valid ID pointers at that
time (i.e. those found in both old and new Main's), and ensure any ID
we try to remap by its name is in that GSet. Otherwise, there is no
possible remapping, just return NULL.
2019-02-08 18:45:57 +01:00
|
|
|
void blo_lib_link_restore(Main *oldmain,
|
|
|
|
|
Main *newmain,
|
|
|
|
|
wmWindowManager *curwm,
|
|
|
|
|
Scene *curscene,
|
|
|
|
|
ViewLayer *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
|
|
|
{
|
2020-03-05 16:17:14 +01:00
|
|
|
struct IDNameLib_Map *id_map = BKE_main_idmap_create(
|
|
|
|
|
newmain, true, oldmain, MAIN_IDMAP_TYPE_NAME);
|
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
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (WorkSpace *, workspace, &newmain->workspaces) {
|
2020-05-26 20:32:21 +02:00
|
|
|
LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
|
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
|
|
|
lib_link_workspace_layout_restore(id_map, newmain, layout);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (wmWindow *, win, &curwm->windows) {
|
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
|
|
|
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
|
|
|
|
|
ID *workspace_id = (ID *)workspace;
|
|
|
|
|
Scene *oldscene = win->scene;
|
|
|
|
|
|
|
|
|
|
workspace = restore_pointer_by_name(id_map, workspace_id, USER_REAL);
|
|
|
|
|
BKE_workspace_active_set(win->workspace_hook, workspace);
|
|
|
|
|
win->scene = restore_pointer_by_name(id_map, (ID *)win->scene, USER_REAL);
|
|
|
|
|
if (win->scene == NULL) {
|
|
|
|
|
win->scene = curscene;
|
|
|
|
|
}
|
2018-07-04 13:00:46 +02:00
|
|
|
if (BKE_view_layer_find(win->scene, win->view_layer_name) == NULL) {
|
|
|
|
|
STRNCPY(win->view_layer_name, cur_view_layer->name);
|
|
|
|
|
}
|
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
|
|
|
BKE_workspace_active_set(win->workspace_hook, workspace);
|
|
|
|
|
|
|
|
|
|
/* keep cursor location through undo */
|
2019-02-26 00:58:35 +11:00
|
|
|
memcpy(&win->scene->cursor, &oldscene->cursor, sizeof(win->scene->cursor));
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: even though that function seems to redo part of what is done by
|
2019-09-23 11:02:58 +02:00
|
|
|
* `lib_link_workspace_layout_restore()` above, it seems to have a slightly different scope:
|
|
|
|
|
* while the former updates the whole UI pointers from Main db (going over all layouts of
|
|
|
|
|
* all workspaces), that one only focuses one current active screen, takes care of
|
|
|
|
|
* potential local view, and needs window's scene pointer to be final... */
|
2018-11-27 16:42:56 -02:00
|
|
|
lib_link_window_scene_data_restore(win, win->scene, 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
|
|
|
|
|
|
|
|
BLI_assert(win->screen == NULL);
|
|
|
|
|
}
|
2012-02-03 13:08:44 +00:00
|
|
|
|
VR: Initial Virtual Reality support - Milestone 1, Scene Inspection
NOTE: While most of the milestone 1 goals are there, a few smaller features and
improvements are still to be done.
Big picture of this milestone: Initial, OpenXR-based virtual reality support
for users and foundation for advanced use cases.
Maniphest Task: https://developer.blender.org/T71347
The tasks contains more information about this milestone.
To be clear: This is not a feature rich VR implementation, it's focused on the
initial scene inspection use case. We intentionally focused on that, further
features like controller support are part of the next milestone.
- How to use?
Instructions on how to use this are here:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/How_to_Test
These will be updated and moved to a more official place (likely the manual) soon.
Currently Windows Mixed Reality and Oculus devices are usable. Valve/HTC
headsets don't support the OpenXR standard yet and hence, do not work with this
implementation.
---------------
This is the C-side implementation of the features added for initial VR
support as per milestone 1. A "VR Scene Inspection" Add-on will be
committed separately, to expose the VR functionality in the UI. It also
adds some further features for milestone 1, namely a landmarking system
(stored view locations in the VR space)
Main additions/features:
* Support for rendering viewports to an HMD, with good performance.
* Option to sync the VR view perspective with a fully interactive,
regular 3D View (VR-Mirror).
* Option to disable positional tracking. Keeps the current position (calculated
based on the VR eye center pose) when enabled while a VR session is running.
* Some regular viewport settings for the VR view
* RNA/Python-API to query and set VR session state information.
* WM-XR: Layer tying Ghost-XR to the Blender specific APIs/data
* wmSurface API: drawable, non-window container (manages Ghost-OpenGL and GPU
context)
* DNA/RNA for management of VR session settings
* `--debug-xr` and `--debug-xr-time` commandline options
* Utility batch & config file for using the Oculus runtime on Windows.
* Most VR data is runtime only. The exception is user settings which are saved
to files (`XrSessionSettings`).
* VR support can be disabled through the `WITH_XR_OPENXR` compiler flag.
For architecture and code documentation, see
https://wiki.blender.org/wiki/Source/Interface/XR.
---------------
A few thank you's:
* A huge shoutout to Ray Molenkamp for his help during the project - it would
have not been that successful without him!
* Sebastian Koenig and Simeon Conzendorf for testing and feedback!
* The reviewers, especially Brecht Van Lommel!
* Dalai Felinto for pushing and managing me to get this done ;)
* The OpenXR working group for providing an open standard. I think we're the
first bigger application to adopt OpenXR. Congratulations to them and
ourselves :)
This project started as a Google Summer of Code 2019 project - "Core Support of
Virtual Reality Headsets through OpenXR" (see
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/).
Some further information, including ideas for further improvements can be found
in the final GSoC report:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/Final_Report
Differential Revisions: D6193, D7098
Reviewed by: Brecht Van Lommel, Jeroen Bakker
2020-03-17 20:20:55 +01:00
|
|
|
lib_link_wm_xr_data_restore(id_map, &curwm->xr);
|
|
|
|
|
|
2019-09-23 11:02:58 +02:00
|
|
|
/* Restore all ID pointers in Main database itself
|
2019-10-10 10:25:46 +11:00
|
|
|
* (especially IDProperties might point to some word-space of other 'weirdly unchanged' ID
|
2019-09-23 11:02:58 +02:00
|
|
|
* pointers, see T69146).
|
2019-10-10 10:25:46 +11:00
|
|
|
* Note that this will re-apply again a few pointers in workspaces or so,
|
2019-09-23 11:02:58 +02:00
|
|
|
* but since we are remapping final ones already set above,
|
|
|
|
|
* that is just some minor harmless double-processing. */
|
|
|
|
|
lib_link_main_data_restore(id_map, newmain);
|
|
|
|
|
|
2012-02-03 13:08:44 +00:00
|
|
|
/* update IDs stored in all possible clipboards */
|
2016-06-07 16:07:13 +10:00
|
|
|
lib_link_clipboard_restore(id_map);
|
|
|
|
|
|
|
|
|
|
BKE_main_idmap_destroy(id_map);
|
2004-09-05 13:43:51 +00: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
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
/* check if the library was already read */
|
2012-05-25 17:13:30 +00:00
|
|
|
for (newmain = fd->mainlist->first; newmain; newmain = newmain->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (newmain->curlib) {
|
2020-06-23 09:54:07 +10:00
|
|
|
if (BLI_path_cmp(newmain->curlib->filepath_abs, lib->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,
|
2012-10-26 17:32:50 +00:00
|
|
|
TIP_("Library '%s', '%s' had multiple instances, save and reload!"),
|
2020-06-23 09:54:14 +10:00
|
|
|
lib->filepath,
|
2020-06-23 09:54:07 +10:00
|
|
|
lib->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);
|
|
|
|
|
/* 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.
|
2018-02-13 20:58:40 +01:00
|
|
|
* See also T53977 for reproducible case. */
|
|
|
|
|
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:07 +10:00
|
|
|
/* Make sure we have full path in lib->filepath_abs */
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_strncpy(lib->filepath_abs, lib->filepath, sizeof(lib->filepath));
|
2020-06-23 09:54:07 +10:00
|
|
|
BLI_path_normalize(fd->relabase, lib->filepath_abs);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-06-23 09:54:14 +10:00
|
|
|
// printf("direct_link_library: filepath %s\n", lib->filepath);
|
|
|
|
|
// printf("direct_link_library: filepath_abs %s\n", lib->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
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
lib->parent = NULL;
|
2020-05-28 12:13:16 +02:00
|
|
|
|
|
|
|
|
id_us_ensure_real(&lib->id);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-26 15:44:56 +02:00
|
|
|
static void lib_link_library(BlendLibReader *UNUSED(reader), Library *UNUSED(lib))
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2008-02-02 11:19:34 +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. */
|
2012-05-17 12:59:34 +00:00
|
|
|
if (basepath == NULL || 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
|
2020-09-30 20:09:02 +10:00
|
|
|
* link into an unsaved blend file. See T27405.
|
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)) {
|
|
|
|
|
BLI_strncpy(lib->filepath, lib->filepath_abs, sizeof(lib->filepath));
|
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,
|
2019-04-22 01:10:29 +10:00
|
|
|
* relative to the blend file since indirectly linked libs will be
|
|
|
|
|
* 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? */
|
|
|
|
|
BLI_strncpy(lib->filepath, lib->filepath_abs, sizeof(lib->filepath));
|
|
|
|
|
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
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2019-08-12 11:54:37 +02:00
|
|
|
static ID *create_placeholder(Main *mainvar, const short idcode, const char *idname, const int tag)
|
|
|
|
|
{
|
|
|
|
|
ListBase *lb = which_libbase(mainvar, idcode);
|
|
|
|
|
ID *ph_id = BKE_libblock_alloc_notest(idcode);
|
|
|
|
|
|
|
|
|
|
*((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;
|
|
|
|
|
|
|
|
|
|
BLI_addtail(lb, ph_id);
|
2019-12-19 21:58:59 +01:00
|
|
|
id_sort_by_name(lb, ph_id, NULL);
|
2019-08-12 11:54:37 +02:00
|
|
|
|
2021-06-30 15:19:35 +02:00
|
|
|
if (mainvar->id_map != NULL) {
|
|
|
|
|
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) {
|
|
|
|
|
BKE_lib_libblock_session_uuid_ensure(ph_id);
|
|
|
|
|
}
|
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) {
|
2019-08-12 11:54:37 +02:00
|
|
|
ID *obdata = ob->data;
|
|
|
|
|
if (obdata != NULL && 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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
static const char *dataname(short id_code)
|
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-09-18 11:06:41 +10:00
|
|
|
switch ((ID_Type)id_code) {
|
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
|
|
|
case ID_OB:
|
|
|
|
|
return "Data from OB";
|
|
|
|
|
case ID_ME:
|
|
|
|
|
return "Data from ME";
|
|
|
|
|
case ID_IP:
|
|
|
|
|
return "Data from IP";
|
|
|
|
|
case ID_SCE:
|
|
|
|
|
return "Data from SCE";
|
|
|
|
|
case ID_MA:
|
|
|
|
|
return "Data from MA";
|
|
|
|
|
case ID_TE:
|
|
|
|
|
return "Data from TE";
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY:
|
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
|
|
|
return "Data from CU";
|
|
|
|
|
case ID_GR:
|
|
|
|
|
return "Data from GR";
|
|
|
|
|
case ID_AR:
|
|
|
|
|
return "Data from AR";
|
|
|
|
|
case ID_AC:
|
|
|
|
|
return "Data from AC";
|
|
|
|
|
case ID_LI:
|
|
|
|
|
return "Data from LI";
|
|
|
|
|
case ID_MB:
|
|
|
|
|
return "Data from MB";
|
|
|
|
|
case ID_IM:
|
|
|
|
|
return "Data from IM";
|
|
|
|
|
case ID_LT:
|
|
|
|
|
return "Data from LT";
|
|
|
|
|
case ID_LA:
|
|
|
|
|
return "Data from LA";
|
|
|
|
|
case ID_CA:
|
|
|
|
|
return "Data from CA";
|
|
|
|
|
case ID_KE:
|
|
|
|
|
return "Data from KE";
|
|
|
|
|
case ID_WO:
|
|
|
|
|
return "Data from WO";
|
|
|
|
|
case ID_SCR:
|
|
|
|
|
return "Data from SCR";
|
|
|
|
|
case ID_VF:
|
|
|
|
|
return "Data from VF";
|
2018-03-23 11:51:19 +01:00
|
|
|
case ID_TXT:
|
|
|
|
|
return "Data from TXT";
|
2011-08-01 11:44:20 +00:00
|
|
|
case ID_SPK:
|
|
|
|
|
return "Data from SPK";
|
2017-06-12 20:59:54 +10:00
|
|
|
case ID_LP:
|
|
|
|
|
return "Data from LP";
|
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
|
|
|
case ID_SO:
|
|
|
|
|
return "Data from SO";
|
Brush Datablock:
- Added a new Brush datablock, only used by image paint, but intended
to be used in texture paint, vertex paint, weight paint and sculpt
mode also.
- Being a datablock, these brushes can be saved, appended and linked.
They have a fake user by default, to make sure they are saved even if
not selected.
Image Painting:
- Replaced the img module with C code in imagepaint.c
- Airbrush is no longer a separate tool, but rather an option that can
be used for soften, smear and clone also.
- Blend modes mix, add, subtract, multiply, darken and lighten have been
added, code taken directly from vertex paint.
Note to project files maintainers:
- The img module was removed from SCons and Makefiles, and this should
be done in other build systems also. I'll wait to remove the module
from cvs, to not break compilation.
2006-07-26 22:29:23 +00:00
|
|
|
case ID_NT:
|
|
|
|
|
return "Data from NT";
|
|
|
|
|
case ID_BR:
|
|
|
|
|
return "Data from BR";
|
2016-12-28 17:30:58 +01:00
|
|
|
case ID_PA:
|
|
|
|
|
return "Data from PA";
|
2014-07-21 12:02:05 +02:00
|
|
|
case ID_PAL:
|
|
|
|
|
return "Data from PAL";
|
|
|
|
|
case ID_PC:
|
|
|
|
|
return "Data from PCRV";
|
2.5
Patch from Joshua, converting Grease Pencil to 2.5.
All GP data now is an ID block, allowing re-use, link and append.
For better contextual control within 2.5, these GP ID's will get
linked to actual data, like NodeTrees, Scenes, Images or Objects.
That will ensure Undo works, and opens up exciting new use cases
as well. :)
Patch note: on reading files, GPencils linked from editors will
get moved to the main library, using standard naming (indicating
where it was used), and with "Fake User" set. That way the user
can manually relink the pencils where appropriate.
We can check on just linking GP to some default, like 3d window
pencils to Scene? Nice to experiment with.
Notes for Joshua:
- for reading old GPencil, it has to use old code as well, meaning
to tread data as "indirect data, within another ID".
- Saving ID data means the chunk in file BHead needs the ID_GD code,
and not "DATA", which indicates 'indirect data'. That's the file
format spec.
- I've added do_versions_gpencil_2_50(), feel free to further tweak
things here, like linking things to scene or so.
- Formerly GPencil saved 2.50 files won't convert gpencil
2009-04-20 10:13:55 +00:00
|
|
|
case ID_GD:
|
|
|
|
|
return "Data from GD";
|
2013-09-11 04:14:27 +00:00
|
|
|
case ID_WM:
|
|
|
|
|
return "Data from WM";
|
2011-11-07 12:55:18 +00:00
|
|
|
case ID_MC:
|
|
|
|
|
return "Data from MC";
|
2013-09-11 04:14:27 +00:00
|
|
|
case ID_MSK:
|
|
|
|
|
return "Data from MSK";
|
2010-06-25 22:45:42 +00:00
|
|
|
case ID_LS:
|
|
|
|
|
return "Data from LS";
|
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
|
|
|
case ID_CF:
|
|
|
|
|
return "Data from CF";
|
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
|
|
|
case ID_WS:
|
|
|
|
|
return "Data from WS";
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case ID_CV:
|
2020-03-17 14:41:48 +01:00
|
|
|
return "Data from HA";
|
|
|
|
|
case ID_PT:
|
|
|
|
|
return "Data from PT";
|
|
|
|
|
case ID_VO:
|
|
|
|
|
return "Data from VO";
|
2020-04-20 10:37:38 +02:00
|
|
|
case ID_SIM:
|
|
|
|
|
return "Data from SIM";
|
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
|
|
|
}
|
|
|
|
|
return "Data from Lib Block";
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
2020-08-28 13:05:48 +02:00
|
|
|
if (id_type->blend_read_data != NULL) {
|
|
|
|
|
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. */
|
|
|
|
|
if (id_type->foreach_cache != NULL) {
|
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
|
|
|
|
2018-11-30 14:51:16 +11:00
|
|
|
while (bhead && bhead->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
|
2020-07-21 12:24:50 +10:00
|
|
|
{
|
|
|
|
|
const short *sp = fd->filesdna->structs[bhead->SDNAnr];
|
|
|
|
|
allocname = fd->filesdna->types[sp[0]];
|
|
|
|
|
size_t allocname_size = strlen(allocname) + 1;
|
|
|
|
|
char *allocname_buf = malloc(allocname_size);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
while (bhead && bhead->code == DATA) {
|
|
|
|
|
if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
/* For undo, restore matching library datablock from the old main. */
|
2020-04-03 13:34:12 +02:00
|
|
|
static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const ID *id)
|
|
|
|
|
{
|
|
|
|
|
/* In undo case, most libs and linked data should be kept as is from previous state
|
|
|
|
|
* (see BLO_read_from_memfile).
|
|
|
|
|
* However, some needed by the snapshot being read may have been removed in previous one,
|
|
|
|
|
* and would go missing.
|
|
|
|
|
* This leads e.g. to disappearing objects in some undo/redo case, see T34446.
|
|
|
|
|
* 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
|
|
|
|
|
|
|
|
Main *libmain = fd->old_mainlist->first;
|
|
|
|
|
/* Skip oldmain itself... */
|
|
|
|
|
for (libmain = libmain->next; libmain; libmain = libmain->next) {
|
|
|
|
|
if (libmain->curlib && STREQ(id->name, libmain->curlib->id.name)) {
|
|
|
|
|
Main *oldmain = fd->old_mainlist->first;
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
" compare with %s -> match",
|
|
|
|
|
libmain->curlib ? libmain->curlib->id.name : "<NULL>");
|
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. */
|
|
|
|
|
BLI_remlink(fd->old_mainlist, libmain);
|
|
|
|
|
BLI_remlink_safe(&oldmain->libraries, libmain->curlib);
|
|
|
|
|
BLI_addtail(fd->mainlist, libmain);
|
|
|
|
|
BLI_addtail(&main->libraries, libmain->curlib);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
" compare with %s -> NO match",
|
|
|
|
|
libmain->curlib ? libmain->curlib->id.name : "<NULL>");
|
2020-04-03 13:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
/* For undo, restore existing linked datablock from the old main. */
|
2020-04-03 13:34:12 +02:00
|
|
|
static bool read_libblock_undo_restore_linked(FileData *fd, Main *main, const ID *id, BHead *bhead)
|
|
|
|
|
{
|
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
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
ID *id_old = BKE_libblock_find_name(main, GS(id->name), id->name + 2);
|
|
|
|
|
if (id_old != NULL) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
" from %s (%s): found",
|
|
|
|
|
main->curlib ? main->curlib->id.name : "<NULL>",
|
|
|
|
|
main->curlib ? main->curlib->filepath : "<NULL>");
|
2020-04-03 14:31:05 +02:00
|
|
|
/* Even though we found our linked ID, there is no guarantee its address
|
|
|
|
|
* is still the same. */
|
|
|
|
|
if (id_old != bhead->old) {
|
|
|
|
|
oldnewmap_insert(fd->libmap, bhead->old, id_old, GS(id_old->name));
|
2020-04-03 13:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
/* No need to do anything else for ID_LINK_PLACEHOLDER, it's assumed
|
|
|
|
|
* already present in its lib's main. */
|
2020-04-03 13:34:12 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
" from %s (%s): NOT found",
|
|
|
|
|
main->curlib ? main->curlib->id.name : "<NULL>",
|
|
|
|
|
main->curlib ? main->curlib->filepath : "<NULL>");
|
2020-04-03 13:34:12 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 14:31:05 +02:00
|
|
|
/* For undo, restore unchanged datablock from old main. */
|
|
|
|
|
static void read_libblock_undo_restore_identical(
|
2020-04-04 19:30:42 +02:00
|
|
|
FileData *fd, Main *main, const ID *UNUSED(id), ID *id_old, const int tag)
|
2020-04-03 14:31:05 +02:00
|
|
|
{
|
|
|
|
|
BLI_assert((fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0);
|
|
|
|
|
BLI_assert(id_old != NULL);
|
|
|
|
|
|
2020-05-20 10:39:50 +02:00
|
|
|
/* Some tags need to be preserved here. */
|
|
|
|
|
id_old->tag = tag | (id_old->tag & LIB_TAG_EXTRAUSER);
|
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... */
|
|
|
|
|
id_old->newid = NULL;
|
|
|
|
|
id_old->orig_id = NULL;
|
|
|
|
|
|
|
|
|
|
const short idcode = GS(id_old->name);
|
|
|
|
|
Main *old_bmain = fd->old_mainlist->first;
|
|
|
|
|
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
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
BLI_assert(id_old != NULL);
|
|
|
|
|
|
|
|
|
|
const short idcode = GS(id->name);
|
|
|
|
|
|
|
|
|
|
Main *old_bmain = fd->old_mainlist->first;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
/* We do not need any remapping from this call here, since no ID pointer is valid in the data
|
|
|
|
|
* currently (they are all pointing to old addresses, and need to go through `lib_link`
|
|
|
|
|
* process). So we can pass NULL for the Main pointer parameter. */
|
|
|
|
|
BKE_lib_id_swap_full(NULL, id, id_old);
|
|
|
|
|
|
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;
|
|
|
|
|
|
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(
|
|
|
|
|
FileData *fd, Main *main, BHead *bhead, const int tag, ID **r_id_old)
|
|
|
|
|
{
|
|
|
|
|
/* Get pointer to memory of new ID that we will be reading. */
|
|
|
|
|
const ID *id = peek_struct_undo(fd, bhead);
|
|
|
|
|
const short idcode = GS(id->name);
|
|
|
|
|
|
|
|
|
|
if (bhead->code == ID_LI) {
|
|
|
|
|
/* Restore library datablock. */
|
|
|
|
|
if (read_libblock_undo_restore_library(fd, main, id)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (bhead->code == ID_LINK_PLACEHOLDER) {
|
|
|
|
|
/* Restore linked datablock. */
|
|
|
|
|
if (read_libblock_undo_restore_linked(fd, main, id, bhead)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ELEM(idcode, ID_WM, ID_SCR, ID_WS)) {
|
|
|
|
|
/* Skip reading any UI datablocks, existing ones are kept. We don't
|
|
|
|
|
* support pointers from other datablocks to UI datablocks so those
|
|
|
|
|
* we also don't put UI datablocks in fd->libmap. */
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore local datablocks. */
|
|
|
|
|
ID *id_old = NULL;
|
|
|
|
|
const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
|
|
|
|
|
if (do_partial_undo && (bhead->code != ID_LINK_PLACEHOLDER)) {
|
|
|
|
|
/* This code should only ever be reached for local data-blocks. */
|
|
|
|
|
BLI_assert(main->curlib == NULL);
|
|
|
|
|
|
|
|
|
|
/* Find the 'current' existing ID we want to reuse instead of the one we
|
|
|
|
|
* would read from the undo memfile. */
|
|
|
|
|
BLI_assert(fd->old_idmap != NULL);
|
|
|
|
|
id_old = BKE_main_idmap_lookup_uuid(fd->old_idmap, id->session_uuid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (id_old != NULL && read_libblock_is_identical(fd, bhead)) {
|
|
|
|
|
/* Local datablock was unchanged, restore from the old main. */
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO,
|
|
|
|
|
2,
|
|
|
|
|
"UNDO: read %s (uuid %u) -> keep identical datablock",
|
|
|
|
|
id->name,
|
|
|
|
|
id->session_uuid);
|
2020-04-04 17:38:07 +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 new. */
|
2020-04-29 18:11:33 +02:00
|
|
|
/* Also do not add LIB_TAG_NEED_LINK, those IDs will never be re-liblinked, hence that tag will
|
2020-05-09 17:15:25 +10:00
|
|
|
* never be cleared, leading to critical issue in link/append code. */
|
2020-04-29 18:11:33 +02:00
|
|
|
const int id_tag = tag | LIB_TAG_UNDO_OLD_ID_REUSED;
|
2020-04-04 17:38:07 +02:00
|
|
|
read_libblock_undo_restore_identical(fd, main, id, id_old, id_tag);
|
|
|
|
|
|
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 anymore, so no need to store this info here. */
|
2020-04-04 17:38:07 +02:00
|
|
|
oldnewmap_insert(fd->libmap, bhead->old, id_old, bhead->code);
|
|
|
|
|
|
|
|
|
|
*r_id_old = id_old;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
if (id_old != NULL) {
|
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,
|
|
|
|
|
"UNDO: read %s (uuid %u) -> read to old existing address",
|
|
|
|
|
id->name,
|
|
|
|
|
id->session_uuid);
|
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(
|
|
|
|
|
&LOG_UNDO, 2, "UNDO: read %s (uuid %u) -> read at new address", id->name, id->session_uuid);
|
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,
|
|
|
|
|
const int tag,
|
|
|
|
|
const bool placeholder_set_indirect_extern,
|
|
|
|
|
ID **r_id)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
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. */
|
|
|
|
|
ID *id_old = NULL;
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
2020-04-04 17:38:07 +02:00
|
|
|
if (read_libblock_undo_restore(fd, main, bhead, tag, &id_old)) {
|
|
|
|
|
if (r_id) {
|
|
|
|
|
*r_id = id_old;
|
|
|
|
|
}
|
2021-06-30 15:19:35 +02:00
|
|
|
if (main->id_map != NULL) {
|
|
|
|
|
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. */
|
|
|
|
|
ID *id = read_struct(fd, bhead, "lib block");
|
|
|
|
|
if (id == NULL) {
|
2020-04-04 17:38:07 +02:00
|
|
|
if (r_id) {
|
|
|
|
|
*r_id = NULL;
|
|
|
|
|
}
|
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);
|
|
|
|
|
if (lb == NULL) {
|
|
|
|
|
/* 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) {
|
|
|
|
|
*r_id = NULL;
|
|
|
|
|
}
|
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. */
|
2020-04-04 17:38:07 +02:00
|
|
|
ID *id_target = id_old ? id_old : id;
|
2020-04-03 13:34:12 +02:00
|
|
|
oldnewmap_insert(fd->libmap, 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. */
|
|
|
|
|
int id_tag = 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
|
|
|
|
|
|
|
|
if (main->id_map != NULL) {
|
|
|
|
|
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. */
|
|
|
|
|
const char *allocname = dataname(idcode);
|
|
|
|
|
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);
|
2020-01-28 15:46:51 +01:00
|
|
|
if (r_id != NULL) {
|
|
|
|
|
*r_id = NULL;
|
|
|
|
|
}
|
2013-05-06 11:23:13 +00:00
|
|
|
}
|
2020-04-04 17:38:07 +02:00
|
|
|
else if (id_old) {
|
2020-04-03 14:31:05 +02:00
|
|
|
/* For undo, store contents read into id at id_old. */
|
|
|
|
|
read_libblock_undo_restore_at_old_address(fd, main, id, id_old);
|
2021-06-30 15:19:35 +02:00
|
|
|
|
|
|
|
|
if (main->id_map != NULL) {
|
|
|
|
|
BKE_main_idmap_insert_id(main->id_map, id_old);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (main->id_map != NULL) {
|
|
|
|
|
BKE_main_idmap_insert_id(main->id_map, id);
|
2020-03-17 12:29:36 +01: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};
|
|
|
|
|
BLO_read_data_address(&reader, r_asset_data);
|
|
|
|
|
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
|
|
|
{
|
2012-05-17 12:59:34 +00:00
|
|
|
FileGlobal *fg = read_struct(fd, bhead, "Global");
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2007-12-24 18:53:37 +00:00
|
|
|
/* copy to bfd handle */
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->main->subversionfile = fg->subversion;
|
|
|
|
|
bfd->main->minversionfile = fg->minversion;
|
|
|
|
|
bfd->main->minsubversionfile = fg->minsubversion;
|
2013-11-15 17:11:59 +06:00
|
|
|
bfd->main->build_commit_timestamp = fg->build_commit_timestamp;
|
2013-11-04 13:21:39 +00:00
|
|
|
BLI_strncpy(bfd->main->build_hash, fg->build_hash, sizeof(bfd->main->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;
|
2021-12-13 16:22:19 +11:00
|
|
|
STRNCPY(bfd->filepath, fg->filepath);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-12-13 16:22:19 +11:00
|
|
|
/* Error in 2.65 and older: `main->filepath` was not set if you save from startup
|
2019-04-22 01:10:29 +10:00
|
|
|
* (not after loading file). */
|
2021-12-13 16:22:19 +11:00
|
|
|
if (bfd->filepath[0] == 0) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->fileversion < 265 || (fd->fileversion == 265 && fg->subversion < 1)) {
|
2021-03-15 13:30:26 +11:00
|
|
|
if ((G.fileflags & G_FILE_RECOVER_READ) == 0) {
|
2021-12-13 16:22:19 +11:00
|
|
|
STRNCPY(bfd->filepath, BKE_main_blendfile_path(bfd->main));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-12-13 16:22:19 +11:00
|
|
|
/* early 2.50 version patch - filepath not in FileGlobal struct at all */
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->fileversion <= 250) {
|
2021-12-13 16:22:19 +11:00
|
|
|
STRNCPY(bfd->filepath, BKE_main_blendfile_path(bfd->main));
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2012-12-19 16:45:47 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-03-15 13:30:26 +11:00
|
|
|
if (G.fileflags & G_FILE_RECOVER_READ) {
|
2021-12-13 16:22:19 +11:00
|
|
|
BLI_strncpy(fd->relabase, fg->filepath, sizeof(fd->relabase));
|
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)
|
|
|
|
|
{
|
2020-09-30 14:49:42 +02:00
|
|
|
bfd->cur_view_layer = blo_read_get_new_globaldata_address(fd, bfd->cur_view_layer);
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd->curscreen = newlibadr(fd, NULL, bfd->curscreen);
|
|
|
|
|
bfd->curscene = newlibadr(fd, NULL, bfd->curscene);
|
2004-09-05 13:43:51 +00:00
|
|
|
/* this happens in files older than 2.35 */
|
2012-05-17 12:59:34 +00:00
|
|
|
if (bfd->curscene == NULL) {
|
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
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Versioning
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-10-02 23:23:57 +10:00
|
|
|
static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
|
2013-03-17 14:38:58 +00:00
|
|
|
{
|
|
|
|
|
UserDef *user = bfd->user;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (user == NULL) {
|
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;
|
2015-05-01 15:52:53 +02:00
|
|
|
struct tm *tm = (temp_time) ? gmtime(&temp_time) : NULL;
|
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 {
|
2015-05-01 15:52:53 +02:00
|
|
|
BLI_strncpy(build_commit_datetime, "unknown", sizeof(build_commit_datetime));
|
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
|
|
|
|
2012-05-04 15:42:49 +00:00
|
|
|
blo_do_versions_pre250(fd, lib, main);
|
|
|
|
|
blo_do_versions_250(fd, lib, main);
|
2013-11-29 23:16:13 +06:00
|
|
|
blo_do_versions_260(fd, lib, main);
|
2014-03-06 04:33:15 +11:00
|
|
|
blo_do_versions_270(fd, lib, main);
|
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
|
|
|
blo_do_versions_280(fd, lib, main);
|
2020-04-16 18:10:21 +10:00
|
|
|
blo_do_versions_290(fd, lib, main);
|
2021-04-20 17:08:31 +02:00
|
|
|
blo_do_versions_300(fd, lib, main);
|
2019-04-20 20:25:23 +02:00
|
|
|
blo_do_versions_cycles(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
|
|
|
}
|
|
|
|
|
|
2019-08-13 00:11:36 +02:00
|
|
|
static void do_versions_after_linking(Main *main, ReportList *reports)
|
2010-06-19 10:50:23 +00:00
|
|
|
{
|
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;
|
|
|
|
|
|
2019-04-20 20:25:20 +02:00
|
|
|
do_versions_after_linking_250(main);
|
|
|
|
|
do_versions_after_linking_260(main);
|
2016-12-07 13:52:12 +01:00
|
|
|
do_versions_after_linking_270(main);
|
2019-08-13 00:11:36 +02:00
|
|
|
do_versions_after_linking_280(main, reports);
|
2020-05-26 12:04:16 +02:00
|
|
|
do_versions_after_linking_290(main, reports);
|
2021-04-20 17:08:31 +02:00
|
|
|
do_versions_after_linking_300(main, reports);
|
2019-04-20 20:25:23 +02:00
|
|
|
do_versions_after_linking_cycles(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)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
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-03-17 12:29:36 +01:00
|
|
|
const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
|
|
|
|
|
|
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) {
|
|
|
|
|
if ((id->tag & LIB_TAG_NEED_LINK) == 0) {
|
|
|
|
|
/* This ID does not need liblink, just skip to next one. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
if ((fd->flags & FD_FLAGS_IS_MEMFILE) && GS(id->name) == ID_WM) {
|
2020-02-05 16:18:17 +01:00
|
|
|
/* No load UI for undo memfiles.
|
|
|
|
|
* Only WM currently, SCR needs it still (see below), and so does WS? */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
if ((fd->flags & FD_FLAGS_IS_MEMFILE) && do_partial_undo &&
|
|
|
|
|
(id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) != 0) {
|
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. */
|
2020-03-17 12:29:36 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 14:40:47 +02:00
|
|
|
lib_link_id(&reader, id);
|
2020-02-05 16:18:17 +01:00
|
|
|
|
2020-08-28 13:05:48 +02:00
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
if (id_type->blend_read_lib != NULL) {
|
|
|
|
|
id_type->blend_read_lib(&reader, id);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 18:41:03 +01:00
|
|
|
if (GS(id->name) == ID_LI) {
|
|
|
|
|
lib_link_library(&reader, (Library *)id); /* Only init users. */
|
2020-02-05 16:18:17 +01: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. */
|
|
|
|
|
if (id_type->blend_read_undo_preserve != NULL && id->orig_id != NULL) {
|
|
|
|
|
id_type->blend_read_undo_preserve(&reader, id, id->orig_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
|
|
|
|
|
/* Cleanup `ID.orig_id`, this is now reserved for depsgraph/COW usage only. */
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
|
|
|
|
id->orig_id = NULL;
|
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.
|
|
|
|
|
*/
|
2021-02-04 15:21:29 +01:00
|
|
|
static void after_liblink_merged_bmain_process(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
/* We only expect a merged Main here, not a split one. */
|
|
|
|
|
BLI_assert((bmain->prev == NULL) && (bmain->next == NULL));
|
|
|
|
|
|
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. */
|
2020-02-05 16:18:17 +01:00
|
|
|
BLO_main_validate_shapekeys(bmain, NULL);
|
2019-05-22 22:57:16 +02:00
|
|
|
|
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
|
|
|
{
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_data_address(reader, &kmi->properties);
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &kmi->properties);
|
2012-05-17 12:59:34 +00:00
|
|
|
kmi->ptr = NULL;
|
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;
|
2018-11-30 14:51:16 +11:00
|
|
|
bfd->user = user = 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_;
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, &user->themes);
|
|
|
|
|
BLO_read_list(reader, &user->user_keymaps);
|
|
|
|
|
BLO_read_list(reader, &user->user_keyconfig_prefs);
|
|
|
|
|
BLO_read_list(reader, &user->user_menus);
|
|
|
|
|
BLO_read_list(reader, &user->addons);
|
|
|
|
|
BLO_read_list(reader, &user->autoexec_paths);
|
2020-12-14 13:39:41 +01:00
|
|
|
BLO_read_list(reader, &user->asset_libraries);
|
2015-04-06 10:40:12 -03:00
|
|
|
|
2020-08-21 14:39:18 +02:00
|
|
|
LISTBASE_FOREACH (wmKeyMap *, keymap, &user->user_keymaps) {
|
2018-11-30 14:51:16 +11:00
|
|
|
keymap->modal_items = NULL;
|
2012-03-24 02:51:46 +00:00
|
|
|
keymap->poll = NULL;
|
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
|
|
|
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_list(reader, &keymap->diff_items);
|
|
|
|
|
BLO_read_list(reader, &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) {
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_data_address(reader, &kmdi->remove_item);
|
|
|
|
|
BLO_read_data_address(reader, &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) {
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_data_address(reader, &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) {
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_list(reader, &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;
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_data_address(reader, &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) {
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_data_address(reader, &addon->prop);
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendDataRead(reader, &addon->prop);
|
2012-12-29 10:24:42 +00: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
|
|
|
/* XXX */
|
2018-11-30 14:51:16 +11:00
|
|
|
user->uifonts.first = user->uifonts.last = NULL;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-06-07 11:30:32 +02:00
|
|
|
BLO_read_list(reader, &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)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
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;
|
2012-05-25 17:13:30 +00:00
|
|
|
ListBase mainlist = {NULL, NULL};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-08-19 23:57:00 +02:00
|
|
|
if (fd->flags & FD_FLAGS_IS_MEMFILE) {
|
2021-06-23 14:23:54 +02:00
|
|
|
CLOG_INFO(&LOG_UNDO, 2, "UNDO: read step");
|
2020-04-04 19:30:42 +02:00
|
|
|
}
|
|
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
bfd = 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;
|
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);
|
|
|
|
|
bfd->main->blen_thumb = 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
|
|
|
|
2012-03-24 07:52:14 +00:00
|
|
|
while (bhead) {
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (bhead->code) {
|
2018-08-30 01:31:20 +10:00
|
|
|
case DATA:
|
|
|
|
|
case DNA1:
|
|
|
|
|
case TEST: /* used as preview since 2.5x */
|
|
|
|
|
case REND:
|
2019-02-22 10:31:17 +11:00
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
2018-08-30 01:31:20 +10:00
|
|
|
break;
|
|
|
|
|
case GLOB:
|
|
|
|
|
bhead = read_global(bfd, fd, bhead);
|
|
|
|
|
break;
|
|
|
|
|
case USER:
|
|
|
|
|
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;
|
|
|
|
|
case ENDB:
|
|
|
|
|
bhead = NULL;
|
|
|
|
|
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. */
|
|
|
|
|
Main *libmain = mainlist.last;
|
2019-09-16 14:52:06 +02:00
|
|
|
bhead = read_libblock(fd, libmain, bhead, 0, true, NULL);
|
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 {
|
2019-09-16 14:52:06 +02:00
|
|
|
bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, false, NULL);
|
2018-08-30 01:31:20 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-11-25 13:07:28 +00:00
|
|
|
/* do before read_libraries, but skip undo case */
|
2021-08-19 23:57:00 +02:00
|
|
|
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
|
2019-05-13 12:36:14 +10:00
|
|
|
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
|
|
|
|
|
do_versions(fd, NULL, bfd->main);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
|
2021-06-23 09:51:11 +02:00
|
|
|
fd->reports->duration.libraries = PIL_check_seconds_timer();
|
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);
|
2021-02-04 15:21:29 +01:00
|
|
|
after_liblink_merged_bmain_process(bfd->main);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
fd->reports->duration.libraries = PIL_check_seconds_timer() - fd->reports->duration.libraries;
|
|
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Skip in undo case. */
|
2021-08-19 23:57:00 +02:00
|
|
|
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
|
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);
|
2021-06-23 09:51:11 +02:00
|
|
|
do_versions_after_linking(mainvar, fd->reports->reports);
|
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
|
|
|
|
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. */
|
|
|
|
|
ntreeUpdateAllNew(bfd->main);
|
|
|
|
|
|
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
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Now that all our data-blocks are loaded,
|
|
|
|
|
* we can re-generate overrides from their references. */
|
2021-08-19 23:57:00 +02:00
|
|
|
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
|
2019-05-13 12:36:14 +10:00
|
|
|
/* Do not apply in undo case! */
|
2021-06-23 09:51:11 +02:00
|
|
|
fd->reports->duration.lib_overrides = PIL_check_seconds_timer();
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
fd->reports->duration.lib_overrides = PIL_check_seconds_timer() -
|
|
|
|
|
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
|
|
|
|
2019-05-13 12:36:14 +10:00
|
|
|
link_global(fd, bfd); /* as last */
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-29 16:47:32 +02:00
|
|
|
fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-30 15:19:35 +02:00
|
|
|
BLI_assert(bfd->main->id_map == NULL);
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
const struct BHeadSort *x1 = v1, *x2 = 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;
|
2012-08-04 19:34:38 +00:00
|
|
|
struct 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
|
|
|
|
2018-01-14 22:14:20 +01:00
|
|
|
bhs = fd->bheadmap = MEM_malloc_arrayN(tot, sizeof(struct 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
|
|
|
|
2012-08-04 19:34:38 +00:00
|
|
|
qsort(fd->bheadmap, tot, sizeof(struct 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) {
|
2009-10-20 16:43:25 +00:00
|
|
|
return NULL;
|
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
|
2020-05-26 12:04:16 +02:00
|
|
|
BHead* bhead;
|
2008-02-03 18:50:03 +00:00
|
|
|
#endif
|
2012-08-04 19:34:38 +00:00
|
|
|
struct BHeadSort *bhs, bhs_s;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (!old) {
|
2002-10-12 11:37:38 +00:00
|
|
|
return NULL;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2004-06-23 18:22:51 +00:00
|
|
|
|
2019-04-22 09:13:00 +10:00
|
|
|
if (fd->bheadmap == NULL) {
|
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;
|
2012-08-04 19:34:38 +00:00
|
|
|
bhs = bsearch(&bhs_s, fd->bheadmap, fd->tot_bheadmap, sizeof(struct 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
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
return BLI_ghash_lookup(fd->bhead_idname_hash, idname_full);
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
2015-03-11 00:05:14 +11:00
|
|
|
return NULL;
|
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
|
|
|
|
|
return BLI_ghash_lookup(fd->bhead_idname_hash, idname);
|
|
|
|
|
#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
|
|
|
}
|
|
|
|
|
|
2007-04-28 16:15:00 +00:00
|
|
|
static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2021-06-30 15:19:35 +02:00
|
|
|
if (mainvar->id_map == NULL) {
|
|
|
|
|
mainvar->id_map = BKE_main_idmap_create(mainvar, false, NULL, MAIN_IDMAP_TYPE_NAME);
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
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
|
|
|
{
|
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
|
|
|
FileData *fd = fdhandle;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
BHead *bhead = find_bhead(fd, old);
|
|
|
|
|
if (bhead == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (bhead->code == ID_LINK_PLACEHOLDER) {
|
2019-06-17 12:51:53 +10:00
|
|
|
/* Placeholder link to data-lock in another library. */
|
2019-02-27 19:25:21 +01:00
|
|
|
BHead *bheadlib = find_previous_lib(fd, bhead);
|
|
|
|
|
if (bheadlib == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
Library *lib = 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
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (libmain->curlib == NULL) {
|
|
|
|
|
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,
|
|
|
|
|
TIP_("LIB: Data refers to main .blend file: '%s' from %s"),
|
|
|
|
|
idname,
|
2020-06-23 09:54:07 +10:00
|
|
|
mainvar->curlib->filepath_abs);
|
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
|
|
|
ID *id = is_yet_read(fd, libmain, bhead);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (id == NULL) {
|
|
|
|
|
/* 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);
|
|
|
|
|
id_sort_by_name(which_libbase(libmain, GS(id->name)), id, id->prev);
|
|
|
|
|
|
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 */
|
|
|
|
|
libmain->curlib->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.
|
|
|
|
|
*/
|
|
|
|
|
oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-17 12:51:53 +10:00
|
|
|
/* If "id" is a real data-lock and not a placeholder, we need to
|
2019-02-27 19:25:21 +01:00
|
|
|
* update fd->libmap to replace ID_LINK_PLACEHOLDER with the real
|
|
|
|
|
* ID_* code.
|
|
|
|
|
*
|
|
|
|
|
* When the real ID is read this replacement happens for all
|
|
|
|
|
* libraries read so far, but not for libraries that have not been
|
|
|
|
|
* read yet at that point. */
|
|
|
|
|
change_link_placeholder_to_real_ID_pointer_fd(fd, bhead->old, id);
|
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
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
ID *id = is_yet_read(fd, mainvar, bhead);
|
|
|
|
|
if (id == NULL) {
|
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);
|
|
|
|
|
id_sort_by_name(which_libbase(mainvar, GS(id->name)), 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 */
|
2019-02-27 19:25:21 +01:00
|
|
|
oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
|
|
|
|
|
/* 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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-12 14:31:47 +02:00
|
|
|
static BLOExpandDoitCallback expand_doit;
|
2009-01-19 02:26:46 +00:00
|
|
|
|
2020-06-26 16:52:44 +02:00
|
|
|
static void expand_id(BlendExpander *expander, ID *id);
|
2020-02-06 16:25:15 +01:00
|
|
|
|
2020-06-26 16:52:44 +02:00
|
|
|
static void expand_id_embedded_id(BlendExpander *expander, ID *id)
|
2020-02-06 16:25:15 +01:00
|
|
|
{
|
|
|
|
|
/* Handle 'private IDs'. */
|
|
|
|
|
bNodeTree *nodetree = ntreeFromID(id);
|
|
|
|
|
if (nodetree != NULL) {
|
2020-06-26 16:52:44 +02:00
|
|
|
expand_id(expander, &nodetree->id);
|
2020-09-10 13:33:29 +02:00
|
|
|
ntreeBlendReadExpand(expander, nodetree);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GS(id->name) == ID_SCE) {
|
|
|
|
|
Scene *scene = (Scene *)id;
|
|
|
|
|
if (scene->master_collection != NULL) {
|
2020-06-26 16:52:44 +02:00
|
|
|
expand_id(expander, &scene->master_collection->id);
|
2020-10-29 19:28:21 +01:00
|
|
|
BKE_collection_blend_read_expand(expander, scene->master_collection);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 16:52:44 +02:00
|
|
|
static void expand_id(BlendExpander *expander, ID *id)
|
2020-02-06 16:25:15 +01:00
|
|
|
{
|
2020-08-28 13:18:24 +02:00
|
|
|
IDP_BlendReadExpand(expander, id->properties);
|
2020-02-06 16:25:15 +01:00
|
|
|
|
|
|
|
|
if (id->override_library) {
|
2020-06-26 16:52:44 +02:00
|
|
|
BLO_expand(expander, id->override_library->reference);
|
|
|
|
|
BLO_expand(expander, id->override_library->storage);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnimData *adt = BKE_animdata_from_id(id);
|
|
|
|
|
if (adt != NULL) {
|
2020-08-28 13:18:24 +02:00
|
|
|
BKE_animdata_blend_read_expand(expander, adt);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-26 16:52:44 +02:00
|
|
|
expand_id_embedded_id(expander, id);
|
2020-02-06 16:25:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-10-12 14:31:47 +02:00
|
|
|
void BLO_main_expander(BLOExpandDoitCallback expand_doit_func)
|
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
|
|
|
{
|
|
|
|
|
expand_doit = expand_doit_func;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_expand_main(void *fdhandle, Main *mainvar)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
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
|
|
|
FileData *fd = fdhandle;
|
2002-10-12 11:37:38 +00:00
|
|
|
ID *id;
|
2014-04-01 11:34:00 +11:00
|
|
|
int a;
|
|
|
|
|
bool do_it = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-26 16:52:44 +02:00
|
|
|
BlendExpander expander = {fd, mainvar};
|
|
|
|
|
|
2012-05-19 13:28:19 +00:00
|
|
|
while (do_it) {
|
2014-04-01 11:34:00 +11:00
|
|
|
do_it = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-17 12:59:34 +00:00
|
|
|
a = set_listbasepointers(mainvar, lbarray);
|
2012-03-24 07:52:14 +00:00
|
|
|
while (a--) {
|
2013-01-21 06:32:09 +00:00
|
|
|
id = lbarray[a]->first;
|
2012-03-24 07:52:14 +00:00
|
|
|
while (id) {
|
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
|
|
|
if (id->tag & LIB_TAG_NEED_EXPAND) {
|
2020-06-26 16:52:44 +02:00
|
|
|
expand_id(&expander, id);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-28 13:05:48 +02:00
|
|
|
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
|
|
|
|
if (id_type->blend_read_expand != NULL) {
|
|
|
|
|
id_type->blend_read_expand(&expander, id);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
do_it = true;
|
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_NEED_EXPAND;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
id = id->next;
|
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) {
|
|
|
|
|
id = is_yet_read(fd, mainl, bhead);
|
|
|
|
|
if (id == NULL) {
|
|
|
|
|
/* 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);
|
2019-12-19 21:58:59 +01:00
|
|
|
id_sort_by_name(lb, id, NULL);
|
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);
|
2015-03-11 00:05:14 +11:00
|
|
|
oldnewmap_insert(fd->libmap, 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(
|
|
|
|
|
mainl, idcode, name, force_indirect ? LIB_TAG_INDIRECT : LIB_TAG_EXTERN);
|
|
|
|
|
}
|
2015-03-11 00:05:14 +11:00
|
|
|
else {
|
|
|
|
|
id = NULL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-05-24 15:02:46 +00:00
|
|
|
/* if we found the id but the id is NULL, this is really bad */
|
2016-06-22 18:05:55 +02:00
|
|
|
BLI_assert(!((bhead != NULL) && (id == NULL)));
|
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,
|
|
|
|
|
const struct LibraryLink_Params *params)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)(*bh);
|
2020-09-08 15:32:43 +10:00
|
|
|
return link_named_part(mainl, fd, idcode, name, params->flag);
|
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,
|
|
|
|
|
FileData **fd,
|
|
|
|
|
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);
|
|
|
|
|
|
2021-03-09 00:53:13 +11:00
|
|
|
(*fd)->id_tag_extra = id_tag_extra;
|
|
|
|
|
|
2012-05-25 17:13:30 +00:00
|
|
|
(*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2003-04-26 18:01:01 +00:00
|
|
|
/* make mains */
|
2012-05-25 17:13:30 +00: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? */
|
2018-06-05 15:10:33 +02:00
|
|
|
mainl = blo_find_main(*fd, filepath, BKE_main_blendfile_path(mainvar));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2010-05-05 14:59:22 +00:00
|
|
|
/* needed for do_version */
|
2012-05-17 12:59:34 +00:00
|
|
|
mainl->versionfile = (*fd)->fileversion;
|
2010-05-05 14:59:22 +00:00
|
|
|
read_file_version(*fd, mainl);
|
2015-03-11 00:33:44 +11:00
|
|
|
#ifdef USE_GHASH_BHEAD
|
|
|
|
|
read_file_bhead_idname_map_create(*fd);
|
|
|
|
|
#endif
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2009-09-12 19:54:39 +00:00
|
|
|
return mainl;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-08 15:32:43 +10:00
|
|
|
void BLO_library_link_params_init(struct LibraryLink_Params *params,
|
|
|
|
|
struct 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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params,
|
|
|
|
|
struct Main *bmain,
|
|
|
|
|
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. */
|
|
|
|
|
struct Scene *scene,
|
|
|
|
|
struct ViewLayer *view_layer,
|
|
|
|
|
const struct View3D *v3d)
|
|
|
|
|
{
|
2021-03-09 00:53:13 +11:00
|
|
|
BLO_library_link_params_init(params, bmain, flag, id_tag_extra);
|
2020-09-08 15:32:43 +10:00
|
|
|
if (scene != NULL) {
|
|
|
|
|
params->context.scene = scene;
|
|
|
|
|
params->context.view_layer = view_layer;
|
|
|
|
|
params->context.v3d = v3d;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Main *BLO_library_link_begin(BlendHandle **bh,
|
|
|
|
|
const char *filepath,
|
|
|
|
|
const struct LibraryLink_Params *params)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)(*bh);
|
2021-11-30 17:52:58 +01:00
|
|
|
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
|
|
|
|
2021-06-30 15:19:35 +02:00
|
|
|
if (mainl->id_map == NULL) {
|
|
|
|
|
mainl->id_map = BKE_main_idmap_create(mainl, false, NULL, MAIN_IDMAP_TYPE_NAME);
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
/* expander now is callback function */
|
|
|
|
|
BLO_main_expander(expand_doit_library);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-01-26 14:00:13 +00:00
|
|
|
/* make main consistent */
|
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
|
|
|
BLO_expand_main(*fd, mainl);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2003-04-26 18:01:01 +00:00
|
|
|
/* do this when expand found other libs */
|
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 */
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_strncpy(curlib->filepath, curlib->filepath_abs, sizeof(curlib->filepath));
|
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);
|
|
|
|
|
mainvar = (*fd)->mainlist->first;
|
2021-06-22 10:42:32 -07:00
|
|
|
mainl = NULL; /* blo_join_main free's mainl, can't use anymore */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-19 16:36:15 +00:00
|
|
|
lib_link_all(*fd, mainvar);
|
2021-02-04 15:21:29 +01:00
|
|
|
after_liblink_merged_bmain_process(mainvar);
|
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
|
|
|
|
|
* current version file, but again this is really not a bottle neck currently. so not worth
|
|
|
|
|
* 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
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
do_versions_after_linking(main_newid, (*fd)->reports->reports);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-15 13:23:01 +02:00
|
|
|
add_main_to_main(mainvar, main_newid);
|
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);
|
|
|
|
|
mainvar = (*fd)->mainlist->first;
|
|
|
|
|
MEM_freeN((*fd)->mainlist);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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. */
|
|
|
|
|
ntreeUpdateAllNew(mainvar);
|
|
|
|
|
|
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
|
|
|
|
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 */
|
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);
|
2008-03-20 04:59:59 +00:00
|
|
|
*fd = NULL;
|
2012-12-11 22:00:22 +00:00
|
|
|
}
|
2009-09-12 19:54:39 +00:00
|
|
|
}
|
|
|
|
|
|
2020-09-08 15:32:43 +10:00
|
|
|
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const struct LibraryLink_Params *params)
|
2009-09-12 19:54:39 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)(*bh);
|
2021-11-30 17:52:58 +01:00
|
|
|
library_link_end(mainl, &fd, params->flag);
|
2018-11-30 14:51:16 +11:00
|
|
|
*bh = (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
|
|
|
{
|
|
|
|
|
BHead *bhead = NULL;
|
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,
|
|
|
|
|
TIP_("LIB: %s: '%s' is directly linked from '%s' (parent '%s'), but is a "
|
|
|
|
|
"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,
|
2020-06-23 09:54:07 +10:00
|
|
|
mainvar->curlib->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 {
|
2021-02-27 13:10:27 +01:00
|
|
|
BLO_reportf_wrap(basefd->reports,
|
2021-02-26 11:59:14 +01:00
|
|
|
RPT_INFO,
|
2019-02-27 19:25:21 +01:00
|
|
|
TIP_("LIB: %s: '%s' missing from '%s', parent '%s'"),
|
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,
|
2020-06-23 09:54:07 +10:00
|
|
|
mainvar->curlib->filepath_abs,
|
2019-02-27 19:25:21 +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) {
|
|
|
|
|
*r_id = is_valid ? create_placeholder(mainvar, GS(id->name), id->name + 2, id->tag) : NULL;
|
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--) {
|
|
|
|
|
ID *id = lbarray[a]->first;
|
|
|
|
|
ListBase pending_free_ids = {NULL};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
while (id) {
|
|
|
|
|
ID *id_next = 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);
|
2021-06-30 15:19:35 +02:00
|
|
|
if (mainvar->id_map != NULL) {
|
|
|
|
|
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. */
|
|
|
|
|
ID **realid = NULL;
|
|
|
|
|
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-03-08 13:48:31 +11:00
|
|
|
/* `realid` shall never be NULL - unless some source file/lib is broken
|
2019-02-27 19:25:21 +01:00
|
|
|
* (known case: some directly linked shapekey from a missing lib...). */
|
2022-03-08 13:48:31 +11:00
|
|
|
// BLI_assert(*realid != NULL);
|
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. */
|
|
|
|
|
BLI_ghash_clear(loaded_ids, NULL, NULL);
|
|
|
|
|
BLI_freelistN(&pending_free_ids);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
BLI_ghash_free(loaded_ids, NULL, NULL);
|
|
|
|
|
}
|
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
|
|
|
|
|
* those by setting them to NULL 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--) {
|
|
|
|
|
ID *id = lbarray[a]->first;
|
|
|
|
|
|
|
|
|
|
while (id) {
|
|
|
|
|
ID *id_next = id->next;
|
|
|
|
|
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);
|
2019-09-16 14:52:06 +02:00
|
|
|
change_link_placeholder_to_real_ID_pointer(mainlist, basefd, id, NULL);
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
FileData *fd = mainptr->curlib->filedata;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (fd != NULL) {
|
|
|
|
|
/* 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. */
|
|
|
|
|
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,
|
|
|
|
|
TIP_("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. */
|
2020-06-23 09:54:07 +10:00
|
|
|
BLI_strncpy(fd->relabase, mainptr->curlib->filepath_abs, sizeof(fd->relabase));
|
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,
|
|
|
|
|
TIP_("Read library: '%s', '%s', parent '%s'"),
|
2020-06-23 09:54:07 +10:00
|
|
|
mainptr->curlib->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));
|
2021-06-22 19:11:06 +02:00
|
|
|
fd = blo_filedata_from_file(mainptr->curlib->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
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
mainptr->curlib->filedata = fd;
|
|
|
|
|
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 {
|
|
|
|
|
mainptr->curlib->filedata = NULL;
|
|
|
|
|
mainptr->curlib->id.tag |= LIB_TAG_MISSING;
|
|
|
|
|
/* Set lib version to current main one... Makes assert later happy. */
|
|
|
|
|
mainptr->versionfile = mainptr->curlib->versionfile = mainl->versionfile;
|
|
|
|
|
mainptr->subversionfile = mainptr->curlib->subversionfile = mainl->subversionfile;
|
|
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
if (fd == NULL) {
|
2020-11-06 15:07:10 +01:00
|
|
|
BLO_reportf_wrap(
|
2021-02-26 11:59:14 +01:00
|
|
|
basefd->reports, RPT_INFO, TIP_("Cannot find lib '%s'"), mainptr->curlib->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)
|
|
|
|
|
{
|
|
|
|
|
Main *mainl = mainlist->first;
|
|
|
|
|
bool do_it = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Expander is now callback function. */
|
|
|
|
|
BLO_main_expander(expand_doit_library);
|
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
|
|
|
|
|
|
|
|
if (mainptr->id_map == NULL) {
|
|
|
|
|
mainptr->id_map = BKE_main_idmap_create(mainptr, false, NULL, MAIN_IDMAP_TYPE_NAME);
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-17 12:51:53 +10:00
|
|
|
/* Read linked data-locks for each link placeholder, and replace
|
|
|
|
|
* the placeholder with the real data-lock. */
|
2019-02-27 19:25:21 +01:00
|
|
|
read_library_linked_ids(basefd, fd, mainlist, mainptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-17 12:51:53 +10:00
|
|
|
/* Test if linked data-locks need to read further linked data-locks
|
2019-02-27 19:25:21 +01:00
|
|
|
* and create link placeholders for them. */
|
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
|
|
|
BLO_expand_main(fd, mainptr);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-15 13:23:01 +02:00
|
|
|
Main *main_newid = BKE_main_new();
|
2019-02-27 19:25:21 +01:00
|
|
|
for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
|
2019-10-10 10:25:46 +11:00
|
|
|
/* Drop weak links for which no data-block was found. */
|
2019-09-16 14:52:06 +02:00
|
|
|
read_library_clear_weak_links(basefd, mainlist, mainptr);
|
|
|
|
|
|
2019-06-17 12:51:53 +10:00
|
|
|
/* Do versioning for newly added linked data-locks. If no data-locks
|
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
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* File data can be zero with link/append. */
|
2019-04-22 09:13:00 +10:00
|
|
|
if (mainptr->curlib->filedata) {
|
2018-05-15 13:23:01 +02:00
|
|
|
do_versions(mainptr->curlib->filedata, mainptr->curlib, main_newid);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2018-05-15 13:23:01 +02:00
|
|
|
do_versions(basefd, NULL, 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. */
|
2019-04-22 09:13:00 +10:00
|
|
|
if (mainptr->curlib->filedata) {
|
2005-12-16 17:35:38 +00:00
|
|
|
lib_link_all(mainptr->curlib->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
|
|
|
|
|
* either full blendfile reading (#blo_read_file_internal()), or library-data linking
|
2020-06-27 14:34:16 +10:00
|
|
|
* (#library_link_end()). */
|
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
|
|
|
|
2019-02-27 19:25:21 +01:00
|
|
|
/* Free file data we no longer need. */
|
2019-04-22 09:13:00 +10:00
|
|
|
if (mainptr->curlib->filedata) {
|
2019-02-27 19:25:21 +01:00
|
|
|
blo_filedata_free(mainptr->curlib->filedata);
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2012-05-17 12:59:34 +00:00
|
|
|
mainptr->curlib->filedata = NULL;
|
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
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-30 15:27:57 +01:00
|
|
|
void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address)
|
|
|
|
|
{
|
|
|
|
|
return newdataadr_no_us(reader->fd, old_address);
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
ID *BLO_read_get_new_id_address(BlendLibReader *reader, Library *lib, ID *id)
|
|
|
|
|
{
|
|
|
|
|
return newlibadr(reader->fd, lib, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 12:53:59 +02:00
|
|
|
void BLO_read_list_cb(BlendDataReader *reader, ListBase *list, BlendReadListFn callback)
|
2020-06-05 11:44:36 +02:00
|
|
|
{
|
|
|
|
|
if (BLI_listbase_is_empty(list)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &list->first);
|
|
|
|
|
if (callback != NULL) {
|
|
|
|
|
callback(reader, list->first);
|
|
|
|
|
}
|
|
|
|
|
Link *ln = list->first;
|
|
|
|
|
Link *prev = NULL;
|
|
|
|
|
while (ln) {
|
|
|
|
|
BLO_read_data_address(reader, &ln->next);
|
|
|
|
|
if (ln->next != NULL && callback != NULL) {
|
|
|
|
|
callback(reader, ln->next);
|
|
|
|
|
}
|
|
|
|
|
ln->prev = prev;
|
|
|
|
|
prev = ln;
|
|
|
|
|
ln = ln->next;
|
|
|
|
|
}
|
|
|
|
|
list->last = prev;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 12:53:36 +02:00
|
|
|
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_list_cb(reader, list, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_data_address(reader, ptr_p);
|
|
|
|
|
if (BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
BLI_endian_switch_int32_array(*ptr_p, array_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_data_address(reader, ptr_p);
|
|
|
|
|
if (BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
BLI_endian_switch_uint32_array(*ptr_p, array_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_data_address(reader, ptr_p);
|
|
|
|
|
if (BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_data_address(reader, ptr_p);
|
|
|
|
|
if (BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
BLI_endian_switch_double_array(*ptr_p, array_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
dst[i] = (uint32_t)(ptr >> 3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (int i = 0; i < array_size; i++) {
|
|
|
|
|
dst[i] = (uint32_t)(src[i] >> 3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void convert_pointer_array_32_to_64(BlendDataReader *UNUSED(reader),
|
|
|
|
|
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);
|
|
|
|
|
if (orig_array == NULL) {
|
|
|
|
|
*ptr_p = NULL;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
void *final_array = NULL;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 11:44:36 +02:00
|
|
|
void BLO_expand_id(BlendExpander *expander, ID *id)
|
|
|
|
|
{
|
|
|
|
|
expand_doit(expander->fd, expander->main, id);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-22 18:15:56 +11:00
|
|
|
/** \} */
|