Created
November 13, 2025 19:26
-
-
Save Forenard/cf7c397e5633b03a4d89a06a35c1b715 to your computer and use it in GitHub Desktop.
brawlcrateの一括wav export plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # https://soopercool101.github.io/BrawlCrate/ | |
| # this shit is created by renard | |
| __author__ = "Renard" | |
| __version__ = "2.0.0" | |
| SCRIPT_NAME = "Dump Music v2" | |
| from BrawlCrate.API import BrawlAPI | |
| from BrawlLib.SSBB.ResourceNodes import * | |
| from BrawlCrate.NodeWrappers import * | |
| from System.IO import Directory, Path as IOPath, File | |
| from System import DateTime | |
| # global | |
| log_file = None | |
| log_path = "" | |
| def init_log(folder): | |
| """ログファイルを初期化""" | |
| global log_file, log_path | |
| log_path = IOPath.Combine(folder, "DumpMusic_Log_{0}.txt".format( | |
| DateTime.Now.ToString("yyyyMMdd_HHmmss"))) | |
| try: | |
| log_file = open(log_path, "w", encoding="utf-8") | |
| except: | |
| log_file = None | |
| def append_log(message): | |
| """ログにリアルタイムで書き込む""" | |
| global log_file | |
| if log_file is not None: | |
| try: | |
| log_file.write(message) | |
| log_file.flush() # 即座にディスクに書き込む | |
| except: | |
| pass | |
| def close_log(): | |
| """ログファイルを閉じる""" | |
| global log_file | |
| if log_file is not None: | |
| try: | |
| log_file.close() | |
| except: | |
| pass | |
| log_file = None | |
| def wav_search(): | |
| wrappers = BrawlAPI.NodeWrapperList | |
| wav_list = [] | |
| for wrapper in wrappers: | |
| append_log("Checking wrapper: {0}, ExportFilter: {1}\n".format(wrapper.Resource.Name, wrapper.ExportFilter)) | |
| if ".wav" in wrapper.ExportFilter: | |
| wav_list += [wrapper.Resource] | |
| return wav_list | |
| def get_name(node): | |
| """再帰的にノード名を取得""" | |
| names = [] | |
| current = node | |
| while current is not None: | |
| names.insert(0, current.Name) | |
| current = current.Parent | |
| return "_".join(names) | |
| def sanitize_filename(name): | |
| """ファイル名として使えない文字を削除""" | |
| invalid_chars = '<>:"/\\|?*' | |
| for char in invalid_chars: | |
| name = name.replace(char, '_') | |
| return name.strip('. ') | |
| def main(): | |
| if BrawlAPI.RootNode != None: | |
| folder = BrawlAPI.OpenFolderDialog() | |
| if folder: | |
| # ログファイルを初期化 | |
| init_log(folder) | |
| count = 0 | |
| failed = 0 | |
| wav_list = wav_search() | |
| append_log("=== Dump Music Log ===\n") | |
| append_log("Total nodes with WAV export filter: {0}\n\n".format(len(wav_list))) | |
| for node in wav_list: | |
| node_type = type(node).__name__ | |
| export_name = get_name(node) | |
| # https://soopercool101.github.io/BrawlCrate/class_brawl_lib_1_1_s_s_b_b_1_1_resource_nodes_1_1_r_s_a_r_sound_node.html#a579038833dcd6c71c853d4d5512e5216 | |
| if node_type == 'RSARSoundNode': | |
| try: | |
| sound_type = int(node.SoundType) | |
| except: | |
| sound_type = -1 | |
| can_export = sound_type == 3 # WAVE | |
| if not can_export: | |
| continue | |
| # エクスポート実行 | |
| try: | |
| safe_name = sanitize_filename(export_name) | |
| export_path = IOPath.Combine(folder, safe_name + ".wav") | |
| node.Export(export_path) | |
| count += 1 | |
| append_log("{0} -> OK\n".format(export_name)) | |
| except Exception as e: | |
| failed += 1 | |
| append_log("{0} -> FAIL: {1}\n".format(export_name, str(e))) | |
| # サマリー | |
| append_log("=== Export Summary ===\n") | |
| append_log("Success: {0}\n".format(count)) | |
| append_log("Failed: {0}\n".format(failed)) | |
| # ログファイルを閉じる | |
| close_log() | |
| # 結果表示 | |
| msg = "{0} wav files were successfully exported to {1}".format(count, folder) | |
| if failed > 0: | |
| msg += "\n{0} files failed to export (see log for details)".format(failed) | |
| BrawlAPI.ShowMessage(msg, SCRIPT_NAME) | |
| else: | |
| BrawlAPI.ShowError('Cannot find Root Node (is a file open?)', 'Error') | |
| # スクリプト実行 | |
| try: | |
| main() | |
| except Exception as e: | |
| append_log("\n=== FATAL ERROR ===\n") | |
| append_log(str(e)) | |
| close_log() | |
| BrawlAPI.ShowError("予期しないエラー: {0}".format(str(e)), SCRIPT_NAME) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment