Major GUI reorganization

This commit is contained in:
codemann8
2023-03-29 08:58:48 -06:00
committed by aerinon
parent 09550cd546
commit f13880eee9
24 changed files with 522 additions and 263 deletions

View File

@@ -133,7 +133,7 @@ class World(object):
set_player_attr('crystals_needed_for_gt', 7) set_player_attr('crystals_needed_for_gt', 7)
set_player_attr('crystals_ganon_orig', {}) set_player_attr('crystals_ganon_orig', {})
set_player_attr('crystals_gt_orig', {}) set_player_attr('crystals_gt_orig', {})
set_player_attr('open_pyramid', False) set_player_attr('open_pyramid', 'auto')
set_player_attr('take_any', 'none') set_player_attr('take_any', 'none')
set_player_attr('treasure_hunt_icon', 'Triforce Piece') set_player_attr('treasure_hunt_icon', 'Triforce Piece')
set_player_attr('treasure_hunt_count', 0) set_player_attr('treasure_hunt_count', 0)
@@ -275,6 +275,19 @@ class World(object):
def is_atgt_swapped(self, player): def is_atgt_swapped(self, player):
return self.mode[player] == 'inverted' return self.mode[player] == 'inverted'
def is_pyramid_open(self, player):
if self.open_pyramid[player] == 'yes':
return True
elif self.open_pyramid[player] == 'no':
return False
else:
if self.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
return False
elif self.goal[player] in ['crystals', 'trinity']:
return True
else:
return False
def check_for_door(self, doorname, player): def check_for_door(self, doorname, player):
if isinstance(doorname, Door): if isinstance(doorname, Door):
return doorname return doorname
@@ -2659,7 +2672,7 @@ class Spoiler(object):
outfile.write(f"Overworld Map: {self.metadata['overworld_map'][player]}\n") outfile.write(f"Overworld Map: {self.metadata['overworld_map'][player]}\n")
outfile.write(f"Take Any Caves: {self.metadata['take_any'][player]}\n") outfile.write(f"Take Any Caves: {self.metadata['take_any'][player]}\n")
if self.metadata['goal'][player] != 'trinity': if self.metadata['goal'][player] != 'trinity':
outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No')) outfile.write('Pyramid hole pre-opened: %s\n' % (self.metadata['open_pyramid'][player]))
outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player]) outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player])
if self.metadata['door_shuffle'][player] != 'vanilla': if self.metadata['door_shuffle'][player] != 'vanilla':
outfile.write(f"Intensity: {self.metadata['intensity'][player]}\n") outfile.write(f"Intensity: {self.metadata['intensity'][player]}\n")
@@ -2997,7 +3010,7 @@ class Settings(object):
| (counter_mode[w.dungeon_counters[p]] << 1) | (1 if w.experimental[p] else 0), | (counter_mode[w.dungeon_counters[p]] << 1) | (1 if w.experimental[p] else 0),
((8 if w.crystals_ganon_orig[p] == "random" else int(w.crystals_ganon_orig[p])) << 3) ((8 if w.crystals_ganon_orig[p] == "random" else int(w.crystals_ganon_orig[p])) << 3)
| (0x4 if w.open_pyramid[p] else 0) | access_mode[w.accessibility[p]], | (0x4 if w.is_pyramid_open[p] else 0) | access_mode[w.accessibility[p]],
(0x80 if w.bigkeyshuffle[p] else 0) (0x80 if w.bigkeyshuffle[p] else 0)
| (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0) | (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0)

2
CLI.py
View File

@@ -186,7 +186,7 @@ def parse_settings():
"restrict_boss_items": "none", "restrict_boss_items": "none",
# Shuffle Ganon defaults to TRUE # Shuffle Ganon defaults to TRUE
"openpyramid": False, "openpyramid": 'auto',
"shuffleganon": True, "shuffleganon": True,
"shuffle": "vanilla", "shuffle": "vanilla",
"shufflelinks": False, "shufflelinks": False,

8
Gui.py
View File

@@ -137,14 +137,14 @@ def guiMain(args=None):
self.pages["randomizer"].pages["entrance"] = entrando_page(self.pages["randomizer"].notebook) self.pages["randomizer"].pages["entrance"] = entrando_page(self.pages["randomizer"].notebook)
self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["entrance"], text="Entrances") self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["entrance"], text="Entrances")
# Dungeons
self.pages["randomizer"].pages["dungeon"] = dungeon_page(self.pages["randomizer"].notebook)
self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["dungeon"], text="Dungeons")
# Enemizer # Enemizer
self.pages["randomizer"].pages["enemizer"],self.settings = enemizer_page(self.pages["randomizer"].notebook,self.settings) self.pages["randomizer"].pages["enemizer"],self.settings = enemizer_page(self.pages["randomizer"].notebook,self.settings)
self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["enemizer"], text="Enemizer") self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["enemizer"], text="Enemizer")
# Dungeon Shuffle
self.pages["randomizer"].pages["dungeon"] = dungeon_page(self.pages["randomizer"].notebook)
self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["dungeon"], text="Dungeon Shuffle")
# Multiworld # Multiworld
# self.pages["randomizer"].pages["multiworld"],self.settings = multiworld_page(self.pages["randomizer"].notebook,self.settings) # self.pages["randomizer"].pages["multiworld"],self.settings = multiworld_page(self.pages["randomizer"].notebook,self.settings)
# self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["multiworld"], text="Multiworld") # self.pages["randomizer"].notebook.add(self.pages["randomizer"].pages["multiworld"], text="Multiworld")

2
Rom.py
View File

@@ -1303,7 +1303,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest
rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest
rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest
if world.open_pyramid[player] or (world.goal[player] in ['trinity', 'crystals'] and world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']): if world.is_pyramid_open(player):
rom.initial_sram.pre_open_pyramid_hole() rom.initial_sram.pre_open_pyramid_hole()
if world.crystals_needed_for_gt[player] == 0: if world.crystals_needed_for_gt[player] == 0:
rom.initial_sram.pre_open_ganons_tower() rom.initial_sram.pre_open_ganons_tower()

View File

@@ -902,7 +902,7 @@ def ow_inverted_rules(world, player):
set_rule(world.get_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player) and set_rule(world.get_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player) and
(state.has_Pearl(player) or state.has('Beat Agahnim 1', player)) (state.has_Pearl(player) or state.has('Beat Agahnim 1', player))
or (state.can_reach('Light World', 'Region', player) and state.has_Mirror(player))) # Need LW access using Mirror or Portal or (state.can_reach('Light World', 'Region', player) and state.has_Mirror(player))) # Need LW access using Mirror or Portal
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: world.open_pyramid[player] or world.goal[player] == 'trinity' or state.has('Beat Agahnim 2', player)) set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: world.is_pyramid_open(player) or state.has('Beat Agahnim 2', player))
def ow_bunny_rules(world, player): def ow_bunny_rules(world, player):

View File

@@ -70,6 +70,16 @@
full: 2 full: 2
crossed: 3 crossed: 3
insanity: 1 insanity: 1
open_pyramid:
auto: 1
yes: 0
no: 0
shufflelinks:
on: 1
off: 1
shuffleganon:
on: 1
off: 1
overworld_map: # control how the overworld map operates when entrance shuffle is on overworld_map: # control how the overworld map operates when entrance shuffle is on
default: 1 default: 1
compass: 10 compass: 10

