212 lines
7.1 KiB
Python
212 lines
7.1 KiB
Python
# SPDX-FileCopyrightText: 2020-2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import unittest
|
|
import bpy
|
|
import pathlib
|
|
import sys
|
|
from rna_prop_ui import rna_idprop_quote_path
|
|
|
|
"""
|
|
blender -b --factory-startup --python tests/python/bl_animation_drivers.py -- --testdir /path/to/tests/data/animation
|
|
"""
|
|
|
|
|
|
class AbstractEmptyDriverTest:
|
|
def setUp(self):
|
|
super().setUp()
|
|
bpy.ops.wm.read_homefile(use_factory_startup=True)
|
|
self.obj = bpy.data.objects['Cube']
|
|
|
|
def assertPropValue(self, prop_name, value):
|
|
self.assertEqual(self.obj[prop_name], value)
|
|
|
|
|
|
def _make_context_driver(obj, prop_name, ctx_type, ctx_path, index=None, fallback=None, force_python=False):
|
|
obj[prop_name] = 0
|
|
fcu = obj.driver_add(rna_idprop_quote_path(prop_name), -1)
|
|
drv = fcu.driver
|
|
|
|
if force_python:
|
|
# Expression that requires full python interpreter
|
|
drv.type = 'SCRIPTED'
|
|
drv.expression = '[var][0]'
|
|
else:
|
|
drv.type = 'SUM'
|
|
|
|
var = drv.variables.new()
|
|
var.name = "var"
|
|
var.type = 'CONTEXT_PROP'
|
|
tgt = var.targets[0]
|
|
tgt.context_property = ctx_type
|
|
tgt.data_path = rna_idprop_quote_path(ctx_path) + (f"[{index}]" if index is not None else "")
|
|
|
|
if fallback is not None:
|
|
tgt.use_fallback_value = True
|
|
tgt.fallback_value = fallback
|
|
|
|
return fcu
|
|
|
|
|
|
def _is_fallback_used(fcu):
|
|
return fcu.driver.variables[0].targets[0].is_fallback_used
|
|
|
|
|
|
class ContextSceneDriverTest(AbstractEmptyDriverTest, unittest.TestCase):
|
|
""" Ensure keying things by name or with a keying set adds the right keys. """
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
bpy.context.scene["test_property"] = 123
|
|
|
|
def test_context_valid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_valid', 'ACTIVE_SCENE', 'test_property')
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertPropValue('test_valid', 123)
|
|
|
|
def test_context_invalid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_invalid', 'ACTIVE_SCENE', 'test_property_bad')
|
|
bpy.context.view_layer.update()
|
|
self.assertFalse(fcu.driver.is_valid)
|
|
|
|
def test_context_fallback(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback', 'ACTIVE_SCENE', 'test_property_bad', fallback=321)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertTrue(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback', 321)
|
|
|
|
def test_context_fallback_valid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback_valid', 'ACTIVE_SCENE', 'test_property', fallback=321)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertFalse(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback_valid', 123)
|
|
|
|
def test_context_fallback_python(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback_py', 'ACTIVE_SCENE', 'test_property_bad', fallback=321, force_python=True)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertTrue(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback_py', 321)
|
|
|
|
|
|
class ContextSceneArrayDriverTest(AbstractEmptyDriverTest, unittest.TestCase):
|
|
""" Ensure keying things by name or with a keying set adds the right keys. """
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
bpy.context.scene["test_property"] = [123, 456]
|
|
|
|
def test_context_valid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_valid', 'ACTIVE_SCENE', 'test_property', index=0)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertPropValue('test_valid', 123)
|
|
|
|
def test_context_invalid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_invalid', 'ACTIVE_SCENE', 'test_property', index=2)
|
|
bpy.context.view_layer.update()
|
|
self.assertFalse(fcu.driver.is_valid)
|
|
|
|
def test_context_fallback(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback', 'ACTIVE_SCENE', 'test_property', index=2, fallback=321)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertTrue(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback', 321)
|
|
|
|
def test_context_fallback_valid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback_valid', 'ACTIVE_SCENE', 'test_property', index=0, fallback=321)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertFalse(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback_valid', 123)
|
|
|
|
def test_context_fallback_python(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback_py', 'ACTIVE_SCENE', 'test_property', index=2, fallback=321, force_python=True)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertTrue(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback_py', 321)
|
|
|
|
|
|
def _select_view_layer(index):
|
|
bpy.context.window.view_layer = bpy.context.scene.view_layers[index]
|
|
|
|
|
|
class ContextViewLayerDriverTest(AbstractEmptyDriverTest, unittest.TestCase):
|
|
""" Ensure keying things by name or with a keying set adds the right keys. """
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
bpy.ops.scene.view_layer_add(type='COPY')
|
|
scene = bpy.context.scene
|
|
scene.view_layers[0]['test_property'] = 123
|
|
scene.view_layers[1]['test_property'] = 456
|
|
_select_view_layer(0)
|
|
|
|
def test_context_valid(self):
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_valid', 'ACTIVE_VIEW_LAYER', 'test_property')
|
|
|
|
_select_view_layer(0)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertPropValue('test_valid', 123)
|
|
|
|
_select_view_layer(1)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertPropValue('test_valid', 456)
|
|
|
|
def test_context_fallback(self):
|
|
del bpy.context.scene.view_layers[1]['test_property']
|
|
|
|
fcu = _make_context_driver(
|
|
self.obj, 'test_fallback', 'ACTIVE_VIEW_LAYER', 'test_property', fallback=321)
|
|
|
|
_select_view_layer(0)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertFalse(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback', 123)
|
|
|
|
_select_view_layer(1)
|
|
bpy.context.view_layer.update()
|
|
self.assertTrue(fcu.driver.is_valid)
|
|
self.assertTrue(_is_fallback_used(fcu))
|
|
self.assertPropValue('test_fallback', 321)
|
|
|
|
|
|
def main():
|
|
global args
|
|
import argparse
|
|
|
|
if '--' in sys.argv:
|
|
argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:]
|
|
else:
|
|
argv = sys.argv
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--testdir', required=True, type=pathlib.Path)
|
|
args, remaining = parser.parse_known_args(argv)
|
|
|
|
unittest.main(argv=remaining)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|