22from .utils import requires
33from deppth2 .entries import AtlasEntry
44
5- import json
6- import os
7- import shutil
8- import re
5+ import json , os , shutil , re , tempfile
96
107try :
118 import PyTexturePacker
129 import PIL .Image
13- import scipy .spatial
1410except ImportError as e :
15- print ("These scripts requires the scipy, PyTexturePacker and pillow packages. Please install them with pip." )
11+ print ("These scripts requires the PyTexturePacker and pillow packages. Please install them with pip." )
1612
1713# To use these scripts, you'll need to pip install scipy and PyTexturePacker in addition to deppth and pillow
1814@requires ('PIL.Image' , 'PyTexturePacker' )
@@ -29,12 +25,13 @@ def build_atlases(source_dir, target_dir, basename, size, include_hulls=False):
2925 namemap [filename .name ] = str (filename )
3026
3127 # Perfom the packing. This will create the spritesheets and primitive atlases, which we'll need to turn to usable ones
32- packer = PyTexturePacker .Packer .create (max_width = size [0 ], max_height = size [1 ], bg_color = 0x00000000 , atlas_format = 'json' ,
28+ packer = PyTexturePacker .Packer .create (max_width = size [0 ], max_height = size [1 ], bg_color = 0x00000000 , atlas_format = 'json' ,
3329 enable_rotated = False , trim_mode = 1 , border_padding = 0 , shape_padding = 0 )
3430 packer .pack (files , f'{ basename } %d' , target_dir )
35-
31+
3632 return (hulls , namemap )
3733
34+ @requires ('PIL.Image' , 'PyTexturePacker' )
3835def build_atlases_hades (source_dir , target_dir , deppth2_pack = True , include_hulls = False , logger = lambda s : None , codec = 'RGBA' ):
3936 """
4037 Build texture atlases from images within a source directory.
@@ -43,22 +40,19 @@ def build_atlases_hades(source_dir, target_dir, deppth2_pack=True, include_hulls
4340 source_dir (str): The root directory to recursively search for images.
4441 target_dir (str): The target directory where the atlases will be saved. The atlases filenames will be named after the target directory name. The .pkg file too. (If created)
4542 deppth2_pack (bool, optional): If True, automatically call pack for putting the built atlases into a SGG .pkg file. Defaults to True.
46- include_hulls (bool, optional): If True, computes convex hull points of images
47- and includes them in the atlas data. Defaults to False.
48- logger (callable, optional): A logging function that accepts a single string argument.
49- Defaults to a no-op (does nothing).
43+ include_hulls (bool, optional): If True, computes convex hull points of images and includes them in the atlas data. Defaults to False.
44+ logger (callable, optional): A logging function that accepts a single string argument. Defaults to a no-op (does nothing).
5045
5146 Returns:
5247 None
5348 """
5449
55- print (target_dir )
50+ print ("Targetted dir:" , target_dir )
5651 basename = os .path .splitext (os .path .basename (target_dir ))[0 ]
57- print (basename )
52+ print ("_PLUGIN.guid, basename:" , basename )
5853
5954 # Regex check to make sure user inserts a mod guid type basename
6055 regexpattern = r"^[a-z0-9]+(\w+[a-z0-9])?-\w+$"
61-
6256 if re .match (regexpattern , basename , flags = re .I | re .A ):
6357 pass
6458 else :
@@ -68,7 +62,6 @@ def build_atlases_hades(source_dir, target_dir, deppth2_pack=True, include_hulls
6862 if os .path .isdir (target_dir ) == True :
6963 print (f"Target directory { target_dir } already exists, deleting it." )
7064 shutil .rmtree (target_dir )
71-
7265 os .mkdir (target_dir , 0o666 )
7366 os .mkdir (os .path .join (target_dir , "manifest" ), 0o666 )
7467 os .mkdir (os .path .join (target_dir , "textures" ), 0o666 )
@@ -77,24 +70,53 @@ def build_atlases_hades(source_dir, target_dir, deppth2_pack=True, include_hulls
7770 files = find_files (source_dir )
7871 hulls = {}
7972 namemap = {}
80- for filename in files :
73+
74+ temp_dir = tempfile .mkdtemp ()
75+ temp_name_mapping = {}
76+ temp_files = []
77+
78+ for file_path in files :
79+ rel_path = os .path .relpath (file_path , source_dir )
80+
8181 # Build hulls for each image so we can store them later
8282 if include_hulls :
83- hulls [filename . name ] = get_hull_points (filename )
83+ hulls [rel_path ] = get_hull_points (file_path )
8484 else :
85- hulls [filename . name ] = []
86- namemap [filename . name ] = str (filename )
85+ hulls [rel_path ] = []
86+ namemap [rel_path ] = str (file_path )
8787
88- # Perfom the packing. This will create the spritesheets and primitive atlases, which we'll need to turn to usable ones
89- packer = PyTexturePacker .Packer .create (max_width = 4096 , max_height = 4096 , bg_color = 0x00000000 , atlas_format = 'json' ,
90- enable_rotated = False , trim_mode = 1 , border_padding = 0 , shape_padding = 1 )
91- packer .pack (files , f'{ basename } %d' )
88+ # Create temporary images with unique names for PyTexturePacker to not override when creating the json file
89+ for rel_path , original_path in namemap .items ():
90+ temp_filename = f"img_{ len (temp_files )} .png"
91+ temp_path = os .path .join (temp_dir , temp_filename )
92+
93+ shutil .copy2 (original_path , temp_path )
94+ temp_files .append (temp_path )
95+ temp_name_mapping [temp_filename ] = rel_path
96+
97+ packer = PyTexturePacker .Packer .create (max_width = 4096 , max_height = 4096 , bg_color = 0x00000000 , atlas_format = 'json' ,
98+ enable_rotated = False , trim_mode = 1 , border_padding = 0 , shape_padding = 1 )
99+ packer .pack (temp_files , f'{ basename } %d' )#use temp instead
92100
93101 # Now, loop through the atlases made and transform them to be the right format
94102 index = 0
95103 atlases = []
96104 manifest_paths = [] # Manifest Path Start
97105 while os .path .exists (f'{ basename } { index } .json' ):
106+ with open (f'{ basename } { index } .json' , 'r' ) as f :
107+ original_data = json .load (f )
108+
109+ # Set the temporary frame names back to path version
110+ new_frames = {}
111+ for temp_filename , frame_data in original_data ['frames' ].items ():
112+ final_path = temp_name_mapping [temp_filename ].replace ('/' , '\\ ' )
113+ new_frames [final_path ] = frame_data
114+
115+ original_data ['frames' ] = new_frames
116+
117+ with open (f'{ basename } { index } .json' , 'w' ) as f :
118+ json .dump (original_data , f , indent = 2 )
119+
98120 atlases .append (transform_atlas (target_dir , basename , f'{ basename } { index } .json' , namemap , hulls , source_dir , manifest_paths ))
99121 os .remove (f'{ basename } { index } .json' )
100122 index += 1
@@ -117,13 +139,23 @@ def build_atlases_hades(source_dir, target_dir, deppth2_pack=True, include_hulls
117139 from .deppth2 import pack
118140 pack (target_dir , f'{ target_dir } .pkg' , * [], logger = lambda s : print (s ), codec = codec )
119141
120- # print the manifest paths, so its easy to see the game path
121- print ("\n Manifest Paths, _PLUGIN.guid followed by directory paths - Use in Codebase:\n " )
142+ print ("\n " + "=" * 70 )
143+ print ("Raw Paths, formatted: _PLUGIN.guid, path" )
144+ print ("USAGE EXAMPLE: rom.path.combine(_PLUGIN.guid, 'GUI\\ \\ Screens\\ \\ image')" )
145+ print ("=" * 70 )
122146 for path in manifest_paths :
123- print (path )
147+ path_clean = path .replace ('/' , '\\ ' ).replace ('\\ ' , '\\ \\ ' )
148+ print (path_clean )
149+
150+ shutil .rmtree (temp_dir )
124151
125152@requires ('scipy.spatial' )
126153def get_hull_points (path ):
154+ try :
155+ import scipy .spatial
156+ except ImportError as e :
157+ print ("To build hulls, you need the scipy package. Please install it with pip." )
158+
127159 im = PIL .Image .open (path )
128160 points = []
129161
@@ -184,7 +216,7 @@ def transform_atlas(target_dir, basename, filename, namemap, hulls={}, source_di
184216 subatlas ['isMulti' ] = False
185217 subatlas ['isMip' ] = False
186218 subatlas ['isAlpha8' ] = False
187- subatlas ['hull' ] = transform_hull (hulls [ texture_name ] , subatlas ['topLeft' ], (subatlas ['rect' ]['width' ], subatlas ['rect' ]['height' ]))
219+ subatlas ['hull' ] = transform_hull (hulls . get ( texture_name , []) , subatlas ['topLeft' ], (subatlas ['rect' ]['width' ], subatlas ['rect' ]['height' ]))
188220 atlas .subAtlases .append (subatlas )
189221
190222 atlas .export_file (f'{ os .path .splitext (filename )[0 ]} .atlas.json' )
0 commit comments