View File

@@ -240,8 +240,11 @@
] ]
}, },
"openpyramid": { "openpyramid": {
"action": "store_true", "choices": [
"type": "bool" "auto",
"yes",
"no"
]
}, },
"rom": {}, "rom": {},
"loglevel": { "loglevel": {

View File

@@ -1,4 +1,22 @@
{ {
"startHeader": {
"usestartinventory": {
"type": "checkbox",
"config": {
"padx": [10,0],
"pady": [10,10]
}
}
},
"customHeader": {
"usecustompool": {
"type": "checkbox",
"config": {
"padx": [10,0],
"pady": [10,10]
}
}
},
"itemList1": { "itemList1": {
"bow": { "bow": {
"type": "textbox", "type": "textbox",

View File

@@ -57,21 +57,7 @@
"randomizer.dungeon.smallkeyshuffle.wild": "Randomized", "randomizer.dungeon.smallkeyshuffle.wild": "Randomized",
"randomizer.dungeon.smallkeyshuffle.universal": "Universal", "randomizer.dungeon.smallkeyshuffle.universal": "Universal",
"randomizer.dungeon.bigkeyshuffle": "Big Keys", "randomizer.dungeon.bigkeyshuffle": "Big Keys",
"randomizer.dungeon.keydropshuffle": "Key Drop Shuffle (Legacy)",
"randomizer.dungeon.decoupledoors": "Decouple Doors", "randomizer.dungeon.decoupledoors": "Decouple Doors",
"randomizer.dungeon.dropshuffle": "Shuffle Enemy Key Drops",
"randomizer.dungeon.potshuffle": "Pot Shuffle (Legacy)",
"randomizer.dungeon.pottery": "Pottery",
"randomizer.dungeon.pottery.none": "None",
"randomizer.dungeon.pottery.keys": "Key Pots",
"randomizer.dungeon.pottery.cave": "Cave Pots",
"randomizer.dungeon.pottery.cavekeys": "Cave+Key Pots",
"randomizer.dungeon.pottery.reduced": "Reduced Dungeon Pots (Dynamic)",
"randomizer.dungeon.pottery.clustered": "Clustered Dungeon Pots (Dynamic)",
"randomizer.dungeon.pottery.nonempty": "Excludes Empty Pots",
"randomizer.dungeon.pottery.dungeon": "Dungeon Pots",
"randomizer.dungeon.pottery.lottery": "Lottery (All Pots and Large Blocks)",
"randomizer.dungeon.colorizepots": "Colorize Randomized Pots",
"randomizer.dungeon.dungeondoorshuffle": "Dungeon Door Shuffle", "randomizer.dungeon.dungeondoorshuffle": "Dungeon Door Shuffle",
"randomizer.dungeon.dungeondoorshuffle.vanilla": "Vanilla", "randomizer.dungeon.dungeondoorshuffle.vanilla": "Vanilla",
@@ -123,7 +109,7 @@
"randomizer.enemizer.enemyshuffle.none": "None", "randomizer.enemizer.enemyshuffle.none": "None",
"randomizer.enemizer.enemyshuffle.shuffled": "Shuffled", "randomizer.enemizer.enemyshuffle.shuffled": "Shuffled",
"randomizer.enemizer.enemyshuffle.random": "Random", "randomizer.enemizer.enemyshuffle.random": "Random",
"randomizer.enemizer.enemyshuffle.legacy": "Random (including Thieves)", "randomizer.enemizer.enemyshuffle.legacy": "Random (50/50 Thieves)",
"randomizer.enemizer.bossshuffle": "Boss Shuffle", "randomizer.enemizer.bossshuffle": "Boss Shuffle",
"randomizer.enemizer.bossshuffle.none": "None", "randomizer.enemizer.bossshuffle.none": "None",
@@ -147,8 +133,10 @@
"randomizer.enemizer.enemizercli": "EnemizerCLI path: ", "randomizer.enemizer.enemizercli": "EnemizerCLI path: ",
"randomizer.enemizer.enemizercli.online": "(get online)", "randomizer.enemizer.enemizercli.online": "(get online)",
"randomizer.entrance.openpyramid": "Pre-open Pyramid Hole", "randomizer.entrance.openpyramid": "Pre-open Pyramid Hole",
"randomizer.entrance.openpyramid.auto": "Auto",
"randomizer.entrance.openpyramid.yes": "Yes",
"randomizer.entrance.openpyramid.no": "No",
"randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool", "randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool",
"randomizer.entrance.shufflelinks": "Include Link's House in the shuffle pool", "randomizer.entrance.shufflelinks": "Include Link's House in the shuffle pool",
"randomizer.entrance.shuffletavern": "Include the back of the tavern in the entrance shuffle pool", "randomizer.entrance.shuffletavern": "Include the back of the tavern in the entrance shuffle pool",
@@ -169,11 +157,6 @@
"randomizer.entrance.entranceshuffle.dungeonsfull": "Dungeons + Full", "randomizer.entrance.entranceshuffle.dungeonsfull": "Dungeons + Full",
"randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple", "randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple",
"randomizer.entrance.take_any": "Take Any Caves",
"randomizer.entrance.take_any.none": "None",
"randomizer.entrance.take_any.random": "Random",
"randomizer.entrance.take_any.fixed": "Fixed",
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1", "randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
"randomizer.gameoptions.quickswap": "L/R Quickswapping", "randomizer.gameoptions.quickswap": "L/R Quickswapping",
"randomizer.gameoptions.reduce_flashing": "Reduce Flashing", "randomizer.gameoptions.reduce_flashing": "Reduce Flashing",
@@ -222,9 +205,6 @@
"randomizer.generation.createrom": "Create Patched ROM", "randomizer.generation.createrom": "Create Patched ROM",
"randomizer.generation.calcplaythrough": "Calculate Playthrough", "randomizer.generation.calcplaythrough": "Calculate Playthrough",
"randomizer.generation.print_custom_yaml": "Print Customizer File", "randomizer.generation.print_custom_yaml": "Print Customizer File",
"randomizer.generation.usestartinventory": "Use Starting Inventory",
"randomizer.generation.usecustompool": "Use Custom Item Pool",
"randomizer.generation.race": "Generate \"Race\" ROM",
"randomizer.generation.saveonexit": "Save Settings on Exit", "randomizer.generation.saveonexit": "Save Settings on Exit",
"randomizer.generation.saveonexit.ask": "Ask Me", "randomizer.generation.saveonexit.ask": "Ask Me",
@@ -236,10 +216,10 @@
"randomizer.generation.rom.dialog.romfiles": "Rom Files", "randomizer.generation.rom.dialog.romfiles": "Rom Files",
"randomizer.generation.rom.dialog.allfiles": "All Files", "randomizer.generation.rom.dialog.allfiles": "All Files",
"randomizer.item.hints": "Include Helpful Hints", "randomizer.item.hints": "Hints",
"randomizer.item.race": "Generate \"Race\" ROM",
"randomizer.item.retro": "Retro mode", "randomizer.item.retro": "Retro mode",
"randomizer.item.pseudoboots": "Start with Pseudo Boots", "randomizer.item.pseudoboots": "Pseudoboots",
"randomizer.item.bombbag": "Bombbag",
"randomizer.item.worldstate": "World State", "randomizer.item.worldstate": "World State",
"randomizer.item.worldstate.standard": "Standard", "randomizer.item.worldstate.standard": "Standard",
@@ -291,20 +271,67 @@
"randomizer.item.weapons.swordless": "Swordless", "randomizer.item.weapons.swordless": "Swordless",
"randomizer.item.weapons.vanilla": "Vanilla", "randomizer.item.weapons.vanilla": "Vanilla",
"randomizer.item.beemizer": "Beemizer", "randomizer.item.sortingalgo": "Item Fill",
"randomizer.item.beemizer.0": "No Bee Traps", "randomizer.item.sortingalgo.balanced": "Balanced",
"randomizer.item.beemizer.1": "25% Bee Traps", "randomizer.item.sortingalgo.vanilla_fill": "Vanilla Fill",
"randomizer.item.beemizer.2": "40% Traps, 20% Refills", "randomizer.item.sortingalgo.major_only": "Major Location Restriction",
"randomizer.item.beemizer.3": "50% Traps, 50% Refills", "randomizer.item.sortingalgo.dungeon_only": "Dungeon Restriction",
"randomizer.item.beemizer.4": "100% Bee Traps", "randomizer.item.sortingalgo.district": "District Restriction",
"randomizer.item.accessibility": "Accessibility",
"randomizer.item.accessibility.items": "100% Inventory",
"randomizer.item.accessibility.locations": "100% Locations",
"randomizer.item.accessibility.none": "Beatable",
"randomizer.item.restrict_boss_items": "Forbidden Boss Items",
"randomizer.item.restrict_boss_items.none": "None",
"randomizer.item.restrict_boss_items.mapcompass": "Map & Compass",
"randomizer.item.restrict_boss_items.dungeon": "Map & Compass & Keys",
"randomizer.item.itemfunction": "Item Functionality",
"randomizer.item.itemfunction.normal": "Normal",
"randomizer.item.itemfunction.hard": "Hard",
"randomizer.item.itemfunction.expert": "Expert",
"randomizer.item.timer": "Timer Setting",
"randomizer.item.timer.none": "No Timer",
"randomizer.item.timer.display": "Stopwatch",
"randomizer.item.timer.timed": "Timed",
"randomizer.item.timer.timed-ohko": "Timed OHKO",
"randomizer.item.timer.ohko": "OHKO",
"randomizer.item.timer.timed-countdown": "Timed Countdown",
"randomizer.item.shopsanity": "Shopsanity",
"randomizer.item.bonk_drops": "Bonk Drops",
"randomizer.item.pottery": "Pottery",
"randomizer.item.pottery.none": "None",
"randomizer.item.pottery.keys": "Key Pots",
"randomizer.item.pottery.cave": "Cave Pots",
"randomizer.item.pottery.cavekeys": "Cave+Key Pots",
"randomizer.item.pottery.reduced": "Reduced Dungeon Pots (Dynamic)",
"randomizer.item.pottery.clustered": "Clustered Dungeon Pots (Dynamic)",
"randomizer.item.pottery.nonempty": "Excludes Empty Pots",
"randomizer.item.pottery.dungeon": "Dungeon Pots",
"randomizer.item.pottery.lottery": "Lottery (All Pots and Large Blocks)",
"randomizer.item.colorizepots": "Colorize Randomized Pots",
"randomizer.item.potshuffle": "Pot Shuffle (Legacy)",
"randomizer.item.dropshuffle": "Shuffle Enemy Key Drops",
"randomizer.item.keydropshuffle": "Key Drop Shuffle (Legacy)",
"randomizer.item.take_any": "Take Any Caves",
"randomizer.item.take_any.none": "None",
"randomizer.item.take_any.random": "Random",
"randomizer.item.take_any.fixed": "Fixed",
"randomizer.item.itempool": "Item Pool", "randomizer.item.itempool": "Item Pool",
"randomizer.item.itempool.normal": "Normal", "randomizer.item.itempool.normal": "Normal",
"randomizer.item.itempool.hard": "Hard", "randomizer.item.itempool.hard": "Hard",
"randomizer.item.itempool.expert": "Expert", "randomizer.item.itempool.expert": "Expert",
"randomizer.item.shopsanity": "Shopsanity",
"randomizer.item.flute_mode": "Flute Mode", "randomizer.item.flute_mode": "Flute Mode",
"randomizer.item.flute_mode.normal": "Normal", "randomizer.item.flute_mode.normal": "Normal",
"randomizer.item.flute_mode.active": "Pre-Activated", "randomizer.item.flute_mode.active": "Pre-Activated",
@@ -315,30 +342,17 @@
"randomizer.item.bow_mode.retro": "Retro (Progressive)", "randomizer.item.bow_mode.retro": "Retro (Progressive)",
"randomizer.item.bow_mode.retro_silvers": "Retro + Silvers", "randomizer.item.bow_mode.retro_silvers": "Retro + Silvers",
"randomizer.item.timer": "Timer Setting", "randomizer.item.beemizer": "Beemizer",
"randomizer.item.timer.none": "No Timer", "randomizer.item.beemizer.0": "No Bee Traps",
"randomizer.item.timer.display": "Stopwatch", "randomizer.item.beemizer.1": "25% Bee Traps",
"randomizer.item.timer.timed": "Timed", "randomizer.item.beemizer.2": "40% Traps, 20% Refills",
"randomizer.item.timer.timed-ohko": "Timed OHKO", "randomizer.item.beemizer.3": "50% Traps, 50% Refills",
"randomizer.item.timer.ohko": "OHKO", "randomizer.item.beemizer.4": "100% Bee Traps",
"randomizer.item.timer.timed-countdown": "Timed Countdown",
"randomizer.item.accessibility": "Accessibility", "randomizer.item.bombbag": "Bombbag",
"randomizer.item.accessibility.items": "100% Inventory",
"randomizer.item.accessibility.locations": "100% Locations",
"randomizer.item.accessibility.none": "Beatable",
"randomizer.item.sortingalgo": "Item Sorting", "startinventory.usestartinventory": "Use Starting Inventory",
"randomizer.item.sortingalgo.balanced": "Balanced", "custom.usecustompool": "Use Custom Item Pool",
"randomizer.item.sortingalgo.vanilla_fill": "Vanilla Fill",
"randomizer.item.sortingalgo.major_only": "Major Location Restriction",
"randomizer.item.sortingalgo.dungeon_only": "Dungeon Restriction",
"randomizer.item.sortingalgo.district": "District Restriction",
"randomizer.item.restrict_boss_items": "Forbidden Boss Items",
"randomizer.item.restrict_boss_items.none": "None",
"randomizer.item.restrict_boss_items.mapcompass": "Map & Compass",
"randomizer.item.restrict_boss_items.dungeon": "Map & Compass & Keys",
"bottom.content.worlds": "Worlds", "bottom.content.worlds": "Worlds",
"bottom.content.names": "Player names", "bottom.content.names": "Player names",

View File

@@ -1,5 +1,13 @@
{ {
"keysanity": { "keysanity": {
"smallkeyshuffle": {
"type": "selectbox",
"options": [
"none",
"wild",
"universal"
]
},
"mapshuffle": { "type": "checkbox" }, "mapshuffle": { "type": "checkbox" },
"compassshuffle": { "type": "checkbox" }, "compassshuffle": { "type": "checkbox" },
"bigkeyshuffle": { "type": "checkbox" } "bigkeyshuffle": { "type": "checkbox" }

View File

@@ -1,12 +1,17 @@
{ {
"widgets": { "widgets": {
"smallkeyshuffle": { "key_logic_algorithm": {
"type": "selectbox", "type": "selectbox",
"default": "default",
"options": [ "options": [
"none", "default",
"wild", "partial",
"universal" "strict"
] ],
"config": {
"padx": [20,0],
"pady": [0,20]
}
}, },
"dungeondoorshuffle": { "dungeondoorshuffle": {
"type": "selectbox", "type": "selectbox",
@@ -28,7 +33,8 @@
"random" "random"
], ],
"config": { "config": {
"width": 45 "width": 45,
"padx": [20,0]
} }
}, },
"door_type_mode": { "door_type_mode": {
@@ -41,7 +47,8 @@
"chaos" "chaos"
], ],
"config": { "config": {
"width": 45 "width": 45,
"padx": [20,0]
} }
}, },
"trap_door_mode": { "trap_door_mode": {
@@ -54,41 +61,17 @@
"oneway" "oneway"
], ],
"config": { "config": {
"width": 30 "width": 30,
"padx": [20,0]
} }
}, },
"key_logic_algorithm": { "decoupledoors": {
"type": "selectbox", "type": "checkbox",
"default": "default",
"options": [
"default",
"partial",
"strict"
]
},
"decoupledoors": { "type": "checkbox" },
"keydropshuffle": { "type": "checkbox" },
"pottery": {
"type": "selectbox",
"default": "none",
"options": [
"none",
"keys",
"cave",
"cavekeys",
"reduced",
"clustered",
"nonempty",
"dungeon",
"lottery"
],
"config": { "config": {
"width": 35 "padx": [20,0],
"pady": [0,20]
} }
}, },
"colorizepots": { "type": "checkbox" },
"dropshuffle": { "type": "checkbox" },
"potshuffle": { "type": "checkbox" },
"experimental": { "type": "checkbox" }, "experimental": { "type": "checkbox" },
"dungeon_counters": { "dungeon_counters": {
"type": "selectbox", "type": "selectbox",

View File

@@ -1,24 +1,50 @@
{ {
"widgets": { "widgets": {
"openpyramid": { "type": "checkbox" },
"shuffleganon": { "type": "checkbox" },
"entranceshuffle": { "entranceshuffle": {
"type": "selectbox", "type": "selectbox",
"options": [ "options": [
"vanilla", "vanilla",
"lite",
"lean",
"simple", "simple",
"restricted", "restricted",
"full", "full",
"lite",
"lean",
"crossed", "crossed",
"insanity", "insanity",
"dungeonsfull", "dungeonsfull",
"dungeonssimple" "dungeonssimple"
] ]
}, },
"shufflelinks": { "type": "checkbox" }, "shuffleganon": {
"shuffletavern": { "type": "checkbox" }, "type": "checkbox",
"config": {
"padx": [20,0]
}
},
"shufflelinks": {
"type": "checkbox",
"config": {
"padx": [20,0]
}
},
"shuffletavern": {
"type": "checkbox",
"config": {
"padx": [20,0]
}
},
"openpyramid": {
"type": "selectbox",
"options": [
"auto",
"yes",
"no"
],
"config": {
"width": 6,
"pady": [20,0]
}
},
"overworld_map": { "overworld_map": {
"type": "selectbox", "type": "selectbox",
"options": [ "options": [
@@ -29,14 +55,6 @@
"config": { "config": {
"width": 45 "width": 45
} }
},
"take_any": {
"type": "selectbox",
"options": [
"none",
"random",
"fixed"
]
} }
} }
} }

View File

@@ -4,9 +4,6 @@
"bps": { "type": "checkbox" }, "bps": { "type": "checkbox" },
"createspoiler": { "type": "checkbox" }, "createspoiler": { "type": "checkbox" },
"calcplaythrough": { "type": "checkbox" }, "calcplaythrough": { "type": "checkbox" },
"print_custom_yaml": { "type": "checkbox" }, "print_custom_yaml": { "type": "checkbox" }
"usestartinventory": { "type": "checkbox" },
"usecustompool": { "type": "checkbox" },
"race": { "type": "checkbox" }
} }
} }

View File

@@ -1,12 +1,8 @@
{ {
"checkboxes": { "checkboxes": {
"retro": { "type": "checkbox" }, "hints": { "type": "checkbox" },
"bombbag": { "type": "checkbox" }, "pseudoboots": { "type": "checkbox" },
"shopsanity": { "type": "checkbox" }, "race": { "type": "checkbox" }
"hints": {
"type": "checkbox"
},
"pseudoboots": { "type": "checkbox" }
}, },
"leftItemFrame": { "leftItemFrame": {
"worldstate": { "worldstate": {
@@ -17,7 +13,10 @@
"open", "open",
"inverted", "inverted",
"retro" "retro"
] ],
"config": {
"command": "worldstate"
}
}, },
"logiclevel": { "logiclevel": {
"type": "selectbox", "type": "selectbox",
@@ -63,15 +62,112 @@
"swordless", "swordless",
"vanilla" "vanilla"
] ]
},
"beemizer": {
"type": "selectbox",
"options": [
"0", "1", "2", "3", "4"
]
} }
}, },
"rightItemFrame": { "rightItemFrame": {
"sortingalgo": {
"type": "selectbox",
"default": "balanced",
"options": [
"balanced",
"vanilla_fill",
"major_only",
"dungeon_only",
"district"
]
},
"accessibility": {
"type": "selectbox",
"options": [
"items",
"locations",
"none"
]
},
"restrict_boss_items": {
"type": "selectbox",
"default": "none",
"options": [
"none",
"mapcompass",
"dungeon"
]
},
"itemfunction": {
"type": "selectbox",
"options": [
"normal",
"hard",
"expert"
]
},
"timer": {
"type": "selectbox",
"options": [
"none",
"display",
"timed",
"timed-ohko",
"ohko",
"timed-countdown"
]
}
},
"leftPoolHeader": {
"shopsanity": {
"type": "checkbox"
}
},
"leftPoolFrame": {
"pottery": {
"type": "selectbox",
"default": "none",
"options": [
"none",
"keys",
"cave",
"cavekeys",
"reduced",
"clustered",
"nonempty",
"dungeon",
"lottery"
],
"config": {
"width": 35
}
},
"colorizepots": {
"type": "checkbox",
"config": {
"padx": [50,0]
}
},
"potshuffle": {
"type": "checkbox",
"config": {
"padx": [50,0]
}
},
"dropshuffle": {
"type": "checkbox"
},
"keydropshuffle": {
"type": "checkbox",
"config": {
"command": "keydropshuffle"
}
},
"take_any": {
"type": "selectbox",
"options": [
"none",
"random",
"fixed"
]
}
},
"rightPoolFrame": {
"itempool": { "itempool": {
"type": "selectbox", "type": "selectbox",
"options": [ "options": [
@@ -96,44 +192,17 @@
"retro_silvers" "retro_silvers"
] ]
}, },
"timer": { "beemizer": {
"type": "selectbox", "type": "selectbox",
"options": [ "options": [
"none", "0", "1", "2", "3", "4"
"display",
"timed",
"timed-ohko",
"ohko",
"timed-countdown"
] ]
}, },
"accessibility": { "bombbag": {
"type": "selectbox", "type": "checkbox",
"options": [ "config": {
"items", "padx": [64,0]
"locations", }
"none"
]
},
"sortingalgo": {
"type": "selectbox",
"default": "balanced",
"options": [
"balanced",
"vanilla_fill",
"major_only",
"dungeon_only",
"district"
]
},
"restrict_boss_items": {
"type": "selectbox",
"default": "none",
"options": [
"none",
"mapcompass",
"dungeon"
]
} }
} }
} }

View File

@@ -56,33 +56,59 @@ SETTINGSTOPROCESS = {
"randomizer": { "randomizer": {
"item": { "item": {
"hints": "hints", "hints": "hints",
"retro": "retro",
"bombbag": "bombbag",
"shopsanity": "shopsanity",
"pseudoboots": "pseudoboots", "pseudoboots": "pseudoboots",
"race": "race",
"worldstate": "mode", "worldstate": "mode",
"logiclevel": "logic", "logiclevel": "logic",
"goal": "goal", "goal": "goal",
"crystals_gt": "crystals_gt", "crystals_gt": "crystals_gt",
"crystals_ganon": "crystals_ganon", "crystals_ganon": "crystals_ganon",
"weapons": "swords", "weapons": "swords",
"sortingalgo": "algorithm",
"accessibility": "accessibility",
"restrict_boss_items": "restrict_boss_items",
"itemfunction": "item_functionality",
"timer": "timer",
"shopsanity": "shopsanity",
"pottery": "pottery",
"colorizepots": "colorizepots",
"potshuffle": "shufflepots",
"dropshuffle": "dropshuffle",
"keydropshuffle": "keydropshuffle",
"take_any": "take_any",
"itempool": "difficulty", "itempool": "difficulty",
"flute_mode": "flute_mode", "flute_mode": "flute_mode",
"bow_mode": "bow_mode", "bow_mode": "bow_mode",
"timer": "timer",
"accessibility": "accessibility",
"sortingalgo": "algorithm",
"beemizer": "beemizer", "beemizer": "beemizer",
"restrict_boss_items": "restrict_boss_items" "bombbag": "bombbag"
}, },
"entrance": { "entrance": {
"openpyramid": "openpyramid", "entranceshuffle": "shuffle",
"shuffleganon": "shuffleganon", "shuffleganon": "shuffleganon",
"shufflelinks": "shufflelinks", "shufflelinks": "shufflelinks",
"shuffletavern": "shuffletavern", "shuffletavern": "shuffletavern",
"entranceshuffle": "shuffle", "openpyramid": "openpyramid",
"overworld_map": "overworld_map", "overworld_map": "overworld_map",
"take_any": "take_any", },
"dungeon": {
"smallkeyshuffle": "keyshuffle",
"mapshuffle": "mapshuffle",
"compassshuffle": "compassshuffle",
"bigkeyshuffle": "bigkeyshuffle",
"key_logic_algorithm": "key_logic_algorithm",
"dungeondoorshuffle": "door_shuffle",
"dungeonintensity": "intensity",
"door_type_mode": "door_type_mode",
"trap_door_mode": "trap_door_mode",
"decoupledoors": "decoupledoors",
"experimental": "experimental",
"dungeon_counters": "dungeon_counters",
"mixed_travel": "mixed_travel",
"standardize_palettes": "standardize_palettes",
}, },
"enemizer": { "enemizer": {
"enemyshuffle": "shuffleenemies", "enemyshuffle": "shuffleenemies",
@@ -90,27 +116,6 @@ SETTINGSTOPROCESS = {
"enemydamage": "enemy_damage", "enemydamage": "enemy_damage",
"enemyhealth": "enemy_health" "enemyhealth": "enemy_health"
}, },
"dungeon": {
"mapshuffle": "mapshuffle",
"compassshuffle": "compassshuffle",
"smallkeyshuffle": "keyshuffle",
"bigkeyshuffle": "bigkeyshuffle",
"dungeondoorshuffle": "door_shuffle",
"dungeonintensity": "intensity",
"door_type_mode": "door_type_mode",
"trap_door_mode": "trap_door_mode",
"key_logic_algorithm": "key_logic_algorithm",
"decoupledoors": "decoupledoors",
"keydropshuffle": "keydropshuffle",
"dropshuffle": "dropshuffle",
"pottery": "pottery",
"colorizepots": "colorizepots",
"potshuffle": "shufflepots",
"experimental": "experimental",
"dungeon_counters": "dungeon_counters",
"mixed_travel": "mixed_travel",
"standardize_palettes": "standardize_palettes",
},
"gameoptions": { "gameoptions": {
"nobgm": "disablemusic", "nobgm": "disablemusic",
"quickswap": "quickswap", "quickswap": "quickswap",
@@ -130,12 +135,15 @@ SETTINGSTOPROCESS = {
"createrom": "create_rom", "createrom": "create_rom",
"calcplaythrough": "calc_playthrough", "calcplaythrough": "calc_playthrough",
"print_custom_yaml": "print_custom_yaml", "print_custom_yaml": "print_custom_yaml",
"usestartinventory": "usestartinventory",
"usecustompool": "custom",
"race": "race",
"saveonexit": "saveonexit" "saveonexit": "saveonexit"
} }
}, },
"startinventory": {
"usestartinventory": "usestartinventory"
},
"custom": {
"usecustompool": "custom"
},
"bottom": { "bottom": {
"content": { "content": {
"names": "names", "names": "names",

View File

@@ -203,13 +203,19 @@ def create_guiargs(parent):
# Cycle through each page # Cycle through each page
for mainpage in options: for mainpage in options:
subpage = None
_, v = next(iter(options[mainpage].items()))
if isinstance(v, str):
subpage = ""
# Cycle through each subpage (in case of Item Randomizer) # Cycle through each subpage (in case of Item Randomizer)
for subpage in options[mainpage]: for subpage in (options[mainpage] if subpage is None else [subpage]):
# Cycle through each widget # Cycle through each widget
for widget in options[mainpage][subpage]: for widget in (options[mainpage][subpage] if subpage != "" else options[mainpage]):
# Get the value and set it # Get the value and set it
arg = options[mainpage][subpage][widget] arg = options[mainpage][subpage][widget] if subpage != "" else options[mainpage][widget]
setattr(guiargs, arg, parent.pages[mainpage].pages[subpage].widgets[widget].storageVar.get()) page = parent.pages[mainpage].pages[subpage] if subpage != "" else parent.pages[mainpage]
pagewidgets = page.content.customWidgets if mainpage == "custom" else page.content.startingWidgets if mainpage == "startinventory" else page.widgets
setattr(guiargs, arg, pagewidgets[widget].storageVar.get())
# Get EnemizerCLI setting # Get EnemizerCLI setting
guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].widgets["enemizercli"].storageVar.get() guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].widgets["enemizercli"].storageVar.get()
@@ -226,7 +232,7 @@ def create_guiargs(parent):
guiargs.customizer = customizer_value guiargs.customizer = customizer_value
# Get if we're using the Custom Item Pool # Get if we're using the Custom Item Pool
guiargs.custom = bool(parent.pages["randomizer"].pages["generation"].widgets["usecustompool"].storageVar.get()) guiargs.custom = bool(parent.pages["custom"].content.customWidgets["usecustompool"].storageVar.get())
# Get Seed ID # Get Seed ID
guiargs.seed = None guiargs.seed = None
@@ -285,7 +291,7 @@ def create_guiargs(parent):
guiargs.dropshuffle = 1 guiargs.dropshuffle = 1
guiargs.pottery = 'keys' if guiargs.pottery == 'none' else guiargs.pottery guiargs.pottery = 'keys' if guiargs.pottery == 'none' else guiargs.pottery
if guiargs.retro or guiargs.mode == 'retro': if (hasattr(guiargs, 'retro') and guiargs.retro) or guiargs.mode == 'retro':
if guiargs.bow_mode == 'progressive': if guiargs.bow_mode == 'progressive':
guiargs.bow_mode = 'retro' guiargs.bow_mode = 'retro'
elif guiargs.bow_mode == 'silvers': elif guiargs.bow_mode == 'silvers':

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y
import source.gui.widgets as widgets import source.gui.widgets as widgets
import json import json
import os import os
@@ -11,10 +11,10 @@ def custom_page(top,parent):
# Create uniform list columns # Create uniform list columns
def create_list_frame(parent, framename): def create_list_frame(parent, framename):
parent.frames[framename] = Frame(parent) self.frames[framename] = Frame(parent)
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N) self.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
parent.frames[framename].thisRow = 0 self.frames[framename].thisRow = 0
parent.frames[framename].thisCol = 0 self.frames[framename].thisCol = 0
# Create a vertical rule to help with splitting columns visually # Create a vertical rule to help with splitting columns visually
def create_vertical_rule(num=1): def create_vertical_rule(num=1):
@@ -34,6 +34,8 @@ def custom_page(top,parent):
# Custom Item Pool option sections # Custom Item Pool option sections
self.frames = {} self.frames = {}
self.frames["customHeader"] = Frame(self)
self.frames["customHeader"].pack(side=TOP, anchor=W)
# Create 5 columns with 2 vertical rules in between each # Create 5 columns with 2 vertical rules in between each
create_list_frame(self, "itemList1") create_list_frame(self, "itemList1")
create_vertical_rule(2) create_vertical_rule(2)
@@ -50,9 +52,14 @@ def custom_page(top,parent):
with open(os.path.join("resources", "app", "gui", "custom", "overview", "widgets.json")) as widgetDefns: with open(os.path.join("resources", "app", "gui", "custom", "overview", "widgets.json")) as widgetDefns:
myDict = json.load(widgetDefns) myDict = json.load(widgetDefns)
for framename,theseWidgets in myDict.items(): for framename,theseWidgets in myDict.items():
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename]) if framename in self.frames:
for key in dictWidgets: dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
self.customWidgets[key] = dictWidgets[key] for key in dictWidgets:
self.customWidgets[key] = dictWidgets[key]
if framename == "customHeader":
packAttrs = {"anchor":W}
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
self.customWidgets[key].pack(packAttrs)
# Load Custom Item Pool settings from settings file # Load Custom Item Pool settings from settings file
for key in CONST.CUSTOMITEMS: for key in CONST.CUSTOMITEMS:

View File

@@ -23,34 +23,41 @@ def loadcliargs(gui, args, settings=None):
# Cycle through each page # Cycle through each page
for mainpage in options: for mainpage in options:
subpage = None
_, v = next(iter(options[mainpage].items()))
if isinstance(v, str):
subpage = ""
# Cycle through each subpage (in case of Item Randomizer) # Cycle through each subpage (in case of Item Randomizer)
for subpage in options[mainpage]: for subpage in (options[mainpage] if subpage is None else [subpage]):
# Cycle through each widget # Cycle through each widget
for widget in options[mainpage][subpage]: for widget in (options[mainpage][subpage] if subpage != "" else options[mainpage]):
if widget in gui.pages[mainpage].pages[subpage].widgets: page = gui.pages[mainpage].pages[subpage] if subpage != "" else gui.pages[mainpage]
pagewidgets = page.content.customWidgets if mainpage == "custom" else page.content.startingWidgets if mainpage == "startinventory" else page.widgets
if widget in pagewidgets:
thisType = "" thisType = ""
# Get the value and set it # Get the value and set it
arg = options[mainpage][subpage][widget] arg = options[mainpage][subpage][widget] if subpage != "" else options[mainpage][widget]
if args[arg] == None: if args[arg] == None:
args[arg] = "" args[arg] = ""
label = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget) label_ref = mainpage + ('.' + subpage if subpage != "" else '') + '.' + widget
if hasattr(gui.pages[mainpage].pages[subpage].widgets[widget],"type"): label = fish.translate("gui","gui", label_ref)
thisType = gui.pages[mainpage].pages[subpage].widgets[widget].type if hasattr(pagewidgets[widget],"type"):
thisType = pagewidgets[widget].type
if thisType == "checkbox": if thisType == "checkbox":
gui.pages[mainpage].pages[subpage].widgets[widget].checkbox.configure(text=label) pagewidgets[widget].checkbox.configure(text=label)
elif thisType == "selectbox": elif thisType == "selectbox":
theseOptions = gui.pages[mainpage].pages[subpage].widgets[widget].selectbox.options theseOptions = pagewidgets[widget].selectbox.options
gui.pages[mainpage].pages[subpage].widgets[widget].label.configure(text=label) pagewidgets[widget].label.configure(text=label)
i = 0 i = 0
for value in theseOptions["values"]: for value in theseOptions["values"]:
gui.pages[mainpage].pages[subpage].widgets[widget].selectbox.options["labels"][i] = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget + '.' + str(value)) pagewidgets[widget].selectbox.options["labels"][i] = fish.translate("gui","gui", label_ref + '.' + str(value))
i += 1 i += 1
for i in range(0, len(theseOptions["values"])): for i in range(0, len(theseOptions["values"])):
gui.pages[mainpage].pages[subpage].widgets[widget].selectbox["menu"].entryconfigure(i, label=theseOptions["labels"][i]) pagewidgets[widget].selectbox["menu"].entryconfigure(i, label=theseOptions["labels"][i])
gui.pages[mainpage].pages[subpage].widgets[widget].selectbox.options = theseOptions pagewidgets[widget].selectbox.options = theseOptions
elif thisType == "spinbox": elif thisType == "spinbox":
gui.pages[mainpage].pages[subpage].widgets[widget].label.configure(text=label) pagewidgets[widget].label.configure(text=label)
gui.pages[mainpage].pages[subpage].widgets[widget].storageVar.set(args[arg]) pagewidgets[widget].storageVar.set(args[arg])
# If we're on the Game Options page and it's not about Hints # If we're on the Game Options page and it's not about Hints
if subpage == "gameoptions" and widget not in ["hints", "collection_rate"]: if subpage == "gameoptions" and widget not in ["hints", "collection_rate"]:
# Check if we've got settings # Check if we've got settings

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT, TOP
import source.gui.widgets as widgets import source.gui.widgets as widgets
import json import json
import os import os
@@ -16,8 +16,8 @@ def dungeon_page(parent):
self.frames["keysanity"].pack(anchor=W) self.frames["keysanity"].pack(anchor=W)
## Dungeon Item Shuffle ## Dungeon Item Shuffle
mscbLabel = Label(self.frames["keysanity"], text="Shuffle: ") mscbLabel = Label(self.frames["keysanity"], text="Dungeon Items: ")
mscbLabel.pack(side=LEFT) mscbLabel.pack(side=TOP, anchor=W)
# Load Dungeon Shuffle option widgets as defined by JSON file # Load Dungeon Shuffle option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes # Defns include frame name, widget type, widget options, widget placement attributes
@@ -28,7 +28,9 @@ def dungeon_page(parent):
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["keysanity"]) dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["keysanity"])
for key in dictWidgets: for key in dictWidgets:
self.widgets[key] = dictWidgets[key] self.widgets[key] = dictWidgets[key]
self.widgets[key].pack(side=LEFT) packAttrs = {"side":LEFT}
packAttrs = widgets.add_padding_from_config(packAttrs, myDict[key])
self.widgets[key].pack(packAttrs)
# These get split left & right # These get split left & right
self.frames["widgets"] = Frame(self) self.frames["widgets"] = Frame(self)
@@ -39,6 +41,8 @@ def dungeon_page(parent):
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["widgets"]) dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["widgets"])
for key in dictWidgets: for key in dictWidgets:
self.widgets[key] = dictWidgets[key] self.widgets[key] = dictWidgets[key]
self.widgets[key].pack(anchor=W) packAttrs = {"anchor":W}
packAttrs = widgets.add_padding_from_config(packAttrs, myDict[key])
self.widgets[key].pack(packAttrs)
return self return self

View File

@@ -26,9 +26,8 @@ def entrando_page(parent):
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename]) dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
for key in dictWidgets: for key in dictWidgets:
self.widgets[key] = dictWidgets[key] self.widgets[key] = dictWidgets[key]
packAttrs = {"anchor":E} packAttrs = {"anchor":W}
if self.widgets[key].type == "checkbox": packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
packAttrs["anchor"] = W
self.widgets[key].pack(packAttrs) self.widgets[key].pack(packAttrs)
return self return self

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, Frame, E, W, LEFT, RIGHT, Label from tkinter import ttk, font, Frame, E, W, NW, TOP, LEFT, RIGHT, Y, Label
import source.gui.widgets as widgets import source.gui.widgets as widgets
import json import json
import os import os
@@ -17,13 +17,39 @@ def item_page(parent):
self.frames["checkboxes"] = Frame(self) self.frames["checkboxes"] = Frame(self)
self.frames["checkboxes"].pack(anchor=W) self.frames["checkboxes"].pack(anchor=W)
various_options = Label(self.frames["checkboxes"], text="") various_options = Label(self.frames["checkboxes"], text="Options: ")
various_options.pack(side=LEFT) various_options.pack(side=LEFT)
self.frames["leftItemFrame"] = Frame(self) self.frames["mainFrame"] = Frame(self)
self.frames["rightItemFrame"] = Frame(self) self.frames["mainFrame"].pack(side=TOP, pady=(20,0))
self.frames["poolFrame"] = Frame(self)
self.frames["poolFrame"].pack(fill=Y)
self.frames["leftItemFrame"] = Frame(self.frames["mainFrame"])
self.frames["leftItemFrame"].pack(side=LEFT) self.frames["leftItemFrame"].pack(side=LEFT)
self.frames["rightItemFrame"] = Frame(self.frames["mainFrame"])
self.frames["rightItemFrame"].pack(side=RIGHT) self.frames["rightItemFrame"].pack(side=RIGHT)
self.frames["leftPoolContainer"] = Frame(self.frames["poolFrame"])
self.frames["leftPoolContainer"].pack(side=LEFT, padx=(0,20))
base_font = font.nametofont('TkTextFont').actual()
underline_font = f'"{base_font["family"]}" {base_font["size"]} underline'
various_options = Label(self.frames["leftPoolContainer"], text="Pool Expansions", font=underline_font)
various_options.pack(side=TOP, pady=(20,0))
self.frames["leftPoolHeader"] = Frame(self.frames["leftPoolContainer"])
self.frames["leftPoolHeader"].pack(side=TOP, anchor=W)
self.frames["leftPoolFrame"] = Frame(self.frames["leftPoolContainer"])
self.frames["leftPoolFrame"].pack(side=LEFT, fill=Y)
self.frames["rightPoolFrame"] = Frame(self.frames["poolFrame"])
self.frames["rightPoolFrame"].pack(side=RIGHT)
various_options = Label(self.frames["rightPoolFrame"], text="Pool Modifications", font=underline_font)
various_options.pack(side=TOP, pady=(20,0))
# Load Item Randomizer option widgets as defined by JSON file # Load Item Randomizer option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes # Defns include frame name, widget type, widget options, widget placement attributes
@@ -36,8 +62,15 @@ def item_page(parent):
for key in dictWidgets: for key in dictWidgets:
self.widgets[key] = dictWidgets[key] self.widgets[key] = dictWidgets[key]
packAttrs = {"anchor":E} packAttrs = {"anchor":E}
if self.widgets[key].type == "checkbox": if self.widgets[key].type == "checkbox" or framename == "leftPoolFrame":
packAttrs["anchor"] = W
if framename == "checkboxes":
packAttrs["side"] = LEFT packAttrs["side"] = LEFT
packAttrs["padx"] = (10,0)
elif framename == "leftPoolHeader":
packAttrs["side"] = LEFT
packAttrs["padx"] = (0,20)
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
self.widgets[key].pack(packAttrs) self.widgets[key].pack(packAttrs)
return self return self

