From 5877a0bee8388c5e44c9a77992740b066c71f4db Mon Sep 17 00:00:00 2001 From: Drew Wingfield Date: Mon, 29 Jul 2024 22:25:42 -0500 Subject: [PATCH 1/6] Add bulk RARC import support Added support for folder-recursive RARC importing in bulk via command line or drag-and-drop. --- gcft_ui/main_window.py | 2 + gcft_ui/rarc_tab.py | 94 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/gcft_ui/main_window.py b/gcft_ui/main_window.py index c3a0acb..3d1b5f7 100644 --- a/gcft_ui/main_window.py +++ b/gcft_ui/main_window.py @@ -108,6 +108,8 @@ def get_open_func_and_tab_name_for_file_path(self, file_path): return (self.gcm_tab.import_gcm_by_path, "GCM ISOs") elif file_ext in RARC_FILE_EXTS: return (self.rarc_tab.import_rarc_by_path, "RARC Archives") + elif os.path.isdir(file_path): + return (self.rarc_tab.import_all_rarcs_from_folder, "RARC Archives") elif file_ext in BTI_FILE_EXTS: return (self.bti_tab.import_bti_by_path, "BTI Images") elif file_ext in [".png"]: diff --git a/gcft_ui/rarc_tab.py b/gcft_ui/rarc_tab.py index e3a673b..bcf32f3 100644 --- a/gcft_ui/rarc_tab.py +++ b/gcft_ui/rarc_tab.py @@ -124,6 +124,100 @@ def extract_all_files_from_rarc_folder(self): file_type="RARC" ) + + def import_all_rarcs_from_folder( + self, + folder_of_rarcs_path, + recursive=True, + base_path="", + debug=True, rtn_counter=False, + swallow_assertion_errors=True + ): + + NO_RECURSION_DIRECTORIES = ["GCFTUnpacked","HomeBTN","\\res\\HomeBTN"] # FIles in HomeBTN throws some strange AssertionError + item_counter = 0 + + #if base_path != "": + # # This is a recursion + # #if debug: + # # print("| "*recursion_guess+f"Base path is still {base_path}") + if base_path == "": + base_path = folder_of_rarcs_path + + if not os.path.isdir(base_path+"\\GCFTUnpacked"): + os.mkdir(base_path+"\\GCFTUnpacked") + + subfolder_path = folder_of_rarcs_path.replace(base_path,"") + recursion_guess = subfolder_path.count("\\") + 1 + #print('subfolder path: '+str(subfolder_path)) + + if debug: + print("| "*recursion_guess+"Importing all rarcs from a folder.") + print("| "*recursion_guess+f"Path: {folder_of_rarcs_path}") + + + for object in os.listdir(folder_of_rarcs_path): + object_path = folder_of_rarcs_path+"\\"+object + + + if debug: + print("| "*recursion_guess+" - Object "+subfolder_path+"\\"+object, end='') + + file_ext = os.path.splitext(object)[1] + + if os.path.isdir(object_path) and recursive and not (object in NO_RECURSION_DIRECTORIES): + if debug: + print(" Folder found. Making directory and recursing...") + + os.mkdir(base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object) # make copy directory in the unpacked section + + item_counter += self.import_all_rarcs_from_folder(object_path, base_path=base_path, debug=debug, rtn_counter=True) + + elif (not os.path.isdir(object_path)) and (file_ext in [".arc"]): + item_counter += 1 + + if debug: + print(" Valid RARC found. Importing. ",end='') + #extract and export + try: + self.import_rarc_by_path(object_path) + + except AssertionError as e: + print("!!! Some assertion error occured while importing RARC file!!! "+str(e)) + if not swallow_assertion_errors: + raise e + + else: + return 1 # Needed to stop the extracting, otherwise more errors crop up + + if debug: + print("Extracting. ") + #input(base_path+"\\GCFTUnpacked\\"+object) + #self.extract_all_files_from_rarc() + + #print("new path: "+str(new_path)) + export_path = base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object + + #print("export path: "+str(export_path)) + #self.extract_all_files_from_rarc_folder() + + #node = self.ui.actionExtractAllFilesFromRARCFolder.data() + self.rarc.extract_all_files_to_disk(export_path) + #self.extract_all_files_from_rarc_folder_by_path(base_path+"\\GCFTUnpacked\\"+object) + + elif debug: + print() + + # If this is the "main" thread - not inside of a recursion + if base_path == folder_of_rarcs_path and debug: + print(f" -- Successfully de-RARC'd {item_counter} files. --") + + if rtn_counter: + return item_counter + + + + def dump_all_rarc_textures(self): self.window().generic_do_gui_file_operation( op_callback=self.dump_all_rarc_textures_by_path, From b57757f315241ffb117c8517f7b2ca361d5498b3 Mon Sep 17 00:00:00 2001 From: Drew Wingfield Date: Tue, 30 Jul 2024 14:53:36 -0500 Subject: [PATCH 2/6] Comment and error message fix Added more info to the error message when a RARC file is invalid, added the swallow_assertion_errors argument to recursion, and correctly capitalized a comment. --- gcft_ui/rarc_tab.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gcft_ui/rarc_tab.py b/gcft_ui/rarc_tab.py index bcf32f3..b26e04c 100644 --- a/gcft_ui/rarc_tab.py +++ b/gcft_ui/rarc_tab.py @@ -169,9 +169,12 @@ def import_all_rarcs_from_folder( if debug: print(" Folder found. Making directory and recursing...") - os.mkdir(base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object) # make copy directory in the unpacked section + os.mkdir(base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object) # Make copy directory in the unpacked section - item_counter += self.import_all_rarcs_from_folder(object_path, base_path=base_path, debug=debug, rtn_counter=True) + item_counter += self.import_all_rarcs_from_folder( + object_path, base_path=base_path, + debug=debug, rtn_counter=True, swallow_assertion_errors=swallow_assertion_errors + ) elif (not os.path.isdir(object_path)) and (file_ext in [".arc"]): item_counter += 1 @@ -183,7 +186,7 @@ def import_all_rarcs_from_folder( self.import_rarc_by_path(object_path) except AssertionError as e: - print("!!! Some assertion error occured while importing RARC file!!! "+str(e)) + print("!!! Some assertion error occured while importing RARC file!!! (most likely invalid RARC file) "+str(e)) if not swallow_assertion_errors: raise e From 644c9e49db99545e0383cd9548d22c19b5a2711f Mon Sep 17 00:00:00 2001 From: Drew Wingfield Date: Tue, 30 Jul 2024 15:28:29 -0500 Subject: [PATCH 3/6] Remove HomeBTN exceptions, Update comments Remove exceptions for files in HomeBTN files, reword, capitalize, and clarify a few comments. --- gcft_ui/rarc_tab.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gcft_ui/rarc_tab.py b/gcft_ui/rarc_tab.py index b26e04c..47423d8 100644 --- a/gcft_ui/rarc_tab.py +++ b/gcft_ui/rarc_tab.py @@ -131,11 +131,11 @@ def import_all_rarcs_from_folder( recursive=True, base_path="", debug=True, rtn_counter=False, - swallow_assertion_errors=True + swallow_assertion_errors=True # Does not stop program if assertion error occurs ): - NO_RECURSION_DIRECTORIES = ["GCFTUnpacked","HomeBTN","\\res\\HomeBTN"] # FIles in HomeBTN throws some strange AssertionError - item_counter = 0 + NO_RECURSION_DIRECTORIES = ["GCFTUnpacked"] # Does not recurse in it's own created "unpacked" directory + item_counter = 0 # Number of files unpacked. #if base_path != "": # # This is a recursion @@ -181,7 +181,7 @@ def import_all_rarcs_from_folder( if debug: print(" Valid RARC found. Importing. ",end='') - #extract and export + # Extract and export try: self.import_rarc_by_path(object_path) @@ -191,7 +191,7 @@ def import_all_rarcs_from_folder( raise e else: - return 1 # Needed to stop the extracting, otherwise more errors crop up + return 1 # Needed to stop the extracting, otherwise more errors happen if debug: print("Extracting. ") From 813f95946ecc7f54d4e58a07f5dd006bff080f52 Mon Sep 17 00:00:00 2001 From: Drew Wingfield Date: Tue, 30 Jul 2024 15:46:30 -0500 Subject: [PATCH 4/6] Remove ".arc" extension filter Remove ".arc" extension filter from RARC decompression loop, catch UnicodeDecodeErrors raised by invalid RARC files, update several comments, and update a print statement to match. --- gcft_ui/rarc_tab.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gcft_ui/rarc_tab.py b/gcft_ui/rarc_tab.py index 47423d8..4996c6d 100644 --- a/gcft_ui/rarc_tab.py +++ b/gcft_ui/rarc_tab.py @@ -131,7 +131,7 @@ def import_all_rarcs_from_folder( recursive=True, base_path="", debug=True, rtn_counter=False, - swallow_assertion_errors=True # Does not stop program if assertion error occurs + swallow_assertion_errors=True # Prevents invalid or non-RARC files from stopping the program ): NO_RECURSION_DIRECTORIES = ["GCFTUnpacked"] # Does not recurse in it's own created "unpacked" directory @@ -165,6 +165,7 @@ def import_all_rarcs_from_folder( file_ext = os.path.splitext(object)[1] + # Path is a valid folder and can recurse if os.path.isdir(object_path) and recursive and not (object in NO_RECURSION_DIRECTORIES): if debug: print(" Folder found. Making directory and recursing...") @@ -176,17 +177,18 @@ def import_all_rarcs_from_folder( debug=debug, rtn_counter=True, swallow_assertion_errors=swallow_assertion_errors ) - elif (not os.path.isdir(object_path)) and (file_ext in [".arc"]): + # Path is not a folder + elif (not os.path.isdir(object_path)): item_counter += 1 if debug: - print(" Valid RARC found. Importing. ",end='') + print(" Potential RARC found. Importing. ",end='') # Extract and export try: self.import_rarc_by_path(object_path) - except AssertionError as e: - print("!!! Some assertion error occured while importing RARC file!!! (most likely invalid RARC file) "+str(e)) + except (AssertionError, UnicodeDecodeError) as e: + print(" -- Invalid RARC file - Skipping -- "+str(e)) if not swallow_assertion_errors: raise e From 56c739a5dbe3f747f98285d237fcc10014a8c968 Mon Sep 17 00:00:00 2001 From: Drew Wingfield Date: Tue, 30 Jul 2024 16:01:11 -0500 Subject: [PATCH 5/6] Bug fix, add total item counter Fix a bug where exceptions were not properly caught, fix a bug where exceptions cause termination of the loop, and add a total item counter for comparison between files de-RARC'd and total files attempted. --- gcft_ui/rarc_tab.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/gcft_ui/rarc_tab.py b/gcft_ui/rarc_tab.py index 4996c6d..9bcc0a1 100644 --- a/gcft_ui/rarc_tab.py +++ b/gcft_ui/rarc_tab.py @@ -136,6 +136,7 @@ def import_all_rarcs_from_folder( NO_RECURSION_DIRECTORIES = ["GCFTUnpacked"] # Does not recurse in it's own created "unpacked" directory item_counter = 0 # Number of files unpacked. + total_item_counter = 0 # Total number of files attempted. #if base_path != "": # # This is a recursion @@ -163,8 +164,6 @@ def import_all_rarcs_from_folder( if debug: print("| "*recursion_guess+" - Object "+subfolder_path+"\\"+object, end='') - file_ext = os.path.splitext(object)[1] - # Path is a valid folder and can recurse if os.path.isdir(object_path) and recursive and not (object in NO_RECURSION_DIRECTORIES): if debug: @@ -179,35 +178,30 @@ def import_all_rarcs_from_folder( # Path is not a folder elif (not os.path.isdir(object_path)): - item_counter += 1 + total_item_counter += 1 if debug: print(" Potential RARC found. Importing. ",end='') # Extract and export try: self.import_rarc_by_path(object_path) + + if debug: + print("Extracting. ") + + export_path = base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object + #print("export path: "+str(export_path)) + self.rarc.extract_all_files_to_disk(export_path) + #input(base_path+"\\GCFTUnpacked\\"+object) + + item_counter += 1 except (AssertionError, UnicodeDecodeError) as e: - print(" -- Invalid RARC file - Skipping -- "+str(e)) + print(" !! Invalid RARC file, skipping. !! ") if not swallow_assertion_errors: raise e - - else: - return 1 # Needed to stop the extracting, otherwise more errors happen - - if debug: - print("Extracting. ") - #input(base_path+"\\GCFTUnpacked\\"+object) - #self.extract_all_files_from_rarc() - - #print("new path: "+str(new_path)) - export_path = base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object - - #print("export path: "+str(export_path)) - #self.extract_all_files_from_rarc_folder() #node = self.ui.actionExtractAllFilesFromRARCFolder.data() - self.rarc.extract_all_files_to_disk(export_path) #self.extract_all_files_from_rarc_folder_by_path(base_path+"\\GCFTUnpacked\\"+object) elif debug: @@ -215,7 +209,7 @@ def import_all_rarcs_from_folder( # If this is the "main" thread - not inside of a recursion if base_path == folder_of_rarcs_path and debug: - print(f" -- Successfully de-RARC'd {item_counter} files. --") + print(f" -- Successfully de-RARC'd {item_counter} files out of {total_item_counter} total files. --") if rtn_counter: return item_counter From 4a60e84ad2a879cadc346142a9ecef6cbb30dc92 Mon Sep 17 00:00:00 2001 From: Drew Wingfield <89153952+DrewWing@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:38:56 -0500 Subject: [PATCH 6/6] Fix item_counter bug Fix item_counter and total_item_counter recursion bugs. --- gcft_ui/rarc_tab.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gcft_ui/rarc_tab.py b/gcft_ui/rarc_tab.py index 9bcc0a1..d959d10 100644 --- a/gcft_ui/rarc_tab.py +++ b/gcft_ui/rarc_tab.py @@ -171,10 +171,12 @@ def import_all_rarcs_from_folder( os.mkdir(base_path+"\\GCFTUnpacked"+subfolder_path+"\\"+object) # Make copy directory in the unpacked section - item_counter += self.import_all_rarcs_from_folder( + add_item_counter, add_total_item_counter = self.import_all_rarcs_from_folder( object_path, base_path=base_path, debug=debug, rtn_counter=True, swallow_assertion_errors=swallow_assertion_errors ) + item_counter += add_item_counter + total_item_counter += add_total_item_counter # Path is not a folder elif (not os.path.isdir(object_path)): @@ -209,10 +211,10 @@ def import_all_rarcs_from_folder( # If this is the "main" thread - not inside of a recursion if base_path == folder_of_rarcs_path and debug: - print(f" -- Successfully de-RARC'd {item_counter} files out of {total_item_counter} total files. --") + print(f" -- Successfully de-RARC'd {item_counter} archives out of {total_item_counter} total files. --") if rtn_counter: - return item_counter + return item_counter, total_item_counter