From 18e0008a998c92b3789c1e2c93282679e9e45ed2 Mon Sep 17 00:00:00 2001 From: "Mike A. Trethewey" Date: Sat, 8 Feb 2020 23:59:58 -0800 Subject: [PATCH] Pretty Item Rando options --- gui/bottom.py | 26 ++-- gui/loadcliargs.py | 26 ++-- gui/randomize/item.py | 299 ++++++++++++++++++++++++++++-------------- gui/widgets.py | 61 +++++++++ 4 files changed, 286 insertions(+), 126 deletions(-) create mode 100644 gui/widgets.py diff --git a/gui/bottom.py b/gui/bottom.py index b009d30d..3f4e13f5 100644 --- a/gui/bottom.py +++ b/gui/bottom.py @@ -35,19 +35,19 @@ def bottom_frame(self,parent,args=None): guiargs.names = parent.multiworldWindow.namesVar.get() guiargs.seed = int(parent.farBottomFrame.seedVar.get()) if parent.farBottomFrame.seedVar.get() else None guiargs.count = int(parent.farBottomFrame.countVar.get()) if parent.farBottomFrame.countVar.get() != '1' else None - guiargs.mode = parent.itemWindow.modeVar.get() - guiargs.logic = parent.itemWindow.logicVar.get() + guiargs.mode = parent.itemWindow.itemWidgets["worldState"].storageVar.get() + guiargs.logic = parent.itemWindow.itemWidgets["logicLevel"].storageVar.get() - guiargs.goal = parent.itemWindow.goalVar.get() - guiargs.crystals_gt = parent.itemWindow.crystalsGTVar.get() - guiargs.crystals_ganon = parent.itemWindow.crystalsGanonVar.get() - guiargs.swords = parent.itemWindow.swordVar.get() - guiargs.difficulty = parent.itemWindow.difficultyVar.get() - guiargs.item_functionality = parent.itemWindow.itemfunctionVar.get() - guiargs.timer = parent.itemWindow.timerVar.get() - guiargs.progressive = parent.itemWindow.progressiveVar.get() - guiargs.accessibility = parent.itemWindow.accessibilityVar.get() - guiargs.algorithm = parent.itemWindow.algorithmVar.get() + guiargs.goal = parent.itemWindow.itemWidgets["goal"].storageVar.get() + guiargs.crystals_gt = parent.itemWindow.itemWidgets["crystals_gt"].storageVar.get() + guiargs.crystals_ganon = parent.itemWindow.itemWidgets["crystals_ganon"].storageVar.get() + guiargs.swords = parent.itemWindow.itemWidgets["weapons"].storageVar.get() + guiargs.difficulty = parent.itemWindow.itemWidgets["itempool"].storageVar.get() + guiargs.item_functionality = parent.itemWindow.itemWidgets["itemfunction"].storageVar.get() + guiargs.timer = parent.itemWindow.itemWidgets["timer"].storageVar.get() + guiargs.progressive = parent.itemWindow.itemWidgets["progressives"].storageVar.get() + guiargs.accessibility = parent.itemWindow.itemWidgets["accessibility"].storageVar.get() + guiargs.algorithm = parent.itemWindow.itemWidgets["sortingalgo"].storageVar.get() guiargs.shuffle = parent.entrandoWindow.shuffleVar.get() guiargs.door_shuffle = parent.dungeonRandoWindow.doorShuffleVar.get() guiargs.heartbeep = parent.gameOptionsWindow.heartbeepVar.get() @@ -61,7 +61,7 @@ def bottom_frame(self,parent,args=None): guiargs.compassshuffle = bool(parent.dungeonRandoWindow.compassshuffleVar.get()) guiargs.keyshuffle = bool(parent.dungeonRandoWindow.keyshuffleVar.get()) guiargs.bigkeyshuffle = bool(parent.dungeonRandoWindow.bigkeyshuffleVar.get()) - guiargs.retro = bool(parent.itemWindow.retroVar.get()) + guiargs.retro = bool(parent.itemWindow.itemWidgets["retro"].storageVar.get()) guiargs.quickswap = bool(parent.gameOptionsWindow.quickSwapVar.get()) guiargs.disablemusic = bool(parent.gameOptionsWindow.disableMusicVar.get()) guiargs.ow_palettes = parent.gameOptionsWindow.owPalettesVar.get() diff --git a/gui/loadcliargs.py b/gui/loadcliargs.py index 4b8fb2c4..e88180d9 100644 --- a/gui/loadcliargs.py +++ b/gui/loadcliargs.py @@ -10,7 +10,7 @@ def loadcliargs(gui,args): gui.dungeonRandoWindow.compassshuffleVar.set(args.compassshuffle) gui.dungeonRandoWindow.keyshuffleVar.set(args.keyshuffle) gui.dungeonRandoWindow.bigkeyshuffleVar.set(args.bigkeyshuffle) - gui.itemWindow.retroVar.set(args.retro) + gui.itemWindow.itemWidgets["retro"].storageVar.set(args.retro) gui.entrandoWindow.openpyramidVar.set(args.openpyramid) gui.gameOptionsWindow.quickSwapVar.set(int(args.quickswap)) gui.gameOptionsWindow.disableMusicVar.set(int(args.disablemusic)) @@ -20,23 +20,23 @@ def loadcliargs(gui,args): gui.farBottomFrame.countVar.set(str(args.count)) if args.seed: gui.farBottomFrame.seedVar.set(str(args.seed)) - gui.itemWindow.modeVar.set(args.mode) - gui.itemWindow.swordVar.set(args.swords) - gui.itemWindow.difficultyVar.set(args.difficulty) - gui.itemWindow.itemfunctionVar.set(args.item_functionality) - gui.itemWindow.timerVar.set(args.timer) - gui.itemWindow.progressiveVar.set(args.progressive) - gui.itemWindow.accessibilityVar.set(args.accessibility) - gui.itemWindow.goalVar.set(args.goal) - gui.itemWindow.crystalsGTVar.set(args.crystals_gt) - gui.itemWindow.crystalsGanonVar.set(args.crystals_ganon) - gui.itemWindow.algorithmVar.set(args.algorithm) + gui.itemWindow.itemWidgets["worldState"].storageVar.set(args.mode) + gui.itemWindow.itemWidgets["weapons"].storageVar.set(args.swords) + gui.itemWindow.itemWidgets["itempool"].storageVar.set(args.difficulty) + gui.itemWindow.itemWidgets["itemfunction"].storageVar.set(args.item_functionality) + gui.itemWindow.itemWidgets["timer"].storageVar.set(args.timer) + gui.itemWindow.itemWidgets["progressives"].storageVar.set(args.progressive) + gui.itemWindow.itemWidgets["accessibility"].storageVar.set(args.accessibility) + gui.itemWindow.itemWidgets["goal"].storageVar.set(args.goal) + gui.itemWindow.itemWidgets["crystals_gt"].storageVar.set(args.crystals_gt) + gui.itemWindow.itemWidgets["crystals_ganon"].storageVar.set(args.crystals_ganon) + gui.itemWindow.itemWidgets["sortingalgo"].storageVar.set(args.algorithm) gui.entrandoWindow.shuffleVar.set(args.shuffle) gui.dungeonRandoWindow.doorShuffleVar.set(args.door_shuffle) gui.gameOptionsWindow.heartcolorVar.set(args.heartcolor) gui.gameOptionsWindow.heartbeepVar.set(args.heartbeep) gui.gameOptionsWindow.fastMenuVar.set(args.fastmenu) - gui.itemWindow.logicVar.set(args.logic) + gui.itemWindow.itemWidgets["logicLevel"].storageVar.set(args.logic) gui.generationSetupWindow.romVar.set(args.rom) gui.entrandoWindow.shuffleGanonVar.set(args.shuffleganon) gui.gameOptionsWindow.hintsVar.set(args.hints) diff --git a/gui/randomize/item.py b/gui/randomize/item.py index 550c9544..2ab1c781 100644 --- a/gui/randomize/item.py +++ b/gui/randomize/item.py @@ -1,4 +1,5 @@ from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT +import gui.widgets as widgets def item_page(parent): # Item Randomizer @@ -6,9 +7,16 @@ def item_page(parent): # Item Randomizer options ## Retro (eventually needs to become a World State) - self.retroVar = IntVar() - retroCheckbutton = Checkbutton(self, text="Retro mode (universal keys)", variable=self.retroVar) - retroCheckbutton.pack(anchor=W) + self.itemWidgets = {} + + self.itemWidgets["retro"] = widgets.make_widget( + self, + "checkbox", + self, + "Retro mode (universal keys)", + None + ) + self.itemWidgets["retro"].pack(anchor=W) leftItemFrame = Frame(self) rightItemFrame = Frame(self) @@ -16,124 +24,215 @@ def item_page(parent): rightItemFrame.pack(side=RIGHT) ## World State - modeFrame = Frame(leftItemFrame) - self.modeVar = StringVar() - self.modeVar.set('open') - modeOptionMenu = OptionMenu(modeFrame, self.modeVar, 'standard', 'open', 'inverted') - modeOptionMenu.pack(side=RIGHT) - modeLabel = Label(modeFrame, text='World State') - modeLabel.pack(side=LEFT) - modeFrame.pack(anchor=E) + key = "worldState" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + leftItemFrame, + "World State", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}, "default": "Open"}, + { + "Standard": "standard", + "Open": "open", + "Inverted": "inverted" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Logic Level - logicFrame = Frame(leftItemFrame) - self.logicVar = StringVar() - self.logicVar.set('noglitches') - logicOptionMenu = OptionMenu(logicFrame, self.logicVar, 'noglitches', 'minorglitches', 'nologic') - logicOptionMenu.pack(side=RIGHT) - logicLabel = Label(logicFrame, text='Game Logic') - logicLabel.pack(side=LEFT) - logicFrame.pack(anchor=E) + key = "logicLevel" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + leftItemFrame, + "Logic Level", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "No Glitches": "noglitches", + "Minor Glitches": "minorglitches", + "No Logic": "nologic" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Goal - goalFrame = Frame(leftItemFrame) - self.goalVar = StringVar() - self.goalVar.set('ganon') - goalOptionMenu = OptionMenu(goalFrame, self.goalVar, 'ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals') - goalOptionMenu.pack(side=RIGHT) - goalLabel = Label(goalFrame, text='Goal') - goalLabel.pack(side=LEFT) - goalFrame.pack(anchor=E) + key = "goal" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + leftItemFrame, + "Goal", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "Defeat Ganon": "ganon", + "Master Sword Pedestal": "pedestal", + "All Dungeons": "dungeons", + "Triforce Hunt": "triforcehunt", + "Crystals": "crystals" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Number of crystals to open GT - crystalsGTFrame = Frame(leftItemFrame) - self.crystalsGTVar = StringVar() - self.crystalsGTVar.set('7') - crystalsGTOptionMenu = OptionMenu(crystalsGTFrame, self.crystalsGTVar, '0', '1', '2', '3', '4', '5', '6', '7', 'random') - crystalsGTOptionMenu.pack(side=RIGHT) - crystalsGTLabel = Label(crystalsGTFrame, text='Crystals to open Ganon\'s Tower') - crystalsGTLabel.pack(side=LEFT) - crystalsGTFrame.pack(anchor=E) + key = "crystals_gt" + keys = [*map(str,range(0,7+1)),"Random"] + vals = [*map(str,range(0,7+1)),"random"] + options = {keys[i]: vals[i] for i in range(len(keys))} + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + leftItemFrame, + "Crystals to open GT", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + options + ) + self.itemWidgets[key].pack(anchor=E) ## Number of crystals to damage Ganon - crystalsGanonFrame = Frame(leftItemFrame) - self.crystalsGanonVar = StringVar() - self.crystalsGanonVar.set('7') - crystalsGanonOptionMenu = OptionMenu(crystalsGanonFrame, self.crystalsGanonVar, '0', '1', '2', '3', '4', '5', '6', '7', 'random') - crystalsGanonOptionMenu.pack(side=RIGHT) - crystalsGanonLabel = Label(crystalsGanonFrame, text='Crystals to fight Ganon') - crystalsGanonLabel.pack(side=LEFT) - crystalsGanonFrame.pack(anchor=E) + key = "crystals_ganon" + keys = [*map(str,range(0,7+1)),"Random"] + vals = [*map(str,range(0,7+1)),"random"] + options = {keys[i]: vals[i] for i in range(len(keys))} + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + leftItemFrame, + "Crystals to harm Ganon", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + options + ) + self.itemWidgets[key].pack(anchor=E) ## Weapons - swordFrame = Frame(leftItemFrame) - self.swordVar = StringVar() - self.swordVar.set('random') - swordOptionMenu = OptionMenu(swordFrame, self.swordVar, 'random', 'assured', 'swordless', 'vanilla') - swordOptionMenu.pack(side=RIGHT) - swordLabel = Label(swordFrame, text='Sword availability') - swordLabel.pack(side=LEFT) - swordFrame.pack(anchor=E) + key = "weapons" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + leftItemFrame, + "Weapons", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "Randomized": "random", + "Assured": "assured", + "Swordless": "swordless", + "Vanilla": "vanilla" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Item Pool - difficultyFrame = Frame(rightItemFrame) - self.difficultyVar = StringVar() - self.difficultyVar.set('normal') - difficultyOptionMenu = OptionMenu(difficultyFrame, self.difficultyVar, 'normal', 'hard', 'expert') - difficultyOptionMenu.pack(side=RIGHT) - difficultyLabel = Label(difficultyFrame, text='Difficulty: item pool') - difficultyLabel.pack(side=LEFT) - difficultyFrame.pack(anchor=E) + key = "itempool" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + rightItemFrame, + "Item Pool", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "Normal": "normal", + "Hard": "hard", + "Expert": "expert" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Item Functionality - itemfunctionFrame = Frame(rightItemFrame) - self.itemfunctionVar = StringVar() - self.itemfunctionVar.set('normal') - itemfunctionOptionMenu = OptionMenu(itemfunctionFrame, self.itemfunctionVar, 'normal', 'hard', 'expert') - itemfunctionOptionMenu.pack(side=RIGHT) - itemfunctionLabel = Label(itemfunctionFrame, text='Difficulty: item functionality') - itemfunctionLabel.pack(side=LEFT) - itemfunctionFrame.pack(anchor=E) + key = "itemfunction" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + rightItemFrame, + "Item Functionality", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "Normal": "normal", + "Hard": "hard", + "Expert": "expert" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Timer setting - timerFrame = Frame(rightItemFrame) - self.timerVar = StringVar() - self.timerVar.set('none') - timerOptionMenu = OptionMenu(timerFrame, self.timerVar, 'none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown') - timerOptionMenu.pack(side=RIGHT) - timerLabel = Label(timerFrame, text='Timer setting') - timerLabel.pack(side=LEFT) - timerFrame.pack(anchor=E) + key = "timer" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + rightItemFrame, + "Timer Setting", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "No Timer": "none", + "Stopwatch": "display", + "Timed": "timed", + "Timed OHKO": "timed-ohko", + "OHKO": "ohko", + "Timed Countdown": "timed-countdown" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Progressives: On/Off - progressiveFrame = Frame(rightItemFrame) - self.progressiveVar = StringVar() - self.progressiveVar.set('on') - progressiveOptionMenu = OptionMenu(progressiveFrame, self.progressiveVar, 'on', 'off', 'random') - progressiveOptionMenu.pack(side=RIGHT) - progressiveLabel = Label(progressiveFrame, text='Progressive equipment') - progressiveLabel.pack(side=LEFT) - progressiveFrame.pack(anchor=E) + key = "progressives" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + rightItemFrame, + "Progressive Items", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "On": "on", + "Off": "off", + "Random": "random" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Accessibilty - accessibilityFrame = Frame(rightItemFrame) - self.accessibilityVar = StringVar() - self.accessibilityVar.set('items') - accessibilityOptionMenu = OptionMenu(accessibilityFrame, self.accessibilityVar, 'items', 'locations', 'none') - accessibilityOptionMenu.pack(side=RIGHT) - accessibilityLabel = Label(accessibilityFrame, text='Item accessibility') - accessibilityLabel.pack(side=LEFT) - accessibilityFrame.pack(anchor=E) - accessibilityFrame.pack(anchor=E) + key = "accessibility" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + rightItemFrame, + "Accessibility", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}}, + { + "100% Inventory": "items", + "100% Locations": "locations", + "Beatable": "none" + } + ) + self.itemWidgets[key].pack(anchor=E) ## Item Sorting Algorithm - algorithmFrame = Frame(rightItemFrame) - self.algorithmVar = StringVar() - self.algorithmVar.set('balanced') - algorithmOptionMenu = OptionMenu(algorithmFrame, self.algorithmVar, 'freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26', 'balanced') - algorithmOptionMenu.pack(side=RIGHT) - algorithmLabel = Label(algorithmFrame, text='Item distribution algorithm') - algorithmLabel.pack(side=LEFT) - algorithmFrame.pack(anchor=E) + key = "sortingalgo" + self.itemWidgets[key] = widgets.make_widget( + self, + "selectbox", + rightItemFrame, + "Item Sorting", + None, + {"label": {"side": LEFT}, "selectbox": {"side": RIGHT}, "default": "Balanced"}, + { + "Freshness": "freshness", + "Flood": "flood", + "VT8.21": "vt21", + "VT8.22": "vt22", + "VT8.25": "vt25", + "VT8.26": "vt26", + "Balanced": "balanced" + } + ) + self.itemWidgets[key].pack(anchor=E) return self diff --git a/gui/widgets.py b/gui/widgets.py new file mode 100644 index 00000000..5887919a --- /dev/null +++ b/gui/widgets.py @@ -0,0 +1,61 @@ +from tkinter import Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, StringVar + +def make_checkbox(self, parent, label, storageVar, packAttrs): + self = Frame(parent) + self.storageVar = storageVar + self.checkbox = Checkbutton(self, text=label, variable=self.storageVar) + self.checkbox.pack(packAttrs) + return self + +def make_selectbox(self, parent, label, options, storageVar, packAttrs): + def change_storage(*args): + self.storageVar.set(options[self.labelVar.get()]) + def change_selected(*args): + keys = options.keys() + vals = options.values() + keysList = list(keys) + valsList = list(vals) + self.labelVar.set(keysList[valsList.index(str(self.storageVar.get()))]) + self = Frame(parent) + self.storageVar = storageVar + self.storageVar.trace_add("write",change_selected) + self.labelVar = StringVar() + self.labelVar.trace_add("write",change_storage) + self.label = Label(self, text=label) + self.label.pack(packAttrs["label"]) + self.selectbox = OptionMenu(self, self.labelVar, *options.keys()) + self.labelVar.set(packAttrs["default"] if "default" in packAttrs else list(options.keys())[0]) + self.selectbox.pack(packAttrs["selectbox"]) + return self + +def make_textbox(self, parent, label, storageVar, packAttrs): + self = Frame(parent) + self.storageVar = storageVar + self.label = Label(self, text=label) + self.label.pack(packAttrs["label"]) + self.textbox = Entry(self) + self.textbox.pack(packAttrs["textbox"]) + return self + +def make_widget(self, type, parent, label, storageVar=None, packAttrs=dict(), options=None): + widget = None + thisStorageVar = None + if isinstance(storageVar,str): + if storageVar == "int" or storageVar == "integer": + thisStorageVar = IntVar() + elif storageVar == "str" or storageVar == "string": + thisStorageVar = StringVar() + + if type == "checkbox": + if thisStorageVar is None: + thisStorageVar = IntVar() + widget = make_checkbox(self, parent, label, thisStorageVar, packAttrs) + elif type == "selectbox": + if thisStorageVar is None: + thisStorageVar = StringVar() + widget = make_selectbox(self, parent, label, options, thisStorageVar, packAttrs) + elif type == "textbox": + if thisStorageVar is None: + thisStorageVar = StringVar() + widget = make_textbox(self, parent, label, thisStorageVar, packAttrs) + return widget