Source/Architecture/Overrides/Library/Functional Design

=Functional Design Library Overrides=

This page contains the functional design for the overrides project. Overrides is a system to link in an asset in your scene and add changes to it.

The functionality is written in use cases as they are more system oriented. It has been written with developer audience in mind who might be willing to implement functionality that isn't available yet in the current code base.

This design assumes you are working with the default theme. Mentioned colors can be different when using other themes.

Glossary
This glossary is extracted from the code-base.


 * Asset
 * Any ID data-block.


 * Library
 * A blend file containing an asset you want to link into a working scene.


 * Library Override
 * A local change of a linked asset in a working scene.


 * Reference Data-Block
 * When an asset is linked into a working scene the reference to the original asset without any local changes applied.


 * Override Data-Block
 * The reference with all local changes applied. This is the object where the artist is interacting with in the working scene.


 * In code this is often called a local data-block.


 * Override Template
 * A template contains predefined rules allowed to be overridden for an asset. The template is stored in the library where the asset is stored.

Override Property
 * Part of the override structure that stores the RNA data path and contains the defined operations.


 * Override Operation
 * Defines how the relation between the original value and the overridden value. This operation can be:
 * Replace: the overridden value will replace the original value
 * Difference: the overridden value is added or subtracted to the original value.
 * Multiply: the overridden value is multiplied with the original value
 * Insert Element: the overridden value is inserted into a list.
 * Difference and Insert Element are functional operations. In implementation they are split to Add/Subtract, Insert :Before/Insert After, to support unsigned RNA values and insert before a specific item to ensure the order (e.g. modifiers).
 * Difference and Insert Element are functional operations. In implementation they are split to Add/Subtract, Insert :Before/Insert After, to support unsigned RNA values and insert before a specific item to ensure the order (e.g. modifiers).
 * Difference and Insert Element are functional operations. In implementation they are split to Add/Subtract, Insert :Before/Insert After, to support unsigned RNA values and insert before a specific item to ensure the order (e.g. modifiers).

Actors
This design uses 2 actors. As the system is generic these actors are also generic.


 * Asset Owner
 * A user that creates a specific asset that would be overridden by another actor. For example a rigger creates a rig thereby the rigger is the owner of the rig.


 * Asset User
 * A user that overrides an asset. For example an animator overrides a rig and adds animation to it. Thereby the animator uses the rig.

=Use Cases=

UC: Change override mode [DRAFT]
As a rigger I want to control if the overrides are restrictive or permissive. In restrictive mode only overrides are allowed that have been added to the template. In permissive mode all overrides are allowed except those who have been specifically set to "disallow override" in the template.

This use case would still need attention on UX. It was added as the current permissive mode is different than the restrictive mode we had to validate. This use case is the bridge between the two modes.


 * Actor
 * Asset Owner


 * Preconditions
 * Overrides templates can only be configured on assets created in the current work file.


 * Postconditions
 * When loading a file that already uses the asset with the new template a warning will be presented to the user if existing override operations are no longer allowed by the override template.
 * When adding an override only overrides are allowed that match the template.
 * Overrides that aren't allowed are disabled in the UI.
 * Overrides that aren't allowed, but have been previously added are marked as an invalid override in the UI (icon and or color).


 * Primary Workflow
 * User selects an object
 * User navigates to Object Menu ⇒ Relations ⇒ Set Restrictive Override Mode/Set Permissive Override Mode


 * Alternative Workflows
 * Via context menu in outliner


 * Technical Status
 * Not implemented, By default the permissive mode is used.

UC: Mark property for override in restrictive mode [DRAFT]
In restrictive mode a rigger wants to control if an operation can be overridden and how.