View File

@@ -1,4 +1,4 @@
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y
import source.gui.widgets as widgets import source.gui.widgets as widgets
import json import json
import os import os
@@ -11,10 +11,10 @@ def startinventory_page(top,parent):
# Create uniform list columns # Create uniform list columns
def create_list_frame(parent, framename): def create_list_frame(parent, framename):
parent.frames[framename] = Frame(parent) self.frames[framename] = Frame(parent)
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N) self.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
parent.frames[framename].thisRow = 0 self.frames[framename].thisRow = 0
parent.frames[framename].thisCol = 0 self.frames[framename].thisCol = 0
# Create a vertical rule to help with splitting columns visually # Create a vertical rule to help with splitting columns visually
def create_vertical_rule(num=1): def create_vertical_rule(num=1):
@@ -34,6 +34,8 @@ def startinventory_page(top,parent):
# Starting Inventory option sections # Starting Inventory option sections
self.frames = {} self.frames = {}
self.frames["startHeader"] = Frame(self)
self.frames["startHeader"].pack(side=TOP, anchor=W)
# Create 5 columns with 2 vertical rules in between each # Create 5 columns with 2 vertical rules in between each
create_list_frame(self,"itemList1") create_list_frame(self,"itemList1")
create_vertical_rule(2) create_vertical_rule(2)
@@ -55,9 +57,14 @@ def startinventory_page(top,parent):
if key in myDict[thisList]: if key in myDict[thisList]:
del myDict[thisList][key] del myDict[thisList][key]
for framename,theseWidgets in myDict.items(): for framename,theseWidgets in myDict.items():
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename]) if framename in self.frames:
for key in dictWidgets: dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
self.startingWidgets[key] = dictWidgets[key] for key in dictWidgets:
self.startingWidgets[key] = dictWidgets[key]
if framename == "startHeader":
packAttrs = {"anchor":W}
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
self.startingWidgets[key].pack(packAttrs)
# Load Custom Starting Inventory settings from settings file, ignoring ones to be excluded # Load Custom Starting Inventory settings from settings file, ignoring ones to be excluded
for key in CONST.CUSTOMITEMS: for key in CONST.CUSTOMITEMS:

