88import webbrowser
99import xml .etree .ElementTree as ET
1010import json
11+ import time
1112
1213from PIL import Image
1314import tkinter as tk
@@ -243,7 +244,13 @@ def store_input():
243244
244245def process_directory (input_dir , output_dir , progress_var , tk_root , create_gif , create_webp , keep_frames , set_framerate , set_loopdelay , set_threshold ):
245246 if not (create_gif or create_webp or keep_frames ):
247+ messagebox .showinfo ("Information" , "Nothing to process.\n Please select tasks." )
246248 return
249+
250+ total_frames_generated = 0
251+ total_gifs_generated = 0
252+ total_sprites_failed = 0
253+
247254 progress_var .set (0 )
248255 total_files = count_xml_files (input_dir )
249256 progress_bar ["maximum" ] = total_files
@@ -253,6 +260,8 @@ def process_directory(input_dir, output_dir, progress_var, tk_root, create_gif,
253260 else :
254261 cpuThreads = os .cpu_count () // 2
255262
263+ start_time = time .time ()
264+
256265 with concurrent .futures .ThreadPoolExecutor (max_workers = cpuThreads ) as executor :
257266 futures = []
258267
@@ -270,23 +279,42 @@ def process_directory(input_dir, output_dir, progress_var, tk_root, create_gif,
270279
271280 for future in concurrent .futures .as_completed (futures ):
272281 try :
273- future .result ()
282+ result = future .result ()
283+ total_frames_generated += result ['frames_generated' ]
284+ total_gifs_generated += result ['gifs_generated' ]
285+ total_sprites_failed += result ['sprites_failed' ]
274286 except ET .ParseError as e :
287+ total_sprites_failed += 1
275288 messagebox .showerror ("Error" , f"Something went wrong!!\n { e } " )
276289 if not messagebox .askyesno ("Continue?" , "Do you want to try continue processing?" ):
277290 sys .exit ()
278291 except Exception as e :
292+ total_sprites_failed += 1
279293 messagebox .showerror ("Error" , f"Something went wrong!!\n { str (e )} " )
280294 if not messagebox .askyesno ("Continue?" , "Do you want to try continue processing?" ):
281295 sys .exit ()
282296
283297 progress_var .set (progress_var .get () + 1 )
284298 tk_root .update_idletasks ()
285299
286- messagebox .showinfo ("Information" ,"Finished processing all files." )
300+ end_time = time .time ()
301+ duration = end_time - start_time
302+ minutes , seconds = divmod (duration , 60 )
303+
304+ messagebox .showinfo (
305+ "Information" ,
306+ f"Finished processing all files.\n \n "
307+ f"Frames Generated: { total_frames_generated } \n "
308+ f"GIFs Generated: { total_gifs_generated } \n "
309+ f"Sprites Failed: { total_sprites_failed } \n \n "
310+ f"Processing Duration: { int (minutes )} minutes and { int (seconds )} seconds" ,
311+ )
287312
288313## Extraction logic
289314def extract_sprites (atlas_path , metadata_path , output_dir , create_gif , create_webp , keep_frames , set_framerate , set_loopdelay , set_threshold ):
315+ frames_generated = 0
316+ gifs_generated = 0
317+ sprites_failed = 0
290318 try :
291319 atlas = Image .open (atlas_path )
292320 if metadata_path .endswith ('.xml' ):
@@ -340,6 +368,8 @@ def extract_sprites(atlas_path, metadata_path, output_dir, create_gif, create_we
340368 os .makedirs (sprite_folder , exist_ok = True )
341369
342370 frame_image .save (os .path .join (sprite_folder , f"{ name } .png" ))
371+ if keep_frames :
372+ frames_generated += 1
343373
344374 if create_gif or create_webp :
345375 animations .setdefault (folder_name , []).append ((name , frame_image ))
@@ -395,20 +425,32 @@ def extract_sprites(atlas_path, metadata_path, output_dir, create_gif, create_we
395425 durations = [round (1000 / fps )] * len (cropped_images )
396426 durations [- 1 ] += delay
397427 cropped_images [0 ].save (os .path .join (output_dir , os .path .splitext (spritesheet_name )[0 ] + f" { animation_name } .gif" ), save_all = True , append_images = cropped_images [1 :], disposal = 2 , optimize = False , duration = durations , loop = 0 , comment = f'GIF generated by: TextureAtlas to GIF and Frames v{ current_version } ' )
428+ gifs_generated += 1
429+
398430 if not keep_frames :
399431 frames_folder = os .path .join (output_dir , animation_name )
400432 for i in os .listdir (frames_folder ):
401433 os .remove (os .path .join (frames_folder , i ))
402434 os .rmdir (frames_folder )
403435
436+ return {
437+ 'frames_generated' : frames_generated ,
438+ 'gifs_generated' : gifs_generated ,
439+ 'sprites_failed' : sprites_failed
440+ }
441+
404442 except ET .ParseError :
443+ sprites_failed += 1
405444 raise ET .ParseError (f"Badly formatted XML file:\n \n { metadata_path } " )
406445 except Exception as e :
407446 if "Coordinate '" in str (e ) and "' is less than '" in str (e ):
447+ sprites_failed += 1
408448 raise Exception (f"XML or TXT frame dimension data doesn't match the spritesheet dimensions.\n \n Error: { str (e )} \n \n File: { metadata_path } " )
409449 elif "'NoneType' object is not subscriptable" in str (e ):
450+ sprites_failed += 1
410451 raise Exception (f"XML or TXT frame dimension data doesn't match the spritesheet dimensions.\n \n Error: { str (e )} \n \n File: { metadata_path } " )
411452 else :
453+ sprites_failed += 1
412454 raise Exception (f"An error occurred: { str (e )} .\n \n File:{ metadata_path } " )
413455
414456## FNF specific stuff
0 commit comments