From ad06d9bb4add61a40812056f5464c4f48aa6a644 Mon Sep 17 00:00:00 2001 From: Robinde67 <1881499+Robinde67@users.noreply.github.com> Date: Thu, 20 Jan 2022 04:19:58 +0100 Subject: [PATCH] Adjuster fixes and added GUI prompt for applying last settings (#173) --- LttPAdjuster.py | 183 ++++++++++++++++++++++++++++++++++++------------ Patch.py | 58 ++++++++++++++- SNIClient.py | 129 ++++++++++++++++++++++++++++++++-- Utils.py | 69 ++++-------------- 4 files changed, 328 insertions(+), 111 deletions(-) diff --git a/LttPAdjuster.py b/LttPAdjuster.py index 148fa55f..452aaf91 100644 --- a/LttPAdjuster.py +++ b/LttPAdjuster.py @@ -14,14 +14,15 @@ import tkinter as tk from argparse import Namespace from concurrent.futures import as_completed, ThreadPoolExecutor from glob import glob -from tkinter import Tk, Frame, Label, StringVar, Entry, filedialog, messagebox, Button, LEFT, X, TOP, LabelFrame, \ +from tkinter import Tk, Frame, Label, StringVar, Entry, filedialog, messagebox, Button, Radiobutton, LEFT, X, TOP, LabelFrame, \ IntVar, Checkbutton, E, W, OptionMenu, Toplevel, BOTTOM, RIGHT, font as font, PhotoImage +from tkinter.constants import DISABLED, NORMAL from urllib.parse import urlparse from urllib.request import urlopen from worlds.alttp.Rom import Sprite, LocalRom, apply_rom_settings, get_base_rom_bytes -from Utils import output_path, local_path, open_file, get_cert_none_ssl_context, persistent_store - +from Utils import output_path, local_path, open_file, get_cert_none_ssl_context, persistent_store, get_adjuster_settings, tkinter_center_window +from Patch import GAME_ALTTP class AdjusterWorld(object): def __init__(self, sprite_pool): @@ -121,7 +122,7 @@ def main(): args, path = adjust(args=args) if isinstance(args.sprite, Sprite): args.sprite = args.sprite.name - persistent_store("adjuster", "last_settings_3", args) + persistent_store("adjuster", GAME_ALTTP, args) def adjust(args): @@ -196,6 +197,7 @@ def adjustGUI(): def adjustRom(): guiargs = Namespace() + guiargs.auto_apply = rom_vars.auto_apply.get() guiargs.heartbeep = rom_vars.heartbeepVar.get() guiargs.heartcolor = rom_vars.heartcolorVar.get() guiargs.menuspeed = rom_vars.menuspeedVar.get() @@ -226,14 +228,43 @@ def adjustGUI(): messagebox.showinfo(title="Success", message=f"Rom patched successfully to {path}") if isinstance(guiargs.sprite, Sprite): guiargs.sprite = guiargs.sprite.name - persistent_store("adjuster", "last_settings_3", guiargs) + delattr(guiargs, "rom") + persistent_store("adjuster", GAME_ALTTP, guiargs) + + def saveGUISettings(): + guiargs = Namespace() + guiargs.auto_apply = rom_vars.auto_apply.get() + guiargs.heartbeep = rom_vars.heartbeepVar.get() + guiargs.heartcolor = rom_vars.heartcolorVar.get() + guiargs.menuspeed = rom_vars.menuspeedVar.get() + guiargs.ow_palettes = rom_vars.owPalettesVar.get() + guiargs.uw_palettes = rom_vars.uwPalettesVar.get() + guiargs.hud_palettes = rom_vars.hudPalettesVar.get() + guiargs.sword_palettes = rom_vars.swordPalettesVar.get() + guiargs.shield_palettes = rom_vars.shieldPalettesVar.get() + guiargs.quickswap = bool(rom_vars.quickSwapVar.get()) + guiargs.music = bool(rom_vars.MusicVar.get()) + guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get()) + guiargs.deathlink = bool(rom_vars.DeathLinkVar.get()) + guiargs.baserom = romVar.get() + if isinstance(rom_vars.sprite, Sprite): + guiargs.sprite = rom_vars.sprite.name + else: + guiargs.sprite = rom_vars.sprite + guiargs.sprite_pool = rom_vars.sprite_pool + persistent_store("adjuster", GAME_ALTTP, guiargs) + messagebox.showinfo(title="Success", message="Settings saved to persistent storage") adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom) rom_options_frame.pack(side=TOP) - adjustButton.pack(side=BOTTOM, padx=(5, 5)) + adjustButton.pack(side=LEFT, padx=(5,5)) - bottomFrame2.pack(side=BOTTOM, pady=(5, 5)) + saveButton = Button(bottomFrame2, text='Save Settings', command=saveGUISettings) + saveButton.pack(side=LEFT, padx=(5,5)) + bottomFrame2.pack(side=TOP, pady=(5,5)) + + tkinter_center_window(adjustWindow) adjustWindow.mainloop() @@ -437,9 +468,14 @@ class BackgroundTaskProgressNullWindow(BackgroundTask): def get_rom_frame(parent=None): + adjuster_settings = get_adjuster_settings(GAME_ALTTP) + if not adjuster_settings: + adjuster_settings = Namespace() + adjuster_settings.baserom = "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" + romFrame = Frame(parent) baseRomLabel = Label(romFrame, text='LttP Base Rom: ') - romVar = StringVar(value="Zelda no Densetsu - Kamigami no Triforce (Japan).sfc") + romVar = StringVar(value=adjuster_settings.baserom) romEntry = Entry(romFrame, textvariable=romVar) def RomSelect(): @@ -465,6 +501,26 @@ def get_rom_frame(parent=None): def get_rom_options_frame(parent=None): + adjuster_settings = get_adjuster_settings(GAME_ALTTP) + if not adjuster_settings: + adjuster_settings = Namespace() + adjuster_settings.auto_apply = 'ask' + adjuster_settings.music = True + adjuster_settings.reduceflashing = True + adjuster_settings.deathlink = False + adjuster_settings.sprite = None + adjuster_settings.quickswap = True + adjuster_settings.menuspeed = 'normal' + adjuster_settings.heartcolor = 'red' + adjuster_settings.heartbeep = 'normal' + adjuster_settings.ow_palettes = 'default' + adjuster_settings.uw_palettes = 'default' + adjuster_settings.hud_palettes = 'default' + adjuster_settings.sword_palettes = 'default' + adjuster_settings.shield_palettes = 'default' + if not hasattr(adjuster_settings, 'sprite_pool'): + adjuster_settings.sprite_pool = [] + romOptionsFrame = LabelFrame(parent, text="Rom options") romOptionsFrame.columnconfigure(0, weight=1) romOptionsFrame.columnconfigure(1, weight=1) @@ -473,16 +529,16 @@ def get_rom_options_frame(parent=None): vars = Namespace() vars.MusicVar = IntVar() - vars.MusicVar.set(1) + vars.MusicVar.set(adjuster_settings.music) MusicCheckbutton = Checkbutton(romOptionsFrame, text="Music", variable=vars.MusicVar) MusicCheckbutton.grid(row=0, column=0, sticky=E) - vars.disableFlashingVar = IntVar(value=1) + vars.disableFlashingVar = IntVar(value=adjuster_settings.reduceflashing) disableFlashingCheckbutton = Checkbutton(romOptionsFrame, text="Disable flashing (anti-epilepsy)", variable=vars.disableFlashingVar) disableFlashingCheckbutton.grid(row=6, column=0, sticky=W) - vars.DeathLinkVar = IntVar(value=0) + vars.DeathLinkVar = IntVar(value=adjuster_settings.deathlink) DeathLinkCheckbutton = Checkbutton(romOptionsFrame, text="DeathLink (Team Deaths)", variable=vars.DeathLinkVar) DeathLinkCheckbutton.grid(row=7, column=0, sticky=W) @@ -491,7 +547,7 @@ def get_rom_options_frame(parent=None): baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:') vars.spriteNameVar = StringVar() - vars.sprite = None + vars.sprite = adjuster_settings.sprite def set_sprite(sprite_param): nonlocal vars @@ -505,8 +561,8 @@ def get_rom_options_frame(parent=None): vars.sprite = sprite_param vars.spriteNameVar.set(vars.sprite.name) - set_sprite(None) - vars.spriteNameVar.set('(unchanged)') + set_sprite(adjuster_settings.sprite) + #vars.spriteNameVar.set(adjuster_settings.sprite) spriteEntry = Label(spriteDialogFrame, textvariable=vars.spriteNameVar) def SpriteSelect(): @@ -519,7 +575,7 @@ def get_rom_options_frame(parent=None): spriteEntry.pack(side=LEFT) spriteSelectButton.pack(side=LEFT) - vars.quickSwapVar = IntVar(value=1) + vars.quickSwapVar = IntVar(value=adjuster_settings.quickswap) quickSwapCheckbutton = Checkbutton(romOptionsFrame, text="L/R Quickswapping", variable=vars.quickSwapVar) quickSwapCheckbutton.grid(row=1, column=0, sticky=E) @@ -528,7 +584,7 @@ def get_rom_options_frame(parent=None): menuspeedLabel = Label(menuspeedFrame, text='Menu speed') menuspeedLabel.pack(side=LEFT) vars.menuspeedVar = StringVar() - vars.menuspeedVar.set('normal') + vars.menuspeedVar.set(adjuster_settings.menuspeed) menuspeedOptionMenu = OptionMenu(menuspeedFrame, vars.menuspeedVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half') menuspeedOptionMenu.pack(side=LEFT) @@ -538,7 +594,7 @@ def get_rom_options_frame(parent=None): heartcolorLabel = Label(heartcolorFrame, text='Heart color') heartcolorLabel.pack(side=LEFT) vars.heartcolorVar = StringVar() - vars.heartcolorVar.set('red') + vars.heartcolorVar.set(adjuster_settings.heartcolor) heartcolorOptionMenu = OptionMenu(heartcolorFrame, vars.heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random') heartcolorOptionMenu.pack(side=LEFT) @@ -547,7 +603,7 @@ def get_rom_options_frame(parent=None): heartbeepLabel = Label(heartbeepFrame, text='Heartbeep') heartbeepLabel.pack(side=LEFT) vars.heartbeepVar = StringVar() - vars.heartbeepVar.set('normal') + vars.heartbeepVar.set(adjuster_settings.heartbeep) heartbeepOptionMenu = OptionMenu(heartbeepFrame, vars.heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off') heartbeepOptionMenu.pack(side=LEFT) @@ -556,7 +612,7 @@ def get_rom_options_frame(parent=None): owPalettesLabel = Label(owPalettesFrame, text='Overworld palettes') owPalettesLabel.pack(side=LEFT) vars.owPalettesVar = StringVar() - vars.owPalettesVar.set('default') + vars.owPalettesVar.set(adjuster_settings.ow_palettes) owPalettesOptionMenu = OptionMenu(owPalettesFrame, vars.owPalettesVar, 'default', 'good', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke') owPalettesOptionMenu.pack(side=LEFT) @@ -566,7 +622,7 @@ def get_rom_options_frame(parent=None): uwPalettesLabel = Label(uwPalettesFrame, text='Dungeon palettes') uwPalettesLabel.pack(side=LEFT) vars.uwPalettesVar = StringVar() - vars.uwPalettesVar.set('default') + vars.uwPalettesVar.set(adjuster_settings.uw_palettes) uwPalettesOptionMenu = OptionMenu(uwPalettesFrame, vars.uwPalettesVar, 'default', 'good', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke') uwPalettesOptionMenu.pack(side=LEFT) @@ -576,7 +632,7 @@ def get_rom_options_frame(parent=None): hudPalettesLabel = Label(hudPalettesFrame, text='HUD palettes') hudPalettesLabel.pack(side=LEFT) vars.hudPalettesVar = StringVar() - vars.hudPalettesVar.set('default') + vars.hudPalettesVar.set(adjuster_settings.hud_palettes) hudPalettesOptionMenu = OptionMenu(hudPalettesFrame, vars.hudPalettesVar, 'default', 'good', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke') hudPalettesOptionMenu.pack(side=LEFT) @@ -586,7 +642,7 @@ def get_rom_options_frame(parent=None): swordPalettesLabel = Label(swordPalettesFrame, text='Sword palettes') swordPalettesLabel.pack(side=LEFT) vars.swordPalettesVar = StringVar() - vars.swordPalettesVar.set('default') + vars.swordPalettesVar.set(adjuster_settings.sword_palettes) swordPalettesOptionMenu = OptionMenu(swordPalettesFrame, vars.swordPalettesVar, 'default', 'good', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke') swordPalettesOptionMenu.pack(side=LEFT) @@ -596,7 +652,7 @@ def get_rom_options_frame(parent=None): shieldPalettesLabel = Label(shieldPalettesFrame, text='Shield palettes') shieldPalettesLabel.pack(side=LEFT) vars.shieldPalettesVar = StringVar() - vars.shieldPalettesVar.set('default') + vars.shieldPalettesVar.set(adjuster_settings.shield_palettes) shieldPalettesOptionMenu = OptionMenu(shieldPalettesFrame, vars.shieldPalettesVar, 'default', 'good', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke') shieldPalettesOptionMenu.pack(side=LEFT) @@ -606,7 +662,7 @@ def get_rom_options_frame(parent=None): baseSpritePoolLabel = Label(spritePoolFrame, text='Sprite Pool:') vars.spritePoolCountVar = StringVar() - vars.sprite_pool = [] + vars.sprite_pool = adjuster_settings.sprite_pool def set_sprite_pool(sprite_param): nonlocal vars @@ -625,7 +681,7 @@ def get_rom_options_frame(parent=None): vars.spritePoolCountVar.set(str(len(vars.sprite_pool))) set_sprite_pool(None) - vars.spritePoolCountVar.set('0') + vars.spritePoolCountVar.set(len(adjuster_settings.sprite_pool)) spritePoolEntry = Label(spritePoolFrame, textvariable=vars.spritePoolCountVar) def SpritePoolSelect(): @@ -645,6 +701,18 @@ def get_rom_options_frame(parent=None): spritePoolSelectButton.pack(side=LEFT) spritePoolClearButton.pack(side=LEFT) + vars.auto_apply = StringVar(value=adjuster_settings.auto_apply) + autoApplyFrame = Frame(romOptionsFrame) + autoApplyFrame.grid(row=8, column=0, columnspan=2, sticky=W) + filler = Label(autoApplyFrame, text="Automatically apply last used settings on opening .apbp files") + filler.pack(side=TOP, expand=True, fill=X) + askRadio = Radiobutton(autoApplyFrame, text='Ask', variable=vars.auto_apply, value='ask') + askRadio.pack(side=LEFT, padx=5, pady=5) + alwaysRadio = Radiobutton(autoApplyFrame, text='Always', variable=vars.auto_apply, value='always') + alwaysRadio.pack(side=LEFT, padx=5, pady=5) + neverRadio = Radiobutton(autoApplyFrame, text='Never', variable=vars.auto_apply, value='never') + neverRadio.pack(side=LEFT, padx=5, pady=5) + return romOptionsFrame, vars, set_sprite @@ -693,6 +761,9 @@ class SpriteSelector(): button = Button(frame, text="Update alttpr sprites", command=self.update_alttpr_sprites) button.pack(side=RIGHT, padx=(5, 0)) + + button = Button(frame, text="Do not adjust sprite",command=self.use_default_sprite) + button.pack(side=LEFT,padx=(0,5)) button = Button(frame, text="Default Link sprite", command=self.use_default_link_sprite) button.pack(side=LEFT, padx=(0, 5)) @@ -710,36 +781,36 @@ class SpriteSelector(): self.randomOnItemVar = IntVar() self.randomOnBonkVar = IntVar() self.randomOnRandomVar = IntVar() + self.randomOnAllVar = IntVar() if self.randomOnEvent: - button = Checkbutton(frame, text="Hit", command=self.update_random_button, variable=self.randomOnHitVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonHit = Checkbutton(frame, text="Hit", command=self.update_random_button, variable=self.randomOnHitVar) + self.buttonHit.pack(side=LEFT, padx=(0, 5)) - button = Checkbutton(frame, text="Enter", command=self.update_random_button, variable=self.randomOnEnterVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonEnter = Checkbutton(frame, text="Enter", command=self.update_random_button, variable=self.randomOnEnterVar) + self.buttonEnter.pack(side=LEFT, padx=(0, 5)) - button = Checkbutton(frame, text="Exit", command=self.update_random_button, variable=self.randomOnExitVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonExit = Checkbutton(frame, text="Exit", command=self.update_random_button, variable=self.randomOnExitVar) + self.buttonExit.pack(side=LEFT, padx=(0, 5)) - button = Checkbutton(frame, text="Slash", command=self.update_random_button, variable=self.randomOnSlashVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonSlash = Checkbutton(frame, text="Slash", command=self.update_random_button, variable=self.randomOnSlashVar) + self.buttonSlash.pack(side=LEFT, padx=(0, 5)) - button = Checkbutton(frame, text="Item", command=self.update_random_button, variable=self.randomOnItemVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonItem = Checkbutton(frame, text="Item", command=self.update_random_button, variable=self.randomOnItemVar) + self.buttonItem.pack(side=LEFT, padx=(0, 5)) - button = Checkbutton(frame, text="Bonk", command=self.update_random_button, variable=self.randomOnBonkVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonBonk = Checkbutton(frame, text="Bonk", command=self.update_random_button, variable=self.randomOnBonkVar) + self.buttonBonk.pack(side=LEFT, padx=(0, 5)) - button = Checkbutton(frame, text="Random", command=self.update_random_button, - variable=self.randomOnRandomVar) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonRandom = Checkbutton(frame, text="Random", command=self.update_random_button, variable=self.randomOnRandomVar) + self.buttonRandom.pack(side=LEFT, padx=(0, 5)) - if adjuster: - button = Button(frame, text="Current sprite from rom", command=self.use_default_sprite) - button.pack(side=LEFT, padx=(0, 5)) + self.buttonAll = Checkbutton(frame, text="All", command=self.update_random_button, variable=self.randomOnAllVar) + self.buttonAll.pack(side=LEFT, padx=(0, 5)) set_icon(self.window) self.window.focus() + tkinter_center_window(self.window) def remove_from_sprite_pool(self, button, spritename): self.callback(("remove", spritename)) @@ -879,9 +950,31 @@ class SpriteSelector(): self.add_to_sprite_pool("link") def update_random_button(self): - if self.randomOnRandomVar.get(): + if self.randomOnAllVar.get(): + randomon = "all" + self.buttonHit.config(state=DISABLED) + self.buttonEnter.config(state=DISABLED) + self.buttonExit.config(state=DISABLED) + self.buttonSlash.config(state=DISABLED) + self.buttonItem.config(state=DISABLED) + self.buttonBonk.config(state=DISABLED) + self.buttonRandom.config(state=DISABLED) + elif self.randomOnRandomVar.get(): randomon = "random" + self.buttonHit.config(state=DISABLED) + self.buttonEnter.config(state=DISABLED) + self.buttonExit.config(state=DISABLED) + self.buttonSlash.config(state=DISABLED) + self.buttonItem.config(state=DISABLED) + self.buttonBonk.config(state=DISABLED) else: + self.buttonHit.config(state=NORMAL) + self.buttonEnter.config(state=NORMAL) + self.buttonExit.config(state=NORMAL) + self.buttonSlash.config(state=NORMAL) + self.buttonItem.config(state=NORMAL) + self.buttonBonk.config(state=NORMAL) + self.buttonRandom.config(state=NORMAL) randomon = "-hit" if self.randomOnHitVar.get() else "" randomon += "-enter" if self.randomOnEnterVar.get() else "" randomon += "-exit" if self.randomOnExitVar.get() else "" @@ -1150,4 +1243,4 @@ class ToolTips(object): if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/Patch.py b/Patch.py index e9b3c800..2b5ccf12 100644 --- a/Patch.py +++ b/Patch.py @@ -1,5 +1,6 @@ # TODO: convert this into a system like AutoWorld +import shutil import bsdiff4 import yaml import os @@ -146,10 +147,63 @@ if __name__ == "__main__": elif rom.endswith(".apbp"): print(f"Applying patch {rom}") data, target = create_rom_file(rom) - romfile, adjusted = Utils.get_adjuster_settings(target) + #romfile, adjusted = Utils.get_adjuster_settings(target) + adjuster_settings = Utils.get_adjuster_settings(GAME_ALTTP) + adjusted = False + if adjuster_settings: + import pprint + from worlds.alttp.Rom import get_base_rom_path + adjuster_settings.rom = target + adjuster_settings.baserom = get_base_rom_path() + adjuster_settings.world = None + whitelist = {"music", "menuspeed", "heartbeep", "heartcolor", "ow_palettes", "quickswap", + "uw_palettes", "sprite", "sword_palettes", "shield_palettes", "hud_palettes", + "reduceflashing", "deathlink"} + printed_options = {name: value for name, value in vars(adjuster_settings).items() if name in whitelist} + if hasattr(adjuster_settings, "sprite_pool"): + sprite_pool = {} + for sprite in getattr(adjuster_settings, "sprite_pool"): + if sprite in sprite_pool: + sprite_pool[sprite] += 1 + else: + sprite_pool[sprite] = 1 + if sprite_pool: + printed_options["sprite_pool"] = sprite_pool + + adjust_wanted = str('no') + if not hasattr(adjuster_settings, 'auto_apply') or 'ask' in adjuster_settings.auto_apply: + adjust_wanted = input(f"Last used adjuster settings were found. Would you like to apply these? \n" + f"{pprint.pformat(printed_options)}\n" + f"Enter yes, no, always or never: ") + if adjuster_settings.auto_apply == 'never': # never adjust, per user request + adjust_wanted = 'no' + elif adjuster_settings.auto_apply == 'always': + adjust_wanted = 'yes' + + if adjust_wanted and "never" in adjust_wanted: + adjuster_settings.auto_apply = 'never' + Utils.persistent_store("adjuster", GAME_ALTTP, adjuster_settings) + + elif adjust_wanted and "always" in adjust_wanted: + adjuster_settings.auto_apply = 'always' + Utils.persistent_store("adjuster", GAME_ALTTP, adjuster_settings) + + if adjust_wanted and adjust_wanted.startswith("y"): + if hasattr(adjuster_settings, "sprite_pool"): + from LttPAdjuster import AdjusterWorld + adjuster_settings.world = AdjusterWorld(getattr(adjuster_settings, "sprite_pool")) + + adjusted = True + import LttPAdjuster + _, romfile = LttPAdjuster.adjust(adjuster_settings) + + if hasattr(adjuster_settings, "world"): + delattr(adjuster_settings, "world") + else: + adjusted = False if adjusted: try: - os.replace(romfile, target) + shutil.move(romfile, target) romfile = target except Exception as e: print(e) diff --git a/SNIClient.py b/SNIClient.py index 6215ffad..af63b1fa 100644 --- a/SNIClient.py +++ b/SNIClient.py @@ -11,6 +11,7 @@ import shutil import logging import asyncio from json import loads, dumps +from tkinter import font from Utils import get_item_name_from_id, init_logging @@ -1087,13 +1088,7 @@ async def main(): time.sleep(3) sys.exit() elif args.diff_file.endswith((".apbp", "apz3")): - adjustedromfile, adjusted = Utils.get_adjuster_settings(romfile, gui_enabled) - if adjusted: - try: - shutil.move(adjustedromfile, romfile) - adjustedromfile = romfile - except Exception as e: - logging.exception(e) + adjustedromfile, adjusted = get_alttp_settings(romfile) asyncio.create_task(run_game(adjustedromfile if adjusted else romfile)) else: asyncio.create_task(run_game(romfile)) @@ -1131,6 +1126,126 @@ async def main(): if input_task: input_task.cancel() +def get_alttp_settings(romfile: str): + lastSettings = Utils.get_adjuster_settings(GAME_ALTTP) + adjusted = False + adjustedromfile = '' + if lastSettings: + choice = 'no' + if not hasattr(lastSettings, 'auto_apply') or 'ask' in lastSettings.auto_apply: + + whitelist = {"music", "menuspeed", "heartbeep", "heartcolor", "ow_palettes", "quickswap", + "uw_palettes", "sprite", "sword_palettes", "shield_palettes", "hud_palettes", + "reduceflashing", "deathlink"} + printed_options = {name: value for name, value in vars(lastSettings).items() if name in whitelist} + if hasattr(lastSettings, "sprite_pool"): + sprite_pool = {} + for sprite in lastSettings.sprite_pool: + if sprite in sprite_pool: + sprite_pool[sprite] += 1 + else: + sprite_pool[sprite] = 1 + if sprite_pool: + printed_options["sprite_pool"] = sprite_pool + import pprint + + if gui_enabled: + + from tkinter import Tk, PhotoImage, Label, LabelFrame, Frame, Button + applyPromptWindow = Tk() + applyPromptWindow.resizable(False, False) + applyPromptWindow.protocol('WM_DELETE_WINDOW',lambda: onButtonClick()) + logo = PhotoImage(file=Utils.local_path('data', 'icon.png')) + applyPromptWindow.tk.call('wm', 'iconphoto', applyPromptWindow._w, logo) + applyPromptWindow.wm_title("Last adjuster settings LttP") + + label = LabelFrame(applyPromptWindow, + text='Last used adjuster settings were found. Would you like to apply these?') + label.grid(column=0,row=0, padx=5, pady=5, ipadx=5, ipady=5) + label.grid_columnconfigure (0, weight=1) + label.grid_columnconfigure (1, weight=1) + label.grid_columnconfigure (2, weight=1) + label.grid_columnconfigure (3, weight=1) + def onButtonClick(answer: str='no'): + setattr(onButtonClick, 'choice', answer) + applyPromptWindow.destroy() + + framedOptions = Frame(label) + framedOptions.grid(column=0, columnspan=4,row=0) + framedOptions.grid_columnconfigure(0, weight=1) + framedOptions.grid_columnconfigure(1, weight=1) + framedOptions.grid_columnconfigure(2, weight=1) + curRow = 0 + curCol = 0 + for name, value in printed_options.items(): + Label(framedOptions, text=name+": "+str(value)).grid(column=curCol, row=curRow, padx=5) + if(curCol==2): + curRow+=1 + curCol=0 + else: + curCol+=1 + + yesButton = Button(label, text='Yes', command=lambda: onButtonClick('yes'), width=10) + yesButton.grid(column=0, row=1) + noButton = Button(label, text='No', command=lambda: onButtonClick('no'), width=10) + noButton.grid(column=1, row=1) + alwaysButton = Button(label, text='Always', command=lambda: onButtonClick('always'), width=10) + alwaysButton.grid(column=2, row=1) + neverButton = Button(label, text='Never', command=lambda: onButtonClick('never'), width=10) + neverButton.grid(column=3, row=1) + + Utils.tkinter_center_window(applyPromptWindow) + applyPromptWindow.mainloop() + choice = getattr(onButtonClick, 'choice') + else: + choice = input(f"Last used adjuster settings were found. Would you like to apply these? \n" + f"{pprint.pformat(printed_options)}\n" + f"Enter yes, no, always or never: ") + if choice and choice.startswith("y"): + choice = 'yes' + elif choice and "never" in choice: + choice = 'no' + lastSettings.auto_apply = 'never' + Utils.persistent_store("adjuster", GAME_ALTTP, lastSettings) + elif choice and "always" in choice: + choice = 'yes' + lastSettings.auto_apply = 'always' + Utils.persistent_store("adjuster", GAME_ALTTP, lastSettings) + else: + choice = 'no' + elif 'never' in lastSettings.auto_apply: + choice = 'no' + elif 'always' in lastSettings.auto_apply: + choice = 'yes' + + if 'yes' in choice: + from worlds.alttp.Rom import get_base_rom_path + lastSettings.rom = romfile + lastSettings.baserom = get_base_rom_path() + lastSettings.world = None + + if hasattr(lastSettings, "sprite_pool"): + from LttPAdjuster import AdjusterWorld + lastSettings.world = AdjusterWorld(getattr(lastSettings, "sprite_pool")) + + adjusted = True + import LttPAdjuster + _, adjustedromfile = LttPAdjuster.adjust(lastSettings) + + if hasattr(lastSettings, "world"): + delattr(lastSettings, "world") + else: + adjusted = False; + if adjusted: + try: + shutil.move(adjustedromfile, romfile) + adjustedromfile = romfile + except Exception as e: + logging.exception(e) + else: + + adjusted = False + return adjustedromfile, adjusted if __name__ == '__main__': colorama.init() diff --git a/Utils.py b/Utils.py index bf29bde6..35a71473 100644 --- a/Utils.py +++ b/Utils.py @@ -11,6 +11,7 @@ import io import collections import importlib import logging +from tkinter import Tk def tuplize_version(version: str) -> Version: @@ -313,63 +314,9 @@ def persistent_load() -> typing.Dict[dict]: return storage -def get_adjuster_settings(romfile: str, skip_questions: bool = False) -> typing.Tuple[str, bool]: - if hasattr(get_adjuster_settings, "adjuster_settings"): - adjuster_settings = getattr(get_adjuster_settings, "adjuster_settings") - else: - adjuster_settings = persistent_load().get("adjuster", {}).get("last_settings_3", {}) - - if adjuster_settings: - import pprint - from worlds.alttp.Rom import get_base_rom_path - adjuster_settings.rom = romfile - adjuster_settings.baserom = get_base_rom_path() - adjuster_settings.world = None - whitelist = {"music", "menuspeed", "heartbeep", "heartcolor", "ow_palettes", "quickswap", - "uw_palettes", "sprite"} - printed_options = {name: value for name, value in vars(adjuster_settings).items() if name in whitelist} - if hasattr(adjuster_settings, "sprite_pool"): - sprite_pool = {} - for sprite in getattr(adjuster_settings, "sprite_pool"): - if sprite in sprite_pool: - sprite_pool[sprite] += 1 - else: - sprite_pool[sprite] = 1 - if sprite_pool: - printed_options["sprite_pool"] = sprite_pool - - if hasattr(get_adjuster_settings, "adjust_wanted"): - adjust_wanted = getattr(get_adjuster_settings, "adjust_wanted") - elif persistent_load().get("adjuster", {}).get("never_adjust", False): # never adjust, per user request - return romfile, False - elif skip_questions: - return romfile, False - else: - adjust_wanted = input(f"Last used adjuster settings were found. Would you like to apply these? \n" - f"{pprint.pformat(printed_options)}\n" - f"Enter yes, no or never: ") - if adjust_wanted and adjust_wanted.startswith("y"): - if hasattr(adjuster_settings, "sprite_pool"): - from LttPAdjuster import AdjusterWorld - adjuster_settings.world = AdjusterWorld(getattr(adjuster_settings, "sprite_pool")) - - adjusted = True - import LttPAdjuster - _, romfile = LttPAdjuster.adjust(adjuster_settings) - - if hasattr(adjuster_settings, "world"): - delattr(adjuster_settings, "world") - elif adjust_wanted and "never" in adjust_wanted: - persistent_store("adjuster", "never_adjust", True) - return romfile, False - else: - adjusted = False - if not hasattr(get_adjuster_settings, "adjust_wanted"): - logging.info(f"Skipping post-patch adjustment") - get_adjuster_settings.adjuster_settings = adjuster_settings - get_adjuster_settings.adjust_wanted = adjust_wanted - return romfile, adjusted - return romfile, False +def get_adjuster_settings(gameName: str): + adjuster_settings = persistent_load().get("adjuster", {}).get(gameName, {}) + return adjuster_settings @cache_argsless @@ -488,5 +435,13 @@ def stream_input(stream, queue): return thread +def tkinter_center_window(window: Tk): + window.update() + xPos = int(window.winfo_screenwidth()/2 - window.winfo_reqwidth()/2) + yPos = int(window.winfo_screenheight()/2 - window.winfo_reqheight()/2) + window.geometry("+{}+{}".format(xPos, yPos)) + + class VersionException(Exception): pass +