This use case would still need attention on UX. It was added as the current permissive mode is different than the restrictive mode we had to validate. This use case shows a possible solution but lacks attention if this is the actual workflow we want to provide our users. Feedback we received was that the UX in the use case wasn't explicit. Adding this would lead to more questions that doesn't fit in the current goal of the project. Questions like: # When adding overrides via the outliner, what properties will be exactly added? # Does the developer make this decision (based on ID data-block) or does the user make this decision (based on a different kind of template mechanism)? # How to report this back to the user? As the technical architecture for these solutions do not differ from the current one and we   don't see that this would change much when implementing such a mechanism we didn't spent much time on it.


 * Actor
 * Asset Owner


 * Preconditions
 * Overrides templates can only be configured on assets created in the current work file.


 * Postconditions
 * Is a subset of the post conditions of "UC: Change override mode [DRAFT]".


 * Primary Workflow
 * User opens context menu of a property. This can also be a collection property.
 * User selects the "Mark Override" operations. This operation is only available when the property isn't yet marked for override.
 * The property is added in the active object's template and marked for override.


 * Alternative Workflows
 * Alternative 1: array properties
 * User opens context menu of an array property.
 * User selects the "Mark Override All" operation. This operation is only visible when an element of the array isn't mark for override yet.
 * All elements of the property that have not yet been overridden are added in the active object's template and marked for override.
 * Alternative 2: via outliner (hierarchy)
 * User opens the context menu of a local collection and selects "Mark Override All Hierarchy"
 * Supported properties of the asset are added in the asset override template and marked for override.
 * Supported properties of child assets are added into the child's override template and marked for override. (This is done via recursion).
 * Alternative 3: via outliner
 * User opens the context menu of a local asset and selects "Mark Override All"
 * Supported properties of the asset are added in the asset override template and marked for override.
 * Alternative 3: via outliner
 * User opens the context menu of a local asset and selects "Mark Override All"
 * Supported properties of the asset are added in the asset override template and marked for override.
 * User opens the context menu of a local asset and selects "Mark Override All"
 * Supported properties of the asset are added in the asset override template and marked for override.


 * Technical Status
 * Restrictive mode isn't implemented

UC: Mark property to be ignored in permissive mode
In permissive mode a rigger wants to control if a property should not be overridable.


 * Actor
 * Asset Owner


 * Preconditions
 * Overrides templates can only be configured on assets created in the current work file.


 * Postconditions
 * When opening/loading a file where operations do not match a warning is showed to the user and the property is marked on the UI.


 * Primary Workflow
 * User opens context menu of a property. This can also be a collection property.
 * User selects the "Ignore" override operator. This operator is only available when the property isn't marked yet to be ignored.
 * The property is added to the active object's template to be ignored.


 * Alternative Workflows
 * Alternative 1: array properties
 * User opens context menu of an array property.
 * User selects the "Ignore All" operator. This operator is only available when any element of the property isn't marked to be ignored yet.
 * All elements of the property that have not yet been marked to be ignored are added in the active object's template and marked to be ignored.
 * All elements of the property that have not yet been marked to be ignored are added in the active object's template and marked to be ignored.


 * Technical Status
 * Current implementation isn't accessible by users. There is a risk that the current implementation isn't tested as it is missing from the UI.

UC: Remove override operation from override template
You want to be able to remove or reset override operations.


 * Actor
 * Asset Owner


 * Preconditions
 * Overrides templates can only be configured on assets created in the current work file.


 * Postconditions
 * When opening/loading a file where operations do not match a warning is showed to the user and the property is marked on the UI.


 * Primary Workflow
 * User opens context menu of a property.
 * User selects the "Remove Override" or "Remove Single Override" operation.
 * The property is removed from the override template of the asset.


 * Alternative Workflows
 * Alternative 1: array property
 * User opens context menu of an array property.
 * User selects the "Remove Overrides" override operation.
 * All the elements of the array are removed from the override template.
 * Alternative 2: via outliner (hierarchy)
 * User opens the context menu of a local asset and selects "Remove Overrides Hierarchy"
 * The local asset override template is cleared.
 * All override templates of child assets are also cleared. (This is done via recursion).
 * Alternative 3: via outliner
 * User opens the context menu of a local asset and selects "Remove Overrides"
 * The local asset override template is cleared.
 * Alternative 3: via outliner
 * User opens the context menu of a local asset and selects "Remove Overrides"
 * The local asset override template is cleared.
 * User opens the context menu of a local asset and selects "Remove Overrides"
 * The local asset override template is cleared.


 * Technical Status
 * Current implementation isn't accessible by users. There is a risk that the current implementation isn't tested as it is missing from the UI.

