From 94627debc6580513136b18bffd327ed41511a8d1 Mon Sep 17 00:00:00 2001 From: Jonas Holzman Date: Thu, 20 Mar 2025 16:59:45 +0100 Subject: [PATCH] MRO based Dumper resolution system --- core/dumper.py | 62 +++++++++++++++++++++++--------------------------- utils.py | 6 +++++ 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 utils.py diff --git a/core/dumper.py b/core/dumper.py index d4d37ff..a4ac200 100644 --- a/core/dumper.py +++ b/core/dumper.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json from copy import copy from os.path import abspath @@ -5,6 +7,8 @@ from pprint import pprint import bpy +from .. import utils + format_token = "#FMT:NODE_KIT#" @@ -29,14 +33,16 @@ def get_default(prop: bpy.types.Property): return prop.default -def get_dumper(bl_object: bpy.types.bpy_struct): - """Get the corresponding dumper for a given Blender object, or its closest base type""" - for dp in dumpers: - if isinstance(bl_object, dp.bl_type): # TODO: Cascade system - return dp +def get_dumper(bl_object: bpy.types.bpy_struct) -> type[Dumper]: + """Get the corresponding dumper for a given Blender object, or its closest base type using its MRO""" - return Dumper or None + for cls in bl_object.__class__.mro(): + dumper_map = DumperRegistry().dumper_map + if cls in dumper_map: + return dumper_map[cls] + # Fallback to base Dumper if no matches are found + return Dumper def get_current_node_tree(data): if data.get("_new", {}).get("type") == "GeometryNodeTree": @@ -780,31 +786,19 @@ class ViewLayers(PropCollection): Dumper.load(value, view_layer) -dumpers = [ - CompositorNodeRLayers, - CompositorNodeGlare, - Node, - NodeSocket, - NodeTree, - NodeLink, - NodeTreeInterface, - NodeTreeInterfaceSocket, - NodeGeometryRepeatOutputItems, - Image, - Material, - Object, - Scene, - Collection, - ViewLayer, - CurveMapPoints, - ColorRampElements, - NodeInputs, - NodeOutputs, - Nodes, - ViewLayers, - PropCollection, - AOVs, - PropArray, - CompositorNodeOutputFileLayerSlots, - CompositorNodeOutputFileFileSlots, -] +class DumperRegistry: + """Singleton-like class that holds a map of all parsers, constructed on first instantiation""" + dumper_map = None + + def __init__(self): + if self.dumper_map is None: + self.construct_dumper_map() + + @classmethod + def construct_dumper_map(cls): + cls.dumper_map = {} + + for subclass in utils.all_subclasses(Dumper): + assert hasattr(subclass, "bl_type") + cls.dumper_map[subclass.bl_type] = subclass + print(cls.dumper_map) \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..df123bb --- /dev/null +++ b/utils.py @@ -0,0 +1,6 @@ + +def all_subclasses(cls): + return set(cls.__subclasses__()).union( + [s for c in cls.__subclasses__() for s in all_subclasses(c)] + ) +