From 91c87e7dbcb3029d23ce0baa9b2bcab1394381c3 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Wed, 28 Oct 2026 10:43:38 +0100 Subject: Apply only the figure's own dial values Co-Authored-By: Claude Sonnet 5.5 --- generat3d/scene.py | 8 +++++++- tests/test_scene.py | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/generat3d/scene.py b/generat3d/scene.py index 08ad4ee..03b92f7 100644 --- a/generat3d/scene.py +++ b/generat3d/scene.py @@ -114,6 +114,7 @@ class _Loader: raise Error(f"{self.path}: no figure in scene") if len(figs) > 1: raise Error(f"{self.path}: v1 handles one figure per scene, found {len(figs)}") + self.inst = {figs[0][0]["id"], figs[0][0].get("name")} - {None} self.figure = self._figure(*figs[0]) self.ids = {n.id for n in self.figure.nodes} | {n.name for n in self.figure.nodes} self._morphs(figs[0][1]) @@ -222,6 +223,9 @@ class _Loader: for m in scene.get("modifiers", []): if "url" not in m: continue + parent = parse_url(m.get("parent", ""))[2] + if parent and parent not in self.inst: + continue # belongs to another node k = key(self.figure.id, parse_url(m["url"])[2], "value") v = _number(m["url"], m.get("channel", {}).get("current_value", 0.0)) if k not in self.graph.props: @@ -233,7 +237,9 @@ class _Loader: elif v: missing.append(m["url"]) for a in scene.get("animations", []): - channel = parse_url(a["url"])[3] + prefix, _, _, channel = parse_url(a["url"]) + if prefix and prefix not in self.inst and prefix not in self.ids: + continue # belongs to another node v = _number(a["url"], a.get("keys", [[0, 0.0]])[0][1]) if channel.split("/")[0] in POSE_REST: posed = posed or bool(v) diff --git a/tests/test_scene.py b/tests/test_scene.py index 13b80bb..6ea7fa3 100644 --- a/tests/test_scene.py +++ b/tests/test_scene.py @@ -190,3 +190,23 @@ class SceneTest(unittest.TestCase): "channel": {"id": "value", "current_value": 1}}]}), [root]) self.assertIn("Fig:Bulk?value", scene.figure.morphs) self.assertEqual(scene.graph.props["Fig:Bulk?value"].value, 1) + + def tall(self, parent="#Fig", value=1, url="/data/Test/Fig/Morphs/Test/Tall.dsf#Tall"): + return {"id": url.split("#")[1], "url": url, "parent": parent, + "channel": {"id": "value", "current_value": value}} + + def test_other_node_modifier_ignored(self): + scene, _ = load_quiet(self.duf({"nodes": self.base_nodes(), "modifiers": [ + self.tall(), + self.tall("#Shirt", 0, "/data/Test/Shirt/Shirt.dsf#Tall")]})) + self.assertEqual(scene.graph.props["Fig:Tall?value"].value, 1) + + def test_other_node_animation_ignored(self): + scene, _ = load_quiet(self.duf({"nodes": self.base_nodes(), "animations": [ + {"url": "Fig:#Tall?value", "keys": [[0, 1]]}, + {"url": "Shirt:#Tall?value", "keys": [[0, 0]]}]})) + self.assertEqual(scene.graph.props["Fig:Tall?value"].value, 1) + + def test_follower_modifier_not_reported_missing(self): + load_quiet(self.duf({"nodes": self.base_nodes(), "modifiers": [ + self.tall("#Shirt", 1, "/data/Test/Shirt/Shirt.dsf#Loose")]})) -- cgit v1.2.3