1919 Texture2D ,
2020)
2121from UnityPy .enums .ClassIDType import ClassIDType
22- from UnityPy .files import SerializedFile
22+ from UnityPy .files import ObjectReader , SerializedFile
2323
2424
2525def export_obj (
26- obj : Union [Object , PPtr ],
27- fp : Path ,
26+ obj : Union [ObjectReader , PPtr ],
27+ fp : str ,
2828 append_name : bool = False ,
2929 append_path_id : bool = False ,
3030 export_unknown_as_typetree : bool = False ,
@@ -53,25 +53,29 @@ def export_obj(
5353 return []
5454
5555 # set filepath
56- obj = obj .read ()
56+ if isinstance (obj , PPtr ):
57+ obj = obj .deref ()
58+
59+ instance = obj .parse_as_object ()
5760
5861 # a filter that returned True during an earlier extract_assets check can return False now with more info from read()
59- if asset_filter and not asset_filter (obj ):
62+ if asset_filter and not asset_filter (instance ):
6063 return []
6164
6265 if append_name :
66+ name = getattr (instance , "m_Name" , obj .type .name )
6367 fp = os .path .join (
6468 fp ,
65- obj . m_Name if getattr ( obj , "m_Name" ) else obj . object_reader . type . name , # noqa: B009
69+ name ,
6670 )
6771
6872 fp , extension = os .path .splitext (fp )
6973
7074 if append_path_id :
71- fp = f"{ fp } _{ obj .object_reader . path_id } "
75+ fp = f"{ fp } _{ obj .m_PathID } "
7276
7377 # export
74- return export_func (obj , fp , extension )
78+ return export_func (instance , fp , extension )
7579
7680
7781def extract_assets (
@@ -193,40 +197,28 @@ def exportShader(obj: Shader, fp: str, extension=".txt") -> List[Tuple[Serialize
193197 return [(obj .assets_file , obj .object_reader .path_id )]
194198
195199
196- def exportMonoBehaviour (
197- obj : Union [MonoBehaviour , Object ], fp : str , extension : str = ""
198- ) -> List [Tuple [SerializedFile , int ]]:
200+ def exportMonoBehaviour (obj : ObjectReader , fp : str , extension : str = "" ) -> List [Tuple [SerializedFile , int ]]:
199201 export = None
200202
201- if obj .object_reader .serialized_type .node :
202- # a typetree is available from the SerializedFile for this object
203- export = obj .object_reader .read_typetree ()
204- elif isinstance (obj , MonoBehaviour ):
205- # try to get the typetree from the MonoBehavior script
206- script_ptr = obj .m_Script
207- if script_ptr :
208- # looks like we have a script
209- script = script_ptr .read ()
210- # check if there is a locally stored typetree for it
211- nodes = MONOBEHAVIOUR_TYPETREES .get (script .m_AssemblyName , {}).get (script .m_ClassName , None )
212- if nodes :
213- export = obj .object_reader .read_typetree (nodes )
214- else :
215- export = obj .object_reader .read_typetree ()
203+ try :
204+ export = obj .parse_as_dict ()
205+ except Exception :
206+ pass
216207
217208 if not export :
218209 extension = ".bin"
219- export = obj .object_reader . raw_data
210+ export = obj .raw_data
220211 else :
221212 extension = ".json"
222213 export = json .dumps (export , indent = 4 , ensure_ascii = False ).encode ("utf8" , errors = "surrogateescape" )
223214 with open (f"{ fp } { extension } " , "wb" ) as f :
224215 f .write (export )
225- return [(obj .assets_file , obj .object_reader . path_id )]
216+ return [(obj .assets_file , obj .path_id )]
226217
227218
228- def exportAudioClip (obj : AudioClip , fp : str , extension : str = "" ) -> List [Tuple [SerializedFile , int ]]:
229- samples = obj .samples
219+ def exportAudioClip (obj : ObjectReader , fp : str , extension : str = "" ) -> List [Tuple [SerializedFile , int ]]:
220+ clip = obj .parse_as_object ()
221+ samples = clip .samples
230222 if len (samples ) == 0 :
231223 pass
232224 elif len (samples ) == 1 :
@@ -237,19 +229,18 @@ def exportAudioClip(obj: AudioClip, fp: str, extension: str = "") -> List[Tuple[
237229 for name , clip_data in samples .items ():
238230 with open (os .path .join (fp , f"{ name } .wav" ), "wb" ) as f :
239231 f .write (clip_data )
240- return [(obj .assets_file , obj .object_reader . path_id )]
232+ return [(obj .assets_file , obj .path_id )]
241233
242234
243- def exportSprite (obj : Sprite , fp : str , extension : str = ".png" ) -> List [Tuple [SerializedFile , int ]]:
244- if not extension :
245- extension = ".png"
246- obj .image .save (f"{ fp } { extension } " )
235+ def exportSprite (obj : ObjectReader , fp : str , extension : str = ".png" ) -> List [Tuple [SerializedFile , int ]]:
236+ sprite = obj .parse_as_object ()
237+ sprite .image .save (f"{ fp } { extension } " )
247238 exported = [
248- (obj .assets_file , obj .object_reader . path_id ),
249- (obj .m_RD .texture .assetsfile , obj .m_RD .texture .path_id ),
239+ (obj .assets_file , obj .path_id ),
240+ (sprite .m_RD .texture .assetsfile , sprite .m_RD .texture .path_id ),
250241 ]
251- alpha_assets_file = getattr (obj .m_RD .alphaTexture , "assets_file" , None )
252- alpha_path_id = getattr (obj .m_RD .alphaTexture , "path_id" , None )
242+ alpha_assets_file = getattr (sprite .m_RD .alphaTexture , "assets_file" , None )
243+ alpha_path_id = getattr (sprite .m_RD .alphaTexture , "path_id" , None )
253244 if alpha_path_id and alpha_assets_file :
254245 exported .append ((alpha_assets_file , alpha_path_id ))
255246 return exported
@@ -303,34 +294,34 @@ def exportGameObject(obj: GameObject, fp: str, extension: str = "") -> List[Tupl
303294MONOBEHAVIOUR_TYPETREES : Dict [ASSEMBLY_NAME_DLL , Dict [CLASS_NAME , List [Dict ]]] = {}
304295
305296
306- def crawl_obj (obj : Object , ret : Optional [dict ] = None ) -> Dict [int , Union [Object , PPtr ]]:
297+ def crawl_obj (obj : Union [ Object , ObjectReader , PPtr ] , ret : Optional [dict ] = None ) -> Dict [int , Union [Object , PPtr ]]:
307298 """Crawls through the data struture of the object
308299 and returns a list of all the components.
309300 """
310301 if not ret :
311302 ret = {}
312303
304+ values : Sequence
313305 if isinstance (obj , PPtr ):
314- if obj .path_id == 0 and obj .file_id == 0 and obj .index == - 2 :
306+ if obj .m_PathID == 0 and obj .m_FileID == 0 and obj .m_Index == - 2 :
315307 return ret
316308 try :
317- obj = obj .read ()
309+ instance = obj .deref_parse_as_dict ()
310+ values = instance .values ()
318311 except AttributeError :
319312 return ret
313+ elif isinstance (obj , Object ):
314+ values = obj .__dict__ .values ()
315+ elif isinstance (obj , ObjectReader ):
316+ values = obj .parse_as_dict ().values ()
320317 else :
321318 return ret
322- ret [obj .path_id ] = obj
323319
324- # MonoBehaviour really on their typetree
325- # while Object denotes that the class of the object isn't implemented yet
326- if isinstance (obj , (MonoBehaviour , Object )):
327- data = obj .read_typetree ().__dict__ .values ()
328- else :
329- data = obj .__dict__ .values ()
320+ ret [obj .m_PathID ] = obj
330321
331- for value in flatten (data ):
322+ for value in flatten (values ):
332323 if isinstance (value , (Object , PPtr )):
333- if value .path_id in ret :
324+ if value .m_PathID in ret :
334325 continue
335326 crawl_obj (value , ret )
336327
0 commit comments