too much edit to describe it

This commit is contained in:
raphael60650 2021-05-15 21:04:17 +02:00
parent dd0fc5b768
commit cc6de3db07
2 changed files with 185 additions and 37 deletions

Binary file not shown.

202
main.pyw
View file

@ -6,6 +6,10 @@ import shutil
from threading import Thread from threading import Thread
from PIL import Image, ImageTk, ImageDraw, ImageFont from PIL import Image, ImageTk, ImageDraw, ImageFont
import json import json
import unidecode
import hashlib
sha1 = lambda x: hashlib.sha1(x.encode()).hexdigest()
track2ID = { track2ID = {
"Circuit Luigi (slot 1.1)": [0x75, 0x08], "Circuit Luigi (slot 1.1)": [0x75, 0x08],
@ -62,6 +66,9 @@ track2ID = {
"Colisée Galactique": [0xC9, 0x36], "Colisée Galactique": [0xC9, 0x36],
} }
IDm2track = {v[0]: k for k, v in track2ID.items()}
IDs2track = {v[1]: k for k, v in track2ID.items()}
SCORE_ENABLED = True
class main(): class main():
def __init__(self): def __init__(self):
@ -515,19 +522,23 @@ class main():
entry_CourseName = Entry(tl, width=50) entry_CourseName = Entry(tl, width=50)
entry_CourseName.grid(row=4, column=1, sticky="NEWS", columnspan=2) entry_CourseName.grid(row=4, column=1, sticky="NEWS", columnspan=2)
Label(tl, text="Musique de la course :").grid(row=5, column=1, columnspan=2) Label(tl, text="Autheur de la course :").grid(row=5, column=1, columnspan=2)
entry_CourseAuthor = Entry(tl, width=50)
entry_CourseAuthor.grid(row=6, column=1, sticky="NEWS", columnspan=2)
Label(tl, text="Musique de la course :").grid(row=7, column=1, columnspan=2)
listbox_MusicType = ttk.Combobox(tl, width=50, values=list(track2ID.keys())) listbox_MusicType = ttk.Combobox(tl, width=50, values=list(track2ID.keys()))
listbox_MusicType.current(0) listbox_MusicType.current(0)
listbox_MusicType.grid(row=6, column=1, sticky="NEWS", columnspan=2) listbox_MusicType.grid(row=8, column=1, sticky="NEWS", columnspan=2)
Label(tl, text="Type de la course :\n(généralement indiqué par son créateur)\n(si non spécifié, choisir slot 1.1)").grid(row=7, column=1, columnspan=2) Label(tl, text="Type de la course :\n(généralement indiqué par son créateur)\n(si non spécifié, choisir slot 1.1)").grid(row=9, column=1, columnspan=2)
listbox_TrackType = ttk.Combobox(tl, width=50, values=list(track2ID.keys())) listbox_TrackType = ttk.Combobox(tl, width=50, values=list(track2ID.keys()))
listbox_TrackType.current(0) listbox_TrackType.current(0)
listbox_TrackType.grid(row=8, column=1, sticky="NEWS", columnspan=2) listbox_TrackType.grid(row=10, column=1, sticky="NEWS", columnspan=2)
Bool_isTrackNew = BooleanVar(value=True) Bool_isTrackNew = BooleanVar(value=True)
checkbutton_TrackNew = Checkbutton(tl, text="Marqué comme étant nouveau", variable=Bool_isTrackNew) checkbutton_TrackNew = Checkbutton(tl, text="Marqué comme étant nouveau", variable=Bool_isTrackNew)
checkbutton_TrackNew.grid(row=9, column=1, columnspan=2) checkbutton_TrackNew.grid(row=11, column=1, columnspan=2)
def confirm(): def confirm():
if self.new_track(entry_CoursePath.get(), if self.new_track(entry_CoursePath.get(),
@ -536,17 +547,29 @@ class main():
course_index, course_index,
Bool_isTrackNew.get(), Bool_isTrackNew.get(),
listbox_MusicType.get(), listbox_MusicType.get(),
listbox_TrackType.get()): listbox_TrackType.get(),
entry_CourseAuthor.get()):
tl.destroy() tl.destroy()
self.root.focus_force() self.root.focus_force()
_config_track = self.config["cup"][str(cup_index)]["courses"][str(course_index)]
entry_CoursePath.insert(0, f"{self.path}/files/.MKCreator/Track/{_config_track['name']}.szs")
entry_CourseName.insert(0, _config_track["name"])
entry_CourseAuthor.insert(0, _config_track["author"])
Tracks = list(track2ID.keys())
listbox_MusicType.current(Tracks.index(IDm2track[_config_track["music"]]))
listbox_TrackType.current(Tracks.index(IDs2track[_config_track["special"]]))
Bool_isTrackNew.set(_config_track["new"])
Button(tl, text="Confirmer", command=confirm, relief=RIDGE).grid(row=10,column=1, columnspan=2, sticky="E") Button(tl, text="Confirmer", command=confirm, relief=RIDGE).grid(row=10,column=1, columnspan=2, sticky="E")
def get_track_name(self, path): def get_track_name(self, path):
return path.split("/")[-1].replace("_", " ").replace(".szs", "").replace(".wbz", "").split("(")[0].split("[")[0] return path.split("/")[-1].replace("_", " ").replace(".szs", "").replace(".wbz", "").split("(")[0].split("[")[0].replace(".le", "").replace(".fix", "").replace(".hp", "")
def patch_game(self): def patch_game(self):
@ -567,6 +590,9 @@ class main():
{"slot": "7040", "name": "Aléatoire: Custom Tracks"}, {"slot": "7040", "name": "Aléatoire: Custom Tracks"},
{"slot": "7041", "name": "Aléatoire: Pistes Nouvelles"}, {"slot": "7041", "name": "Aléatoire: Pistes Nouvelles"},
] ]
Cup_score = {1: [], 2: [], 3:[]}
text_index = 0 text_index = 0
total_cup = len(self.config["cup"]) total_cup = len(self.config["cup"])
ct_icon = Image.new("RGBA", (128, 128*(total_cup+2))) ct_icon = Image.new("RGBA", (128, 128*(total_cup+2)))
@ -585,6 +611,12 @@ class main():
for course in _cup_config["courses"]: for course in _cup_config["courses"]:
_course_config = _cup_config["courses"][course] _course_config = _cup_config["courses"][course]
if "score" in list(_course_config.keys()):
score = _course_config["score"]
if score > 0: Cup_score[score].append(_course_config)
else: score = 0
self.label_Action.config(text=f"Configuration de la course {_course_config['name']} (coupe {cup})...") self.label_Action.config(text=f"Configuration de la course {_course_config['name']} (coupe {cup})...")
self.progressbar_Action.step(1) self.progressbar_Action.step(1)
@ -596,9 +628,9 @@ class main():
f" {flag};"+\ f" {flag};"+\
f" \"{_course_config['name']}\";"+\ f" \"{_course_config['name']}\";"+\
f" \"{_course_config['name']}\";"+\ f" \"{_course_config['name']}\";"+\
f" \"\"" f" \"{sha1(_course_config['name'])}\""
TEXT_DATA.append({"slot": format(0x7044 + text_index, '02x'), "name": _course_config['name']}) TEXT_DATA.append({"slot": format(0x7044 + text_index, '02x'), "name": _course_config['name'], "score": score, "author": _course_config['author']})
text_index += 1 text_index += 1
if _course_config["name"] == "/": if _course_config["name"] == "/":
@ -609,11 +641,96 @@ class main():
self.label_Action.grid_forget() self.label_Action.grid_forget()
return return
if False:
LE_CODE += f"\n\nC \"Star1\""
rank_retro_course = {1: 0, 2: 0, 3: 0, "2+3": 0}
for rank in Cup_score:
LE_CODE += f"\nT 145;" + \
f" T43;" + \
f" 0x02;" + \
f" \"star{rank}courses\";" + \
f" \"star{rank}courses\";" + \
f" \"{sha1(f'star{rank}courses')}\""
for course in Cup_score[rank]:
flag = "0x00"
if course["new"]: flag = "0x01"
else: rank_retro_course[rank] += 1
LE_CODE += f"\nH {course['music']};" + \
f" {hex(course['special'])};" + \
f" 0x04;" + \
f" \"{course['name']}\";" + \
f" \"{course['name']}\";" + \
f" \"{sha1(course['name'])}\""
LE_CODE += f"\nT 145;" + \
f" T43;" + \
f" 0x02;" + \
f" \"2or3courses\";" + \
f" \"2or3courses\";" + \
f" \"{sha1('2or3courses')}\""
for course in Cup_score[2] + Cup_score[3]:
flag = "0x00"
if course["new"]: flag = "0x01"
else: rank_retro_course["2+3"] += 1
LE_CODE += f"\nH {course['music']};" + \
f" {hex(course['special'])};" + \
f" 0x04;" + \
f" \"{course['name']}\";" + \
f" \"{course['name']}\";" + \
f" \"{sha1(course['name'])}\""
LE_CODE += f"\n\nC \"Star2\"" # Pas de rétro
for rank in Cup_score:
LE_CODE += f"\nT 145;" + \
f" T43;" + \
f" 0x02;" + \
f" \"nr{rank}courses\";" + \
f" \"nr{rank}courses\";" + \
f" \"{sha1(f'nr{rank}courses')}\""
for course in Cup_score[rank]:
if course["new"]:
LE_CODE += f"\nH {course['music']};" + \
f" {hex(course['special'])};" + \
f" 0x04;" + \
f" \"{course['name']}\";" + \
f" \"{course['name']}\";" + \
f" \"{sha1(course['name'])}\""
LE_CODE += f"\nT 145;" + \
f" T43;" + \
f" 0x02;" + \
f" \"nr2or3courses\";" + \
f" \"nr2or3courses\";" + \
f" \"{sha1('nr2or3courses')}\""
for course in Cup_score[2] + Cup_score[3]:
if course["new"]:
LE_CODE += f"\nH {course['music']};" + \
f" {hex(course['special'])};" + \
f" 0x04;" + \
f" \"{course['name']}\";" + \
f" \"{course['name']}\";" + \
f" \"{sha1(course['name'])}\""
TEXT_DATA.append({"slot": format(0x7044 + text_index + 0, '02x'), "name": f"courses ★☆☆ ({len(Cup_score[1])})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 1, '02x'), "name": f"courses ★★☆ ({len(Cup_score[2])})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 2, '02x'), "name": f"courses ★★★ ({len(Cup_score[3])})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 3, '02x'), "name": f"courses ★★☆/★★★ ({len(Cup_score[2] + Cup_score[3])})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 4, '02x'), "name": f"(sans rétro) courses ★☆☆ ({len(Cup_score[1]) - rank_retro_course[1]})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 5, '02x'), "name": f"(sans rétro) courses ★★☆ ({len(Cup_score[2]) - rank_retro_course[2]})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 6, '02x'), "name": f"(sans rétro) courses ★★★ ({len(Cup_score[3]) - rank_retro_course[3]})", "score": 0, "author": "-"})
TEXT_DATA.append({"slot": format(0x7044 + text_index + 7, '02x'), "name": f"(sans rétro) courses ★★☆/★★★ ({len(Cup_score[2] + Cup_score[3]) - rank_retro_course['2+3']})", "score": 0, "author": "-"})
self.label_Action.config(text=f"Création du fichier CTFILE.txt...") self.label_Action.config(text=f"Création du fichier CTFILE.txt...")
self.progressbar_Action.step(1) self.progressbar_Action.step(1)
shutil.copy("./assets/CTFILE-default.txt", f"{self.path}/files/.MKCreator/CTFILE.txt") shutil.copy("./assets/CTFILE-default.txt", f"{self.path}/files/.MKCreator/CTFILE.txt")
with open(f"{self.path}/files/.MKCreator/CTFILE.txt", "a") as CTFile: with open(f"{self.path}/files/.MKCreator/CTFILE.txt", "a", encoding='utf-8') as CTFile:
CTFile.write(LE_CODE) CTFile.write(LE_CODE)
@ -624,7 +741,8 @@ class main():
f"--DEST \"{self.path}/files/.MKCreator/ct_icons.tpl\" -x tpl.CMPR --overwrite") f"--DEST \"{self.path}/files/.MKCreator/ct_icons.tpl\" -x tpl.CMPR --overwrite")
p.wait() p.wait()
for file in ["Channel", "MenuMulti", "MenuSingle"]: for file in ["Channel", "MenuMulti", "MenuSingle", "Race"]:
if file != "Race":
self.label_Action.config(text=f"Configuration des icones {file}.szs...") self.label_Action.config(text=f"Configuration des icones {file}.szs...")
self.progressbar_Action.step(1) self.progressbar_Action.step(1)
@ -650,19 +768,39 @@ class main():
p = subprocess.Popen(f"wbmgt decode \"{tmp_path}/message/Common.bmg\" --overwrite") p = subprocess.Popen(f"wbmgt decode \"{tmp_path}/message/Common.bmg\" --overwrite")
p.wait() p.wait()
with open(f"{tmp_path}/message/Common.txt", "a+") as CommonFile: with open(f"{tmp_path}/message/Common.txt", "a+", encoding="utf-8") as CommonFile:
for line in CommonFile.readlines(): for line in CommonFile.readlines():
for TEXT in TEXT_DATA: for TEXT in TEXT_DATA:
print(line[len(f" {TEXT['slot']}"):])
if line[len(f" {TEXT['slot']}"):] == f" {TEXT['slot']}": if line[len(f" {TEXT['slot']}"):] == f" {TEXT['slot']}":
starTEXT = " "
try:
star = int(TEXT['score'])
if star > 0:
starTEXT = ("" * star) + ("" * (3 - star))
starTEXT += " "
except: pass
if line != f"\n {TEXT['slot']}\t= {TEXT['name']}": if line != f"\n {TEXT['slot']}\t= {TEXT['name']}":
pointer = CommonFile.tell() pointer = CommonFile.tell()
CommonFile.write(f"\n {TEXT['slot']}\t= {TEXT['name']}") if (file == "Race") & ("author" in TEXT):
CommonFile.write(f"\n {TEXT['slot']}\t={starTEXT}{TEXT['name']}\\npar {TEXT['author']}")
else: CommonFile.write(f"\n {TEXT['slot']}\t= {starTEXT}{TEXT['name']}")
CommonFile.seek(pointer) CommonFile.seek(pointer)
TEXT_DATA.pop(TEXT) TEXT_DATA.pop(TEXT)
for TEXT in TEXT_DATA: for TEXT in TEXT_DATA:
CommonFile.write(f"\n {TEXT['slot']}\t= {TEXT['name']}") starTEXT = " "
try:
star = int(TEXT['score'])
if star > 0:
starTEXT = ("" * star) + ("" * (3 - star))
starTEXT += " "
except: pass
print(f"{TEXT['slot']}\t= {starTEXT}{TEXT['name']}")
if (file == "Race") & ("author" in TEXT):
CommonFile.write(f"\n {TEXT['slot']}\t= {starTEXT}{TEXT['name']}\\npar {TEXT['author']}")
else: CommonFile.write(f"\n {TEXT['slot']}\t= {starTEXT}{TEXT['name']}")
p = subprocess.Popen(f"wbmgt encode \"{tmp_path}/message/Common.txt\" --overwrite --le-code") p = subprocess.Popen(f"wbmgt encode \"{tmp_path}/message/Common.txt\" --overwrite --le-code")
p.wait() p.wait()
@ -676,12 +814,12 @@ class main():
self.label_Action.config(text=f"Patch de LE-CODE.bin...") self.label_Action.config(text=f"Patch de LE-CODE.bin...")
self.progressbar_Action.step(1) self.progressbar_Action.step(1)
p = subprocess.Popen( """p = subprocess.Popen(
f"wlect patch ./assets/lecode-PAL.bin -od \"{self.path}/files/rel/lecode-PAL.bin\" --track-dir " + \ f"wlect patch ./assets/lecode-PAL.bin -od \"{self.path}/files/rel/lecode-PAL.bin\" --track-dir " + \
f"\"{self.path}/files/Race/Course\" --copy-tracks \"{self.path}/files/.MKCreator/Track/\" " + \ f"\"{self.path}/files/Race/Course\" --copy-tracks \"{self.path}/files/.MKCreator/Track/\" " + \
f"--copy-tracks \"{self.path}/files/.MKCreator/Track-Original/\" --le-define " + \ f"--copy-tracks \"{self.path}/files/.MKCreator/Track-Original/\" --le-define " + \
f"\"{self.path}/files/.MKCreator/CTFILE.txt\" --lpar ./assets/lpar-default.txt --overwrite") f"\"{self.path}/files/.MKCreator/CTFILE.txt\" --lpar ./assets/lpar-default.txt --overwrite")
p.wait() p.wait()"""
self.progressbar_Action.grid_forget() self.progressbar_Action.grid_forget()
self.label_Action.grid_forget() self.label_Action.grid_forget()
@ -771,12 +909,12 @@ class main():
draw.text((4, 4), "CT", (255, 165, 0), font=font) draw.text((4, 4), "CT", (255, 165, 0), font=font)
font = ImageFont.truetype("./assets/SuperMario256.ttf", 60) font = ImageFont.truetype("./assets/SuperMario256.ttf", 60)
draw.text((15-2, 80-2), "%03i" % index, (0, 0, 0), font=font) draw.text((5-2, 80-2), "%03i" % index, (0, 0, 0), font=font)
draw.text((15+2, 80-2), "%03i" % index, (0, 0, 0), font=font) draw.text((5+2, 80-2), "%03i" % index, (0, 0, 0), font=font)
draw.text((15-2, 80+2), "%03i" % index, (0, 0, 0), font=font) draw.text((5-2, 80+2), "%03i" % index, (0, 0, 0), font=font)
draw.text((15+2, 80+2), "%03i" % index, (0, 0, 0), font=font) draw.text((5+2, 80+2), "%03i" % index, (0, 0, 0), font=font)
draw.text((15, 80), "%03i" % index, (255, 165, 0), font=font) draw.text((5, 80), "%03i" % index, (255, 165, 0), font=font)
return cup_icon return cup_icon
@ -796,12 +934,18 @@ class main():
self.save_config() self.save_config()
def new_track(self, path, name, cup_index, course_index, is_new, music_type, track_type): def new_track(self, path, name, cup_index, course_index, is_new, music_type, track_type, track_author = ""):
if os.path.exists(path): if os.path.exists(path):
_formated_name = name.replace(" ", "") _formated_name = name.replace(" ", "")
if (_formated_name != "") and (_formated_name != "/"): if (_formated_name != "") and (_formated_name != "/"):
if music_type in track2ID: if music_type in track2ID:
if track_type in track2ID: if track_type in track2ID:
if not(path.isascii()):
try:
_path = path
path = unidecode.unidecode(path)
os.rename(_path, path)
except: pass
if not (os.path.exists(f"{self.path}/files/.MKCreator/Track/")): if not (os.path.exists(f"{self.path}/files/.MKCreator/Track/")):
os.makedirs(f"{self.path}/files/.MKCreator/Track/") os.makedirs(f"{self.path}/files/.MKCreator/Track/")
@ -813,6 +957,7 @@ class main():
f"--autoadd-path \"{self.path}/files/.MKCreator/auto-add/\"") f"--autoadd-path \"{self.path}/files/.MKCreator/auto-add/\"")
p.wait() p.wait()
elif extension == ".szs": elif extension == ".szs":
if path != f"{self.path}/files/.MKCreator/Track/{name}.szs":
shutil.copy(path, f"{self.path}/files/.MKCreator/Track/{name}.szs") shutil.copy(path, f"{self.path}/files/.MKCreator/Track/{name}.szs")
self.config["cup"][str(cup_index)]["courses"][str(course_index)] = { self.config["cup"][str(cup_index)]["courses"][str(course_index)] = {
@ -820,6 +965,7 @@ class main():
"music": track2ID[music_type][0], "music": track2ID[music_type][0],
"special": track2ID[track_type][1], "special": track2ID[track_type][1],
"new": is_new, "new": is_new,
"author": track_author
} }
self.save_config() self.save_config()
self.select_cup(cup_index) self.select_cup(cup_index)
@ -865,11 +1011,11 @@ class main():
if course_id == 0: if course_id == 0:
cup_id = len(self.config["cup"]) cup_id = len(self.config["cup"])
new_icon = self.generate_cup_icon(cup_id) new_icon = self.generate_cup_icon(cup_id - 8)
cup_name = "CT%03i" % cup_id cup_name = "CT%03i" % cup_id
self.new_cup(cup_id, new_icon, cup_name) self.new_cup(cup_id, new_icon, cup_name)
self.new_track(path, name, cup_id, course_id, True, special_slot, special_slot) self.new_track(path, name, cup_id, course_id, True, special_slot, special_slot, "Inconnu")
self.progressbar_Action.grid_forget() self.progressbar_Action.grid_forget()
self.label_Action.grid_forget() self.label_Action.grid_forget()
@ -880,9 +1026,11 @@ class main():
#TODO: Vérifier les overwrites pour éviter les bugs #TODO: Vérifier les overwrites pour éviter les bugs
#TODO: Améliorer la modification des sous-fichiers des szs #TODO: Améliorer la modification des sous-fichiers des szs
#TODO: Warning sur les dossier à accent !!! impossible d'importer une course depuis l'un d'eux ! + Installer les outils wszst, ... #TODO: Warning Installer les outils wszst, ...
#TODO: Bouton réinitilialisé le jeu
#DONE: Les .fix, .hp & .le sont automatiquement supprimés dans les noms des courses
#DONE: L'importation de plusieurs courses verra ses icônes de CT commencer à 1
Main = main() Main = main()
mainloop() mainloop()