View File

@@ -1,4 +1,4 @@
from tkinter import Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, LEFT, RIGHT, X from tkinter import messagebox, Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, LEFT, RIGHT, X
from source.classes.Empty import Empty from source.classes.Empty import Empty
# Override Spinbox to include mousewheel support for changing value # Override Spinbox to include mousewheel support for changing value
@@ -16,7 +16,7 @@ class mySpinbox(Spinbox):
self.invoke('buttonup') self.invoke('buttonup')
# Make a Checkbutton with a label # Make a Checkbutton with a label
def make_checkbox(self, parent, label, storageVar, manager, managerAttrs): def make_checkbox(self, parent, label, storageVar, manager, managerAttrs, config):
self = Frame(parent) self = Frame(parent)
self.storageVar = storageVar self.storageVar = storageVar
if managerAttrs is not None and "default" in managerAttrs: if managerAttrs is not None and "default" in managerAttrs:
@@ -25,7 +25,10 @@ def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
elif managerAttrs["default"] == "false" or managerAttrs["default"] == False: elif managerAttrs["default"] == "false" or managerAttrs["default"] == False:
self.storageVar.set(False) self.storageVar.set(False)
del managerAttrs["default"] del managerAttrs["default"]
self.checkbox = Checkbutton(self, text=label, variable=self.storageVar) options = {"text":label, "variable":self.storageVar}
if config and "command" in config:
options.update({"command":lambda m=config["command"]: widget_command(self, m)})
self.checkbox = Checkbutton(self, options)
if managerAttrs is not None: if managerAttrs is not None:
self.checkbox.pack(managerAttrs) self.checkbox.pack(managerAttrs)
else: else:
@@ -43,7 +46,11 @@ def make_selectbox(self, parent, label, options, storageVar, manager, managerAtt
self.labelVar = StringVar() self.labelVar = StringVar()
self.storageVar = storageVar self.storageVar = storageVar
self.selectbox = OptionMenu(self, self.labelVar, *labels) if config and "command" in config:
self.command = config["command"]
self.selectbox = OptionMenu(self, self.labelVar, *labels, command=lambda m: widget_command(self, self.command))
else:
self.selectbox = OptionMenu(self, self.labelVar, *labels)
self.selectbox.options = {} self.selectbox.options = {}
if isinstance(options,dict): if isinstance(options,dict):
@@ -96,7 +103,7 @@ def make_selectbox(self, parent, label, options, storageVar, manager, managerAtt
else: else:
self.label.pack(side=LEFT) self.label.pack(side=LEFT)
self.selectbox.config(width=config['width'] if config and config['width'] else 20) self.selectbox.config(width=config['width'] if config and 'width' in config else 20)
idx = 0 idx = 0
default = self.selectbox.options["values"][idx] default = self.selectbox.options["values"][idx]
if managerAttrs is not None and "default" in managerAttrs: if managerAttrs is not None and "default" in managerAttrs:
@@ -181,7 +188,7 @@ def make_widget(self, type, parent, label, storageVar=None, manager=None, manage
if type == "checkbox": if type == "checkbox":
if thisStorageVar is None: if thisStorageVar is None:
thisStorageVar = IntVar() thisStorageVar = IntVar()
widget = make_checkbox(self, parent, label, thisStorageVar, manager, managerAttrs) widget = make_checkbox(self, parent, label, thisStorageVar, manager, managerAttrs, config)
elif type == "selectbox": elif type == "selectbox":
if thisStorageVar is None: if thisStorageVar is None:
thisStorageVar = StringVar() thisStorageVar = StringVar()
@@ -221,3 +228,51 @@ def make_widgets_from_dict(self, defns, parent):
for key,defn in defns.items(): for key,defn in defns.items():
widgets[key] = make_widget_from_dict(self, defn, parent) widgets[key] = make_widget_from_dict(self, defn, parent)
return widgets return widgets
# Add padding to widget
def add_padding_from_config(packAttrs, defn):
if "config" in defn:
config = defn["config"]
if 'padx' in config:
packAttrs["padx"] = config['padx']
if 'pady' in config:
packAttrs["pady"] = config['pady']
return packAttrs
# Callback when a widget issues a command
def widget_command(widget, command=""):
root = widget.winfo_toplevel()
text_output = ""
if command == "worldstate":
if widget.storageVar.get() == 'retro':
temp_widget = root.pages["randomizer"].pages["dungeon"].widgets["smallkeyshuffle"]
text_output += f'\n {temp_widget.label.cget("text")}'
temp_widget.storageVar.set('universal')
temp_widget = root.pages["randomizer"].pages["item"].widgets["bow_mode"]
text_output += f'\n {temp_widget.label.cget("text")}'
if temp_widget.storageVar.get() == 'progressive':
temp_widget.storageVar.set('retro')
elif temp_widget.storageVar.get() == 'silvers':
temp_widget.storageVar.set('retro_silvers')
temp_widget = root.pages["randomizer"].pages["item"].widgets["take_any"]
text_output += f'\n {temp_widget.label.cget("text")}'
if temp_widget.storageVar.get() == 'none':
temp_widget.storageVar.set('random')
widget.storageVar.set('open')
messagebox.showinfo('', f'The following settings were changed:{text_output}')
elif command == "keydropshuffle":
if widget.storageVar.get() > 0:
temp_widget = root.pages["randomizer"].pages["item"].widgets["pottery"]
text_output += f'\n {temp_widget.label.cget("text")}'
if temp_widget.storageVar.get() == 'none':
temp_widget.storageVar.set('keys')
temp_widget = root.pages["randomizer"].pages["item"].widgets["dropshuffle"]
temp_widget.storageVar.set(1)
text_output += f'\n {temp_widget.checkbox.cget("text")}'
widget.storageVar.set(0)
messagebox.showinfo('', f'The following settings were changed:{text_output}')

View File

@@ -119,7 +119,7 @@ def roll_settings(weights):
'ganonhunt': 'ganonhunt', 'ganonhunt': 'ganonhunt',
'completionist': 'completionist' 'completionist': 'completionist'
}[goal] }[goal]
ret.openpyramid = goal in ['fast_ganon', 'trinity'] if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False ret.openpyramid = get_choice('open_pyramid') if 'open_pyramid' in weights else 'auto'
ret.crystals_gt = get_choice('tower_open') ret.crystals_gt = get_choice('tower_open')