Document stuff, add a couple things

Add Retro World State (Open & Retro on)
Add SpriteSomething plug to sprite selector
Fix Custom Item Pool loading to use disct instead of list
This commit is contained in:
Mike A. Trethewey
2020-03-03 23:43:43 -08:00
parent e093431b00
commit 4968e72a3b
23 changed files with 179 additions and 53 deletions

View File

@@ -73,6 +73,10 @@ class World(object):
self.key_layout = defaultdict(dict)
for player in range(1, players + 1):
# If World State is Retro, set to Open and set Retro flag
if self.mode[player] == "retro":
self.mode[player] = "open"
self.retro[player] = True
def set_player_attr(attr, val):
self.__dict__.setdefault(attr, {})[player] = val
set_player_attr('_region_cache', {})

9
CLI.py
View File

@@ -9,8 +9,6 @@ import shlex
import sys
from Main import main
from Utils import is_bundled, close_console
from Fill import FillError
import classes.constants as CONST
@@ -185,7 +183,7 @@ def parse_arguments(argv, no_defaults=False):
Crossed: Doors are mixed between all dungeons.
(Not yet implemented)
Vanilla: All doors are connected the same way they were in the
base game.
base game.
''')
parser.add_argument('--experimental', default=defval(settings["experimental"] != 0), help='Enable experimental features', action='store_true')
parser.add_argument('--dungeon_counters', default=defval(settings["dungeon_counters"]), help='Enable dungeon chest counters', const='off', nargs='?', choices=['off', 'on', 'pickup'])
@@ -477,7 +475,10 @@ def get_settings():
settings[k] = v
return settings
# Priority fallback is:
# 1: CLI
# 2: Settings file
# 3: Canned defaults
def get_args_priority(settings_args, gui_args, cli_args):
args = {}
args["settings"] = get_settings() if settings_args is None else settings_args

7
Gui.py
View File

@@ -4,8 +4,7 @@ import os
import sys
from tkinter import Tk, Button, BOTTOM, TOP, StringVar, BooleanVar, X, BOTH, RIGHT, ttk, messagebox
from argparse import Namespace
from CLI import get_settings, get_args_priority
from CLI import get_args_priority
from DungeonRandomizer import parse_arguments
from gui.adjust.overview import adjust_page
from gui.startinventory.overview import startinventory_page
@@ -24,6 +23,7 @@ from Main import __version__ as ESVersion
def guiMain(args=None):
# Save settings to file
def save_settings(args):
user_resources_path = os.path.join(".", "resources", "user")
settings_path = os.path.join(user_resources_path)
@@ -35,6 +35,7 @@ def guiMain(args=None):
f.write(json.dumps(args, indent=2))
os.chmod(os.path.join(settings_path, "settings.json"),0o755)
# Save settings from GUI
def save_settings_from_gui(confirm):
gui_args = vars(create_guiargs(self))
if self.randomSprite.get():
@@ -83,6 +84,7 @@ def guiMain(args=None):
# make array for frames
self.frames = {}
# make pages for each section
self.notebook = ttk.Notebook(self)
self.pages["randomizer"] = ttk.Frame(self.notebook)
self.pages["adjust"] = ttk.Frame(self.notebook)
@@ -178,6 +180,7 @@ def guiMain(args=None):
# load adjust settings into options
loadadjustargs(self, self.settings)
# run main window
mainWindow.mainloop()

View File

@@ -126,6 +126,7 @@ difficulties = {
),
}
# Translate between Mike's label array and YAML/JSON keys
def get_custom_array_key(item):
label_switcher = {
"silverarrow": "silversupgrade",
@@ -264,10 +265,10 @@ def generate_itempool(world, player):
if player in world.pool_adjustment.keys():
amt = world.pool_adjustment[player]
if amt < 0:
for i in range(0, amt):
for _ in range(0, amt):
pool.remove('Rupees (20)')
elif amt > 0:
for i in range(0, amt):
for _ in range(0, amt):
pool.append('Rupees (20)')
for item in precollected_items:
@@ -707,24 +708,25 @@ def test():
for difficulty in ['normal', 'hard', 'expert']:
for goal in ['ganon', 'triforcehunt', 'pedestal']:
for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
for mode in ['open', 'standard', 'inverted']:
for mode in ['open', 'standard', 'inverted', 'retro']:
for swords in ['random', 'assured', 'swordless', 'vanilla']:
for progressive in ['on', 'off']:
for shuffle in ['full', 'insanity_legacy']:
for retro in [True, False]:
out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro)
count = len(out[0]) + len(out[1])
for door_shuffle in ['basic', 'crossed', 'vanilla']:
out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, door_shuffle)
count = len(out[0]) + len(out[1])
correct_count = total_items_to_place
if goal == 'pedestal' and swords != 'vanilla':
# pedestal goals generate one extra item
correct_count += 1
if retro:
correct_count += 28
try:
assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro))
except AssertionError as e:
print(e)
correct_count = total_items_to_place
if goal == 'pedestal' and swords != 'vanilla':
# pedestal goals generate one extra item
correct_count += 1
if retro:
correct_count += 28
try:
assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro))
except AssertionError as e:
print(e)
if __name__ == '__main__':
test()

View File

@@ -77,7 +77,8 @@ def main(args, seed=None):
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
if world.mode[player] == 'standard' and world.enemy_shuffle[player] != 'none':
world.escape_assist[player].append('bombs') # enemized escape assumes infinite bombs available and will likely be unbeatable without it
if hasattr(world,"escape_assist") and player in world.escape_assist:
world.escape_assist[player].append('bombs') # enemized escape assumes infinite bombs available and will likely be unbeatable without it
for tok in filter(None, args.startinventory[player].split(',')):
item = ItemFactory(tok.strip(), player)
@@ -383,7 +384,7 @@ def copy_dynamic_regions_and_locations(world, ret):
new_loc.always_allow = location.always_allow
new_loc.item_rule = location.item_rule
new_reg.locations.append(new_loc)
ret.clear_location_cache()

View File

@@ -2,16 +2,20 @@ import subprocess
import os
import shutil
# Destination is current dir
DEST_DIRECTORY = '.'
# Check for UPX
if os.path.isdir("upx"):
upx_string = "--upx-dir=upx"
else:
upx_string = ""
# Nuke Build dir
if os.path.isdir("build"):
shutil.rmtree("build")
# Run pyinstaller for DungeonRandomizer
subprocess.run(" ".join(["pyinstaller DungeonRandomizer.spec ",
upx_string,
"-y ",

View File

@@ -2,16 +2,20 @@ import subprocess
import os
import shutil
# Destination is current dir
DEST_DIRECTORY = '.'
# Check for UPX
if os.path.isdir("upx"):
upx_string = "--upx-dir=upx"
else:
upx_string = ""
# Nuke Build dir
if os.path.isdir("build"):
shutil.rmtree("build")
# Run pyinstaller for Gui
subprocess.run(" ".join(["pyinstaller Gui.spec ",
upx_string,
"-y ",

View File

@@ -1,4 +1,4 @@
from tkinter import filedialog, messagebox, Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, ALL, NSEW, LEFT, BOTTOM, X, RIGHT, TOP, HORIZONTAL, EW, NS
from tkinter import filedialog, messagebox, Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, ALL, LEFT, BOTTOM, X, RIGHT, TOP, EW, NS
from glob import glob
import json
import os
@@ -34,6 +34,7 @@ class SpriteSelector(object):
def open_unofficial_sprite_dir(_evt):
open_file(self.unofficial_sprite_dir)
# Open SpriteSomething directory for Link sprites
def open_spritesomething_listing(_evt):
webbrowser.open("https://artheau.github.io/SpriteSomething/?mode=zelda3/link")
@@ -50,6 +51,7 @@ class SpriteSelector(object):
unofficial_title_text.pack(side=LEFT)
unofficial_title_link.pack(side=LEFT)
unofficial_title_link.bind("<Button-1>", open_unofficial_sprite_dir)
# Include hyperlink to SpriteSomething directory for Link sprites
spritesomething_title_link = Label(unofficial_frametitle, text="(SpriteSomething)", fg="blue", cursor="hand2")
spritesomething_title_link.pack(side=LEFT)
spritesomething_title_link.bind("<Button-1>", open_spritesomething_listing)

View File

@@ -1,3 +1,4 @@
# Ordered list of items in Custom Item Pool page and Starting Inventory page
CUSTOMITEMS = [
"bow", "progressivebow", "boomerang", "redmerang", "hookshot",
"mushroom", "powder", "firerod", "icerod", "bombos",
@@ -20,11 +21,13 @@ CUSTOMITEMS = [
"rupoorcost"
]
# These can't be in the Starting Inventory page
CANTSTARTWITH = [
"triforcepiecesgoal", "triforce", "rupoor",
"rupoorcost"
]
# In the same order as CUSTOMITEMS, these are Pretty Labels for each option
CUSTOMITEMLABELS = [
"Bow", "Progressive Bow", "Blue Boomerang", "Red Boomerang", "Hookshot",
"Mushroom", "Magic Powder", "Fire Rod", "Ice Rod", "Bombos",
@@ -33,7 +36,7 @@ CUSTOMITEMLABELS = [
"Ocarina", "Bug Catching Net", "Book of Mudora", "Bottle", "Cane of Somaria",
"Cane of Byrna", "Magic Cape", "Magic Mirror", "Pegasus Boots", "Power Glove",
"Titans Mitts", "Progressive Glove", "Flippers", "Moon Pearl", "Piece of Heart",
"Boss Heart Container", "Sanctuary Heart Container", "Fighter Sword", "Master Sword", "Tempered Sword",
"Golden Sword", "Progressive Sword", "Blue Shield", "Red Shield", "Mirror Shield",
"Progressive Shield", "Blue Mail", "Red Mail", "Progressive Armor", "Magic Upgrade (1/2)",
@@ -47,6 +50,8 @@ CUSTOMITEMLABELS = [
"Rupoor Cost"
]
# Stuff on each page to save, according to internal names as defined by the widgets definitions
# and how it eventually translates to YAML/JSON weight files
SETTINGSTOPROCESS = {
"randomizer": {
"item": {
@@ -104,6 +109,6 @@ SETTINGSTOPROCESS = {
"usestartinventory": "usestartinventory",
"usecustompool": "custom",
"saveonexit": "saveonexit"
}
}
}
}

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, filedialog, messagebox, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, OptionMenu, E, W, LEFT, RIGHT, X, BOTTOM
from tkinter import ttk, filedialog, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X, BOTTOM
from AdjusterMain import adjust
from argparse import Namespace
from classes.SpriteSelector import SpriteSelector
@@ -19,6 +19,7 @@ def adjust_page(top, parent, settings):
self.frames["checkboxes"] = Frame(self)
self.frames["checkboxes"].pack(anchor=W)
# Adjust option frames
self.frames["selectOptionsFrame"] = Frame(self)
self.frames["leftAdjustFrame"] = Frame(self.frames["selectOptionsFrame"])
self.frames["rightAdjustFrame"] = Frame(self.frames["selectOptionsFrame"])
@@ -28,6 +29,8 @@ def adjust_page(top, parent, settings):
self.frames["rightAdjustFrame"].pack(side=RIGHT)
self.frames["bottomAdjustFrame"].pack(fill=X)
# Load Adjust option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
with open(os.path.join("resources","app","gui","adjust","overview","widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items():
@@ -40,6 +43,7 @@ def adjust_page(top, parent, settings):
self.widgets[key].pack(packAttrs)
# Sprite Selection
# This one's more-complicated, build it and stuff it
self.spriteNameVar2 = StringVar()
spriteDialogFrame2 = Frame(self.frames["leftAdjustFrame"])
baseSpriteLabel2 = Label(spriteDialogFrame2, text='Sprite:')
@@ -65,6 +69,8 @@ def adjust_page(top, parent, settings):
spriteSelectButton2.pack(side=LEFT)
spriteDialogFrame2.pack(anchor=E)
# Path to game file to Adjust
# This one's more-complicated, build it and stuff it
adjustRomFrame = Frame(self.frames["bottomAdjustFrame"])
adjustRomLabel = Label(adjustRomFrame, text='Rom to adjust: ')
self.romVar2 = StringVar(value=settings["rom"])
@@ -82,6 +88,7 @@ def adjust_page(top, parent, settings):
romSelectButton2.pack(side=LEFT)
adjustRomFrame.pack(fill=X)
# These are the options to Adjust
def adjustRom():
options = {
"heartbeep": "heartbeep",

View File

@@ -1,10 +1,9 @@
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, Spinbox, E, W, LEFT, RIGHT, X
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X
from argparse import Namespace
from functools import partial
import logging
import os
import random
from CLI import parse_arguments, get_settings
from CLI import parse_arguments
from Main import main
from Utils import local_path, output_path, open_file
import classes.constants as CONST
@@ -97,22 +96,35 @@ def create_guiargs(parent):
# Page::Subpage::GUI-id::param-id
options = CONST.SETTINGSTOPROCESS
# Cycle through each page
for mainpage in options:
# Cycle through each subpage (in case of Item Randomizer)
for subpage in options[mainpage]:
# Cycle through each widget
for widget in options[mainpage][subpage]:
# Get the value and set it
arg = options[mainpage][subpage][widget]
setattr(guiargs, arg, parent.pages[mainpage].pages[subpage].widgets[widget].storageVar.get())
# Get EnemizerCLI setting
guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].enemizerCLIpathVar.get()
# Get Multiworld Worlds count
guiargs.multi = int(parent.pages["randomizer"].pages["multiworld"].widgets["worlds"].storageVar.get())
# Get baserom path
guiargs.rom = parent.pages["randomizer"].pages["generation"].romVar.get()
# Get if we're using the Custom Item Pool
guiargs.custom = bool(parent.pages["randomizer"].pages["generation"].widgets["usecustompool"].storageVar.get())
# Get Seed ID
guiargs.seed = int(parent.frames["bottom"].seedVar.get()) if parent.frames["bottom"].seedVar.get() else None
# Get number of generations to run
guiargs.count = int(parent.frames["bottom"].widgets["generationcount"].storageVar.get()) if parent.frames["bottom"].widgets["generationcount"].storageVar.get() != '1' else None
# Get Adjust settings
adjustargs = {
"nobgm": "disablemusic",
"quickswap": "quickswap",
@@ -126,22 +138,29 @@ def create_guiargs(parent):
internal = adjustargs[adjustarg]
setattr(guiargs,"adjust." + internal, parent.pages["adjust"].content.widgets[adjustarg].storageVar.get())
# Get Custom Items and Starting Inventory Items
customitems = CONST.CUSTOMITEMS
guiargs.startinventory = []
guiargs.customitemarray = {}
guiargs.startinventoryarray = {}
for customitem in customitems:
if customitem not in ["triforcepiecesgoal", "triforce", "rupoor", "rupoorcost"]:
if customitem not in CONST.CANTSTARTWITH:
# Starting Inventory is a CSV
amount = int(parent.pages["startinventory"].content.startingWidgets[customitem].storageVar.get())
guiargs.startinventoryarray[customitem] = amount
for i in range(0, amount):
for _ in range(0, amount):
label = CONST.CUSTOMITEMLABELS[customitems.index(customitem)]
guiargs.startinventory.append(label)
# Custom Item Pool is a dict of ints
guiargs.customitemarray[customitem] = int(parent.pages["custom"].content.customWidgets[customitem].storageVar.get())
# Starting Inventory is a CSV
guiargs.startinventory = ','.join(guiargs.startinventory)
# Get Sprite Selection (set or random)
guiargs.sprite = parent.pages["randomizer"].pages["gameoptions"].widgets["sprite"]["spriteObject"]
guiargs.randomSprite = parent.randomSprite.get()
# Get output path
guiargs.outputpath = parent.outputPath.get()
return guiargs

View File

@@ -1,25 +1,27 @@
from tkinter import ttk, Frame, N, LEFT, VERTICAL, Y
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y
import gui.widgets as widgets
import json
import os
import classes.constants as CONST
def custom_page(top, parent):
def custom_page(top,parent):
# Custom Item Pool
self = ttk.Frame(parent)
# Create uniform list columns
def create_list_frame(parent, framename):
parent.frames[framename] = Frame(parent)
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
parent.frames[framename].thisRow = 0
parent.frames[framename].thisCol = 0
# Create a vertical rule to help with splitting columns visually
def create_vertical_rule(num=1):
for i in range(0,num):
for _ in range(0,num):
ttk.Separator(self, orient=VERTICAL).pack(side=LEFT, anchor=N, fill=Y)
# This was in here, I have no idea what it was but I left it just in case: MikeT
def validation(P):
if str.isdigit(P) or P == "":
return True
@@ -32,6 +34,7 @@ def custom_page(top, parent):
# Custom Item Pool option sections
self.frames = {}
# Create 5 columns with 2 vertical rules in between each
create_list_frame(self, "itemList1")
create_vertical_rule(2)
create_list_frame(self, "itemList2")
@@ -42,6 +45,8 @@ def custom_page(top, parent):
create_vertical_rule(2)
create_list_frame(self, "itemList5")
# Load Custom option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
with open(os.path.join("resources", "app", "gui", "custom", "overview", "widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items():
@@ -49,7 +54,8 @@ def custom_page(top, parent):
for key in dictWidgets:
self.customWidgets[key] = dictWidgets[key]
for i, key in enumerate(CONST.CUSTOMITEMS):
self.customWidgets[key].storageVar.set(top.settings["customitemarray"][i])
# Load Custom Item Pool settings from settings file
for key in CONST.CUSTOMITEMS:
self.customWidgets[key].storageVar.set(top.settings["customitemarray"][key])
return self

View File

@@ -3,6 +3,7 @@ from gui.randomize.gameoptions import set_sprite
from Rom import Sprite, get_sprite_from_name
import classes.constants as CONST
# Load args/settings for most tabs
def loadcliargs(gui, args, settings=None):
if args is not None:
# for k, v in vars(args).items():
@@ -14,28 +15,47 @@ def loadcliargs(gui, args, settings=None):
# Page::Subpage::GUI-id::param-id
options = CONST.SETTINGSTOPROCESS
# Cycle through each page
for mainpage in options:
# Cycle through each subpage (in case of Item Randomizer)
for subpage in options[mainpage]:
# Cycle through each widget
for widget in options[mainpage][subpage]:
# Get the value and set it
arg = options[mainpage][subpage][widget]
gui.pages[mainpage].pages[subpage].widgets[widget].storageVar.set(args[arg])
# If we're on the Game Options page and it's not about Hints
if subpage == "gameoptions" and not widget == "hints":
# Check if we've got settings
# Check if we've got the widget in Adjust settings
hasSettings = settings is not None
hasWidget = ("adjust." + widget) in settings if hasSettings else None
if hasWidget is None:
# If we've got a Game Options val and we don't have an Adjust val, use the Game Options val
gui.pages["adjust"].content.widgets[widget].storageVar.set(args[arg])
# Get EnemizerCLI setting
gui.pages["randomizer"].pages["enemizer"].enemizerCLIpathVar.set(args["enemizercli"])
# Get baserom path
gui.pages["randomizer"].pages["generation"].romVar.set(args["rom"])
# Get Multiworld Worlds count
if args["multi"]:
gui.pages["randomizer"].pages["multiworld"].widgets["worlds"].storageVar.set(str(args["multi"]))
# Get Seed ID
if args["seed"]:
gui.frames["bottom"].seedVar.set(str(args["seed"]))
# Get number of generations to run
if args["count"]:
gui.frames["bottom"].widgets["generationcount"].storageVar.set(str(args["count"]))
# Get output path
gui.outputPath.set(args["outputpath"])
# Figure out Sprite Selection
def sprite_setter(spriteObject):
gui.pages["randomizer"].pages["gameoptions"].widgets["sprite"]["spriteObject"] = spriteObject
if args["sprite"] is not None:
@@ -52,6 +72,7 @@ def loadcliargs(gui, args, settings=None):
spriteNameVar=gui.pages["adjust"].content.spriteNameVar2,
randomSpriteVar=gui.randomSprite)
# Load args/settings for Adjust tab
def loadadjustargs(gui, settings):
options = {
"adjust": {

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT
import gui.widgets as widgets
import json
import os
@@ -19,6 +19,9 @@ def dungeon_page(parent):
mscbLabel = Label(self.frames["keysanity"], text="Shuffle: ")
mscbLabel.pack(side=LEFT)
# Load Dungeon Shuffle option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
# This first set goes in the Keysanity frame
with open(os.path.join("resources","app","gui","randomize","dungeon","keysanity.json")) as keysanityItems:
myDict = json.load(keysanityItems)
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["keysanity"])
@@ -26,6 +29,7 @@ def dungeon_page(parent):
self.widgets[key] = dictWidgets[key]
self.widgets[key].pack(side=LEFT)
# These get split left & right
self.frames["widgets"] = Frame(self)
self.frames["widgets"].pack(anchor=W)
with open(os.path.join("resources","app","gui","randomize","dungeon","widgets.json")) as dungeonWidgets:

View File

@@ -1,5 +1,5 @@
import os
from tkinter import ttk, filedialog, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, LabelFrame, OptionMenu, N, E, W, LEFT, RIGHT, BOTTOM, X
from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, N, E, W, LEFT, RIGHT, BOTTOM, X
import gui.widgets as widgets
import json
import os
@@ -18,6 +18,7 @@ def enemizer_page(parent,settings):
# Enemizer option sections
self.frames = {}
# Enemizer option frames
self.frames["checkboxes"] = Frame(self)
self.frames["checkboxes"].pack(anchor=W)
@@ -30,6 +31,9 @@ def enemizer_page(parent,settings):
self.frames["rightEnemizerFrame"].pack(side=RIGHT)
self.frames["bottomEnemizerFrame"].pack(fill=X)
# Load Enemizer option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
# These get split left & right
with open(os.path.join("resources","app","gui","randomize","enemizer","widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items():
@@ -42,6 +46,7 @@ def enemizer_page(parent,settings):
self.widgets[key].pack(packAttrs)
## Enemizer CLI Path
# This one's more-complicated, build it and stuff it
enemizerPathFrame = Frame(self.frames["bottomEnemizerFrame"])
enemizerCLIlabel = Label(enemizerPathFrame, text="EnemizerCLI path: ")
enemizerCLIlabel.pack(side=LEFT)

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
from tkinter import ttk, Frame, E, W, LEFT, RIGHT
import gui.widgets as widgets
import json
import os
@@ -15,6 +15,11 @@ def entrando_page(parent):
self.frames["widgets"] = Frame(self)
self.frames["widgets"].pack(anchor=W)
# Load Entrance Randomizer option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
# Checkboxes go West
# Everything else goes East
# They also get split left & right
with open(os.path.join("resources","app","gui","randomize","entrando","widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items():

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
from tkinter import ttk, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT
from functools import partial
import classes.SpriteSelector as spriteSelector
import gui.widgets as widgets
@@ -17,11 +17,17 @@ def gameoptions_page(top, parent):
self.frames["checkboxes"] = Frame(self)
self.frames["checkboxes"].pack(anchor=W)
# Game Options frames
self.frames["leftRomOptionsFrame"] = Frame(self)
self.frames["rightRomOptionsFrame"] = Frame(self)
self.frames["leftRomOptionsFrame"].pack(side=LEFT)
self.frames["rightRomOptionsFrame"].pack(side=RIGHT)
# Load Game Options widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
# Checkboxes go West
# Everything else goes East
# They also get split left & right
with open(os.path.join("resources","app","gui","randomize","gameoptions","widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items():
@@ -34,6 +40,7 @@ def gameoptions_page(top, parent):
self.widgets[key].pack(packAttrs)
## Sprite selection
# This one's more-complicated, build it and stuff it
spriteDialogFrame = Frame(self.frames["leftRomOptionsFrame"])
baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:')
@@ -75,4 +82,3 @@ def set_sprite(sprite_param, random_sprite=False, spriteSetter=None, spriteNameV
spriteNameVar.set(sprite_param.name)
if randomSpriteVar:
randomSpriteVar.set(random_sprite)

View File

@@ -1,5 +1,4 @@
import os
from tkinter import ttk, filedialog, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, E, W, LEFT, RIGHT, X
from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, E, W, LEFT, X
import gui.widgets as widgets
import json
import os
@@ -16,6 +15,8 @@ def generation_page(parent,settings):
self.frames["checkboxes"] = Frame(self)
self.frames["checkboxes"].pack(anchor=W)
# Load Generation Setup option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
with open(os.path.join("resources","app","gui","randomize","generation","checkboxes.json")) as checkboxes:
myDict = json.load(checkboxes)
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["checkboxes"])
@@ -26,6 +27,7 @@ def generation_page(parent,settings):
self.frames["baserom"] = Frame(self)
self.frames["baserom"].pack(anchor=W, fill=X)
## Locate base ROM
# This one's more-complicated, build it and stuff it
baseRomFrame = Frame(self.frames["baserom"])
baseRomLabel = Label(baseRomFrame, text='Base Rom: ')
self.romVar = StringVar()

View File

@@ -1,8 +1,8 @@
from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
from tkinter import ttk, Frame, E, W, LEFT, RIGHT
import gui.widgets as widgets
import json
import os
def item_page(parent):
# Item Randomizer
self = ttk.Frame(parent)
@@ -13,6 +13,7 @@ def item_page(parent):
# Item Randomizer option sections
self.frames = {}
# Item Randomizer option frames
self.frames["checkboxes"] = Frame(self)
self.frames["checkboxes"].pack(anchor=W)
@@ -21,6 +22,10 @@ def item_page(parent):
self.frames["leftItemFrame"].pack(side=LEFT)
self.frames["rightItemFrame"].pack(side=RIGHT)
# Load Item Randomizer option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
# Checkboxes go West
# Everything else goes East
with open(os.path.join("resources","app","gui","randomize","item","widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items():

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, StringVar, Entry, Frame, Label, Spinbox, N, E, W, X, LEFT, RIGHT
from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, X, LEFT
import gui.widgets as widgets
import json
import os
@@ -15,6 +15,8 @@ def multiworld_page(parent,settings):
self.frames["widgets"] = Frame(self)
self.frames["widgets"].pack(anchor=W, fill=X)
# Load Multiworld option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes
with open(os.path.join("resources","app","gui","randomize","multiworld","widgets.json")) as multiworldItems:
myDict = json.load(multiworldItems)
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["widgets"])
@@ -23,6 +25,7 @@ def multiworld_page(parent,settings):
self.widgets[key].pack(side=LEFT, anchor=N)
## List of Player Names
# This one's more-complicated, build it and stuff it
key = "names"
self.widgets[key] = Frame(self.frames["widgets"])
self.widgets[key].label = Label(self.widgets[key], text='Player names')

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, LEFT, RIGHT, X, VERTICAL, Y
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y
import gui.widgets as widgets
import json
import os
@@ -9,16 +9,19 @@ def startinventory_page(top,parent):
# Starting Inventory
self = ttk.Frame(parent)
# Create uniform list columns
def create_list_frame(parent, framename):
parent.frames[framename] = Frame(parent)
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
parent.frames[framename].thisRow = 0
parent.frames[framename].thisCol = 0
# Create a vertical rule to help with splitting columns visually
def create_vertical_rule(num=1):
for i in range(0,num):
for _ in range(0,num):
ttk.Separator(self, orient=VERTICAL).pack(side=LEFT, anchor=N, fill=Y)
# This was in Custom Item Pool, I have no idea what it was but I left it just in case: MikeT
def validation(P):
if str.isdigit(P) or P == "":
return True
@@ -31,6 +34,7 @@ def startinventory_page(top,parent):
# Starting Inventory option sections
self.frames = {}
# Create 5 columns with 2 vertical rules in between each
create_list_frame(self,"itemList1")
create_vertical_rule(2)
create_list_frame(self,"itemList2")
@@ -41,6 +45,8 @@ def startinventory_page(top,parent):
create_vertical_rule(2)
create_list_frame(self,"itemList5")
# Load Starting Inventory option widgets as defined by JSON file, ignoring the ones to be excluded
# Defns include frame name, widget type, widget options, widget placement attributes
with open(os.path.join("resources","app","gui","custom","overview","widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns)
for key in CONST.CANTSTARTWITH:
@@ -53,6 +59,7 @@ def startinventory_page(top,parent):
for key in dictWidgets:
self.startingWidgets[key] = dictWidgets[key]
# Load Custom Starting Inventory settings from settings file, ignoring ones to be excluded
for key in CONST.CUSTOMITEMS:
if key not in CONST.CANTSTARTWITH:
val = 0

View File

@@ -1,8 +1,10 @@
from tkinter import Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, RIGHT, X
# Need a dummy class
class Empty():
pass
# Override Spinbox to include mousewheel support for changing value
class mySpinbox(Spinbox):
def __init__(self, *args, **kwargs):
Spinbox.__init__(self, *args, **kwargs)
@@ -16,6 +18,7 @@ class mySpinbox(Spinbox):
elif event.num == 4 or event.delta == 120:
self.invoke('buttonup')
# Make a Checkbutton with a label
def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
self = Frame(parent, name="checkframe-" + label.lower())
self.storageVar = storageVar
@@ -26,6 +29,7 @@ def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
self.checkbox.pack()
return self
# Make an OptionMenu with a label and pretty option labels
def make_selectbox(self, parent, label, options, storageVar, manager, managerAttrs):
def change_storage(*args):
self.storageVar.set(options[self.labelVar.get()])
@@ -54,6 +58,7 @@ def make_selectbox(self, parent, label, options, storageVar, manager, managerAtt
self.selectbox.pack()
return self
# Make a Spinbox with a label, limit 1-100
def make_spinbox(self, parent, label, storageVar, manager, managerAttrs):
self = Frame(parent, name="spinframe-" + label.lower())
self.storageVar = storageVar
@@ -76,6 +81,8 @@ def make_spinbox(self, parent, label, storageVar, manager, managerAttrs):
self.spinbox.pack()
return self
# Make an Entry box with a label
# Support for Grid or Pack so that the Custom Item Pool & Starting Inventory pages don't look ugly
def make_textbox(self, parent, label, storageVar, manager, managerAttrs):
widget = Empty()
widget.storageVar = storageVar
@@ -98,7 +105,7 @@ def make_textbox(self, parent, label, storageVar, manager, managerAttrs):
widget.textbox.pack(managerAttrs["textbox"] if managerAttrs is not None and "textbox" in managerAttrs else None)
return widget
# Make a generic widget
def make_widget(self, type, parent, label, storageVar=None, manager=None, managerAttrs=dict(), options=None):
widget = None
if manager is None:
@@ -129,6 +136,7 @@ def make_widget(self, type, parent, label, storageVar=None, manager=None, manage
widget.type = type
return widget
# Make a generic widget from a dict
def make_widget_from_dict(self, defn, parent):
type = defn["type"] if "type" in defn else None
label = defn["label"]["text"] if "label" in defn and "text" in defn["label"] else ""
@@ -138,8 +146,9 @@ def make_widget_from_dict(self, defn, parent):
widget = make_widget(self, type, parent, label, None, manager, managerAttrs, options)
return widget
# Make a set of generic widgets from a dict
def make_widgets_from_dict(self, defns, parent):
widgets = {}
for key,defn in defns.items():
widgets[key] = make_widget_from_dict(self, defn, parent)
return widgets
return widgets

View File

@@ -25,7 +25,8 @@
"options": {
"Standard": "standard",
"Open": "open",
"Inverted": "inverted"
"Inverted": "inverted",
"Retro": "retro"
}
},
"logiclevel": {