@@ -36,8 +36,8 @@ def traverse(self) -> Iterator[TypeTreeNode]:
3636 def parse (cls , reader : EndianBinaryReader , version : int ) -> TypeTreeNode :
3737 # stack approach is way faster than recursion
3838 # using a fake root node to avoid special case for root node
39- dummy_node = TypeTreeNode (- 1 , "" , "" , 0 , 0 , 0 , [])
40- dummy_root = TypeTreeNode (- 1 , "" , "" , 0 , 0 , 0 , [dummy_node ])
39+ dummy_node = cls (- 1 , "" , "" , 0 , 0 , 0 , [])
40+ dummy_root = cls (- 1 , "" , "" , 0 , 0 , 0 , [dummy_node ])
4141
4242 stack : List [Tuple [TypeTreeNode , int ]] = [(dummy_root , 1 )]
4343 while stack :
@@ -47,7 +47,7 @@ def parse(cls, reader: EndianBinaryReader, version: int) -> TypeTreeNode:
4747 else :
4848 stack [- 1 ] = (parent , count - 1 )
4949
50- node = TypeTreeNode (
50+ node = cls (
5151 m_Level = parent .m_Level + 1 ,
5252 m_Type = reader .read_string_to_null (),
5353 m_Name = reader .read_string_to_null (),
@@ -87,13 +87,13 @@ def read_string(reader: EndianBinaryReader, value: int) -> str:
8787 offset = value & 0x7FFFFFFF
8888 return CommonString .get (offset , str (offset ))
8989
90- fake_root : TypeTreeNode = TypeTreeNode (- 1 , "" , "" , 0 , 0 , 0 , [])
90+ fake_root : TypeTreeNode = cls (- 1 , "" , "" , 0 , 0 , 0 , [])
9191 stack : List [TypeTreeNode ] = [fake_root ]
9292 parent = fake_root
9393 prev = fake_root
9494
9595 for raw_node in node_struct .iter_unpack (struct_data ):
96- node = TypeTreeNode (
96+ node = cls (
9797 ** dict (zip (keys [:3 ], raw_node [:3 ])),
9898 ** dict (zip (keys [5 :], raw_node [5 :])),
9999 m_Type = read_string (stringbuffer_reader , raw_node [3 ]),
@@ -112,6 +112,28 @@ def read_string(reader: EndianBinaryReader, value: int) -> str:
112112
113113 return fake_root .m_Children [0 ]
114114
115+ @classmethod
116+ def from_list (cls , nodes : List [dict ]) -> TypeTreeNode :
117+ fake_root : TypeTreeNode = cls (- 1 , "" , "" , 0 , 0 , 0 , [])
118+ stack : List [TypeTreeNode ] = [fake_root ]
119+ parent = fake_root
120+ prev = fake_root
121+
122+ for dict_node in nodes :
123+ node = cls (** dict_node )
124+
125+ if node .m_Level > prev .m_Level :
126+ stack .append (parent )
127+ parent = prev
128+ elif node .m_Level < prev .m_Level :
129+ while node .m_Level <= parent .m_Level :
130+ parent = stack .pop ()
131+
132+ parent .m_Children .append (node )
133+ prev = node
134+
135+ return fake_root .m_Children [0 ]
136+
115137 def dump (self , writer : EndianBinaryWriter , version : int ):
116138 stack : list [TypeTreeNode ] = [self ]
117139 while stack :
@@ -181,6 +203,15 @@ def write_node(node: TypeTreeNode):
181203 writer .write (node_writer .bytes )
182204 writer .write (string_writer .bytes )
183205
206+ def dump_structure (self , indent : str = " " ) -> str :
207+ # dump structure similar to https://github.com/AssetRipper/TypeTreeDumps/blob/main/StructsDump
208+ sb = [
209+ f"{ indent } { self .m_Type } { self .m_Name } // ByteSize{{{ self .m_ByteSize :X} }}, Index{{{ self .m_Index } }}, Version{{{ self .m_Version } }}, TypeFlags{{{ self .m_TypeFlags } }}, MetaFlag{{{ self .m_MetaFlag } }}"
210+ ]
211+ for child in self .m_Children :
212+ sb .append (child .dump_structure (indent + " " ))
213+ return "\n " .join (sb )
214+
184215
185216COMMONSTRING_CACHE : Dict [Optional [UnityVersion ], Dict [int , str ]] = {}
186217
0 commit comments