tornavis/source/blender/blenkernel/BKE_lib_override.hh

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

573 lines
24 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*
2020-02-15 05:58:06 +01:00
* API to manage data-blocks inside of Blender's Main data-base, or as independent runtime-only
* data.
*
* \note `BKE_lib_` files are for operations over data-blocks themselves, although they might
* alter Main as well (when creating/renaming/deleting an ID e.g.).
*
* \section Function Names
*
* \warning Descriptions below is ideal goal, current status of naming does not yet fully follow it
* (this is WIP).
*
* - `BKE_lib_override_library_` should be used for function affecting a single ID.
* - `BKE_lib_override_library_main_` should be used for function affecting the whole collection
* of IDs in a given Main data-base.
*/
LibOverride: Add ID pointer to operations over ID pointers. In RNA collections storing ID references, the name of the collection item may not always be unique, when several IDs from different libraries are present. While rare, this situation can become deadly to liboverride, by causing random but exponential liboverride hierarchies corruptions. This has already been alleviated by using preferably both name and index in items lookup (a05419f18b) and by reducing the risk of name collision in general between liboverrides and their linked reference (b9becc47de). This commit goes further, by ensuring that references to items of RNA collections of IDs stored in liboverride operations become completely unambiguous. This is achieved by storing an extra pointer to the item's ID itself, when relevant. Lookup then requires a complete match `name + ID` to be successful, which is guaranteed to match at most a single item in the whole RNA collection (since RNA collection of IDs do not allow duplicates, and the ID pointer is always unique). Note that this ID pointer is implemented as an `std::optional` one (either directly in C++ code, or using an new liboverride operation `flag` in DNA). This allows to smoothly transition from existing data to the added ID pointer info (when needed), without needing any dedicated versioning. This solution also preserves forward compatibility as much as possible. It may also provide marginal performances improvements in some cases, as looking up for ID items in RNA collections will first check for the ID pointer, which should be faster than a string comparision. Implements #110421. Pull Request: https://projects.blender.org/blender/blender/pulls/110773
2023-08-03 20:32:36 +02:00
#include <optional>
struct BlendFileReadReport;
2021-07-16 03:48:54 +02:00
struct Collection;
struct ID;
struct IDOverrideLibrary;
struct IDOverrideLibraryProperty;
struct IDOverrideLibraryPropertyOperation;
struct Library;
struct Main;
2020-09-30 03:51:13 +02:00
struct Object;
struct PointerRNA;
struct PropertyRNA;
struct ReportList;
struct Scene;
struct ViewLayer;
/**
* Initialize empty overriding of \a reference_id by \a local_id.
*/
IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id);
/**
* Shallow or deep copy of a whole override from \a src_id to \a dst_id.
*/
void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, bool do_full_copy);
/**
* Clear any overriding data from given \a liboverride.
*/
void BKE_lib_override_library_clear(IDOverrideLibrary *liboverride, bool do_id_user);
/**
* Free given \a liboverride.
*/
void BKE_lib_override_library_free(IDOverrideLibrary **liboverride, bool do_id_user);
/**
2022-08-12 12:42:03 +02:00
* Return the actual #IDOverrideLibrary data 'controlling' the given `id`, and the actual ID owning
* it.
*
* \note This is especially useful when `id` is a non-real override (e.g. embedded ID like a master
* collection or root node tree, or a shape key).
*
2022-08-12 12:42:03 +02:00
* \param owner_id_hint: If not NULL, a potential owner for the given override-embedded `id`.
* \param r_owner_id: If given, will be set with the actual ID owning the return liboverride data.
*/
IDOverrideLibrary *BKE_lib_override_library_get(Main *bmain,
ID *id,
ID *owner_id_hint,
ID **r_owner_id);
/**
* Check if given ID has some override rules that actually indicate the user edited it.
*/
bool BKE_lib_override_library_is_user_edited(const ID *id);
/**
* Check if given ID is a system override.
*/
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id);
/**
* Check if given Override Property for given ID is animated (through a F-Curve in an Action, or
* from a driver).
*
* \param liboverride_rna_prop: if not NULL, the RNA property matching the given path in the
* `liboverride_prop`.
* \param rnaprop_index: Array in the RNA property, 0 if unknown or irrelevant.
*/
bool BKE_lib_override_library_property_is_animated(
const ID *id,
const IDOverrideLibraryProperty *liboverride_prop,
const PropertyRNA *override_rna_prop,
const int rnaprop_index);
/**
* Check if given ID is a leaf in its liboverride hierarchy (i.e. if it does not use any other
* override ID).
*
* NOTE: Embedded IDs of override IDs are not considered as leaves.
*/
bool BKE_lib_override_library_is_hierarchy_leaf(Main *bmain, ID *id);
/**
* Tag the liboverride ID for auto-refresh when it gets tagged for depsgraph update.
*
* NOTE: This should only handle direct user editing, it is assumed that indirect updates should
* never require an update of the liboverride diffing info.
*/
void BKE_lib_override_id_tag_on_deg_tag_from_user(ID *id);
/**
* Create an overridden local copy of linked reference.
*
2022-01-06 03:54:52 +01:00
* \note This function is very basic, low-level. It does not consider any hierarchical dependency,
* and also prevents any automatic re-sync of this local override.
*/
ID *BKE_lib_override_library_create_from_id(Main *bmain, ID *reference_id, bool do_tagged_remap);
/**
* Create overridden local copies of all tagged data-blocks in given Main.
*
* \note Set `id->newid` of overridden libraries with newly created overrides,
* caller is responsible to clean those pointers before/after usage as needed.
*
* \note By default, it will only remap newly created local overriding data-blocks between
* themselves, to avoid 'enforcing' those overrides into all other usages of the linked data in
* main. You can add more local IDs to be remapped to use new overriding ones by setting their
* LIB_TAG_DOIT tag.
*
* \param owner_library: the library in which the overrides should be created. Besides versioning
* and resync code path, this should always be NULL (i.e. the local .blend file).
*
* \param id_root_reference: the linked ID that is considered as the root of the overridden
* hierarchy.
*
* \param id_hierarchy_root: the override ID that is the root of the hierarchy. May be NULL, in
* which case it is assumed that the given `id_root_reference` is tagged for override, and its
* newly created override will be used as hierarchy root. Must be NULL if
* `id_hierarchy_root_reference` is not NULL.
*
* \param id_hierarchy_root_reference: the linked ID that is the root of the hierarchy. Must be
* tagged for override. May be NULL, in which case it is assumed that the given `id_root_reference`
* is tagged for override, and its newly created override will be used as hierarchy root. Must be
* NULL if `id_hierarchy_root` is not NULL.
*
* \param do_no_main: Create the new override data outside of Main database.
* Used for resyncing of linked overrides.
*
* \param do_fully_editable: if true, tag all created overrides as user-editable by default.
*
* \return \a true on success, \a false otherwise.
*/
bool BKE_lib_override_library_create_from_tag(Main *bmain,
Library *owner_library,
const ID *id_root_reference,
ID *id_hierarchy_root,
const ID *id_hierarchy_root_reference,
bool do_no_main,
const bool do_fully_editable);
/**
* Advanced 'smart' function to create fully functional overrides.
*
* \note Currently it only does special things if given \a id_root is an object or collection, more
* specific behaviors may be added in the future for other ID types.
*
* \note It will override all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at
* its beginning, so caller code can add extra data-blocks to be overridden as well.
*
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
*
* \param owner_library: the library in which the overrides should be created. Besides versioning
* and resync code path, this should always be NULL (i.e. the local .blend file).
*
* \param id_root_reference: The linked root ID to create an override from. May be a sub-root of
* the overall hierarchy, in which case calling code is expected to have already tagged required
* 'path' of IDs leading from the given `id_hierarchy_root` to the given `id_root`.
*
* \param id_hierarchy_root_reference: The ID to be used a hierarchy root of the overrides to be
* created. Can be either the linked root ID of the whole override hierarchy, (typically the same
* as `id_root`, unless a sub-part only of the hierarchy is overridden), or the already existing
* override hierarchy root if part of the hierarchy is already overridden.
*
* \param id_instance_hint: Some ID used as hint/reference to do some post-processing after
* overrides have been created, may be NULL. Typically, the Empty object instantiating the linked
* collection we override, currently.
*
* \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
*
* \param do_fully_editable: if true, tag all created overrides as user-editable by default.
*
* \return true if override was successfully created.
*/
bool BKE_lib_override_library_create(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
Library *owner_library,
ID *id_root_reference,
ID *id_hierarchy_root_reference,
ID *id_instance_hint,
ID **r_id_root_override,
const bool do_fully_editable);
/**
* Convert a given proxy object into a library override.
*
* \note This is a thin wrapper around \a BKE_lib_override_library_create, only extra work is to
* actually convert the proxy itself into an override first.
*
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
* \return true if override was successfully created.
*/
bool BKE_lib_override_library_proxy_convert(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
Object *ob_proxy);
/**
* Convert all proxy objects into library overrides.
*
* \note Only affects local proxies, linked ones are not affected.
*/
void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports);
/**
* Find and set the 'hierarchy root' ID pointer of all library overrides in given `bmain`.
*
* NOTE: Cannot be called from `do_versions_after_linking` as this code needs a single complete
* Main database, not a split-by-libraries one.
*/
void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain);
/**
* Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked
* data, from an existing override hierarchy.
*
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
* \param id_root: The root liboverride ID to resync from.
* \param do_hierarchy_enforce: If `true`, enforce the liboverride hierarchy of dependencies to
* match the one from the reference linked data (i.e. if some manually
* override were applied to some ID pointers, they will be reset to
* the default reference value).
*
* \return true if override was successfully resynced.
*/
bool BKE_lib_override_library_resync(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
ID *id_root,
Collection *override_resync_residual_storage,
bool do_hierarchy_enforce,
BlendFileReadReport *reports);
/**
* Detect and handle required resync of overrides data, when relations between reference linked IDs
* have changed.
*
* This is a fairly complex and costly operation, typically it should be called after
* #BKE_lib_override_library_main_update, which would already detect and tag a lot of cases.
*
* This function will first detect the remaining cases requiring a resync (namely, either when an
* existing linked ID that did not require to be overridden before now would be, or when new IDs
* are added to the hierarchy).
*
* Then it will handle the resync of necessary IDs (through calls to
* #BKE_lib_override_library_resync).
*
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
*/
void BKE_lib_override_library_main_resync(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
BlendFileReadReport *reports);
/**
* Advanced 'smart' function to delete library overrides (including their existing override
* hierarchy) and remap their usages to their linked reference IDs.
*
* \note All IDs tagged with #LIB_TAG_DOIT will be deleted.
*
* \param id_root: The root liboverride ID to delete.
*/
void BKE_lib_override_library_delete(Main *bmain, ID *id_root);
/**
* Make given ID fully local.
*
* \param bmain: If given, all liboverrides hierarchy roots will be re-validated/generated after
* clearing the liboverride data from given \a id. If nullptr, caller is responsible to perform
* this action (call #BKE_lib_override_library_main_hierarchy_root_ensure) itself.
*
* \note Only differs from lower-level #BKE_lib_override_library_free in infamous embedded ID
* cases.
*/
void BKE_lib_override_library_make_local(Main *bmain, ID *id);
/**
* Find override property from given RNA path, if it exists.
*/
IDOverrideLibraryProperty *BKE_lib_override_library_property_find(IDOverrideLibrary *override,
const char *rna_path);
/**
* Find override property from given RNA path, or create it if it does not exist.
*/
IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibrary *override,
const char *rna_path,
bool *r_created);
/**
* Remove and free given \a liboverride_property from given ID \a liboverride.
*/
void BKE_lib_override_library_property_delete(IDOverrideLibrary *liboverride,
IDOverrideLibraryProperty *liboverride_property);
Fix #102662: NLA-Strip Corrupted after reopening file w/ lib override Mark `NlaStrip.frame_{start,end}` and `NlaStrip.frame_{start,end}_ui` as to-be-ignored for the library override system, and add a new set of RNA properties `frame_{start,end}_raw` that the library override system can use. Versioning code ensures that overrides on `frame_{start,end}` are altered to be applied to the `..._raw` counterpart instead. The override system uses RNA to update properties one-by-one, and the RNA code trying its best to keep things consistent / valid. This is very much desired behaviour while a human is editing the data. However, when the library override system is doing this, it is not replaying the individual steps (that each end in a valid configuration), but just setting each property one by one. As a result, the intermediate state can be invalid (for example moving one strip into another) even when the end result is perfectly fine. This is what the `..._raw` properties do -- they set the values without doing any validation, so they allow the library overrides system to move strips around. This assumes that the result of the override is still valid. Logic to detect invalid situations, and reshuffle the NLA strips if necessary, is left for a future commit as it is related to #107990 (NLA Vertical Reorder). Additionally, this commit adds functions `BKE_lib_override_library_property_rna_path_change()` and `BKE_lib_override_library_property_search_and_delete()` to the library override API. The former is used to change RNA paths of property overrides, and the latter is used to remove a property override identified by its RNA path.
2023-05-22 10:36:50 +02:00
/**
* Delete a property override from the given ID \a liboverride, if it exists.
Fix #102662: NLA-Strip Corrupted after reopening file w/ lib override Mark `NlaStrip.frame_{start,end}` and `NlaStrip.frame_{start,end}_ui` as to-be-ignored for the library override system, and add a new set of RNA properties `frame_{start,end}_raw` that the library override system can use. Versioning code ensures that overrides on `frame_{start,end}` are altered to be applied to the `..._raw` counterpart instead. The override system uses RNA to update properties one-by-one, and the RNA code trying its best to keep things consistent / valid. This is very much desired behaviour while a human is editing the data. However, when the library override system is doing this, it is not replaying the individual steps (that each end in a valid configuration), but just setting each property one by one. As a result, the intermediate state can be invalid (for example moving one strip into another) even when the end result is perfectly fine. This is what the `..._raw` properties do -- they set the values without doing any validation, so they allow the library overrides system to move strips around. This assumes that the result of the override is still valid. Logic to detect invalid situations, and reshuffle the NLA strips if necessary, is left for a future commit as it is related to #107990 (NLA Vertical Reorder). Additionally, this commit adds functions `BKE_lib_override_library_property_rna_path_change()` and `BKE_lib_override_library_property_search_and_delete()` to the library override API. The former is used to change RNA paths of property overrides, and the latter is used to remove a property override identified by its RNA path.
2023-05-22 10:36:50 +02:00
*
* \return True when the property was found (and thus deleted), false if it wasn't found.
*/
bool BKE_lib_override_library_property_search_and_delete(IDOverrideLibrary *liboverride,
Fix #102662: NLA-Strip Corrupted after reopening file w/ lib override Mark `NlaStrip.frame_{start,end}` and `NlaStrip.frame_{start,end}_ui` as to-be-ignored for the library override system, and add a new set of RNA properties `frame_{start,end}_raw` that the library override system can use. Versioning code ensures that overrides on `frame_{start,end}` are altered to be applied to the `..._raw` counterpart instead. The override system uses RNA to update properties one-by-one, and the RNA code trying its best to keep things consistent / valid. This is very much desired behaviour while a human is editing the data. However, when the library override system is doing this, it is not replaying the individual steps (that each end in a valid configuration), but just setting each property one by one. As a result, the intermediate state can be invalid (for example moving one strip into another) even when the end result is perfectly fine. This is what the `..._raw` properties do -- they set the values without doing any validation, so they allow the library overrides system to move strips around. This assumes that the result of the override is still valid. Logic to detect invalid situations, and reshuffle the NLA strips if necessary, is left for a future commit as it is related to #107990 (NLA Vertical Reorder). Additionally, this commit adds functions `BKE_lib_override_library_property_rna_path_change()` and `BKE_lib_override_library_property_search_and_delete()` to the library override API. The former is used to change RNA paths of property overrides, and the latter is used to remove a property override identified by its RNA path.
2023-05-22 10:36:50 +02:00
const char *rna_path);
/**
* Change the RNA path of a library override on a property.
Fix #102662: NLA-Strip Corrupted after reopening file w/ lib override Mark `NlaStrip.frame_{start,end}` and `NlaStrip.frame_{start,end}_ui` as to-be-ignored for the library override system, and add a new set of RNA properties `frame_{start,end}_raw` that the library override system can use. Versioning code ensures that overrides on `frame_{start,end}` are altered to be applied to the `..._raw` counterpart instead. The override system uses RNA to update properties one-by-one, and the RNA code trying its best to keep things consistent / valid. This is very much desired behaviour while a human is editing the data. However, when the library override system is doing this, it is not replaying the individual steps (that each end in a valid configuration), but just setting each property one by one. As a result, the intermediate state can be invalid (for example moving one strip into another) even when the end result is perfectly fine. This is what the `..._raw` properties do -- they set the values without doing any validation, so they allow the library overrides system to move strips around. This assumes that the result of the override is still valid. Logic to detect invalid situations, and reshuffle the NLA strips if necessary, is left for a future commit as it is related to #107990 (NLA Vertical Reorder). Additionally, this commit adds functions `BKE_lib_override_library_property_rna_path_change()` and `BKE_lib_override_library_property_search_and_delete()` to the library override API. The former is used to change RNA paths of property overrides, and the latter is used to remove a property override identified by its RNA path.
2023-05-22 10:36:50 +02:00
*
* No-op if the property override cannot be found.
*
2023-07-04 04:27:38 +02:00
* \param from_rna_path: The RNA path of the property to change.
* \param to_rna_path: The new RNA path.
* The library override system will copy the string to its own memory;
* the caller will retain ownership of the passed pointer.
Fix #102662: NLA-Strip Corrupted after reopening file w/ lib override Mark `NlaStrip.frame_{start,end}` and `NlaStrip.frame_{start,end}_ui` as to-be-ignored for the library override system, and add a new set of RNA properties `frame_{start,end}_raw` that the library override system can use. Versioning code ensures that overrides on `frame_{start,end}` are altered to be applied to the `..._raw` counterpart instead. The override system uses RNA to update properties one-by-one, and the RNA code trying its best to keep things consistent / valid. This is very much desired behaviour while a human is editing the data. However, when the library override system is doing this, it is not replaying the individual steps (that each end in a valid configuration), but just setting each property one by one. As a result, the intermediate state can be invalid (for example moving one strip into another) even when the end result is perfectly fine. This is what the `..._raw` properties do -- they set the values without doing any validation, so they allow the library overrides system to move strips around. This assumes that the result of the override is still valid. Logic to detect invalid situations, and reshuffle the NLA strips if necessary, is left for a future commit as it is related to #107990 (NLA Vertical Reorder). Additionally, this commit adds functions `BKE_lib_override_library_property_rna_path_change()` and `BKE_lib_override_library_property_search_and_delete()` to the library override API. The former is used to change RNA paths of property overrides, and the latter is used to remove a property override identified by its RNA path.
2023-05-22 10:36:50 +02:00
* \return True if the property was found (and thus changed), false if it wasn't found.
*/
bool BKE_lib_override_library_property_rna_path_change(IDOverrideLibrary *liboverride,
Fix #102662: NLA-Strip Corrupted after reopening file w/ lib override Mark `NlaStrip.frame_{start,end}` and `NlaStrip.frame_{start,end}_ui` as to-be-ignored for the library override system, and add a new set of RNA properties `frame_{start,end}_raw` that the library override system can use. Versioning code ensures that overrides on `frame_{start,end}` are altered to be applied to the `..._raw` counterpart instead. The override system uses RNA to update properties one-by-one, and the RNA code trying its best to keep things consistent / valid. This is very much desired behaviour while a human is editing the data. However, when the library override system is doing this, it is not replaying the individual steps (that each end in a valid configuration), but just setting each property one by one. As a result, the intermediate state can be invalid (for example moving one strip into another) even when the end result is perfectly fine. This is what the `..._raw` properties do -- they set the values without doing any validation, so they allow the library overrides system to move strips around. This assumes that the result of the override is still valid. Logic to detect invalid situations, and reshuffle the NLA strips if necessary, is left for a future commit as it is related to #107990 (NLA Vertical Reorder). Additionally, this commit adds functions `BKE_lib_override_library_property_rna_path_change()` and `BKE_lib_override_library_property_search_and_delete()` to the library override API. The former is used to change RNA paths of property overrides, and the latter is used to remove a property override identified by its RNA path.
2023-05-22 10:36:50 +02:00
const char *old_rna_path,
const char *new_rna_path);
/**
* Get the RNA-property matching the \a library_prop override property. Used for UI to query
* additional data about the overridden property (e.g. UI name).
*
* \param idpoin: Pointer to the override ID.
* \param library_prop: The library override property to find the matching RNA property for.
2022-06-14 06:30:13 +02:00
* \param r_index: The RNA array flat index (i.e. flattened index in case of multi-dimensional
* array properties). See #RNA_path_resolve_full family of functions for details.
*/
bool BKE_lib_override_rna_property_find(PointerRNA *idpoin,
const IDOverrideLibraryProperty *library_prop,
PointerRNA *r_override_poin,
PropertyRNA **r_override_prop,
int *r_index);
/**
* Find override property operation from given sub-item(s), if it exists.
LibOverride: Add ID pointer to operations over ID pointers. In RNA collections storing ID references, the name of the collection item may not always be unique, when several IDs from different libraries are present. While rare, this situation can become deadly to liboverride, by causing random but exponential liboverride hierarchies corruptions. This has already been alleviated by using preferably both name and index in items lookup (a05419f18b) and by reducing the risk of name collision in general between liboverrides and their linked reference (b9becc47de). This commit goes further, by ensuring that references to items of RNA collections of IDs stored in liboverride operations become completely unambiguous. This is achieved by storing an extra pointer to the item's ID itself, when relevant. Lookup then requires a complete match `name + ID` to be successful, which is guaranteed to match at most a single item in the whole RNA collection (since RNA collection of IDs do not allow duplicates, and the ID pointer is always unique). Note that this ID pointer is implemented as an `std::optional` one (either directly in C++ code, or using an new liboverride operation `flag` in DNA). This allows to smoothly transition from existing data to the added ID pointer info (when needed), without needing any dedicated versioning. This solution also preserves forward compatibility as much as possible. It may also provide marginal performances improvements in some cases, as looking up for ID items in RNA collections will first check for the ID pointer, which should be faster than a string comparision. Implements #110421. Pull Request: https://projects.blender.org/blender/blender/pulls/110773
2023-08-03 20:32:36 +02:00
*
* \param subitem_refid:
* \param subitem_locid: Only for RNA collections of ID pointers, the ID pointers
* referenced by the given names. Note that both must be set, or left unset.
*/
IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_find(
IDOverrideLibraryProperty *liboverride_property,
const char *subitem_refname,
const char *subitem_locname,
LibOverride: Add ID pointer to operations over ID pointers. In RNA collections storing ID references, the name of the collection item may not always be unique, when several IDs from different libraries are present. While rare, this situation can become deadly to liboverride, by causing random but exponential liboverride hierarchies corruptions. This has already been alleviated by using preferably both name and index in items lookup (a05419f18b) and by reducing the risk of name collision in general between liboverrides and their linked reference (b9becc47de). This commit goes further, by ensuring that references to items of RNA collections of IDs stored in liboverride operations become completely unambiguous. This is achieved by storing an extra pointer to the item's ID itself, when relevant. Lookup then requires a complete match `name + ID` to be successful, which is guaranteed to match at most a single item in the whole RNA collection (since RNA collection of IDs do not allow duplicates, and the ID pointer is always unique). Note that this ID pointer is implemented as an `std::optional` one (either directly in C++ code, or using an new liboverride operation `flag` in DNA). This allows to smoothly transition from existing data to the added ID pointer info (when needed), without needing any dedicated versioning. This solution also preserves forward compatibility as much as possible. It may also provide marginal performances improvements in some cases, as looking up for ID items in RNA collections will first check for the ID pointer, which should be faster than a string comparision. Implements #110421. Pull Request: https://projects.blender.org/blender/blender/pulls/110773
2023-08-03 20:32:36 +02:00
const std::optional<const ID *> &subitem_refid,
const std::optional<const ID *> &subitem_locid,
int subitem_refindex,
int subitem_locindex,
bool strict,
bool *r_strict);
/**
* Find override property operation from given sub-item(s), or create it if it does not exist.
*/
IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_get(
IDOverrideLibraryProperty *liboverride_property,
short operation,
const char *subitem_refname,
const char *subitem_locname,
LibOverride: Add ID pointer to operations over ID pointers. In RNA collections storing ID references, the name of the collection item may not always be unique, when several IDs from different libraries are present. While rare, this situation can become deadly to liboverride, by causing random but exponential liboverride hierarchies corruptions. This has already been alleviated by using preferably both name and index in items lookup (a05419f18b) and by reducing the risk of name collision in general between liboverrides and their linked reference (b9becc47de). This commit goes further, by ensuring that references to items of RNA collections of IDs stored in liboverride operations become completely unambiguous. This is achieved by storing an extra pointer to the item's ID itself, when relevant. Lookup then requires a complete match `name + ID` to be successful, which is guaranteed to match at most a single item in the whole RNA collection (since RNA collection of IDs do not allow duplicates, and the ID pointer is always unique). Note that this ID pointer is implemented as an `std::optional` one (either directly in C++ code, or using an new liboverride operation `flag` in DNA). This allows to smoothly transition from existing data to the added ID pointer info (when needed), without needing any dedicated versioning. This solution also preserves forward compatibility as much as possible. It may also provide marginal performances improvements in some cases, as looking up for ID items in RNA collections will first check for the ID pointer, which should be faster than a string comparision. Implements #110421. Pull Request: https://projects.blender.org/blender/blender/pulls/110773
2023-08-03 20:32:36 +02:00
const std::optional<ID *> &subitem_refid,
const std::optional<ID *> &subitem_locid,
int subitem_refindex,
int subitem_locindex,
bool strict,
bool *r_strict,
bool *r_created);
/**
* Remove and free given \a liboverride_property_operation from given ID \a liboverride_property.
*/
void BKE_lib_override_library_property_operation_delete(
IDOverrideLibraryProperty *liboverride_property,
IDOverrideLibraryPropertyOperation *liboverride_property_operation);
/**
* Validate that required data for a given operation are available.
*/
bool BKE_lib_override_library_property_operation_operands_validate(
IDOverrideLibraryPropertyOperation *liboverride_property_operation,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *ptr_storage,
PropertyRNA *prop_dst,
PropertyRNA *prop_src,
PropertyRNA *prop_storage);
/**
* Check against potential \a bmain.
*/
void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports);
/**
* Check against potential \a bmain.
*/
void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports);
/**
* Check that status of local data-block is still valid against current reference one.
*
* It means that all overridable, but not overridden, properties' local values must be equal to
* reference ones. Clears #LIB_TAG_OVERRIDE_OK if they do not.
*
* This is typically used to detect whether some property has been changed in local and a new
* #IDOverrideProperty (of #IDOverridePropertyOperation) has to be added.
*
* \return true if status is OK, false otherwise.
*/
bool BKE_lib_override_library_status_check_local(Main *bmain, ID *local);
/**
* Check that status of reference data-block is still valid against current local one.
*
* It means that all non-overridden properties' local values must be equal to reference ones.
* Clears LIB_TAG_OVERRIDE_OK if they do not.
*
* This is typically used to detect whether some reference has changed and local
* needs to be updated against it.
*
* \return true if status is OK, false otherwise.
*/
bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local);
/**
* Compare local and reference data-blocks and create new override operations as needed,
* or reset to reference values if overriding is not allowed.
*
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Defining override operations is only mandatory before saving a `.blend` file on disk
* (not for undo!).
* Knowing that info at runtime is only useful for UI/UX feedback.
*
* \note This is by far the biggest operation (the more time-consuming) of the three so far,
* since it has to go over all properties in depth (all overridable ones at least).
* Generating differential values and applying overrides are much cheaper.
*/
void BKE_lib_override_library_operations_create(Main *bmain, ID *local, int *r_report_flags);
/**
* Check all overrides from given \a bmain and create/update overriding operations as needed.
*
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*/
void BKE_lib_override_library_main_operations_create(Main *bmain,
bool force_auto,
int *r_report_flags);
/**
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID.
*
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.
*/
void BKE_lib_override_library_operations_restore(Main *bmain, ID *local, int *r_report_flags);
/**
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID, for all liboverride IDs tagged as needing such process in given `bmain`.
*
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.
*/
void BKE_lib_override_library_main_operations_restore(Main *bmain, int *r_report_flags);
/**
* Reset all overrides in given \a id_root, while preserving ID relations.
*
* \param do_reset_system_override: If \a true, reset the given ID as a system override one (i.e.
* non-editable).
*/
void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root, bool do_reset_system_override);
/**
* Reset all overrides in given \a id_root and its dependencies, while preserving ID relations.
*
* \param do_reset_system_override: If \a true, reset the given ID and all of its descendants in
* the override hierarchy as system override ones (i.e. non-editable).
*/
void BKE_lib_override_library_id_hierarchy_reset(Main *bmain,
ID *id_root,
bool do_reset_system_override);
/**
* Set or clear given tag in all operations in that override property data.
*/
void BKE_lib_override_library_operations_tag(IDOverrideLibraryProperty *liboverride_property,
short tag,
bool do_set);
/**
* Set or clear given tag in all properties and operations in that override data.
*/
void BKE_lib_override_library_properties_tag(IDOverrideLibrary *liboverride,
short tag,
bool do_set);
/**
* Set or clear given tag in all properties and operations in that Main's ID override data.
*/
void BKE_lib_override_library_main_tag(Main *bmain, short tag, bool do_set);
/**
* Remove all tagged-as-unused properties and operations from that ID override data.
*/
void BKE_lib_override_library_id_unused_cleanup(ID *local);
/**
* Remove all tagged-as-unused properties and operations from that Main's ID override data.
*/
void BKE_lib_override_library_main_unused_cleanup(Main *bmain);
/**
* Update given override from its reference (re-applying overridden properties).
*/
void BKE_lib_override_library_update(Main *bmain, ID *local);
/**
* Update all overrides from given \a bmain.
*/
void BKE_lib_override_library_main_update(Main *bmain);
/**
* In case an ID is used by another liboverride ID, user may not be allowed to delete it.
*/
bool BKE_lib_override_library_id_is_user_deletable(Main *bmain, ID *id);
/**
2023-07-12 04:45:35 +02:00
* Debugging helper to show content of given liboverride data.
*/
void BKE_lib_override_debug_print(IDOverrideLibrary *liboverride, const char *intro_txt);
/* Storage (.blend file writing) part. */
/* For now, we just use a temp main list. */
using OverrideLibraryStorage = Main;
/**
* Initialize an override storage.
*/
OverrideLibraryStorage *BKE_lib_override_library_operations_store_init();
/**
* Generate suitable 'write' data (this only affects differential override operations).
*
* Note that \a local ID is no more modified by this call,
* all extra data are stored in its temp \a storage_id copy.
*/
ID *BKE_lib_override_library_operations_store_start(Main *bmain,
OverrideLibraryStorage *liboverride_storage,
ID *local);
/**
* Restore given ID modified by #BKE_lib_override_library_operations_store_start, to its
* original state.
*/
void BKE_lib_override_library_operations_store_end(OverrideLibraryStorage *liboverride_storage,
ID *local);
void BKE_lib_override_library_operations_store_finalize(
OverrideLibraryStorage *liboverride_storage);