diff --git a/CRC.py b/CRC.py
index 545266f..8497e6b 100644
--- a/CRC.py
+++ b/CRC.py
@@ -105,5 +105,7 @@ def qbkey_hex(text, endian = "big"):
if __name__ == "__main__":
- test = "Solo 1"
- print(QBKey_qs(test))
\ No newline at end of file
+ x = 0
+ while x != -1:
+ x = input("Enter string: ")
+ print(QBKey(x))
diff --git a/GH Toolkit.py b/GH Toolkit.py
index ed3de50..04357e6 100644
--- a/GH Toolkit.py
+++ b/GH Toolkit.py
@@ -16,6 +16,7 @@
menu_options = [
"compile_wt_song - Compile a Guitar Hero: World Tour song pak file from audio and a MIDI file",
"convert_ska_file - Convert a SKA file from one game to another (for conversions)",
+ # "convert_5_to_wt - Convert a song from Guitar Hero 5 or Warriors of Rock to the World Tour format",
"convert_to_5 - Convert a WT song to Guitar Hero 5 format",
"convert_to_gh3 - Convert a GH:A song to GH3 (removing rhythm anims/special mocap calls, porting lights and cameras)",
"convert_to_gha - Convert a GH3 song to GH:A (adding rhythm anims, porting lights and cameras)",
@@ -96,19 +97,22 @@ def manual_input():
print("Choose your singer: ")
print("1.) Default\n2.) Steven Tyler\n3.) Run DMC\n4.) Joe Perry")
singer = singer_dict[input("Type in the number corresponding to your singer: ")]
- song_name, song_pak = convert_to_gha(midqb_file, output, lipsync_dict[singer])
+ song_name, song_pak = convert_to_gha(midqb_file, output, singer)
if midqb_file.lower().endswith(".mid"):
pak_name = f'\\{song_name}_song.pak.xen'
else:
pak_name = f'\\{song_name}_song_GHA.pak.xen'
with open(output + pak_name, 'wb') as f:
f.write(song_pak)
+ input("Convert complete! Press Enter to continue. ")
elif main_menu == "convert_to_gh3":
midqb_file = input("Drag in your song PAK file: ").replace("\"", "")
output = f'{os.path.dirname(midqb_file)}'
song_name, song_pak = convert_to_gh3(midqb_file, output)
with open(output + f'\\{song_name}_song_GH3.pak.xen', 'wb') as f:
f.write(song_pak)
+ input("Convert complete! Press Enter to continue. ")
+
elif main_menu == "convert_to_5" or main_menu == "convert_to_ghwor":
compile_args = []
if main_menu == "convert_to_ghwor":
@@ -240,6 +244,25 @@ def manual_input():
input("\nPress any key to exit.")
input("Complete! Press any key to exit.")
+ elif main_menu == "convert_5_to_wt":
+ midqb_file = input("Drag in your song PAK file: ").replace("\"", "")
+ output = f'{os.path.dirname(midqb_file)}'
+ midname = os.path.basename(midqb_file)[:os.path.basename(midqb_file).find(".")]
+ if re.search(r'^[a-c]dlc', midname, flags=re.IGNORECASE):
+ midname = midname[1:]
+ print("""\nYou can add a performance override file to be added to the song.\nFor example, you can add tapping animation events or for WoR songs, add PlayIdle events.""".replace("\t",""))
+ perf_override = input("Drag in your perf override file (or leave this blank) and press Enter to continue: ").replace("\"", "")
+ music_override = input("Drag in the folder containing your audio files from the PS3 version.\nLeave blank to skip: ").replace("\"", "")
+ if music_override:
+ try:
+ audio_functions.strip_mp3(music_override)
+ except Exception as E:
+ raise E
+ print("Could not convert audio.")
+ print(midname)
+ wt_pak = convert_5_to_wt(midqb_file, perf_override)
+ with open(f"{output}\\a{midname}.pak.xen".lower(), "wb") as f:
+ f.write(wt_pak)
elif main_menu == 1337:
input("Ha! Got ourselves a leet hacker over here ")
@@ -438,6 +461,18 @@ def launch_gui(ghproj = ""):
anim_string = f"qb_file = songs/{midname}_scripts.qb".lower() + "\n" + anim_string
with open(f"{output}\\{midname}_scripts.txt", "w") as f:
f.write(anim_string)
+ elif sys.argv[1] == "convert_5_to_wt":
+ if "output" not in locals():
+ output = f'{os.path.dirname(input_file)}'
+ midname = os.path.basename(input_file)[:os.path.basename(input_file).find(".")]
+ if re.search(r'^[a-c]dlc', midname, flags=re.IGNORECASE):
+ midname = midname[1:]
+ compile_args = []
+ if len(sys.argv) > 3:
+ compile_args.extend(sys.argv[3:])
+ wt_pak = convert_5_to_wt(input_file, *compile_args)
+ with open(f"{output}\\a{midname}.pak.xen".lower(), "wb") as f:
+ f.write(wt_pak)
elif sys.argv[1] == "make_wt_mid":
qb_file = mid_qb.make_wt_qb(sys.argv[2])
elif sys.argv[1] == "extract_fsb":
diff --git a/compile-folder.bat b/compile-folder.bat
index f5cee13..0395658 100644
--- a/compile-folder.bat
+++ b/compile-folder.bat
@@ -1,9 +1,10 @@
-pyinstaller -p "D:\GitHub\Guitar-Hero-III-Tools\create_audio" ^
--p D:\GitHub\Guitar-Hero-III-Tools\midqb_gen ^
--p D:\GitHub\Guitar-Hero-III-Tools\pak_extract ^
--p D:\GitHub\Guitar-Hero-III-Tools\ska_converter ^
--p D:\GitHub\Guitar-Hero-III-Tools ^
--p "D:\GitHub\Guitar-Hero-III-Tools\gui" ^
+pyinstaller -p ".\create_audio" ^
+-p .\midqb_gen ^
+-p .\pak_extract ^
+-p .\ska_converter ^
+-p . ^
+-p ".\gui" ^
+--add-data "anim_loops.txt;." ^
--add-data "debug.txt;." ^
--add-data "conversion_files_prod;conversion_files" ^
--add-data "create_audio\default_audio\blank.mp3;create_audio\default_audio" ^
diff --git a/conversion_files/basic_loops.txt b/conversion_files/basic_loops.txt
new file mode 100644
index 0000000..48e2b50
--- /dev/null
+++ b/conversion_files/basic_loops.txt
@@ -0,0 +1,112 @@
+car_female_anim_struct = {
+ guitar = {
+ pak = L_GUIT_Ginger_Bulls_anims
+ anim_set = L_GUIT_Ginger_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_car_female
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Female_Normal
+ facial_anims = facial_anims_female_rocker
+ }
+ Bass = {
+ pak = L_GUIT_Judita_Bulls_anims
+ anim_set = L_GUIT_Judita_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_car_female
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Female_Normal
+ facial_anims = facial_anims_female_rocker
+ }
+ drum = {
+ pak = L_DRUM_Loops_Standard_anims
+ anim_set = l_drum_loops_standard_anims_set
+ facial_anims = facial_anims_female_rocker
+ }
+ vocals = {
+ pak = L_SING_Amanda_Bulls_anims
+ anim_set = L_SING_Amanda_Bulls_anims_set
+ facial_anims = facial_anims_female_rocker
+ }
+}
+car_male_anim_struct = {
+ guitar = {
+ pak = L_GUIT_Matt_Bulls_anims
+ anim_set = L_GUIT_Matt_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_CAR_Male
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Male_Normal
+ facial_anims = facial_anims_male_rocker
+ }
+ Bass = {
+ pak = L_GUIT_Davidicus_Bulls_anims
+ anim_set = L_GUIT_Davidicus_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_CAR_Male
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Male_Normal
+ facial_anims = facial_anims_male_rocker
+ }
+ drum = {
+ pak = L_DRUM_Loops_Standard_anims
+ anim_set = l_drum_loops_standard_anims_set
+ facial_anims = facial_anims_male_rocker
+ }
+ vocals = {
+ pak = L_SING_Patrick_Bulls_anims
+ anim_set = L_SING_Patrick_Bulls_anims_set
+ facial_anims = facial_anims_male_rocker
+ }
+}
+car_female_alt_anim_struct = {
+ guitar = {
+ pak = L_GUIT_Ginger_Bulls_anims
+ anim_set = L_GUIT_Ginger_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_car_female
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Female_Normal
+ facial_anims = facial_anims_female_rocker
+ }
+ Bass = {
+ pak = L_GUIT_Judita_Bulls_anims
+ anim_set = L_GUIT_Judita_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_car_female
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Female_Normal
+ facial_anims = facial_anims_female_rocker
+ }
+ drum = {
+ pak = L_DRUM_Loops_Standard_anims
+ anim_set = l_drum_loops_standard_anims_set
+ facial_anims = facial_anims_female_rocker
+ }
+ vocals = {
+ pak = L_SING_Amanda_Bulls_anims
+ anim_set = L_SING_Amanda_Bulls_anims_set
+ facial_anims = facial_anims_female_rocker
+ }
+}
+car_male_alt_anim_struct = {
+ guitar = {
+ pak = L_GUIT_Matt_Bulls_anims
+ anim_set = L_GUIT_Matt_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_CAR_Male
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Male_Normal
+ facial_anims = facial_anims_male_rocker
+ }
+ Bass = {
+ pak = L_GUIT_Davidicus_Bulls_anims
+ anim_set = L_GUIT_Davidicus_Bulls_anims_set
+ finger_anims = guitarist_finger_anims_CAR_Male
+ fret_anims = fret_anims_rocker
+ strum_anims = CAR_Male_Normal
+ facial_anims = facial_anims_male_rocker
+ }
+ drum = {
+ pak = L_DRUM_Loops_Standard_anims
+ anim_set = l_drum_loops_standard_anims_set
+ facial_anims = facial_anims_male_rocker
+ }
+ vocals = {
+ pak = L_SING_Patrick_Bulls_anims
+ anim_set = L_SING_Patrick_Bulls_anims_set
+ facial_anims = facial_anims_male_rocker
+ }
+}
diff --git a/convert_5_to_wt.py b/convert_5_to_wt.py
new file mode 100644
index 0000000..e57d395
--- /dev/null
+++ b/convert_5_to_wt.py
@@ -0,0 +1,10 @@
+import subprocess
+import os
+import shutil
+
+pak_name = os.path.basename(input("Drag in your pak file: ")).replace("\"","")
+root_folder = os.path.realpath(os.path.dirname(__file__))
+perf = "_performance.txt" if os.path.isfile("_performance.txt") else ""
+scripts = "_song_scripts_anim_loops.txt" if os.path.isfile("_song_scripts_anim_loops.txt") else ""
+ska_files = "SKA Files" if os.path.isdir("SKA Files") else ""
+subprocess.run(["python",f"{root_folder}\\GHToolkit.py", "convert_5_to_wt", pak_name, perf])
\ No newline at end of file
diff --git a/create_audio/audio_functions.py b/create_audio/audio_functions.py
index dcbb2b2..40744b0 100644
--- a/create_audio/audio_functions.py
+++ b/create_audio/audio_functions.py
@@ -7,6 +7,7 @@
import sox
import json
+import strip_mp3_padding as pad_strip
from crypt_keys import ghwor_keys, ghwor_cipher
from struct import pack as floatPack, unpack as f_up
@@ -43,16 +44,6 @@ def pad_wav_file_sox(input_file, target_length, file_num = 0):
# Calculate the required padding
padding = target_length - duration
- # Set up SoX transform parameters
- tfm = sox.Transformer()
- transform_args = ["mp3"]
- if sample_rate != 48000:
- transform_args.append(48000)
- tfm.set_output_format(*transform_args)
-
- # Add the padding to the input file and convert it to an MP3
- if padding > 0:
- tfm.pad(end_duration=padding)
# Run the sox command, save temp file, and re-read
temp_dir = ".\\temp"
temp_out = temp_dir + f"\\temp_{file_num}.mp3"
@@ -62,8 +53,13 @@ def pad_wav_file_sox(input_file, target_length, file_num = 0):
except:
pass
+ sox_command = ["sox", input_file, "-c", "2", "-C", "128", "-r", "48000", temp_out]
+ # Add the padding to the input file
+ if padding > 0:
+ sox_command.extend(["pad", "0", str(padding)])
try:
- tfm.build_file(input_filepath=input_file, output_filepath=temp_out)
+ subprocess.run(sox_command)
+ #tfm.build_file(input_filepath=input_file, output_filepath=temp_out)
except Exception as E:
raise E
@@ -72,7 +68,7 @@ def pad_wav_file_sox(input_file, target_length, file_num = 0):
return padded_mp3_data
-def make_preview_sox(start_time, end_time):
+def make_preview_sox(start_time, end_time, *args):
# Run the sox command, save temp file, and re-read
temp_dir = ".\\temp"
@@ -82,24 +78,34 @@ def make_preview_sox(start_time, end_time):
os.remove(temp_out)
audio_list = []
- for file in os.listdir(temp_dir):
- audio_list.append(temp_dir + "\\" + file)
+ if "rendered_preview" in args:
+ print("Converting custom preview audio")
+ audio_list.append(args[args.index("rendered_preview") + 1])
+
+ else:
+ for file in os.listdir(temp_dir):
+ audio_list.append(temp_dir + "\\" + file)
extra_args = []
+
# Create SoX Combiner
- if len(audio_list) == 1:
+ if "rendered_preview" not in args:
+ if len(audio_list) == 1:
+ preview = sox.Transformer()
+ preview.set_input_format("mp3")
+ audio_list = audio_list[0]
+ else:
+ preview = sox.Combiner()
+ preview.set_input_format(["mp3"] * len(audio_list))
+ extra_args.append("mix")
+
+ preview.trim(start_time, end_time)
+ preview.fade(1.0, 1.0)
+ preview.vol(-7.0, "db")
+ else:
preview = sox.Transformer()
- preview.set_input_format("mp3")
audio_list = audio_list[0]
- else:
- preview = sox.Combiner()
- preview.set_input_format(["mp3"] * len(audio_list))
- extra_args.append("mix")
preview.set_output_format("mp3", 48000)
- preview.trim(start_time, end_time)
- preview.fade(1.0, 1.0)
- preview.vol(-7.0, "db")
-
try:
preview.build(audio_list, temp_out, *extra_args)
@@ -153,32 +159,16 @@ def pad_wav_file_ffmpeg(input_file, target_length, file_num=0):
if padding > 0:
# Use FFmpeg to add silence to the end of the audio
- subprocess.run([
- 'ffmpeg', '-y', '-f', 'lavfi', '-i', f'anullsrc=r=48000:cl=stereo:d={padding}',
- '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', silent_file
- ], check=True)
subprocess.run([
- 'ffmpeg', '-y', '-i', input_file, '-ar', '48000', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
+ 'ffmpeg', '-y', '-i', input_file, '-ar', '48000', '-ac', '2', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
], check=True)
- with open(f"{temp_dir}\\temp_concat.txt", "w") as f:
- f.write(f"file temp_{file_num}.mp3\n")
- f.write(f"file silent.mp3\n")
-
- # Concatenate the input audio file and the silent audio file
- subprocess.run([
- 'ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', f"{temp_dir}\\temp_concat.txt", '-c', 'copy', '-map_metadata', '-1',
- temp_out
- ], check=True)
-
- os.remove(f"{temp_dir}\\temp_concat.txt")
- os.remove(f"{temp_dir}\\silent.mp3")
else:
# Convert audio to mp3 with 48000 sample rate
subprocess.run([
- 'ffmpeg', '-y', '-i', input_file, '-ar', '48000', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
+ 'ffmpeg', '-y', '-i', input_file, '-ar', '48000', '-ac', '2', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
], check=True)
# Read the padded mp3 file
@@ -187,7 +177,7 @@ def pad_wav_file_ffmpeg(input_file, target_length, file_num=0):
return padded_mp3_data
-def make_preview_ffmpeg(start_time, end_time):
+def make_preview_ffmpeg(start_time, end_time, *args):
# Set temp directory and output file
temp_dir = ".\\temp"
temp_out = temp_dir + "\\temp.mp3"
@@ -196,17 +186,11 @@ def make_preview_ffmpeg(start_time, end_time):
os.remove(temp_out)
# Get a list of all audio files in temp directory
- audio_list = [os.path.join(temp_dir, file) for file in os.listdir(temp_dir)]
-
- trim_duration = end_time - start_time
- fade_duration = 1.0
-
- # Build filtergraph for mixing and trimming audio
- mix_filter = ''.join([f'[{i}:0]' for i in range(len(audio_list))]) + f'amix=inputs={len(audio_list)}:duration=first:dropout_transition=2:normalize=0[mixout]'
- # trim_filter = f'[mixout]atrim=start={start_time}:duration={trim_duration}[final]'
- trim_filter = f'[mixout]atrim=start={start_time}:duration={trim_duration},afade=t=in:st={start_time}:d=1,afade=t=out:st={start_time+trim_duration - 1}:d=1,volume=-7.0dB[final]'
- #trim_filter = f'[mixout]atrim=start={start_time}:duration={trim_duration},afade=t=in:ss=0:d={fade_duration},afade=t=out:st={trim_duration-fade_duration}:d={fade_duration}[final]'
- filtergraph = mix_filter + ';' + trim_filter
+ if "rendered_preview" in args:
+ print("Using custom preview audio")
+ audio_list = [args[args.index("rendered_preview") + 1]]
+ else:
+ audio_list = [os.path.join(temp_dir, file) for file in os.listdir(temp_dir)]
command = ['ffmpeg']
@@ -214,11 +198,27 @@ def make_preview_ffmpeg(start_time, end_time):
for audio_file in audio_list:
command.extend(['-i', audio_file])
- # Add the rest of the command
- command.extend([
- '-filter_complex', filtergraph, '-map', '[final]',
- '-ar', '48000', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
- ])
+ if "rendered_preview" not in args:
+ trim_duration = end_time - start_time
+ fade_duration = 1.0
+
+ # Build filtergraph for mixing and trimming audio
+ mix_filter = ''.join([f'[{i}:0]' for i in range(len(audio_list))]) + f'amix=inputs={len(audio_list)}:duration=first:dropout_transition=2:normalize=0[mixout]'
+ # trim_filter = f'[mixout]atrim=start={start_time}:duration={trim_duration}[final]'
+ trim_filter = f'[mixout]atrim=start={start_time}:duration={trim_duration},afade=t=in:st={start_time}:d=1,afade=t=out:st={start_time+trim_duration - 1}:d=1,volume=-7.0dB[final]'
+ #trim_filter = f'[mixout]atrim=start={start_time}:duration={trim_duration},afade=t=in:ss=0:d={fade_duration},afade=t=out:st={trim_duration-fade_duration}:d={fade_duration}[final]'
+ filtergraph = mix_filter + ';' + trim_filter
+
+ # Add the rest of the command
+ command.extend([
+ '-filter_complex', filtergraph, '-map', '[final]',
+ '-ar', '48000', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
+ ])
+ else:
+ # Add the rest of the command without filters
+ command.extend([
+ '-ac', '2', '-ar', '48000', '-acodec', 'libmp3lame', '-b:a', '128k', '-map_metadata', '-1', temp_out
+ ])
try:
# Run FFmpeg command
@@ -237,58 +237,70 @@ def make_preview_ffmpeg(start_time, end_time):
def is_program_in_path(program_name):
return shutil.which(program_name) is not None
-def get_padded_audio(all_audio, shortname, start_time = 30, end_time = 60, *args):
+def get_padded_audio(all_audio, start_time = 30, end_time = 60, *args):
# Get the maximum length
- time_0 = time.time()
- encrypt = False
- if "encrypt" in args:
- encrypt = True
max_length = 0
if not "audio_len" in args:
print("Converting all files to MP3 and padding to the longest")
- if is_program_in_path("sox") and "ffmpeg" not in args:
- for input_file in all_audio:
- duration = get_audio_duration_sox(input_file)
- max_length = max(max_length, duration)
- if "audio_len" in args:
- return max_length
- print("Using SoX to convert")
- # Pad each input file and store the output in a list
- print(f"Padding all files to match the longest file ({strftime('%M:%S', gmtime(max_length))})")
- # Pad each input file and store the output in a list
+ if "no_convert" in args:
padded_mp3_data_list = []
for enum, input_file in enumerate(all_audio):
- if input_file.endswith("default_audio/blank.mp3"):
- with open(input_file, 'rb') as f:
- padded_mp3_data_list.append(f.read())
- else:
- padded_mp3_data_list.append(pad_wav_file_sox(input_file, max_length, enum))
- preview = make_preview_sox(start_time, end_time)
- elif is_program_in_path("ffmpeg"):
- for input_file in all_audio:
- duration = get_audio_duration_ffmpeg(input_file)
- max_length = max(max_length, duration)
- if "audio_len" in args:
- return max_length
- print("Using FFmpeg to convert")
- # Pad each input file and store the output in a list
- padded_mp3_data_list = []
- for enum, input_file in enumerate(all_audio):
- if input_file.endswith("default_audio/blank.mp3"):
- with open(input_file, 'rb') as f:
- padded_mp3_data_list.append(f.read())
- else:
- padded_mp3_data_list.append(pad_wav_file_ffmpeg(input_file, max_length, enum))
- preview = make_preview_ffmpeg(start_time, end_time)
- elif "ffmpeg" in args:
- print("FFmpeg was asked to use, but cannot find it in PATH")
- return 0
+ with open(input_file, 'rb') as f:
+ padded_mp3_data_list.append(f.read())
+ preview = padded_mp3_data_list[-1]
+ padded_mp3_data_list.pop()
else:
- print("Could not find ffmpeg or SoX in PATH")
- return 0
+ if is_program_in_path("sox") and "ffmpeg" not in args:
+ for input_file in all_audio:
+ duration = get_audio_duration_sox(input_file)
+ max_length = max(max_length, duration)
+ if "audio_len" in args:
+ return max_length
+ print("Using SoX to convert")
+ # Pad each input file and store the output in a list
+ print(f"Padding all files to match the longest file ({strftime('%M:%S', gmtime(max_length))})")
+ # Pad each input file and store the output in a list
+ padded_mp3_data_list = []
+ for enum, input_file in enumerate(all_audio):
+ if input_file.endswith("default_audio/blank.mp3"):
+ with open(input_file, 'rb') as f:
+ padded_mp3_data_list.append(f.read())
+ else:
+ padded_mp3_data_list.append(pad_wav_file_sox(input_file, max_length, enum))
+ preview = make_preview_sox(start_time, end_time, *args)
+ elif is_program_in_path("ffmpeg"):
+ for input_file in all_audio:
+ duration = get_audio_duration_ffmpeg(input_file)
+ max_length = max(max_length, duration)
+ if "audio_len" in args:
+ return max_length
+ print("Using FFmpeg to convert")
+ # Pad each input file and store the output in a list
+ padded_mp3_data_list = []
+ for enum, input_file in enumerate(all_audio):
+ if input_file.endswith("default_audio/blank.mp3"):
+ with open(input_file, 'rb') as f:
+ padded_mp3_data_list.append(f.read())
+ else:
+ padded_mp3_data_list.append(pad_wav_file_ffmpeg(input_file, max_length, enum))
+ preview = make_preview_ffmpeg(start_time, end_time, *args)
+ elif "ffmpeg" in args:
+ print("FFmpeg was asked to use, but cannot find it in PATH")
+ return 0
+ else:
+ print("Could not find ffmpeg or SoX in PATH")
+ return 0
stream_size = 0
for x in padded_mp3_data_list:
stream_size = max(len(pullMP3Frames(x)[0]), stream_size)
+ return padded_mp3_data_list, preview, stream_size
+
+def compile_wt_audio(all_audio, shortname, start_time, end_time, *args):
+ time_0 = time.time()
+ encrypt = False
+ if "encrypt" in args:
+ encrypt = True
+ padded_mp3_data_list, preview, stream_size = get_padded_audio(all_audio, start_time, end_time, *args)
extra_args = ["-stream_size", stream_size]
print("Creating Drum Audio")
drum_files = createFSB4(padded_mp3_data_list[:4], f"{shortname}_1", encrypt, *extra_args)
@@ -303,6 +315,23 @@ def get_padded_audio(all_audio, shortname, start_time = 30, end_time = 60, *args
print(f"Audio generation took {time_1-time_0} seconds")
return drum_files, inst_files, song_files, preview
+def compile_gh3_audio(all_audio, shortname, start_time, end_time, *args):
+ time_0 = time.time()
+ audio_names = []
+ audio_paths = []
+ for key,value in all_audio.items():
+ audio_names.append(key)
+ audio_paths.append(value)
+ padded_mp3_data_list, preview, stream_size = get_padded_audio(audio_paths, start_time, end_time, *args)
+ padded_mp3_data_list.append(preview)
+ audio_names.append("preview")
+ extra_args = ["-stream_size", stream_size, "compiler"]
+ print("Creating Audio")
+ fsb_file, fsb_dat = createFSB3(padded_mp3_data_list, f"{shortname}", *extra_args, audio_names = audio_names)
+ time_1 = time.time()
+
+ print(f"Audio generation took {time_1 - time_0} seconds")
+ return fsb_file, fsb_dat
def flipBits(audio):
return bytes(br[x] for x in audio)
@@ -571,10 +600,10 @@ def pullMP3Frames(audio):
position += to_pull
return frames, first_frame
-def FSBentry(data, filename):
+def FSBentry(data, filename, *args):
filesize = len(data)
frameSize = 1152
- frames = len(pullMP3Frames(data))
+ frames = len(pullMP3Frames(data)[0])
file_entry_len = 80
fsb_file = bytes(filename if len(filename) <= 30 else filename[:30], "latin-1")
while len(fsb_file) < 30:
@@ -583,7 +612,10 @@ def FSBentry(data, filename):
loop_start = 0
loop_end = samples_length - 1
mode = 576
- sample_rate = 44100
+ if "compiler" in args:
+ sample_rate = 48000
+ else:
+ sample_rate = 44100
volume, priority = 255, 255
pan = 128
channels = 2
@@ -610,17 +642,27 @@ def FSBentry(data, filename):
return fsb_entry
-def createFSB3(file, shortname):
+def createFSB3(files, shortname, *args, **kwargs):
headers = []
audio = bytearray()
dat_entries = []
- for x in file:
- audio_name = f"{shortname}_{os.path.basename(x)}"
- with open(x, 'rb') as f:
- audio_data = f.read()
- headers.append(FSBentry(audio_data, audio_name)[0])
- dat_entries.append(os.path.splitext(audio_name)[0])
- audio += audio_data
+ if type(files) == list:
+ for y, x in enumerate(files):
+ if type(x) == str:
+ audio_name = f"{shortname}_{os.path.basename(x)}"
+ with open(x, 'rb') as f:
+ audio_data = f.read()
+ else:
+ stream_frames, temp_frame = pullMP3Frames(x)
+ audio_name = f"{shortname}_{kwargs['audio_names'][y]}"
+ if "-stream_size" in args and not audio_name.endswith("preview"):
+ stream_length = int(args[args.index("-stream_size") + 1])
+ if len(stream_frames) != stream_length:
+ stream_frames.extend([blank_48k_mp3] * (stream_length - len(stream_frames)))
+ audio_data = b''.join(stream_frames)
+ audio += audio_data
+ headers.append(FSBentry(audio_data, audio_name, *args))
+ dat_entries.append(os.path.splitext(audio_name)[0])
print(dat_entries)
fsb_file = bytearray()
fsb_file += b'FSB3' # FSB3 header
@@ -643,12 +685,15 @@ def createFSB3(file, shortname):
fsb_dat += toBytes(y, 4, "big")
fsb_dat += toBytes(0, 12)
- raise Exception
- with open(f"{shortname}.fsb.xen", 'wb') as f:
+ # print(binascii.hexlify(fsb_dat, ' ', 1))
+ return fsb_file, fsb_dat
+
+def writeFSB3(fsb_file, fsb_dat, filepath):
+ print("Encrypting FSB file.")
+ with open(f"{filepath}.fsb.xen", 'wb') as f:
f.write(encrypt_fsb3(fsb_file))
- with open(f"{shortname}.dat.xen", 'wb') as f:
+ with open(f"{filepath}.dat.xen", 'wb') as f:
f.write(fsb_dat)
- # print(binascii.hexlify(fsb_dat, ' ', 1))
return
def splitFSBFrames(audio):
@@ -766,39 +811,43 @@ def file_renamer(file_name):
file_name = file_name[1:]
return file_name
-
+def crypt_files(dirin, filename, gh3 = False):
+ t0 = time.process_time()
+ with open(f"{dirin}\\{filename}", 'rb') as f:
+ audio = f.read()
+ if filename.lower().endswith(".fsb.xen") or filename.lower().endswith(".fsb.ps3"):
+ crypted = decrypt_file(audio, filename)
+ elif filename.endswith(".fsb"):
+ if gh3:
+ crypted = encrypt_fsb3(audio)
+ else:
+ no_ext = file_renamer(os.path.basename(filename[:-4]).lower())
+ key = generate_fsb_key(no_ext)
+ crypted = encrypt_fsb4(audio, key)
+ else:
+ print(f"Unknown file {filename} found, skipping...")
+ return 0, 0
+ t1 = time.process_time()
+ fileout = (f"{filename}.xen" if filename.endswith(".fsb") else filename[:-4])
+ print(filename, t1 - t0)
+ return crypted, fileout
def main(gh3 = False):
dirin = f".\\input"
dirout = f".\\output"
for filename in os.listdir(dirin):
- t0 = time.process_time()
- with open(f"{dirin}\\{filename}", 'rb') as f:
- audio = f.read()
- if filename.lower().endswith(".fsb.xen") or filename.lower().endswith(".fsb.ps3"):
- crypted = decrypt_file(audio, filename)
- elif filename.endswith(".fsb"):
- if gh3:
- crypted = encrypt_fsb3(audio)
- else:
- no_ext = file_renamer(os.path.basename(filename[:-4]).lower())
- key = generate_fsb_key(no_ext)
- crypted = encrypt_fsb4(audio, key)
- else:
- print(f"Unknown file {filename} found, skipping...")
- continue
- t1 = time.process_time()
- fileout = (f"{filename}.xen" if filename.endswith(".fsb") else filename[:-4])
- with open(f"{dirout}\\{fileout}", 'wb') as f:
+ crypted, fileout = crypt_files(dirin, filename, gh3)
+ with open(f"{dirout}\\{fileout}", 'wb') as f:
f.write(crypted)
- print(filename, t1 - t0)
-
return
+def strip_mp3(in_folder):
+ pad_strip.main(in_folder)
+
def test_make():
dirin = f".\\input"
dirout = f".\\output"
- song_name = ""
+ song_name = "aqualung"
files = []
songs = {}
for filename in os.listdir(dirin):
@@ -817,14 +866,16 @@ def test_make():
f.write(fsb_file)
return
-def test_combine():
- dirin = f".\\input"
- dirout = f".\\output"
- song_name = "test"
+def test_combine(song_name = "output", dirin = ".\\input", dirout = ".\\output"):
+ song_name = song_name
files = []
for filename in os.listdir(dirin):
- files.append(f"{os.path.join(dirin,filename)}")
- drum, inst, other, preview = get_padded_audio(files, song_name)
+ if filename.endswith(".mp3"):
+ files.append(f"{os.path.join(dirin,filename)}")
+ if not len(files) == 10:
+ print(f"Not enough files found. Found {len(files)}, expected 10.")
+ return
+ drum, inst, other, preview = compile_wt_audio(files, song_name, 0, 0, "no_convert")
for enum, x in enumerate([drum, inst, other, preview]):
if enum != 3:
with open(f"{dirout}\\{song_name}_{enum+1}.fsb.xen", 'wb') as f:
@@ -837,7 +888,21 @@ def test_combine():
# Playable:
# Preview: sox -m D:\RB\Songs\Pleymo\Sept\GH3\Guitar.wav D:\RB\Songs\Pleymo\Sept\GH3\Bass.wav D:\RB\Songs\Pleymo\Sept\GH3\Backing.wav -C 128 output.mp3 trim 0:35 1:05
if __name__ == "__main__":
- main()
+ if len(sys.argv) > 1:
+ if sys.argv[1] == "combine":
+ song_name = input("Enter the checksum for this song: ")
+ test_combine(song_name)
+ elif sys.argv[1] == "make":
+ test_make()
+ elif sys.argv[1] == "header":
+ with open(sys.argv[2], 'rb') as f:
+ headerFile = f.read()[:4]
+ header = parseMP3header("{:08b}".format(int(headerFile.hex(), 16)))
+
+ for k, v in header.items():
+ print(k, v)
+ else:
+ main()
#test_combine()
#test_make()
diff --git a/create_audio/combine_fsb.bat b/create_audio/combine_fsb.bat
new file mode 100644
index 0000000..58816a5
--- /dev/null
+++ b/create_audio/combine_fsb.bat
@@ -0,0 +1,3 @@
+@echo off
+
+audio_functions.py combine
\ No newline at end of file
diff --git a/create_audio/strip_mp3_padding.py b/create_audio/strip_mp3_padding.py
new file mode 100644
index 0000000..2ffd676
--- /dev/null
+++ b/create_audio/strip_mp3_padding.py
@@ -0,0 +1,85 @@
+import subprocess
+import os
+import shutil
+import audio_functions as af
+
+def delete_files_in_directory(directory_path):
+ try:
+ files = os.listdir(directory_path)
+ for file in files:
+ file_path = os.path.join(directory_path, file)
+ if os.path.isfile(file_path):
+ os.remove(file_path)
+ elif os.path.isdir(file_path):
+ shutil.rmtree(file_path)
+ print("All files deleted successfully.")
+ except OSError:
+ print("Error occurred while deleting files.")
+
+def main(in_folder = "input"):
+ if not shutil.which("fsbext"):
+ input("fsbext is not found in your computer's PATH.\nPress Enter to continue...")
+ return 0
+ if in_folder == "input":
+ out_folder = "output"
+ else:
+ if not os.path.isdir(in_folder):
+ print("Invalid folder. Aborting audio function.")
+ return 0
+ out_folder = os.path.join(os.path.dirname(in_folder),"audio_stripped")
+ try:
+ os.mkdir(out_folder)
+ except:
+ pass
+ try:
+ if in_folder == "input":
+ delete_files_in_directory("output")
+ subprocess.run(["python","audio_functions.py"])
+ else:
+ for filename in os.listdir(in_folder):
+ crypted, fileout = af.crypt_files(in_folder, filename)
+ with open(f"{out_folder}\\{fileout}", 'wb') as f:
+ f.write(crypted)
+ for filename in os.listdir(out_folder):
+ print(filename)
+ subprocess.run(["fsbext", "-M","-d",out_folder, f"{out_folder}\\{filename}"])
+ if filename.endswith("_1.FSB"):
+ new_folder = "drums"
+ elif filename.endswith("_2.FSB"):
+ new_folder = "playable"
+ elif filename.endswith("_3.FSB"):
+ new_folder = "non-playable"
+ elif filename.lower().endswith("_preview.fsb"):
+ new_folder = "preview"
+ else:
+ continue
+ os.rename(f"{out_folder}\\multichannel sound.mp3_channels", f"{out_folder}\\{new_folder}")
+ for filename in os.listdir(out_folder):
+ if filename == "playable":
+ modifier = 4
+ elif filename == "non-playable":
+ modifier = 7
+ elif filename == "preview":
+ modifier = 9
+ else:
+ continue
+ for file in os.listdir(f"{out_folder}\\{filename}"):
+ audio_name = int(os.path.splitext(file)[0])
+ audio_name += modifier
+ shutil.copy(f"{out_folder}\\{filename}\\{file}",f"{out_folder}\\drums\\{audio_name}.mp3")
+ for filename in os.listdir(f"{out_folder}\\drums"):
+ shutil.copy(f"{out_folder}\\drums\\{filename}", f"{in_folder}\\{filename}")
+ delete_files_in_directory(f"{out_folder}")
+ if in_folder == "input":
+ subprocess.run(["combine_fsb.bat"])
+ else:
+ song_name = input("Enter the checksum for this song: ")
+ af.test_combine(song_name, in_folder, out_folder)
+ except Exception as e:
+ raise e
+ print(f"Error: {e}")
+ os.system('pause')
+ return 1
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/ghtoolkit.py b/ghtoolkit.py
new file mode 100644
index 0000000..cd5f57b
--- /dev/null
+++ b/ghtoolkit.py
@@ -0,0 +1,9 @@
+import subprocess
+import sys
+import os
+import shutil
+
+
+root_folder = os.path.realpath(os.path.dirname(__file__))
+args = sys.argv
+subprocess.run(["python",f"{root_folder}\\GH Toolkit.py", *sys.argv[1:]])
\ No newline at end of file
diff --git a/gui/gui_initialize.py b/gui/gui_initialize.py
index 8e2a352..0448363 100644
--- a/gui/gui_initialize.py
+++ b/gui/gui_initialize.py
@@ -35,6 +35,13 @@
from toolkit_functions import convert_to_5
+def wrap_string(to_wrap, wide=False):
+ new_string = f'"{to_wrap}"'
+ if wide:
+ new_string = "w" + new_string
+ return new_string
+
+
class main_window(QWidget):
def __init__(self):
super().__init__()
@@ -52,14 +59,7 @@ def __init__(self, ghproj=""):
self.gh3_audio_fields()
self.gh3_song_data_fields()
self.compile_fields()
-
- self.ghwt_checksum = ""
- self.ghwt_genre = ""
- self.ghwor_checksum = ""
- self.ghwor_genre = ""
-
- self.checksum_input.textEdited.connect(self.set_checksum_variable)
- self.genre_select.activated.connect(self.set_game_genre)
+ self.changing_fields()
self.first_boot()
@@ -95,7 +95,7 @@ def compile_pak(self):
return
game = self.game_select_group.checkedButton().objectName()
if game == "gh3":
- self.compile_gh3()
+ self.compile_gh3("skip_audio")
elif game == "ghwt":
self.compile_ghwt("skip_audio")
elif game == "gh5":
@@ -185,6 +185,8 @@ def save_project(self):
"ghwor_checksum": self.ghwor_checksum,
"ghwt_genre": self.ghwt_genre,
"ghwor_genre": self.ghwor_genre,
+ "ghwt_drumkit": self.ghwt_drumkit,
+ "ghwor_drumkit": self.ghwor_drumkit,
# WT Data
"kick_input": self.kick_input.text(),
@@ -199,6 +201,9 @@ def save_project(self):
"backing_input": self.backing_input.text(),
"crowd_input": self.crowd_input.text(),
+ "ghwt_preview_audio_input": self.ghwt_preview_audio_input.text(),
+ "ghwt_rendered_preview_check": self.ghwt_rendered_preview_check.isChecked(),
+
"encrypt_audio": self.encrypt_audio.isChecked(),
"preview_minutes": self.preview_minutes.value(),
@@ -219,7 +224,9 @@ def save_project(self):
"ghwt_drumkit_select": self.ghwt_drumkit_select.currentText(),
"ghwt_vocal_gender_select": self.ghwt_vocal_gender_select.currentText(),
"vocal_scroll_speed_input": self.vocal_scroll_speed_input.value(),
+ "ghwt_vocal_cents": self.ghwt_vocal_cents.value(),
"ghwt_band_vol": self.ghwt_band_vol.value(),
+ "ghwt_whammy_cutoff": self.ghwt_whammy_cutoff.value(),
"band_tier_value": self.band_tier_value.value(),
"drums_tier_value": self.drums_tier_value.value(),
@@ -253,6 +260,9 @@ def save_project(self):
"coop_backing_input_gh3": self.coop_backing_input_gh3.text(),
"crowd_input_gh3": self.crowd_input_gh3.text(),
+
+ "gh3_preview_audio_input": self.gh3_preview_audio_input.text(),
+ "gh3_rendered_preview_check": self.gh3_rendered_preview_check.isChecked(),
"preview_minutes_gh3": self.preview_minutes_gh3.value(),
"preview_seconds_gh3": self.preview_seconds_gh3.value(),
@@ -264,6 +274,8 @@ def save_project(self):
"gh3_midi_file_input": self.gh3_midi_file_input.text(),
"gh3_perf_override_input": self.gh3_perf_override_input.text(),
+ "gh3_ska_files_input": self.gh3_ska_files_input.text(),
+ "gh3_song_script_input": self.gh3_song_script_input.text(),
"gh3_countoff_select": self.gh3_countoff_select.currentText(),
"gh3_vocal_gender_select": self.gh3_vocal_gender_select.currentText(),
"gh3_bassist_select": self.gh3_bassist_select.currentText(),
@@ -310,7 +322,7 @@ def load_project_file(self, ghproj=""):
i.setChecked(True)
break
self.set_game_fields()
- platform_index = self.platform_button_group.findChildren(QRadioButton)
+ platform_index = self.platform_button_group.buttons()
for i in platform_index:
if i.objectName() == load_vars["platform"]:
i.setChecked(True)
@@ -318,7 +330,8 @@ def load_project_file(self, ghproj=""):
check_boxes = ["cover_checkbox", "p2_rhythm_check", "coop_audio_check", "beatlines_check", "encrypt_audio",
"ghwt_set_end",
- "guitar_mic_check", "bass_mic_check", "use_new_clips_check", "force_ffmpeg_check"]
+ "guitar_mic_check", "bass_mic_check", "use_new_clips_check", "force_ffmpeg_check",
+ "gh3_rendered_preview_check", "ghwt_rendered_preview_check"]
for x in check_boxes:
try:
@@ -362,12 +375,20 @@ def set_checksum_variable(self):
elif game == "ghwor":
self.ghwor_checksum = self.checksum_input.text()
- def set_game_genre(self):
+ def set_genre(self):
game = self.game_select_group.checkedButton().objectName()
if game == "ghwt":
self.ghwt_genre = self.genre_select.currentText()
elif game == "ghwor":
self.ghwor_genre = self.genre_select.currentText()
+
+ def set_drumkit(self):
+ game = self.game_select_group.checkedButton().objectName()
+ if game == "ghwt":
+ self.ghwt_drumkit = self.ghwt_drumkit_select.currentText()
+ elif game == "ghwor":
+ self.ghwor_drumkit = self.ghwt_drumkit_select.currentText()
+
def set_game_fields(self):
self.setUpdatesEnabled(False)
game = self.game_select_group.checkedButton().objectName()
@@ -400,6 +421,8 @@ def set_game_fields(self):
self.deactivate_layout(self.setlist_settings_layout)
self.deactivate_layout(self.skeleton_types_layout)
+ self.platform_360.setEnabled(False)
+ self.platform_pc.setEnabled(False)
if any([game == "gh3", game == "gha"]):
self.genre_select.setDisabled(True)
elif game == "ghwt":
@@ -407,6 +430,7 @@ def set_game_fields(self):
self.ghwt_drumkit_select.addItems(sorted(drum_kit_wt))
self.checksum_input.setText(self.ghwt_checksum)
self.genre_select.setCurrentText(self.ghwt_genre)
+ self.ghwt_drumkit_select.setCurrentText(self.ghwt_drumkit)
self.other_settings_label.setText("World Tour Definitive Edition Settings")
self.activate_layout(self.setlist_settings_layout)
self.activate_layout(self.skeleton_types_layout)
@@ -418,6 +442,7 @@ def set_game_fields(self):
self.ghwt_drumkit_select.addItems(sorted(drum_kit_gh5))
self.checksum_input.setText(self.ghwor_checksum)
self.genre_select.setCurrentText(self.ghwor_genre)
+ self.ghwt_drumkit_select.setCurrentText(self.ghwor_drumkit)
self.ghwor_stfs_input.setEnabled(True)
self.ghwor_stfs_select.setEnabled(True)
self.encrypt_audio.setDisabled(True)
@@ -434,6 +459,8 @@ def set_game_fields(self):
self.crowd_input_gh3.setDisabled(True)
self.crowd_select_gh3.setDisabled(True)
self.cover_checkbox.setDisabled(True)
+ self.platform_360.setEnabled(True)
+ self.platform_pc.setEnabled(True)
else:
self.crowd_input_gh3.setDisabled(False)
self.crowd_select_gh3.setDisabled(False)
@@ -462,6 +489,9 @@ def wt_audio_fields(self):
self.backing_select.clicked.connect(partial(self.open_file_dialog_audio, self.backing_input))
self.crowd_select.clicked.connect(partial(self.open_file_dialog_audio, self.crowd_input))
+ self.ghwt_preview_audio_select.clicked.connect(
+ partial(self.open_file_dialog_audio, self.ghwt_preview_audio_input))
+
self.ghwt_set_end.toggled.connect(self.set_end_time)
def wt_song_data_fields(self):
@@ -484,11 +514,15 @@ def gh3_audio_fields(self):
self.coop_rhythm_select_gh3.clicked.connect(partial(self.open_file_dialog_audio, self.coop_rhythm_input_gh3))
self.coop_backing_select_gh3.clicked.connect(partial(self.open_file_dialog_audio, self.coop_backing_input_gh3))
+ self.gh3_preview_audio_select.clicked.connect(partial(self.open_file_dialog_audio, self.gh3_preview_audio_input))
+
self.p2_rhythm_check.toggled.connect(self.p2_rhythm_toggle)
def gh3_song_data_fields(self):
self.gh3_midi_file_select.clicked.connect(partial(self.open_file_dialog_midi, self.gh3_midi_file_input))
self.gh3_perf_override_select.clicked.connect(partial(self.open_file_dialog_qb, self.gh3_perf_override_input))
+ self.gh3_ska_files_select.clicked.connect(partial(self.open_file_dialog_folder, self.gh3_ska_files_input))
+ self.gh3_song_script_select.clicked.connect(partial(self.open_file_dialog_qb, self.gh3_song_script_input))
bassists = ["Default"] + ["Axel", "Casey", "Izzy", "Judy", "Johnny", "Lars", "Midori", "Xavier", "Slash",
"Tom Morello", "Lou", "God of Rock", "Grim Ripper"]
self.gh3_bassist_select.addItems(bassists)
@@ -505,6 +539,18 @@ def compile_fields(self):
self.compile_button.clicked.connect(self.compile_song_package)
self.compile_pak_button.clicked.connect(self.compile_pak)
+ def changing_fields(self):
+ self.ghwt_checksum = ""
+ self.ghwt_genre = ""
+ self.ghwor_checksum = ""
+ self.ghwor_genre = ""
+ self.ghwt_drumkit = ""
+ self.ghwor_drumkit = ""
+
+ self.checksum_input.textEdited.connect(self.set_checksum_variable)
+ self.genre_select.activated.connect(self.set_genre)
+ self.ghwt_drumkit_select.activated.connect(self.set_drumkit)
+
def update_ns_value(self):
self.ns_hopo_value.setText(str(round(self.ns_value(), 5)))
@@ -538,14 +584,14 @@ def combo_copy(self, source, destination):
item_text = source.itemText(i)
destination.addItem(item_text)
- def midi_check(self):
- if not self.ghwt_midi_file_input.text():
+ def midi_check(self, midi_path):
+ if not midi_path:
print("No MIDI file selected! Cancelling compilation")
return 0
- elif not os.path.isfile(self.ghwt_midi_file_input.text()):
+ elif not os.path.isfile(midi_path):
print("MIDI file not found! Cancelling compilation")
return 0
- return self.ghwt_midi_file_input.text()
+ return midi_path
def wor_checksum(self):
text, ok = QInputDialog.getText(None, "Proper DLC ID Required",
@@ -585,7 +631,7 @@ def ghwt_ini_file(self):
ini.optionxform = str
ini["ModInfo"] = {
"Name": self.checksum_input.text(),
- "Description": "Created with Addy's Toolkit",
+ "Description": "Created with the Addy GH Toolkit",
"Author": self.author_input.text(),
"Version": "1"
}
@@ -624,6 +670,15 @@ def ghwt_ini_file(self):
ini["SongInfo"]["MicForBassist"] = "1"
if self.guitar_mic_check.isChecked():
ini["SongInfo"]["MicForGuitarist"] = "1"
+ if self.beatlines_check.isChecked():
+ ini["SongInfo"]["Low8Bars"] = str(self.beat_8th_low_input.value())
+ ini["SongInfo"]["High8Bars"] = str(self.beat_8th_high_input.value())
+ ini["SongInfo"]["Low16Bars"] = str(self.beat_16th_low_input.value())
+ ini["SongInfo"]["High16Bars"] = str(self.beat_16th_high_input.value())
+ if self.ghwt_vocal_cents.value() != 0:
+ ini["SongInfo"]["Cents"] = str(self.ghwt_vocal_cents.value())
+ if self.ghwt_whammy_cutoff.value() != 0.5:
+ ini["SongInfo"]["WhammyCutoff"] = str(self.ghwt_whammy_cutoff.value())
return ini
def ghwor_songlist_info(self, *args):
@@ -636,6 +691,8 @@ def ghwor_songlist_info(self, *args):
artist_text = "$artist_text_as_made_famous_by"
orig_artist = 0
+ cents = self.ghwt_vocal_cents.value()
+
if self.beatlines_check.isChecked():
low_8 = self.beat_8th_low_input.text()
high_8 = self.beat_8th_high_input.text()
@@ -696,13 +753,78 @@ def ghwor_songlist_info(self, *args):
"cymbal": f'"{drumkit}"',
"drum_kit": f'"{drumkit}"',
"countoff": f'"{self.ghwt_countoff_select.currentText().lower()}"',
- "overall_song_volume": self.ghwt_band_vol.value()
+ "overall_song_volume": self.ghwt_band_vol.value(),
+ "vocals_pitch_score_shift": "{ " + f"cents = {cents} " + "}"
}
if not parts_with_mic:
songlist_info.pop("parts_with_mic")
+ if not cents:
+ songlist_info.pop("vocals_pitch_score_shift")
return songlist_info, qs_keys
+ def gh3_songlist_info(self):
+ artist_text = self.artist_text_select.currentText()
+ orig_artist = 1
+ if artist_text == "By":
+ artist_text = "$artist_text_by"
+ elif artist_text == "Other":
+ artist_text = wrap_string(self.artist_text_other.text(), True)
+ else:
+ artist_text = "$artist_text_as_made_famous_by"
+ orig_artist = 0
+ if self.p2_rhythm_check.isChecked():
+ rhythm_track = 1
+ else:
+ rhythm_track = 0
+
+ songlist_info = {
+ "checksum": self.checksum_input.text(),
+ "name": wrap_string(self.checksum_input.text()),
+ "title": wrap_string(self.title_input.text(), True),
+ "artist": wrap_string(self.artist_input.text(), True),
+ "year": wrap_string(f", {self.year_input.text()}", True),
+ "artist_text": artist_text,
+ "original_artist": orig_artist,
+ "version": "gh3",
+ "leaderboard": 1,
+ "gem_offset": 0,
+ "input_offset": 0,
+ "singer": self.gh3_vocal_gender_select.currentText(),
+ "keyboard": "False",
+ "band_playback_volume": self.gh3_gtr_vol.value(),
+ "guitar_playback_volume": self.gh3_band_vol.value(),
+ "countoff": wrap_string(self.gh3_countoff_select.currentText()),
+ "rhythm_track": rhythm_track
+ }
+ if self.coop_audio_check.isChecked():
+ songlist_info["no_id"] = "use_coop_notetracks"
+ return songlist_info
+
+ def gh3_audio_gen(self, song_name, start_time, end_time, compile_args):
+ all_audio = {
+ "guitar": self.guitar_input_gh3.text(),
+ "rhythm": self.rhythm_input_gh3.text(),
+ "song": self.backing_input_gh3.text()
+ }
+ if self.coop_audio_check.isChecked():
+ all_audio["coop_guitar"] = self.coop_guitar_input_gh3.text()
+ all_audio["coop_rhythm"] = self.coop_rhythm_input_gh3.text()
+ all_audio["coop_song"] = self.coop_backing_input_gh3.text()
+ if self.game_select_group.checkedButton().objectName() == "gha":
+ all_audio["crowd"] = self.crowd_input_gh3.text()
+
+ for key, value in all_audio.items():
+ if not os.path.isfile(value):
+ print(f"File for {key} does not exist. Using blank audio")
+ all_audio[key] = f"{audio_folder}/default_audio/blank.mp3"
+ elif value.endswith("default_audio/blank.wav"):
+ value = f"{audio_folder}/default_audio/blank.mp3"
+ all_audio[key] = value
+ fsb_file, fsb_dat = af.compile_gh3_audio(all_audio, song_name, start_time, end_time, *compile_args)
+
+ return fsb_file, fsb_dat
+
def ghwt_audio_gen(self, song_name, start_time, end_time, compile_args):
all_audio = [self.kick_input, self.snare_input, self.cymbals_input, self.toms_input, self.guitar_input,
self.bass_input, self.vocals_input, self.backing_input, self.crowd_input]
@@ -716,7 +838,7 @@ def ghwt_audio_gen(self, song_name, start_time, end_time, compile_args):
files.setText(f"{audio_folder}/default_audio/blank.mp3")
all_audio_path.append(files.text())
try:
- drum, inst, other, preview = af.get_padded_audio(all_audio_path, song_name, start_time, end_time,
+ drum, inst, other, preview = af.compile_wt_audio(all_audio_path, song_name, start_time, end_time,
*compile_args)
except Exception as E:
traceback.print_exc()
@@ -737,10 +859,38 @@ def get_audio_duration(self):
duration = int(af.get_padded_audio(all_audio_path, 0, 0, 0, *compile_args))
return duration
+ def gen_gh3_songlist(self, *args):
+ songlist_info = self.gh3_songlist_info()
+ qb_text = ""
+ checksum = songlist_info['checksum']
+ qb_text += f"{checksum} = " + "{\n"
+ for k, v in songlist_info.items():
+ qb_text += f"{k} = {v}\n"
+ qb_text += "}"
+ platform = self.platform_button_group.checkedButton().objectName()
+ if platform == "platform_360":
+ dl_qb = """qb_file = 0xbf0730f0
+ GH3_Download_Songs = {
+ prefix = "download"
+ num_tiers = 1
+ tier1 = {
+ Title = w"Downloaded songs"
+ songs = [%s]
+ no_id = unlockall
+ level = load_z_artdeco
+ }
+ }
+ download_songlist = [%s]
+ download_songlist_props = {
+ """.replace("%s", checksum)
+ qb_text = dl_qb + qb_text + " }"
+ qb_text = mid_gen.t2q_main(qb_text, game = "GH3")
+ return qb_text
+
def gen_wor_songlist(self, *args):
songlist_info, qs_keys = self.ghwor_songlist_info(*args)
- qb_text_name = f"{hex(int(QBKey(self.checksum_input.text()),16)+2)}"
+ qb_text_name = f"{hex(int(QBKey(self.checksum_input.text()), 16) + 2)}"
'''.download_songlist.qb'''
gh6_dlc_songlist = f"gh6_dlc_songlist = [{songlist_info['checksum']}]\n"
@@ -799,7 +949,18 @@ def gen_wor_manifest(self):
return cmanifest_qb, qb_file_name, cmanifest
def set_compile_args(self, *args):
- midi_file = self.midi_check()
+ if "gh3" in args:
+ midi_file = self.midi_check(self.gh3_midi_file_input.text())
+ perf = self.gh3_perf_override_input.text()
+ ska_files = self.gh3_ska_files_input.text()
+ song_script = self.gh3_song_script_input.text()
+ rendered_audio = self.gh3_rendered_preview_check.isChecked()
+ else:
+ midi_file = self.midi_check(self.ghwt_midi_file_input.text())
+ perf = self.ghwt_perf_override_input.text()
+ ska_files = self.ghwt_ska_files_input.text()
+ song_script = self.ghwt_song_script_input.text()
+ rendered_audio = self.ghwt_rendered_preview_check.isChecked()
if not midi_file:
return 0
@@ -808,14 +969,21 @@ def set_compile_args(self, *args):
if self.encrypt_audio.isChecked():
compile_args += ["encrypt"]
- perf = self.ghwt_perf_override_input.text()
+
if perf and os.path.isfile(perf):
compile_args += ["replace_perf", perf]
- ska_files = self.ghwt_ska_files_input.text()
if ska_files and os.path.isdir(ska_files):
compile_args += ["add_ska", ska_files]
+ if rendered_audio:
+ if "gh3" in args and os.path.exists(self.gh3_preview_audio_input.text()):
+ compile_args += ["rendered_preview", self.gh3_preview_audio_input.text()]
+ elif "ghwt" in args and os.path.exists(self.ghwt_preview_audio_input.text()):
+ compile_args += ["rendered_preview", self.ghwt_preview_audio_input.text()]
+ else:
+ print("Rendered preview audio selected, but file is not found. Creating preview based on time.")
+
hopo_mode = self.hopo_mode_select.currentText()
if hopo_mode == "Guitar Hero 3":
compile_args += ["gh3_mode"]
@@ -824,7 +992,6 @@ def set_compile_args(self, *args):
elif hopo_mode == "Guitar Hero World Tour+":
compile_args += ["force_only"]
- song_script = self.ghwt_song_script_input.text()
if song_script and os.path.isfile(song_script):
compile_args += ["song_script", song_script]
@@ -832,7 +999,37 @@ def set_compile_args(self, *args):
compile_args += ["ffmpeg"]
return compile_args
- def compile_gh3(self):
+ def compile_gh3(self, *args):
+ start_time = self.conv_to_secs("start")
+ end_time = self.conv_to_secs("end")
+ if not self.ghwt_set_end.isChecked():
+ end_time += start_time
+
+ song_name = self.checksum_input.text()
+ compile_args = self.set_compile_args(*["gh3"])
+ project_folder = os.path.dirname(self.project_file_path.text())
+ save_folder = f"{project_folder}\\gh3_compile"
+ try:
+ os.mkdir(save_folder)
+ except:
+ pass
+ if not compile_args:
+ return
+
+ songlist = self.gen_gh3_songlist()
+ try:
+ song_pak = mid_gen.make_mid(*compile_args)[0]
+ except Exception as E:
+ # raise E
+ traceback.print_exc()
+ return
+ if not "skip_audio" in args:
+ audio, dat = self.gh3_audio_gen(song_name, start_time, end_time, compile_args)
+ audio_path = f"{save_folder}\\{song_name}"
+ af.writeFSB3(audio, dat, audio_path)
+ with open(f"{save_folder}\\{self.checksum_input.text()}_song.pak.xen", "wb") as f:
+ f.write(song_pak)
+ print("Compile complete!")
return
def compile_ghwt(self, *args):
@@ -860,15 +1057,16 @@ def compile_ghwt(self, *args):
with open(f"{song_folder}/song.ini", "w") as f:
ini.write(f, space_around_delimiters=False)
- compile_args = self.set_compile_args(*["ghwt", "wtde"])
+ compile_args = self.set_compile_args(*["ghwt", "wtde", "gh5_mode"])
if not compile_args:
return
try:
- song_pak = mid_gen.make_mid(*compile_args)[0]
+ song_pak, xplus_pak = mid_gen.make_mid(*compile_args)
except Exception as E:
traceback.print_exc()
+ # raise E
return
with open(f"{song_folder}\\Content\\a{song_name}_song.pak.xen", "wb") as f:
f.write(song_pak)
@@ -908,7 +1106,8 @@ def compile_ghwor(self, *args):
traceback.print_exc()
return
- wor_pak_files = convert_to_5(song_pak, self.checksum_input.text(), *compile_args, song_name = self.checksum_input.text(), decomp_ska = True)
+ wor_pak_files = convert_to_5(song_pak, self.checksum_input.text(), *compile_args,
+ song_name=self.checksum_input.text(), decomp_ska=True)
songlist_args = []
if "double_kick" in wor_pak_files:
songlist_args += ["double_kick"]
@@ -917,21 +1116,23 @@ def compile_ghwor(self, *args):
songlist_qb, qs_bytes, empty_qs = self.gen_wor_songlist(*songlist_args)
manifest_pak = mid_gen.pakMaker([[cmanifest_qb, f"{man_file_name}.0xb2a7df81.qb"]])
- cdl_pak = mid_gen.pakMaker([[b'\x00\x00\x00\x00\x00\x00\x00\x1C\x1C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
- "0xb1392214.0x179eac5.qb"]])
+ cdl_pak = mid_gen.pakMaker([[
+ b'\x00\x00\x00\x00\x00\x00\x00\x1C\x1C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ "0xb1392214.0x179eac5.qb"]])
cdl_text_files = []
langs = ["de", "en", "fr", "it", "es"]
for enum, blanks in enumerate(["0x5a7a551", "0x8b6e4d98", "0xb4424214", "0xdab9fbee", "0xe8682141"]):
cdl_text_files.append([empty_qs, f"{blanks}.0x179eac5.qs.{langs[enum]}"])
- dl_qb = hex(int(QBKey(self.checksum_input.text()),16))
+ dl_qb = hex(int(QBKey(self.checksum_input.text()), 16))
for lang in langs:
cdl_text_files.append([qs_bytes, f"{dl_qb}.download_songlist.qs.{lang}"])
- cdl_text_files.append([songlist_qb, f"{hex(int(QBKey(self.checksum_input.text()), 16)+2)}.download_songlist.qb"])
+ cdl_text_files.append(
+ [songlist_qb, f"{hex(int(QBKey(self.checksum_input.text()), 16) + 2)}.download_songlist.qb"])
cdl_text_pak = mid_gen.pakMaker(cdl_text_files)
-
- wor_pak = mid_gen.pakMaker([[x["file_data"], x["file_name"]] for x in wor_pak_files], self.checksum_input.text())
+ wor_pak = mid_gen.pakMaker([[x["file_data"], x["file_name"]] for x in wor_pak_files],
+ self.checksum_input.text())
project_folder = os.path.dirname(self.project_file_path.text())
save_folder = f"{project_folder}\\{self.checksum_input.text()}_WoR_Files"
@@ -943,7 +1144,8 @@ def compile_ghwor(self, *args):
end_time = self.conv_to_secs("end")
if not self.ghwt_set_end.isChecked():
end_time += start_time
- drum, inst, other, preview = self.ghwt_audio_gen(self.checksum_input.text(), start_time, end_time, compile_args)
+ drum, inst, other, preview = self.ghwt_audio_gen(self.checksum_input.text(), start_time, end_time,
+ compile_args)
if not drum:
return
for enum, x in enumerate([drum, inst, other, preview]):
diff --git a/gui/project_files/compile_package.py b/gui/project_files/compile_package.py
index 7345573..f21ecd0 100644
--- a/gui/project_files/compile_package.py
+++ b/gui/project_files/compile_package.py
@@ -3,7 +3,7 @@
################################################################################
## Form generated from reading UI file 'compile_package.ui'
##
-## Created by: Qt User Interface Compiler version 6.4.2
+## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
@@ -25,7 +25,7 @@ class Ui_Form(object):
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
- Form.resize(562, 659)
+ Form.resize(562, 712)
self.verticalLayout_11 = QVBoxLayout(Form)
self.verticalLayout_11.setObjectName(u"verticalLayout_11")
self.verticalLayout_4 = QVBoxLayout()
@@ -70,7 +70,7 @@ def setupUi(self, Form):
self.game_select_group.setObjectName(u"game_select_group")
self.game_select_group.addButton(self.gh3)
self.gh3.setObjectName(u"gh3")
- self.gh3.setEnabled(False)
+ self.gh3.setEnabled(True)
self.gh3.setText(u"GH3")
self.gh3.setChecked(False)
@@ -79,7 +79,7 @@ def setupUi(self, Form):
self.gha = QRadioButton(self.game_select)
self.game_select_group.addButton(self.gha)
self.gha.setObjectName(u"gha")
- self.gha.setEnabled(False)
+ self.gha.setEnabled(True)
self.horizontalLayout.addWidget(self.gha)
@@ -269,11 +269,23 @@ def setupUi(self, Form):
self.ghwt_stems_layout = QGridLayout()
self.ghwt_stems_layout.setObjectName(u"ghwt_stems_layout")
self.ghwt_stems_layout.setContentsMargins(0, 9, -1, 9)
- self.toms_input = QLineEdit(self.wt_audio_widget)
- self.toms_input.setObjectName(u"toms_input")
- self.toms_input.setEnabled(True)
+ self.crowd_select = QToolButton(self.wt_audio_widget)
+ self.crowd_select.setObjectName(u"crowd_select")
+ self.crowd_select.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.toms_input, 4, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.crowd_select, 14, 3, 1, 1)
+
+ self.vocals_input = QLineEdit(self.wt_audio_widget)
+ self.vocals_input.setObjectName(u"vocals_input")
+ self.vocals_input.setEnabled(True)
+
+ self.ghwt_stems_layout.addWidget(self.vocals_input, 10, 2, 1, 1)
+
+ self.toms_label = QLabel(self.wt_audio_widget)
+ self.toms_label.setObjectName(u"toms_label")
+ self.toms_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.ghwt_stems_layout.addWidget(self.toms_label, 4, 1, 1, 1)
self.backing_select = QToolButton(self.wt_audio_widget)
self.backing_select.setObjectName(u"backing_select")
@@ -281,11 +293,11 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.backing_select, 12, 3, 1, 1)
- self.cymbals_select = QToolButton(self.wt_audio_widget)
- self.cymbals_select.setObjectName(u"cymbals_select")
- self.cymbals_select.setEnabled(True)
+ self.backing_label = QLabel(self.wt_audio_widget)
+ self.backing_label.setObjectName(u"backing_label")
+ self.backing_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.ghwt_stems_layout.addWidget(self.cymbals_select, 3, 3, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.backing_label, 12, 1, 1, 1)
self.line_4 = QFrame(self.wt_audio_widget)
self.line_4.setObjectName(u"line_4")
@@ -294,11 +306,11 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.line_4, 7, 0, 1, 4)
- self.bass_label = QLabel(self.wt_audio_widget)
- self.bass_label.setObjectName(u"bass_label")
- self.bass_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.cymbals_input = QLineEdit(self.wt_audio_widget)
+ self.cymbals_input.setObjectName(u"cymbals_input")
+ self.cymbals_input.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.bass_label, 8, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.cymbals_input, 3, 2, 1, 1)
self.snare_select = QToolButton(self.wt_audio_widget)
self.snare_select.setObjectName(u"snare_select")
@@ -306,36 +318,56 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.snare_select, 2, 3, 1, 1)
- self.kick_label = QLabel(self.wt_audio_widget)
- self.kick_label.setObjectName(u"kick_label")
- self.kick_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.line_3 = QFrame(self.wt_audio_widget)
+ self.line_3.setObjectName(u"line_3")
+ self.line_3.setFrameShape(QFrame.HLine)
+ self.line_3.setFrameShadow(QFrame.Sunken)
- self.ghwt_stems_layout.addWidget(self.kick_label, 1, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.line_3, 5, 0, 1, 4)
- self.bass_input = QLineEdit(self.wt_audio_widget)
- self.bass_input.setObjectName(u"bass_input")
- self.bass_input.setEnabled(True)
+ self.line_6 = QFrame(self.wt_audio_widget)
+ self.line_6.setObjectName(u"line_6")
+ self.line_6.setFrameShape(QFrame.HLine)
+ self.line_6.setFrameShadow(QFrame.Sunken)
- self.ghwt_stems_layout.addWidget(self.bass_input, 8, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.line_6, 11, 0, 1, 4)
- self.crowd_label = QLabel(self.wt_audio_widget)
- self.crowd_label.setObjectName(u"crowd_label")
- self.crowd_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.kick_input = QLineEdit(self.wt_audio_widget)
+ self.kick_input.setObjectName(u"kick_input")
+ self.kick_input.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.crowd_label, 14, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.kick_input, 1, 2, 1, 1)
- self.snare_label = QLabel(self.wt_audio_widget)
- self.snare_label.setObjectName(u"snare_label")
- self.snare_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.guitar_select = QToolButton(self.wt_audio_widget)
+ self.guitar_select.setObjectName(u"guitar_select")
+ self.guitar_select.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.snare_label, 2, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.guitar_select, 6, 3, 1, 1)
- self.line_8 = QFrame(self.wt_audio_widget)
- self.line_8.setObjectName(u"line_8")
- self.line_8.setFrameShape(QFrame.HLine)
- self.line_8.setFrameShadow(QFrame.Sunken)
+ self.vocals_select = QToolButton(self.wt_audio_widget)
+ self.vocals_select.setObjectName(u"vocals_select")
+ self.vocals_select.setEnabled(True)
+
+ self.ghwt_stems_layout.addWidget(self.vocals_select, 10, 3, 1, 1)
+
+ self.snare_input = QLineEdit(self.wt_audio_widget)
+ self.snare_input.setObjectName(u"snare_input")
+ self.snare_input.setEnabled(True)
+
+ self.ghwt_stems_layout.addWidget(self.snare_input, 2, 2, 1, 1)
+
+ self.line_5 = QFrame(self.wt_audio_widget)
+ self.line_5.setObjectName(u"line_5")
+ self.line_5.setFrameShape(QFrame.HLine)
+ self.line_5.setFrameShadow(QFrame.Sunken)
- self.ghwt_stems_layout.addWidget(self.line_8, 15, 0, 1, 4)
+ self.ghwt_stems_layout.addWidget(self.line_5, 9, 0, 1, 4)
+
+ self.bass_label = QLabel(self.wt_audio_widget)
+ self.bass_label.setObjectName(u"bass_label")
+ self.bass_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.ghwt_stems_layout.addWidget(self.bass_label, 8, 1, 1, 1)
self.bass_select = QToolButton(self.wt_audio_widget)
self.bass_select.setObjectName(u"bass_select")
@@ -343,30 +375,24 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.bass_select, 8, 3, 1, 1)
- self.line_3 = QFrame(self.wt_audio_widget)
- self.line_3.setObjectName(u"line_3")
- self.line_3.setFrameShape(QFrame.HLine)
- self.line_3.setFrameShadow(QFrame.Sunken)
-
- self.ghwt_stems_layout.addWidget(self.line_3, 5, 0, 1, 4)
-
- self.vocals_input = QLineEdit(self.wt_audio_widget)
- self.vocals_input.setObjectName(u"vocals_input")
- self.vocals_input.setEnabled(True)
+ self.crowd_input = QLineEdit(self.wt_audio_widget)
+ self.crowd_input.setObjectName(u"crowd_input")
+ self.crowd_input.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.vocals_input, 10, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.crowd_input, 14, 2, 1, 1)
- self.guitar_select = QToolButton(self.wt_audio_widget)
- self.guitar_select.setObjectName(u"guitar_select")
- self.guitar_select.setEnabled(True)
+ self.backing_input = QLineEdit(self.wt_audio_widget)
+ self.backing_input.setObjectName(u"backing_input")
+ self.backing_input.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.guitar_select, 6, 3, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.backing_input, 12, 2, 1, 1)
- self.vocals_label = QLabel(self.wt_audio_widget)
- self.vocals_label.setObjectName(u"vocals_label")
- self.vocals_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.line_8 = QFrame(self.wt_audio_widget)
+ self.line_8.setObjectName(u"line_8")
+ self.line_8.setFrameShape(QFrame.HLine)
+ self.line_8.setFrameShadow(QFrame.Sunken)
- self.ghwt_stems_layout.addWidget(self.vocals_label, 10, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.line_8, 17, 0, 1, 4)
self.line_7 = QFrame(self.wt_audio_widget)
self.line_7.setObjectName(u"line_7")
@@ -375,23 +401,11 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.line_7, 13, 0, 1, 4)
- self.toms_label = QLabel(self.wt_audio_widget)
- self.toms_label.setObjectName(u"toms_label")
- self.toms_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
-
- self.ghwt_stems_layout.addWidget(self.toms_label, 4, 1, 1, 1)
-
- self.backing_input = QLineEdit(self.wt_audio_widget)
- self.backing_input.setObjectName(u"backing_input")
- self.backing_input.setEnabled(True)
-
- self.ghwt_stems_layout.addWidget(self.backing_input, 12, 2, 1, 1)
-
- self.toms_select = QToolButton(self.wt_audio_widget)
- self.toms_select.setObjectName(u"toms_select")
- self.toms_select.setEnabled(True)
+ self.cymbals_select = QToolButton(self.wt_audio_widget)
+ self.cymbals_select.setObjectName(u"cymbals_select")
+ self.cymbals_select.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.toms_select, 4, 3, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.cymbals_select, 3, 3, 1, 1)
self.guitar_label = QLabel(self.wt_audio_widget)
self.guitar_label.setObjectName(u"guitar_label")
@@ -399,18 +413,29 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.guitar_label, 6, 1, 1, 1)
- self.crowd_select = QToolButton(self.wt_audio_widget)
- self.crowd_select.setObjectName(u"crowd_select")
- self.crowd_select.setEnabled(True)
+ self.toms_input = QLineEdit(self.wt_audio_widget)
+ self.toms_input.setObjectName(u"toms_input")
+ self.toms_input.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.crowd_select, 14, 3, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.toms_input, 4, 2, 1, 1)
- self.line_6 = QFrame(self.wt_audio_widget)
- self.line_6.setObjectName(u"line_6")
- self.line_6.setFrameShape(QFrame.HLine)
- self.line_6.setFrameShadow(QFrame.Sunken)
+ self.vocals_label = QLabel(self.wt_audio_widget)
+ self.vocals_label.setObjectName(u"vocals_label")
+ self.vocals_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.ghwt_stems_layout.addWidget(self.line_6, 11, 0, 1, 4)
+ self.ghwt_stems_layout.addWidget(self.vocals_label, 10, 1, 1, 1)
+
+ self.ghwt_preview_audio_input = QLineEdit(self.wt_audio_widget)
+ self.ghwt_preview_audio_input.setObjectName(u"ghwt_preview_audio_input")
+ self.ghwt_preview_audio_input.setEnabled(False)
+
+ self.ghwt_stems_layout.addWidget(self.ghwt_preview_audio_input, 16, 2, 1, 1)
+
+ self.snare_label = QLabel(self.wt_audio_widget)
+ self.snare_label.setObjectName(u"snare_label")
+ self.snare_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.ghwt_stems_layout.addWidget(self.snare_label, 2, 1, 1, 1)
self.cymbals_label = QLabel(self.wt_audio_widget)
self.cymbals_label.setObjectName(u"cymbals_label")
@@ -426,49 +451,54 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.label, 0, 2, 1, 1)
- self.track_label = QLabel(self.wt_audio_widget)
- self.track_label.setObjectName(u"track_label")
- sizePolicy2.setHeightForWidth(self.track_label.sizePolicy().hasHeightForWidth())
- self.track_label.setSizePolicy(sizePolicy2)
- self.track_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.kick_select = QToolButton(self.wt_audio_widget)
+ self.kick_select.setObjectName(u"kick_select")
+ self.kick_select.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.track_label, 0, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.kick_select, 1, 3, 1, 1)
- self.crowd_input = QLineEdit(self.wt_audio_widget)
- self.crowd_input.setObjectName(u"crowd_input")
- self.crowd_input.setEnabled(True)
+ self.ghwt_preview_label = QLabel(self.wt_audio_widget)
+ self.ghwt_preview_label.setObjectName(u"ghwt_preview_label")
- self.ghwt_stems_layout.addWidget(self.crowd_input, 14, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.ghwt_preview_label, 16, 1, 1, 1, Qt.AlignRight)
- self.vocals_select = QToolButton(self.wt_audio_widget)
- self.vocals_select.setObjectName(u"vocals_select")
- self.vocals_select.setEnabled(True)
+ self.kick_label = QLabel(self.wt_audio_widget)
+ self.kick_label.setObjectName(u"kick_label")
+ self.kick_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.ghwt_stems_layout.addWidget(self.vocals_select, 10, 3, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.kick_label, 1, 1, 1, 1)
- self.cymbals_input = QLineEdit(self.wt_audio_widget)
- self.cymbals_input.setObjectName(u"cymbals_input")
- self.cymbals_input.setEnabled(True)
+ self.toms_select = QToolButton(self.wt_audio_widget)
+ self.toms_select.setObjectName(u"toms_select")
+ self.toms_select.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.cymbals_input, 3, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.toms_select, 4, 3, 1, 1)
- self.kick_select = QToolButton(self.wt_audio_widget)
- self.kick_select.setObjectName(u"kick_select")
- self.kick_select.setEnabled(True)
+ self.bass_input = QLineEdit(self.wt_audio_widget)
+ self.bass_input.setObjectName(u"bass_input")
+ self.bass_input.setEnabled(True)
- self.ghwt_stems_layout.addWidget(self.kick_select, 1, 3, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.bass_input, 8, 2, 1, 1)
- self.snare_input = QLineEdit(self.wt_audio_widget)
- self.snare_input.setObjectName(u"snare_input")
- self.snare_input.setEnabled(True)
+ self.track_label = QLabel(self.wt_audio_widget)
+ self.track_label.setObjectName(u"track_label")
+ sizePolicy2.setHeightForWidth(self.track_label.sizePolicy().hasHeightForWidth())
+ self.track_label.setSizePolicy(sizePolicy2)
+ self.track_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.ghwt_stems_layout.addWidget(self.snare_input, 2, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.track_label, 0, 1, 1, 1)
- self.backing_label = QLabel(self.wt_audio_widget)
- self.backing_label.setObjectName(u"backing_label")
- self.backing_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.ghwt_preview_audio_select = QToolButton(self.wt_audio_widget)
+ self.ghwt_preview_audio_select.setObjectName(u"ghwt_preview_audio_select")
+ self.ghwt_preview_audio_select.setEnabled(False)
- self.ghwt_stems_layout.addWidget(self.backing_label, 12, 1, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.ghwt_preview_audio_select, 16, 3, 1, 1)
+
+ self.crowd_label = QLabel(self.wt_audio_widget)
+ self.crowd_label.setObjectName(u"crowd_label")
+ self.crowd_label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.ghwt_stems_layout.addWidget(self.crowd_label, 14, 1, 1, 1)
self.guitar_input = QLineEdit(self.wt_audio_widget)
self.guitar_input.setObjectName(u"guitar_input")
@@ -476,32 +506,16 @@ def setupUi(self, Form):
self.ghwt_stems_layout.addWidget(self.guitar_input, 6, 2, 1, 1)
- self.line_5 = QFrame(self.wt_audio_widget)
- self.line_5.setObjectName(u"line_5")
- self.line_5.setFrameShape(QFrame.HLine)
- self.line_5.setFrameShadow(QFrame.Sunken)
-
- self.ghwt_stems_layout.addWidget(self.line_5, 9, 0, 1, 4)
-
- self.kick_input = QLineEdit(self.wt_audio_widget)
- self.kick_input.setObjectName(u"kick_input")
- self.kick_input.setEnabled(True)
+ self.line_11 = QFrame(self.wt_audio_widget)
+ self.line_11.setObjectName(u"line_11")
+ self.line_11.setFrameShape(QFrame.HLine)
+ self.line_11.setFrameShadow(QFrame.Sunken)
- self.ghwt_stems_layout.addWidget(self.kick_input, 1, 2, 1, 1)
+ self.ghwt_stems_layout.addWidget(self.line_11, 15, 0, 1, 4)
self.verticalLayout_9.addLayout(self.ghwt_stems_layout)
- self.horizontalLayout_13 = QHBoxLayout()
- self.horizontalLayout_13.setObjectName(u"horizontalLayout_13")
- self.encrypt_audio = QCheckBox(self.wt_audio_widget)
- self.encrypt_audio.setObjectName(u"encrypt_audio")
-
- self.horizontalLayout_13.addWidget(self.encrypt_audio, 0, Qt.AlignRight)
-
-
- self.verticalLayout_9.addLayout(self.horizontalLayout_13)
-
self.horizontalLayout_2 = QHBoxLayout()
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.preview_label = QLabel(self.wt_audio_widget)
@@ -557,6 +571,21 @@ def setupUi(self, Form):
self.verticalLayout_9.addLayout(self.horizontalLayout_2)
+ self.horizontalLayout_13 = QHBoxLayout()
+ self.horizontalLayout_13.setObjectName(u"horizontalLayout_13")
+ self.encrypt_audio = QCheckBox(self.wt_audio_widget)
+ self.encrypt_audio.setObjectName(u"encrypt_audio")
+
+ self.horizontalLayout_13.addWidget(self.encrypt_audio, 0, Qt.AlignLeft)
+
+ self.ghwt_rendered_preview_check = QCheckBox(self.wt_audio_widget)
+ self.ghwt_rendered_preview_check.setObjectName(u"ghwt_rendered_preview_check")
+
+ self.horizontalLayout_13.addWidget(self.ghwt_rendered_preview_check)
+
+
+ self.verticalLayout_9.addLayout(self.horizontalLayout_13)
+
self.verticalLayout_3.addWidget(self.wt_audio_widget)
@@ -576,19 +605,24 @@ def setupUi(self, Form):
self.verticalLayout_10.setContentsMargins(0, 0, 0, 0)
self.gh3_stems_layout = QGridLayout()
self.gh3_stems_layout.setObjectName(u"gh3_stems_layout")
- self.line_9 = QFrame(self.gh3_audio_widget)
- self.line_9.setObjectName(u"line_9")
- self.line_9.setFrameShape(QFrame.HLine)
- self.line_9.setFrameShadow(QFrame.Sunken)
-
- self.gh3_stems_layout.addWidget(self.line_9, 11, 0, 1, 3)
-
self.guitar_label_gh3 = QLabel(self.gh3_audio_widget)
self.guitar_label_gh3.setObjectName(u"guitar_label_gh3")
self.guitar_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.gh3_stems_layout.addWidget(self.guitar_label_gh3, 1, 0, 1, 1)
+ self.backing_label_gh3 = QLabel(self.gh3_audio_widget)
+ self.backing_label_gh3.setObjectName(u"backing_label_gh3")
+ self.backing_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.gh3_stems_layout.addWidget(self.backing_label_gh3, 3, 0, 1, 1)
+
+ self.crowd_label_gh3 = QLabel(self.gh3_audio_widget)
+ self.crowd_label_gh3.setObjectName(u"crowd_label_gh3")
+ self.crowd_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.gh3_stems_layout.addWidget(self.crowd_label_gh3, 12, 0, 1, 1)
+
self.track_label_2 = QLabel(self.gh3_audio_widget)
self.track_label_2.setObjectName(u"track_label_2")
sizePolicy2.setHeightForWidth(self.track_label_2.sizePolicy().hasHeightForWidth())
@@ -597,29 +631,45 @@ def setupUi(self, Form):
self.gh3_stems_layout.addWidget(self.track_label_2, 0, 0, 1, 1)
- self.guitar_select_gh3 = QToolButton(self.gh3_audio_widget)
- self.guitar_select_gh3.setObjectName(u"guitar_select_gh3")
- self.guitar_select_gh3.setEnabled(True)
+ self.gh3_audio_options = QHBoxLayout()
+ self.gh3_audio_options.setObjectName(u"gh3_audio_options")
+ self.p2_rhythm_check = QCheckBox(self.gh3_audio_widget)
+ self.p2_rhythm_check.setObjectName(u"p2_rhythm_check")
- self.gh3_stems_layout.addWidget(self.guitar_select_gh3, 1, 2, 1, 1)
+ self.gh3_audio_options.addWidget(self.p2_rhythm_check)
- self.coop_guitar_input_gh3 = QLineEdit(self.gh3_audio_widget)
- self.coop_guitar_input_gh3.setObjectName(u"coop_guitar_input_gh3")
- self.coop_guitar_input_gh3.setEnabled(False)
+ self.coop_audio_check = QCheckBox(self.gh3_audio_widget)
+ self.coop_audio_check.setObjectName(u"coop_audio_check")
+ self.coop_audio_check.setEnabled(False)
- self.gh3_stems_layout.addWidget(self.coop_guitar_input_gh3, 7, 1, 1, 1)
+ self.gh3_audio_options.addWidget(self.coop_audio_check)
- self.rhythm_label_gh3 = QLabel(self.gh3_audio_widget)
- self.rhythm_label_gh3.setObjectName(u"rhythm_label_gh3")
- self.rhythm_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.gh3_stems_layout.addWidget(self.rhythm_label_gh3, 2, 0, 1, 1)
+ self.gh3_stems_layout.addLayout(self.gh3_audio_options, 5, 1, 1, 1)
- self.crowd_input_gh3 = QLineEdit(self.gh3_audio_widget)
- self.crowd_input_gh3.setObjectName(u"crowd_input_gh3")
- self.crowd_input_gh3.setEnabled(True)
+ self.coop_backing_input_gh3 = QLineEdit(self.gh3_audio_widget)
+ self.coop_backing_input_gh3.setObjectName(u"coop_backing_input_gh3")
+ self.coop_backing_input_gh3.setEnabled(False)
- self.gh3_stems_layout.addWidget(self.crowd_input_gh3, 12, 1, 1, 1)
+ self.gh3_stems_layout.addWidget(self.coop_backing_input_gh3, 10, 1, 1, 1)
+
+ self.coop_rhythm_input_gh3 = QLineEdit(self.gh3_audio_widget)
+ self.coop_rhythm_input_gh3.setObjectName(u"coop_rhythm_input_gh3")
+ self.coop_rhythm_input_gh3.setEnabled(False)
+
+ self.gh3_stems_layout.addWidget(self.coop_rhythm_input_gh3, 9, 1, 1, 1)
+
+ self.coop_guitar_select_gh3 = QToolButton(self.gh3_audio_widget)
+ self.coop_guitar_select_gh3.setObjectName(u"coop_guitar_select_gh3")
+ self.coop_guitar_select_gh3.setEnabled(False)
+
+ self.gh3_stems_layout.addWidget(self.coop_guitar_select_gh3, 7, 2, 1, 1)
+
+ self.coop_rhythm_label_gh3 = QLabel(self.gh3_audio_widget)
+ self.coop_rhythm_label_gh3.setObjectName(u"coop_rhythm_label_gh3")
+ self.coop_rhythm_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+
+ self.gh3_stems_layout.addWidget(self.coop_rhythm_label_gh3, 9, 0, 1, 1)
self.backing_select_gh3 = QToolButton(self.gh3_audio_widget)
self.backing_select_gh3.setObjectName(u"backing_select_gh3")
@@ -627,12 +677,6 @@ def setupUi(self, Form):
self.gh3_stems_layout.addWidget(self.backing_select_gh3, 3, 2, 1, 1)
- self.coop_backing_select_gh3 = QToolButton(self.gh3_audio_widget)
- self.coop_backing_select_gh3.setObjectName(u"coop_backing_select_gh3")
- self.coop_backing_select_gh3.setEnabled(False)
-
- self.gh3_stems_layout.addWidget(self.coop_backing_select_gh3, 10, 2, 1, 1)
-
self.gh3_file_path_label = QLabel(self.gh3_audio_widget)
self.gh3_file_path_label.setObjectName(u"gh3_file_path_label")
sizePolicy2.setHeightForWidth(self.gh3_file_path_label.sizePolicy().hasHeightForWidth())
@@ -641,41 +685,29 @@ def setupUi(self, Form):
self.gh3_stems_layout.addWidget(self.gh3_file_path_label, 0, 1, 1, 1)
- self.guitar_input_gh3 = QLineEdit(self.gh3_audio_widget)
- self.guitar_input_gh3.setObjectName(u"guitar_input_gh3")
- self.guitar_input_gh3.setEnabled(True)
-
- self.gh3_stems_layout.addWidget(self.guitar_input_gh3, 1, 1, 1, 1)
-
- self.backing_label_gh3 = QLabel(self.gh3_audio_widget)
- self.backing_label_gh3.setObjectName(u"backing_label_gh3")
- self.backing_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
-
- self.gh3_stems_layout.addWidget(self.backing_label_gh3, 3, 0, 1, 1)
-
self.crowd_select_gh3 = QToolButton(self.gh3_audio_widget)
self.crowd_select_gh3.setObjectName(u"crowd_select_gh3")
self.crowd_select_gh3.setEnabled(True)
self.gh3_stems_layout.addWidget(self.crowd_select_gh3, 12, 2, 1, 1)
- self.rhythm_select_gh3 = QToolButton(self.gh3_audio_widget)
- self.rhythm_select_gh3.setObjectName(u"rhythm_select_gh3")
- self.rhythm_select_gh3.setEnabled(True)
+ self.rhythm_label_gh3 = QLabel(self.gh3_audio_widget)
+ self.rhythm_label_gh3.setObjectName(u"rhythm_label_gh3")
+ self.rhythm_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.gh3_stems_layout.addWidget(self.rhythm_select_gh3, 2, 2, 1, 1)
+ self.gh3_stems_layout.addWidget(self.rhythm_label_gh3, 2, 0, 1, 1)
- self.coop_backing_input_gh3 = QLineEdit(self.gh3_audio_widget)
- self.coop_backing_input_gh3.setObjectName(u"coop_backing_input_gh3")
- self.coop_backing_input_gh3.setEnabled(False)
+ self.guitar_select_gh3 = QToolButton(self.gh3_audio_widget)
+ self.guitar_select_gh3.setObjectName(u"guitar_select_gh3")
+ self.guitar_select_gh3.setEnabled(True)
- self.gh3_stems_layout.addWidget(self.coop_backing_input_gh3, 10, 1, 1, 1)
+ self.gh3_stems_layout.addWidget(self.guitar_select_gh3, 1, 2, 1, 1)
- self.backing_input_gh3 = QLineEdit(self.gh3_audio_widget)
- self.backing_input_gh3.setObjectName(u"backing_input_gh3")
- self.backing_input_gh3.setEnabled(True)
+ self.coop_backing_label_gh3 = QLabel(self.gh3_audio_widget)
+ self.coop_backing_label_gh3.setObjectName(u"coop_backing_label_gh3")
+ self.coop_backing_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
- self.gh3_stems_layout.addWidget(self.backing_input_gh3, 3, 1, 1, 1)
+ self.gh3_stems_layout.addWidget(self.coop_backing_label_gh3, 10, 0, 1, 1)
self.coop_guitar_label_gh3 = QLabel(self.gh3_audio_widget)
self.coop_guitar_label_gh3.setObjectName(u"coop_guitar_label_gh3")
@@ -689,23 +721,42 @@ def setupUi(self, Form):
self.gh3_stems_layout.addWidget(self.rhythm_input_gh3, 2, 1, 1, 1)
- self.coop_rhythm_label_gh3 = QLabel(self.gh3_audio_widget)
- self.coop_rhythm_label_gh3.setObjectName(u"coop_rhythm_label_gh3")
- self.coop_rhythm_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.coop_guitar_input_gh3 = QLineEdit(self.gh3_audio_widget)
+ self.coop_guitar_input_gh3.setObjectName(u"coop_guitar_input_gh3")
+ self.coop_guitar_input_gh3.setEnabled(False)
- self.gh3_stems_layout.addWidget(self.coop_rhythm_label_gh3, 9, 0, 1, 1)
+ self.gh3_stems_layout.addWidget(self.coop_guitar_input_gh3, 7, 1, 1, 1)
- self.coop_rhythm_input_gh3 = QLineEdit(self.gh3_audio_widget)
- self.coop_rhythm_input_gh3.setObjectName(u"coop_rhythm_input_gh3")
- self.coop_rhythm_input_gh3.setEnabled(False)
+ self.rhythm_select_gh3 = QToolButton(self.gh3_audio_widget)
+ self.rhythm_select_gh3.setObjectName(u"rhythm_select_gh3")
+ self.rhythm_select_gh3.setEnabled(True)
- self.gh3_stems_layout.addWidget(self.coop_rhythm_input_gh3, 9, 1, 1, 1)
+ self.gh3_stems_layout.addWidget(self.rhythm_select_gh3, 2, 2, 1, 1)
- self.crowd_label_gh3 = QLabel(self.gh3_audio_widget)
- self.crowd_label_gh3.setObjectName(u"crowd_label_gh3")
- self.crowd_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.coop_backing_select_gh3 = QToolButton(self.gh3_audio_widget)
+ self.coop_backing_select_gh3.setObjectName(u"coop_backing_select_gh3")
+ self.coop_backing_select_gh3.setEnabled(False)
- self.gh3_stems_layout.addWidget(self.crowd_label_gh3, 12, 0, 1, 1)
+ self.gh3_stems_layout.addWidget(self.coop_backing_select_gh3, 10, 2, 1, 1)
+
+ self.line_9 = QFrame(self.gh3_audio_widget)
+ self.line_9.setObjectName(u"line_9")
+ self.line_9.setFrameShape(QFrame.HLine)
+ self.line_9.setFrameShadow(QFrame.Sunken)
+
+ self.gh3_stems_layout.addWidget(self.line_9, 11, 0, 1, 3)
+
+ self.backing_input_gh3 = QLineEdit(self.gh3_audio_widget)
+ self.backing_input_gh3.setObjectName(u"backing_input_gh3")
+ self.backing_input_gh3.setEnabled(True)
+
+ self.gh3_stems_layout.addWidget(self.backing_input_gh3, 3, 1, 1, 1)
+
+ self.crowd_input_gh3 = QLineEdit(self.gh3_audio_widget)
+ self.crowd_input_gh3.setObjectName(u"crowd_input_gh3")
+ self.crowd_input_gh3.setEnabled(True)
+
+ self.gh3_stems_layout.addWidget(self.crowd_input_gh3, 12, 1, 1, 1)
self.coop_rhythm_select_gh3 = QToolButton(self.gh3_audio_widget)
self.coop_rhythm_select_gh3.setObjectName(u"coop_rhythm_select_gh3")
@@ -713,37 +764,37 @@ def setupUi(self, Form):
self.gh3_stems_layout.addWidget(self.coop_rhythm_select_gh3, 9, 2, 1, 1)
- self.coop_guitar_select_gh3 = QToolButton(self.gh3_audio_widget)
- self.coop_guitar_select_gh3.setObjectName(u"coop_guitar_select_gh3")
- self.coop_guitar_select_gh3.setEnabled(False)
-
- self.gh3_stems_layout.addWidget(self.coop_guitar_select_gh3, 7, 2, 1, 1)
-
- self.coop_backing_label_gh3 = QLabel(self.gh3_audio_widget)
- self.coop_backing_label_gh3.setObjectName(u"coop_backing_label_gh3")
- self.coop_backing_label_gh3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.guitar_input_gh3 = QLineEdit(self.gh3_audio_widget)
+ self.guitar_input_gh3.setObjectName(u"guitar_input_gh3")
+ self.guitar_input_gh3.setEnabled(True)
- self.gh3_stems_layout.addWidget(self.coop_backing_label_gh3, 10, 0, 1, 1)
+ self.gh3_stems_layout.addWidget(self.guitar_input_gh3, 1, 1, 1, 1)
- self.gh3_audio_options = QHBoxLayout()
- self.gh3_audio_options.setObjectName(u"gh3_audio_options")
- self.p2_rhythm_check = QCheckBox(self.gh3_audio_widget)
- self.p2_rhythm_check.setObjectName(u"p2_rhythm_check")
+ self.gh3_preview_audio_label = QLabel(self.gh3_audio_widget)
+ self.gh3_preview_audio_label.setObjectName(u"gh3_preview_audio_label")
- self.gh3_audio_options.addWidget(self.p2_rhythm_check)
+ self.gh3_stems_layout.addWidget(self.gh3_preview_audio_label, 13, 0, 1, 1)
- self.coop_audio_check = QCheckBox(self.gh3_audio_widget)
- self.coop_audio_check.setObjectName(u"coop_audio_check")
- self.coop_audio_check.setEnabled(False)
+ self.gh3_preview_audio_input = QLineEdit(self.gh3_audio_widget)
+ self.gh3_preview_audio_input.setObjectName(u"gh3_preview_audio_input")
+ self.gh3_preview_audio_input.setEnabled(False)
- self.gh3_audio_options.addWidget(self.coop_audio_check)
+ self.gh3_stems_layout.addWidget(self.gh3_preview_audio_input, 13, 1, 1, 1)
+ self.gh3_preview_audio_select = QToolButton(self.gh3_audio_widget)
+ self.gh3_preview_audio_select.setObjectName(u"gh3_preview_audio_select")
+ self.gh3_preview_audio_select.setEnabled(False)
- self.gh3_stems_layout.addLayout(self.gh3_audio_options, 5, 1, 1, 1)
+ self.gh3_stems_layout.addWidget(self.gh3_preview_audio_select, 13, 2, 1, 1)
self.verticalLayout_10.addLayout(self.gh3_stems_layout)
+ self.gh3_rendered_preview_check = QCheckBox(self.gh3_audio_widget)
+ self.gh3_rendered_preview_check.setObjectName(u"gh3_rendered_preview_check")
+
+ self.verticalLayout_10.addWidget(self.gh3_rendered_preview_check)
+
self.gh3_preview_layout = QHBoxLayout()
self.gh3_preview_layout.setObjectName(u"gh3_preview_layout")
self.preview_label_2 = QLabel(self.gh3_audio_widget)
@@ -791,6 +842,11 @@ def setupUi(self, Form):
self.gh3_preview_layout.addWidget(self.length_mills_gh3)
+ self.gh3_set_end = QCheckBox(self.gh3_audio_widget)
+ self.gh3_set_end.setObjectName(u"gh3_set_end")
+
+ self.gh3_preview_layout.addWidget(self.gh3_set_end)
+
self.verticalLayout_10.addLayout(self.gh3_preview_layout)
@@ -809,83 +865,99 @@ def setupUi(self, Form):
self.verticalLayout_13.setContentsMargins(0, 0, 0, 0)
self.gridLayout_3 = QGridLayout()
self.gridLayout_3.setObjectName(u"gridLayout_3")
- self.ghwt_song_script_input = QLineEdit(self.wt_song_data_widget)
- self.ghwt_song_script_input.setObjectName(u"ghwt_song_script_input")
+ self.setlist_settings_layout = QHBoxLayout()
+ self.setlist_settings_layout.setObjectName(u"setlist_settings_layout")
+ self.game_icon_label = QLabel(self.wt_song_data_widget)
+ self.game_icon_label.setObjectName(u"game_icon_label")
- self.gridLayout_3.addWidget(self.ghwt_song_script_input, 3, 1, 1, 1)
+ self.setlist_settings_layout.addWidget(self.game_icon_label)
- self.ghwt_band_vol = QDoubleSpinBox(self.wt_song_data_widget)
- self.ghwt_band_vol.setObjectName(u"ghwt_band_vol")
- self.ghwt_band_vol.setMinimum(-10.000000000000000)
- self.ghwt_band_vol.setMaximum(5.000000000000000)
- self.ghwt_band_vol.setSingleStep(0.500000000000000)
+ self.game_icon_input = QLineEdit(self.wt_song_data_widget)
+ self.game_icon_input.setObjectName(u"game_icon_input")
- self.gridLayout_3.addWidget(self.ghwt_band_vol, 10, 1, 1, 1)
+ self.setlist_settings_layout.addWidget(self.game_icon_input)
- self.ghwor_stfs_label = QLabel(self.wt_song_data_widget)
- self.ghwor_stfs_label.setObjectName(u"ghwor_stfs_label")
+ self.game_category_label = QLabel(self.wt_song_data_widget)
+ self.game_category_label.setObjectName(u"game_category_label")
- self.gridLayout_3.addWidget(self.ghwor_stfs_label, 4, 0, 1, 1)
+ self.setlist_settings_layout.addWidget(self.game_category_label)
- self.ghwt_drumkit_label = QLabel(self.wt_song_data_widget)
- self.ghwt_drumkit_label.setObjectName(u"ghwt_drumkit_label")
+ self.game_category_input = QLineEdit(self.wt_song_data_widget)
+ self.game_category_input.setObjectName(u"game_category_input")
- self.gridLayout_3.addWidget(self.ghwt_drumkit_label, 7, 0, 1, 1)
+ self.setlist_settings_layout.addWidget(self.game_category_input)
- self.line_10 = QFrame(self.wt_song_data_widget)
- self.line_10.setObjectName(u"line_10")
- self.line_10.setFrameShape(QFrame.HLine)
- self.line_10.setFrameShadow(QFrame.Sunken)
+ self.band_label = QLabel(self.wt_song_data_widget)
+ self.band_label.setObjectName(u"band_label")
- self.gridLayout_3.addWidget(self.line_10, 12, 0, 1, 3)
+ self.setlist_settings_layout.addWidget(self.band_label)
- self.ghwt_midi_file_select = QToolButton(self.wt_song_data_widget)
- self.ghwt_midi_file_select.setObjectName(u"ghwt_midi_file_select")
+ self.band_input = QLineEdit(self.wt_song_data_widget)
+ self.band_input.setObjectName(u"band_input")
- self.gridLayout_3.addWidget(self.ghwt_midi_file_select, 0, 2, 1, 1)
+ self.setlist_settings_layout.addWidget(self.band_input)
- self.ghwt_ska_files_input = QLineEdit(self.wt_song_data_widget)
- self.ghwt_ska_files_input.setObjectName(u"ghwt_ska_files_input")
- self.gridLayout_3.addWidget(self.ghwt_ska_files_input, 2, 1, 1, 1)
+ self.gridLayout_3.addLayout(self.setlist_settings_layout, 17, 1, 1, 2)
- self.ghwt_vocal_gender_select = QComboBox(self.wt_song_data_widget)
- self.ghwt_vocal_gender_select.addItem("")
- self.ghwt_vocal_gender_select.addItem("")
- self.ghwt_vocal_gender_select.addItem("")
- self.ghwt_vocal_gender_select.setObjectName(u"ghwt_vocal_gender_select")
+ self.ghwt_perf_override_input = QLineEdit(self.wt_song_data_widget)
+ self.ghwt_perf_override_input.setObjectName(u"ghwt_perf_override_input")
- self.gridLayout_3.addWidget(self.ghwt_vocal_gender_select, 8, 1, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_perf_override_input, 1, 1, 1, 1)
- self.ghwt_song_script_select = QToolButton(self.wt_song_data_widget)
- self.ghwt_song_script_select.setObjectName(u"ghwt_song_script_select")
+ self.ghwt_band_vol = QDoubleSpinBox(self.wt_song_data_widget)
+ self.ghwt_band_vol.setObjectName(u"ghwt_band_vol")
+ self.ghwt_band_vol.setMinimum(-10.000000000000000)
+ self.ghwt_band_vol.setMaximum(5.000000000000000)
+ self.ghwt_band_vol.setSingleStep(0.500000000000000)
- self.gridLayout_3.addWidget(self.ghwt_song_script_select, 3, 2, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_band_vol, 11, 1, 1, 1)
- self.ghwt_vocal_gender_label = QLabel(self.wt_song_data_widget)
- self.ghwt_vocal_gender_label.setObjectName(u"ghwt_vocal_gender_label")
+ self.ghwt_drumkit_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_drumkit_label.setObjectName(u"ghwt_drumkit_label")
- self.gridLayout_3.addWidget(self.ghwt_vocal_gender_label, 8, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_drumkit_label, 7, 0, 1, 1)
- self.ghwt_song_script_label = QLabel(self.wt_song_data_widget)
- self.ghwt_song_script_label.setObjectName(u"ghwt_song_script_label")
+ self.ghwt_midi_file_input = QLineEdit(self.wt_song_data_widget)
+ self.ghwt_midi_file_input.setObjectName(u"ghwt_midi_file_input")
- self.gridLayout_3.addWidget(self.ghwt_song_script_label, 3, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_midi_file_input, 0, 1, 1, 1)
- self.ghwt_ska_files_label = QLabel(self.wt_song_data_widget)
- self.ghwt_ska_files_label.setObjectName(u"ghwt_ska_files_label")
+ self.ghwt_countoff_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_countoff_label.setObjectName(u"ghwt_countoff_label")
- self.gridLayout_3.addWidget(self.ghwt_ska_files_label, 2, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_countoff_label, 5, 0, 1, 1)
+
+ self.other_settings_label = QLabel(self.wt_song_data_widget)
+ self.other_settings_label.setObjectName(u"other_settings_label")
+
+ self.gridLayout_3.addWidget(self.other_settings_label, 15, 0, 1, 3, Qt.AlignHCenter)
+
+ self.ghwor_stfs_select = QToolButton(self.wt_song_data_widget)
+ self.ghwor_stfs_select.setObjectName(u"ghwor_stfs_select")
+
+ self.gridLayout_3.addWidget(self.ghwor_stfs_select, 4, 2, 1, 1)
self.ghwor_stfs_input = QLineEdit(self.wt_song_data_widget)
self.ghwor_stfs_input.setObjectName(u"ghwor_stfs_input")
self.gridLayout_3.addWidget(self.ghwor_stfs_input, 4, 1, 1, 1)
- self.ghwt_perf_override_select = QToolButton(self.wt_song_data_widget)
- self.ghwt_perf_override_select.setObjectName(u"ghwt_perf_override_select")
+ self.ghwt_song_script_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_song_script_label.setObjectName(u"ghwt_song_script_label")
- self.gridLayout_3.addWidget(self.ghwt_perf_override_select, 1, 2, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_song_script_label, 3, 0, 1, 1)
+
+ self.ghwt_countoff_select = QComboBox(self.wt_song_data_widget)
+ self.ghwt_countoff_select.addItem(u"Hihat01")
+ self.ghwt_countoff_select.addItem(u"Hihat02")
+ self.ghwt_countoff_select.addItem(u"Hihat03")
+ self.ghwt_countoff_select.addItem(u"Sticks_Huge")
+ self.ghwt_countoff_select.addItem(u"Sticks_Normal")
+ self.ghwt_countoff_select.addItem(u"Sticks_Tiny")
+ self.ghwt_countoff_select.setObjectName(u"ghwt_countoff_select")
+
+ self.gridLayout_3.addWidget(self.ghwt_countoff_select, 5, 1, 1, 1)
self.tiers_layout = QGridLayout()
self.tiers_layout.setObjectName(u"tiers_layout")
@@ -963,78 +1035,23 @@ def setupUi(self, Form):
self.tiers_layout.addWidget(self.band_tier_value, 4, 1, 1, 1)
- self.gridLayout_3.addLayout(self.tiers_layout, 11, 1, 1, 1)
-
- self.ghwt_countoff_select = QComboBox(self.wt_song_data_widget)
- self.ghwt_countoff_select.addItem(u"Hihat01")
- self.ghwt_countoff_select.addItem(u"Hihat02")
- self.ghwt_countoff_select.addItem(u"Hihat03")
- self.ghwt_countoff_select.addItem(u"Sticks_Huge")
- self.ghwt_countoff_select.addItem(u"Sticks_Normal")
- self.ghwt_countoff_select.addItem(u"Sticks_Tiny")
- self.ghwt_countoff_select.setObjectName(u"ghwt_countoff_select")
+ self.gridLayout_3.addLayout(self.tiers_layout, 13, 1, 1, 1)
- self.gridLayout_3.addWidget(self.ghwt_countoff_select, 5, 1, 1, 1)
-
- self.ghwt_ska_files_select = QToolButton(self.wt_song_data_widget)
- self.ghwt_ska_files_select.setObjectName(u"ghwt_ska_files_select")
-
- self.gridLayout_3.addWidget(self.ghwt_ska_files_select, 2, 2, 1, 1)
-
- self.ghwt_countoff_label = QLabel(self.wt_song_data_widget)
- self.ghwt_countoff_label.setObjectName(u"ghwt_countoff_label")
+ self.vocal_scroll_speed_input = QDoubleSpinBox(self.wt_song_data_widget)
+ self.vocal_scroll_speed_input.setObjectName(u"vocal_scroll_speed_input")
+ self.vocal_scroll_speed_input.setValue(1.000000000000000)
- self.gridLayout_3.addWidget(self.ghwt_countoff_label, 5, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.vocal_scroll_speed_input, 9, 1, 1, 1)
self.tiers_label = QLabel(self.wt_song_data_widget)
self.tiers_label.setObjectName(u"tiers_label")
- self.gridLayout_3.addWidget(self.tiers_label, 11, 0, 1, 1)
-
- self.setlist_settings_layout = QHBoxLayout()
- self.setlist_settings_layout.setObjectName(u"setlist_settings_layout")
- self.game_icon_label = QLabel(self.wt_song_data_widget)
- self.game_icon_label.setObjectName(u"game_icon_label")
-
- self.setlist_settings_layout.addWidget(self.game_icon_label)
-
- self.game_icon_input = QLineEdit(self.wt_song_data_widget)
- self.game_icon_input.setObjectName(u"game_icon_input")
-
- self.setlist_settings_layout.addWidget(self.game_icon_input)
-
- self.game_category_label = QLabel(self.wt_song_data_widget)
- self.game_category_label.setObjectName(u"game_category_label")
-
- self.setlist_settings_layout.addWidget(self.game_category_label)
-
- self.game_category_input = QLineEdit(self.wt_song_data_widget)
- self.game_category_input.setObjectName(u"game_category_input")
-
- self.setlist_settings_layout.addWidget(self.game_category_input)
-
- self.band_label = QLabel(self.wt_song_data_widget)
- self.band_label.setObjectName(u"band_label")
-
- self.setlist_settings_layout.addWidget(self.band_label)
-
- self.band_input = QLineEdit(self.wt_song_data_widget)
- self.band_input.setObjectName(u"band_input")
-
- self.setlist_settings_layout.addWidget(self.band_input)
-
-
- self.gridLayout_3.addLayout(self.setlist_settings_layout, 15, 1, 1, 2)
+ self.gridLayout_3.addWidget(self.tiers_label, 13, 0, 1, 1)
- self.other_settings_label = QLabel(self.wt_song_data_widget)
- self.other_settings_label.setObjectName(u"other_settings_label")
-
- self.gridLayout_3.addWidget(self.other_settings_label, 13, 0, 1, 3, Qt.AlignHCenter)
-
- self.label_3 = QLabel(self.wt_song_data_widget)
- self.label_3.setObjectName(u"label_3")
+ self.vocal_speed_label = QLabel(self.wt_song_data_widget)
+ self.vocal_speed_label.setObjectName(u"vocal_speed_label")
- self.gridLayout_3.addWidget(self.label_3, 15, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.vocal_speed_label, 9, 0, 1, 1)
self.skeleton_types_layout = QHBoxLayout()
self.skeleton_types_layout.setObjectName(u"skeleton_types_layout")
@@ -1086,83 +1103,145 @@ def setupUi(self, Form):
self.skeleton_types_layout.addWidget(self.skeleton_type_v_select)
- self.gridLayout_3.addLayout(self.skeleton_types_layout, 16, 1, 1, 2)
+ self.gridLayout_3.addLayout(self.skeleton_types_layout, 18, 1, 1, 2)
- self.vocal_speed_label = QLabel(self.wt_song_data_widget)
- self.vocal_speed_label.setObjectName(u"vocal_speed_label")
+ self.ghwt_band_vol_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_band_vol_label.setObjectName(u"ghwt_band_vol_label")
- self.gridLayout_3.addWidget(self.vocal_speed_label, 9, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_band_vol_label, 11, 0, 1, 1)
- self.ghwor_stfs_select = QToolButton(self.wt_song_data_widget)
- self.ghwor_stfs_select.setObjectName(u"ghwor_stfs_select")
+ self.horizontalLayout_9 = QHBoxLayout()
+ self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
+ self.guitar_mic_check = QCheckBox(self.wt_song_data_widget)
+ self.guitar_mic_check.setObjectName(u"guitar_mic_check")
- self.gridLayout_3.addWidget(self.ghwor_stfs_select, 4, 2, 1, 1)
+ self.horizontalLayout_9.addWidget(self.guitar_mic_check)
- self.skeleton_types_label = QLabel(self.wt_song_data_widget)
- self.skeleton_types_label.setObjectName(u"skeleton_types_label")
+ self.bass_mic_check = QCheckBox(self.wt_song_data_widget)
+ self.bass_mic_check.setObjectName(u"bass_mic_check")
+
+ self.horizontalLayout_9.addWidget(self.bass_mic_check)
+
+ self.use_new_clips_check = QCheckBox(self.wt_song_data_widget)
+ self.use_new_clips_check.setObjectName(u"use_new_clips_check")
+
+ self.horizontalLayout_9.addWidget(self.use_new_clips_check)
+
+
+ self.gridLayout_3.addLayout(self.horizontalLayout_9, 16, 1, 1, 2)
+
+ self.ghwt_vocal_cents_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_vocal_cents_label.setObjectName(u"ghwt_vocal_cents_label")
+
+ self.gridLayout_3.addWidget(self.ghwt_vocal_cents_label, 10, 0, 1, 1)
+
+ self.ghwt_ska_files_input = QLineEdit(self.wt_song_data_widget)
+ self.ghwt_ska_files_input.setObjectName(u"ghwt_ska_files_input")
+
+ self.gridLayout_3.addWidget(self.ghwt_ska_files_input, 2, 1, 1, 1)
+
+ self.ghwt_perf_override_select = QToolButton(self.wt_song_data_widget)
+ self.ghwt_perf_override_select.setObjectName(u"ghwt_perf_override_select")
+
+ self.gridLayout_3.addWidget(self.ghwt_perf_override_select, 1, 2, 1, 1)
+
+ self.ghwt_ska_files_select = QToolButton(self.wt_song_data_widget)
+ self.ghwt_ska_files_select.setObjectName(u"ghwt_ska_files_select")
+
+ self.gridLayout_3.addWidget(self.ghwt_ska_files_select, 2, 2, 1, 1)
+
+ self.ghwt_ska_files_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_ska_files_label.setObjectName(u"ghwt_ska_files_label")
+
+ self.gridLayout_3.addWidget(self.ghwt_ska_files_label, 2, 0, 1, 1)
+
+ self.label_3 = QLabel(self.wt_song_data_widget)
+ self.label_3.setObjectName(u"label_3")
+
+ self.gridLayout_3.addWidget(self.label_3, 17, 0, 1, 1)
+
+ self.ghwt_song_script_select = QToolButton(self.wt_song_data_widget)
+ self.ghwt_song_script_select.setObjectName(u"ghwt_song_script_select")
+
+ self.gridLayout_3.addWidget(self.ghwt_song_script_select, 3, 2, 1, 1)
+
+ self.label_7 = QLabel(self.wt_song_data_widget)
+ self.label_7.setObjectName(u"label_7")
+
+ self.gridLayout_3.addWidget(self.label_7, 16, 0, 1, 1)
+
+ self.ghwt_song_script_input = QLineEdit(self.wt_song_data_widget)
+ self.ghwt_song_script_input.setObjectName(u"ghwt_song_script_input")
+
+ self.gridLayout_3.addWidget(self.ghwt_song_script_input, 3, 1, 1, 1)
+
+ self.line_10 = QFrame(self.wt_song_data_widget)
+ self.line_10.setObjectName(u"line_10")
+ self.line_10.setFrameShape(QFrame.HLine)
+ self.line_10.setFrameShadow(QFrame.Sunken)
- self.gridLayout_3.addWidget(self.skeleton_types_label, 16, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.line_10, 14, 0, 1, 3)
self.ghwt_drumkit_select = QComboBox(self.wt_song_data_widget)
self.ghwt_drumkit_select.setObjectName(u"ghwt_drumkit_select")
self.gridLayout_3.addWidget(self.ghwt_drumkit_select, 7, 1, 1, 1)
- self.ghwt_perf_override_label = QLabel(self.wt_song_data_widget)
- self.ghwt_perf_override_label.setObjectName(u"ghwt_perf_override_label")
-
- self.gridLayout_3.addWidget(self.ghwt_perf_override_label, 1, 0, 1, 1)
-
- self.ghwt_perf_override_input = QLineEdit(self.wt_song_data_widget)
- self.ghwt_perf_override_input.setObjectName(u"ghwt_perf_override_input")
+ self.ghwt_vocal_gender_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_vocal_gender_label.setObjectName(u"ghwt_vocal_gender_label")
- self.gridLayout_3.addWidget(self.ghwt_perf_override_input, 1, 1, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_vocal_gender_label, 8, 0, 1, 1)
- self.ghwt_band_vol_label = QLabel(self.wt_song_data_widget)
- self.ghwt_band_vol_label.setObjectName(u"ghwt_band_vol_label")
+ self.ghwt_midi_file_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_midi_file_label.setObjectName(u"ghwt_midi_file_label")
- self.gridLayout_3.addWidget(self.ghwt_band_vol_label, 10, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_midi_file_label, 0, 0, 1, 1)
- self.vocal_scroll_speed_input = QDoubleSpinBox(self.wt_song_data_widget)
- self.vocal_scroll_speed_input.setObjectName(u"vocal_scroll_speed_input")
- self.vocal_scroll_speed_input.setValue(1.000000000000000)
+ self.ghwt_perf_override_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_perf_override_label.setObjectName(u"ghwt_perf_override_label")
- self.gridLayout_3.addWidget(self.vocal_scroll_speed_input, 9, 1, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_perf_override_label, 1, 0, 1, 1)
- self.ghwt_midi_file_input = QLineEdit(self.wt_song_data_widget)
- self.ghwt_midi_file_input.setObjectName(u"ghwt_midi_file_input")
+ self.ghwor_stfs_label = QLabel(self.wt_song_data_widget)
+ self.ghwor_stfs_label.setObjectName(u"ghwor_stfs_label")
- self.gridLayout_3.addWidget(self.ghwt_midi_file_input, 0, 1, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwor_stfs_label, 4, 0, 1, 1)
- self.ghwt_midi_file_label = QLabel(self.wt_song_data_widget)
- self.ghwt_midi_file_label.setObjectName(u"ghwt_midi_file_label")
+ self.skeleton_types_label = QLabel(self.wt_song_data_widget)
+ self.skeleton_types_label.setObjectName(u"skeleton_types_label")
- self.gridLayout_3.addWidget(self.ghwt_midi_file_label, 0, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.skeleton_types_label, 18, 0, 1, 1)
- self.label_7 = QLabel(self.wt_song_data_widget)
- self.label_7.setObjectName(u"label_7")
+ self.ghwt_vocal_gender_select = QComboBox(self.wt_song_data_widget)
+ self.ghwt_vocal_gender_select.addItem("")
+ self.ghwt_vocal_gender_select.addItem("")
+ self.ghwt_vocal_gender_select.addItem("")
+ self.ghwt_vocal_gender_select.setObjectName(u"ghwt_vocal_gender_select")
- self.gridLayout_3.addWidget(self.label_7, 14, 0, 1, 1)
+ self.gridLayout_3.addWidget(self.ghwt_vocal_gender_select, 8, 1, 1, 1)
- self.horizontalLayout_9 = QHBoxLayout()
- self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
- self.guitar_mic_check = QCheckBox(self.wt_song_data_widget)
- self.guitar_mic_check.setObjectName(u"guitar_mic_check")
+ self.ghwt_vocal_cents = QSpinBox(self.wt_song_data_widget)
+ self.ghwt_vocal_cents.setObjectName(u"ghwt_vocal_cents")
+ self.ghwt_vocal_cents.setMinimum(-50)
+ self.ghwt_vocal_cents.setMaximum(50)
- self.horizontalLayout_9.addWidget(self.guitar_mic_check)
+ self.gridLayout_3.addWidget(self.ghwt_vocal_cents, 10, 1, 1, 1)
- self.bass_mic_check = QCheckBox(self.wt_song_data_widget)
- self.bass_mic_check.setObjectName(u"bass_mic_check")
+ self.ghwt_midi_file_select = QToolButton(self.wt_song_data_widget)
+ self.ghwt_midi_file_select.setObjectName(u"ghwt_midi_file_select")
- self.horizontalLayout_9.addWidget(self.bass_mic_check)
+ self.gridLayout_3.addWidget(self.ghwt_midi_file_select, 0, 2, 1, 1)
- self.use_new_clips_check = QCheckBox(self.wt_song_data_widget)
- self.use_new_clips_check.setObjectName(u"use_new_clips_check")
+ self.ghwt_whammy_cutoff_label = QLabel(self.wt_song_data_widget)
+ self.ghwt_whammy_cutoff_label.setObjectName(u"ghwt_whammy_cutoff_label")
- self.horizontalLayout_9.addWidget(self.use_new_clips_check)
+ self.gridLayout_3.addWidget(self.ghwt_whammy_cutoff_label, 12, 0, 1, 1)
+ self.ghwt_whammy_cutoff = QDoubleSpinBox(self.wt_song_data_widget)
+ self.ghwt_whammy_cutoff.setObjectName(u"ghwt_whammy_cutoff")
+ self.ghwt_whammy_cutoff.setValue(0.500000000000000)
- self.gridLayout_3.addLayout(self.horizontalLayout_9, 14, 1, 1, 2)
+ self.gridLayout_3.addWidget(self.ghwt_whammy_cutoff, 12, 1, 1, 1)
self.verticalLayout_13.addLayout(self.gridLayout_3)
@@ -1182,6 +1261,25 @@ def setupUi(self, Form):
self.verticalLayout_7.setContentsMargins(0, 0, 0, 0)
self.gridLayout_5 = QGridLayout()
self.gridLayout_5.setObjectName(u"gridLayout_5")
+ self.gh3_ska_files_select = QToolButton(self.gh3_song_data_widget)
+ self.gh3_ska_files_select.setObjectName(u"gh3_ska_files_select")
+
+ self.gridLayout_5.addWidget(self.gh3_ska_files_select, 2, 2, 1, 1)
+
+ self.gh3_ska_files_label = QLabel(self.gh3_song_data_widget)
+ self.gh3_ska_files_label.setObjectName(u"gh3_ska_files_label")
+
+ self.gridLayout_5.addWidget(self.gh3_ska_files_label, 2, 0, 1, 1)
+
+ self.gh3_vocal_gender_select = QComboBox(self.gh3_song_data_widget)
+ self.gh3_vocal_gender_select.addItem("")
+ self.gh3_vocal_gender_select.addItem("")
+ self.gh3_vocal_gender_select.addItem("")
+ self.gh3_vocal_gender_select.addItem("")
+ self.gh3_vocal_gender_select.setObjectName(u"gh3_vocal_gender_select")
+
+ self.gridLayout_5.addWidget(self.gh3_vocal_gender_select, 7, 1, 1, 1)
+
self.horizontalLayout_7 = QHBoxLayout()
self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
self.gh3_gtr_vol_label = QLabel(self.gh3_song_data_widget)
@@ -1213,17 +1311,34 @@ def setupUi(self, Form):
self.horizontalLayout_7.addWidget(self.gh3_band_vol)
- self.gridLayout_5.addLayout(self.horizontalLayout_7, 7, 1, 1, 1)
+ self.gridLayout_5.addLayout(self.horizontalLayout_7, 10, 1, 1, 1)
- self.gh3_perf_override_label = QLabel(self.gh3_song_data_widget)
- self.gh3_perf_override_label.setObjectName(u"gh3_perf_override_label")
+ self.gh3_perf_override_input = QLineEdit(self.gh3_song_data_widget)
+ self.gh3_perf_override_input.setObjectName(u"gh3_perf_override_input")
- self.gridLayout_5.addWidget(self.gh3_perf_override_label, 1, 0, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_perf_override_input, 1, 1, 1, 1)
self.gh3_countoff_label = QLabel(self.gh3_song_data_widget)
self.gh3_countoff_label.setObjectName(u"gh3_countoff_label")
- self.gridLayout_5.addWidget(self.gh3_countoff_label, 2, 0, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_countoff_label, 5, 0, 1, 1)
+
+ self.line = QFrame(self.gh3_song_data_widget)
+ self.line.setObjectName(u"line")
+ self.line.setFrameShape(QFrame.HLine)
+ self.line.setFrameShadow(QFrame.Sunken)
+
+ self.gridLayout_5.addWidget(self.line, 9, 0, 1, 3)
+
+ self.gh3_midi_file_input = QLineEdit(self.gh3_song_data_widget)
+ self.gh3_midi_file_input.setObjectName(u"gh3_midi_file_input")
+
+ self.gridLayout_5.addWidget(self.gh3_midi_file_input, 0, 1, 1, 1)
+
+ self.gh3_perf_override_label = QLabel(self.gh3_song_data_widget)
+ self.gh3_perf_override_label.setObjectName(u"gh3_perf_override_label")
+
+ self.gridLayout_5.addWidget(self.gh3_perf_override_label, 1, 0, 1, 1)
self.gh3_countoff_select = QComboBox(self.gh3_song_data_widget)
self.gh3_countoff_select.addItem(u"Hihat01")
@@ -1234,68 +1349,67 @@ def setupUi(self, Form):
self.gh3_countoff_select.addItem(u"Sticks_Tiny")
self.gh3_countoff_select.setObjectName(u"gh3_countoff_select")
- self.gridLayout_5.addWidget(self.gh3_countoff_select, 2, 1, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_countoff_select, 5, 1, 1, 1)
- self.gh3_vocal_gender_select = QComboBox(self.gh3_song_data_widget)
- self.gh3_vocal_gender_select.addItem("")
- self.gh3_vocal_gender_select.addItem("")
- self.gh3_vocal_gender_select.addItem("")
- self.gh3_vocal_gender_select.addItem("")
- self.gh3_vocal_gender_select.setObjectName(u"gh3_vocal_gender_select")
+ self.gh3_bassist_select = QComboBox(self.gh3_song_data_widget)
+ self.gh3_bassist_select.setObjectName(u"gh3_bassist_select")
+
+ self.gridLayout_5.addWidget(self.gh3_bassist_select, 8, 1, 1, 1)
+
+ self.gh3_volume_label = QLabel(self.gh3_song_data_widget)
+ self.gh3_volume_label.setObjectName(u"gh3_volume_label")
+
+ self.gridLayout_5.addWidget(self.gh3_volume_label, 10, 0, 1, 1)
+
+ self.gh3_song_script_label = QLabel(self.gh3_song_data_widget)
+ self.gh3_song_script_label.setObjectName(u"gh3_song_script_label")
- self.gridLayout_5.addWidget(self.gh3_vocal_gender_select, 4, 1, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_song_script_label, 4, 0, 1, 1)
+
+ self.gh3_midi_file_select = QToolButton(self.gh3_song_data_widget)
+ self.gh3_midi_file_select.setObjectName(u"gh3_midi_file_select")
+
+ self.gridLayout_5.addWidget(self.gh3_midi_file_select, 0, 2, 1, 1)
self.gh3_bassist_select_label = QLabel(self.gh3_song_data_widget)
self.gh3_bassist_select_label.setObjectName(u"gh3_bassist_select_label")
- self.gridLayout_5.addWidget(self.gh3_bassist_select_label, 5, 0, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_bassist_select_label, 8, 0, 1, 1)
- self.gh3_midi_file_input = QLineEdit(self.gh3_song_data_widget)
- self.gh3_midi_file_input.setObjectName(u"gh3_midi_file_input")
+ self.gh3_song_script_select = QToolButton(self.gh3_song_data_widget)
+ self.gh3_song_script_select.setObjectName(u"gh3_song_script_select")
- self.gridLayout_5.addWidget(self.gh3_midi_file_input, 0, 1, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_song_script_select, 4, 2, 1, 1)
- self.gh3_midi_file_label = QLabel(self.gh3_song_data_widget)
- self.gh3_midi_file_label.setObjectName(u"gh3_midi_file_label")
+ self.gh3_song_script_input = QLineEdit(self.gh3_song_data_widget)
+ self.gh3_song_script_input.setObjectName(u"gh3_song_script_input")
- self.gridLayout_5.addWidget(self.gh3_midi_file_label, 0, 0, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_song_script_input, 4, 1, 1, 1)
self.gh3_perf_override_select = QToolButton(self.gh3_song_data_widget)
self.gh3_perf_override_select.setObjectName(u"gh3_perf_override_select")
self.gridLayout_5.addWidget(self.gh3_perf_override_select, 1, 2, 1, 1)
- self.gh3_bassist_select = QComboBox(self.gh3_song_data_widget)
- self.gh3_bassist_select.setObjectName(u"gh3_bassist_select")
-
- self.gridLayout_5.addWidget(self.gh3_bassist_select, 5, 1, 1, 1)
-
- self.gh3_midi_file_select = QToolButton(self.gh3_song_data_widget)
- self.gh3_midi_file_select.setObjectName(u"gh3_midi_file_select")
-
- self.gridLayout_5.addWidget(self.gh3_midi_file_select, 0, 2, 1, 1)
-
- self.gh3_perf_override_input = QLineEdit(self.gh3_song_data_widget)
- self.gh3_perf_override_input.setObjectName(u"gh3_perf_override_input")
+ self.gh3_vocal_gender_label = QLabel(self.gh3_song_data_widget)
+ self.gh3_vocal_gender_label.setObjectName(u"gh3_vocal_gender_label")
- self.gridLayout_5.addWidget(self.gh3_perf_override_input, 1, 1, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_vocal_gender_label, 7, 0, 1, 1)
- self.gh3_volume_label = QLabel(self.gh3_song_data_widget)
- self.gh3_volume_label.setObjectName(u"gh3_volume_label")
+ self.gh3_ska_files_input = QLineEdit(self.gh3_song_data_widget)
+ self.gh3_ska_files_input.setObjectName(u"gh3_ska_files_input")
- self.gridLayout_5.addWidget(self.gh3_volume_label, 7, 0, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_ska_files_input, 2, 1, 1, 1)
- self.gh3_vocal_gender_label = QLabel(self.gh3_song_data_widget)
- self.gh3_vocal_gender_label.setObjectName(u"gh3_vocal_gender_label")
+ self.gh3_midi_file_label = QLabel(self.gh3_song_data_widget)
+ self.gh3_midi_file_label.setObjectName(u"gh3_midi_file_label")
- self.gridLayout_5.addWidget(self.gh3_vocal_gender_label, 4, 0, 1, 1)
+ self.gridLayout_5.addWidget(self.gh3_midi_file_label, 0, 0, 1, 1)
- self.line = QFrame(self.gh3_song_data_widget)
- self.line.setObjectName(u"line")
- self.line.setFrameShape(QFrame.HLine)
- self.line.setFrameShadow(QFrame.Sunken)
+ self.gh3_ska_file_convert_check = QCheckBox(self.gh3_song_data_widget)
+ self.gh3_ska_file_convert_check.setObjectName(u"gh3_ska_file_convert_check")
- self.gridLayout_5.addWidget(self.line, 6, 0, 1, 3)
+ self.gridLayout_5.addWidget(self.gh3_ska_file_convert_check, 3, 1, 1, 1)
self.verticalLayout_7.addLayout(self.gridLayout_5)
@@ -1440,12 +1554,12 @@ def setupUi(self, Form):
self.verticalLayout_15.addLayout(self.gridLayout_6)
- self.horizontalLayout_5 = QHBoxLayout()
- self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
+ self.platform_select = QHBoxLayout()
+ self.platform_select.setObjectName(u"platform_select")
self.platform_label = QLabel(self.compile_settings)
self.platform_label.setObjectName(u"platform_label")
- self.horizontalLayout_5.addWidget(self.platform_label)
+ self.platform_select.addWidget(self.platform_label)
self.platform_pc = QRadioButton(self.compile_settings)
self.platform_button_group = QButtonGroup(Form)
@@ -1454,17 +1568,17 @@ def setupUi(self, Form):
self.platform_pc.setObjectName(u"platform_pc")
self.platform_pc.setChecked(True)
- self.horizontalLayout_5.addWidget(self.platform_pc)
+ self.platform_select.addWidget(self.platform_pc)
self.platform_360 = QRadioButton(self.compile_settings)
self.platform_button_group.addButton(self.platform_360)
self.platform_360.setObjectName(u"platform_360")
self.platform_360.setEnabled(False)
- self.horizontalLayout_5.addWidget(self.platform_360)
+ self.platform_select.addWidget(self.platform_360)
- self.verticalLayout_15.addLayout(self.horizontalLayout_5)
+ self.verticalLayout_15.addLayout(self.platform_select)
self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
@@ -1574,8 +1688,19 @@ def setupUi(self, Form):
self.beatlines_check.toggled.connect(self.beat_16th_low_input.setEnabled)
self.beatlines_check.toggled.connect(self.beat_16th_high_input.setEnabled)
self.p2_rhythm_check.toggled.connect(self.coop_audio_check.setEnabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.ghwt_preview_audio_input.setEnabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.ghwt_preview_audio_select.setEnabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.preview_minutes.setDisabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.preview_seconds.setDisabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.preview_mills.setDisabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.length_minutes.setDisabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.length_seconds.setDisabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.length_mills.setDisabled)
+ self.ghwt_rendered_preview_check.toggled.connect(self.ghwt_set_end.setDisabled)
+ self.gh3_rendered_preview_check.toggled.connect(self.gh3_preview_audio_input.setEnabled)
+ self.gh3_rendered_preview_check.toggled.connect(self.gh3_preview_audio_select.setEnabled)
- self.compile_tabs.setCurrentIndex(3)
+ self.compile_tabs.setCurrentIndex(5)
QMetaObject.connectSlotsByName(Form)
@@ -1603,81 +1728,78 @@ def retranslateUi(self, Form):
self.artist_label.setText(QCoreApplication.translate("Form", u"Artist:", None))
self.cover_artist_label.setText(QCoreApplication.translate("Form", u"Cover Artist:", None))
self.compile_tabs.setTabText(self.compile_tabs.indexOf(self.metadata_tab), QCoreApplication.translate("Form", u"Metadata", None))
+ self.crowd_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.toms_label.setText(QCoreApplication.translate("Form", u"Toms", None))
self.backing_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.cymbals_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.bass_label.setText(QCoreApplication.translate("Form", u"Bass", None))
+ self.backing_label.setText(QCoreApplication.translate("Form", u"Backing", None))
self.snare_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.kick_label.setText(QCoreApplication.translate("Form", u"Kick", None))
- self.crowd_label.setText(QCoreApplication.translate("Form", u"Crowd", None))
- self.snare_label.setText(QCoreApplication.translate("Form", u"Snare", None))
- self.bass_select.setText(QCoreApplication.translate("Form", u"...", None))
self.guitar_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.vocals_label.setText(QCoreApplication.translate("Form", u"Vocals", None))
- self.toms_label.setText(QCoreApplication.translate("Form", u"Toms", None))
- self.toms_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.vocals_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.bass_label.setText(QCoreApplication.translate("Form", u"Bass", None))
+ self.bass_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.cymbals_select.setText(QCoreApplication.translate("Form", u"...", None))
self.guitar_label.setText(QCoreApplication.translate("Form", u"Guitar", None))
- self.crowd_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.vocals_label.setText(QCoreApplication.translate("Form", u"Vocals", None))
+ self.snare_label.setText(QCoreApplication.translate("Form", u"Snare", None))
self.cymbals_label.setText(QCoreApplication.translate("Form", u"Cymbals", None))
self.label.setText(QCoreApplication.translate("Form", u"Audio File Path", None))
- self.track_label.setText(QCoreApplication.translate("Form", u"Track", None))
- self.vocals_select.setText(QCoreApplication.translate("Form", u"...", None))
self.kick_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.backing_label.setText(QCoreApplication.translate("Form", u"Backing", None))
- self.encrypt_audio.setText(QCoreApplication.translate("Form", u"Encrypt Audio", None))
+ self.ghwt_preview_label.setText(QCoreApplication.translate("Form", u"Preview", None))
+ self.kick_label.setText(QCoreApplication.translate("Form", u"Kick", None))
+ self.toms_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.track_label.setText(QCoreApplication.translate("Form", u"Track", None))
+ self.ghwt_preview_audio_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.crowd_label.setText(QCoreApplication.translate("Form", u"Crowd", None))
self.preview_label.setText(QCoreApplication.translate("Form", u"Preview Start:", None))
self.length_label.setText(QCoreApplication.translate("Form", u"Length:", None))
self.ghwt_set_end.setText(QCoreApplication.translate("Form", u"Set End Time", None))
+ self.encrypt_audio.setText(QCoreApplication.translate("Form", u"Encrypt Audio", None))
+ self.ghwt_rendered_preview_check.setText(QCoreApplication.translate("Form", u"Use Rendered Preview Audio", None))
self.compile_tabs.setTabText(self.compile_tabs.indexOf(self.audio_tab_wt), QCoreApplication.translate("Form", u"Audio (WT)", None))
self.guitar_label_gh3.setText(QCoreApplication.translate("Form", u"Guitar", None))
+ self.backing_label_gh3.setText(QCoreApplication.translate("Form", u"Backing", None))
+ self.crowd_label_gh3.setText(QCoreApplication.translate("Form", u"Crowd", None))
self.track_label_2.setText(QCoreApplication.translate("Form", u"Track", None))
- self.guitar_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
- self.rhythm_label_gh3.setText(QCoreApplication.translate("Form", u"Bass", None))
+ self.p2_rhythm_check.setText(QCoreApplication.translate("Form", u"P2 is Rhythm", None))
+ self.coop_audio_check.setText(QCoreApplication.translate("Form", u"Separate Co-op Audio", None))
+ self.coop_guitar_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
+ self.coop_rhythm_label_gh3.setText(QCoreApplication.translate("Form", u"Rhythm", None))
self.backing_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
- self.coop_backing_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
self.gh3_file_path_label.setText(QCoreApplication.translate("Form", u"Audio File Path", None))
- self.backing_label_gh3.setText(QCoreApplication.translate("Form", u"Backing", None))
self.crowd_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
- self.rhythm_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
+ self.rhythm_label_gh3.setText(QCoreApplication.translate("Form", u"Bass", None))
+ self.guitar_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
+ self.coop_backing_label_gh3.setText(QCoreApplication.translate("Form", u"Backing", None))
self.coop_guitar_label_gh3.setText(QCoreApplication.translate("Form", u"Guitar", None))
- self.coop_rhythm_label_gh3.setText(QCoreApplication.translate("Form", u"Rhythm", None))
- self.crowd_label_gh3.setText(QCoreApplication.translate("Form", u"Crowd", None))
+ self.rhythm_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
+ self.coop_backing_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
self.coop_rhythm_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
- self.coop_guitar_select_gh3.setText(QCoreApplication.translate("Form", u"...", None))
- self.coop_backing_label_gh3.setText(QCoreApplication.translate("Form", u"Backing", None))
- self.p2_rhythm_check.setText(QCoreApplication.translate("Form", u"P2 is Rhythm", None))
- self.coop_audio_check.setText(QCoreApplication.translate("Form", u"Separate Co-op Audio", None))
+ self.gh3_preview_audio_label.setText(QCoreApplication.translate("Form", u"Preview", None))
+ self.gh3_preview_audio_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.gh3_rendered_preview_check.setText(QCoreApplication.translate("Form", u"Use Rendered Preview", None))
self.preview_label_2.setText(QCoreApplication.translate("Form", u"Song Preview:", None))
self.length_label_2.setText(QCoreApplication.translate("Form", u"Length:", None))
+ self.gh3_set_end.setText(QCoreApplication.translate("Form", u"Set End Time", None))
self.compile_tabs.setTabText(self.compile_tabs.indexOf(self.audio_tab_gh3), QCoreApplication.translate("Form", u"Audio (GH3)", None))
- self.ghwor_stfs_label.setText(QCoreApplication.translate("Form", u"WoR STFS File", None))
- self.ghwt_drumkit_label.setText(QCoreApplication.translate("Form", u"Drum Kit:", None))
- self.ghwt_midi_file_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.game_icon_label.setText(QCoreApplication.translate("Form", u"Game Icon", None))
+ self.game_category_label.setText(QCoreApplication.translate("Form", u"Game Category", None))
+ self.band_label.setText(QCoreApplication.translate("Form", u"Band", None))
#if QT_CONFIG(tooltip)
- self.ghwt_ska_files_input.setToolTip(QCoreApplication.translate("Form", u"
A folder containing all SKA files used. Gets ignored if it's blank or doesn't exist
", None))
+ self.ghwt_perf_override_input.setToolTip(QCoreApplication.translate("Form", u"Select a file with a performance array to override the generated performance array.
Can be a text file compatible with the toolkit, or an already compiled qb file.
", None))
#endif // QT_CONFIG(tooltip)
- self.ghwt_vocal_gender_select.setItemText(0, QCoreApplication.translate("Form", u"Male", None))
- self.ghwt_vocal_gender_select.setItemText(1, QCoreApplication.translate("Form", u"Female", None))
- self.ghwt_vocal_gender_select.setItemText(2, QCoreApplication.translate("Form", u"None", None))
-
- self.ghwt_song_script_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.ghwt_vocal_gender_label.setText(QCoreApplication.translate("Form", u"Vocal Gender:", None))
+ self.ghwt_drumkit_label.setText(QCoreApplication.translate("Form", u"Drum Kit:", None))
+ self.ghwt_countoff_label.setText(QCoreApplication.translate("Form", u"Count Off:", None))
+ self.other_settings_label.setText(QCoreApplication.translate("Form", u"World Tour Definitive Edition Settings", None))
+ self.ghwor_stfs_select.setText(QCoreApplication.translate("Form", u"...", None))
self.ghwt_song_script_label.setText(QCoreApplication.translate("Form", u"Song Script:", None))
- self.ghwt_ska_files_label.setText(QCoreApplication.translate("Form", u"SKA Files:", None))
- self.ghwt_perf_override_select.setText(QCoreApplication.translate("Form", u"...", None))
+
self.band_tier_label.setText(QCoreApplication.translate("Form", u"Band", None))
self.vocal_tier_label.setText(QCoreApplication.translate("Form", u"Vocals", None))
self.drums_tier_label.setText(QCoreApplication.translate("Form", u"Drums", None))
self.guitar_tier_label.setText(QCoreApplication.translate("Form", u"Guitar", None))
self.bass_tier_label.setText(QCoreApplication.translate("Form", u"Bass", None))
-
- self.ghwt_ska_files_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.ghwt_countoff_label.setText(QCoreApplication.translate("Form", u"Count Off:", None))
self.tiers_label.setText(QCoreApplication.translate("Form", u"Tiers", None))
- self.game_icon_label.setText(QCoreApplication.translate("Form", u"Game Icon", None))
- self.game_category_label.setText(QCoreApplication.translate("Form", u"Game Category", None))
- self.band_label.setText(QCoreApplication.translate("Form", u"Band", None))
- self.other_settings_label.setText(QCoreApplication.translate("Form", u"World Tour Definitive Edition Settings", None))
- self.label_3.setText(QCoreApplication.translate("Form", u"Setlist Settings", None))
+ self.vocal_speed_label.setText(QCoreApplication.translate("Form", u"Vocal Scroll Speed:", None))
self.skeleton_type_g_label.setText(QCoreApplication.translate("Form", u"G", None))
self.skeleton_type_g_select.setItemText(0, QCoreApplication.translate("Form", u"Default", None))
self.skeleton_type_g_select.setItemText(1, QCoreApplication.translate("Form", u"Alex", None))
@@ -1690,39 +1812,59 @@ def retranslateUi(self, Form):
self.skeleton_type_b_label.setText(QCoreApplication.translate("Form", u"B", None))
self.skeleton_type_d_label.setText(QCoreApplication.translate("Form", u"D", None))
self.skeleton_type_v_label.setText(QCoreApplication.translate("Form", u"V", None))
- self.vocal_speed_label.setText(QCoreApplication.translate("Form", u"Vocal Scroll Speed:", None))
- self.ghwor_stfs_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.skeleton_types_label.setText(QCoreApplication.translate("Form", u"Skeleton Types", None))
- self.ghwt_perf_override_label.setText(QCoreApplication.translate("Form", u"Perf Override:", None))
-#if QT_CONFIG(tooltip)
- self.ghwt_perf_override_input.setToolTip(QCoreApplication.translate("Form", u"Select a file with a performance array to override the generated performance array.
Can be a text file compatible with the toolkit, or an already compiled qb file.
", None))
-#endif // QT_CONFIG(tooltip)
self.ghwt_band_vol_label.setText(QCoreApplication.translate("Form", u"Overall Volume:", None))
- self.ghwt_midi_file_label.setText(QCoreApplication.translate("Form", u"MIDI File:", None))
- self.label_7.setText(QCoreApplication.translate("Form", u"In-game Settings", None))
self.guitar_mic_check.setText(QCoreApplication.translate("Form", u"Guitar Mic", None))
self.bass_mic_check.setText(QCoreApplication.translate("Form", u"Bass Mic", None))
self.use_new_clips_check.setText(QCoreApplication.translate("Form", u"Use New Clips", None))
- self.compile_tabs.setTabText(self.compile_tabs.indexOf(self.song_data_tab_wt), QCoreApplication.translate("Form", u"Song Data (WT)", None))
- self.gh3_gtr_vol_label.setText(QCoreApplication.translate("Form", u"Guitar:", None))
- self.gh3_band_vol_label.setText(QCoreApplication.translate("Form", u"Band:", None))
- self.gh3_perf_override_label.setText(QCoreApplication.translate("Form", u"Perf Override", None))
- self.gh3_countoff_label.setText(QCoreApplication.translate("Form", u"Count Off:", None))
+ self.ghwt_vocal_cents_label.setText(QCoreApplication.translate("Form", u"Vocal Tuning Cents:", None))
+#if QT_CONFIG(tooltip)
+ self.ghwt_ska_files_input.setToolTip(QCoreApplication.translate("Form", u"A folder containing all SKA files used. Gets ignored if it's blank or doesn't exist
", None))
+#endif // QT_CONFIG(tooltip)
+ self.ghwt_perf_override_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.ghwt_ska_files_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.ghwt_ska_files_label.setText(QCoreApplication.translate("Form", u"SKA Files:", None))
+ self.label_3.setText(QCoreApplication.translate("Form", u"Setlist Settings", None))
+ self.ghwt_song_script_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.label_7.setText(QCoreApplication.translate("Form", u"In-game Settings", None))
+ self.ghwt_vocal_gender_label.setText(QCoreApplication.translate("Form", u"Vocal Gender:", None))
+ self.ghwt_midi_file_label.setText(QCoreApplication.translate("Form", u"MIDI File:", None))
+ self.ghwt_perf_override_label.setText(QCoreApplication.translate("Form", u"Perf Override:", None))
+ self.ghwor_stfs_label.setText(QCoreApplication.translate("Form", u"WoR STFS File", None))
+ self.skeleton_types_label.setText(QCoreApplication.translate("Form", u"Skeleton Types", None))
+ self.ghwt_vocal_gender_select.setItemText(0, QCoreApplication.translate("Form", u"Male", None))
+ self.ghwt_vocal_gender_select.setItemText(1, QCoreApplication.translate("Form", u"Female", None))
+ self.ghwt_vocal_gender_select.setItemText(2, QCoreApplication.translate("Form", u"None", None))
+ self.ghwt_midi_file_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.ghwt_whammy_cutoff_label.setText(QCoreApplication.translate("Form", u"Sustain Threshold:", None))
+#if QT_CONFIG(tooltip)
+ self.ghwt_whammy_cutoff.setToolTip(QCoreApplication.translate("Form", u"The threshold at which sustains appear. In World Tour, the default is 0.50 and it can be read as "If a note is longer than 50% of the current beat's length, it is a sustain."
In GH5 and up, this value is 0.45, meaning that a note only needs to be 45% the length of the distance between 2 beats.
Make the number smaller to have more sustains appear (for lower BPMs), and make it larger to have fewer sustains appear (for higher BPMs).
", None))
+#endif // QT_CONFIG(tooltip)
+ self.compile_tabs.setTabText(self.compile_tabs.indexOf(self.song_data_tab_wt), QCoreApplication.translate("Form", u"Song Data (WT)", None))
+ self.gh3_ska_files_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.gh3_ska_files_label.setText(QCoreApplication.translate("Form", u"SKA Files:", None))
self.gh3_vocal_gender_select.setItemText(0, QCoreApplication.translate("Form", u"Male", None))
self.gh3_vocal_gender_select.setItemText(1, QCoreApplication.translate("Form", u"Female", None))
self.gh3_vocal_gender_select.setItemText(2, QCoreApplication.translate("Form", u"Bret Michaels", None))
self.gh3_vocal_gender_select.setItemText(3, QCoreApplication.translate("Form", u"None", None))
- self.gh3_bassist_select_label.setText(QCoreApplication.translate("Form", u"Bassist:", None))
- self.gh3_midi_file_label.setText(QCoreApplication.translate("Form", u"MIDI File", None))
- self.gh3_perf_override_select.setText(QCoreApplication.translate("Form", u"...", None))
- self.gh3_midi_file_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.gh3_gtr_vol_label.setText(QCoreApplication.translate("Form", u"Guitar:", None))
+ self.gh3_band_vol_label.setText(QCoreApplication.translate("Form", u"Band:", None))
#if QT_CONFIG(tooltip)
self.gh3_perf_override_input.setToolTip(QCoreApplication.translate("Form", u"Select a qb file with a performance array to override the generated performance array.", None))
#endif // QT_CONFIG(tooltip)
+ self.gh3_countoff_label.setText(QCoreApplication.translate("Form", u"Count Off:", None))
+ self.gh3_perf_override_label.setText(QCoreApplication.translate("Form", u"Perf Override:", None))
+
self.gh3_volume_label.setText(QCoreApplication.translate("Form", u"Volume:", None))
+ self.gh3_song_script_label.setText(QCoreApplication.translate("Form", u"Song Script:", None))
+ self.gh3_midi_file_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.gh3_bassist_select_label.setText(QCoreApplication.translate("Form", u"Bassist:", None))
+ self.gh3_song_script_select.setText(QCoreApplication.translate("Form", u"...", None))
+ self.gh3_perf_override_select.setText(QCoreApplication.translate("Form", u"...", None))
self.gh3_vocal_gender_label.setText(QCoreApplication.translate("Form", u"Vocal Gender:", None))
+ self.gh3_midi_file_label.setText(QCoreApplication.translate("Form", u"MIDI File:", None))
+ self.gh3_ska_file_convert_check.setText(QCoreApplication.translate("Form", u"Do not convert SKA Files", None))
self.compile_tabs.setTabText(self.compile_tabs.indexOf(self.song_data_tab_gh3), QCoreApplication.translate("Form", u"Song Data (GH3)", None))
self.compile_settings.setTitle(QCoreApplication.translate("Form", u"Compile Settings", None))
self.beat_8th_high_label.setText(QCoreApplication.translate("Form", u"High:", None))
@@ -1737,7 +1879,7 @@ def retranslateUi(self, Form):
self.beat_8th_low_label.setText(QCoreApplication.translate("Form", u"Low:", None))
self.hopo_mode_label.setText(QCoreApplication.translate("Form", u"HOPO Mode", None))
self.hopo_mode_select.setItemText(0, QCoreApplication.translate("Form", u"Rock Band", None))
- self.hopo_mode_select.setItemText(1, QCoreApplication.translate("Form", u"HMX/NS Hybrid", None))
+ self.hopo_mode_select.setItemText(1, QCoreApplication.translate("Form", u"Moonscraper", None))
self.hopo_mode_select.setItemText(2, QCoreApplication.translate("Form", u"Guitar Hero 3", None))
self.hopo_mode_select.setItemText(3, QCoreApplication.translate("Form", u"Guitar Hero World Tour+", None))
diff --git a/gui/project_files/compile_package.ui b/gui/project_files/compile_package.ui
index f88f840..8e3238c 100644
--- a/gui/project_files/compile_package.ui
+++ b/gui/project_files/compile_package.ui
@@ -7,7 +7,7 @@
0
0
562
- 659
+ 712
@@ -31,7 +31,7 @@
- 4
+ 5
true
@@ -86,7 +86,7 @@
-
- false
+ true
GH3
@@ -102,7 +102,7 @@
-
- false
+ true
GHA
@@ -391,15 +391,8 @@
9
-
-
-
-
- true
-
-
-
- -
-
+
-
+
true
@@ -408,35 +401,25 @@
- -
-
+
-
+
true
-
- ...
-
-
-
- -
-
-
- Qt::Horizontal
-
- -
-
+
-
+
- Bass
+ Toms
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
+
-
+
true
@@ -445,52 +428,32 @@
- -
-
-
- Kick
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- true
-
-
-
- -
-
+
-
+
- Crowd
+ Backing
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
- Snare
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
-
+
+
+ Qt::Horizontal
- -
-
-
- Qt::Horizontal
+
-
+
+
+ true
- -
-
+
-
+
true
@@ -506,8 +469,15 @@
- -
-
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
true
@@ -523,33 +493,57 @@
- -
-
+
-
+
+
+ true
+
- Vocals
+ ...
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ -
+
+
+ true
- -
-
+
-
+
Qt::Horizontal
- -
-
+
-
+
- Toms
+ Bass
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+ -
+
+
+ true
+
+
+ ...
+
+
+
+ -
+
+
+ true
+
+
+
-
@@ -557,8 +551,22 @@
- -
-
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
true
@@ -577,20 +585,37 @@
- -
-
+
-
+
true
+
+
+ -
+
- ...
+ Vocals
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
- Qt::Horizontal
+
-
+
+
+ false
+
+
+
+ -
+
+
+ Snare
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -620,31 +645,35 @@
- -
-
-
-
- 0
- 0
-
+
-
+
+
+ true
- Track
+ ...
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ -
+
+
+ Preview
- -
-
-
- true
+
-
+
+
+ Kick
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
+
-
+
true
@@ -653,34 +682,43 @@
- -
-
+
-
+
true
- -
-
-
- true
+
-
+
+
+
+ 0
+ 0
+
- ...
+ Track
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
+
-
+
- true
+ false
+
+
+ ...
- -
-
+
-
+
- Backing
+ Crowd
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -694,31 +732,13 @@
- -
-
+
-
+
Qt::Horizontal
- -
-
-
- true
-
-
-
-
-
- -
-
-
-
-
-
- Encrypt Audio
-
-
-
-
@@ -783,6 +803,24 @@
+ -
+
+
-
+
+
+ Encrypt Audio
+
+
+
+ -
+
+
+ Use Rendered Preview Audio
+
+
+
+
+
@@ -822,13 +860,6 @@
-
-
-
-
-
- Qt::Horizontal
-
-
-
-
@@ -839,6 +870,26 @@
+ -
+
+
+ Backing
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Crowd
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
-
@@ -855,40 +906,61 @@
- -
-
+
-
+
+
-
+
+
+ P2 is Rhythm
+
+
+
+ -
+
+
+ false
+
+
+ Separate Co-op Audio
+
+
+
+
+
+ -
+
- true
+ false
-
- ...
+
+
+ -
+
+
+ false
- -
-
+
-
+
false
+
+ ...
+
- -
-
+
-
+
- Bass
+ Rhythm
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
- true
-
-
-
-
@@ -899,16 +971,6 @@
- -
-
-
- false
-
-
- ...
-
-
-
-
@@ -925,25 +987,28 @@
- -
-
+
-
+
true
+
+ ...
+
- -
-
+
-
+
- Backing
+ Bass
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
+
-
+
true
@@ -952,27 +1017,13 @@
- -
-
-
- true
-
+
-
+
- ...
-
-
-
- -
-
-
- false
+ Backing
-
-
- -
-
-
- true
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -993,30 +1044,51 @@
- -
-
-
- Rhythm
+
-
+
+
+ false
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ -
+
+
+ true
+
+
+ ...
- -
-
+
-
+
false
+
+ ...
+
- -
-
-
- Crowd
+
-
+
+
+ Qt::Horizontal
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ true
@@ -1030,8 +1102,29 @@
- -
-
+
-
+
+
+ true
+
+
+
+ -
+
+
+ Preview
+
+
+
+ -
+
+
+ false
+
+
+
+ -
+
false
@@ -1040,45 +1133,21 @@
- -
-
+
+
+ -
+
+
+ Use Rendered Preview
+
+
+
+ -
+
+
-
+
- Backing
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
-
-
- P2 is Rhythm
-
-
-
- -
-
-
- false
-
-
- Separate Co-op Audio
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Song Preview:
+ Song Preview:
@@ -1126,6 +1195,13 @@
+ -
+
+
+ Set End Time
+
+
+
@@ -1155,10 +1231,48 @@
-
-
-
-
+
-
+
+
-
+
+
+ Game Icon
+
+
+
+ -
+
+
+ -
+
+
+ Game Category
+
+
+
+ -
+
+
+ -
+
+
+ Band
+
+
+
+ -
+
+
+
- -
+
-
+
+
+ <html><head/><body><p>Select a file with a performance array to override the generated performance array.</p><p>Can be a text file compatible with the toolkit, or an already compiled qb file.</p></body></html>
+
+
+
+ -
-10.000000000000000
@@ -1171,99 +1285,82 @@
- -
-
+
-
+
- WoR STFS File
+ Drum Kit:
- -
-
+
-
+
+
+ -
+
- Drum Kit:
+ Count Off:
- -
-
-
- Qt::Horizontal
+
-
+
+
+ World Tour Definitive Edition Settings
- -
-
+
-
+
...
- -
-
-
- <html><head/><body><p>A folder containing all SKA files used. Gets ignored if it's blank or doesn't exist</p></body></html>
+
-
+
+
+ -
+
+
+ Song Script:
- -
-
+
-
+
-
- Male
+ Hihat01
-
- Female
+ Hihat02
-
- None
+ Hihat03
+
+
+ -
+
+ Sticks_Huge
+
+
+ -
+
+ Sticks_Normal
+
+
+ -
+
+ Sticks_Tiny
- -
-
-
- ...
-
-
-
- -
-
-
- Vocal Gender:
-
-
-
- -
-
-
- Song Script:
-
-
-
- -
-
-
- SKA Files:
-
-
-
- -
-
-
- -
-
-
- ...
-
-
-
- -
+
-
-
@@ -1382,110 +1479,28 @@
- -
-
-
-
-
- Hihat01
-
-
- -
-
- Hihat02
-
-
- -
-
- Hihat03
-
-
- -
-
- Sticks_Huge
-
-
- -
-
- Sticks_Normal
-
-
- -
-
- Sticks_Tiny
-
-
-
-
- -
-
-
- ...
-
-
-
- -
-
-
- Count Off:
+
-
+
+
+ 1.000000000000000
- -
+
-
Tiers
- -
-
-
-
-
-
- Game Icon
-
-
-
- -
-
-
- -
-
-
- Game Category
-
-
-
- -
-
-
- -
-
-
- Band
-
-
-
- -
-
-
-
-
- -
-
-
- World Tour Definitive Edition Settings
-
-
-
- -
-
+
-
+
- Setlist Settings
+ Vocal Scroll Speed:
- -
+
-
-
@@ -1565,30 +1580,121 @@
- -
-
+
-
+
- Vocal Scroll Speed:
+ Overall Volume:
- -
-
+
-
+
+
-
+
+
+ Guitar Mic
+
+
+
+ -
+
+
+ Bass Mic
+
+
+
+ -
+
+
+ Use New Clips
+
+
+
+
+
+ -
+
+
+ Vocal Tuning Cents:
+
+
+
+ -
+
+
+ <html><head/><body><p>A folder containing all SKA files used. Gets ignored if it's blank or doesn't exist</p></body></html>
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ SKA Files:
+
+
+
+ -
+
+
+ Setlist Settings
+
+
+
+ -
+
...
-
-
+
- Skeleton Types
+ In-game Settings
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
-
+ -
+
+
+ Vocal Gender:
+
+
+
+ -
+
+
+ MIDI File:
+
+
+
-
@@ -1596,99 +1702,141 @@
- -
-
-
- <html><head/><body><p>Select a file with a performance array to override the generated performance array.</p><p>Can be a text file compatible with the toolkit, or an already compiled qb file.</p></body></html>
+
-
+
+
+ WoR STFS File
- -
-
+
-
+
- Overall Volume:
+ Skeleton Types
- -
-
-
- 1.000000000000000
+
-
+
+
-
+
+ Male
+
+
+ -
+
+ Female
+
+
+ -
+
+ None
+
+
+
+
+ -
+
+
+ -50
+
+
+ 50
- -
-
+
-
+
+
+ ...
+
+
- -
-
+
-
+
- MIDI File:
+ Sustain Threshold:
- -
-
+
-
+
+
+ <html><head/><body><p>The threshold at which sustains appear. In World Tour, the default is 0.50 and it can be read as "If a note is longer than 50% of the current beat's length, it is a sustain."</p><p><br/></p><p>In GH5 and up, this value is 0.45, meaning that a note only needs to be 45% the length of the distance between 2 beats.</p><p><br/></p><p>Make the number smaller to have more sustains appear (for lower BPMs), and make it larger to have fewer sustains appear (for higher BPMs).</p></body></html>
+
+
+ 0.500000000000000
+
+
+
+
+
+
+
+
+
+
+
+
+ Song Data (GH3)
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
-
+
- In-game Settings
+ ...
- -
-
+
-
+
+
+ SKA Files:
+
+
+
+ -
+
-
-
-
- Guitar Mic
-
-
+
+ Male
+
-
-
-
- Bass Mic
-
-
+
+ Female
+
-
-
-
- Use New Clips
-
-
+
+ Bret Michaels
+
+
+ -
+
+ None
+
-
+
-
-
-
-
-
-
-
-
-
- Song Data (GH3)
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
+
-
-
@@ -1738,21 +1886,38 @@
- -
-
-
- Perf Override
+
-
+
+
+ Select a qb file with a performance array to override the generated performance array.
- -
+
-
Count Off:
- -
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ -
+
+
+ Perf Override:
+
+
+
+ -
-
@@ -1786,89 +1951,75 @@
- -
-
-
-
-
- Male
-
-
- -
-
- Female
-
-
- -
-
- Bret Michaels
-
-
- -
-
- None
-
-
-
+ -
+
- -
-
+
-
+
- Bassist:
+ Volume:
- -
-
-
- -
-
+
-
+
- MIDI File
+ Song Script:
- -
-
+
-
+
...
- -
-
+
-
+
+
+ Bassist:
+
+
- -
-
+
-
+
...
- -
-
-
- Select a qb file with a performance array to override the generated performance array.
+
-
+
+
+ -
+
+
+ ...
-
-
+
- Volume:
+ Vocal Gender:
- -
-
+
-
+
+
+ -
+
- Vocal Gender:
+ MIDI File:
- -
-
-
- Qt::Horizontal
+
-
+
+
+ Do not convert SKA Files
@@ -2081,7 +2232,7 @@
-
- HMX/NS Hybrid
+ Moonscraper
-
@@ -2099,7 +2250,7 @@
-
-
+
-
@@ -2250,11 +2401,11 @@
setEnabled(bool)
- 240
- 238
+ 330
+ 261
- 391
+ 541
239
@@ -2270,8 +2421,8 @@
170
- 96
- 187
+ 155
+ 213
@@ -2282,12 +2433,12 @@
setEnabled(bool)
- 229
- 163
+ 512
+ 170
- 395
- 186
+ 541
+ 199
@@ -2298,12 +2449,12 @@
setEnabled(bool)
- 238
- 167
+ 512
+ 170
- 77
- 216
+ 136
+ 243
@@ -2314,12 +2465,12 @@
setEnabled(bool)
- 232
- 161
+ 512
+ 170
- 396
- 216
+ 541
+ 227
@@ -2334,8 +2485,8 @@
170
- 122
- 240
+ 181
+ 273
@@ -2346,12 +2497,12 @@
setEnabled(bool)
- 239
- 163
+ 512
+ 170
- 393
- 244
+ 541
+ 255
@@ -2362,12 +2513,12 @@
setEnabled(bool)
- 186
- 229
+ 330
+ 261
- 188
- 250
+ 305
+ 293
@@ -2378,12 +2529,12 @@
setEnabled(bool)
- 84
- 143
+ 107
+ 180
- 300
- 130
+ 376
+ 149
@@ -2394,12 +2545,12 @@
setEnabled(bool)
- 70
- 143
+ 93
+ 180
- 391
- 130
+ 529
+ 166
@@ -2410,12 +2561,12 @@
setEnabled(bool)
- 97
- 143
+ 120
+ 180
- 300
- 158
+ 376
+ 177
@@ -2426,12 +2577,12 @@
setEnabled(bool)
- 105
- 143
+ 128
+ 180
- 391
- 158
+ 529
+ 197
@@ -2442,18 +2593,194 @@
setEnabled(bool)
- 76
- 158
+ 136
+ 182
- 240
- 166
+ 512
+ 170
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ ghwt_preview_audio_input
+ setEnabled(bool)
+
+
+ 541
+ 620
+
+
+ 329
+ 425
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ ghwt_preview_audio_select
+ setEnabled(bool)
+
+
+ 541
+ 620
+
+
+ 541
+ 424
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ preview_minutes
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 139
+ 513
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ preview_seconds
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 188
+ 513
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ preview_mills
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 241
+ 513
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ length_minutes
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 339
+ 513
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ length_seconds
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 388
+ 513
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ length_mills
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 441
+ 513
+
+
+
+
+ ghwt_rendered_preview_check
+ toggled(bool)
+ ghwt_set_end
+ setDisabled(bool)
+
+
+ 541
+ 620
+
+
+ 541
+ 511
+
+
+
+
+ gh3_rendered_preview_check
+ toggled(bool)
+ gh3_preview_audio_input
+ setEnabled(bool)
+
+
+ 88
+ 362
+
+
+ 115
+ 335
+
+
+
+
+ gh3_rendered_preview_check
+ toggled(bool)
+ gh3_preview_audio_select
+ setEnabled(bool)
+
+
+ 453
+ 355
+
+
+ 526
+ 330
-
+
diff --git a/midqb_gen/MidQbGen.py b/midqb_gen/MidQbGen.py
index 09dcbbd..dc58f92 100644
--- a/midqb_gen/MidQbGen.py
+++ b/midqb_gen/MidQbGen.py
@@ -8,11 +8,15 @@
sys.path.append("..\\pak_extract")
-
+sys.path.append("..\\ska_converter")
+root_folder = os.path.realpath(os.path.dirname(__file__))
from pak_extract.pak_functions import createHeaderDict
from pak_extract.QB2Text import convert_qb_file, qb_bytes, print_qb_text_file
from pak_extract.Text2QB import main as t2q_main
+from ska_converter.ska_classes import ska_bytes, lipsync_dict
+from ska_converter.ska_functions import make_modern_ska, make_gh3_ska
+
tbp = 480
@@ -27,104 +31,167 @@ def make_mid(midfile, hopo, filename = "", *args, **kwargs):
headerDict = createHeaderDict(filename)
# print(headerDict)
+ xplus = 0
if "ghwt" in args:
qb_dict = parse_wt_qb(mid, hopo, *args)
- if "replace_perf" in args:
- perf_file = args[args.index("replace_perf") + 1]
-
- if perf_file.endswith(".txt"):
- with open(perf_file, "r") as f:
- perf_qb = f.read().replace("song_performance", f"{filename}_performance")
- if "qb_file = " not in perf_qb:
- perf_qb = f"qb_file = songs/{filename}.mid.qb\n" + perf_qb
- perf_qb = t2q_main(perf_qb, game = "GHWT")
- else:
- with open(perf_file, "rb") as f:
- perf_qb = f.read()
- qb_sections = convert_qb_file(qb_bytes(perf_qb), filename, headerDict,
- "PC")
- for x in qb_sections:
- if "_performance" in x.section_id and not "notes" in x.section_id:
- qb_dict["performance"] = x
- '''if qb_dict["performance_mid"]:
- sorted_section = {}
- for y in qb_dict["performance"].section_data:
- sorted_section[y.data_value[0].data_value] = y
- qb_dict["performance"].section_data += qb_dict["performance_mid"]'''
- break
- QBSections, midQS = create_wt_qb_sections(qb_dict, filename, *args)
- midQB = create_wt_qb(QBSections, filename)
- if "performance" in qb_dict:
- midQB = convert_qb_file(qb_bytes(midQB), filename, headerDict, "PC")
- for x in midQB:
- if "_performance" in x.section_id and not "notes" in x.section_id:
- if x.section_data == [0, 0]:
- x.array_node_type = qb_dict["performance"].array_node_type
- x.section_data = qb_dict["performance"].section_data
- else:
- x.section_data += qb_dict["performance"].section_data
- cam_list = list(qb_dict["anim"]["CAMERAS"].keys())
- sorted_section = {}
- for y in x.section_data:
- event_time = y.data_value[0].data_value
- if re.search(r'Band_PlayLoop', y.data_value[1].data_value, flags = re.IGNORECASE):
- closest_value = min(cam_list, key=lambda x: abs(y.data_value[0].data_value - x))
- if event_time != closest_value and abs(event_time - closest_value) < 1000:
- event_time = closest_value
- y.data_value[0].data_value = event_time
- if event_time in sorted_section:
- sorted_section[event_time].append(y)
- else:
- sorted_section[event_time] = [y]
- sorted_section = dict(sorted(sorted_section.items()))
- new_perf = []
- for z in sorted_section:
- new_perf.extend(sorted_section[z])
- x.section_data = new_perf
- break
- result = StringIO()
- orig_stdout = sys.stdout
- sys.stdout = result
- print_qb_text_file(midQB)
- sys.stdout = orig_stdout
- qb_text = result.getvalue()
- midQB = t2q_main(qb_text, game = "GHWT")
- # print()
+ midQB, midQS = make_wt_files(headerDict, qb_dict,filename, *args)
else:
- midParsed = parseGH3QB(mid, hopo)
- midQB = makeMidQB(midParsed, filename, headerDict, consoleType)
- """with open(f"{filename}_song.mid.qb", 'wb') as f:
- f.write(midQB)"""
+ # midParsed = parseGH3QB(mid, hopo)
+ qb_dict = parse_gh3_qb(mid, hopo, *args)
+ if "replace_perf" in args:
+ override_perf(filename, headerDict, qb_dict, *args)
+ qb_sections = create_gh3_sections(qb_dict, filename, headerDict, consoleType)
+ midQB = create_game_qb(qb_sections, filename, "GH3")
+ if "performance" in qb_dict:
+ midQB = add_perf_to_qb(midQB, filename, headerDict, qb_dict, *args)
if "qb" in args:
pakFile = {"qb": midQB, "qs": midQS}
else:
- to_pak = [[midQB, f"songs\\{filename}.mid.qb"]]
- if midQS:
- to_pak.append([midQS, f"songs\\{filename}.mid.qs"])
- if "add_ska" in args:
- for files in os.listdir(args[args.index("add_ska") + 1]):
- to_pak.append([open(f"{args[args.index('add_ska') + 1]}\\{files}", 'rb').read(), files])
- if "song_script" in args:
- song_script_file = args[args.index("song_script") + 1]
+ pakFile = create_pak_file(midQB, filename, midQS, *args)
+
+ if xplus:
+ x_filename = f"{filename}xplus"
+ xplusQB = make_wt_files(headerDict, xplus, x_filename, *args)[0]
+ if "performance" in xplus:
+ xplusQB = add_perf_to_qb(xplusQB, x_filename, headerDict, xplus, *args)
+ xplusPAK = create_pak_file(xplusQB, x_filename, midQS, *args)
+ return pakFile, xplusPAK
+ else:
+ return pakFile, filename
+
+def make_wt_files(headerDict, qb_dict, filename, *args):
+ if "replace_perf" in args:
+ override_perf(filename, headerDict, qb_dict, "GHWT", *args)
+ QBSections, midQS = create_wt_qb_sections(qb_dict, filename, *args)
+ midQB = create_game_qb(QBSections, filename)
+ return midQB, midQS
+
+def add_perf_to_qb(midQB, filename, headerDict, qb_dict, *args):
+ midQB = convert_qb_file(qb_bytes(midQB), filename, headerDict, "PC")
+ for x in midQB:
+ if "_performance" in x.section_id and not "notes" in x.section_id:
+ if x.section_data == [0, 0]:
+ x.array_node_type = qb_dict["performance"].array_node_type
+ x.section_data = qb_dict["performance"].section_data
+ else:
+ x.section_data += qb_dict["performance"].section_data
+ cam_list = list(qb_dict["anim"]["CAMERAS"].keys())
+ sorted_section = {}
+ for y in x.section_data:
+ event_time = y.data_value[0].data_value
+ if re.search(r'Band_PlayLoop', y.data_value[1].data_value, flags=re.IGNORECASE):
+ closest_value = min(cam_list, key=lambda x: abs(y.data_value[0].data_value - x))
+ if event_time != closest_value and abs(event_time - closest_value) < 1000:
+ event_time = closest_value
+ y.data_value[0].data_value = event_time
+ if event_time in sorted_section:
+ sorted_section[event_time].append(y)
+ else:
+ sorted_section[event_time] = [y]
+ sorted_section = dict(sorted(sorted_section.items()))
+ new_perf = []
+ for z in sorted_section:
+ new_perf.extend(sorted_section[z])
+ x.section_data = new_perf
+ break
+ result = StringIO()
+ orig_stdout = sys.stdout
+ sys.stdout = result
+ print_qb_text_file(midQB)
+ sys.stdout = orig_stdout
+ qb_text = result.getvalue()
+ if "ghwt" in args:
+ game = "GHWT"
+ else:
+ game = "GH3"
+ midQB = t2q_main(qb_text, game=game)
+ return midQB
+
+def song_script_check(song_script_raw, filename):
+ song_script = ""
+ if not "qb_file = " in song_script_raw:
+ song_script = f"qb_file = songs/{filename}_song_scripts.qb\n"
+ if not "_song_startup = " in song_script_raw:
+ song_script += f'script {filename}_song_startup = "29 b6 24 06 00 00 00 09 00 00 00 09 01 16 f8 2d 15 1a 2c 01 24"\n'
+ song_script += song_script_raw
+ if not f"_anim_struct_{filename}" in song_script:
+ song_script = song_script.replace("anim_struct", f"anim_struct_{filename}")
+ song_script = t2q_main(song_script, game="GHWT")
+ return song_script
+
+def create_pak_file(midQB, filename, midQS = "", *args):
+ to_pak = [[midQB, f"songs\\{filename}.mid.qb"]]
+ if midQS:
+ to_pak.append([midQS, f"songs\\{filename}.mid.qs"])
+ if "song_script" in args:
+ song_script_file = args[args.index("song_script") + 1]
+ if os.path.exists(song_script_file):
if song_script_file.endswith(".txt"):
- song_script = ""
with open(song_script_file, "r") as f:
- song_script_raw = f.read()
- if not "qb_file = " in song_script_raw:
- song_script = f"qb_file = songs/{filename}_song_scripts.qb\n"
- if not "_song_startup = " in song_script_raw:
- song_script += f'script {filename}_song_startup = "29 b6 24 06 00 00 00 09 00 00 00 09 01 16 f8 2d 15 1a 2c 01 24"\n'
- song_script += song_script_raw
- if not f"_anim_struct_{filename}" in song_script:
- song_script = song_script.replace("anim_struct", f"anim_struct_{filename}")
- song_script = t2q_main(song_script, game = "GHWT")
+ song_script = song_script_check(f.read(), filename)
else:
with open(song_script_file, "rb") as f:
song_script = f.read()
- to_pak.append([song_script, f"songs\\{filename}_song_scripts.qb"])
- pakFile = pakMaker(to_pak)
+ else:
+ try:
+ song_script = song_script_check(song_script_file, filename)
+ except Exception as e:
+ raise e
+ to_pak.append([song_script, f"songs\\{filename}_song_scripts.qb"])
+ if "add_ska" in args:
+ ska_files = args[args.index("add_ska") + 1]
+ if type(ska_files) == list:
+ to_pak.extend(ska_files)
+ elif os.path.exists(ska_files):
+ for files in os.listdir(ska_files):
+ with open(f"{args[args.index('add_ska') + 1]}\\{files}", 'rb') as f:
+ ska_file = f.read()
+ if "gh3" in args:
+ ska_file = ska_bytes(ska_file)
+ ska_file = make_modern_ska(ska_file)
+ ska_file = ska_bytes(ska_file)
+ if "gha" in args:
+ to_ska = "gha_singer"
+ else:
+ to_ska = "gh3_singer"
+ ska_file = make_gh3_ska(ska_file, quats_mult=0.5, ska_switch=to_ska)
+ to_pak.append([ska_file, files])
- return pakFile, filename
+ else:
+ raise Exception("Could not find SKA files.")
+ if "add_loops" in args:
+ for file in args[args.index("add_loops") + 1]:
+ with open(f"{root_folder}\\..\\conversion_files\\anim_loops_wt\\{file}.ska.xen", 'rb') as f:
+ to_pak.append([f.read(), f"{file}.ska"])
+ pakFile = pakMaker(to_pak)
+ return pakFile
+
+def override_perf(filename, headerDict, qb_dict, game, *args):
+ perf_file = args[args.index("replace_perf") + 1]
+ if os.path.isfile(perf_file):
+ if perf_file.endswith(".txt"):
+ with open(perf_file, "r") as f:
+ perf_qb = f.read().replace("song_performance", f"{filename}_performance")
+ if "qb_file = " not in perf_qb:
+ perf_qb = f"qb_file = songs/{filename}.mid.qb\n" + perf_qb
+ perf_qb = t2q_main(perf_qb, game=game)
+ else:
+ with open(perf_file, "rb") as f:
+ perf_qb = f.read()
+ else:
+ try:
+ perf_qb = perf_file.replace("song_performance", f"{filename}_performance")
+ if "qb_file = " not in perf_qb:
+ perf_qb = f"qb_file = songs/{filename}.mid.qb\n" + perf_qb
+ perf_qb = t2q_main(perf_qb, game=game)
+ except Exception as e:
+ raise e
+ qb_sections = convert_qb_file(qb_bytes(perf_qb), filename, headerDict,
+ "PC")
+ for x in qb_sections:
+ if "_performance" in x.section_id and not "notes" in x.section_id:
+ qb_dict["performance"] = x
+ break
if __name__ == "__main__":
consoleType = 1 # 0 for Wii, 1 for PC, 2 for 360, 3 for XBX, 4 for PS2, 5 for WPC
diff --git a/midqb_gen/midqb_classes.py b/midqb_gen/midqb_classes.py
index 536b0ad..25049a5 100644
--- a/midqb_gen/midqb_classes.py
+++ b/midqb_gen/midqb_classes.py
@@ -100,20 +100,22 @@ def __init__(self, time, prevNote, currTempChange, colour):
setattr(self, colour, 1)
class NoteChart:
- def __init__(self, part, diff):
+ def __init__(self, part, diff, gh3 = False):
self.part = part
self.diff = diff
self.notes = []
+ self.gh3 = gh3
def __str__(self):
- return f"Part {self.part if self.part != '' else 'Guitar'}, {self.diff}, {int(len(self.notes)/2)} in chart"
+ divisor = 3 if self.gh3 else 2
+ return f"Part {self.part if self.part != '' else 'Guitar'}, {self.diff}, {int(len(self.notes)/divisor)} in chart"
class AnimNote:
- def __init__(self, time, note):
+ def __init__(self, time, note, length = 1):
self.time = time
self.note = note
- self.length = 1
+ self.length = length
def __str__(self):
return f"Anim note {self.note} at {self.time} lasting {self.length}"
diff --git a/midqb_gen/midqb_definitions.py b/midqb_gen/midqb_definitions.py
index cf20c3f..4bbad31 100644
--- a/midqb_gen/midqb_definitions.py
+++ b/midqb_gen/midqb_definitions.py
@@ -55,6 +55,12 @@
percussion_start = ["[clap_start]", "[cowbell_start]", "[tambourine_start]"]
percussion_end = ["[clap_end]", "[cowbell_end]", "[tambourine_end]"]
+singer_stances = ["Stance_A", "Stance_B"]
+singer_anims = ["special", "jump", "kick", "release", "long_note"]
+guit_stances = singer_stances + ["Stance_C"]
+guit_anims = ["jump", "kick", "solo", "special"]
+gha_guit_stances = guit_stances + ["Stance_D"]
+
venue_states = ["[verse]", "[chorus]", "[solo]"]
valid_camera_notes_gh3 = [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
@@ -67,27 +73,31 @@
valid_camera_notes_wt = [0, 1, 3, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16, 18, 19, 20, 21, 23, 24, 25, 26, 28, 29, 30, 31,
33, 34, 35, 36, 38, 40, 41, 43, 45, 46, 48]
-valid_camera_notes_wor = [50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 74, 75, 90, 91,
+valid_camera_notes_wor = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99]
-valid_camera_notes_wtde = [50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 74, 75, 81,
+moment_cams = [3, 4, 5, 6, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
+
+valid_camera_notes_wtde = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 81,
82, 83, 84, 85, 86, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107,
108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126]
valid_lightshow_notes_gh3 = [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 56, 57, 58, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76]
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 107]
valid_lightshow_notes_wt = [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 87, 88, 90, 91, 92, 93, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105]
+ 98, 99, 100, 101, 102, 103, 104, 105, 107]
-valid_lightshow_notes_wor = [19, 107]
+valid_lightshow_notes_wor = [19]
valid_crowd_gh3 = [72, 73, 74, 75, 76, 77, 78, 79, 80]
valid_crowd_wt = [82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96]
+venue_track = "LIGHTSHOWCAMERASCROWD"
+
gh5_camera_dict = { # This dict is to grab camera cuts to add to a gh5-style perf file
33: 8,
34: 13,
@@ -96,7 +106,8 @@
}
anims_guitar = [] # MIDI Note 127-118 is Lead left hand anims, 110-101 is Bass/Rhythm left hand notes
-stances = ["Stance_A", "Stance_B", "Stance_C", "jump", "special", "Solo", "kick"]
+
+
drumKeyMapGH3 = { # More FYI, but may use this dict in later code
36: "Kick_R", # Budokan and Hell venues only
37: "Tom_3_L",
@@ -144,12 +155,13 @@
34: 44,
32: 50,
31: 53,
- 30: 41,
+ 30: 42,
29: 52,
28: 40,
27: 52,
26: 40,
24: 48,
+ 23: 36,
22: 70
}
@@ -221,33 +233,35 @@
59: 97,
58: 102,
57: 101,
- 48: 79,
+ 48: 87,
46: 113,
- 45: 112,
- 43: 79,
+ 45: 111,
+ 43: 91,
38: 79,
+ 36: 97,
+ 35: 89,
34: 104,
- 33: 90,
- 31: 79,
+ 33: 81,
+ 31: 87,
30: 85,
29: 94,
28: 114,
- 26: 105,
- 25: 105,
+ 26: 89,
+ 25: 89,
24: 87,
23: 89,
- 21: 105,
- 20: 105,
+ 21: 97,
+ 20: 97,
19: 110,
18: 97,
16: 88,
- 15: 101,
+ 15: 88,
14: 103,
13: 104,
- 11: 105,
- 10: 106,
+ 11: 79,
+ 10: 79,
9: 87,
- 8: 95,
+ 8: 95
},
"gha": {
@@ -324,6 +338,12 @@
59: 84
}
+anim_maps_gh3 = {
+ "Guitar": leftHandGtr_gh3,
+ "Bass": leftHandBass_gh3,
+ "Rhythm": leftHandMappingRhythm
+}
+
note_mapping_gh3 = {
60: 'Easy_green',
61: 'Easy_red',
@@ -531,7 +551,7 @@
sp_note = 116
fo_star_note = 107
-playable_range = range(36, 85)
+playable_range = [26] + list(range(36, 85))
phrase_marker = [105, 106]
freeform_marker = tap_note
diff --git a/midqb_gen/midqb_functions.py b/midqb_gen/midqb_functions.py
index ccb7289..87bac0c 100644
--- a/midqb_gen/midqb_functions.py
+++ b/midqb_gen/midqb_functions.py
@@ -12,7 +12,7 @@
sys.path.append("..\\pak_extract")
from pak_extract.Text2QB import basic_data, struct_data, assign_data, assign_types, create_qb
-from pak_extract.pak_functions import make_script_struct, round_time, round_cam_len
+from pak_extract.pak_functions import make_script_struct, round_time, round_cam_len, new_stance_gh3
sys.path.append("..\\")
import CRC
@@ -32,9 +32,8 @@ def create_wt_qb_sections(qb_dict, filename, *args):
if "wtde" in args:
parsing.append(qb_dict["solo_markers"])
-
-
- qb_sections[f"{filename}_timesig"] = basic_data(f"{filename}_timesig", [[x.time, x.numerator, x.denominator] for x in qb_dict["timesigs"]])
+ qb_sections[f"{filename}_timesig"] = basic_data(f"{filename}_timesig",
+ [[x.time, x.numerator, x.denominator] for x in qb_dict["timesigs"]])
qb_sections[f"{filename}_fretbars"] = basic_data(f"{filename}_fretbars", qb_dict["fretbars"])
no_diff = ["tap", "fo_star_note", "face_off"]
@@ -134,7 +133,7 @@ def create_wt_qb_sections(qb_dict, filename, *args):
bin_len = bin(anim_stuff.length)[2:].zfill(16)
bin_mid_note = bin(anim_stuff.note)[2:].zfill(8)
bin_velocity = bin(anim_stuff.velocity)[2:].zfill(8)
- note_val = int(bin_velocity+bin_mid_note+bin_len, 2)
+ note_val = int(bin_velocity + bin_mid_note + bin_len, 2)
anim_list.append(timing)
anim_list.append(note_val)
qb_sections[chart_name] = basic_data(chart_name, anim_list.copy())
@@ -145,7 +144,7 @@ def create_wt_qb_sections(qb_dict, filename, *args):
qb_sections[chart_name] = basic_data(chart_name, anim_list)
else:
qb_sections[chart_name] = basic_data(chart_name, [])
- #"performance",
+ # "performance",
for temp in ["song_vocals", "vocals_freeform", "vocals_phrases", "vocals_note_range", "lyrics", "vocals_markers"]:
chart_name = f"{filename}_{temp}"
try:
@@ -170,6 +169,9 @@ def create_wt_qb_sections(qb_dict, filename, *args):
if "wor" in args and qb_dict["ghost_notes"]:
chart_name = f"{filename}_ghost_notes"
qb_sections[chart_name] = basic_data(chart_name, qb_dict["ghost_notes"])
+ if "wtde" in args and qb_dict["xplus"]:
+ chart_name = f"{filename}_song_drums_expertplus"
+ qb_sections[chart_name] = basic_data(chart_name, qb_dict["xplus"].notes)
if qb_dict["has_2x_kick"]:
chart_name = f"{filename}_double_kick"
@@ -185,10 +187,13 @@ def create_wt_qb_sections(qb_dict, filename, *args):
return qb_sections, qs_file
-def create_wt_qb(qb_sections, filename):
- qb_list = [value for key, value in qb_sections.items()]
- assign_types(qb_list, game="GHWT")
- qb_file = create_qb(qb_list, "Section", f"songs/{filename}.mid.qb", game = "GHWT")
+def create_game_qb(qb_sections, filename, game="GHWT"):
+ if type(qb_sections) == dict:
+ qb_list = [value for key, value in qb_sections.items()]
+ else:
+ qb_list = qb_sections
+ assign_types(qb_list, game=game)
+ qb_file = create_qb(qb_list, "Section", f"songs/{filename}.mid.qb", game=game)
return qb_file
@@ -281,11 +286,15 @@ def mod_notes(time_array, compare):
return np.where((time_array >= compare[0]) & (time_array < compare[1]))
-def make_bin_notes(gem):
+def set_gems(gem):
notes_bin = 0
for temp_colour in gem["colours"]:
notes_bin += 1 << temp_colour
+ return notes_bin
+
+def make_bin_notes(gem):
+ notes_bin = set_gems(gem)
return bin(notes_bin)[2:].zfill(7)
@@ -316,7 +325,8 @@ def parse_fretbars(timeSigs, end_event_ticks, changes, ticksArray, mid):
return fretbars
-def active_note_check(x, active_notes, timeSec, midi_track, track): # midi_track is usually anim_notes
+
+def active_note_check(x, active_notes, timeSec, midi_track, track): # midi_track is usually anim_notes
if x.velocity != 0:
if x.note in active_notes:
return -1
@@ -335,13 +345,59 @@ def active_note_check(x, active_notes, timeSec, midi_track, track): # midi_track
raise Exception(f"Something went wrong parsing the {track.name} track.")
return 0
+
+def create_diff_dicts():
+ play_notes = {
+ "Easy": [],
+ "Medium": [],
+ "Hard": [],
+ "Expert": []
+ }
+
+ active_notes = {
+ "Easy": {},
+ "Medium": {},
+ "Hard": {},
+ "Expert": {}
+ }
+ forced_notes = {
+ "Easy": {"off": [], "on": []},
+ "Medium": {"off": [], "on": []},
+ "Hard": {"off": [], "on": []},
+ "Expert": {"off": [], "on": []}
+ }
+ play_face_off = {"P1": [], "P2": []}
+ play_star = {
+ "Easy": [],
+ "Medium": [],
+ "Hard": [],
+ "Expert": []
+ }
+ play_star_bm = {
+ "Easy": [],
+ "Medium": [],
+ "Hard": [],
+ "Expert": []
+ }
+ play_star_fo = {
+ "Easy": [],
+ "Medium": [],
+ "Hard": [],
+ "Expert": []
+ }
+ return play_notes, active_notes, forced_notes, play_face_off, play_star, play_star_bm, play_star_fo
+
+
+def split_list(l_in):
+ return [l_in[i:i + 2] for i in range(0, len(l_in), 2)]
+
+
def parse_wt_qb(mid, hopo, *args, **kwargs):
changes, ticks = tempMap(mid)
if "force_only" in args:
time_hopos = False
else:
time_hopos = True
- split_list = lambda l_in: [l_in[i:i + 2] for i in range(0, len(l_in), 2)]
global sp_note
if "star_power" in kwargs:
@@ -356,6 +412,8 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
ticksArray = np.array(ticks)
changesArray = np.array(changes)
+ xplus_chart = False
+ make_xplus = False
ghost_notes = {}
has_2x_kick = False
@@ -433,14 +491,6 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
valid_anims["LIGHTSHOW"].extend(valid_lightshow_notes_wor)
valid_anims["CAMERAS"].extend(valid_camera_notes_wtde)
-
- venue_track = "LIGHTSHOWCAMERASCROWD"
-
- leftHandAnims = {
- "Guitar": [],
- "Bass": []
- }
-
anim_notes = {
"scripts_notes": {},
"left_hand": {},
@@ -459,8 +509,6 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
"performance": []
}
-
-
fo_star_power = {
"Guitar": [],
"Bass": [],
@@ -484,9 +532,10 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
vocals_freeform = {
0: [],
1: []
- } # 0 is freeform, 1 is hype
+ } # 0 is freeform, 1 is hype
vocals_freeform_playable = []
- vocals_phrases = {105: [], 106: []} # 105 is star power, 106 is bm star power# Type 0 is blank, playable phrases alternate between 1 and 2
+ vocals_phrases = {105: [],
+ 106: []} # 105 is star power, 106 is bm star power# Type 0 is blank, playable phrases alternate between 1 and 2
vocals_phrase_dict = {0: {}}
# 3 exists too. Maybe to do with face-off?
vocals_lyrics = {}
@@ -518,50 +567,18 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
drums = False
elif re.search(r'(drums)', instrument, flags=re.IGNORECASE):
inst_map = note_mapping_gh3 | forceMapping | note_mapping_wt_drum
+ if "2x_check" in args:
+ inst_map.pop(96)
+ inst_map[95] = 'Expert_purple'
+ xplus_chart = True
+
drums = True
else:
inst_map = note_mapping_gh3 | forceMapping | note_mapping_wt_drum
drums = False
- play_vox = []
+ play_notes, active_notes, forced_notes, play_face_off, play_star, play_star_bm, play_star_fo = create_diff_dicts()
- play_notes = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
- active_notes = {
- "Easy": {},
- "Medium": {},
- "Hard": {},
- "Expert": {}
- }
- forced_notes = {
- "Easy": {"off": [], "on": []},
- "Medium": {"off": [], "on": []},
- "Hard": {"off": [], "on": []},
- "Expert": {"off": [], "on": []}
- }
- play_face_off = {"P1": [], "P2": []}
- play_star = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
- play_star_bm = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
- play_star_fo = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
play_tap = []
play_solo = []
@@ -581,27 +598,32 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
for y, x in enumerate(track):
time += x.time
currChange = changes[len(ticksArray[ticksArray <= time]) - 1] # time, tempo, avgTempo
- timeSec = timeInSecs(currChange, mid, time)
+ time_sec = timeInSecs(currChange, mid, time)
if track_num == 0:
if x.type == "time_signature":
- timeSigs.append(timeSigEvent(timeSec, x.numerator, x.denominator))
+ timeSigs.append(timeSigEvent(time_sec, x.numerator, x.denominator))
elif track.name == "EVENTS":
if x.type == 'text':
- end_event_secs, end_event_ticks = process_text_event(x, markers, time, timeSec)
+ end_event_secs, end_event_ticks = process_text_event(x, markers, time, time_sec)
if end_event_secs and end_event_ticks:
continue
- elif re.search(track.name, venue_track, flags=re.IGNORECASE):
- track.name = track.name.upper()
+ elif re.search(track.name, rf'{venue_track}|cameras_wt', flags=re.IGNORECASE):
+ if track.name == "cameras_wt":
+ track.name = "CAMERAS"
+ else:
+ track.name = track.name.upper()
valid_check = valid_anims[track.name]
if x.type == "note_on" or x.type == "note_off":
if x.note in valid_check:
- if x.velocity != 0:
+ create_anim_note(x, active_notes, track.name, anim_notes, time_sec,
+ AnimNoteWT(time_sec, x.note, x.velocity))
+ '''if x.velocity != 0:
if x.note in active_notes:
continue
- active_notes[x.note] = AnimNoteWT(timeSec, x.note, x.velocity)
+ active_notes[x.note] = AnimNoteWT(time_sec, x.note, x.velocity)
else:
try:
- active_notes[x.note].setLength(timeSec - active_notes[x.note].time)
+ active_notes[x.note].setLength(time_sec - active_notes[x.note].time)
if active_notes[x.note].time in anim_notes[track.name]:
anim_notes[track.name][active_notes[x.note].time].append(active_notes[x.note])
else:
@@ -610,21 +632,22 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
except KeyError:
pass
except:
- raise Exception(f"Something went wrong parsing the {track.name} track.")
+ raise Exception(f"Something went wrong parsing the {track.name} track.")'''
elif x.type == "text":
if re.search(r'^(SetBlendTime|LightShow_Set)', x.text, flags=re.IGNORECASE):
- # if x.text.startswith("SetBlendTime") or x.text.startswith("LightShow_Set"):
- blendtime = {"param": "time", "data": float(x.text.split(" ")[1]), "type": "Float"} # Blend time is in seconds
- anim_notes["lightshow"].append(scriptsNode(timeSec, "LightShow_SetTime", [blendtime]))
- elif re.search(r'(zoom_(in|out)_(quick|slow)_(small|large)|pulse[1-5]) [0-9]+', x.text, flags = re.IGNORECASE):
+ # if x.text.startswith("SetBlendTime") or x.text.startswith("LightShow_Set"):
+ blendtime = lightshow_script(x)
+ anim_notes["lightshow"].append(scriptsNode(time_sec, "LightShow_SetTime", [blendtime]))
+ elif re.search(r'(zoom_(in|out)_(quick|slow)_(small|large)|pulse[1-5]) [0-9]+', x.text,
+ flags=re.IGNORECASE):
zoom_type = x.text.split(" ")[0]
zoom_length = float(x.text.split(" ")[1])
if zoom_length.is_integer():
zoom_length = int(zoom_length)
- param_type = {"param": "type", "data": zoom_type, "type": "QbKey"}
- param_time = {"param": "time", "data": zoom_length, "type": "Integer" if type(zoom_length) == int else "Float"}
- anim_notes["performance"].append(scriptsNode(timeSec, "CameraCutsEffect_FOVPulse", [param_type, param_time]))
+ param_type, param_time = camera_script(zoom_type, zoom_length)
+ anim_notes["performance"].append(
+ scriptsNode(time_sec, "CameraCutsEffect_FOVPulse", [param_type, param_time]))
elif playable:
if re.search(r'(guitar|bass|drums)', instrument, flags=re.IGNORECASE):
if x.type == "note_on" or x.type == "note_off":
@@ -632,7 +655,7 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
chart_diff = inst_map[x.note].split("_")[0]
note_colour = inst_map[x.note].split("_")[1]
if note_colour not in ["off", "on"]:
- to_add = {"time_sec": timeSec, "time_tick": time, "curr_change": currChange,
+ to_add = {"time_sec": time_sec, "time_tick": time, "curr_change": currChange,
"velocity": x.velocity}
if note_colour in active_notes[chart_diff]:
temp = active_notes[chart_diff]
@@ -641,35 +664,34 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
active_notes[chart_diff][note_colour] = [to_add]
if all([drums, x.note >= 97, x.velocity == 1]):
ghost = (1 << note_bit_vals[note_colour])
- if timeSec in ghost_notes:
- if not ghost & ghost_notes[timeSec]:
- ghost_notes[timeSec] += ghost
+ if time_sec in ghost_notes:
+ if not ghost & ghost_notes[time_sec]:
+ ghost_notes[time_sec] += ghost
else:
- ghost_notes[timeSec] = ghost
-
+ ghost_notes[time_sec] = ghost
else:
- forced_notes[chart_diff][note_colour].append(timeSec)
+ forced_notes[chart_diff][note_colour].append(time_sec)
elif x.note == sp_note:
- star_power[instrument].append(timeSec)
+ star_power[instrument].append(time_sec)
elif x.note == bm_star_note:
- bm_star_power[instrument].append(timeSec)
+ bm_star_power[instrument].append(time_sec)
elif x.note == fo_star_note:
- fo_star_power[instrument].append(timeSec)
+ fo_star_power[instrument].append(time_sec)
elif x.note in faceOffMapping:
- play_face_off[faceOffMapping[x.note]].append(timeSec)
+ play_face_off[faceOffMapping[x.note]].append(time_sec)
elif x.note == tap_note:
- play_tap.append(timeSec)
+ play_tap.append(time_sec)
elif x.note == solo_note:
- play_solo.append(timeSec)
+ play_solo.append(time_sec)
elif x.note in leftHandGtr_wt and not drums:
new_note = anim_maps[instrument][x.note]
- if x.velocity != 0:
+ if x.velocity != 0 and x.type == "note_on":
if new_note in active_notes:
continue
- active_notes[new_note] = AnimNoteWT(timeSec, new_note, x.velocity)
+ active_notes[new_note] = AnimNoteWT(time_sec, new_note, x.velocity)
else:
try:
- active_notes[new_note].setLength(timeSec - active_notes[new_note].time)
+ active_notes[new_note].setLength(time_sec - active_notes[new_note].time)
if active_notes[new_note].time in anim_notes["left_hand"]:
anim_notes["left_hand"][active_notes[new_note].time].append(
active_notes[new_note])
@@ -687,10 +709,11 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
if x.velocity != 0 and x.type == "note_on":
if new_note in active_notes:
continue
- active_notes[new_note] = AnimNoteWT(timeSec, new_note, x.velocity)
+ active_notes[new_note] = AnimNoteWT(time_sec, new_note, x.velocity)
else:
try:
- new_len = timeSec - active_notes[new_note].time
+ drum_anim_note(x, active_notes, new_note, anim_notes, time_sec, args)
+ '''new_len = time_sec - active_notes[new_note].time
active_notes[new_note].setLength(new_len)
if active_notes[new_note].time in anim_notes["drum_anims"]:
anim_notes["drum_anims"][active_notes[new_note].time].append(
@@ -708,10 +731,10 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
active_notes.pop(new_note)
continue
else:
- practice_note = new_note-13
- temp.append(AnimNoteWT(timeSec, practice_note, temp[-1].velocity))
+ practice_note = new_note - 13
+ temp.append(AnimNoteWT(time_sec, practice_note, temp[-1].velocity))
temp[-1].setLength(new_len)
- active_notes.pop(new_note)
+ active_notes.pop(new_note)'''
except KeyError as E:
# raise E
pass
@@ -720,125 +743,60 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
raise Exception(f"Something went wrong parsing the {track.name} track.")
elif x.note == 25 and drums:
- open_hh.append(timeSec)
+ open_hh.append(time_sec)
+ if all([x.note == 95, drums, "wtde" in args, not make_xplus]):
+ make_xplus = True
# if x.note in faceOffMapping:
elif x.type == "sysex":
sys_head = x.data[:3]
if not sys_head == (80, 83, 0):
continue
if x.data[5] == 4 and x.data[4] in [3, 127]:
- sysex_taps.append(timeSec)
+ sysex_taps.append(time_sec)
elif x.data[5] == 1 and x.data[4] != 127:
try:
- sysex_opens[x.data[4]].append(timeSec)
+ sysex_opens[x.data[4]].append(time_sec)
if not sysex_opens_check:
sysex_opens_check = 1
except:
- print(f"{track.name}: Invalid SysEx event found at {timeSec}")
+ print(f"{track.name}: Invalid SysEx event found at {time_sec}")
# print()
- else: # vocals. Note range 36-84 inclusive probably
+ else: # vocals. Note range 36-84 inclusive probably
if x.type == "lyrics":
- vocals_lyrics[timeSec] = x.text
+ vocals_lyrics[time_sec] = x.text
elif x.type == "text":
if "[" not in x.text:
- vocals_lyrics[timeSec] = x.text
+ vocals_lyrics[time_sec] = x.text
elif x.type == "note_on" or x.type == "note_off":
if x.note in playable_range:
if x.note in vocals_notes:
- vocals_notes[x.note].append(timeSec)
+ vocals_notes[x.note].append(time_sec)
else:
- vocals_notes[x.note] = [timeSec]
+ vocals_notes[x.note] = [time_sec]
elif x.note in phrase_marker:
- vocals_phrases[x.note].append(timeSec)
+ vocals_phrases[x.note].append(time_sec)
elif x.note == freeform_marker:
- vocals_freeform[x.channel].append(timeSec)
+ vocals_freeform[x.channel].append(time_sec)
elif x.note == sp_note:
- vocal_sp.append(timeSec)
-
+ vocal_sp.append(time_sec)
if time > last_event_tick:
last_event_tick = time
- last_event_secs = timeSec
+ last_event_secs = time_sec
if playable and not re.search(r'(vocal)', instrument, flags=re.IGNORECASE):
if sysex_taps and not play_tap:
play_tap = sysex_taps
star_power[instrument] = split_list(star_power[instrument])
bm_star_power[instrument] = split_list(bm_star_power[instrument])
fo_star_power[instrument] = split_list(fo_star_power[instrument])
- time_array_diffs = {
- }
for player, fo in play_face_off.items():
if fo:
play_face_off[player] = split_list(fo)
for diff, notes in active_notes.items():
- timestamps = {}
- for colour, times in notes.items():
- if colour == "2x":
- continue
- note_bit = note_bit_vals[colour]
- colour_time = []
- for count, playtime in enumerate(times):
- if count % 2 == 0:
- colour_time.append(playtime)
- else:
- if colour_time[-1]["time_sec"] in timestamps:
- s_time = colour_time[-1]["time_sec"]
- test_colour = timestamps[s_time]
- t_time = colour_time[-1]["time_tick"]
- test_colour["colours"].append(note_bit)
- test_colour["colour_name"].append(colour)
- temp_len = playtime["time_sec"] - s_time
- temp_other_len = test_colour["length_sec"]
- if drums:
- if colour_time[-1]["velocity"] == 127:
- timestamps[s_time]["accents"].append(note_bit)
- if temp_len != test_colour["length_sec"]:
- if colour == "purple":
- test_colour["length_sec_kick"] = temp_len
- elif 5 in test_colour["colours"]:
- test_colour["length_sec_kick"] = test_colour["length_sec"]
- test_colour["length_sec"] = temp_len
- else:
- temp_len_t = playtime["time_tick"] - t_time
- other_temp_t = timestamps[s_time]["length_tick"]
- timestamps[s_time]["length_sec"] = min(temp_len, temp_other_len)
- timestamps[s_time]["length_tick"] = min(temp_len_t, other_temp_t)
- del temp_len
- del temp_other_len
- del temp_len_t
- del other_temp_t
- else:
- if temp_len != timestamps[s_time]["length_sec"]:
- temp_len_t = playtime["time_tick"] - t_time
- other_temp_t = timestamps[s_time]["length_tick"]
- timestamps[s_time]["length_sec"] = min(temp_len, temp_other_len)
- timestamps[s_time]["length_tick"] = min(temp_len_t, other_temp_t)
- del temp_len
- del temp_other_len
- del temp_len_t
- del other_temp_t
- else:
- s_time = colour_time[-1]["time_sec"]
- t_time = colour_time[-1]["time_tick"]
- len_sec = playtime["time_sec"] - s_time
- if len_sec < 10:
- len_sec = 10
- len_tick = playtime["time_tick"] - t_time
- if not drums:
- timestamps[s_time] = {"colours": [note_bit], "colour_name": [colour],
- "length_sec": len_sec,
- "length_tick": playtime["time_tick"] - t_time,
- "extended": []} | colour_time[-1]
- else:
- timestamps[s_time] = {"colours": [note_bit], "colour_name": [colour],
- "length_sec": len_sec,
- "length_tick": len_tick,
- "accents": [], "length_sec_kick": 0} | colour_time[-1]
- if colour_time[-1]["velocity"] == 127:
- timestamps[s_time]["accents"].append(note_bit)
- # colour_time[-1]["length"] = playtime - colour_time[-1]["time"]
+ timestamps = create_playable_notes(notes, drums)
+ # colour_time[-1]["length"] = playtime - colour_time[-1]["time"]
if all([drums, "2x_kick" in args, diff == "Expert", "2x" in notes]):
has_2x_kick = True
d_kick_list = []
@@ -851,7 +809,9 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
if x["time_sec"] in timestamps:
timestamps[x["time_sec"]]["2x_kick"] = 1
else:
- timestamps[x["time_sec"]] = {"colours": [], "colour_name": [], "2x_kick": 1, "length_sec": x["length_sec"], "velocity": x["velocity"], "accents": [], "length_sec_kick": 0}
+ timestamps[x["time_sec"]] = {"colours": [], "colour_name": [], "2x_kick": 1,
+ "length_sec": x["length_sec"], "velocity": x["velocity"],
+ "accents": [], "length_sec_kick": 0}
timestamps = dict(sorted(timestamps.items()))
if drums and diff == "Expert":
drum_notes = dict(sorted(timestamps.items()))
@@ -894,21 +854,18 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
curr_in["extended"].extend(
q for q in extended if q not in curr_in["extended"] + curr_in["colours"])
# print()
-
+ curr_colours = "".join(sorted(gem["colour_name"]))
# Set hopos
if not prev_time == 0:
- curr_colours = "".join(sorted(gem["colour_name"]))
if all([gem["time_tick"] - prev_time <= hopo, len(gem["colours"]) == 1,
prev_colours != curr_colours, time_hopos]):
gem["colours"].append(6)
if "rb_mode" in args:
if curr_colours in prev_colours:
gem["colours"].remove(6)
- prev_time = gem["time_tick"]
- prev_colours = curr_colours
- else:
- prev_time = gem["time_tick"]
- prev_colours = "".join(sorted(gem["colour_name"]))
+
+ prev_time = gem["time_tick"]
+ prev_colours = curr_colours
force_on = forced_notes[diff]["on"]
if force_on:
force_on = split_list(force_on)
@@ -930,7 +887,7 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
else:
timestamps[time_array[index]]["colours"].append(6)
# print()
- force_off = forced_notes[diff]["off"]
+ force_off = forced_notes[diff]["off"] if not "gh3_mode" in args else 0
if force_off:
force_off = split_list(force_off)
for forced in force_off:
@@ -950,48 +907,10 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
playable_face_off[instrument] = play_face_off.copy()
play_notes[diff] = NoteChart(instrument, diff)
- for enum, gem in timestamps.items():
- play_notes[diff].notes.append(enum)
- len_bin = bin(gem["length_sec"])[2:].zfill(16)
- if not drums:
- mod_bin = "11111"
- if gem["extended"]:
- mod_bin = int(mod_bin, 2)
- for mod in gem["extended"]:
- mod_bin -= 1 << mod
- mod_bin = bin(mod_bin)[2:]
- elif gem["accents"]:
- mod_bin = int("11111", 2)
- for mod in gem["colours"]:
- if mod not in gem["accents"] and mod < 5:
- mod_bin -= 1 << mod
- mod_bin = bin(mod_bin)[2:]
- else:
- mod_bin = "00000"
-
- if drums and "2x_kick" in gem:
- double_bits = "0010"
- mod_bin = double_bits + mod_bin
- mod_bin = mod_bin.zfill(9)
- sep_kick = 0
- if not drums:
- notes_bin = make_bin_notes(gem)
- elif gem["length_sec_kick"]:
- gem["colours"].remove(5)
- notes_bin = make_bin_notes(gem)
- kick_note = make_bin_notes({"colours": [5]})
- len_bin_kick = bin(gem["length_sec_kick"])[2:].zfill(16)
- sep_kick = int(mod_bin + kick_note + len_bin_kick, 2)
- mod_bin = "0000" + mod_bin[4:]
- else:
- notes_bin = make_bin_notes(gem)
+ if "ghwt" in args:
+ make_wt_bin_notes(timestamps, play_notes, diff, drums)
- note_val = mod_bin + notes_bin + len_bin
- play_notes[diff].notes.append(int(note_val, 2))
- if sep_kick:
- play_notes[diff].notes.append(enum)
- play_notes[diff].notes.append(sep_kick)
playable_qb[instrument] = play_notes.copy()
playable_star_power[instrument] = play_star.copy()
playable_fo_star_power[instrument] = play_star_fo.copy()
@@ -1008,12 +927,13 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
curr_taps = []
if not np.any(all_taps):
print("No notes found under any tap note on Expert track.")
- no_tap_notes = input("Type 'Continue' to compile without taps, or press enter to cancel compilation: ")
+ no_tap_notes = input(
+ "Type 'Continue' to compile without taps, or press enter to cancel compilation: ")
if not no_tap_notes.lower() == "continue":
raise Exception("Cancelled compilation by user")
else:
- break
- for note_check in list(timestamps.values())[all_taps[0]:all_taps[-1]+1]:
+ break
+ for note_check in list(timestamps.values())[all_taps[0]:all_taps[-1] + 1]:
if len(note_check['colour_name']) > 1:
if curr_taps:
curr_taps.append(note_check["time_sec"])
@@ -1086,12 +1006,12 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
t_diff = next_key - current_key
if t_diff > phrase_dist: # difference is greater than 5 seconds
num_keys_to_add = ceil(t_diff / phrase_dist) # number of keys to add
- interval = t_diff // num_keys_to_add # interval between new keys
+ interval = t_diff // num_keys_to_add # interval between new keys
for j in range(0, num_keys_to_add):
new_key = current_key + j * (interval + 1)
- master_phrases[new_key] = [new_key, next_key-1]
+ master_phrases[new_key] = [new_key, next_key - 1]
master_phrases[values[-1][1]] = [values[-1][1], values[-1][1]]
- master_phrases[timeSec] = [timeSec, timeSec]
+ master_phrases[time_sec] = [time_sec, time_sec]
master_phrases = dict(sorted(master_phrases.items()))
vocals_phrases = [phrase for phrase in master_phrases.values()]
lyrics_array = np.array(list(vocals_lyrics.keys()))
@@ -1119,7 +1039,7 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
f_split = split_list(freeform)
for f2 in f_split:
f_len = f2[1] - f2[0]
- f_unk = 0 if f_type == 1 else f_len//6
+ f_unk = 0 if f_type == 1 else f_len // 6
if f2[0] in vocals_phrase_dict:
vocals_phrase_dict[f2[0]] = {"freeform_marker": "freeform" if f_type == 0 else "hype"}
vocals_freeform_playable.append([f2[0], f_len, f_unk])
@@ -1127,11 +1047,12 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
for key in list(vocals_phrase_dict.keys())[::-1]:
if key <= f2[0]:
if not vocals_phrase_dict[key]:
- vocals_phrase_dict[key]= {"freeform_marker": "freeform" if f_type == 0 else "hype"}
+ vocals_phrase_dict[key] = {"freeform_marker": "freeform" if f_type == 0 else "hype"}
vocals_freeform_playable.append([key, f_len, f_unk])
break
else:
- print(f"Freeform marker at {f2[0]} does not coincide with a free phrase marker. Skipping...")
+ print(
+ f"Freeform marker at {f2[0]} does not coincide with a free phrase marker. Skipping...")
playable_freeform_dict = {}
for t in vocals_freeform_playable:
playable_freeform_dict[t[0]] = t
@@ -1181,12 +1102,34 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
if "text" in v_note:
playable_vocals["vocals_markers"].append(markerNode(t, f"qbs(0x{CRC.QBKey_qs(v_note['text'])})"))
elif "freeform_marker" in v_note:
- playable_vocals["vocals_markers"].append(markerNode(t, f"$vocal_marker_{v_note['freeform_marker']}"))
+ playable_vocals["vocals_markers"].append(
+ markerNode(t, f"$vocal_marker_{v_note['freeform_marker']}"))
for t, v_note in vocals_lyrics_playable.items():
playable_vocals["lyrics"].append(markerNode(t, f"qbs(0x{v_note})"))
playable_vocals["qs_file"] = lyrics_qs_dict
# print()
+ if anim_notes["CAMERAS"]:
+ prev_time = 0
+ for k, v in anim_notes["CAMERAS"].items():
+ if prev_time:
+ prev_note = anim_notes["CAMERAS"][prev_time][0]
+ prev_note.setLength(v[0].time - prev_note.time)
+ prev_time = v[0].time
+ if len(v) > 1:
+ to_keep = -1
+ to_keep_2 = -1
+ for enum, cut in enumerate(v):
+ if cut.note in moment_cams:
+ to_keep = enum
+ elif cut.note in range(33,37):
+ to_keep_2 = enum
+ if to_keep >= 0:
+ anim_notes["CAMERAS"][k] = [v[to_keep]]
+ elif to_keep_2 >= 0:
+ anim_notes["CAMERAS"][k] = [v[to_keep_2]]
+ else:
+ anim_notes["CAMERAS"][k] = [v[0]]
temp_sp = []
for enum, sp in enumerate(vocal_sp):
if enum % 2 == 0:
@@ -1211,8 +1154,9 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
for index in np.nditer(to_open): # Loop through indexes in drum anims
temp_anim = drum_anim[hh_array[index]]
temp_notes = [x.note for x in temp_anim]
- if 78 in temp_notes:
- temp_anim[temp_notes.index(78)].note = 79
+ for x in [78, 65, 39, 9]:
+ if x in temp_notes:
+ temp_anim[temp_notes.index(x)].note += 1
except:
continue
@@ -1230,27 +1174,125 @@ def parse_wt_qb(mid, hopo, *args, **kwargs):
if ghost_notes:
ghost_notes = split_list([elem for pair in ghost_notes.items() for elem in pair])
+ to_return = {"playable_qb": playable_qb, "star_power": playable_star_power, "bm_star_power": playable_bm_star_power,
+ "tap": playable_tap, "fo_star_power": playable_fo_star_power, "face_off": playable_face_off,
+ "gtr_markers": markers, "drum_fills": playable_drum_fills, "anim": anim_notes, "timesigs": timeSigs,
+ "fretbars": fretbars, "vox_sp": vocal_sp, "ghost_notes": ghost_notes,
+ "solo_markers": playable_solo_markers,
+ "has_2x_kick": has_2x_kick, "xplus": 0
+ }
+ xplus_track = 0
+ '''if "wtde" in args and make_xplus and not "2x_check" in args:
+ x_args = list(args) + ["2x_check"]
+ xplus_track = parse_wt_qb(mid, hopo, *x_args)
+
+ if xplus_track:
+ to_return["wtde_xplus"] = xplus_track'''
+
+ return to_return
+
+
+def make_open(temp_anim, temp_notes, from_note):
+ temp_anim[temp_notes.index(from_note)].note = from_note + 1
+
+
+def create_playable_notes(notes, drums=False):
+ timestamps = {}
+ for colour, times in notes.items():
+ if colour == "2x":
+ continue
+ note_bit = note_bit_vals[colour]
+ colour_time = []
+ for count, playtime in enumerate(times):
+ if count % 2 == 0:
+ colour_time.append(playtime)
+ else:
+ if colour_time[-1]["time_sec"] in timestamps:
+ s_time = colour_time[-1]["time_sec"]
+ test_colour = timestamps[s_time]
+ t_time = colour_time[-1]["time_tick"]
+ test_colour["colours"].append(note_bit)
+ test_colour["colour_name"].append(colour)
+ temp_len = playtime["time_sec"] - s_time
+ if temp_len < 13:
+ temp_len = 13
+ temp_other_len = test_colour["length_sec"]
+ if drums:
+ if colour_time[-1]["velocity"] == 127:
+ timestamps[s_time]["accents"].append(note_bit)
+ if temp_len != test_colour["length_sec"]:
+ temp_len_t = playtime["time_tick"] - t_time
+ other_temp_t = timestamps[s_time]["length_tick"]
+ if temp_len_t <= 180 and other_temp_t <= 180:
+ timestamps[s_time]["length_sec"] = min(temp_len, temp_other_len)
+ timestamps[s_time]["length_tick"] = min(temp_len_t, other_temp_t)
+ del temp_len
+ del temp_other_len
+ del temp_len_t
+ del other_temp_t
+ elif colour == "purple":
+ test_colour["length_sec_kick"] = temp_len
+ elif 5 in test_colour["colours"]:
+ test_colour["length_sec_kick"] = test_colour["length_sec"]
+ test_colour["length_sec"] = temp_len
+ else:
+ timestamps[s_time]["length_sec"] = min(temp_len, temp_other_len)
+ timestamps[s_time]["length_tick"] = min(temp_len_t, other_temp_t)
+ del temp_len
+ del temp_other_len
+ del temp_len_t
+ del other_temp_t
+ else:
+ if temp_len != timestamps[s_time]["length_sec"]:
+ temp_len_t = playtime["time_tick"] - t_time
+ other_temp_t = timestamps[s_time]["length_tick"]
+ timestamps[s_time]["length_sec"] = min(temp_len, temp_other_len)
+ timestamps[s_time]["length_tick"] = min(temp_len_t, other_temp_t)
+ del temp_len
+ del temp_other_len
+ del temp_len_t
+ del other_temp_t
+ else:
+ s_time = colour_time[-1]["time_sec"]
+ t_time = colour_time[-1]["time_tick"]
+ len_sec = playtime["time_sec"] - s_time
+ if len_sec < 13:
+ len_sec = 13
+ len_tick = playtime["time_tick"] - t_time
+ if not drums:
+ timestamps[s_time] = {"colours": [note_bit], "colour_name": [colour],
+ "length_sec": len_sec,
+ "length_tick": playtime["time_tick"] - t_time,
+ "extended": []} | colour_time[-1]
+ else:
+ timestamps[s_time] = {"colours": [note_bit], "colour_name": [colour],
+ "length_sec": len_sec,
+ "length_tick": len_tick,
+ "accents": [], "length_sec_kick": 0} | colour_time[-1]
+ if colour_time[-1]["velocity"] == 127:
+ timestamps[s_time]["accents"].append(note_bit)
+ return timestamps
- return {"playable_qb": playable_qb, "star_power": playable_star_power, "bm_star_power": playable_bm_star_power,
- "tap": playable_tap, "fo_star_power": playable_fo_star_power, "face_off": playable_face_off,
- "gtr_markers": markers, "drum_fills": playable_drum_fills, "anim": anim_notes, "timesigs": timeSigs,
- "fretbars": fretbars, "vox_sp": vocal_sp, "ghost_notes": ghost_notes, "solo_markers": playable_solo_markers,
- "has_2x_kick": has_2x_kick
- }
-def auto_gen_camera(fretbars):
+def auto_gen_camera(fretbars, gh3=False):
cam_cycle = [10, 18, 23, 15, 43, 11, 19, 24, 16, 30]
+ if gh3:
+ cam_cycle = [wor_camera_converts["gh3"][x] for x in cam_cycle]
cameras = {}
for enum, fb in enumerate(fretbars):
note_start = round_time(fb)
try:
- note_len = round_cam_len(round_time(fretbars[enum+1]) - note_start)
+ note_len = round_cam_len(round_time(fretbars[enum + 1]) - note_start)
except IndexError:
note_len = 20000
- cameras[note_start] = [AnimNoteWT(note_start, cam_cycle[enum % len(cam_cycle)], 96)]
+ if gh3:
+ cameras[note_start] = [AnimNote(note_start, cam_cycle[enum % len(cam_cycle)])]
+ else:
+ cameras[note_start] = [AnimNoteWT(note_start, cam_cycle[enum % len(cam_cycle)], 96)]
cameras[note_start][0].setLength(note_len)
return cameras
+
def auto_gen_drums(drum_notes):
anim_lookup = {
0: 74,
@@ -1271,10 +1313,23 @@ def auto_gen_drums(drum_notes):
drum_anim[note_time] = anim_array
return drum_anim
-def auto_gen_lightshow(fretbars, markers):
+
+def auto_gen_lightshow(fretbars, markers, gh3=False):
fb_array = np.array(fretbars)
lightshow = {}
- lightshow[0] = [AnimNoteWT(0, 39, 96, 25), AnimNoteWT(0, 84, 96, 25)]
+ if gh3:
+ lightshow[0] = [AnimNote(0, 39, 25), AnimNote(0, 76, 25)]
+ else:
+ lightshow[0] = [AnimNoteWT(0, 39, 96, 25), AnimNoteWT(0, 84, 96, 25)]
+
+ gh3_lights = {
+ 74: 74,
+ 75: 74,
+ 76: 75,
+ 77: 74,
+ 78: 75,
+ 79: 78
+ }
for enum, marker in enumerate(markers):
try:
@@ -1282,10 +1337,10 @@ def auto_gen_lightshow(fretbars, markers):
except IndexError:
break
if re.search(r'intro( [0-9]?[a-z]?)?', marker.marker, flags=re.IGNORECASE):
- light = 79 # Prelude
+ light = 79 # Prelude
light_steps = 0
elif re.search(r'(verse( [0-9]?a))|verse$', marker.marker, flags=re.IGNORECASE):
- light = 78 # Exposition
+ light = 78 # Exposition
light_steps = 4
elif re.search(r'((pre)-?(chorus)( [0-9]?a))|(pre)-?(chorus)$', marker.marker, flags=re.IGNORECASE):
light = 74 # Falling Action
@@ -1302,17 +1357,25 @@ def auto_gen_lightshow(fretbars, markers):
else:
light = 78 # Exposition
light_steps = 4
- lightshow[marker.time] = [AnimNoteWT(marker.time, light, 96, 25)]
+ if gh3:
+ light = gh3_lights[light]
+ lightshow[marker.time] = [AnimNote(marker.time, light, 25)]
+ else:
+ lightshow[marker.time] = [AnimNoteWT(marker.time, light, 96, 25)]
if light_steps != 0:
curr_steps = 1
frets_in_range = fb_array[(fb_array > marker.time) & (fb_array < next_time)]
for x in frets_in_range:
if curr_steps % light_steps == 0:
light_time = int(x)
- lightshow[light_time] = [AnimNoteWT(light_time, 58, 96, 25)]
+ if gh3:
+ lightshow[light_time] = [AnimNote(light_time, 58, 25)]
+ else:
+ lightshow[light_time] = [AnimNoteWT(light_time, 58, 96, 25)]
curr_steps += 1
return lightshow
+
def process_text_event(event, markers, time, time_sec):
if event.text.startswith("[section"):
if event.text.startswith("[section_"):
@@ -1320,7 +1383,8 @@ def process_text_event(event, markers, time, time_sec):
try:
markers.append(markerNode(time_sec, sections[event.text.split(" ")[1][:-1]].title()))
except:
- new_marker = " ".join(w.capitalize() for w in event.text.replace("_", " ").replace("\"", "\'").split(" ")[1:])
+ new_marker = " ".join(
+ w.capitalize() for w in event.text.replace("_", " ").replace("\"", "\'").split(" ")[1:])
if new_marker[-1] == "]":
new_marker = new_marker[:-1]
markers.append(markerNode(time_sec, new_marker))
@@ -1338,7 +1402,60 @@ def process_text_event(event, markers, time, time_sec):
return 0, 0
-def parseGH3QB(mid, hopo, hmxmode=1, spNote=116):
+def make_gh3_bin_notes(timestamps, play_notes, diff):
+ for enum, gem in timestamps.items():
+ play_notes[diff].notes.append(enum)
+ return
+
+
+def make_wt_bin_notes(timestamps, play_notes, diff, drums):
+ for enum, gem in timestamps.items():
+ play_notes[diff].notes.append(enum)
+ len_bin = bin(gem["length_sec"])[2:].zfill(16)
+ if not drums:
+ mod_bin = "11111"
+ if gem["extended"]:
+ mod_bin = int(mod_bin, 2)
+ for mod in gem["extended"]:
+ mod_bin -= 1 << mod
+ mod_bin = bin(mod_bin)[2:]
+ elif gem["accents"]:
+ mod_bin = int("11111", 2)
+ for mod in gem["colours"]:
+ if mod not in gem["accents"] and mod < 5:
+ mod_bin -= 1 << mod
+ mod_bin = bin(mod_bin)[2:]
+ else:
+ mod_bin = "00000"
+
+ if drums and "2x_kick" in gem:
+ double_bits = "0010"
+ mod_bin = double_bits + mod_bin
+
+ mod_bin = mod_bin.zfill(9)
+ sep_kick = 0
+ if not drums:
+ notes_bin = make_bin_notes(gem)
+ elif gem["length_sec_kick"]:
+ gem["colours"].remove(5)
+ notes_bin = make_bin_notes(gem)
+ kick_note = make_bin_notes({"colours": [5]})
+ len_bin_kick = bin(gem["length_sec_kick"])[2:].zfill(16)
+ sep_kick = int(mod_bin + kick_note + len_bin_kick, 2)
+ mod_bin = "0000" + mod_bin[4:]
+ else:
+ notes_bin = make_bin_notes(gem)
+
+ note_val = mod_bin + notes_bin + len_bin
+ play_notes[diff].notes.append(int(note_val, 2))
+ if sep_kick:
+ play_notes[diff].notes.append(enum)
+ play_notes[diff].notes.append(sep_kick)
+ return
+
+
+def parse_gh3_qb(mid, hopo, *args, **kwargs):
+ hmxmode = 1
changes, ticks = tempMap(mid)
ticksArray = np.array(ticks)
@@ -1351,8 +1468,6 @@ def parseGH3QB(mid, hopo, hmxmode=1, spNote=116):
for x in mid.tracks:
if x.name in GH2Tracks:
spNote = 103
- elif x.name == "VENUE":
- hmxvenue = x.copy()
elif x.name == "GH3 VENUE":
gh3venue = x.copy()
@@ -1360,14 +1475,14 @@ def parseGH3QB(mid, hopo, hmxmode=1, spNote=116):
"""if hmxvenue and not gh3venue:
gh3venue = convertVenue(mid, hmxvenue, changes, ticksArray)"""
- playTracksDict = {
+ play_notes_dict = {
"PART GUITAR": "Guitar",
"PART BASS": "Bass",
"PART GUITAR COOP": "Guitar_Coop",
"PART RHYTHM": "Rhythm_Coop"
}
- playableQB = {
+ playable_qb = {
"Guitar": {},
"Bass": {},
"Guitar_Coop": {},
@@ -1379,11 +1494,78 @@ def parseGH3QB(mid, hopo, hmxmode=1, spNote=116):
"Bass": []
}
- faceOffs = {
+ face_offs = {
"P1": [],
"P2": []
}
+ venue_track = "LIGHTSHOWCAMERASCROWD"
+
+ valid_anims = {
+ "LIGHTSHOW": valid_lightshow_notes_gh3,
+ "CAMERAS": valid_camera_notes_gha if "gha" in args else valid_camera_notes_gh3,
+ "CROWD": valid_crowd_wt
+ }
+
+ anim_notes = {
+ "scripts_notes": {},
+ "left_hand": {},
+ "triggers_notes": {},
+ "CAMERAS": {},
+ "LIGHTSHOW": {},
+ "CROWD": {},
+ "drum_anims": {},
+ "scripts": {},
+ "anim": {},
+ "triggers": {},
+ "cameras": [],
+ "lightshow": [],
+ "crowd": {},
+ "drums": {},
+ "performance": []
+ }
+
+ fo_star_power = {
+ "Guitar": [],
+ "Bass": [],
+ "Guitar_Coop": [],
+ "Rhythm_Coop": []
+ }
+
+ star_power = {
+ "Guitar": [],
+ "Bass": [],
+ "Guitar_Coop": [],
+ "Rhythm_Coop": []
+ }
+
+ bm_star_power = {
+ "Guitar": [],
+ "Bass": [],
+ "Guitar_Coop": [],
+ "Rhythm_Coop": []
+ }
+
+ playable_star_power = {
+ "Guitar": {},
+ "Bass": {},
+ "Guitar_Coop": {},
+ "Rhythm_Coop": {}
+ }
+
+ playable_bm_star_power = {
+ "Guitar": {},
+ "Bass": {},
+ "Guitar_Coop": {},
+ "Rhythm_Coop": {}
+ }
+
+ open_hh = []
+ inst_map = note_mapping_gh3 | forceMapping
+
+ note_len_mode = 0 # Convert WoR lighting to GH3 style blend events
+ drum_key_map = drumKeyMapRB_gh3
+
cameraNotes = []
lightshowNotes = []
lightshowScripts = []
@@ -1392,562 +1574,548 @@ def parseGH3QB(mid, hopo, hmxmode=1, spNote=116):
markers = []
fretbars = []
- for trackNum, track in enumerate(mid.tracks):
- diffs = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
-
- starPowerList = []
-
- starPowerDiffs = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
-
- starBM = {
- "Easy": [],
- "Medium": [],
- "Hard": [],
- "Expert": []
- }
-
- time = 0
- activeNote = {
- "Easy": 0,
- "Medium": 0,
- "Hard": 0,
- "Expert": 0
- }
-
- qbItems = []
- forcing = {
- "Easy": {"force_on": 0, "force_off": 0},
- "Medium": {"force_on": 0, "force_off": 0},
- "Hard": {"force_on": 0, "force_off": 0},
- "Expert": {"force_on": 0, "force_off": 0}
- }
+ last_event_secs = 0
+ last_event_tick = 0
+ end_event_secs, end_event_ticks = 0, 0
+ for track_num, track in enumerate(mid.tracks):
try:
- instrument = playTracksDict[track.name]
+ instrument = play_notes_dict[track.name]
except:
print(f"Processing non-instrument track {track.name}")
+ playable = False
else:
print(f"Processing instrument track {track.name}")
- for x in track:
+ playable = True
+ if playable:
+ play_notes, active_notes, forced_notes, play_face_off, play_star, play_star_bm, play_star_fo = create_diff_dicts()
+
+ starPowerList = []
+
+ activeNote = {
+ "Easy": 0,
+ "Medium": 0,
+ "Hard": 0,
+ "Expert": 0
+ }
+
+ forcing = {
+ "Easy": {"force_on": 0, "force_off": 0},
+ "Medium": {"force_on": 0, "force_off": 0},
+ "Hard": {"force_on": 0, "force_off": 0},
+ "Expert": {"force_on": 0, "force_off": 0}
+ }
+
+ else:
+ active_notes = {}
+ time = 0
+ for y, x in enumerate(track):
time += x.time
currChange = changes[len(ticksArray[ticksArray <= time]) - 1] # time, tempo, avgTempo
- timeSec = timeInSecs(currChange, mid, time)
- if trackNum == 0:
+ time_sec = timeInSecs(currChange, mid, time)
+ if track_num == 0:
if x.type == "time_signature":
- timeSigs.append(timeSigEvent(timeSec, x.numerator, x.denominator))
+ timeSigs.append(timeSigEvent(time_sec, x.numerator, x.denominator))
elif track.name == "EVENTS":
if x.type == 'text':
- # print(msg, timeSec)
- end_event_secs, end_event_ticks = process_text_event(x, markers, time, timeSec)
+ # print(msg, time_sec)
+ end_event_secs, end_event_ticks = process_text_event(x, markers, time, time_sec)
if end_event_secs and end_event_ticks:
continue
- """if x.text.startswith("[section"):
- if x.text.startswith("[section_"):
- x.text = x.text.replace("_", " ", 1)
- try:
- markers.append(markerNode(timeSec, sections[x.text.split(" ")[1][:-1]].title()))
- except:
- markers.append(markerNode(timeSec, x.text.split(" ")[1].title()))
- elif x.text.startswith("[prc_"):
- try:
- markers.append(markerNode(timeSec, sections[x.text[1:-1]].title()))
- except:
- markers.append(markerNode(timeSec, x.text[1:-1].title()))
- elif x.text == '[end]':
- end_event_secs = timeSec
- end_event_ticks = time"""
-
- elif track.name == "GH3 VENUE":
- if x.type == "note_on":
- if x.note in valid_camera_notes_gh3:
- if x.velocity != 0:
- if len(cameraNotes) >= 1:
- camera_length = timeSec - cameraNotes[-1].time
- if camera_length > 0:
- cameraNotes[-1].setLength(timeSec - cameraNotes[-1].time)
- else:
- continue
- cameraNotes.append(AnimNote(timeSec, x.note))
- elif x.note in valid_lightshow_notes_gh3:
- if x.velocity != 0:
- lightshowNotes.append(AnimNote(timeSec, x.note))
+ elif re.search(track.name, venue_track, flags=re.IGNORECASE):
+ track.name = track.name.upper()
+ valid_check = valid_anims[track.name]
+ if track.name == "CAMERAS" and not "gha" in args:
+ alt_check = wor_camera_converts["gh3"]
+ else:
+ alt_check = []
+ if x.type == "note_on" or x.type == "note_off":
+ if x.note in valid_check:
+ if track.name == "LIGHTSHOW":
+ if x.note == 107:
+ note_len_mode = 1
+ continue
+ if all([x.note in range(39, 54), note_len_mode]):
+ continue
+ create_anim_note(x, active_notes, track.name, anim_notes, time_sec,
+ AnimNote(time_sec, x.note))
+ elif x.note in alt_check and "gha" not in args:
+ create_anim_note(x, active_notes, track.name, anim_notes, time_sec,
+ AnimNote(time_sec, alt_check[x.note]))
elif x.type == "text":
- if x.text.startswith("SetBlendTime"):
- blendtime = float(x.text.split(" ")[1])
- lightshowScripts.append(scriptsNode(timeSec, "LightShow_SetTime", blendtime))
+ if re.search(r'^(SetBlendTime|LightShow_Set)', x.text, flags=re.IGNORECASE) and not note_len_mode:
+ # if x.text.startswith("SetBlendTime") or x.text.startswith("LightShow_Set"):
+ blendtime = {"param": "time", "data": float(x.text.split(" ")[1]),
+ "type": "Float"} # Blend time is in seconds
+ anim_notes["lightshow"].append(scriptsNode(time_sec, "LightShow_SetTime", [blendtime]))
elif track.name == "PART DRUMS":
- if x.type == "note_on":
- if x.note in drumKeyMapRB_gh3.keys():
+ if x.type == "note_on" or x.type == "note_off":
+ if x.note in drum_key_map:
+ new_note = drum_key_map[x.note]
+ if x.velocity != 0 and x.type == "note_on":
+ if new_note in active_notes:
+ continue
+ active_notes[new_note] = AnimNote(time_sec, drumKeyMapRB_gh3[x.note])
+ else:
+ try:
+ drum_anim_note(x, active_notes, new_note, anim_notes, time_sec, args)
+ except KeyError as E:
+ # raise E
+ pass
+ except:
+ raise Exception(f"Something went wrong parsing the {track.name} track.")
+ elif x.note == 25:
+ open_hh.append(time_sec)
+ elif track.name == "PART VOCALS":
+ if x.type == "text":
+ check_to_add_stance(x, time_sec, anim_notes, "Vocalist", singer_stances, singer_anims)
+ elif playable:
+ if x.type == "note_on" or x.type == "note_off":
+ if x.note in inst_map:
+ chart_diff = inst_map[x.note].split("_")[0]
+ note_colour = inst_map[x.note].split("_")[1]
+ if note_colour not in ["off", "on"]:
+ to_add = {"time_sec": time_sec, "time_tick": time, "curr_change": currChange,
+ "velocity": x.velocity}
+ if note_colour in active_notes[chart_diff]:
+ temp = active_notes[chart_diff]
+ temp[note_colour].append(to_add)
+ else:
+ active_notes[chart_diff][note_colour] = [to_add]
+ else:
+ forced_notes[chart_diff][note_colour].append(time_sec)
+ elif x.note == sp_note:
+ star_power[instrument].append(time_sec)
+ if track.name == "PART GUITAR":
+ if x.note == bm_star_note:
+ bm_star_power[instrument].append(time_sec)
+ elif x.note in faceOffMapping:
+ play_face_off[faceOffMapping[x.note]].append(time_sec)
+ if not "COOP" in track.name and x.note in leftHandGtr_gh3:
+ lh_name = instrument if instrument != "Rhythm_Coop" else "Bass"
+ new_note = anim_maps_gh3[lh_name][x.note]
if x.velocity != 0:
- drumNotes.append(AnimNote(timeSec, drumKeyMapRB_gh3[x.note]))
- else:
- if x.type == "note_on":
- if track.name in playTracksDict:
- if x.velocity == 0:
- if x.note in note_mapping_gh3:
- chartDiff = note_mapping_gh3[x.note].split("_")[0]
- noteColour = note_mapping_gh3[x.note].split("_")[1]
- if activeNote[chartDiff] == 1:
- activeNote[chartDiff] = 0
- diffs[chartDiff][-1].setLength(timeSec - diffs[chartDiff][-1].time,
- currChange.tempo,
- mid.ticks_per_beat)
- elif x.note in forceMapping:
- chartDiff = forceMapping[x.note].split("_")[0]
- forceType = "force_" + forceMapping[x.note].split("_")[1]
- forcing[chartDiff][forceType] = 0
- if diffs[chartDiff]:
- if timeSec == diffs[chartDiff][-1].time:
- setattr(diffs[chartDiff][-1], forceType, 0)
- elif x.note == spNote:
- starPowerList[-1].setLength(timeSec - starPowerList[-1].time)
- elif instrument == "Guitar":
- if x.note in faceOffMapping:
- faceOffs[faceOffMapping[x.note]][-1].setLength(
- timeSec - faceOffs[faceOffMapping[x.note]][-1].time - 1)
- elif instrument != "Guitar_Coop":
- if x.note in leftHandGtr_gh3:
- if instrument == "Rhythm_Coop":
- leftIns = "Bass"
- else:
- leftIns = instrument
- leftHandAnims[leftIns][-1].setLength(timeSec - leftHandAnims[leftIns][-1].time)
+ if new_note in active_notes:
+ continue
+ active_notes[new_note] = AnimNote(time_sec, new_note)
else:
- if x.note in note_mapping_gh3:
- chartDiff = note_mapping_gh3[x.note].split("_")[0]
- noteColour = note_mapping_gh3[x.note].split("_")[1]
-
- if not diffs[chartDiff]: # Check for empty note array and adds a note
- diffs[chartDiff].append(Note(timeSec, 0, currChange))
- activeNote[chartDiff] = 1
- elif diffs[chartDiff][
- -1].time != timeSec: # Check if the note shows up at the same time as the previous note
- if activeNote[
- chartDiff] == 1: # If a note has already been placed before a note_off event occured
- if timeSec - diffs[chartDiff][
- -1].time <= 16: # Broken chord check. If the note is within 16ms (approx 1/60, i.e. one frame) assume it's part of the same note as before
- setattr(diffs[chartDiff][-1], noteColour, 1)
- else: # If not, it's assumed to be a new note. Old note gets cut off at the time stamp and new note is created
- diffs[chartDiff][-1].setLength(timeSec - diffs[chartDiff][-1].time,
- currChange.tempo,
- mid.ticks_per_beat)
- diffs[chartDiff].append(Note(timeSec, diffs[chartDiff][-1], currChange))
- activeNote[chartDiff] = 1
- else: # If no note is currently active at this note_on event, create one.
- diffs[chartDiff].append(Note(timeSec, diffs[chartDiff][-1], currChange))
- activeNote[chartDiff] = 1
- if noteColour in colours:
- setattr(diffs[chartDiff][-1], noteColour, 1)
- if "forceType" in locals():
- if forcing[chartDiff][forceType] == 1:
- setattr(diffs[chartDiff][-1], forceType, 1)
- if x.note in forceMapping:
- chartDiff = forceMapping[x.note].split("_")[0]
- forceType = "force_" + forceMapping[x.note].split("_")[1]
- forcing[chartDiff][forceType] = 1
- if diffs[chartDiff]:
- if timeSec == diffs[chartDiff][-1].time:
- setattr(diffs[chartDiff][-1], forceType, 1)
- if x.note == spNote:
- if not starPowerList:
- starPowerList.append(StarPower(timeSec))
- elif starPowerList[-1].time != timeSec:
- starPowerList.append(StarPower(timeSec))
- if instrument == "Guitar":
- if x.note in leftHandGtr_gh3:
- if not leftHandAnims[instrument]:
- leftHandAnims[instrument].append(AnimNote(timeSec, leftHandGtr_gh3[x.note]))
- elif leftHandAnims[instrument][-1].time != timeSec:
- leftHandAnims[instrument].append(AnimNote(timeSec, leftHandGtr_gh3[x.note]))
- if x.note in faceOffMapping:
- if not faceOffs[faceOffMapping[x.note]]:
- faceOffs[faceOffMapping[x.note]].append(FaceOffSection(timeSec))
- elif faceOffs[faceOffMapping[x.note]][-1].time != timeSec:
- faceOffs[faceOffMapping[x.note]].append(FaceOffSection(timeSec))
- if instrument == "Bass" or instrument == "Rhythm_Coop":
- if x.note in leftHandBass_gh3:
- if not leftHandAnims["Bass"]:
- leftHandAnims["Bass"].append(AnimNote(timeSec, leftHandBass_gh3[x.note]))
- elif leftHandAnims["Bass"][-1].time != timeSec:
- leftHandAnims["Bass"].append(AnimNote(timeSec, leftHandBass_gh3[x.note]))
-
- elif x.type == "note_off":
- if track.name in playTracksDict:
- if x.note in note_mapping_gh3:
- chartDiff = note_mapping_gh3[x.note].split("_")[0]
- noteColour = note_mapping_gh3[x.note].split("_")[1]
- if activeNote[chartDiff] == 1:
- activeNote[chartDiff] = 0
- diffs[chartDiff][-1].setLength(timeSec - diffs[chartDiff][-1].time, currChange.tempo,
- mid.ticks_per_beat)
- if x.note in forceMapping:
- chartDiff = forceMapping[x.note].split("_")[0]
- forceType = "force_" + forceMapping[x.note].split("_")[1]
- forcing[chartDiff][forceType] = 0
- if diffs[chartDiff]:
- if timeSec == diffs[chartDiff][-1].time:
- setattr(diffs[chartDiff][-1], forceType, 0)
- if x.note == spNote:
- starPowerList[-1].setLength(timeSec - starPowerList[-1].time)
- if instrument == "Guitar":
- if x.note in faceOffMapping:
- faceOffs[faceOffMapping[x.note]][-1].setLength(
- timeSec - faceOffs[faceOffMapping[x.note]][-1].time - 1)
- if instrument != "Guitar_Coop":
- if x.note in leftHandGtr_gh3:
- leftHandAnims[instrument][-1].setLength(timeSec - leftHandAnims[instrument][-1].time)
-
- for x in diffs:
- spCounter = 0
- for y in diffs[x]:
- if not starPowerDiffs[x]:
- try:
- starPowerDiffs[x].append(
- StarPowerPhrase(starPowerList[spCounter].time, starPowerList[spCounter].length))
- except:
- print(f"No Star Power found for track {track.name} on {x} difficulty")
- break
- if y.time >= starPowerList[spCounter].time and y.time <= starPowerList[spCounter].time + starPowerList[
- spCounter].length:
- starPowerDiffs[x][-1].incNotes()
- # print(spCounter, x, y, len(starPowerList))
- elif y.time > starPowerList[spCounter].time + starPowerList[spCounter].length:
- if len(starPowerList) == spCounter + 1:
- pass
+ try:
+ active_notes[new_note].setLength(time_sec - active_notes[new_note].time)
+ if active_notes[new_note].time in anim_notes["left_hand"]:
+ anim_notes["left_hand"][active_notes[new_note].time].append(
+ active_notes[new_note])
+ else:
+ anim_notes["left_hand"][active_notes[new_note].time] = [active_notes[new_note]]
+ active_notes.pop(new_note)
+ except KeyError:
+ pass
+ except:
+ raise Exception(f"Something went wrong parsing the {track.name} track.")
+ elif x.type == "text":
+ if instrument == "Bass" or instrument == "Guitar":
+ player = "Bassist" if instrument == "Bass" else "Guitarist"
+ check_to_add_stance(x, time_sec, anim_notes, player, guit_stances, guit_anims)
+ if playable:
+ star_power[instrument] = split_list(star_power[instrument])
+ bm_star_power[instrument] = split_list(bm_star_power[instrument])
+ if track.name == "PART GUITAR":
+ for player, fo in play_face_off.items():
+ if fo:
+ play_face_off[player] = split_list(fo)
+ for diff, notes in active_notes.items():
+ timestamps = create_playable_notes(notes)
+ timestamps = dict(sorted(timestamps.items()))
+ time_array = np.array(list(timestamps.keys()))
+
+ prev_time = 0
+ prev_colours = ""
+ for enum, (timing, gem) in enumerate(timestamps.items()):
+ curr_colours = "".join(sorted(gem["colour_name"]))
+ if prev_time != 0:
+ if all([gem["time_tick"] - prev_time <= hopo, len(gem["colours"]) == 1,
+ prev_colours != curr_colours]):
+ gem["is_hopo"] = True
+ else:
+ gem["is_hopo"] = False
+ if all([gem["is_hopo"], "rb_mode" in args, curr_colours in prev_colours]):
+ gem["colours"].append(5)
+ elif all([gem["is_hopo"], "force_only" in args]):
+ gem["colours"].append(5)
else:
- while y.time > starPowerList[spCounter].time + starPowerList[spCounter].length:
- spCounter += 1
- starPowerDiffs[x].append(
- StarPowerPhrase(starPowerList[spCounter].time, starPowerList[spCounter].length))
-
- if track.name in playTracksDict:
- for x in diffs:
- playableQB[instrument][x] = Difficulty(x, instrument, diffs[x], starPowerDiffs[x], starBM[x])
- for y in playableQB[instrument][x].song:
- y.setForcing(hopo, mid.ticks_per_beat, hmxmode)
-
- # print(playableQB)
+ gem["is_hopo"] = False
+
+ prev_time = gem["time_tick"]
+ prev_colours = curr_colours
+ # print()
+ force_on = forced_notes[diff]["on"]
+ if force_on:
+ force_on = split_list(force_on)
+ for forced in force_on:
+ if forced[0] == forced[1]:
+ forced[1] += 1
+ # Pull all timestamps that need to be forced
+ to_force = mod_notes(time_array, forced)
+ for index in np.nditer(to_force): # Loop through indexes in timestamps
+ temp_colour = timestamps[time_array[index]]["colours"]
+ if index == 0:
+ continue
+ elif temp_colour == timestamps[time_array[index - 1]]["colours"]:
+ continue
+ elif len(temp_colour) > 1:
+ continue
+ elif timestamps[time_array[index]]["is_hopo"]:
+ if 5 in timestamps[time_array[index]]["colours"] and not "gh3_mode" in args:
+ timestamps[time_array[index]]["colours"].remove(5)
+ continue
+ else:
+ timestamps[time_array[index]]["colours"].append(5)
+
+ force_off = forced_notes[diff]["off"] if not "gh3_mode" in args else 0
+ if force_off:
+ force_off = split_list(force_off)
+ for forced in force_off:
+ if forced[0] == forced[1]:
+ forced[1] += 1
+ to_force = mod_notes(time_array, forced)
+ for index in np.nditer(to_force):
+ if not timestamps[time_array[index]]["is_hopo"] and 5 in timestamps[time_array[index]][
+ "colours"]:
+ timestamps[time_array[index]]["colours"].remove(5)
+ elif timestamps[time_array[index]]["is_hopo"]:
+ timestamps[time_array[index]]["colours"].append(5)
+
+ if star_power[instrument]:
+ note_range_count(star_power[instrument], time_array, play_star[diff])
+ if bm_star_power[instrument]:
+ note_range_count(bm_star_power[instrument], time_array, play_star_bm[diff])
+
+ play_notes[diff] = NoteChart(instrument, diff, True)
+ for enum, gem in timestamps.items():
+ play_notes[diff].notes.append(enum)
+ play_notes[diff].notes.append(gem["length_sec"])
+ play_notes[diff].notes.append(set_gems(gem))
+
+ playable_qb[instrument] = play_notes.copy()
+ playable_star_power[instrument] = play_star.copy()
+ playable_bm_star_power[instrument] = play_star_bm.copy()
+
+ if note_len_mode:
+ blend_lookup = {
+ 1000: 53,
+ 900: 52,
+ 800: 51,
+ 700: 50,
+ 600: 49,
+ 500: 48,
+ 400: 47,
+ 300: 46,
+ 250: 45,
+ 200: 44,
+ 150: 43,
+ 100: 42,
+ 50: 41,
+ 0: 40
+ }
+ strobe_mode = 0
+ prev_len = -1
+ new_lights = {}
+ for key, value in anim_notes["LIGHTSHOW"].items():
+ blend_time = key - 20
+ max_len = 0
+ blended = False
+ for lights in value:
+ if lights.note in range(70, 77) or lights.note in range(57,59):
+ blended = True
+ if lights.note == 70:
+ strobe_mode = 1
+ elif lights.note in range(71, 77):
+ strobe_mode = 0
+ if lights.note == 56:
+ continue
+ max_len = max(max_len, lights.length)
+ if not blended:
+ continue
+ if not strobe_mode:
+ if max_len > 1020:
+ max_len = round((max_len) / 1000, 3)
+ blendtime = {"param": "time", "data": float(max_len),
+ "type": "Float"} # Blend time is in seconds
+ anim_notes["lightshow"].append(scriptsNode(blend_time, "LightShow_SetTime", [blendtime]))
+ elif max_len % 100 < 50:
+ max_len = round(max_len, -2)
+ blend_note = AnimNote(blend_time, blend_lookup[max_len])
+ blend_note.setLength(20)
+ if max_len == prev_len:
+ continue
+ if blend_time in new_lights:
+ new_lights[blend_time].append(blend_note)
+ else:
+ new_lights[blend_time] = [blend_note]
+ elif max_len % 100 < 100 and max_len % 100 >= 50 and max_len < 300:
+ max_len = round(max_len) // 50 * 50
+ blend_note = AnimNote(blend_time, blend_lookup[max_len])
+ blend_note.setLength(20)
+ if max_len == prev_len:
+ continue
+ if blend_time in new_lights:
+ new_lights[blend_time].append(blend_note)
+ else:
+ new_lights[blend_time] = [blend_note]
+ else:
+ max_len = round((max_len) / 1000, 3)
+ blendtime = {"param": "time", "data": float(max_len),
+ "type": "Float"} # Blend time is in seconds
+ anim_notes["lightshow"].append(scriptsNode(blend_time, "LightShow_SetTime", [blendtime]))
+ else:
+ blend_note = AnimNote(blend_time, 40)
+ blend_note.setLength(20)
+ if blend_time in new_lights:
+ new_lights[blend_time].append(blend_note)
+ else:
+ new_lights[blend_time] = [blend_note]
+ prev_len = max_len
+ for key, value in new_lights.items():
+ if key in anim_notes["LIGHTSHOW"]:
+ for note in value:
+ anim_notes["LIGHTSHOW"][key].append(note)
+ else:
+ anim_notes["LIGHTSHOW"][key] = value
+ anim_notes["LIGHTSHOW"] = dict(sorted((anim_notes["LIGHTSHOW"].items())))
+
+
if not "end_event_secs" in locals():
raise Exception("Invalid MIDI: No [end] event found. Cannot parse MIDI.")
if cameraNotes:
cameraNotes[-1].setLength(end_event_secs - cameraNotes[-1].time)
fretbars = parse_fretbars(timeSigs, end_event_ticks, changes, ticksArray, mid)
+ if anim_notes["drum_anims"]:
+ drum_anim = anim_notes["drum_anims"]
+ open_hh = split_list(open_hh)
+ hh_array = np.array(list(drum_anim.keys()))
+ for hh in open_hh:
+ to_open = mod_notes(hh_array, hh)[0]
+ try:
+ for index in np.nditer(to_open): # Loop through indexes in drum anims
+ temp_anim = drum_anim[hh_array[index]]
+ temp_notes = [x.note for x in temp_anim]
+ for x in [65, 53, 41]:
+ if x in temp_notes:
+ temp_anim[temp_notes.index(x)].note += 1
+ except:
+ continue
- # print(fretbars[-1])
+ if not anim_notes["CAMERAS"] and "gha" not in args:
+ print("Generating cameras")
+ anim_notes["CAMERAS"] = auto_gen_camera(fretbars[::8], True)
- for x in playableQB:
- for i, y in enumerate(playableQB[x]):
- for j, z in enumerate(playableQB[x][y].song):
- if j != 0:
- prev = playableQB[x][y].song[j - 1]
- if z.time == prev.time + prev.length:
- prev.noNoteTouch()
- # print(y, z.time, prev.time + prev.length)
+ if not anim_notes["LIGHTSHOW"]:
+ print("Generating lightshow")
+ anim_notes["LIGHTSHOW"] = auto_gen_lightshow(fretbars, markers, True)
- return {"playableQB": playableQB, "drums_notes": drumNotes, "timesig": timeSigs, "markers": markers,
- "fretbars": fretbars, "leftHandAnims": leftHandAnims, "faceOffs": faceOffs, "cameras_notes": cameraNotes,
- "lightshow_notes": lightshowNotes, "lightshow": lightshowScripts}
+ return {"playable_qb": playable_qb, "star_power": playable_star_power, "bm_star_power": playable_bm_star_power,
+ "timesig": timeSigs, "markers": markers,
+ "fretbars": fretbars, "face_offs": play_face_off, "anim": anim_notes}
-def makeMidQB(midQB, filename, headerDict, consoleType):
+def create_gh3_sections(qb_dict, filename, headerDict, consoleType):
QBItems = []
- qbFileHeader = b'\x1C\x08\x02\x04\x10\x04\x08\x0C\x0C\x08\x02\x04\x14\x02\x04\x0C\x10\x10\x0C\x00'
# print(midQB)
- for x in midQB["playableQB"]:
+ for x in qb_dict["playable_qb"]:
QBChart = []
QBStar = []
QBStarBM = []
# print(x)
- if not midQB["playableQB"][x]:
+ if not qb_dict["playable_qb"][x]:
for y in difficulties:
instrument = x.replace("_", "").lower() if x != "Bass" else "rhythm"
- chartName = f"{filename}_song_{instrument}_{y}"
- starName = f"{filename}_{instrument}_{y}_Star"
- BMStarName = f"{filename}_{instrument}_{y}_StarBattleMode"
- QBChart.append(
- QBItem("ArrayInteger", chartName, headerDict[chartName], [], consoleType))
- QBStar.append(QBItem("ArrayArray", starName, headerDict[starName], [], consoleType))
- QBStarBM.append(QBItem("ArrayArray", BMStarName, headerDict[BMStarName], [], consoleType))
-
- for i, y in enumerate(midQB["playableQB"][x]):
- data = [midQB["playableQB"][x][y].song, midQB["playableQB"][x][y].star, midQB["playableQB"][x][y].starBM]
- if x == "Guitar":
- chartName = f"{filename}_song_{y}"
- starName = f"{filename}_{y}_Star"
- BMStarName = f"{filename}_{y}_StarBattleMode"
- QBChart.append(
- QBItem("ArrayInteger", chartName, headerDict[chartName], data[0], consoleType))
- QBStar.append(QBItem("ArrayArray", starName, headerDict[starName], data[1], consoleType))
- QBStarBM.append(QBItem("ArrayArray", BMStarName, headerDict[BMStarName], data[2], consoleType))
- else:
- instrument = x.replace("_", "").lower() if x != "Bass" else "rhythm"
- chartName = f"{filename}_song_{instrument}_{y}"
+ chart_name = f"{filename}_song_{instrument}_{y}"
starName = f"{filename}_{instrument}_{y}_Star"
BMStarName = f"{filename}_{instrument}_{y}_StarBattleMode"
- QBChart.append(
- QBItem("ArrayInteger", chartName, headerDict[chartName], data[0], consoleType))
- QBStar.append(QBItem("ArrayArray", starName, headerDict[starName], data[1], consoleType))
- QBStarBM.append(QBItem("ArrayArray", BMStarName, headerDict[BMStarName], data[2], consoleType))
+ QBChart.append(basic_data(chart_name, []))
+ QBStar.append(basic_data(chart_name, []))
+ QBStarBM.append(basic_data(chart_name, []))
+ else:
+ for i, y in enumerate(qb_dict["playable_qb"][x]):
+ song = qb_dict["playable_qb"][x][y].notes
+ star = qb_dict["star_power"][x][y]
+ star_bm = qb_dict["bm_star_power"][x][y]
+ if x == "Guitar":
+ chart_name = f"{filename}_song_{y}"
+ starName = f"{filename}_{y}_Star"
+ BMStarName = f"{filename}_{y}_StarBattleMode"
+ else:
+ instrument = x.replace("_", "").lower() if x != "Bass" else "rhythm"
+ chart_name = f"{filename}_song_{instrument}_{y}"
+ starName = f"{filename}_{instrument}_{y}_Star"
+ BMStarName = f"{filename}_{instrument}_{y}_StarBattleMode"
+ QBChart.append(basic_data(chart_name, song))
+ QBStar.append(basic_data(starName, star))
+ QBStarBM.append(basic_data(BMStarName, star_bm))
for y in [QBChart, QBStar, QBStarBM]:
for z in y:
QBItems.append(z)
# print(midQB["faceOffs"])
- for x in midQB["faceOffs"]:
- chartName = f"{filename}_FaceOff{x}"
- if not midQB["faceOffs"][x]:
- QBItems.append(QBItem("ArrayInteger", chartName, headerDict[chartName], [], consoleType))
+ for x in qb_dict["face_offs"]:
+ chart_name = f"{filename}_FaceOff{x}"
+ if not qb_dict["face_offs"][x]:
+ QBItems.append(basic_data(chart_name, []))
else:
- QBItems.append(QBItem("ArrayArray", chartName, headerDict[chartName], midQB["faceOffs"][x], consoleType))
+ QBItems.append(basic_data(chart_name, []))
# Boss Battle Array
- for x in midQB["faceOffs"]:
- chartName = f"{filename}_BossBattle{x}"
- QBItems.append(QBItem("ArrayArray", chartName, headerDict[chartName], [], consoleType))
+ for x in qb_dict["face_offs"]:
+ chart_name = f"{filename}_BossBattle{x}"
+ QBItems.append(basic_data(chart_name, []))
# timesig (array), markers (struct), fretbars (integer)
- chartName = f"{filename}_timesig"
- QBItems.append(QBItem("ArrayArray", chartName, headerDict[chartName], midQB["timesig"], consoleType))
+ chart_name = f"{filename}_timesig"
+ QBItems.append(basic_data(chart_name, [[x.time, x.numerator, x.denominator] for x in qb_dict["timesig"]]))
+
+ chart_name = f"{filename}_fretbars"
+ QBItems.append(basic_data(chart_name, qb_dict["fretbars"]))
+ chart_name = f"{filename}_markers"
+ gtr_markers = []
+ if qb_dict["markers"]:
+ for gtr in qb_dict["markers"]:
+ gtr_markers.append(struct_data())
+ temp_struct = gtr_markers[-1]
+ temp_struct.add_data("time", str(gtr.time))
+ temp_struct.add_data("marker", f"w\"{gtr.marker}\"")
+ QBItems.append(basic_data(chart_name, gtr_markers))
- chartName = f"{filename}_fretbars"
- QBItems.append(QBItem("ArrayInteger", chartName, headerDict[chartName], midQB["fretbars"], consoleType))
- chartName = f"{filename}_markers"
- QBItems.append(QBItem("ArrayStruct", chartName, headerDict[chartName], midQB["markers"], consoleType))
+ for anim, value in qb_dict["anim"].items():
+ if anim in anim_lookup:
+ chart_name = f"{filename}_{anim_lookup[anim]}"
+ else:
+ chart_name = f"{filename}_{anim}"
+ anim_list = []
+ if value:
+ if type(value) == dict:
+ prev_time = 0
+ for timing, notes in sorted(value.items()):
+ for anim_stuff in notes:
+ anim_list.append([timing, anim_stuff.note, anim_stuff.length])
+ prev_time = timing
+ elif type(value) == list:
+ for anim_stuff in value:
+ anim_list.append(make_script_struct(anim_stuff, False))
+ QBItems.append(basic_data(chart_name, anim_list.copy()))
+
+ return QBItems
- P1count = 0
- P2count = 0
- mergedAnim = []
+
+def check_to_add_stance(x, time_sec, anim_notes, player, stances, anims):
while True:
- try:
- if midQB["leftHandAnims"]["Guitar"][P1count].time < midQB["leftHandAnims"]["Bass"][P2count].time:
- mergedAnim.append(midQB["leftHandAnims"]["Guitar"][P1count])
- P1count += 1
- else:
- mergedAnim.append(midQB["leftHandAnims"]["Bass"][P2count])
- P2count += 1
- except:
- if P1count == len(midQB["leftHandAnims"]["Guitar"]):
- mergedAnim += midQB["leftHandAnims"]["Bass"][P2count:]
- else:
- mergedAnim += midQB["leftHandAnims"]["Guitar"][P1count:]
+ extra = []
+ if re.search(r'(cycle)', x.text, re.IGNORECASE):
+ extra.append("cycle")
+ if re.search(r'(no_wait)', x.text, re.IGNORECASE):
+ extra.append("no_wait")
+ if re.search(r'( [1-9]+)$', x.text, re.IGNORECASE):
+ extra.append("repeat")
+ extra.append(re.search(r'( [1-9]+)$', x.text, re.IGNORECASE).group(0).strip())
+ pattern = re.search(rf'({"|".join(stances)})', x.text, re.IGNORECASE)
+ if pattern:
+ new_stance = stance_script(time_sec, "Band_ChangeStance", player, pattern.group(0), *extra)
break
+ pattern = re.search(rf'^({"|".join(anims)})', x.text, re.IGNORECASE)
+ if pattern:
+ new_stance = stance_script(time_sec, "Band_PlayAnim", player, pattern.group(0), *extra)
+ break
+ new_stance = 0
+ break
+ if new_stance:
+ anim_notes["performance"].append(new_stance)
- misc = ["scripts", "anim", "triggers", "cameras", "lightshow", "crowd", "drums", "performance"]
- withNotes = ["drums", "lightshow", "cameras"]
- withScripts = ["lightshow"]
- QBNotes = []
- QBScripts = []
-
- for x in misc:
- xscript = f"{filename}_{x}"
- xnote = f"{xscript}_notes"
- notesqb = f"{x}_notes"
- if x == "anim":
- QBNotes.append(QBItem("ArrayArray", xnote, headerDict[xnote], mergedAnim, consoleType))
- elif x in withNotes:
- if not midQB[notesqb]:
- QBNotes.append(QBItem("ArrayInteger", xnote, headerDict[xnote], [], consoleType))
- else:
- QBNotes.append(QBItem("ArrayArray", xnote, headerDict[xnote], midQB[notesqb], consoleType))
- else:
- QBNotes.append(QBItem("ArrayInteger", xnote, headerDict[xnote], [], consoleType))
- if x in withScripts:
- QBScripts.append(QBItem("ArrayStruct", xscript, headerDict[xscript], midQB[x], consoleType))
- # print(QBScripts[-1])
- else:
- QBScripts.append(QBItem("ArrayInteger", xscript, headerDict[xscript], [], consoleType))
- for x in QBNotes:
- QBItems.append(x)
- for x in QBScripts:
- QBItems.append(x)
+def stance_script(time_sec, script, player, event, *args):
+ if script == "Band_ChangeStance":
+ params = new_stance_gh3(player, event, "stance", *args)
+ elif script == "Band_PlayAnim":
+ params = new_stance_gh3(player, event, "anim", *args)
+ else:
+ print(f"Script {script} at {time_sec} not recognized.")
+ return 0
+ script_node = scriptsNode(time_sec, script, params)
+ return script_node
- positionStart = 28
- qbbytes = bytearray()
+def create_anim_note(x, active_notes, track_name, anim_notes, time_sec, anim_entry):
+ if x.velocity != 0 and x.type == "note_on":
+ if x.note in active_notes:
+ return
+ active_notes[x.note] = anim_entry
+ else:
+ try:
+ anim_len = time_sec - active_notes[x.note].time
+ if anim_len < 13 or anim_len > 2**32:
+ anim_len = 13
+ active_notes[x.note].setLength(anim_len)
+ if active_notes[x.note].time in anim_notes[track_name]:
+ anim_notes[track_name][active_notes[x.note].time].append(active_notes[x.note])
+ else:
+ anim_notes[track_name][active_notes[x.note].time] = [active_notes[x.note]]
+ active_notes.pop(x.note)
+ except KeyError:
+ pass
+ except:
+ raise Exception(f"Something went wrong parsing the {track_name} track.")
+ return
- toBytes = lambda a, b=4: a.to_bytes(b, "big")
+def camera_script(zoom_type, zoom_length):
+ param_type = {"param": "type", "data": zoom_type, "type": "QbKey"}
+ param_time = {"param": "time", "data": zoom_length,
+ "type": "Integer" if type(zoom_length) == int else "Float"}
+ return param_type, param_time
- # binascii.hexlify(bytes("Intro Slow", "latin-1"), ' ', 1))
- # print(bytes("Intro Slow", "utf-8"))
- packname = f"songs/{filename}.mid.qb"
- for i, x in enumerate(QBItems):
- # print(x)
- x.processData(consoleType) # Convert data in classes to numbers for use
- sectionbytes = bytearray()
-
- # QB Item Header
- sectionbytes += toBytes(qbNodeHeaders["SectionArray"][consoleType])
- sectionbytes += toBytes(int(headerDict[x.name], 16)) # CRC of the header name
- sectionbytes += toBytes(int(QBKey(packname), 16)) # CRC of the mid.qb name (e.g. "songs\slowride.mid.qb")
-
- position = positionStart + len(sectionbytes)
- sectionbytes += toBytes(position + 8) # +8 to account for the next 8 bytes
- sectionbytes += toBytes(0) # Next Item = 0 for mid.qb
-
- sectionbytes += toBytes(x.qbType) # Add the hex value of the qb type
- if x.node == "ArrayInteger":
- sectionbytes += toBytes(x.itemcount)
- position = positionStart + len(sectionbytes)
- sectionbytes += toBytes(position + 4) # List starts 4 bytes after where the offset is defined
- for y in x.data:
- if isinstance(y, Note):
- sectionbytes += toBytes(y.time)
- sectionbytes += toBytes(y.length)
- sectionbytes += toBytes(int(y.binForm(), 2))
- else:
- sectionbytes += toBytes(y)
- elif x.node == "ArrayArray":
- sectionbytes += toBytes(x.itemcount)
- position = positionStart + len(sectionbytes)
- liststart = position + 4 # To cover the 4 bytes that point to the start of list
- sectionbytes += toBytes(liststart)
- firstitem = position + 4 + (x.itemcount * 4)
- # print(firstitem)
- for j, y in enumerate(x.arraydata): # Add all starts of array entries to the mid
- arraynodelength = 4 + 4 + 4 + (len(y) * 4)
- # print(arraynodelength)
- if len(x.arraydata) == 1:
- pass
- else:
- sectionbytes += toBytes(firstitem + (arraynodelength * j))
- # print(y)
- position = positionStart + len(sectionbytes)
- # print(len(x.arraydata))
- for y in x.arraydata:
- sectionbytes += toBytes(x.subarraytype)
- sectionbytes += toBytes(len(y))
- position = positionStart + len(sectionbytes) + 4
- sectionbytes += toBytes(position)
- for z in y:
- sectionbytes += toBytes(z)
- position = positionStart + len(sectionbytes)
- elif x.node == "ArrayStruct":
- sectionbytes += toBytes(x.itemcount)
- position = positionStart + len(sectionbytes)
- liststart = position + 4 # To cover the 4 bytes that point to the start of list
- sectionbytes += toBytes(liststart)
- # sectionbytes += toBytes(0) * x.itemcount
- # print(firstitem)
- if "markers" in x.name:
- offsets = []
- markerBytes = bytearray() # 4 for header_marker, 4 for "first item" in struct
- for y in x.arraydata:
- # Struct Header
- offsets.append(positionStart + len(sectionbytes) + 4 * x.itemcount + len(markerBytes))
- markerBytes += toBytes(qbNodeHeaders["StructHeader"][consoleType])
-
- # time
- position = positionStart + len(sectionbytes) + len(markerBytes) + 4 * x.itemcount
- markerBytes += toBytes(position + 4)
- markerBytes += toBytes(qbNodeHeaders["StructItemInteger"][consoleType])
- markerBytes += toBytes(int(QBKey("time"), 16))
- markerBytes += toBytes(y[0]) # Add the time of the marker
- position = positionStart + len(sectionbytes) + len(markerBytes) + 4 * x.itemcount
- markerBytes += toBytes(position + 4) # Position of next item
-
- # marker
- markerBytes += toBytes(qbNodeHeaders["StructItemStringW"][consoleType])
- markerBytes += toBytes(int(QBKey("marker"), 16))
- position = positionStart + len(sectionbytes) + len(markerBytes) + 4 * x.itemcount + 8
- markerBytes += toBytes(position)
- markerBytes += toBytes(0) # Next item is 0 as it's the final item in this struct
- markername = y[1]
- # print(markername, len(markername))
- markernamebytes = bytes(markername, "latin-1")
- for z in markernamebytes:
- markerBytes += toBytes(z, 2)
- markerBytes += toBytes(0, 2)
- if len(markername) % 2 == 0:
- markerBytes += toBytes(0, 2)
- for y in offsets:
- sectionbytes += toBytes(y)
- sectionbytes += markerBytes
- if "lightshow" in x.name:
- offsets = []
- lightshowBytes = bytearray()
- if len(x.arraydata) == 1:
- setattr(x, "itemcount",
- 0) # If only one blend event, it shuffles back the position of the following items
- for y in x.arraydata:
- # Struct Header
- offsets.append(positionStart + len(sectionbytes) + 4 * x.itemcount + len(lightshowBytes))
- lightshowBytes += toBytes(qbNodeHeaders["StructHeader"][consoleType])
-
- # Time
- position = positionStart + len(sectionbytes) + len(lightshowBytes) + 4 * x.itemcount
- lightshowBytes += toBytes(position + 4)
- lightshowBytes += toBytes(qbNodeHeaders["StructItemInteger"][consoleType])
- lightshowBytes += toBytes(int(QBKey("time"), 16))
- lightshowBytes += toBytes(y[0]) # Add the time of the lightshow event
- position = positionStart + len(sectionbytes) + len(lightshowBytes) + 4 * x.itemcount
- lightshowBytes += toBytes(position + 4) # Position of next item in struct
-
- # Event Type
- lightshowBytes += toBytes(qbNodeHeaders["StructItemQbKey"][consoleType])
- lightshowBytes += toBytes(int(QBKey("scr"), 16))
- lightshowBytes += toBytes(int(QBKey(y[1]), 16)) # Add blend time to struct
- position = positionStart + len(sectionbytes) + len(lightshowBytes) + 4 * x.itemcount
- lightshowBytes += toBytes(position + 4) # Position of next item in struct
-
- # Struct Item Struct - To feed the game the custom blend time
- lightshowBytes += toBytes(qbNodeHeaders["StructItemStruct"][consoleType])
- lightshowBytes += toBytes(int(QBKey("params"), 16)) # Tell the game to change the params
- position = positionStart + len(sectionbytes) + len(lightshowBytes) + 4 * x.itemcount + 8
- lightshowBytes += toBytes(position)
- lightshowBytes += toBytes(0) # Next item is 0 as it's the final item in this overall struct
- if y[1] == "LightShow_SetTime":
- lightshowBytes += toBytes(qbNodeHeaders["StructHeader"][consoleType])
- position = positionStart + len(sectionbytes) + len(lightshowBytes) + 4 * x.itemcount + 4
- lightshowBytes += toBytes(position)
- lightshowBytes += toBytes(qbNodeHeaders["StructItemFloat"][consoleType])
- lightshowBytes += toBytes(int(QBKey("time"), 16))
- lightshowBytes += struct.pack(">f", y[2]) # Pack in the float as bytes
- lightshowBytes += toBytes(0) # Next item is 0 as it's the final item in this internal struct
-
- if len(offsets) > 1:
- for y in offsets:
- # print(y)
- sectionbytes += toBytes(y)
-
- sectionbytes += lightshowBytes
-
- # position = positionStart + len(sectionbytes) + len(lightshowBytes) + 4 * x.itemcount + 8
-
- # print(offsets)
-
- elif x.node == "Floats":
- sectionbytes += toBytes(0)
- sectionbytes += toBytes(0)
- # print(position)
- # print(position)
- # print(x.name, x.itemcount)
- # Add the section to the overall bytearray
- qbbytes += sectionbytes
- positionStart = 28 + len(qbbytes)
-
- # print(positionStart)
-
- # print(binascii.hexlify(qbbytes, ' ', 1))
- # exit()
- filesize = len(qbbytes) + 28
- fullqb = bytearray()
- fullqb += toBytes(0) + toBytes(filesize) + qbFileHeader + qbbytes
-
- return fullqb
+def lightshow_script(x):
+ if type(x) == float or type(x) == int:
+ t = x
+ else:
+ t = x.text.split(" ")[1]
+ blendtime = {"param": "time", "data": float(t),
+ "type": "Float"} # Blend time is in seconds
+ return blendtime
+
+def drum_anim_note(x, active_notes, new_note, anim_notes, time_sec, args):
+ new_len = time_sec - active_notes[new_note].time
+ active_notes[new_note].setLength(new_len)
+ if active_notes[new_note].time in anim_notes["drum_anims"]:
+ anim_notes["drum_anims"][active_notes[new_note].time].append(
+ active_notes[new_note])
+ else:
+ anim_notes["drum_anims"][active_notes[new_note].time] = [active_notes[new_note]]
+ if x.note not in practice_mode_wt:
+ temp = anim_notes["drum_anims"][active_notes[new_note].time]
+ if "wor" in args:
+ if new_note < 22:
+ practice_note = new_note + 86
+ elif new_note < 105:
+ practice_note = new_note + 56
+ else:
+ active_notes.pop(new_note)
+ return
+ elif "gh3" in args:
+ if new_note < 47:
+ practice_note = new_note + 24
+ elif new_note < 59:
+ practice_note = new_note + 12
+ else:
+ active_notes.pop(new_note)
+ return
+ else:
+ practice_note = new_note - 13
+ if "gh3" in args:
+ temp.append(AnimNote(time_sec, practice_note))
+ else:
+ temp.append(AnimNoteWT(time_sec, practice_note, temp[-1].velocity))
+ temp[-1].setLength(new_len)
+ active_notes.pop(new_note)
+ return
def make_wt_drum_anims(midi_track, tempo_data):
@@ -1997,6 +2165,3 @@ def make_wt_qb(mid_file):
if track.name == "drums":
drum_anims = make_wt_drum_anims(track, tempo_data)
return
-
-
-
diff --git a/pak_extract/PAKExtract.py b/pak_extract/PAKExtract.py
index f730297..c2d9d7e 100644
--- a/pak_extract/PAKExtract.py
+++ b/pak_extract/PAKExtract.py
@@ -4,6 +4,7 @@
from dbg import checksum_dbg
from pak_functions import *
from CRC import QBKey
+from io import BytesIO
import os
import zlib
@@ -149,6 +150,55 @@ def main(pak, folder, endian = "big", wor_mode = 0, pak_header_size = 0, toolkit
return files
+def decompress_pab(comp, pak_file):
+ pak = BytesIO(pak_file)
+ del pak_file
+ last = 0x2CB3EF3B
+ files = []
+ uint32 = lambda x: int.from_bytes(x.read(4), 'big')
+ ext = uint32(pak)
+ while ext != last:
+ entry = {"extension": ext}
+ entry["offset"] = uint32(pak)
+ entry["length"] = uint32(pak)
+ entry["pak_key"] = uint32(pak)
+ entry["full_name"] = uint32(pak)
+ entry["name_sum"] = uint32(pak)
+ entry["parent"] = uint32(pak)
+ entry["flags"] = uint32(pak)
+ try:
+ entry["file_name"] = f"{checksum_dbg[entry['full_name']]}{checksum_dbg[entry['extension']]}"
+ entry["full_name"] = checksum_dbg[entry['full_name']]
+ entry['extension'] = checksum_dbg[entry['extension']]
+ except:
+ entry["file_name"] = f"{entry['full_name']}.{entry['name_sum']}.{entry['extension']}"
+ files.append(entry)
+ ext = uint32(pak)
+ pak.close()
+ comp = BytesIO(comp)
+ for entry in files:
+ comp_bytes = comp.read(entry["length"])
+ if entry["full_name"] == "SING_Adam_Dammit_100_01":
+ print()
+ if entry["flags"] == 512:
+ magic = str(comp_bytes[:4], encoding = "UTF-8")
+ if magic == "CHNK":
+ comp_bytes = comp_bytes[128:]
+ else:
+ raise Exception("Unknown magic value found. Contact me.")
+ file_bytes = zlib.decompress(comp_bytes, wbits=-15)
+ file_size = int.from_bytes(file_bytes[:4], "big")
+ #print()
+ elif entry["flags"] == 0:
+ file_size = int.from_bytes(comp_bytes[:4], "big")
+ file_bytes = comp_bytes[:file_size]
+ else:
+ raise Exception("Unknown Flag number found. Contact me.")
+ entry["file_bytes"] = file_bytes
+ #while magic == "CHNK":
+
+ return files
+
def decompress_pak(comp, endian = "big"):
comp = compressed_pak(comp, endian)
decomp_file = b''
@@ -185,9 +235,13 @@ def compress_pak(decomp):
return
-def check_decomp(pak_file, file_path = "", output_decomp = True):
- if pak_file[:4] == b'CHNK': # Check for xbox compressed file
- pak_file = decompress_pak(pak_file)
+def check_decomp(comp_file, file_path = "", output_decomp = True, pab = False, *args, **kwargs):
+ if comp_file[:4] == b'CHNK': # Check for xbox compressed file
+ if pab:
+ comp_file = decompress_pab(comp_file, kwargs["pak_file"])
+ return comp_file
+ else:
+ comp_file = decompress_pak(comp_file)
if output_decomp:
pak_decomp_out = f'.\\Decompressed PAKs\\{file_path}'
if not os.path.exists(pak_decomp_out):
@@ -197,8 +251,8 @@ def check_decomp(pak_file, file_path = "", output_decomp = True):
except:
pass
with open(pak_decomp_out, 'wb') as write_file:
- write_file.write(pak_file)
- return pak_file
+ write_file.write(comp_file)
+ return comp_file
def extract_paks():
pabs = []
@@ -232,15 +286,26 @@ def extract_paks():
header_size = 0
curr_file = os.path.basename(filepaths[y])
print(f"Processing {curr_file}")
+ with open(filepaths[y], 'rb') as f:
+ pak_file = f.read()
+ if pak_file[:4] == b'CHNK': # Check for WoR style PAK
+ pak_file = check_decomp(pak_file, curr_file,)
if x in pabs:
with open(filepaths_pab[pabs.index(x)], 'rb') as f:
- pab_file = check_decomp(f.read(), curr_file.replace(".pak.xen", ".pab.xen"))
+ pab_file = check_decomp(f.read(), curr_file.replace(".pak.xen", ".pab.xen"), False, True, pak_file= pak_file)
+ if type(pab_file) == list:
+ for z in pab_file:
+ output_file = f'.\\output\\PAK\\{x}\\{z["file_name"]}.xen'
+ dir_name = os.path.dirname(output_file)
+ try:
+ os.makedirs(dir_name)
+ except:
+ pass
+ with open(output_file, 'wb') as write_file:
+ write_file.write(z["file_bytes"])
+ continue
else:
pab_file = b''
- with open(filepaths[y], 'rb') as f:
- pak_file = f.read()
- if pak_file[:4] == b'CHNK': # Check for WoR style PAK
- pak_file = check_decomp(pak_file, curr_file)
first_file = int.from_bytes(pak_file[4:8], "big")
if first_file == 0:
wor_mode = 1
diff --git a/pak_extract/QB2Text.py b/pak_extract/QB2Text.py
index b3a0090..93a2701 100644
--- a/pak_extract/QB2Text.py
+++ b/pak_extract/QB2Text.py
@@ -1,12 +1,20 @@
from pak_definitions import *
from pak_functions import *
from pak_classes import *
+from io import StringIO
import os
import sys
orig_stdout = sys.stdout
-
+def print_to_var(text_qb):
+ result = StringIO()
+ orig_stdout = sys.stdout
+ sys.stdout = result
+ print_qb_text_file(text_qb)
+ sys.stdout = orig_stdout
+ qb_text = result.getvalue()
+ return qb_text
def convert_qb_file(qb_file, file_name, file_headers, console = "PC"):
endian = console_endian[console]
consoleType = console_lookup[console]
diff --git a/pak_extract/pak_definitions.py b/pak_extract/pak_definitions.py
index 6ec5a7f..182826b 100644
--- a/pak_extract/pak_definitions.py
+++ b/pak_extract/pak_definitions.py
@@ -112,7 +112,7 @@
others = ["_BossBattleP1", "_BossBattleP2", "_timesig", "_fretbars", "_markers",
"_scripts_notes", "_anim_notes", "_triggers_notes", "_cameras_notes", "_lightshow_notes", "_crowd_notes",
"_drums_notes", "_performance_notes", "_scripts", "_anim", "_triggers", "_cameras", "_lightshow", "_crowd",
- "_drums", "_performance"]
+ "_drums", "_performance", "_song_drums_expertplus"]
markers_wt = ["_guitar_markers", "_rhythm_markers", "_drum_markers"]
diff --git a/pak_extract/pak_functions.py b/pak_extract/pak_functions.py
index 3d027d4..ccc8cdd 100644
--- a/pak_extract/pak_functions.py
+++ b/pak_extract/pak_functions.py
@@ -20,9 +20,11 @@ def round_time(entry):
new_time = entry
elif time_trunc == 99:
new_time = entry + 1
- elif time_trunc < 33:
+ elif time_trunc == 1:
+ new_time = int(str(entry)[:-2] + "00")
+ elif time_trunc <= 34:
new_time = int(str(entry)[:-2] + str(33))
- elif time_trunc < 67:
+ elif time_trunc <= 68:
new_time = int(str(entry)[:-2] + str(67))
else:
new_time = int(str(entry)[:-2] + str(99)) + 1
@@ -511,7 +513,7 @@ def print_array_data(array_data, array_type, sub_array="", id_string="", indent=
for y, x in enumerate(array_data):
array_string += f"{output_item_data(x, array_type)}"
if y != len(array_data) - 1:
- array_string += ", "
+ array_string += " "
# print(f"{indent_val}{id_string}", f"= [{array_string}]")
return array_string + "]"
elif array_type.endswith("Array"):
@@ -526,12 +528,12 @@ def print_array_data(array_data, array_type, sub_array="", id_string="", indent=
print(f"{indent_val}\t\t" + "{")
for items in struct.data_value:
print_struct_item(items, indent + 3)
- print(f"{indent_val}\t\t" + "}" + f"{',' if s_count != len(array_data[y]) - 1 else ''}")
- print(f"{indent_val}\t]" + f"{',' if y != len(array_data) - 1 else ''}")
+ print(f"{indent_val}\t\t" + "}" + f"{'' if s_count != len(array_data[y]) - 1 else ''}")
+ print(f"{indent_val}\t]" + f"{'' if y != len(array_data) - 1 else ''}")
# raise Exception
else:
print(
- f"{print_array_data(x, sub_array[y], 1, '', indent + 1)}{',' if y != len(array_data) - 1 else ''}")
+ f"{print_array_data(x, sub_array[y], 1, '', indent + 1)}{'' if y != len(array_data) - 1 else ''}")
print(f"{indent_val}]")
elif array_type.endswith("Struct"):
"""if sub_array:
@@ -545,21 +547,21 @@ def print_array_data(array_data, array_type, sub_array="", id_string="", indent=
else:
for z in x.data_value:
print_struct_item(z, indent + 2)
- print(f"{indent_val}\t" + "}" + f"{',' if y != len(array_data) - 1 else ''}")
+ print(f"{indent_val}\t" + "}" + f"{'' if y != len(array_data) - 1 else ''}")
# raise Exception
print(f"{indent_val}]")
# raise Exception
elif len(array_data) > 3:
print(f"{indent_val}{id_string} = [")
for y, x in enumerate(array_data):
- print(f"{indent_val}\t{output_item_data(x, array_type)}{',' if y != len(array_data) - 1 else ''}")
+ print(f"{indent_val}\t{output_item_data(x, array_type)}{'' if y != len(array_data) - 1 else ''}")
print(f"{indent_val}]")
else:
array_string = ""
for y, x in enumerate(array_data):
array_string += f"{output_item_data(x, array_type)}"
if y != len(array_data) - 1:
- array_string += ", "
+ array_string += " "
print(f"{indent_val}{id_string}", f"= [{array_string}]")
return
@@ -713,11 +715,17 @@ def new_play_clip(time, clip, start, end = 0):
return play_clip
-def make_script_struct(script_data):
+def make_script_struct(script_data, to_round = True):
final_struct = struct_data()
- time = basic_data("time", round_time(script_data.time))
+ if to_round:
+ time = basic_data("time", round_time(script_data.time))
+ else:
+ time = basic_data("time", script_data.time)
time.set_type("Integer")
- time.set_bin_data(struct.pack(">i", round_time(script_data.time)))
+ if to_round:
+ time.set_bin_data(struct.pack(">i", round_time(script_data.time)))
+ else:
+ time.set_bin_data(struct.pack(">i", script_data.time))
scr = basic_data("scr", script_data.type)
scr.set_type("QbKey")
scr.set_bin_data(bytes.fromhex(CRC.QBKey(script_data.type)))
@@ -772,16 +780,16 @@ def new_band_clip_gh5(char_class):
return char_array
-def new_stance_gh3(time, name, stance):
- params_list = []
- params_list.append(struct_item("StructItemQbKey", "name", name, 0))
- params_list.append(struct_item("StructItemQbKey", "stance", stance, 0))
-
- time = struct_item("StructItemInteger", "time", time, 0)
- scr = struct_item("StructItemQbKey", "scr", "Band_ChangeStance", 0)
- params = struct_item("StructItemStruct", "params", params_list, 0)
-
- new_stance = struct_item("StructHeader", 0, [time, scr, params], 0)
+def new_stance_gh3(name, stance, anim_type, *args):
+ param_name = {"param": "name", "data": name, "type": "QbKey"}
+ param_stance = {"param": anim_type, "data": stance, "type": "QbKey"}
+ new_stance = [param_name, param_stance]
+ if "cycle" in args:
+ new_stance.append({"param": "no_id", "data": "cycle", "type": "QbKey"})
+ if "no_wait" in args:
+ new_stance.append({"param": "no_id", "data": "no_wait", "type": "QbKey"})
+ if "repeat" in args:
+ new_stance.append({"param": "repeat_count", "data": int(args[args.index("repeat")+1]), "type": "Integer"})
return new_stance
diff --git a/requirements/install_requirements.bat b/requirements/install_requirements.bat
index e3c029b..1f83b31 100644
--- a/requirements/install_requirements.bat
+++ b/requirements/install_requirements.bat
@@ -1,3 +1,5 @@
@echo off
-python -m pip install -r requirements.txt
\ No newline at end of file
+python -m pip install -r requirements.txt
+
+pause
\ No newline at end of file
diff --git a/ska_converter/read_ska.py b/ska_converter/read_ska.py
index 06cda1b..fa87b6c 100644
--- a/ska_converter/read_ska.py
+++ b/ska_converter/read_ska.py
@@ -141,6 +141,7 @@ def main(func, write = False, **kwargs):
out_dir = f"{root_folder}/out"
with os.scandir(directory) as songs:
for x in songs:
+ print(f"Processing {x}")
with open(x, 'rb') as f:
ska_orig = f.read()
ska_file = ska_bytes(ska_orig)
diff --git a/ska_converter/ska_classes.py b/ska_converter/ska_classes.py
index 39a2407..94a68c2 100644
--- a/ska_converter/ska_classes.py
+++ b/ska_converter/ska_classes.py
@@ -373,7 +373,23 @@ def read_custom_keys(self):
self.position = self.customkey_pos
custom_keys = []
for x in range(self.custom_keys):
- custom_keys.append([self.readFloat(), self.readBytes(), self.readBytes(), self.readFloat()])
+ curr_key = []
+ key_time = self.readFloat()
+ key_type = self.readBytes()
+ key_value = self.readBytes()
+ curr_key.append(key_time)
+ curr_key.append(key_type)
+ curr_key.append(key_value)
+ if key_type == 1:
+ key_mod = self.readFloat()
+ curr_key.append(key_mod)
+ elif key_type == 9:
+ pass
+ else:
+ raise Exception("Custom keys found in unsupported ska file. Contact me.")
+ custom_keys.append(curr_key)
+
+
return custom_keys
def read_pointer_block(self):
diff --git a/ska_converter/ska_functions.py b/ska_converter/ska_functions.py
index 3b7e539..892bed1 100644
--- a/ska_converter/ska_functions.py
+++ b/ska_converter/ska_functions.py
@@ -592,12 +592,26 @@ def make_modern_ska(ska, game = "GH5", *args, **kwargs):
total_size = len(quat_data) + len(trans_data) + len(block_sizes) + len(partial_anim) + len(custom_keys) + 256
quat_pos = 256
- custom_key_pos = (total_size - len(custom_keys)) if custom_keys else NO_OFF
- partial_anim_offset = (total_size - len(partial_anim)) if partial_anim else NO_OFF
+ to_move_back = 0
+ if custom_keys:
+ custom_key_pos = total_size
+ if partial_anim:
+ custom_key_pos -= len(partial_anim)
+ custom_key_pos -= len(custom_keys)
+ to_move_back += len(custom_keys)
+ else:
+ custom_key_pos = NO_OFF
+
+ if partial_anim:
+ partial_anim_offset = total_size - len(partial_anim)
+ to_move_back += len(partial_anim)
+ else:
+ partial_anim_offset = NO_OFF
+
if all([custom_key_pos == NO_OFF, partial_anim_offset == NO_OFF]):
bone_start = total_size
else:
- bone_start = custom_key_pos if partial_anim_offset == NO_OFF else partial_anim_offset
+ bone_start = total_size - to_move_back
if bone_pointers:
bonepointer_offset = total_size
bone_header = bytearray()
@@ -630,5 +644,5 @@ def make_modern_ska(ska, game = "GH5", *args, **kwargs):
for y in x:
header_bytes += struct.pack(">f", y)
header_bytes += b'\x00' * (256 - len(header_bytes))
- ska_file = header_bytes + quat_data + trans_data + block_sizes + partial_anim + custom_keys + bone_header + bone_pointers
+ ska_file = header_bytes + quat_data + trans_data + block_sizes + custom_keys + partial_anim + bone_header + bone_pointers
return ska_file
diff --git a/toolkit_functions.py b/toolkit_functions.py
index ca53b93..2952d0e 100644
--- a/toolkit_functions.py
+++ b/toolkit_functions.py
@@ -228,7 +228,7 @@ def add_to_dict(p_dict, t, entry):
return
-def convert_to_gh3(pakmid, output=f'{os.getcwd()}', singer=lipsync_dict["gh3_singer"]):
+def convert_to_gh3(pakmid, output=f'{os.getcwd()}', singer="gh3_singer"):
if not "_song.pak" in pakmid:
warning = input(
"WARNING: File does not appear to be a validly named mid PAK file. Do you want to continue? (Y/N): ")
@@ -405,11 +405,10 @@ def convert_to_gh3(pakmid, output=f'{os.getcwd()}', singer=lipsync_dict["gh3_sin
song_pak = mid_qb.pakMaker(gh3_array)
# raise Exception
-
return song_name, song_pak
-def convert_to_gha(pakmid, output=f'{os.getcwd()}', singer=lipsync_dict["gha_singer"]):
+def convert_to_gha(pakmid, output=f'{os.getcwd()}', singer="gha_singer"):
if "_song.pak" in pakmid:
song_name = pakmid[len(os.path.dirname(pakmid)) + 1:pakmid.find("_song")]
elif ".mid" in pakmid:
@@ -507,7 +506,7 @@ def convert_to_gha(pakmid, output=f'{os.getcwd()}', singer=lipsync_dict["gha_sin
if re.search("[0-9][bB]\.ska", x['file_name'].lower()):
# raise Exception
- x["file_data"] = make_gh3_ska(ska_bytes(x["file_data"]), ska_switch=lipsync_dict["gha_guitarist"],
+ x["file_data"] = make_gh3_ska(ska_bytes(x["file_data"]), ska_switch="gha_guitarist",
quats_mult=2)
else:
x["file_data"] = make_gh3_ska(ska_bytes(x["file_data"]), ska_switch=singer, quats_mult=2)
@@ -1377,7 +1376,7 @@ def convert_to_5(pakmid, new_name, *args, **kwargs):
if "vocals_note_range" in x:
continue
temp_sections[x] = y
- override_sections = mid_qb.create_wt_qb(temp_sections, song_name)
+ override_sections = mid_qb.create_game_qb(temp_sections, song_name)
override_sections = QB2Text.convert_qb_file(QB2Text.qb_bytes(override_sections), song_name,
file_headers)
del (temp_sections)
@@ -2583,7 +2582,7 @@ def rename_track(avatar):
return track
-def read_gh3_note(sections_dict, tempo_data, tpb, game="GH3"):
+def read_gh3_note(sections_dict, tempo_data, tpb, game="GH3", *args):
if game == "GH3":
gtr_anims = range(117, 128)
bass_anims = range(100, 111)
@@ -2657,6 +2656,7 @@ def read_gh3_note(sections_dict, tempo_data, tpb, game="GH3"):
"anim": [],
"triggers": [],
"cameras": [],
+ "cameras_wt": [],
"lightshow": [],
"crowd": [],
"drums": [],
@@ -2794,8 +2794,10 @@ def read_gh3_note(sections_dict, tempo_data, tpb, game="GH3"):
note_val -= 1 if note_val != 40 else 0
note_charts[track].append({"time": t_sec, "length": length, "note": note_val})
continue
- # if misc_type == "drum":
-
+ if misc_type == "cameras":
+ if "gha" not in args:
+ misc_charts["cameras_wt"].append({"time": t_sec, "length": length, "note": gh3_to_wt[note_val]})
+ #print()
misc_note.append({"time": t_sec, "length": length, "note": note_val})
misc_charts[misc_type] += misc_note.copy()
elif re.search(r"(lightshow)", misc_type, flags=re.IGNORECASE):
@@ -2940,7 +2942,7 @@ def read_gh3_note(sections_dict, tempo_data, tpb, game="GH3"):
return mid
-def read_gh5_note(note_bin, drum_mode=False):
+def read_gh5_note(note_bin, drum_mode=False, *args):
note_file = BytesIO(note_bin)
read_int = lambda a=4, note=note_file: int.from_bytes(note.read(a), "big")
dbg = lambda check: PAKExtract.pull_dbg_name(check)
@@ -3010,21 +3012,50 @@ def read_gh5_note(note_bin, drum_mode=False):
base_notes = drum_base_notes
else:
base_notes = other_base_notes
+ if "raw" in args:
+ note_file_dict[entry_id] = {
+ "normal": [],
+ "xplus": []
+ }
for entry in range(entry_count):
entry_time = read_int()
entry_length = read_int(2)
drum_note = read_int(1)
drum_accent = read_int(1)
+ drum_ghost = 0
if entry_type == "gh6_expert_drum_note":
drum_ghost = read_int(1)
+ if "raw" in args:
+ len_bin = bin(entry_length)[2:].zfill(16)
+ acc_bin = bin(drum_accent)[2:].zfill(9)
+ if "drum" in entry_id:
+ if drum_ghost:
+ drum_note += drum_ghost
+ norm_bin = bin(drum_note)[2:].zfill(7)
+ xplus_bin = norm_bin
+ if drum_note & 1 << 6 and drum_note & 1 << 5: # 2x note
+ norm_bin = bin(drum_note)[3:].zfill(7)
+ xplus_bin = norm_bin
+ elif drum_note & 1 << 6:
+ norm_bin = bin(drum_note)[3:].zfill(7)
+ xplus_bin = f"1{bin(drum_note)[4:]}".zfill(7)
+
+ if int(norm_bin, 2):
+ note_file_dict[entry_id]["normal"].extend([entry_time, int(acc_bin+norm_bin+len_bin,2)])
+
+ if diff == "expert":
+ note_file_dict[entry_id]["xplus"].extend(
+ [entry_time, int(acc_bin + xplus_bin + len_bin, 2)])
+ else:
+ norm_bin = bin(drum_note)[2:].zfill(7)
+ note_file_dict[entry_id]["normal"].extend([entry_time, int(acc_bin + norm_bin + len_bin, 2)])
+ else:
entry_note = set_note_type(drum_note, drum_accent, drum_ghost)
- else:
- entry_note = set_note_type(drum_note, drum_accent)
- for note in entry_note:
- note_file_dict[entry_id].append({"time": entry_time, "length": entry_length,
- "note": base_notes[note["colour"]] + (12 * note_mult[entry_diff]),
- "velocity": note["velocity"]})
+ for note in entry_note:
+ note_file_dict[entry_id].append({"time": entry_time, "length": entry_length,
+ "note": base_notes[note["colour"]] + (12 * note_mult[entry_diff]),
+ "velocity": note["velocity"]})
elif entry_type == "gh5_band_moment_note":
for entry in range(entry_count):
entry_time = read_int()
@@ -3244,7 +3275,403 @@ def gh5_to_midi(notes, tempo_data, tpb, vox=False, anim=False, drums=False):
return temp_tracks
+def perf_override_check(perf_override, to_add):
+ if perf_override:
+ perf_override += f",\n {to_add}"
+ else:
+ perf_override = to_add
+ return perf_override
+
+def convert_5_to_wt(pakmid, perf_override = "", *args):
+ ska_override = []
+ song_name = pakmid[len(os.path.dirname(pakmid)) + 1:pakmid.lower().find("_s")].lower()
+ if re.search(r'^[a-c]dlc', song_name, flags=re.IGNORECASE):
+ song_name = song_name[1:]
+ qb_sections, file_headers, file_headers_hex, song_files = pak2mid(pakmid, song_name)
+ sections_dict = get_section_dict(qb_sections, file_headers_hex)
+ game_check = ''.join(x for x in sections_dict.keys())
+ if perf_override:
+ with open(perf_override) as f:
+ perf_override = "\n".join(f.read().split("\n")[1:-1])
+ if not re.search(rf"{song_name}_song_easy", game_check, flags=re.IGNORECASE):
+ pass
+ else:
+ print("Not a valid GH5+ file.")
+ return
+ playable_qb = {
+ "Guitar": {},
+ "Bass": {},
+ "Drums": {},
+ "Vocals": {
+ "song_vocals": [],
+ "vocals_freeform": [],
+ "vocals_phrases": [],
+ "vocals_note_range": [60, 60],
+ "lyrics": [],
+ "vocals_markers": [],
+ "qs_file": {}
+ }
+ }
+
+ playable_face_off = {
+ "Guitar": {"P1": [], "P2": []},
+ "Bass": {"P1": [], "P2": []},
+ "Drums": {"P1": [], "P2": []}
+ }
+
+ playable_fo_star_power = {
+ "Guitar": {},
+ "Bass": {},
+ "Drums": {}
+ }
+
+ playable_star_power = {
+ "Guitar": {},
+ "Bass": {},
+ "Drums": {}
+ }
+ playable_bm_star_power = {
+ "Guitar": {},
+ "Bass": {},
+ "Drums": {}
+ }
+
+ playable_tap = {
+ "Guitar": [],
+ "Bass": []
+ }
+
+ playable_solo_markers = {
+ "Guitar": [],
+ "Bass": [],
+ "Drums": []
+ }
+
+ playable_drum_fills = []
+ anim_notes = {
+ "scripts_notes": {},
+ "left_hand": {},
+ "triggers_notes": {},
+ "CAMERAS": {},
+ "LIGHTSHOW": {},
+ "CROWD": {},
+ "drum_anims": {},
+ "scripts": {},
+ "anim": {},
+ "triggers": {},
+ "cameras": [],
+ "lightshow": [],
+ "crowd": {},
+ "drums": {},
+ "performance": []
+ }
+ band_clips = []
+ instruments = 0
+ perf_clips = 0
+ use_cams = 0
+ pull_struct = 0
+ struct_string = ""
+ anim_structs = []
+ anim_loops = []
+ qs_dict = 0
+ lyrics_qs = []
+ lyrics_qs_dict = {}
+ gtr_markers = []
+ xplus = 0
+ new_perf = ""
+ for files in song_files:
+ if re.search(fr"songs/{song_name}\.mid.qb$", files["file_name"], flags=re.IGNORECASE):
+ qb_mid_file = QB2Text.convert_qb_file(QB2Text.qb_bytes(files["file_data"]), song_name, file_headers)
+ qb_mid_text = QB2Text.print_to_var(qb_mid_file)
+ qb_mid_nohead = "\n".join(qb_mid_text.split("\n")[1:])
+ lip_events_loc = qb_mid_nohead.find(f"{song_name}_facial")
+ lip_events_end = qb_mid_nohead.find("]", lip_events_loc)
+ lip_events = "\n".join(qb_mid_nohead[lip_events_loc:lip_events_end].strip().split("\n")[1:])
+ perf_override = perf_override_check(perf_override, lip_events)
+ if re.search(fr"songs/{song_name}\.mid\.qs.en$", files["file_name"], flags=re.IGNORECASE):
+ qs_dict = get_qs_strings(files["file_data"])
+ elif re.search(fr"songs/{song_name}\.note$", files["file_name"], flags=re.IGNORECASE):
+ instruments = read_gh5_note(files["file_data"], False, "raw")
+ elif re.search(fr"songs/{song_name}\.perf$", files["file_name"], flags=re.IGNORECASE):
+ cameras, anim_structs = read_gh5_perf(files["file_data"], song_name)
+ use_cams = 1
+ pull_struct = 1
+ elif re.search(fr"songs/{song_name}\.perf.xml.qb$", files["file_name"], flags=re.IGNORECASE):
+ perf_xml_file = QB2Text.convert_qb_file(QB2Text.qb_bytes(files["file_data"]), song_name, file_headers)
+ for x in perf_xml_file:
+ if x.section_id.endswith("scriptevents"):
+ for y in x.section_data:
+ if y.data_dict["scr"] == "Band_PlayClip":
+ clip_params = y.data_dict["params"]
+ clip_len = round((clip_params["endframe"] - clip_params["startframe"]) / 30 / clip_params[
+ "timefactor"] * 1000)
+ band_clips.append(
+ [clip_params["clip"], y.data_dict["time"], clip_len + y.data_dict["time"]])
+ elif y.data_dict["scr"] == "Band_PlayLoop":
+ anim_loops.append({"text": y.data_dict["params"]["name"], "time": y.data_dict["time"]})
+ perf_xml_text = QB2Text.print_to_var(perf_xml_file)
+ perf_xml_nohead = "\n".join(perf_xml_text.split("\n")[1:]).strip()
+ perf_events_loc = perf_xml_nohead.find(f"{song_name}_scriptevents")
+ perf_clips = perf_xml_nohead[:perf_events_loc]
+ perf_events = "\n".join(perf_xml_nohead[perf_events_loc:].split("\n")[1:-1])
+ if perf_events.endswith("]"):
+ perf_events = perf_events[:-1]
+ perf_override = perf_override_check(perf_override, perf_events)
+ elif re.search(r".ska$", files["file_name"], flags=re.IGNORECASE):
+ wt_ska = make_modern_ska(ska_bytes(files["file_data"]),"GHWT", quats_mult=1, ska_switch = "wt_rocker")
+ #wt_ska = files["file_data"]
+ ska_override.append([wt_ska, files["file_name"]])
+ if perf_override:
+ perf_override = f"song_performance = [\n{perf_override}\n]"
+ fretbars = instruments["fretbar"]
+ instruments.pop("fretbar")
+ timesigs = [mid_qb.timeSigEvent(x[0],x[1],x[2]) for x in instruments["timesig"]]
+ instruments.pop("timesig")
+ temp_phrase = []
+ temp_freeform = []
+ to_pop = []
+ for k, v in instruments.items():
+ key_name = k
+ reg = re.search(r'^(drums|bass|guitar)', key_name)
+ if reg:
+ play = reg[0].title()
+ key_name = key_name[len(play):]
+ type_reg = re.search(r'(starpower|tapping|instrument|markers)$', key_name)[0]
+ key_name = key_name[:-len(type_reg)].title()
+ if type_reg == "markers":
+ gtr_markers = []
+ for x in v:
+ marker = qs_dict[int(x["text"], 16)]
+ if marker.startswith("\\u[m]"):
+ marker = marker[5:]
+ gtr_markers.append(mid_qb.markerNode(x["time"], marker))
+ elif type_reg == "instrument":
+ new_chart = mid_qb.NoteChart(play, key_name)
+ new_chart.notes = v["normal"]
+ if v["normal"] != v["xplus"] and play == "Drums" and key_name == "Expert":
+ xplus = mid_qb.NoteChart(play, key_name)
+ xplus.notes = v["xplus"]
+
+ playable_qb[play][key_name] = new_chart
+ elif type_reg == "starpower":
+ playable_star_power[play][key_name] = [[x["time"], x["length"]] for x in v]
+ else:
+ if v and key_name == "Expert":
+ playable_tap[play] = [[x["time"], x["length"], 1] for x in v]
+ to_pop.append(k)
+ continue
+ reg = re.search(r'(drumfill)', key_name)
+ if reg:
+ to_pop.append(k)
+ if "expert" in k:
+ playable_drum_fills.extend([[x["time"], x["time"]+x["length"]] for x in v])
+ continue
+ reg = re.search(r'(vocal)', key_name)
+ if reg:
+ curr = playable_qb["Vocals"]
+ #to_pop.append(k)
+ if k == "vocals":
+ low = 128
+ high = 0
+ for vox in v:
+ if vox["note"] > 27:
+ low = min(vox["note"], low)
+ high = max(vox["note"], high)
+ curr["song_vocals"].extend([vox["time"],vox["length"],vox["note"]])
+ curr["vocals_note_range"] = [low, high]
+ elif "freeform" in k:
+ for vox in v:
+ temp_freeform.append(vox["time"])
+ curr["vocals_freeform"].append([vox["time"], vox["length"], round(vox["length"]/6)])
+ elif "lyrics" in k:
+ split_word = 0
+ for vox in v:
+ raw_text = vox['text']
+ if split_word:
+ split_word = 0
+ raw_text = "=" + raw_text
+ if raw_text.endswith("-"):
+ split_word = 1
+ raw_text = raw_text[:-1]
+ elif raw_text.endswith("="):
+ split_word = 1
+ raw_text = raw_text[:-1] + "-"
+ lyric = f"\\L{raw_text}"
+ if lyric not in lyrics_qs:
+ lyrics_qs.append(lyric)
+ curr["lyrics"].append(mid_qb.markerNode(vox["time"], f"qbs(0x{CRC.QBKey_qs(lyric)})"))
+
+ for vox in instruments["vocalsmarkers"]:
+ raw_text = vox['text']
+ if not raw_text:
+ if vox["time"] in temp_freeform:
+ playable_qb["Vocals"]["vocals_markers"].append(mid_qb.markerNode(vox["time"], f"$vocal_marker_freeform"))
+ continue
+ lyric = f"\\L{raw_text}"
+ if lyric not in lyrics_qs:
+ lyrics_qs.append(lyric)
+ temp_phrase.append(vox["time"])
+ playable_qb["Vocals"]["vocals_markers"].append(mid_qb.markerNode(vox["time"], f"qbs(0x{CRC.QBKey_qs(lyric)})"))
+
+ for lyrics in sorted(lyrics_qs):
+ playable_qb["Vocals"]["qs_file"][lyrics] = CRC.QBKey_qs(lyrics)
+
+ lyric_time = np.array(playable_qb["Vocals"]["song_vocals"][::3])
+ phrase_time = []
+ for enum, phrase in enumerate(instruments["vocalphrase"]):
+ if enum != 0:
+ phrase_time.append(phrase["time"])
+ phrase_time.append(phrase["time"])
+ if enum == len(instruments["vocalphrase"]) - 1:
+ if phrase["time"] <= lyric_time[-1]:
+ phrase_time.append(lyric_time[-1]+60)
+ else:
+ phrase_time.append(phrase["time"]+1)
+ phrase_mod = mid_qb.split_list(phrase_time)
+ player = 0
+ for times in phrase_mod:
+ phrase_check = mid_qb.mod_notes(lyric_time, times)[0]
+ phrase_to = 0
+ if len(phrase_check) > 0:
+ phrase_to = (player % 2) + 1
+ player += 1
+ elif times[0] in temp_freeform:
+ phrase_to = 3
+ playable_qb["Vocals"]["vocals_phrases"].extend([times[0], phrase_to])
+
+ for x in to_pop:
+ instruments.pop(x)
+ # Calculate Star Power notes!
+ for inst, v in playable_star_power.items():
+ inst_play = playable_qb[inst]
+ for diff, val in inst_play.items():
+ diff_time = np.array(val.notes[::2])
+ if diff == "Expert":
+ playable_face_off[inst]["P1"] = playable_face_off[inst]["P2"] = [int(diff_time[0]-50), int(diff_time[-1]-diff_time[0]+50)]
+ diff_split = v[diff]
+ for starpower in diff_split:
+ star_list = [starpower[0],starpower[0] + starpower[1]]
+ notes = mid_qb.mod_notes(diff_time, star_list)[0]
+ starpower.append(len(notes))
+ for x in qb_sections:
+ if x.array_node_type == "Floats":
+ continue
+ elif x.section_id.endswith("_notes"):
+ if "anim" in x.section_id:
+ to_add = "left_hand"
+ elif "drums" in x.section_id:
+ to_add = "drum_anims"
+ elif "crowd" in x.section_id:
+ to_add = "CROWD"
+ elif "lightshow" in x.section_id:
+ to_add = "LIGHTSHOW"
+ elif "cameras" in x.section_id:
+ continue
+ else:
+ input(f"Unknown track {x.section_id} found. Enter to continue.")
+ continue
+ anim_time = x.section_data[::2]
+ anim_event = x.section_data[1::2]
+ drum_count = ""
+ for t, e in zip(anim_time, anim_event):
+ e_bin = bin(e)[2:].zfill(32)
+ e_len = int(e_bin[16:], 2)
+ e_note = int(e_bin[8:16], 2)
+ e_vel = int(e_bin[:8], 2)
+ if "drums" in x.section_id:
+ if e_note <= 59:
+ e_note = mid_qb.drumKeyMapRB_wt[mid_qb.wor_to_rb_drums[e_note]]
+ e_prac = mid_qb.AnimNoteWT(t, e_note-13, e_vel, e_len)
+ if t in anim_notes[to_add]:
+ anim_notes[to_add][t].append(e_prac)
+ else:
+ anim_notes[to_add][t] = [e_prac]
+ elif e_note in range(108,114):
+ e_prac = mid_qb.AnimNoteWT(t, 70, e_vel, e_len)
+ if e_note in range(108,111):
+ e_note = 83
+ else:
+ e_note = 78
+ if not drum_count:
+ if e_note == 83:
+ drum_count = f"Sticks"
+ else:
+ drum_count = f"Hihat"
+ print(drum_count)
+ if t in anim_notes[to_add]:
+ anim_notes[to_add][t].append(e_prac)
+ else:
+ anim_notes[to_add][t] = [e_prac]
+ elif e_note in range(60,84):
+ pass
+ else:
+ continue
+ e_anim = mid_qb.AnimNoteWT(t, e_note, e_vel, e_len)
+ if t in anim_notes[to_add]:
+ anim_notes[to_add][t].append(e_anim)
+ else:
+ anim_notes[to_add][t] = [e_anim]
+ elif "lightshow" in x.section_id:
+ for y in x.section_data:
+ blendtime = mid_qb.lightshow_script(y.data_dict['params']['time'])
+ anim_notes["lightshow"].append(mid_qb.scriptsNode(y.data_dict['time'], "LightShow_SetTime", [blendtime]))
+
+ for cams in cameras["momentcameras"]:
+ anim_notes["CAMERAS"][cams["time"]] = [mid_qb.AnimNoteWT(cams["time"], cams["note"], 100, cams["length"])]
+ for cams in cameras["autocutcameras"]:
+ if not cams["time"] in anim_notes["CAMERAS"]:
+ anim_notes["CAMERAS"][cams["time"]] = [mid_qb.AnimNoteWT(cams["time"], cams["note"], 100, cams["length"])]
+ anim_notes["CAMERAS"] = dict(sorted(anim_notes["CAMERAS"].items()))
+
+ playable_bm_star_power = playable_fo_star_power = playable_star_power
+ qb_dict = {"playable_qb": playable_qb, "star_power": playable_star_power, "bm_star_power": playable_bm_star_power,
+ "tap": playable_tap, "fo_star_power": playable_fo_star_power, "face_off": playable_face_off,
+ "gtr_markers": gtr_markers, "drum_fills": playable_drum_fills, "anim": anim_notes, "timesigs": timesigs,
+ "fretbars": fretbars, "vox_sp": 0, "ghost_notes": 0,
+ "solo_markers": playable_solo_markers,
+ "has_2x_kick": 0, "xplus": xplus
+ }
+ compile_args = []
+ if perf_override:
+ compile_args.extend(["replace_perf", perf_override])
+ if anim_structs['type'] == "gh6":
+ with open(f"{root_folder}\\conversion_files\\basic_loops.txt", "r") as f:
+ scripts_override = f.read()
+ if perf_clips:
+ scripts_override += f"\n{perf_clips}"
+ gh6_anims = []
+ for gen in ["male", "female"]:
+ for k, v in anim_structs[f"car_{gen}_anim_struct_{song_name}"].items():
+ for loops in v:
+ if loops not in gh6_anims:
+ gh6_anims.append(loops)
+ compile_args.extend(["add_loops", gh6_anims])
+ else:
+ anim_structs.pop("type")
+ for x in anim_structs.keys():
+ struct_string += f"{x}" + " = {\n"
+ for structs in anim_structs[x].keys():
+ struct_string += "\t" + f"{structs}" + " = {\n"
+ for anims in anim_structs[x][structs].keys():
+ struct_string += "\t\t" + f"{anims}" + f" = {anim_structs[x][structs][anims]}" + "\n"
+ struct_string += "\t}\n"
+ struct_string += "}\n"
+ scripts_override = struct_string
+ if perf_clips:
+ scripts_override += perf_clips
+
+ if scripts_override:
+ compile_args.extend(["song_script", scripts_override])
+ if ska_override:
+ compile_args.extend(["add_ska", ska_override])
+
+ compile_args.extend(["ghwt", "wtde"])
+ midQB, midQS = mid_qb.make_wt_files(file_headers, qb_dict, song_name, *compile_args)
+ if "performance" in qb_dict:
+ midQB = mid_qb.add_perf_to_qb(midQB, song_name, file_headers, qb_dict, *compile_args)
+ wt_pak = mid_qb.create_pak_file(midQB, song_name, midQS, *compile_args)
+ return wt_pak
def create_mid_from_qb(pakmid):
song_name = pakmid[len(os.path.dirname(pakmid)) + 1:pakmid.lower().find("_s")].lower()
if re.search(r'^[a-c]dlc', song_name, flags=re.IGNORECASE):
@@ -3253,11 +3680,16 @@ def create_mid_from_qb(pakmid):
sections_dict = get_section_dict(qb_sections, file_headers_hex)
game_check = ''.join(x for x in sections_dict.keys())
gh3 = False
+ gha = False
ghwt = False
if not re.search(rf"{song_name}_song_easy", game_check, flags=re.IGNORECASE):
print("GH5+ song found")
elif not re.search(rf"{song_name}_drum_easy", game_check, flags=re.IGNORECASE):
- print("GH3 song found")
+ if re.search(r"_song_aux", game_check, flags=re.IGNORECASE):
+ gha = True
+ print("GHA song found")
+ else:
+ print("GH3 song found")
gh3 = True
else:
print("GHWT song found")
@@ -3268,12 +3700,16 @@ def create_mid_from_qb(pakmid):
pull_struct = 0
struct_string = ""
anim_structs = []
+ anim_loops = []
+ qs_dict = 0
for files in song_files:
if re.search(fr"songs/{song_name}\.mid\.qs$", files["file_name"], flags=re.IGNORECASE):
qs_dict = get_qs_strings(files["file_data"])
note_file, qb_file, qs_file, cameras, marker_names = wt_to_5_file(sections_dict, qs_dict, song_name,
convert="")
instruments = read_gh5_note(convert_to_gh5_bin(note_file, "note", song_name))
+ elif re.search(fr"songs/{song_name}\.mid\.qs.en$", files["file_name"], flags=re.IGNORECASE):
+ qs_dict = get_qs_strings(files["file_data"])
elif re.search(fr"songs/{song_name}\.note$", files["file_name"], flags=re.IGNORECASE):
instruments = read_gh5_note(files["file_data"])
elif re.search(fr"songs/{song_name}\.perf$", files["file_name"], flags=re.IGNORECASE):
@@ -3289,6 +3725,8 @@ def create_mid_from_qb(pakmid):
clip_params = y.data_dict["params"]
clip_len = round((clip_params["endframe"] - clip_params["startframe"]) / 30 / clip_params["timefactor"] * 1000)
band_clips.append([clip_params["clip"],y.data_dict["time"], clip_len+y.data_dict["time"]])
+ elif y.data_dict["scr"] == "Band_PlayLoop":
+ anim_loops.append({"text": y.data_dict["params"]["name"], "time": y.data_dict["time"]})
#print()
try:
timesig = sections_dict[f"{song_name}_timesig"].section_data
@@ -3341,7 +3779,10 @@ def create_mid_from_qb(pakmid):
tempo_data.set_seconds_array(np.array(tempo_data.songSeconds))
if gh3:
- new_mid.tracks += read_gh3_note(sections_dict, tempo_data, tpb)
+ extra_args = []
+ if gha:
+ extra_args.append("gha")
+ new_mid.tracks += read_gh3_note(sections_dict, tempo_data, tpb, "GH3", *extra_args)
return new_mid, struct_string
"""elif ghwt:
new_mid.tracks += read_gh3_note(sections_dict, tempo_data, tpb, "GHWT")"""
@@ -3351,6 +3792,7 @@ def create_mid_from_qb(pakmid):
gtr_events = {"name": "PART GUITAR"}
bass_events = {"name": "PART BASS"}
vox_events = {"name": "PART VOCALS"}
+ event_markers = {"name": "EVENTS"}
to_pop = []
if instruments:
@@ -3367,6 +3809,17 @@ def create_mid_from_qb(pakmid):
elif "vocal" in x and not "marker" in x:
vox_events[x] = instruments[x]
to_pop.append(x)
+ elif "guitarmarker" in x:
+ event_markers[x] = instruments[x]
+ for marker in event_markers[x]:
+ qs_entry = int(marker["text"],16)
+ if qs_entry in qs_dict:
+ marker_text = qs_dict[qs_entry]
+ if "ENDOFSONG" in marker_text:
+ marker_text = "[end]"
+ elif marker_text.startswith("\\u[m]"):
+ marker_text = f"[section {marker_text[5:]}]"
+ marker["text"] = marker_text
for x in to_pop:
instruments.pop(x)
for inst in [drum_events, gtr_events, bass_events, vox_events]:
@@ -3384,8 +3837,13 @@ def create_mid_from_qb(pakmid):
all_tracks.append(mido.merge_tracks(gh5_to_midi(inst[track], tempo_data, tpb)))
elif "vocal" in track:
all_tracks.append(mido.merge_tracks(gh5_to_midi(inst[track], tempo_data, tpb, vox=True)))
- new_mid.tracks[-1] = mido.merge_tracks(all_tracks)
+ new_mid.tracks[-1] = mido.merge_tracks(all_tracks)
+ new_mid.add_track(event_markers["name"])
+ if "guitarmarkers" in event_markers:
+ events = gh5_to_midi(event_markers["guitarmarkers"], tempo_data, tpb)
+ new_mid.tracks[-1] = mido.merge_tracks([new_mid.tracks[-1]] + events)
+ print()
non_play = ["scripts", "anim", "triggers", "cameras", "lightshow", "crowd", "drums"]
for x in non_play:
try:
@@ -3482,6 +3940,9 @@ def create_mid_from_qb(pakmid):
band_midi[-1].append(Message("note_on", time=timeVal, note=clip_note, velocity=100))
band_midi[-1].append(Message("note_on", time=timeVal2, note=clip_note, velocity=0))
+ if anim_loops:
+ anim_events = gh5_to_midi(anim_loops, tempo_data, tpb)
+ band_midi.extend(anim_events)
band_midi = mido.merge_tracks(band_midi)
band_midi.name = "Band_Clips"
new_mid.tracks.append(band_midi)
diff --git a/toolkit_variables.py b/toolkit_variables.py
index 96ff2fb..50f1cc1 100644
--- a/toolkit_variables.py
+++ b/toolkit_variables.py
@@ -138,6 +138,50 @@
91: 117,
}
+gh3_to_wt = {
+ 117: 34,
+ 116: 8,
+ 115: 18,
+ 114: 74,
+ 113: 46,
+ 112: 45,
+ 111: 45,
+ 110: 31,
+ 109: 41,
+ 108: 41,
+ 107: 40,
+ 106: 40,
+ 105: 40,
+ 104: 13,
+ 103: 14,
+ 102: 58,
+ 101: 57,
+ 100: 64,
+ 99: 63,
+ 98: 14,
+ 97: 20,
+ 96: 15,
+ 95: 8,
+ 94: 75,
+ 93: 74,
+ 92: 75,
+ 91: 74,
+ 90: 33,
+ 89: 25,
+ 88: 15,
+ 87: 31,
+ 86: 8,
+ 85: 29,
+ 84: 11,
+ 83: 45,
+ 82: 74,
+ 81: 33,
+ 79: 38,
+ 78: 1,
+ 77: 0
+}
+gha_to_wt = {}
+
anim_struct = {
"guitar": {},
"bass": {},