UC: Override linked in asset
Before an asset user can use an asset it needs to be marked as library override in the working file. The linked in asset does not need to be the original asset. It could also be an overridden asset. In that case the original asset is loaded including the overrides of the linked asset in any file that is linked to get to the original asset.


 * Actor
 * Asset User


 * Preconditions
 * An asset should already be prepared by an asset owner.
 * The asset should already be linked in into the current work file.


 * Postconditions
 * User can make local changes to the asset.
 * The local changes will be stored in the working file.


 * Primary Workflow
 * Select the linked in asset.
 * In the object menu in the 3d viewport execute the "Relations → Make Library Override ..." operator.
 * Confirm the popup.
 * The asset including all child assets will be overridden.


 * Alternative Workflows
 * Alternative 1: Via outliner
 * In the outliner open the context menu of the loaded asset. Navigate to the "ID Data → Add Library Override Hierarchy" operator.
 * The asset including all child assets will be overridden.
 * Alternative 2: Only override the selected object (no hierarchy)
 * In the outliner open the context menu of the loaded asset. Navigate to the "ID Data → Add Library Override" operator.
 * Only the selected asset will be overridden. Its children are left unchanged.
 * In the outliner open the context menu of the loaded asset. Navigate to the "ID Data → Add Library Override" operator.
 * Only the selected asset will be overridden. Its children are left unchanged.
 * Only the selected asset will be overridden. Its children are left unchanged.


 * Technical Status
 * Implemented

UC: Change a property of an overridden asset
A user of the asset want to record the local changes of a linked asset. These changes can be "any" property. When changes are detected the override structure is marked to record the change. This is done by adding an override operation to track the change.


 * Actor
 * Asset User


 * Preconditions
 * Override linked asset should already be performed.


 * Postconditions
 * Local changes are marked to be stored in the working file.
 * In the UI the property will be displayed in turquoise.


 * Primary Workflow
 * The user interacts with the model in the 3d viewport.
 * For each changed property during interaction
 * If the asset override mode is permissive and the property isn't marked to be ignored go to step 2.4
 * If the asset override mode is restrictive and the property has an operation assigned to this property go to step 2.4
 * Reset the value to the reference data-block value. Continue with next property.
 * if a property operation does not already exist in the override structure of the local data block?
 * Add a replace operation for the changed data.


 * Alternative Workflows
 * Alternative 1: Use UI controls to interact with the asset
 * Similar to the primary workflow, but the changes are detected from UI control interaction.
 * If the asset override mode is permissive and the property isn't marked to be ignored go to step 4
 * If the asset override mode is restrictive and the property has an operation assigned to this property go to step 4
 * Reset the value to the reference data-block value. Exit this workflow.
 * if a property operation does not already exist in the override structure of the local data block? For arrays this can be done per element.
 * Add a replace operation for the changed data.
 * Alternative 2: Use UI controls to add an element to a list
 * The user adds a new element to a list via the properties panel.
 * If the asset override mode is permissive and the property isn't marked to be ignored go to step 5.
 * If the asset override mode is restrictive and the property has an operation assigned to this property go to step 5.
 * Exit this workflow.
 * Add an override operation to Insert the new data block to the list. The override operation would mark the new data to be inserted to the list after the previous element.
 * Alternative 3: Use python scripting
 * Similar to any case mentioned above, except when done via a python script.
 * Exit this workflow.
 * Add an override operation to Insert the new data block to the list. The override operation would mark the new data to be inserted to the list after the previous element.
 * Alternative 3: Use python scripting
 * Similar to any case mentioned above, except when done via a python script.
 * Similar to any case mentioned above, except when done via a python script.
 * Similar to any case mentioned above, except when done via a python script.


 * Technical Status
 * The permissive part is implemented.
 * The restrictive check isn't implemented.
 * The restrictive check isn't implemented.

UC: Change override operation of a property
By default override operations are created to replace the linked in asset property with the data that is stored in the working file.

There are some advanced use cases where the user might want to use a different encoding to store the data to the working file. For example to store scales as a multiplication factor, or to store values as delta.


 * Actor
 * Asset User


 * Preconditions
 * A property must be overridable.


 * Postconditions


 * Primary Workflow
 * User opens context menu from a property. Here it has the option to set a different encoding.
 * For int properties the next encodings are available:
 * Replace
 * Difference
 * For float properties the next encodings are available:
 * Replace
 * Difference
 * Multiply
 * For bit flag enum properties the next encodings are available:
 * Replace
 * And
 * Or
 * Others?
 * For new elements in a collection properties the next encodings are available:
 * Insert Before - The item would be inserted before the next item when reapplying the override operations.
 * Insert After - The item would be inserted after the previous item when reapplying the override operations.
 * The override operation of the property will be updated with the new override operation.
 * Non bit flag enum properties and bool properties can only be stored using the replace override operation.
 * Non bit flag enum properties and bool properties can only be stored using the replace override operation.


 * Alternative Workflows
 * Alternative 1: Array properties
 * Next to the override operations mentioned in the primary workflow there are also settings to update all override operations of the array at once.
 * Replace → Replace All
 * Difference → Difference All
 * Multiply → Multiply All
 * Difference → Difference All
 * Multiply → Multiply All


 * Technical Status
 * Current implementation isn't accessible via the UI. There is a risk that the current implementation isn't tested.

