Overrides: API to create an override template.

This is functionality that isn't accessible via the user interface. The
API allows the creation and modification of an override template that
holds rules that needs to be checked when overriding the asset.

The API is setup that it cannot be changed after creation. Later on when
the system is more mature we will allow changing overrides operations.

NOTE: This is an experimental feature and should not be used in productions.

Reviewed By: mont29, sebbas

Differential Revision: https://developer.blender.org/D10792
This commit is contained in:
2021-03-29 09:53:12 +02:00
parent 27fa2507a1
commit 87f9405c9a
7 changed files with 326 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
# Apache License, Version 2.0
# ./blender.bin --background -noaudio --python tests/python/bl_blendfile_library_overrides.py
# ./blender.bin --background -noaudio --python tests/python/bl_blendfile_library_overrides.py -- --output-dir=/tmp/
import pathlib
import bpy
import sys
@@ -16,6 +16,8 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
OBJECT_LIBRARY_PARENT = "LibMeshParent"
MESH_LIBRARY_CHILD = "LibMeshChild"
OBJECT_LIBRARY_CHILD = "LibMeshChild"
MESH_LIBRARY_PERMISSIVE = "LibMeshPermissive"
OBJECT_LIBRARY_PERMISSIVE = "LibMeshPermissive"
def __init__(self, args):
self.args = args
@@ -33,6 +35,14 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
obj_child = bpy.data.objects.new(TestLibraryOverrides.OBJECT_LIBRARY_CHILD, object_data=mesh_child)
obj_child.parent = obj
bpy.context.collection.objects.link(obj_child)
mesh = bpy.data.meshes.new(TestLibraryOverrides.MESH_LIBRARY_PERMISSIVE)
obj = bpy.data.objects.new(TestLibraryOverrides.OBJECT_LIBRARY_PERMISSIVE, object_data=mesh)
bpy.context.collection.objects.link(obj)
obj.override_template_create()
prop = obj.override_library.properties.add(rna_path='scale')
prop.operations.add(operation='NOOP')
bpy.ops.wm.save_as_mainfile(filepath=str(self.output_path), check_existing=False, compress=False)
def __ensure_override_library_updated(self):
@@ -47,29 +57,108 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
bpy.ops.wm.link(directory=str(link_dir), filename=TestLibraryOverrides.OBJECT_LIBRARY_PARENT)
obj = bpy.data.objects[TestLibraryOverrides.OBJECT_LIBRARY_PARENT]
assert(obj.override_library is None)
self.assertIsNone(obj.override_library)
local_id = obj.override_create()
assert(local_id.override_library)
assert(local_id.data.override_library is None)
self.assertIsNotNone(local_id.override_library)
self.assertIsNone(local_id.data.override_library)
assert(len(local_id.override_library.properties) == 0)
local_id.location.y = 1.0
self.__ensure_override_library_updated()
assert (len(local_id.override_library.properties) == 1)
assert(len(local_id.override_library.properties) == 1)
override_prop = local_id.override_library.properties[0]
assert(override_prop.rna_path == "location");
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert (override_operation.operation == 'REPLACE')
assert(override_operation.operation == 'REPLACE')
# Setting location.y overridded all elements in the location array. -1 is a wildcard.
assert(override_operation.subitem_local_index == -1)
def test_link_permissive(self):
"""
Linked assets with a permissive template.
- Checks if the NOOP is properly handled.
- Checks if the correct properties and operations are created/updated.
"""
bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
bpy.data.orphans_purge()
link_dir = self.output_path / "Object"
bpy.ops.wm.link(directory=str(link_dir), filename=TestLibraryOverrides.OBJECT_LIBRARY_PERMISSIVE)
obj = bpy.data.objects[TestLibraryOverrides.OBJECT_LIBRARY_PERMISSIVE]
self.assertIsNotNone(obj.override_library)
local_id = obj.override_create()
self.assertIsNotNone(local_id.override_library)
self.assertIsNone(local_id.data.override_library)
assert(len(local_id.override_library.properties) == 1)
override_prop = local_id.override_library.properties[0]
assert(override_prop.rna_path == "scale");
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'NOOP')
assert(override_operation.subitem_local_index == -1)
local_id.location.y = 1.0
local_id.scale.x = 0.5
# XXX(jbakker): This change should not applied. But it is as the library
# overrides aren't updated yet. We should expect 1.0
assert(local_id.scale.x == 0.5)
assert(local_id.location.y == 1.0)
self.__ensure_override_library_updated()
assert(local_id.scale.x == 1.0)
assert(local_id.location.y == 1.0)
assert(len(local_id.override_library.properties) == 2)
override_prop = local_id.override_library.properties[0]
assert(override_prop.rna_path == "scale");
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'NOOP')
assert(override_operation.subitem_local_index == -1)
override_prop = local_id.override_library.properties[1]
assert(override_prop.rna_path == "location");
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'REPLACE')
assert (override_operation.subitem_local_index == -1)
class TestLibraryTemplate(TestHelper, unittest.TestCase):
MESH_LIBRARY_PERMISSIVE = "LibMeshPermissive"
OBJECT_LIBRARY_PERMISSIVE = "LibMeshPermissive"
def __init__(self, args):
pass
def test_permissive_template(self):
"""
Test setting up a permissive template.
"""
bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
mesh = bpy.data.meshes.new(TestLibraryTemplate.MESH_LIBRARY_PERMISSIVE)
obj = bpy.data.objects.new(TestLibraryTemplate.OBJECT_LIBRARY_PERMISSIVE, object_data=mesh)
bpy.context.collection.objects.link(obj)
assert(obj.override_library is None)
obj.override_template_create()
assert(obj.override_library is not None)
assert(len(obj.override_library.properties) == 0)
prop = obj.override_library.properties.add(rna_path='scale')
assert(len(obj.override_library.properties) == 1)
assert(len(prop.operations) == 0)
operation = prop.operations.add(operation='NOOP')
assert(len(prop.operations) == 1)
assert(operation.operation == 'NOOP')
TESTS = (
TestLibraryOverrides,
TestLibraryTemplate,
)
@@ -95,6 +184,7 @@ def main():
# Don't write thumbnails into the home directory.
bpy.context.preferences.filepaths.use_save_preview_images = False
bpy.context.preferences.experimental.use_override_templates = True
for Test in TESTS:
Test(args).run_all_tests()