diff --git a/src/nnnotes/unity.py b/src/nnnotes/unity.py index 087b046..ca2c7f2 100644 --- a/src/nnnotes/unity.py +++ b/src/nnnotes/unity.py @@ -327,18 +327,23 @@ def _head_node(node: TypeTreeNode) -> TypeTreeNode | None: return head -def script_class(obj) -> str: - """Class name of a MonoBehaviour (needs the monoscript bundle loaded). Reads the header up to m_Script with the - object's own typetree (not its fields); the whole object when that is not possible.""" +def script_class(obj) -> str | None: + """Class name of a MonoBehaviour (needs the monoscript bundle loaded); None for a missing script (null m_Script). + Reads the header up to m_Script with the object's own typetree (not its fields); the whole object when that is + not possible.""" try: head = _head_node(obj._get_typetree_node()) if head is not None: - ms = deref(obj, obj.read_typetree(head, check_read=False)["m_Script"]) - if ms is not None: - return ms.read().m_ClassName + pptr = obj.read_typetree(head, check_read=False)["m_Script"] + if not pptr["m_PathID"]: + return None + return deref(obj, pptr).read().m_ClassName except Exception: pass - return obj.read().m_Script.read().m_ClassName + script = obj.read().m_Script + if not script.m_PathID: + return None + return script.read().m_ClassName def strip_pptrs(tt: dict) -> dict: diff --git a/tests/test_speed_exact.py b/tests/test_speed_exact.py index d42c40f..d96b33e 100644 --- a/tests/test_speed_exact.py +++ b/tests/test_speed_exact.py @@ -137,6 +137,19 @@ def test_head_node_cut_after_script(): assert unity._head_node(TypeTreeNode(0, "X", "Base", -1, 1, m_Children=kids[:2])) is None +def test_script_class_missing_script_is_none(): + kids = [TypeTreeNode(1, t, n, 0, 0) for t, n in (("PPtr", "m_GameObject"), ("UInt8", "m_Enabled"), + ("PPtr", "m_Script"))] + node = TypeTreeNode(0, "MonoBehaviour", "Base", -1, 1, m_Children=kids) + null = {"m_FileID": 0, "m_PathID": 0} + obj = SimpleNamespace(_get_typetree_node=lambda: node, + read_typetree=lambda *a, **k: {"m_GameObject": null, "m_Enabled": 1, "m_Script": null}) + assert unity.script_class(obj) is None + whole = SimpleNamespace(_get_typetree_node=lambda: None, + read=lambda: SimpleNamespace(m_Script=SimpleNamespace(m_PathID=0))) + assert unity.script_class(whole) is None + + # ---------------------------------------------------------------- typetree values def ref_value(ex, owner, v): if unity.is_pptr(v):