v0.4
Fonction d'import & export ajouté meilleurs icones par défaut pour les coupes Choisir une course sélectionne automatiquement les emplacements adapté (si possible) Support des fichiers .wbz pour les courses Amélioration des imports / exports pour les copyright Possibilité d'importer des groupes entier de course et de coupe Suppresion du boutton "modifier la ROM" : chargé la rom affichera automatiquement les courses
This commit is contained in:
parent
90bc6e7ae6
commit
dd0fc5b768
1 changed files with 307 additions and 123 deletions
422
main.pyw
422
main.pyw
|
@ -4,9 +4,65 @@ import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from PIL import Image, ImageTk
|
from PIL import Image, ImageTk, ImageDraw, ImageFont
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
track2ID = {
|
||||||
|
"Circuit Luigi (slot 1.1)": [0x75, 0x08],
|
||||||
|
"Prairie Meuh Meuh (slot 1.2)": [0x77, 0x01],
|
||||||
|
"Gorge Champignon (slot 1.3)": [0x79, 0x02],
|
||||||
|
"Usine Toad (slot 1.4)": [0x7B, 0x04],
|
||||||
|
|
||||||
|
"Circuit Mario (slot 2.1)": [0x7D, 0x00],
|
||||||
|
"Supermarché Coco (slot 2.2)": [0x7F, 0x05],
|
||||||
|
"Pic DK (slot 2.3)": [0x81, 0x06],
|
||||||
|
"Mine Wario (slot 2.4)": [0x83, 0x07],
|
||||||
|
|
||||||
|
"Circuit Daisy (slot 3.1)": [0x87, 0x09],
|
||||||
|
"Cap Koopa (slot 3.2)": [0x85, 0x0F],
|
||||||
|
"Bois Vermeil (slot 3.3)": [0x8F, 0x0B],
|
||||||
|
"Volcan Grondant (slot 3.4)": [0x8B, 0x03],
|
||||||
|
|
||||||
|
"Ruines Sec Sec (slot 4.1)": [0x89, 0x0E],
|
||||||
|
"Route Clair de Lune (slot 4.2)": [0x8D, 0x0A],
|
||||||
|
"Château de Bowser (slot 4.3)": [0x91, 0x0C],
|
||||||
|
"Route Arc-en-Ciel (slot 4.4)": [0x93, 0x0D],
|
||||||
|
|
||||||
|
"GCN Plage Peach (slot 5.1)": [0xA5, 0x10],
|
||||||
|
"DS Cascades Yoshi (slot 5.2)": [0xAD, 0x14],
|
||||||
|
"SNES Vallée Fantôme 2 (slot 5.3)": [0x97, 0x19],
|
||||||
|
"N64 Autodrome Mario (slot 5.4)": [0x9F, 0x1A],
|
||||||
|
|
||||||
|
"N64 Royaume Sorbet (slot 6.1)": [0x9D, 0x1B],
|
||||||
|
"GBA Plage Maskass (slot 6.2)": [0x95, 0x1F],
|
||||||
|
"DS Quartier Delfino (slot 6.3)": [0xAF, 0x17],
|
||||||
|
"GCN Stade Waluigi (slot 6.4)": [0xA9, 0x12],
|
||||||
|
|
||||||
|
"DS Désert du Soleil (slot 7.1)": [0xB1, 0x15],
|
||||||
|
"GBA Château de Bowser 3 (slot 7.2)":[0x9B, 0x1E],
|
||||||
|
"N64 Jungle DK (slot 7.3)": [0xA1, 0x1D],
|
||||||
|
"GCN Circuit Mario (slot 7.4)": [0xA7, 0x11],
|
||||||
|
|
||||||
|
"SNES Circuit Mario 3 (slot 8.1)": [0x99, 0x18],
|
||||||
|
"DS Jardin Peach (slot 8.2)": [0xB3, 0x16],
|
||||||
|
"GCN Montagne DK (slot 8.3)": [0xAB, 0x13],
|
||||||
|
"N64 Château de Bowser (slot 8.4)": [0xA3, 0x1C],
|
||||||
|
|
||||||
|
"Block Plaza (battle slot 1.1)": [0xB7, 0x21],
|
||||||
|
"Quai Delfino (battle slot 1.2)": [0xB5, 0x20],
|
||||||
|
"Stade de Funky Kong (battle slot 1.3)": [0xB9, 0x23],
|
||||||
|
"Roulette Chomp (battle slot 1.4)": [0xBB, 0x22],
|
||||||
|
"Désert Thwomp (battle slot 1.5)": [0xBD, 0x24],
|
||||||
|
|
||||||
|
"SNES Circuit de Bataille 4 (battle slot 2.1)": [0xC3, 0x27],
|
||||||
|
"GBA Circuit de Bataille 3 (battle slot 2.2)": [0xC5, 0x28],
|
||||||
|
"N64 Gratte-ciel (battle slot 2.3)": [0xC7, 0x29],
|
||||||
|
"GCN Cookie Arena (battle slot 2.4)": [0xBF, 0x25],
|
||||||
|
"DS Maison de l'Aube (battle slot 2.5)": [0xC1, 0x26],
|
||||||
|
|
||||||
|
"Colisée Galactique": [0xC9, 0x36],
|
||||||
|
}
|
||||||
|
|
||||||
class main():
|
class main():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.root = Tk()
|
self.root = Tk()
|
||||||
|
@ -28,8 +84,16 @@ class main():
|
||||||
self.label_GameInformation.grid(row=1, column=1)
|
self.label_GameInformation.grid(row=1, column=1)
|
||||||
self.button_ExtractROM = Button(self.frame_ActionGameFile, text="Extraire le jeu", relief=RIDGE, command=self.extract_game)
|
self.button_ExtractROM = Button(self.frame_ActionGameFile, text="Extraire le jeu", relief=RIDGE, command=self.extract_game)
|
||||||
self.button_InstallLECODE = Button(self.frame_ActionGameFile, text="Installer LE-CODE", relief=RIDGE, command=self.install_lecode)
|
self.button_InstallLECODE = Button(self.frame_ActionGameFile, text="Installer LE-CODE", relief=RIDGE, command=self.install_lecode)
|
||||||
self.button_EditROM = Button(self.frame_ActionGameFile, text="Modifier la configuration", relief=RIDGE, command=self.edit_game)
|
|
||||||
self.button_PatchROM = Button(self.frame_ActionGameFile, text="Patcher le jeu", relief=RIDGE, command=self.patch_game)
|
self.frame_ActionGameEditROM = Frame(self.frame_ActionGameFile)
|
||||||
|
self.button_ImportROM = Button(self.frame_ActionGameEditROM, text="Importer un pack de courses", relief=RIDGE, command=self.import_track_pack)
|
||||||
|
self.button_ImportROM.grid(row=1,column=1, sticky="NEWS")
|
||||||
|
self.button_ExportROM = Button(self.frame_ActionGameEditROM, text="Exporter un pack de courses", relief=RIDGE, command=self.export_track_pack)
|
||||||
|
self.button_ExportROM.grid(row=2,column=1, sticky="NEWS")
|
||||||
|
self.button_ImportMultipleRace = Button(self.frame_ActionGameEditROM, text="Importer plusieurs courses", relief=RIDGE, command=self.import_multiple_race)
|
||||||
|
self.button_ImportMultipleRace.grid(row=3,column=1, sticky="NEWS")
|
||||||
|
self.button_PatchROM = Button(self.frame_ActionGameEditROM, text="Patcher le jeu", relief=RIDGE, command=self.patch_game)
|
||||||
|
self.button_PatchROM.grid(row=4, column=1, sticky="NEWS")
|
||||||
self.progressbar_Action = ttk.Progressbar(self.frame_ActionGameFile)
|
self.progressbar_Action = ttk.Progressbar(self.frame_ActionGameFile)
|
||||||
self.label_Action = Label(self.frame_ActionGameFile)
|
self.label_Action = Label(self.frame_ActionGameFile)
|
||||||
|
|
||||||
|
@ -111,20 +175,18 @@ class main():
|
||||||
if self.file_type in ["wbfs", "iso"]:
|
if self.file_type in ["wbfs", "iso"]:
|
||||||
self.button_ExtractROM.grid(row=2,column=1,sticky="NEWS")
|
self.button_ExtractROM.grid(row=2,column=1,sticky="NEWS")
|
||||||
self.button_InstallLECODE.grid_forget()
|
self.button_InstallLECODE.grid_forget()
|
||||||
self.button_EditROM.grid_forget()
|
self.frame_ActionGameEditROM.grid_forget()
|
||||||
self.button_PatchROM.grid_forget()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.button_ExtractROM.grid_forget()
|
self.button_ExtractROM.grid_forget()
|
||||||
if os.path.exists(f"{self.path}/files/.MKCreator/"):
|
if os.path.exists(f"{self.path}/files/.MKCreator/"):
|
||||||
self.button_InstallLECODE.grid_forget()
|
self.button_InstallLECODE.grid_forget()
|
||||||
self.button_EditROM.grid(row = 4, column = 1, sticky = "NEWS")
|
self.frame_ActionGameEditROM.grid(row=4,column=1,sticky="NEWS")
|
||||||
self.button_PatchROM.grid_forget()
|
self.edit_game()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.button_InstallLECODE.grid(row=3,column=1,sticky="NEWS")
|
self.button_InstallLECODE.grid(row=3,column=1,sticky="NEWS")
|
||||||
self.button_EditROM.grid_forget()
|
self.frame_ActionGameEditROM.grid_forget()
|
||||||
self.button_PatchROM.grid_forget()
|
|
||||||
|
|
||||||
|
|
||||||
def extract_game(self):
|
def extract_game(self):
|
||||||
|
@ -158,7 +220,7 @@ class main():
|
||||||
self.progressbar_Action.config(mode = "determinate")
|
self.progressbar_Action.config(mode = "determinate")
|
||||||
self.label_Action.grid(row = 101, column = 1, sticky = "NEWS")
|
self.label_Action.grid(row = 101, column = 1, sticky = "NEWS")
|
||||||
self.progressbar_Action.stop()
|
self.progressbar_Action.stop()
|
||||||
self.progressbar_Action['maximum'] = 56
|
self.progressbar_Action['maximum'] = 57
|
||||||
self.progressbar_Action["value"] = 0
|
self.progressbar_Action["value"] = 0
|
||||||
self.button_InstallLECODE.grid_forget()
|
self.button_InstallLECODE.grid_forget()
|
||||||
|
|
||||||
|
@ -235,19 +297,20 @@ class main():
|
||||||
|
|
||||||
# correction des courses
|
# correction des courses
|
||||||
if not(os.path.exists(f"{self.path}/files/.MKCreator/Track/")): os.makedirs(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/")
|
||||||
|
if not(os.path.exists(f"{self.path}/files/.MKCreator/Track-Original/")): os.makedirs(f"{self.path}/files/.MKCreator/Track-Original/")
|
||||||
|
if not (os.path.exists(f"{self.path}/files/.MKCreator/auto-add/")): os.makedirs(f"{self.path}/files/.MKCreator/auto-add/")
|
||||||
|
|
||||||
for file in os.listdir(f"{self.path}/files/Race/Course/"):
|
for file in os.listdir(f"{self.path}/files/Race/Course/"):
|
||||||
if os.path.isfile(f"{self.path}/files/Race/Course/{file}"):
|
if os.path.isfile(f"{self.path}/files/Race/Course/{file}"):
|
||||||
_, extension = os.path.splitext(file)
|
_, extension = os.path.splitext(file)
|
||||||
if extension == ".szs":
|
if extension == ".szs":
|
||||||
self.label_Action.config(text=f"Correction de la course {file}...")
|
self.label_Action.config(text=f"Correction de la course {file}...")
|
||||||
shutil.move(f"{self.path}/files/Race/Course/{file}", f"{self.path}/files/.MKCreator/Track/{file}")
|
shutil.move(f"{self.path}/files/Race/Course/{file}", f"{self.path}/files/.MKCreator/Track-Original/{file}")
|
||||||
|
|
||||||
# application du patch
|
# application du patch
|
||||||
self.label_Action.config(text=f"Patch de LE-CODE.bin")
|
self.label_Action.config(text=f"Patch de LE-CODE.bin")
|
||||||
p = subprocess.Popen(f"wlect patch ./assets/lecode-PAL.bin -od \"{self.path}/files/rel/lecode-PAL.bin\" --track-dir "+\
|
p = subprocess.Popen(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/\" --le-define "+\
|
f"\"{self.path}/files/Race/Course\" --copy-tracks \"{self.path}/files/.MKCreator/Track-Original/\" --le-define "+\
|
||||||
f"./assets/CTFILE-default.txt --lpar ./assets/lpar-default.txt --overwrite")
|
f"./assets/CTFILE-default.txt --lpar ./assets/lpar-default.txt --overwrite")
|
||||||
p.wait()
|
p.wait()
|
||||||
|
|
||||||
|
@ -257,6 +320,12 @@ class main():
|
||||||
shutil.copy("./assets/config-fr.json", f"{self.path}/files/.MKCreator/config.json")
|
shutil.copy("./assets/config-fr.json", f"{self.path}/files/.MKCreator/config.json")
|
||||||
|
|
||||||
|
|
||||||
|
self.label_Action.config(text=f"Création du dossier auto-add...")
|
||||||
|
self.progressbar_Action.step(1)
|
||||||
|
p = subprocess.Popen(f"wszst autoadd -q \"{self.path}/files/.MKCreator/Track-Original/\" --dest " + \
|
||||||
|
f"\"{self.path}/files/.MKCreator/auto-add/\" --remove-dest --preserve")
|
||||||
|
p.wait()
|
||||||
|
|
||||||
self.progressbar_Action.grid_forget()
|
self.progressbar_Action.grid_forget()
|
||||||
self.label_Action.grid_forget()
|
self.label_Action.grid_forget()
|
||||||
self.refresh_action_frame()
|
self.refresh_action_frame()
|
||||||
|
@ -272,8 +341,6 @@ class main():
|
||||||
|
|
||||||
|
|
||||||
def refresh_cup_menu(self):
|
def refresh_cup_menu(self):
|
||||||
self.button_PatchROM.grid(row = 5, column = 1, sticky = "NEWS")
|
|
||||||
|
|
||||||
for x in range(4):
|
for x in range(4):
|
||||||
for y in range(2):
|
for y in range(2):
|
||||||
pos_index = (x * 2) + y
|
pos_index = (x * 2) + y
|
||||||
|
@ -339,8 +406,9 @@ class main():
|
||||||
tl.title("Nouvelle Coupe")
|
tl.title("Nouvelle Coupe")
|
||||||
tl.resizable(False, False)
|
tl.resizable(False, False)
|
||||||
|
|
||||||
new_icon = self._add_img_raw
|
cup_id = len(self.config["cup"])
|
||||||
new_icon_tk = self._add_img
|
new_icon = self.generate_cup_icon(cup_id - 8)
|
||||||
|
new_icon_tk = ImageTk.PhotoImage(new_icon)
|
||||||
|
|
||||||
def select_icon():
|
def select_icon():
|
||||||
nonlocal new_icon, new_icon_tk
|
nonlocal new_icon, new_icon_tk
|
||||||
|
@ -356,28 +424,16 @@ class main():
|
||||||
entry_NewCupName = Entry(tl)
|
entry_NewCupName = Entry(tl)
|
||||||
entry_NewCupName.grid(row=2,column=1,sticky="NEWS")
|
entry_NewCupName.grid(row=2,column=1,sticky="NEWS")
|
||||||
Label(tl, text="Choississez une icone pour votre coupe :").grid(row=3, column=1)
|
Label(tl, text="Choississez une icone pour votre coupe :").grid(row=3, column=1)
|
||||||
button_NewCupIcon = Button(tl, image=self._add_img, command=select_icon)
|
button_NewCupIcon = Button(tl, image=new_icon_tk, command=select_icon)
|
||||||
button_NewCupIcon.grid(row=4, column=1)
|
button_NewCupIcon.grid(row=4, column=1)
|
||||||
|
|
||||||
def confirm():
|
def confirm():
|
||||||
nonlocal new_icon
|
nonlocal new_icon, cup_id
|
||||||
cup_name = entry_NewCupName.get()
|
cup_name = entry_NewCupName.get()
|
||||||
if cup_name.replace(" ", "") != "":
|
if cup_name.replace(" ", "") != "":
|
||||||
|
|
||||||
cup_id = len(self.config["cup"])
|
self.new_cup(cup_id, new_icon, cup_name)
|
||||||
|
|
||||||
new_icon.save(f"{self.path}/files/.MKCreator/cup_icon/{cup_id}.png")
|
|
||||||
self.config["cup"][str(cup_id)] = {
|
|
||||||
"name": cup_name,
|
|
||||||
"locked": False,
|
|
||||||
"courses": {
|
|
||||||
"0": {"name":"/", "music": 0x75, "special": 0x08, "new": False},
|
|
||||||
"1": {"name":"/", "music": 0x75, "special": 0x08, "new": False},
|
|
||||||
"2": {"name":"/", "music": 0x75, "special": 0x08, "new": False},
|
|
||||||
"3": {"name":"/", "music": 0x75, "special": 0x08, "new": False},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.save_config()
|
|
||||||
self.refresh_cup_menu()
|
self.refresh_cup_menu()
|
||||||
tl.destroy()
|
tl.destroy()
|
||||||
self.root.focus_force()
|
self.root.focus_force()
|
||||||
|
@ -427,68 +483,22 @@ class main():
|
||||||
tl.title("Modifier la course")
|
tl.title("Modifier la course")
|
||||||
tl.resizable(False, False)
|
tl.resizable(False, False)
|
||||||
|
|
||||||
track2ID = {
|
|
||||||
"Circuit Luigi (slot 1.1)": [0x75, 0x08],
|
|
||||||
"Prairie Meuh Meuh (slot 1.2)": [0x77, 0x01],
|
|
||||||
"Gorge Champignon (slot 1.3)": [0x79, 0x02],
|
|
||||||
"Usine Toad (slot 1.4)": [0x7B, 0x04],
|
|
||||||
|
|
||||||
"Circuit Mario (slot 2.1)": [0x7D, 0x00],
|
|
||||||
"Supermarché Coco (slot 2.2)": [0x7F, 0x05],
|
|
||||||
"Pic DK (slot 2.3)": [0x81, 0x06],
|
|
||||||
"Mine Wario (slot 2.4)": [0x83, 0x07],
|
|
||||||
|
|
||||||
"Circuit Daisy (slot 3.1)": [0x87, 0x09],
|
|
||||||
"Cap Koopa (slot 3.2)": [0x85, 0x0F],
|
|
||||||
"Bois Vermeil (slot 3.3)": [0x8F, 0x0B],
|
|
||||||
"Volcan Grondant (slot 3.4)": [0x8B, 0x03],
|
|
||||||
|
|
||||||
"Ruines Sec Sec (slot 4.1)": [0x89, 0x0E],
|
|
||||||
"Route Clair de Lune (slot 4.2)": [0x8D, 0x0A],
|
|
||||||
"Château de Bowser (slot 4.3)": [0x91, 0x0C],
|
|
||||||
"Route Arc-en-Ciel (slot 4.4)": [0x93, 0x0D],
|
|
||||||
|
|
||||||
"GCN Plage Peach (slot 5.1)": [0xA5, 0x10],
|
|
||||||
"DS Cascades Yoshi (slot 5.2)": [0xAD, 0x14],
|
|
||||||
"SNES Vallée Fantôme 2 (slot 5.3)": [0x97, 0x19],
|
|
||||||
"N64 Autodrome Mario (slot 5.4)": [0x9F, 0x1A],
|
|
||||||
|
|
||||||
"N64 Royaume Sorbet (slot 6.1)": [0x9D, 0x1B],
|
|
||||||
"GBA Plage Maskass (slot 6.2)": [0x95, 0x1F],
|
|
||||||
"DS Quartier Delfino (slot 6.3)": [0xAF, 0x17],
|
|
||||||
"GCN Stade Waluigi (slot 6.4)": [0xA9, 0x12],
|
|
||||||
|
|
||||||
"DS Désert du Soleil (slot 7.1)": [0xB1, 0x15],
|
|
||||||
"GBA Château de Bowser 3 (slot 7.2)":[0x9B, 0x1E],
|
|
||||||
"N64 Jungle DK (slot 7.3)": [0xA1, 0x1D],
|
|
||||||
"GCN Circuit Mario (slot 7.4)": [0xA7, 0x11],
|
|
||||||
|
|
||||||
"SNES Circuit Mario 3 (slot 8.1)": [0x99, 0x18],
|
|
||||||
"DS Jardin Peach (slot 8.2)": [0xB3, 0x16],
|
|
||||||
"GCN Montagne DK (slot 8.3)": [0xAB, 0x13],
|
|
||||||
"N64 Château de Bowser (slot 8.4)": [0xA3, 0x1C],
|
|
||||||
|
|
||||||
"Block Plaza (battle slot 1.1)": [0xB7, 0x21],
|
|
||||||
"Quai Delfino (battle slot 1.2)": [0xB5, 0x20],
|
|
||||||
"Stade de Funky Kong (battle slot 1.3)": [0xB9, 0x23],
|
|
||||||
"Roulette Chomp (battle slot 1.4)": [0xBB, 0x22],
|
|
||||||
"Désert Thwomp (battle slot 1.5)": [0xBD, 0x24],
|
|
||||||
|
|
||||||
"SNES Circuit de Bataille 4 (battle slot 2.1)": [0xC3, 0x27],
|
|
||||||
"GBA Circuit de Bataille 3 (battle slot 2.2)": [0xC5, 0x28],
|
|
||||||
"N64 Gratte-ciel (battle slot 2.3)": [0xC7, 0x29],
|
|
||||||
"GCN Cookie Arena (battle slot 2.4)": [0xBF, 0x25],
|
|
||||||
"DS Maison de l'Aube (battle slot 2.5)": [0xC1, 0x26],
|
|
||||||
|
|
||||||
"Colisée Galactique": [0xC9, 0x36],
|
|
||||||
}
|
|
||||||
|
|
||||||
def select_file():
|
def select_file():
|
||||||
path = filedialog.askopenfilename(filetypes = (("Fichier course", r"*.szs"),))
|
path = filedialog.askopenfilename(filetypes = (("Fichier course", r"*.szs *.wbz"),))
|
||||||
tl.focus_force()
|
tl.focus_force()
|
||||||
if path:
|
if path:
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
name = path.split("/")[-1].replace("_", " ").replace(".szs", "")
|
name = self.get_track_name(path)
|
||||||
|
Property = path[path.find("[")+1:path.rfind("]")]
|
||||||
|
try:
|
||||||
|
r = Property.find("r")
|
||||||
|
if r != -1:
|
||||||
|
Type = Property[r+1:r+3]
|
||||||
|
Type = ((int(Type[0]) - 1) * 4) + (int(Type[1]) - 1)
|
||||||
|
listbox_MusicType.current(Type)
|
||||||
|
listbox_TrackType.current(Type)
|
||||||
|
except: pass
|
||||||
|
|
||||||
entry_CoursePath.delete(0, END)
|
entry_CoursePath.delete(0, END)
|
||||||
entry_CoursePath.insert(0, path)
|
entry_CoursePath.insert(0, path)
|
||||||
entry_CourseName.delete(0, END)
|
entry_CourseName.delete(0, END)
|
||||||
|
@ -515,47 +525,36 @@ class main():
|
||||||
listbox_TrackType.current(0)
|
listbox_TrackType.current(0)
|
||||||
listbox_TrackType.grid(row=8, column=1, sticky="NEWS", columnspan=2)
|
listbox_TrackType.grid(row=8, column=1, sticky="NEWS", columnspan=2)
|
||||||
|
|
||||||
Bool_isTrackNew = BooleanVar(value=False)
|
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=9, column=1, columnspan=2)
|
||||||
|
|
||||||
def confirm():
|
def confirm():
|
||||||
if os.path.exists(entry_CoursePath.get()):
|
if self.new_track(entry_CoursePath.get(),
|
||||||
_formated_name = entry_CourseName.get().replace(" ", "")
|
entry_CourseName.get(),
|
||||||
if (_formated_name != "") and (_formated_name != "/"):
|
cup_index,
|
||||||
if listbox_MusicType.get() in track2ID:
|
course_index,
|
||||||
if listbox_TrackType.get() in track2ID:
|
Bool_isTrackNew.get(),
|
||||||
|
listbox_MusicType.get(),
|
||||||
|
listbox_TrackType.get()):
|
||||||
|
|
||||||
if not(os.path.exists(f"{self.path}/files/.MKCreator/Track/")):
|
|
||||||
os.makedirs(f"{self.path}/files/.MKCreator/Track/")
|
|
||||||
|
|
||||||
shutil.copy(entry_CoursePath.get(), f"{self.path}/files/.MKCreator/Track/{entry_CourseName.get()}.szs")
|
|
||||||
self.config["cup"][str(cup_index)]["courses"][str(course_index)] = {
|
|
||||||
"name": entry_CourseName.get(),
|
|
||||||
"music": track2ID[listbox_MusicType.get()][0],
|
|
||||||
"special": track2ID[listbox_TrackType.get()][1],
|
|
||||||
"new": Bool_isTrackNew.get(),
|
|
||||||
}
|
|
||||||
self.save_config()
|
|
||||||
self.select_cup(cup_index)
|
|
||||||
tl.destroy()
|
tl.destroy()
|
||||||
self.root.focus_force()
|
self.root.focus_force()
|
||||||
|
|
||||||
else: messagebox.showerror("Erreur", "Le type spécial de la map est invalide.")
|
|
||||||
else: messagebox.showerror("Erreur", "La musique de la map est invalide.")
|
|
||||||
else: messagebox.showerror("Erreur", "Le nom de la course doit être défini.")
|
|
||||||
else: messagebox.showerror("Erreur", "Vous devez sélectionner le fichier .szs de la course.")
|
|
||||||
|
|
||||||
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):
|
||||||
|
return path.split("/")[-1].replace("_", " ").replace(".szs", "").replace(".wbz", "").split("(")[0].split("[")[0]
|
||||||
|
|
||||||
|
|
||||||
def patch_game(self):
|
def patch_game(self):
|
||||||
def main():
|
def main():
|
||||||
self.progressbar_Action.grid(row = 100, column = 1, sticky = "NEWS")
|
self.progressbar_Action.grid(row = 100, column = 1, sticky = "NEWS")
|
||||||
self.label_Action.grid(row = 101, column = 1)
|
self.label_Action.grid(row = 101, column = 1)
|
||||||
self.label_Action.config(text=f"Préparation...")
|
self.label_Action.config(text=f"Préparation...")
|
||||||
self.button_EditROM.grid_forget()
|
self.frame_ActionGameEditROM.grid_forget()
|
||||||
self.button_PatchROM.grid_forget()
|
|
||||||
self.progressbar_Action.config(mode = "determinate")
|
self.progressbar_Action.config(mode = "determinate")
|
||||||
self.progressbar_Action.stop()
|
self.progressbar_Action.stop()
|
||||||
self.progressbar_Action['maximum'] = 31
|
self.progressbar_Action['maximum'] = 31
|
||||||
|
@ -679,14 +678,14 @@ class main():
|
||||||
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/\" --le-define " + \
|
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"\"{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()
|
||||||
self.button_EditROM.grid(row = 4, column = 1, sticky = "NEWS")
|
self.frame_ActionGameEditROM.grid(row = 4, column = 1, sticky = "NEWS")
|
||||||
self.button_PatchROM.grid(row = 5, column = 1, sticky = "NEWS")
|
|
||||||
|
|
||||||
|
|
||||||
Thread(target=main).start()
|
Thread(target=main).start()
|
||||||
|
@ -696,9 +695,194 @@ class main():
|
||||||
with open(f"{self.path}/files/.MKCreator/config.json", "w") as file:
|
with open(f"{self.path}/files/.MKCreator/config.json", "w") as file:
|
||||||
json.dump(self.config, file)
|
json.dump(self.config, file)
|
||||||
|
|
||||||
#TODO: Icone CTx pour les icones par défaut de course
|
|
||||||
#TODO: Importer des groupes entier de course et de coupe
|
def import_track_pack(self):
|
||||||
|
def main():
|
||||||
|
path = filedialog.askopenfilename(filetypes = (("Fichier MKCTP", r"*.mkctp"),))
|
||||||
|
if path:
|
||||||
|
|
||||||
|
self.progressbar_Action.grid(row = 100, column = 1, sticky = "NEWS")
|
||||||
|
self.label_Action.grid(row = 101, column = 1)
|
||||||
|
self.label_Action.config(text=f"Importation du pack de courses...")
|
||||||
|
self.frame_ActionGameEditROM.grid_forget()
|
||||||
|
self.progressbar_Action.config(mode = "indeterminate")
|
||||||
|
self.progressbar_Action.start(50)
|
||||||
|
|
||||||
|
shutil.unpack_archive(path, f"{self.path}/files/.MKCreator/", 'zip')
|
||||||
|
if os.path.exists(f"{self.path}/files/.MKCreator/Track-WBZ/"):
|
||||||
|
for track in os.listdir(f"{self.path}/files/.MKCreator/Track-WBZ/"):
|
||||||
|
p = subprocess.Popen(f"wszst normalize \"{self.path}/files/.MKCreator/Track-WBZ/{track}\" --szs --overwrite " + \
|
||||||
|
f"--DEST \"{self.path}/files/.MKCreator/Track/{track[:-3]}szs\" " + \
|
||||||
|
f"--autoadd-path \"{self.path}/files/.MKCreator/auto-add/\"")
|
||||||
|
p.wait()
|
||||||
|
shutil.rmtree(f"{self.path}/files/.MKCreator/Track-WBZ/")
|
||||||
|
self.refresh_cup_menu()
|
||||||
|
|
||||||
|
self.progressbar_Action.grid_forget()
|
||||||
|
self.label_Action.grid_forget()
|
||||||
|
self.frame_ActionGameEditROM.grid(row=4,column=1,sticky="NEWS")
|
||||||
|
|
||||||
|
Thread(target=main).start()
|
||||||
|
|
||||||
|
|
||||||
|
def export_track_pack(self):
|
||||||
|
def main():
|
||||||
|
path = filedialog.asksaveasfilename(filetypes=(("Fichier MKCTP", r"*.mkctp"),)) # Mario Kart Creator Track Pack
|
||||||
|
if path:
|
||||||
|
|
||||||
|
self.progressbar_Action.grid(row=100, column=1, sticky="NEWS")
|
||||||
|
self.label_Action.grid(row=101, column=1)
|
||||||
|
self.label_Action.config(text=f"Exportation du pack de courses...")
|
||||||
|
self.frame_ActionGameEditROM.grid_forget()
|
||||||
|
self.progressbar_Action.config(mode="indeterminate")
|
||||||
|
self.progressbar_Action.start(50)
|
||||||
|
|
||||||
|
shutil.copytree(f"{self.path}/files/.MKCreator/", "./.tmp/.MKCreator")
|
||||||
|
shutil.rmtree("./.tmp/.MKCreator/Track-Original/") # Ces courses sont copyright.
|
||||||
|
shutil.rmtree("./.tmp/.MKCreator/auto-add/") # Fichier librairie nécéssaire pour convertir les wbz en szs.
|
||||||
|
if not(os.path.exists("./.tmp/.MKCreator/Track-WBZ/")): os.makedirs("./.tmp/.MKCreator/Track-WBZ/")
|
||||||
|
for track in os.listdir("./.tmp/.MKCreator/Track/"):
|
||||||
|
p = subprocess.Popen(f"wszst normalize \"./.tmp/.MKCreator/Track/{track}\" --wbz --overwrite " + \
|
||||||
|
f"--DEST \"./.tmp/.MKCreator/Track-WBZ/{track[:-3]}wbz\" " + \
|
||||||
|
f"--autoadd-path \"{self.path}/files/.MKCreator/auto-add/\"")
|
||||||
|
p.wait()
|
||||||
|
shutil.rmtree("./.tmp/.MKCreator/Track/") # Ces courses sont copyright.
|
||||||
|
shutil.make_archive(path, 'zip', "./.tmp/.MKCreator")
|
||||||
|
if not(".zip" in path): path += ".zip"
|
||||||
|
os.rename(path, path.replace(".zip", ".mkctp"))
|
||||||
|
shutil.rmtree("./.tmp/.MKCreator/")
|
||||||
|
|
||||||
|
self.progressbar_Action.grid_forget()
|
||||||
|
self.label_Action.grid_forget()
|
||||||
|
self.frame_ActionGameEditROM.grid(row=4, column=1, sticky="NEWS")
|
||||||
|
|
||||||
|
Thread(target=main).start()
|
||||||
|
|
||||||
|
|
||||||
|
def generate_cup_icon(self, index):
|
||||||
|
cup_icon = Image.new("RGBA", (128, 128))
|
||||||
|
draw = ImageDraw.Draw(cup_icon)
|
||||||
|
font = ImageFont.truetype("./assets/SuperMario256.ttf", 90)
|
||||||
|
draw.text((4-2, 4-2), "CT", (0, 0, 0), font=font)
|
||||||
|
draw.text((4+2, 4-2), "CT", (0, 0, 0), font=font)
|
||||||
|
draw.text((4-2, 4+2), "CT", (0, 0, 0), font=font)
|
||||||
|
draw.text((4+2, 4+2), "CT", (0, 0, 0), font=font)
|
||||||
|
|
||||||
|
draw.text((4, 4), "CT", (255, 165, 0), font=font)
|
||||||
|
|
||||||
|
font = ImageFont.truetype("./assets/SuperMario256.ttf", 60)
|
||||||
|
draw.text((15-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((15-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((15, 80), "%03i" % index, (255, 165, 0), font=font)
|
||||||
|
|
||||||
|
return cup_icon
|
||||||
|
|
||||||
|
|
||||||
|
def new_cup(self, cup_id, new_icon, cup_name):
|
||||||
|
new_icon.save(f"{self.path}/files/.MKCreator/cup_icon/{cup_id}.png")
|
||||||
|
self.config["cup"][str(cup_id)] = {
|
||||||
|
"name": cup_name,
|
||||||
|
"locked": False,
|
||||||
|
"courses": {
|
||||||
|
"0": {"name": "/", "music": 0x75, "special": 0x08, "new": False},
|
||||||
|
"1": {"name": "/", "music": 0x75, "special": 0x08, "new": False},
|
||||||
|
"2": {"name": "/", "music": 0x75, "special": 0x08, "new": False},
|
||||||
|
"3": {"name": "/", "music": 0x75, "special": 0x08, "new": False},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.save_config()
|
||||||
|
|
||||||
|
|
||||||
|
def new_track(self, path, name, cup_index, course_index, is_new, music_type, track_type):
|
||||||
|
if os.path.exists(path):
|
||||||
|
_formated_name = name.replace(" ", "")
|
||||||
|
if (_formated_name != "") and (_formated_name != "/"):
|
||||||
|
if music_type in track2ID:
|
||||||
|
if track_type in track2ID:
|
||||||
|
|
||||||
|
if not (os.path.exists(f"{self.path}/files/.MKCreator/Track/")):
|
||||||
|
os.makedirs(f"{self.path}/files/.MKCreator/Track/")
|
||||||
|
|
||||||
|
_, extension = os.path.splitext(path)
|
||||||
|
if extension == ".wbz":
|
||||||
|
p = subprocess.Popen(f"wszst normalize \"{path}\" --szs --overwrite " + \
|
||||||
|
f"--DEST \"{self.path}/files/.MKCreator/Track/{name}.szs\" " + \
|
||||||
|
f"--autoadd-path \"{self.path}/files/.MKCreator/auto-add/\"")
|
||||||
|
p.wait()
|
||||||
|
elif extension == ".szs":
|
||||||
|
shutil.copy(path, f"{self.path}/files/.MKCreator/Track/{name}.szs")
|
||||||
|
|
||||||
|
self.config["cup"][str(cup_index)]["courses"][str(course_index)] = {
|
||||||
|
"name": name,
|
||||||
|
"music": track2ID[music_type][0],
|
||||||
|
"special": track2ID[track_type][1],
|
||||||
|
"new": is_new,
|
||||||
|
}
|
||||||
|
self.save_config()
|
||||||
|
self.select_cup(cup_index)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
else: messagebox.showerror("Erreur", "Le type spécial de la map est invalide.")
|
||||||
|
else: messagebox.showerror("Erreur", "La musique de la map est invalide.")
|
||||||
|
else: messagebox.showerror("Erreur", "Le nom de la course doit être défini.")
|
||||||
|
else: messagebox.showerror("Erreur", "Vous devez sélectionner le fichier .szs de la course.")
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def import_multiple_race(self):
|
||||||
|
def main():
|
||||||
|
paths = filedialog.askopenfilenames(filetypes = (("Fichier course", r"*.szs *.wbz"),))
|
||||||
|
if paths:
|
||||||
|
|
||||||
|
self.progressbar_Action.grid(row=100, column=1, sticky="NEWS")
|
||||||
|
self.label_Action.grid(row=101, column=1)
|
||||||
|
self.frame_ActionGameEditROM.grid_forget()
|
||||||
|
self.progressbar_Action.config(mode="determinate")
|
||||||
|
self.progressbar_Action['maximum'] = len(paths) + 1
|
||||||
|
self.progressbar_Action["value"] = 0
|
||||||
|
|
||||||
|
for index, path in enumerate(paths):
|
||||||
|
name = self.get_track_name(path)
|
||||||
|
self.label_Action.config(text=f"Ajout de la course \"{name}\"...")
|
||||||
|
self.progressbar_Action.step(1)
|
||||||
|
course_id = index % 4
|
||||||
|
|
||||||
|
Type = 0
|
||||||
|
Property = path[path.find("[") + 1:path.rfind("]")]
|
||||||
|
try:
|
||||||
|
r = Property.find("r")
|
||||||
|
if r != -1:
|
||||||
|
_Type = Property[r + 1:r + 3]
|
||||||
|
Type = ((int(_Type[0]) - 1) * 4) + (int(_Type[1]) - 1)
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
special_slot = list(track2ID.keys())[Type]
|
||||||
|
|
||||||
|
if course_id == 0:
|
||||||
|
cup_id = len(self.config["cup"])
|
||||||
|
new_icon = self.generate_cup_icon(cup_id)
|
||||||
|
cup_name = "CT%03i" % cup_id
|
||||||
|
self.new_cup(cup_id, new_icon, cup_name)
|
||||||
|
|
||||||
|
self.new_track(path, name, cup_id, course_id, True, special_slot, special_slot)
|
||||||
|
|
||||||
|
self.progressbar_Action.grid_forget()
|
||||||
|
self.label_Action.grid_forget()
|
||||||
|
self.frame_ActionGameEditROM.grid(row=4, column=1, sticky="NEWS")
|
||||||
|
|
||||||
|
Thread(target=main).start()
|
||||||
|
|
||||||
|
|
||||||
#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: Warning sur les dossier à accent !!! impossible d'importer une course depuis l'un d'eux ! + Installer les outils wszst, ...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Main = main()
|
Main = main()
|
||||||
mainloop()
|
mainloop()
|
Reference in a new issue