UC: Reset overridden value
As an asset user you want to be able to reset a property to its original value.


 * Actor
 * Asset User


 * Preconditions
 * A property should already be marked to be recorded for override.


 * Postconditions
 * The property will not be marked for library override.


 * Primary Workflow
 * User opens context menu of a property.
 * User selects the "Remove Override" or "Remove Single Override" operator.
 * The property operation is removed from the override structure of the active asset.


 * Alternative Workflows
 * Alternative* 1: array properties
 * User opens context menu of an array property.
 * User selects the "Remove Overrides" override operation.
 * All override operations of the property will be removed from the override structure.
 * Alternative 2: outliner
 * User opens the context menu of the asset in the outliner
 * User selects "Reset Library Override"
 * The override structure of the asset is cleared.
 * Alternative 3: outliner hierarchy
 * User opens the context menu of the asset in the outliner
 * User selects "Reset Library Override Hierarchy"
 * The override structure of the asset and its children are cleared.
 * Alternative 3: outliner hierarchy
 * User opens the context menu of the asset in the outliner
 * User selects "Reset Library Override Hierarchy"
 * The override structure of the asset and its children are cleared.
 * User selects "Reset Library Override Hierarchy"
 * The override structure of the asset and its children are cleared.


 * Technical Status
 * The operators in the context menu/outliner are implemented.

UC: Delete library override hierarchy
Delete this local override (including its hierarchy of override dependencies) and relink its usages to the linked data-blocks


 * Actor
 * Asset User


 * Preconditions
 * An asset should be a library override.


 * Postconditions
 * The asset should be reset


 * Primary Workflow
 * User opens context menu of a property.
 * User selects the "Delete Library Override Hierarchy".
 * The local overrides is cleared and reconstructed based on the linked asset.


 * Alternative Workflows


 * Technical Status
 * The operators in the context menu/outliner are implemented.

UC: Make local
Removes the library override structure from local asset.


 * Actor
 * Asset User


 * Preconditions
 * An asset should be a library override.


 * Postconditions
 * The asset will become a local object
 * The asset can still be part of a library override hierarchy.


 * Primary Workflow
 * User opens object menu in the 3d viewport.
 * The user selects "Relations → Make Local ... → Selected Objects"
 * The override structure of the local override is removed.


 * Alternative Workflows
 * Alternative 1: Including data
 * User opens object menu in the 3d viewport.
 * The user selects "Relations → Make Local ... → Selected Objects And Data"
 * The override structure of the local override and its data are removed.
 * Alternative 2: Including data and materials
 * User opens object menu in the 3d viewport.
 * The user selects "Relations → Make Local ... → Selected Objects, Data and Materials"
 * The override structure of the local override and its data and materials are removed.
 * Alternative 3: All
 * User opens object menu in the 3d viewport.
 * The user selects "Relations → Make Local ... → All"
 * The override structure any asset with library override are removed.
 * Alternative 4: Outliner
 * User opens the context menu of the asset in the outliner
 * User selects "Make Local"
 * The override structure of the asset are removed.
 * The override structure any asset with library override are removed.
 * Alternative 4: Outliner
 * User opens the context menu of the asset in the outliner
 * User selects "Make Local"
 * The override structure of the asset are removed.
 * User selects "Make Local"
 * The override structure of the asset are removed.


 * Technical Status
 * Implemented

UC: Resync library override/Fix conflicts [DRAFT]
Compares the current override hierarchy with the linked hierarchy. It edits the overrides local one to match the linked one. Resyncing is a `git rebase` like process. Where rebase conflicts are resolved automatically.

We currently have "Resync Library Override" operator that supports this use case. This use case was written with the resync operator in mind. There is an idea to have an override view in the outliner. Exact details of the override view in the outliner is in development (February 2021) and will be added to this use case when the design is more detailed.


 * Actor
 * Asset User


 * Preconditions
 * An asset should be a library override.


 * Postconditions
 * Issues that could be solved are solved.


 * Primary Workflow
 * User opens the context menu of the asset in the outliner
 * User selects "Resync Library Override"
 * Linkage issues are automatically resolved.


 * Alternative Workflows


 * Technical Status
 * Implemented, but currently the algorithm is optimized to support more scenarios.