Exemplo n.º 1
0
def guiMain(settings=None):
    frames = {}

    mainWindow = Tk()
    mainWindow.wm_title("OoT Randomizer %s" % ESVersion)

    set_icon(mainWindow)

    notebook = ttk.Notebook(mainWindow)
    frames['rom_tab'] = ttk.Frame(notebook)
    frames['rules_tab'] = ttk.Frame(notebook)
    frames['logic_tab'] = ttk.Frame(notebook)
    frames['other_tab'] = ttk.Frame(notebook)
    frames['aesthetic_tab'] = ttk.Frame(notebook)
    adjustWindow = ttk.Frame(notebook)
    customWindow = ttk.Frame(notebook)
    notebook.add(frames['rom_tab'], text='ROM Options')
    notebook.add(frames['rules_tab'], text='Main Rules')
    notebook.add(frames['logic_tab'], text='Detailed Logic')
    notebook.add(frames['other_tab'], text='Other')
    notebook.add(frames['aesthetic_tab'], text='Aesthetics')

    # Shared Controls   

    # adds a LabelFrame containing a list of radio buttons based on the given data
    # returns the label_frame, and a variable associated with it
    def MakeRadioList(parent, data):
        # create a frame to hold the radio buttons
        lable_frame = LabelFrame(parent, text=data["name"], labelanchor=NW)
        # create a variable to hold the result of the user's decision
        radio_var = StringVar(value=data["default"]);
        # setup orientation
        side = TOP
        anchor = W
        if "horizontal" in data and data["horizontal"]:
            side = LEFT
            anchor = N
        # add the radio buttons
        for option in data["options"]:
            radio_button = Radiobutton(lable_frame, text=option["description"], value=option["value"], variable=radio_var,
                                       justify=LEFT, wraplength=data["wraplength"])
            radio_button.pack(expand=True, side=side, anchor=anchor)
        # return the frame so it can be packed, and the var so it can be used
        return (lable_frame, radio_var)

    #######################
    # randomizer controls #
    #######################

    # hold the results of the user's decisions here
    guivars = {}

    # hierarchy
    ############

    #Rules Tab
    frames['open']   = LabelFrame(frames['rules_tab'], text='Open',   labelanchor=NW)
    frames['logic']  = LabelFrame(frames['rules_tab'], text='Logic',  labelanchor=NW)

    # Logic tab
    frames['rewards'] = LabelFrame(frames['logic_tab'], text='Remove Specific Locations', labelanchor=NW)
    frames['tricks']  = LabelFrame(frames['logic_tab'], text='Specific expected tricks', labelanchor=NW)

    #Other Tab
    frames['convenience'] = LabelFrame(frames['other_tab'], text='Speed Ups', labelanchor=NW)
    frames['other']       = LabelFrame(frames['other_tab'], text='Misc',      labelanchor=NW)

    #Aesthetics tab
    frames['tuniccolor'] = LabelFrame(frames['aesthetic_tab'], text='Tunic Color', labelanchor=NW)
    frames['navicolor']       = LabelFrame(frames['aesthetic_tab'], text='Navi Color',  labelanchor=NW)
    frames['lowhp']      = LabelFrame(frames['aesthetic_tab'], text='Low HP SFX',  labelanchor=NW)


    # shared
    settingsFrame = Frame(mainWindow)
    settings_string_var = StringVar()
    settingsEntry = Entry(settingsFrame, textvariable=settings_string_var)

    def show_settings(event=None):
        settings = guivars_to_settings(guivars)
        settings_string_var.set( settings.get_settings_string() )

        # Update any dependencies
        for info in setting_infos:
            if info.gui_params and 'dependency' in info.gui_params:
                dep_met = True
                for dep_var, dep_val in info.gui_params['dependency'].items():
                    if guivars[dep_var].get() != dep_val:
                        dep_met = False

                if widgets[info.name].winfo_class() == 'Frame':
                    for child in widgets[info.name].winfo_children():
                        child.configure(state= 'normal' if dep_met else 'disabled')
                else:
                    widgets[info.name].config(state = 'normal' if dep_met else 'disabled')


    def import_settings(event=None):
        try:
            settings = guivars_to_settings(guivars)
            text = settings_string_var.get().upper()
            settings.seed = guivars['seed'].get()
            settings.update_with_settings_string(text)
            settings_to_guivars(settings, guivars)
        except Exception as e:
            messagebox.showerror(title="Error", message="Invalid settings string")

    label = Label(settingsFrame, text="Settings String")
    importSettingsButton = Button(settingsFrame, text='Import Settings String', command=import_settings)
    label.pack(side=LEFT, anchor=W, padx=5)
    settingsEntry.pack(side=LEFT, anchor=W)
    importSettingsButton.pack(side=LEFT, anchor=W, padx=5)



    fileDialogFrame = Frame(frames['rom_tab'])

    romDialogFrame = Frame(fileDialogFrame)
    baseRomLabel = Label(romDialogFrame, text='Base Rom')
    guivars['rom'] = StringVar(value='ZOOTDEC.z64')
    romEntry = Entry(romDialogFrame, textvariable=guivars['rom'], width=40)

    def RomSelect():
        rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".z64", ".n64")), ("All Files", "*")])
        if rom != '':
            guivars['rom'].set(rom)
    romSelectButton = Button(romDialogFrame, text='Select Rom', command=RomSelect, width=10)

    baseRomLabel.pack(side=LEFT, padx=(40,0))
    romEntry.pack(side=LEFT, padx=3)
    romSelectButton.pack(side=LEFT)

    romDialogFrame.pack()

    fileDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(5,1))

    def open_output():
        open_file(output_path(''))
    
    def output_dir_select():
        rom = filedialog.askdirectory(initialdir = default_output_path(guivars['output_dir'].get()))
        if rom != '':
            guivars['output_dir'].set(rom)

    outputDialogFrame = Frame(frames['rom_tab'])
    outputDirLabel = Label(outputDialogFrame, text='Output Directory')
    guivars['output_dir'] = StringVar(value='')
    outputDirEntry = Entry(outputDialogFrame, textvariable=guivars['output_dir'], width=40)
    outputDirButton = Button(outputDialogFrame, text='Select Dir', command=output_dir_select, width=10)
    outputDirLabel.pack(side=LEFT, padx=(3,0))
    outputDirEntry.pack(side=LEFT, padx=3)
    outputDirButton.pack(side=LEFT)
    outputDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(5,1))

    if os.path.exists(local_path('README.html')):
        def open_readme():
            open_file(local_path('README.html'))
        openReadmeButton = Button(outputDialogFrame, text='Open Documentation', command=open_readme)
        openReadmeButton.pack(side=LEFT, padx=5)

    outputDialogFrame.pack(side=TOP, anchor=W, pady=3)

    countDialogFrame = Frame(frames['rom_tab'])
    countLabel = Label(countDialogFrame, text='Generation Count')
    guivars['count'] = StringVar()
    countSpinbox = Spinbox(countDialogFrame, from_=1, to=100, textvariable=guivars['count'], width=3)

    countLabel.pack(side=LEFT)
    countSpinbox.pack(side=LEFT, padx=2)
    countDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(1,1))

    multiworldFrame = LabelFrame(frames['rom_tab'], text='Multi-World Generation')
    countLabel = Label(multiworldFrame, wraplength=300, justify=LEFT, text='This is used for co-op generations. Increasing World Count will drastically increase the generation time. For more information see https://github.com/TestRunnerSRL/bizhawk-co-op')
    countLabel.pack(side=TOP, anchor=W, padx=5, pady=(1,1))


    worldCountFrame = Frame(multiworldFrame)
    countLabel = Label(worldCountFrame, text='World Count')
    guivars['world_count'] = StringVar()
    countSpinbox = Spinbox(worldCountFrame, from_=1, to=100, textvariable=guivars['world_count'], width=3)

    countLabel.pack(side=LEFT)
    countSpinbox.pack(side=LEFT, padx=2)
    worldCountFrame.pack(side=LEFT, anchor=N, padx=5, pady=(1,1))

    playerNumFrame = Frame(multiworldFrame)
    countLabel = Label(playerNumFrame, text='Player Number')
    guivars['player_num'] = StringVar()
    countSpinbox = Spinbox(playerNumFrame, from_=1, to=100, textvariable=guivars['player_num'], width=3)

    countLabel.pack(side=LEFT)
    countSpinbox.pack(side=LEFT, padx=2)
    playerNumFrame.pack(side=LEFT, anchor=N, padx=5, pady=(1,1))
    multiworldFrame.pack(side=TOP, anchor=W, padx=5, pady=(1,1))




    # build gui
    ############

    widgets = {}

    for info in setting_infos:
        if info.gui_params:
            if info.gui_params['widget'] == 'Checkbutton':
                # determine the initial value of the checkbox
                default_value = 1 if info.gui_params['default'] == "checked" else 0
                # create a variable to access the box's state
                guivars[info.name] = IntVar(value=default_value)
                # create the checkbox
                widgets[info.name] = Checkbutton(frames[info.gui_params['group']], text=info.gui_params['text'], variable=guivars[info.name], justify=LEFT, wraplength=200, command=show_settings)
                widgets[info.name].pack(expand=False, anchor=W)
            elif info.gui_params['widget'] == 'Combobox':
                # create the variable to store the user's decision
                guivars[info.name] = StringVar(value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])
                # dropdown = OptionMenu(widgets[info.name], guivars[info.name], *(info['options']))
                if isinstance(info.gui_params['options'], list):
                    info.gui_params['options'] = dict(zip(info.gui_params['options'], info.gui_params['options']))
                dropdown = ttk.Combobox(widgets[info.name], textvariable=guivars[info.name], values=list(info.gui_params['options'].keys()), state='readonly', width=30)
                dropdown.bind("<<ComboboxSelected>>", show_settings)
                dropdown.pack(side=BOTTOM, anchor=W)
                # label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name], text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
            elif info.gui_params['widget'] == 'Scale':
                # create the variable to store the user's decision
                guivars[info.name] = IntVar(value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])
                # dropdown = OptionMenu(widgets[info.name], guivars[info.name], *(info['options']))
                minval = 'min' in info.gui_params and info.gui_params['min'] or 0
                maxval = 'max' in info.gui_params and info.gui_params['max'] or 100
                stepval = 'step' in info.gui_params and info.gui_params['step'] or 1


                scale = Scale(widgets[info.name], variable=guivars[info.name], from_=minval, to=maxval, tickinterval=stepval, resolution=stepval, showvalue=0, orient=HORIZONTAL, sliderlength=15, length=200, command=show_settings)
                scale.pack(side=BOTTOM, anchor=W)
                # label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name], text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
            elif info.gui_params['widget'] == 'Entry':
                # create the variable to store the user's decision
                guivars[info.name] = StringVar(value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])

                entry = Entry(widgets[info.name], textvariable=guivars[info.name], width=30)
                entry.pack(side=BOTTOM, anchor=W)
                # label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name], text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)


    # pack the hierarchy

    frames['open'].pack(  fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1) )
    frames['logic'].pack( fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1) )

    # Logic tab
    frames['rewards'].pack(fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1) )
    frames['tricks'].pack( fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1) )

    #Other Tab
    frames['convenience'].pack(fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1) )
    frames['other'].pack(      fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1) )

    #Aesthetics tab
    frames['navicolor'].pack( fill=BOTH, expand=True, anchor=N, side=RIGHT, pady=(5,1) )
    frames['tuniccolor'].pack(fill=BOTH, expand=True, anchor=W, side=TOP, pady=(5,1) )
    frames['lowhp'].pack(     fill=BOTH, expand=True, anchor=W, side=BOTTOM, pady=(5,1) )

    
    notebook.pack(fill=BOTH, expand=True, padx=5, pady=5)



    # didn't refactor the rest, sorry


    # create the option menu

    settingsFrame.pack(fill=BOTH, anchor=W, padx=5, pady=(10,0))

    def generateRom():
        settings = guivars_to_settings(guivars)

        try:
            if settings.count is not None:
                orig_seed = settings.seed
                for i in range(settings.count):
                    settings.update_seed(orig_seed + '-' + str(i))
                    main(settings)
            else:
                main(settings)
        except Exception as e:
            messagebox.showerror(title="Error while creating seed", message=str(e))
        else:
            messagebox.showinfo(title="Success", message="Rom patched successfully")

    generateSeedFrame = Frame(mainWindow)
    generateButton = Button(generateSeedFrame, text='Generate Patched Rom', command=generateRom)

    seedLabel = Label(generateSeedFrame, text='Seed')
    guivars['seed'] = StringVar()
    seedEntry = Entry(generateSeedFrame, textvariable=guivars['seed'])
    seedLabel.pack(side=LEFT)
    seedEntry.pack(side=LEFT)
    generateButton.pack(side=LEFT, padx=(5, 0))

    generateSeedFrame.pack(side=BOTTOM, anchor=W, padx=5, pady=10)

    if settings is not None:
        # load values from commandline args
        settings_to_guivars(settings, guivars)
    else:
        # try to load saved settings
        try:
            with open('settings.sav') as f:
                settings = Settings( json.load(f) )
                settings.update_seed("")
                settings_to_guivars(settings, guivars)
        except:
            pass

    show_settings()

    mainWindow.mainloop()

    # save settings on close
    with open('settings.sav', 'w') as outfile:
        settings = guivars_to_settings(guivars)
        json.dump(settings.__dict__, outfile)
Exemplo n.º 2
0
def guiMain(args=None):
    mainWindow = Tk()
    mainWindow.wm_title("OoT Randomizer %s" % ESVersion)

    set_icon(mainWindow)

    notebook = ttk.Notebook(mainWindow)
    randomizerWindow = ttk.Frame(notebook)
    adjustWindow = ttk.Frame(notebook)
    customWindow = ttk.Frame(notebook)
    notebook.add(randomizerWindow, text='Randomize')
    notebook.pack()

    # Shared Controls

    farBottomFrame = Frame(mainWindow)

    def open_output():
        open_file(output_path(''))

    openOutputButton = Button(farBottomFrame, text='Open Output Directory', command=open_output)

    if os.path.exists(local_path('README.html')):
        def open_readme():
            open_file(local_path('README.html'))
        openReadmeButton = Button(farBottomFrame, text='Open Documentation', command=open_readme)
        openReadmeButton.pack(side=LEFT)

    farBottomFrame.pack(side=BOTTOM, fill=X, padx=5, pady=5)

    # randomizer controls

    topFrame = Frame(randomizerWindow)
    rightHalfFrame = Frame(topFrame)
    checkBoxFrame = Frame(rightHalfFrame)

    createSpoilerVar = IntVar()
    createSpoilerCheckbutton = Checkbutton(checkBoxFrame, text="Create Spoiler Log", variable=createSpoilerVar)
    suppressRomVar = IntVar()
    suppressRomCheckbutton = Checkbutton(checkBoxFrame, text="Do not create patched Rom", variable=suppressRomVar)
    compressRomVar = IntVar()
    compressRomCheckbutton = Checkbutton(checkBoxFrame, text="Compress patched Rom", variable=compressRomVar)
    openForestVar = IntVar()
    openForestCheckbutton = Checkbutton(checkBoxFrame, text="Open Forest", variable=openForestVar)
    openDoorVar = IntVar()
    openDoorCheckbutton = Checkbutton(checkBoxFrame, text="Open Door of Time", variable=openDoorVar)
    dungeonItemsVar = IntVar()
    dungeonItemsCheckbutton = Checkbutton(checkBoxFrame, text="Place Dungeon Items (Compasses/Maps)", onvalue=0, offvalue=1, variable=dungeonItemsVar)
    beatableOnlyVar = IntVar()
    beatableOnlyCheckbutton = Checkbutton(checkBoxFrame, text="Only ensure seed is beatable, not all items must be reachable", variable=beatableOnlyVar)
    hintsVar = IntVar()
    hintsCheckbutton = Checkbutton(checkBoxFrame, text="Gossip Stone Hints with Stone of Agony", variable=hintsVar)

    createSpoilerCheckbutton.pack(expand=True, anchor=W)
    suppressRomCheckbutton.pack(expand=True, anchor=W)
    compressRomCheckbutton.pack(expand=True, anchor=W)
    openForestCheckbutton.pack(expand=True, anchor=W)
    openDoorCheckbutton.pack(expand=True, anchor=W)
    dungeonItemsCheckbutton.pack(expand=True, anchor=W)
    beatableOnlyCheckbutton.pack(expand=True, anchor=W)
    hintsCheckbutton.pack(expand=True, anchor=W)

    fileDialogFrame = Frame(rightHalfFrame)

    romDialogFrame = Frame(fileDialogFrame)
    baseRomLabel = Label(romDialogFrame, text='Base Rom')
    romVar = StringVar()
    romEntry = Entry(romDialogFrame, textvariable=romVar)

    def RomSelect():
        rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".z64", ".n64")), ("All Files", "*")])
        romVar.set(rom)
    romSelectButton = Button(romDialogFrame, text='Select Rom', command=RomSelect)

    baseRomLabel.pack(side=LEFT)
    romEntry.pack(side=LEFT)
    romSelectButton.pack(side=LEFT)

    romDialogFrame.pack()

    checkBoxFrame.pack()
    fileDialogFrame.pack()

    drowDownFrame = Frame(topFrame)


    bridgeFrame = Frame(drowDownFrame)
    bridgeVar = StringVar()
    bridgeVar.set('medallions')
    bridgeOptionMenu = OptionMenu(bridgeFrame, bridgeVar, 'medallions', 'vanilla', 'dungeons', 'open')
    bridgeOptionMenu.pack(side=RIGHT)
    bridgeLabel = Label(bridgeFrame, text='Rainbow Bridge Requirement')
    bridgeLabel.pack(side=LEFT)

    bridgeFrame.pack(expand=True, anchor=E)

    bottomFrame = Frame(randomizerWindow)

    seedLabel = Label(bottomFrame, text='Seed #')
    seedVar = StringVar()
    seedEntry = Entry(bottomFrame, textvariable=seedVar)
    countLabel = Label(bottomFrame, text='Count')
    countVar = StringVar()
    countSpinbox = Spinbox(bottomFrame, from_=1, to=100, textvariable=countVar)

    def generateRom():
        guiargs = Namespace
        guiargs.seed = int(seedVar.get()) if seedVar.get() else None
        guiargs.count = int(countVar.get()) if countVar.get() != '1' else None
        guiargs.bridge = bridgeVar.get()
        guiargs.create_spoiler = bool(createSpoilerVar.get())
        guiargs.suppress_rom = bool(suppressRomVar.get())
        guiargs.compress_rom = bool(compressRomVar.get())
        guiargs.open_forest = bool(openForestVar.get())
        guiargs.open_door_of_time = bool(openDoorVar.get())
        guiargs.nodungeonitems = bool(dungeonItemsVar.get())
        guiargs.beatableonly = bool(beatableOnlyVar.get())
        guiargs.hints = bool(hintsVar.get())
        guiargs.rom = romVar.get()
        try:
            if guiargs.count is not None:
                seed = guiargs.seed
                for _ in range(guiargs.count):
                    main(seed=seed, args=guiargs)
                    seed = random.randint(0, 999999999)
            else:
                main(seed=guiargs.seed, args=guiargs)
        except Exception as e:
            messagebox.showerror(title="Error while creating seed", message=str(e))
        else:
            messagebox.showinfo(title="Success", message="Rom patched successfully")

    generateButton = Button(bottomFrame, text='Generate Patched Rom', command=generateRom)

    seedLabel.pack(side=LEFT)
    seedEntry.pack(side=LEFT)
    countLabel.pack(side=LEFT, padx=(5, 0))
    countSpinbox.pack(side=LEFT)
    generateButton.pack(side=LEFT, padx=(5, 0))

    openOutputButton.pack(side=RIGHT)

    drowDownFrame.pack(side=LEFT)
    rightHalfFrame.pack(side=RIGHT)
    topFrame.pack(side=TOP)
    bottomFrame.pack(side=BOTTOM)

    if args is not None:
        # load values from commandline args
        createSpoilerVar.set(int(args.create_spoiler))
        suppressRomVar.set(int(args.suppress_rom))
        compressRomVar.set(int(args.compress_rom))
        if args.nodungeonitems:
            dungeonItemsVar.set(int(not args.nodungeonitems))
        openForestVar.set(int(args.open_forest))
        openDoorVar.set(int(args.open_door_of_time))
        beatableOnlyVar.set(int(args.beatableonly))
        hintsVar.set(int(args.hints))
        if args.count:
            countVar.set(str(args.count))
        if args.seed:
            seedVar.set(str(args.seed))
        bridgeVar.set(args.bridge)
        romVar.set(args.rom)

    mainWindow.mainloop()
Exemplo n.º 3
0
    def __init__(self, parent, callback, adjuster=False):
        if is_bundled():
            self.deploy_icons()
        self.parent = parent
        self.window = Toplevel(parent)
        self.window.geometry("800x650")
        self.sections = []
        self.callback = callback
        self.adjuster = adjuster

        self.window.wm_title("TAKE ANY ONE YOU WANT")
        self.window['padx'] = 5
        self.window['pady'] = 5
        self.all_sprites = []

        def open_official_sprite_listing(_evt):
            webbrowser.open("http://alttpr.com/sprite_preview")

        def open_unofficial_sprite_dir(_evt):
            open_file(self.unofficial_sprite_dir)

        def open_spritesomething_listing(_evt):
            webbrowser.open(
                "https://artheau.github.io/SpriteSomething/?mode=zelda3/link")

        official_frametitle = Frame(self.window)
        official_title_text = Label(official_frametitle,
                                    text="Official Sprites")
        official_title_link = Label(official_frametitle,
                                    text="(open)",
                                    fg="blue",
                                    cursor="hand2")
        official_title_text.pack(side=LEFT)
        official_title_link.pack(side=LEFT)
        official_title_link.bind("<Button-1>", open_official_sprite_listing)

        unofficial_frametitle = Frame(self.window)
        unofficial_title_text = Label(unofficial_frametitle,
                                      text="Unofficial Sprites")
        unofficial_title_link = Label(unofficial_frametitle,
                                      text="(open)",
                                      fg="blue",
                                      cursor="hand2")
        unofficial_title_text.pack(side=LEFT)
        unofficial_title_link.pack(side=LEFT)
        unofficial_title_link.bind("<Button-1>", open_unofficial_sprite_dir)
        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)

        self.icon_section(
            official_frametitle, self.official_sprite_dir + '/*',
            'Official sprites not found. Click "Update official sprites" to download them.'
        )
        self.icon_section(
            unofficial_frametitle, self.unofficial_sprite_dir + '/*',
            'Put sprites in the unofficial sprites folder (see open link above) to have them appear here.'
        )

        frame = Frame(self.window)
        frame.pack(side=BOTTOM, fill=X, pady=5)

        button = Button(frame,
                        text="Browse for file...",
                        command=self.browse_for_sprite)
        button.pack(side=RIGHT, padx=(5, 0))

        button = Button(frame,
                        text="Update official sprites",
                        command=self.update_official_sprites)
        button.pack(side=RIGHT, padx=(5, 0))

        button = Button(frame,
                        text="Default Link sprite",
                        command=self.use_default_link_sprite)
        button.pack(side=LEFT, padx=(0, 5))

        button = Button(frame,
                        text="Random sprite",
                        command=self.use_random_sprite)
        button.pack(side=LEFT, padx=(0, 5))

        if adjuster:
            button = Button(frame,
                            text="Current sprite from rom",
                            command=self.use_default_sprite)
            button.pack(side=LEFT, padx=(0, 5))

        set_icon(self.window)
        self.window.focus()
Exemplo n.º 4
0
def guiMain(settings=None):
    frames = {}

    mainWindow = Tk()
    mainWindow.wm_title("OoT Randomizer %s" % ESVersion)
    mainWindow.resizable(False, False)

    set_icon(mainWindow)

    notebook = ttk.Notebook(mainWindow)
    frames['rom_tab'] = ttk.Frame(notebook)
    frames['rules_tab'] = ttk.Frame(notebook)
    frames['logic_tab'] = ttk.Frame(notebook)
    frames['other_tab'] = ttk.Frame(notebook)
    frames['cosmetic_tab'] = ttk.Frame(notebook)
    frames['SFX_tab'] = ttk.Frame(notebook)
    frames['cosmetic_tab_left'] = Frame(frames['cosmetic_tab'])
    frames['cosmetic_tab_right'] = Frame(frames['cosmetic_tab'])
    notebook.add(frames['rom_tab'], text='ROM Options')
    notebook.add(frames['rules_tab'], text='Main Rules')
    notebook.add(frames['logic_tab'], text='Detailed Logic')
    notebook.add(frames['other_tab'], text='Other')
    notebook.add(frames['cosmetic_tab'], text='Cosmetic')
    notebook.add(frames['SFX_tab'], text='SFX')

    #######################
    # Randomizer controls #
    #######################

    # Hold the results of the user's decisions here
    guivars = {}
    widgets = {}
    presets = {}

    # Hierarchy
    ############

    #Rules Tab
    frames['open']        = LabelFrame(frames['rules_tab'],          text='Open',              labelanchor=NW)
    frames['world']       = LabelFrame(frames['rules_tab'],          text='World',             labelanchor=NW)
    frames['shuffle']     = LabelFrame(frames['rules_tab'],          text='Shuffle',           labelanchor=NW)

    # Logic tab
    frames['checks']      = LabelFrame(frames['logic_tab'],          text='Adult Trade Sequence', labelanchor=NW)
    frames['tricks']      = LabelFrame(frames['logic_tab'],          text='Lens of Truth',     labelanchor=NW)

    #Other Tab
    frames['convenience'] = LabelFrame(frames['other_tab'],          text='Timesavers',        labelanchor=NW)
    frames['other']       = LabelFrame(frames['other_tab'],          text='Misc',              labelanchor=NW)

    #Cosmetic tab
    frames['cosmetic']    = LabelFrame(frames['cosmetic_tab_left'],  text='General',           labelanchor=NW)
    frames['sword_trails']= LabelFrame(frames['cosmetic_tab_left'],  text='Sword Trail Colors',labelanchor=NW)
    frames['ui_colors']=    LabelFrame(frames['cosmetic_tab_left'], text='UI Colors',         labelanchor=NW)
    frames['tunic_colors']= LabelFrame(frames['cosmetic_tab_right'], text='Tunic Colors',      labelanchor=NW)
    frames['navi_colors']=  LabelFrame(frames['cosmetic_tab_right'], text='Navi Colors',       labelanchor=NW)
    frames['gauntlet_colors']= LabelFrame(frames['cosmetic_tab_right'], text='Gauntlet Colors', labelanchor=NW)

    #Cosmetic tab
    frames['sfx']         = LabelFrame(frames['SFX_tab'],            text='General',           labelanchor=NW)
    frames['menu_sfx']    = LabelFrame(frames['SFX_tab'],            text='Menu',              labelanchor=NW)
    frames['npc_sfx']     = LabelFrame(frames['SFX_tab'],            text='NPC',               labelanchor=NW)


    # Shared
    def toggle_widget(widget, enabled):
        widget_type = widget.winfo_class()
        if widget_type == 'Frame' or widget_type == 'TFrame' or widget_type == 'Labelframe':
            if widget_type == 'Labelframe':
                widget.configure(fg='Black'if enabled else 'Grey')
            for child in widget.winfo_children():
                toggle_widget(child, enabled)
        else:
            if widget_type == 'TCombobox':
                widget.configure(state= 'readonly' if enabled else 'disabled')
            else:
                widget.configure(state= 'normal' if enabled else 'disabled')

            if widget_type == 'Scale':
                widget.configure(fg='Black'if enabled else 'Grey')

    def show_settings(*event):
        settings = guivars_to_settings(guivars)
        settings_string_var.set( settings.get_settings_string() )

        # Update any dependencies
        for info in setting_infos:
            dep_met = settings.check_dependency(info.name)

            if info.name in widgets:
                toggle_widget(widgets[info.name], dep_met)

            if info.type == list:
                widgets[info.name].delete(0, END)
                widgets[info.name].insert(0, *guivars[info.name])

            if info.type != list and info.name in guivars and guivars[info.name].get() == 'Custom Color':
                color = colorchooser.askcolor()
                if color == (None, None):
                    color = ((0,0,0),'#000000')
                guivars[info.name].set('Custom (' + color[1] + ')')

            if info.type != list and info.name in guivars and guivars[info.name].get() == 'Custom Navi Color':
                innerColor = colorchooser.askcolor(title='Pick an Inner Core color.')
                if innerColor == (None, None):
                    innerColor = ((0,0,0),'#000000')
                outerColor = colorchooser.askcolor(title='Pick an Outer Glow color.')
                if outerColor == (None, None):
                    outerColor = ((0,0,0),'#000000')
                guivars[info.name].set('Custom (%s %s)' % (innerColor[1], outerColor[1]))

        update_generation_type()


    versionCheckFrame = Frame(frames['rom_tab'])
    versionCheckFrame.pack(side=BOTTOM, anchor=NW, fill=X)

    fileDialogFrame = Frame(frames['rom_tab'])

    romDialogFrame = Frame(fileDialogFrame)
    baseRomLabel = Label(romDialogFrame, text='Base ROM')
    guivars['rom'] = StringVar(value='')
    romEntry = Entry(romDialogFrame, textvariable=guivars['rom'], width=50)

    def RomSelect():
        rom = filedialog.askopenfilename(filetypes=[("ROM Files", (".z64", ".n64")), ("All Files", "*")])
        if rom != '':
            guivars['rom'].set(rom)
    romSelectButton = Button(romDialogFrame, text='Browse', command=RomSelect, width=10)

    baseRomLabel.pack(side=LEFT, padx=(34,0))
    romEntry.pack(side=LEFT, padx=3)
    romSelectButton.pack(side=LEFT)

    romDialogFrame.pack()

    fileDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(5,1))

    def output_dir_select():
        rom = filedialog.askdirectory(initialdir = default_output_path(guivars['output_dir'].get()))
        if rom != '':
            guivars['output_dir'].set(rom)

    outputDialogFrame = Frame(frames['rom_tab'])
    outputDirLabel = Label(outputDialogFrame, text='Output Directory')
    guivars['output_dir'] = StringVar(value='')
    outputDirEntry = Entry(outputDialogFrame, textvariable=guivars['output_dir'], width=50)
    outputDirButton = Button(outputDialogFrame, text='Browse', command=output_dir_select, width=10)
    outputDirLabel.pack(side=LEFT, padx=(3,0))
    outputDirEntry.pack(side=LEFT, padx=3)
    outputDirButton.pack(side=LEFT)
    outputDialogFrame.pack(side=TOP, anchor=W, pady=3)

    distFileDialogFrame = Frame(frames['rom_tab'])
    distFileLabel = Label(distFileDialogFrame, text='Distribution File')
    guivars['distribution_file'] = StringVar(value='')
    distFileEntry = Entry(distFileDialogFrame, textvariable=guivars['distribution_file'], width=50)

    def DistFileSelect():
        distFile = filedialog.askopenfilename(filetypes=[("JSON Files", (".json")), ("All Files", "*")])
        if distFile != '':
            guivars['distribution_file'].set(distFile)
    distFileSelectButton = Button(distFileDialogFrame, text='Browse', command=DistFileSelect, width=10)

    distFileLabel.pack(side=LEFT, padx=(9,0))
    distFileEntry.pack(side=LEFT, padx=3)
    distFileSelectButton.pack(side=LEFT)

    distFileDialogFrame.pack(side=TOP, anchor=W, pady=3)

    countDialogFrame = Frame(frames['rom_tab'])
    countLabel = Label(countDialogFrame, text='Generation Count')
    guivars['count'] = StringVar()
    widgets['count'] = Spinbox(countDialogFrame, from_=1, to=100, textvariable=guivars['count'], width=3)

    def open_readme():
        open_file('https://wiki.ootrandomizer.com/index.php?title=Main_Page')
    openReadmeButton = Button(countDialogFrame, text='Open Wiki Page', command=open_readme)
    openReadmeButton.pack(side=RIGHT, padx=5)

    def open_output():
        open_file(default_output_path(guivars['output_dir'].get()))
    openOutputButton = Button(countDialogFrame, text='Open Output Directory', command=open_output)
    openOutputButton.pack(side=RIGHT, padx=5)

    countLabel.pack(side=LEFT)
    widgets['count'].pack(side=LEFT, padx=2)
    countDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(1,1))

    # Build gui
    ############

    for info in setting_infos:
        if 'group' in info.gui_params:
            if info.gui_params['widget'] == 'Checkbutton':
                # Determine the initial value of the checkbox
                default_value = 1 if info.choices[info.default] == 'checked' else 0
                # Create a variable to access the box's state
                guivars[info.name] = IntVar(value=default_value)
                # Create the checkbox
                widgets[info.name] = Checkbutton(frames[info.gui_params['group']], text=info.gui_params['text'], variable=guivars[info.name], justify=LEFT, wraplength=220, command=show_settings)
                widgets[info.name].pack(expand=False, anchor=W)
            elif info.gui_params['widget'] == 'Combobox':
                # Create the variable to store the user's decision
                guivars[info.name] = StringVar(value=info.choices[info.default])
                # Create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])
                dropdown = ttk.Combobox(widgets[info.name], textvariable=guivars[info.name], values=list(map(lambda choice: info.choices[choice], info.choice_list)), state='readonly', width=36)
                dropdown.bind("<<ComboboxSelected>>", show_settings)
                dropdown.pack(side=BOTTOM, anchor=W)
                # Label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name], text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # Pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
            elif info.gui_params['widget'] == 'Radiobutton':
                # Create the variable to store the user's decision
                guivars[info.name] = StringVar(value=info.choices[info.default])
                # Create the option menu
                widgets[info.name] = LabelFrame(frames[info.gui_params['group']], text=info.gui_params.get('text', info.name), labelanchor=NW)
                # Setup orientation
                side = TOP
                anchor = W
                if "horizontal" in info.gui_params and info.gui_params["horizontal"]:
                    side = LEFT
                    anchor = N
                # Add the radio buttons
                for option in map(lambda choice: info.choices[choice], info.choice_list):
                    radio_button = Radiobutton(widgets[info.name], text=option, value=option, variable=guivars[info.name], justify=LEFT, wraplength=220, indicatoron=False, command=show_settings)
                    radio_button.pack(expand=True, side=side, anchor=anchor)
                # Pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
            elif info.gui_params['widget'] == 'Scale':
                # Create the variable to store the user's decision
                guivars[info.name] = IntVar(value=info.choices[info.default])
                # Create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])
                minval = info.gui_params.get('min', 0)
                maxval = info.gui_params.get('max', 100)
                stepval = info.gui_params.get('step', 1)
                scale = Scale(widgets[info.name], variable=guivars[info.name], from_=minval, to=maxval, tickinterval=stepval, resolution=stepval, showvalue=0, orient=HORIZONTAL, sliderlength=15, length=235, command=show_settings)
                scale.pack(side=BOTTOM, anchor=W)
                # Label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name], text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # Pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
            elif info.gui_params['widget'] == 'Entry':
                # Create the variable to store the user's decision
                guivars[info.name] = StringVar(value=info.default)
                # Create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])

                if 'validate' in info.gui_params:
                    entry = ValidatingEntry(widgets[info.name], command=show_settings, validate=info.gui_params['validate'], textvariable=guivars[info.name], width=35)
                else:
                    entry = Entry(widgets[info.name], textvariable=guivars[info.name], width=36)
                entry.pack(side=BOTTOM, anchor=W)
                # Label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name], text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # Pack the frame
                widgets[info.name].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
            elif info.gui_params['widget'] == 'SearchBox' or info.gui_params['widget'] == 'FilteredSearchBox':
                filtered = (info.gui_params['widget'] == 'FilteredSearchBox')
                search_frame = LabelFrame(frames[info.gui_params['group']], text=info.gui_params.get('text', info.name), labelanchor=NW)

                if filtered:
                    filter_frame = Frame(search_frame)
                    widgets[info.name + '_filterlabel'] = Label(filter_frame, text="Filter: ")
                    widgets[info.name + '_filterlabel'].pack(side=LEFT, anchor=W)
                    widgets[info.name + '_entry'] = SearchBox(search_frame, list(map(lambda choice: info.choices[choice], info.choice_list)), width=78)
                    widgets[info.name + '_filter'] = SearchBoxFilterControl(filter_frame, widgets[info.name + '_entry'], info.gui_params['filterdata'], width=50)
                    widgets[info.name + '_filter'].pack(expand=False, side=LEFT, anchor=W)
                    filter_frame.pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)
                    widgets[info.name + '_entry'].pack(expand=False, side=TOP, anchor=W)
                else:
                    widgets[info.name + '_entry'] = SearchBox(search_frame, list(map(lambda choice: info.choices[choice], info.choice_list)), width=78)
                    widgets[info.name + '_entry'].pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)

                list_frame = Frame(search_frame)
                scrollbar = Scrollbar(list_frame, orient=VERTICAL)
                widgets[info.name] = Listbox(list_frame, width=78, height=7, yscrollcommand=scrollbar.set)
                guivars[info.name] = list(info.default)
                scrollbar.config(command=widgets[info.name].yview)
                scrollbar.pack(side=RIGHT, fill=Y)
                widgets[info.name].pack(side=LEFT)
                list_frame.pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)

                if 'entry_tooltip' in info.gui_params:
                    ToolTips.register(widgets[info.name + '_entry'], info.gui_params['entry_tooltip'])
                    if filtered:
                        ToolTips.register(widgets[info.name + '_filter'], info.gui_params['entry_tooltip'])
                if 'list_tooltip' in info.gui_params:
                    ToolTips.register(widgets[info.name], info.gui_params['list_tooltip'])

                def get_lambda(function, *args):
                    return lambda: function(*args)

                def add_list_selected(name):
                    new_location = widgets[name +'_entry'].get()
                    if new_location in widgets[name +'_entry'].options and new_location not in widgets[name].get(0, END):
                        widgets[name].insert(END, new_location)
                        guivars[name].append(new_location)
                    show_settings()

                def remove_list_selected(name):
                    location = widgets[name].get(ACTIVE)
                    widgets[name].delete(ACTIVE)
                    guivars[name].remove(location)
                    show_settings()

                def add_list_all(name):
                    for new_location in widgets[name + '_entry'].options:
                        if new_location not in widgets[name].get(0, END):
                            widgets[name].insert(END, new_location)
                            guivars[name].append(new_location)
                    show_settings()

                def remove_list_all(name):
                    items = list(widgets[name].get(0, END))
                    widgets[name].delete(0, END)
                    guivars[name] = []
                    for item in (x for x in items if x not in widgets[name + '_entry'].options):
                        widgets[name].insert(END, item)
                        guivars[name].append(item)
                    show_settings()
                    
                def clear_list_all(name):
                    widgets[name].delete(0, END)
                    guivars[name] = []
                    show_settings()

                list_button_frame = Frame(search_frame)
                list_add = Button(list_button_frame, width=10, text='Add', command=get_lambda(add_list_selected, info.name))
                list_add.pack(side=LEFT, anchor=N, padx=3, pady=3)
                list_remove = Button(list_button_frame, width=10, text='Remove', command=get_lambda(remove_list_selected, info.name))
                list_remove.pack(side=LEFT, anchor=N, padx=3, pady=3)

                list_add = Button(list_button_frame, width=10, text='All', command=get_lambda(add_list_all, info.name))
                list_add.pack(side=LEFT, anchor=N, padx=3, pady=3)
                list_remove = Button(list_button_frame, width=10, text='None', command=get_lambda(remove_list_all, info.name))
                list_remove.pack(side=LEFT, anchor=N, padx=3, pady=3)
                if filtered:
                    list_clear = Button(list_button_frame, width=10, text='Clear', command=get_lambda(clear_list_all, info.name))
                    list_clear.pack(side=LEFT, anchor=N, padx=3, pady=3)

                list_button_frame.pack(expand=False, side=TOP, padx=3, pady=3)

                # pack the frame
                search_frame.pack(expand=False, side=TOP, anchor=W, padx=3, pady=3)


            if 'tooltip' in info.gui_params:
                ToolTips.register(widgets[info.name], info.gui_params['tooltip'])


    # Pack the hierarchy
    frames['shuffle'].pack(fill=BOTH,  expand=True, anchor=N, side=RIGHT,  pady=(5,1))
    frames['open'].pack(   fill=BOTH,  expand=True, anchor=W, side=TOP,    pady=(5,1))
    frames['world'].pack(  fill=BOTH,  expand=True, anchor=W, side=BOTTOM, pady=(5,1))

    # Logic tab
    frames['checks'].pack(fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1))
    frames['tricks'].pack(fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1))

    # Other Tab
    frames['convenience'].pack(fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1))
    frames['other'].pack(      fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1))

    # Cosmetics tab
    frames['cosmetic'].pack(          fill=BOTH, expand=True, anchor=W, side=TOP)
    frames['cosmetic_tab_left'].pack( fill=BOTH, expand=True, anchor=W, side=LEFT)
    frames['cosmetic_tab_right'].pack(fill=BOTH, expand=True, anchor=W, side=RIGHT)

    # Cosmetics tab - Left Side
    frames['sword_trails'].pack(   fill=BOTH, expand=True, anchor=W, side=TOP)
    frames['ui_colors'].pack(      fill=BOTH, expand=True, anchor=W, side=BOTTOM)

    # Cosmetics tab - Right Side
    frames['tunic_colors'].pack(fill=BOTH, expand=True, anchor=N, side=TOP)
    frames['navi_colors'].pack( fill=BOTH, expand=True, anchor=W, side=TOP)
    frames['gauntlet_colors'].pack(fill=BOTH, expand=True, anchor=W, side=BOTTOM)


    #SFX tab
    frames['sfx'].pack(          fill=BOTH, expand=True, anchor=N, side=LEFT, pady=(5,1))
    frames['menu_sfx'].pack( fill=BOTH, expand=False, anchor=W, side=TOP, pady=(5,1))
    frames['npc_sfx'].pack(fill=BOTH, expand=True, anchor=W, side=BOTTOM, pady=(5,1))

    notebook.pack(fill=BOTH, expand=True, padx=5, pady=5)


    #Multi-World
    widgets['multiworld'] = LabelFrame(frames['rom_tab'], text='Multi-World Generation')
    countLabel = Label(
            widgets['multiworld'],
            wraplength=250,
            justify=LEFT,
            text='''This is used for co-op generations. \
                    Increasing Player Count will drastically \
                    increase the generation time. \
                    \nFor more information, see: \
                 '''
            )
    hyperLabel = Label(widgets['multiworld'], wraplength=250, justify=LEFT, text='https://github.com/TestRunnerSRL/\nbizhawk-co-op\n', fg='blue', cursor='hand2')
    hyperLabel.bind("<Button-1>", lambda event: webbrowser.open_new(r"https://github.com/TestRunnerSRL/bizhawk-co-op"))
    countLabel.pack(side=TOP, anchor=W, padx=5, pady=0)
    hyperLabel.pack(side=TOP, anchor=W, padx=5, pady=0)

    worldCountFrame = Frame(widgets['multiworld'])
    countLabel = Label(worldCountFrame, text='Player Count')
    guivars['world_count'] = StringVar()
    widgets['world_count'] = Spinbox(worldCountFrame, from_=1, to=255, textvariable=guivars['world_count'], width=3)
    guivars['world_count'].trace('w', show_settings)
    countLabel.pack(side=LEFT)
    widgets['world_count'].pack(side=LEFT, padx=2)
    worldCountFrame.pack(side=LEFT, anchor=N, padx=10, pady=(1,5))

    playerNumFrame = Frame(widgets['multiworld'])
    countLabel = Label(playerNumFrame, text='Player ID')
    guivars['player_num'] = StringVar()
    widgets['player_num'] = Spinbox(playerNumFrame, from_=1, to=255, textvariable=guivars['player_num'], width=3)
    countLabel.pack(side=LEFT)
    widgets['player_num'].pack(side=LEFT, padx=2)
    ToolTips.register(widgets['player_num'], 'Generate for specific Player.')
    playerNumFrame.pack(side=LEFT, anchor=N, padx=10, pady=(1,5))

    widgets['multiworld'].pack(side=LEFT, fill=BOTH, anchor=NW, padx=5, pady=5)


    # Settings Presets Functions
    def import_setting_preset():
        if guivars['settings_preset'].get() == '[New Preset]':
            messagebox.showerror("Invalid Preset", "You must select an existing preset!")
            return

        # Get cosmetic settings
        old_settings = guivars_to_settings(guivars)
        new_settings = {setting.name: old_settings.__dict__[setting.name] for setting in
                            filter(lambda s: not (s.shared and s.bitwidth > 0), setting_infos)}

        preset = presets[guivars['settings_preset'].get()]
        new_settings.update(preset)

        settings = Settings(new_settings)
        settings.seed = guivars['seed'].get()

        settings_to_guivars(settings, guivars)
        show_settings()


    def add_settings_preset():
        preset_name = guivars['settings_preset'].get()
        if preset_name == '[New Preset]':
            preset_name = simpledialog.askstring("New Preset", "Enter a new preset name:")
            if not preset_name or preset_name in presets or preset_name == '[New Preset]':
                messagebox.showerror("Invalid Preset", "You must enter a new preset name!")
                return
        elif presets[preset_name].get('locked', False):
            messagebox.showerror("Invalid Preset", "You cannot modify a locked preset!")
            return
        else:
            if messagebox.askquestion("Overwrite Preset", 'Are you sure you want to overwrite the "%s" preset?' % preset_name) != 'yes':
                return

        settings = guivars_to_settings(guivars)
        preset = {setting.name: settings.__dict__[setting.name] for setting in
            filter(lambda s: s.shared and s.bitwidth > 0, setting_infos)}

        presets[preset_name] = preset
        guivars['settings_preset'].set(preset_name)
        update_preset_dropdown()
        save_presets()


    def remove_setting_preset():
        preset_name = guivars['settings_preset'].get()
        if preset_name == '[New Preset]':
            messagebox.showerror("Invalid Preset", "You must select an existing preset!")
            return
        elif presets[preset_name].get('locked', False):
            messagebox.showerror("Invalid Preset", "You cannot modify a locked preset!")
            return

        confirm = messagebox.askquestion('Remove Setting Preset', 'Are you sure you want to remove the setting preset "%s"?' % preset_name)
        if confirm != 'yes':
            return

        del presets[preset_name]
        guivars['settings_preset'].set('[New Preset]')
        update_preset_dropdown()
        save_presets()


    def update_preset_dropdown():
        widgets['settings_preset']['values'] = ['[New Preset]'] + list(presets.keys())


    def save_presets():
        presets_file = local_path('presets.sav')
        with open(presets_file, 'w') as outfile:
            preset_json = {name: preset for name,preset in presets.items() if not preset.get('locked')}
            json.dump(preset_json, outfile, indent=4)


    # Settings Presets
    widgets['settings_presets'] = LabelFrame(frames['rom_tab'], text='Settings Presets')
    countLabel = Label(
            widgets['settings_presets'],
            wraplength=250,
            justify=LEFT,
            text='''Presets are settings that can be saved\
                    and loaded from. Loading a preset\
                    will overwrite all settings that affect\
                    the seed.\
                    \n\
                 '''
            )
    countLabel.pack(side=TOP, anchor=W, padx=5, pady=0)

    selectPresetFrame = Frame(widgets['settings_presets'])
    guivars['settings_preset'] = StringVar(value='[New Preset]')
    widgets['settings_preset'] = ttk.Combobox(selectPresetFrame, textvariable=guivars['settings_preset'], values=['[New Preset]'], state='readonly', width=33)
    widgets['settings_preset'].pack(side=BOTTOM, anchor=W)
    ToolTips.register(widgets['settings_preset'], 'Select a setting preset to apply.')
    widgets['settings_preset'].pack(side=LEFT, padx=(5, 0))
    selectPresetFrame.pack(side=TOP, anchor=W, padx=5, pady=(1,5))

    buttonPresetFrame = Frame(widgets['settings_presets'])
    importPresetButton = Button(buttonPresetFrame, text='Load', width=9, command=import_setting_preset)
    addPresetButton = Button(buttonPresetFrame, text='Save', width=9, command=add_settings_preset)
    removePresetButton = Button(buttonPresetFrame, text='Remove', width=9, command=remove_setting_preset)
    importPresetButton.pack(side=LEFT, anchor=W, padx=2)
    addPresetButton.pack(side=LEFT, anchor=W, padx=2)
    removePresetButton.pack(side=LEFT, anchor=W, padx=2)
    buttonPresetFrame.pack(side=TOP, anchor=W, padx=5, pady=(1,5))

    widgets['settings_presets'].pack(side=RIGHT, fill=BOTH, anchor=NW, padx=5, pady=5)


    # Create the generation menu
    def update_generation_type(event=None):
        settings = guivars_to_settings(guivars)
        if generation_notebook.tab(generation_notebook.select())['text'] == 'Generate From Seed':
            notebook.tab(1, state="normal")
            if guivars['logic_rules'].get() == 'Glitchless':
                notebook.tab(2, state="normal")
            else:
                notebook.tab(2, state="disabled")
            notebook.tab(3, state="normal")
            notebook.tab(4, state="normal")
            notebook.tab(5, state="normal")
            toggle_widget(widgets['world_count'], settings.check_dependency('world_count'))
            toggle_widget(widgets['create_spoiler'], settings.check_dependency('create_spoiler'))
            toggle_widget(widgets['count'], settings.check_dependency('count'))
            toggle_widget(widgets['settings_presets'], True)
        else:
            notebook.tab(1, state="disabled")
            notebook.tab(2, state="disabled")
            notebook.tab(3, state="disabled")
            if guivars['repatch_cosmetics'].get():
                notebook.tab(4, state="normal")
                notebook.tab(5, state="normal")
                toggle_widget(widgets['create_cosmetics_log'], settings.check_dependency('create_cosmetics_log'))
            else:
                notebook.tab(4, state="disabled")
                notebook.tab(5, state="disabled")
                toggle_widget(widgets['create_cosmetics_log'], False)
            toggle_widget(widgets['world_count'], False)
            toggle_widget(widgets['create_spoiler'], False)
            toggle_widget(widgets['count'], False)
            toggle_widget(widgets['settings_presets'], False)



    generation_notebook = ttk.Notebook(mainWindow)
    frames['gen_from_seed'] = ttk.Frame(generation_notebook)
    frames['gen_from_file'] = ttk.Frame(generation_notebook)
    generation_notebook.add(frames['gen_from_seed'], text='Generate From Seed')
    generation_notebook.add(frames['gen_from_file'], text='Generate From File')
    generation_notebook.bind("<<NotebookTabChanged>>", show_settings)

    # From seed tab
    def import_settings(event=None):
        try:
            settings = guivars_to_settings(guivars)
            text = settings_string_var.get().upper()
            settings.seed = guivars['seed'].get()
            settings.update_with_settings_string(text)
            settings_to_guivars(settings, guivars)
            show_settings()
        except Exception as e:
            messagebox.showerror(title="Error", message="Invalid settings string")

    def copy_settings(event=None):
        mainWindow.clipboard_clear()
        new_clip = settings_string_var.get().upper()
        mainWindow.clipboard_append(new_clip)
        mainWindow.update()

    settingsFrame = Frame(frames['gen_from_seed'])
    settings_string_var = StringVar()
    widgets['setting_string'] = Entry(settingsFrame, textvariable=settings_string_var, width=44)

    label = Label(settingsFrame, text="Settings String", width=13, anchor=E)
    widgets['copy_settings'] = Button(settingsFrame, text='Copy', width=5, command=copy_settings)
    widgets['import_settings'] = Button(settingsFrame, text='Import', width=7, command=import_settings)
    label.pack(side=LEFT, anchor=W, padx=5)
    widgets['setting_string'].pack(side=LEFT, anchor=W)
    widgets['copy_settings'].pack(side=LEFT, anchor=W, padx=(5, 0))
    widgets['import_settings'].pack(side=LEFT, anchor=W)

    settingsFrame.pack(fill=BOTH, anchor=W, padx=5, pady=(10,0))

    def multiple_run(settings, window):
        orig_seed = settings.seed
        for i in range(settings.count):
            settings.update_seed(orig_seed + '-' + str(i))
            window.update_title("Generating Seed %s...%d/%d" % (settings.seed, i+1, settings.count))
            main(settings, window)

    def generateRom():
        settings = guivars_to_settings(guivars)
        if settings.count:
            BackgroundTaskProgress(mainWindow, "Generating Seed %s..." % settings.seed, multiple_run, settings)
        else:
            BackgroundTaskProgress(mainWindow, "Generating Seed %s..." % settings.seed, main, settings)

    generateSeedFrame = Frame(frames['gen_from_seed'])
    seedLabel = Label(generateSeedFrame, text='Seed', width=13, anchor=E)
    generateButton = Button(generateSeedFrame, text='Generate!', width=14, command=generateRom)
    guivars['seed'] = StringVar()
    widgets['seed'] = Entry(generateSeedFrame, textvariable=guivars['seed'], width=44)
    seedLabel.pack(side=LEFT, padx=5)
    widgets['seed'].pack(side=LEFT)
    generateButton.pack(side=LEFT, padx=(5, 0))

    generateSeedFrame.pack(side=BOTTOM, anchor=W, padx=5, pady=10)

    # From file tab
    patchDialogFrame = Frame(frames['gen_from_file'])

    patchFileLabel = Label(patchDialogFrame, text='Patch File')
    guivars['patch_file'] = StringVar(value='')
    patchEntry = Entry(patchDialogFrame, textvariable=guivars['patch_file'], width=52)

    def PatchSelect():
        patch_file = filedialog.askopenfilename(filetypes=[("Patch File Archive", "*.zpfz *.zpf"), ("All Files", "*")])
        if patch_file != '':
            guivars['patch_file'].set(patch_file)
    patchSelectButton = Button(patchDialogFrame, text='Select File', command=PatchSelect, width=14)

    patchFileLabel.pack(side=LEFT, padx=(5,0))
    patchEntry.pack(side=LEFT, padx=3)
    patchSelectButton.pack(side=LEFT)

    patchDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(10,5))

    def generateFromFile():
        settings = guivars_to_settings(guivars)
        BackgroundTaskProgress(mainWindow, "Generating From File %s..." % os.path.basename(settings.patch_file), from_patch_file, settings)

    patchCosmeticsAndGenerateFrame = Frame(frames['gen_from_file'])
    guivars['repatch_cosmetics'] = IntVar()
    widgets['repatch_cosmetics'] = Checkbutton(patchCosmeticsAndGenerateFrame, text='Update Cosmetics', variable=guivars['repatch_cosmetics'], justify=LEFT, wraplength=220, command=show_settings)
    widgets['repatch_cosmetics'].pack(side=LEFT, padx=5, anchor=W)

    generateFileButton = Button(patchCosmeticsAndGenerateFrame, text='Generate!', width=14, command=generateFromFile)
    generateFileButton.pack(side=RIGHT, anchor=E)
    patchCosmeticsAndGenerateFrame.pack(side=BOTTOM, fill=BOTH, expand=True, pady=(0,10), padx=(0, 10))

    generation_notebook.pack(fill=BOTH, expand=True, padx=5, pady=5)


    guivars['checked_version'] = StringVar()
    guivars['cosmetics_only'] = IntVar()

    if settings is not None:
        # Load values from commandline args
        settings_to_guivars(settings, guivars)
    else:
        # Try to load saved settings
        settingsFile = local_path('settings.sav')
        try:
            with open(settingsFile) as f:
                settings = Settings( json.load(f) )
        except:
            settings = Settings({})
        settings_to_guivars(settings, guivars)
        guivars['seed'].set("")

        presets = {}
        for file in [data_path('presets_default.json')] \
                  + [local_path(f) for f in os.listdir(local_path()) if f.startswith('presets_') and f.endswith('.sav')] \
                  + [local_path('presets.sav')]:
            try:
                with open(file) as f:
                    presets_temp = json.load(f)
                    if file != local_path('presets.sav'):
                        for preset in presets_temp.values():
                            preset['locked'] = True
                    presets.update(presets_temp)
            except:
                pass
        update_preset_dropdown()

    show_settings()

    def gui_check_version():
        task = BackgroundTask(mainWindow, check_version, guivars['checked_version'].get())
        while task.running:
            mainWindow.update()

        if task.status:
            versionCheckLabel = LabelFrame(versionCheckFrame, text="New Version Available!")
            versionCheckText = Label(versionCheckLabel, justify=LEFT, text=task.status[(task.status.find(' ')+1):])
            versionCheckLink = Label(versionCheckLabel, justify=LEFT, text='Click here and download the current version.', fg='blue', cursor='hand2')
            versionCheckLink.bind("<Button-1>", lambda event: webbrowser.open_new(r"https://github.com/TestRunnerSRL/OoT-Randomizer/tree/Dev"))
            versionCheckText.pack(anchor=NW, padx=5, pady=0)
            versionCheckLink.pack(anchor=NW, padx=5, pady=0)
            versionCheckLabel.pack(anchor=NW, fill=X, expand="yes", padx=5, pady=5)

    mainWindow.after(1000, gui_check_version)
    mainWindow.mainloop()

    # Save settings on close
    settings_file = local_path('settings.sav')
    with open(settings_file, 'w') as outfile:
        settings = guivars_to_settings(guivars)
        del settings.__dict__["distribution"]
        del settings.__dict__["seed"]
        del settings.__dict__["numeric_seed"]
        del settings.__dict__["check_version"]
        if "locked" in settings.__dict__:
            del settings.__dict__["locked"]
        json.dump(settings.__dict__, outfile, indent=4)
    
    save_presets()
Exemplo n.º 5
0
def guiMain(args=None):
    mainWindow = Tk()
    mainWindow.wm_title("OoT Randomizer %s" % ESVersion)

    set_icon(mainWindow)

    notebook = ttk.Notebook(mainWindow)
    randomizerWindow = ttk.Frame(notebook)
    adjustWindow = ttk.Frame(notebook)
    customWindow = ttk.Frame(notebook)
    notebook.add(randomizerWindow, text='Randomize')
    notebook.pack()

    # Shared Controls

    farBottomFrame = Frame(mainWindow)

    def open_output():
        open_file(output_path(''))

    openOutputButton = Button(farBottomFrame,
                              text='Open Output Directory',
                              command=open_output)

    if os.path.exists(local_path('README.html')):

        def open_readme():
            open_file(local_path('README.html'))

        openReadmeButton = Button(farBottomFrame,
                                  text='Open Documentation',
                                  command=open_readme)
        openReadmeButton.pack(side=LEFT)

    farBottomFrame.pack(side=BOTTOM, fill=X, padx=5, pady=5)

    # randomizer controls

    topFrame = Frame(randomizerWindow)
    rightHalfFrame = Frame(topFrame)
    checkBoxFrame = Frame(rightHalfFrame)

    createSpoilerVar = IntVar()
    createSpoilerCheckbutton = Checkbutton(
        checkBoxFrame,
        text="Create Spoiler Log (affects item layout)",
        variable=createSpoilerVar)
    suppressRomVar = IntVar()
    suppressRomCheckbutton = Checkbutton(checkBoxFrame,
                                         text="Do not create patched Rom",
                                         variable=suppressRomVar)
    compressRomVar = IntVar()
    compressRomCheckbutton = Checkbutton(checkBoxFrame,
                                         text="Compress patched Rom",
                                         variable=compressRomVar)
    openForestVar = IntVar()
    openForestCheckbutton = Checkbutton(checkBoxFrame,
                                        text="Open Forest",
                                        variable=openForestVar)
    openDoorVar = IntVar()
    openDoorCheckbutton = Checkbutton(checkBoxFrame,
                                      text="Open Door of Time",
                                      variable=openDoorVar)
    fastGanonVar = IntVar()
    fastGanonCheckbutton = Checkbutton(checkBoxFrame,
                                       text="Skip most of Ganon's Castle",
                                       variable=fastGanonVar)
    dungeonItemsVar = IntVar()
    dungeonItemsCheckbutton = Checkbutton(
        checkBoxFrame,
        text="Place Dungeon Items (Compasses/Maps)",
        onvalue=0,
        offvalue=1,
        variable=dungeonItemsVar)
    beatableOnlyVar = IntVar()
    beatableOnlyCheckbutton = Checkbutton(
        checkBoxFrame,
        text="Only ensure seed is beatable, not all items must be reachable",
        variable=beatableOnlyVar)
    hintsVar = IntVar()
    hintsCheckbutton = Checkbutton(
        checkBoxFrame,
        text="Gossip Stone Hints with Stone of Agony",
        variable=hintsVar)

    createSpoilerCheckbutton.pack(expand=True, anchor=W)
    suppressRomCheckbutton.pack(expand=True, anchor=W)
    compressRomCheckbutton.pack(expand=True, anchor=W)
    openForestCheckbutton.pack(expand=True, anchor=W)
    openDoorCheckbutton.pack(expand=True, anchor=W)
    fastGanonCheckbutton.pack(expand=True, anchor=W)
    dungeonItemsCheckbutton.pack(expand=True, anchor=W)
    beatableOnlyCheckbutton.pack(expand=True, anchor=W)
    hintsCheckbutton.pack(expand=True, anchor=W)

    fileDialogFrame = Frame(rightHalfFrame)

    romDialogFrame = Frame(fileDialogFrame)
    baseRomLabel = Label(romDialogFrame, text='Base Rom')
    romVar = StringVar()
    romEntry = Entry(romDialogFrame, textvariable=romVar)

    def RomSelect():
        rom = filedialog.askopenfilename(
            filetypes=[("Rom Files", (".z64", ".n64")), ("All Files", "*")])
        romVar.set(rom)

    romSelectButton = Button(romDialogFrame,
                             text='Select Rom',
                             command=RomSelect)

    baseRomLabel.pack(side=LEFT)
    romEntry.pack(side=LEFT)
    romSelectButton.pack(side=LEFT)

    romDialogFrame.pack()

    checkBoxFrame.pack()
    fileDialogFrame.pack()

    dropDownFrame = Frame(topFrame)

    bridgeFrame = Frame(dropDownFrame)
    bridgeVar = StringVar()
    bridgeVar.set('medallions')
    bridgeOptionMenu = OptionMenu(bridgeFrame, bridgeVar, 'medallions',
                                  'vanilla', 'dungeons', 'open')
    bridgeOptionMenu.pack(side=RIGHT)
    bridgeLabel = Label(bridgeFrame, text='Rainbow Bridge Requirement')
    bridgeLabel.pack(side=LEFT)

    colorVars = []
    colorVars.append(StringVar())
    colorVars.append(StringVar())
    colorVars.append(StringVar())
    colorVars[0].set('Kokiri Green')
    colorVars[1].set('Goron Red')
    colorVars[2].set('Zora Blue')

    kokiriFrame = Frame(dropDownFrame)
    kokiriOptionMenu = OptionMenu(kokiriFrame, colorVars[0], 'Kokiri Green',
                                  'Goron Red', 'Zora Blue', 'Black', 'White',
                                  'Purple', 'Yellow', 'Orange', 'Pink', 'Gray',
                                  'Brown', 'Gold', 'Silver', 'Beige', 'Teal',
                                  'Royal Blue', 'Sonic Blue', 'Blood Red',
                                  'Blood Orange', 'NES Green', 'Dark Green',
                                  'Random', 'True Random')
    kokiriOptionMenu.pack(side=RIGHT)
    kokiriLabel = Label(kokiriFrame, text='Kokiri Tunic Color')
    kokiriLabel.pack(side=LEFT)

    goronFrame = Frame(dropDownFrame)
    goronOptionMenu = OptionMenu(goronFrame, colorVars[1], 'Kokiri Green',
                                 'Goron Red', 'Zora Blue', 'Black', 'White',
                                 'Purple', 'Yellow', 'Orange', 'Pink', 'Gray',
                                 'Brown', 'Gold', 'Silver', 'Beige', 'Teal',
                                 'Royal Blue', 'Sonic Blue', 'Blood Red',
                                 'Blood Orange', 'NES Green', 'Dark Green',
                                 'Random', 'True Random')
    goronOptionMenu.pack(side=RIGHT)
    goronLabel = Label(goronFrame, text='Goron Tunic Color')
    goronLabel.pack(side=LEFT)

    zoraFrame = Frame(dropDownFrame)
    zoraOptionMenu = OptionMenu(zoraFrame, colorVars[2], 'Kokiri Green',
                                'Goron Red', 'Zora Blue', 'Black', 'White',
                                'Purple', 'Yellow', 'Orange', 'Pink', 'Gray',
                                'Brown', 'Gold', 'Silver', 'Beige', 'Teal',
                                'Royal Blue', 'Sonic Blue', 'Blood Red',
                                'Blood Orange', 'NES Green', 'Dark Green',
                                'Random', 'True Random')
    zoraOptionMenu.pack(side=RIGHT)
    zoraLabel = Label(zoraFrame, text='Zora Tunic Color')
    zoraLabel.pack(side=LEFT)

    lowHealthSFXVar = StringVar()
    lowHealthSFXVar.set('Default')

    lowHealthSFXFrame = Frame(dropDownFrame)
    lowHealthSFXOptionMenu = OptionMenu(lowHealthSFXFrame, lowHealthSFXVar,
                                        'Default', 'Softer Beep', 'Rupee',
                                        'Timer', 'Tamborine', 'Recovery Heart',
                                        'Carrot Refill', 'Navi - Hey!',
                                        'Zelda - Gasp', 'Cluck', 'Mweep!',
                                        'Random', 'None')
    lowHealthSFXOptionMenu.pack(side=RIGHT)
    lowHealthSFXLabel = Label(lowHealthSFXFrame, text='Low Health SFX')
    lowHealthSFXLabel.pack(side=LEFT)

    bridgeFrame.pack(expand=True, anchor=E)
    kokiriFrame.pack(expand=True, anchor=E)
    goronFrame.pack(expand=True, anchor=E)
    zoraFrame.pack(expand=True, anchor=E)
    lowHealthSFXFrame.pack(expand=True, anchor=E)

    bottomFrame = Frame(randomizerWindow)

    seedLabel = Label(bottomFrame, text='Seed #')
    seedVar = StringVar()
    seedEntry = Entry(bottomFrame, textvariable=seedVar)
    countLabel = Label(bottomFrame, text='Count')
    countVar = StringVar()
    countSpinbox = Spinbox(bottomFrame, from_=1, to=100, textvariable=countVar)

    def generateRom():
        guiargs = Namespace
        guiargs.seed = int(seedVar.get()) if seedVar.get() else None
        guiargs.count = int(countVar.get()) if countVar.get() != '1' else None
        guiargs.bridge = bridgeVar.get()
        guiargs.kokiricolor = colorVars[0].get()
        guiargs.goroncolor = colorVars[1].get()
        guiargs.zoracolor = colorVars[2].get()
        guiargs.healthSFX = lowHealthSFXVar.get()
        guiargs.create_spoiler = bool(createSpoilerVar.get())
        guiargs.suppress_rom = bool(suppressRomVar.get())
        guiargs.compress_rom = bool(compressRomVar.get())
        guiargs.open_forest = bool(openForestVar.get())
        guiargs.open_door_of_time = bool(openDoorVar.get())
        guiargs.fast_ganon = bool(fastGanonVar.get())
        guiargs.nodungeonitems = bool(dungeonItemsVar.get())
        guiargs.beatableonly = bool(beatableOnlyVar.get())
        guiargs.hints = bool(hintsVar.get())
        guiargs.rom = romVar.get()
        try:
            if guiargs.count is not None:
                seed = guiargs.seed
                for _ in range(guiargs.count):
                    main(seed=seed, args=guiargs)
                    seed = random.randint(0, 999999999)
            else:
                main(seed=guiargs.seed, args=guiargs)
        except Exception as e:
            messagebox.showerror(title="Error while creating seed",
                                 message=str(e))
        else:
            messagebox.showinfo(title="Success",
                                message="Rom patched successfully")

    generateButton = Button(bottomFrame,
                            text='Generate Patched Rom',
                            command=generateRom)

    seedLabel.pack(side=LEFT)
    seedEntry.pack(side=LEFT)
    countLabel.pack(side=LEFT, padx=(5, 0))
    countSpinbox.pack(side=LEFT)
    generateButton.pack(side=LEFT, padx=(5, 0))

    openOutputButton.pack(side=RIGHT)

    dropDownFrame.pack(side=LEFT)
    rightHalfFrame.pack(side=RIGHT)
    topFrame.pack(side=TOP)
    bottomFrame.pack(side=BOTTOM)

    if args is not None:
        # load values from commandline args
        createSpoilerVar.set(int(args.create_spoiler))
        suppressRomVar.set(int(args.suppress_rom))
        compressRomVar.set(int(args.compress_rom))
        if args.nodungeonitems:
            dungeonItemsVar.set(int(not args.nodungeonitems))
        openForestVar.set(int(args.open_forest))
        openDoorVar.set(int(args.open_door_of_time))
        fastGanonVar.set(int(args.fast_ganon))
        beatableOnlyVar.set(int(args.beatableonly))
        hintsVar.set(int(args.hints))
        if args.count:
            countVar.set(str(args.count))
        if args.seed:
            seedVar.set(str(args.seed))
        bridgeVar.set(args.bridge)
        colorVars[0].set(args.kokiricolor)
        colorVars[1].set(args.goroncolor)
        colorVars[2].set(args.zoracolor)
        lowHealthSFXVar.set(args.healthSFX)
        romVar.set(args.rom)

    mainWindow.mainloop()
Exemplo n.º 6
0
def guiMain(settings=None):
    frames = {}

    mainWindow = Tk()
    mainWindow.wm_title("OoT Randomizer %s" % ESVersion)
    mainWindow.resizable(False, False)

    set_icon(mainWindow)

    notebook = ttk.Notebook(mainWindow)
    frames['rom_tab'] = ttk.Frame(notebook)
    frames['rules_tab'] = ttk.Frame(notebook)
    frames['logic_tab'] = ttk.Frame(notebook)
    frames['other_tab'] = ttk.Frame(notebook)
    frames['aesthetic_tab'] = ttk.Frame(notebook)
    frames['aesthetic_tab_left'] = Frame(frames['aesthetic_tab'])
    frames['aesthetic_tab_right'] = Frame(frames['aesthetic_tab'])
    adjustWindow = ttk.Frame(notebook)
    customWindow = ttk.Frame(notebook)
    notebook.add(frames['rom_tab'], text='ROM Options')
    notebook.add(frames['rules_tab'], text='Main Rules')
    notebook.add(frames['logic_tab'], text='Detailed Logic')
    notebook.add(frames['other_tab'], text='Other')
    notebook.add(frames['aesthetic_tab'], text='Cosmetics')

    #######################
    # randomizer controls #
    #######################

    # hold the results of the user's decisions here
    guivars = {}

    # hierarchy
    ############

    #Rules Tab
    frames['open'] = LabelFrame(frames['rules_tab'],
                                text='Open',
                                labelanchor=NW)
    frames['world'] = LabelFrame(frames['rules_tab'],
                                 text='World',
                                 labelanchor=NW)
    frames['logic'] = LabelFrame(frames['rules_tab'],
                                 text='Shuffle',
                                 labelanchor=NW)

    # Logic tab
    frames['rewards'] = LabelFrame(frames['logic_tab'],
                                   text='Remove Specific Locations',
                                   labelanchor=NW)
    frames['tricks'] = LabelFrame(frames['logic_tab'],
                                  text='Specific expected tricks',
                                  labelanchor=NW)

    #Other Tab
    frames['convenience'] = LabelFrame(frames['other_tab'],
                                       text='Speed Ups',
                                       labelanchor=NW)
    frames['other'] = LabelFrame(frames['other_tab'],
                                 text='Misc',
                                 labelanchor=NW)

    #Aesthetics tab
    frames['cosmetics'] = LabelFrame(frames['aesthetic_tab'],
                                     text='General',
                                     labelanchor=NW)
    frames['tuniccolor'] = LabelFrame(frames['aesthetic_tab_left'],
                                      text='Tunic Color',
                                      labelanchor=NW)
    frames['navicolor'] = LabelFrame(frames['aesthetic_tab_right'],
                                     text='Navi Color',
                                     labelanchor=NW)
    frames['lowhp'] = LabelFrame(frames['aesthetic_tab_left'],
                                 text='Low HP SFX',
                                 labelanchor=NW)
    frames['navihint'] = LabelFrame(frames['aesthetic_tab_right'],
                                    text='Navi SFX',
                                    labelanchor=NW)

    # shared
    settingsFrame = Frame(mainWindow)
    settings_string_var = StringVar()
    settingsEntry = Entry(settingsFrame,
                          textvariable=settings_string_var,
                          width=25)

    def show_settings(event=None):
        settings = guivars_to_settings(guivars)
        settings_string_var.set(settings.get_settings_string())

        # Update any dependencies
        for info in setting_infos:
            if info.gui_params and 'dependency' in info.gui_params:
                dep_met = info.gui_params['dependency'](guivars)

                if widgets[info.name].winfo_class() == 'Frame':
                    for child in widgets[info.name].winfo_children():
                        if child.winfo_class() == 'TCombobox':
                            child.configure(
                                state='readonly' if dep_met else 'disabled')
                        else:
                            child.configure(
                                state='normal' if dep_met else 'disabled')

                        if child.winfo_class() == 'Scale':
                            child.configure(fg='Black' if dep_met else 'Grey')
                else:
                    if widgets[info.name].winfo_class() == 'TCombobox':
                        widgets[info.name].configure(
                            state='readonly' if dep_met else 'disabled')
                    else:
                        widgets[info.name].configure(
                            state='normal' if dep_met else 'disabled')

                    if widgets[info.name].winfo_class() == 'Scale':
                        widgets[info.name].configure(
                            fg='Black' if dep_met else 'Grey')

            if info.name in guivars and guivars[
                    info.name].get() == 'Custom Color':
                color = askcolor()
                if color == (None, None):
                    color = ((0, 0, 0), '#000000')
                guivars[info.name].set('Custom (' + color[1] + ')')

    def show_settings_special(event=None):
        if guivars['logic_tricks'].get():
            widgets['logic_man_on_roof'].select()
            widgets['logic_child_deadhand'].select()
            widgets['logic_dc_jump'].select()
            widgets['logic_windmill_poh'].select()
            widgets['logic_crater_bean_poh_with_hovers'].select()
            widgets['logic_zora_with_cucco'].select()
            widgets['logic_fewer_tunic_requirements'].select()
        else:
            widgets['logic_man_on_roof'].deselect()
            widgets['logic_child_deadhand'].deselect()
            widgets['logic_dc_jump'].deselect()
            widgets['logic_windmill_poh'].deselect()
            widgets['logic_crater_bean_poh_with_hovers'].deselect()
            widgets['logic_zora_with_cucco'].deselect()
            widgets['logic_fewer_tunic_requirements'].deselect()
        settings = guivars_to_settings(guivars)
        settings_string_var.set(settings.get_settings_string())

    def import_settings(event=None):
        try:
            settings = guivars_to_settings(guivars)
            text = settings_string_var.get().upper()
            settings.seed = guivars['seed'].get()
            settings.update_with_settings_string(text)
            settings_to_guivars(settings, guivars)
        except Exception as e:
            messagebox.showerror(title="Error",
                                 message="Invalid settings string")

    label = Label(settingsFrame, text="Settings String")
    importSettingsButton = Button(settingsFrame,
                                  text='Import Settings String',
                                  command=import_settings)
    label.pack(side=LEFT, anchor=W, padx=5)
    settingsEntry.pack(side=LEFT, anchor=W)
    importSettingsButton.pack(side=LEFT, anchor=W, padx=5)

    fileDialogFrame = Frame(frames['rom_tab'])

    romDialogFrame = Frame(fileDialogFrame)
    baseRomLabel = Label(romDialogFrame, text='Base ROM')
    guivars['rom'] = StringVar(value='ZOOTDEC.z64')
    romEntry = Entry(romDialogFrame, textvariable=guivars['rom'], width=40)

    def RomSelect():
        rom = filedialog.askopenfilename(
            filetypes=[("ROM Files", (".z64", ".n64")), ("All Files", "*")])
        if rom != '':
            guivars['rom'].set(rom)

    romSelectButton = Button(romDialogFrame,
                             text='Select ROM',
                             command=RomSelect,
                             width=10)

    baseRomLabel.pack(side=LEFT, padx=(38, 0))
    romEntry.pack(side=LEFT, padx=3)
    romSelectButton.pack(side=LEFT)

    romDialogFrame.pack()

    fileDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(5, 1))

    def open_output():
        open_file(output_path(''))

    def output_dir_select():
        rom = filedialog.askdirectory(
            initialdir=default_output_path(guivars['output_dir'].get()))
        if rom != '':
            guivars['output_dir'].set(rom)

    outputDialogFrame = Frame(frames['rom_tab'])
    outputDirLabel = Label(outputDialogFrame, text='Output Directory')
    guivars['output_dir'] = StringVar(value='')
    outputDirEntry = Entry(outputDialogFrame,
                           textvariable=guivars['output_dir'],
                           width=40)
    outputDirButton = Button(outputDialogFrame,
                             text='Select Dir',
                             command=output_dir_select,
                             width=10)
    outputDirLabel.pack(side=LEFT, padx=(3, 0))
    outputDirEntry.pack(side=LEFT, padx=3)
    outputDirButton.pack(side=LEFT)
    outputDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(5, 1))

    if os.path.exists(local_path('README.html')):

        def open_readme():
            open_file(local_path('README.html'))

        openReadmeButton = Button(outputDialogFrame,
                                  text='Open Documentation',
                                  command=open_readme)
        openReadmeButton.pack(side=LEFT, padx=5)

    outputDialogFrame.pack(side=TOP, anchor=W, pady=3)

    countDialogFrame = Frame(frames['rom_tab'])
    countLabel = Label(countDialogFrame, text='Generation Count')
    guivars['count'] = StringVar()
    countSpinbox = Spinbox(countDialogFrame,
                           from_=1,
                           to=100,
                           textvariable=guivars['count'],
                           width=3)

    countLabel.pack(side=LEFT)
    countSpinbox.pack(side=LEFT, padx=2)
    countDialogFrame.pack(side=TOP, anchor=W, padx=5, pady=(1, 1))

    # build gui
    ############

    widgets = {}

    for info in setting_infos:
        if info.gui_params:
            if info.gui_params['widget'] == 'Checkbutton':
                # determine the initial value of the checkbox
                default_value = 1 if info.gui_params[
                    'default'] == "checked" else 0
                # create a variable to access the box's state
                guivars[info.name] = IntVar(value=default_value)
                # create the checkbox
                widgets[info.name] = Checkbutton(
                    frames[info.gui_params['group']],
                    text=info.gui_params['text'],
                    variable=guivars[info.name],
                    justify=LEFT,
                    wraplength=190,
                    command=show_settings)
                widgets[info.name].pack(expand=False, anchor=W)
            if info.gui_params['widget'] == 'SpecialCheckbutton':
                # determine the initial value of the checkbox
                default_value = 1 if info.gui_params[
                    'default'] == "checked" else 0
                # create a variable to access the box's state
                guivars[info.name] = IntVar(value=default_value)
                # create the checkbox
                widgets[info.name] = Checkbutton(
                    frames[info.gui_params['group']],
                    text=info.gui_params['text'],
                    variable=guivars[info.name],
                    justify=LEFT,
                    wraplength=190,
                    command=show_settings_special)
                widgets[info.name].pack(expand=False, anchor=W)
            elif info.gui_params['widget'] == 'Combobox':
                # create the variable to store the user's decision
                guivars[info.name] = StringVar(
                    value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])
                # dropdown = OptionMenu(widgets[info.name], guivars[info.name], *(info['options']))
                if isinstance(info.gui_params['options'], list):
                    info.gui_params['options'] = dict(
                        zip(info.gui_params['options'],
                            info.gui_params['options']))
                dropdown = ttk.Combobox(widgets[info.name],
                                        textvariable=guivars[info.name],
                                        values=list(
                                            info.gui_params['options'].keys()),
                                        state='readonly',
                                        width=30)
                dropdown.bind("<<ComboboxSelected>>", show_settings)
                dropdown.pack(side=BOTTOM, anchor=W)
                # label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name],
                                  text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # pack the frame
                widgets[info.name].pack(expand=False,
                                        side=TOP,
                                        anchor=W,
                                        padx=3,
                                        pady=3)
            elif info.gui_params['widget'] == 'Radiobutton':
                # create the variable to store the user's decision
                guivars[info.name] = StringVar(
                    value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = LabelFrame(
                    frames[info.gui_params['group']],
                    text=info.gui_params['text']
                    if 'text' in info.gui_params else info["name"],
                    labelanchor=NW)
                if isinstance(info.gui_params['options'], list):
                    info.gui_params['options'] = dict(
                        zip(info.gui_params['options'],
                            info.gui_params['options']))
                # setup orientation
                side = TOP
                anchor = W
                if "horizontal" in info.gui_params and info.gui_params[
                        "horizontal"]:
                    side = LEFT
                    anchor = N
                # add the radio buttons
                for option in info.gui_params["options"]:
                    radio_button = Radiobutton(widgets[info.name],
                                               text=option,
                                               value=option,
                                               variable=guivars[info.name],
                                               justify=LEFT,
                                               wraplength=190,
                                               indicatoron=False,
                                               command=show_settings)
                    radio_button.pack(expand=True, side=side, anchor=anchor)
                # pack the frame
                widgets[info.name].pack(expand=False,
                                        side=TOP,
                                        anchor=W,
                                        padx=3,
                                        pady=3)
            elif info.gui_params['widget'] == 'Scale':
                # create the variable to store the user's decision
                guivars[info.name] = IntVar(value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])
                # dropdown = OptionMenu(widgets[info.name], guivars[info.name], *(info['options']))
                minval = 'min' in info.gui_params and info.gui_params[
                    'min'] or 0
                maxval = 'max' in info.gui_params and info.gui_params[
                    'max'] or 100
                stepval = 'step' in info.gui_params and info.gui_params[
                    'step'] or 1
                scale = Scale(widgets[info.name],
                              variable=guivars[info.name],
                              from_=minval,
                              to=maxval,
                              tickinterval=stepval,
                              resolution=stepval,
                              showvalue=0,
                              orient=HORIZONTAL,
                              sliderlength=15,
                              length=200,
                              command=show_settings)
                scale.pack(side=BOTTOM, anchor=W)
                # label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name],
                                  text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # pack the frame
                widgets[info.name].pack(expand=False,
                                        side=TOP,
                                        anchor=W,
                                        padx=3,
                                        pady=3)
            elif info.gui_params['widget'] == 'Entry':
                # create the variable to store the user's decision
                guivars[info.name] = StringVar(
                    value=info.gui_params['default'])
                # create the option menu
                widgets[info.name] = Frame(frames[info.gui_params['group']])

                entry = Entry(widgets[info.name],
                              textvariable=guivars[info.name],
                              width=30)
                entry.pack(side=BOTTOM, anchor=W)
                # label the option
                if 'text' in info.gui_params:
                    label = Label(widgets[info.name],
                                  text=info.gui_params['text'])
                    label.pack(side=LEFT, anchor=W, padx=5)
                # pack the frame
                widgets[info.name].pack(expand=False,
                                        side=TOP,
                                        anchor=W,
                                        padx=3,
                                        pady=3)

            if 'tooltip' in info.gui_params:
                ToolTips.register(widgets[info.name],
                                  info.gui_params['tooltip'])

    # pack the hierarchy

    frames['logic'].pack(fill=BOTH,
                         expand=True,
                         anchor=N,
                         side=RIGHT,
                         pady=(5, 1))
    frames['open'].pack(fill=BOTH,
                        expand=True,
                        anchor=W,
                        side=TOP,
                        pady=(5, 1))
    frames['world'].pack(fill=BOTH,
                         expand=True,
                         anchor=W,
                         side=BOTTOM,
                         pady=(5, 1))

    # Logic tab
    frames['rewards'].pack(fill=BOTH,
                           expand=True,
                           anchor=N,
                           side=LEFT,
                           pady=(5, 1))
    frames['tricks'].pack(fill=BOTH,
                          expand=True,
                          anchor=N,
                          side=LEFT,
                          pady=(5, 1))

    #Other Tab
    frames['convenience'].pack(fill=BOTH,
                               expand=True,
                               anchor=N,
                               side=LEFT,
                               pady=(5, 1))
    frames['other'].pack(fill=BOTH,
                         expand=True,
                         anchor=N,
                         side=LEFT,
                         pady=(5, 1))

    #Aesthetics tab
    frames['cosmetics'].pack(fill=BOTH, expand=True, anchor=W, side=TOP)
    frames['aesthetic_tab_left'].pack(fill=BOTH,
                                      expand=True,
                                      anchor=W,
                                      side=LEFT)
    frames['aesthetic_tab_right'].pack(fill=BOTH,
                                       expand=True,
                                       anchor=W,
                                       side=RIGHT)

    #Aesthetics tab - Left Side
    frames['tuniccolor'].pack(fill=BOTH,
                              expand=True,
                              anchor=W,
                              side=TOP,
                              pady=(5, 1))
    frames['lowhp'].pack(fill=BOTH,
                         expand=True,
                         anchor=W,
                         side=TOP,
                         pady=(5, 1))

    #Aesthetics tab - Right Side
    frames['navicolor'].pack(fill=BOTH,
                             expand=True,
                             anchor=W,
                             side=TOP,
                             pady=(5, 1))
    frames['navihint'].pack(fill=BOTH,
                            expand=True,
                            anchor=W,
                            side=TOP,
                            pady=(5, 1))

    notebook.pack(fill=BOTH, expand=True, padx=5, pady=5)

    multiworldFrame = LabelFrame(frames['rom_tab'],
                                 text='Multi-World Generation')
    countLabel = Label(
        multiworldFrame,
        wraplength=350,
        justify=LEFT,
        text=
        'This is used for co-op generations. Increasing Player Count will drastically increase the generation time. For more information see:'
    )
    hyperLabel = Label(multiworldFrame,
                       wraplength=350,
                       justify=LEFT,
                       text='https://github.com/TestRunnerSRL/bizhawk-co-op',
                       fg='blue',
                       cursor='hand2')
    hyperLabel.bind(
        "<Button-1>", lambda event: webbrowser.open_new(
            r"https://github.com/TestRunnerSRL/bizhawk-co-op"))
    countLabel.pack(side=TOP, anchor=W, padx=5, pady=0)
    hyperLabel.pack(side=TOP, anchor=W, padx=5, pady=0)

    worldCountFrame = Frame(multiworldFrame)
    countLabel = Label(worldCountFrame, text='Player Count')
    guivars['world_count'] = StringVar()
    countSpinbox = Spinbox(worldCountFrame,
                           from_=1,
                           to=100,
                           textvariable=guivars['world_count'],
                           width=3)

    countLabel.pack(side=LEFT)
    countSpinbox.pack(side=LEFT, padx=2)
    worldCountFrame.pack(side=LEFT, anchor=N, padx=10, pady=(1, 5))

    playerNumFrame = Frame(multiworldFrame)
    countLabel = Label(playerNumFrame, text='Player ID')
    guivars['player_num'] = StringVar()
    countSpinbox = Spinbox(playerNumFrame,
                           from_=1,
                           to=100,
                           textvariable=guivars['player_num'],
                           width=3)

    countLabel.pack(side=LEFT)
    countSpinbox.pack(side=LEFT, padx=2)
    playerNumFrame.pack(side=LEFT, anchor=N, padx=10, pady=(1, 5))
    multiworldFrame.pack(side=TOP, anchor=W, padx=5, pady=(1, 1))

    # didn't refactor the rest, sorry

    # create the option menu

    settingsFrame.pack(fill=BOTH, anchor=W, padx=5, pady=(10, 0))

    def multiple_run(settings, window):
        orig_seed = settings.seed
        for i in range(settings.count):
            settings.update_seed(orig_seed + '-' + str(i))
            window.update_title("Generating Seed...%d/%d" %
                                (i + 1, settings.count))
            main(settings, window)

    def generateRom():
        settings = guivars_to_settings(guivars)
        if settings.count is not None:
            BackgroundTaskProgress(mainWindow, "Generating Seed...",
                                   multiple_run, settings)
        else:
            BackgroundTaskProgress(mainWindow, "Generating Seed...", main,
                                   settings)

    generateSeedFrame = Frame(mainWindow)
    generateButton = Button(generateSeedFrame,
                            text='Generate Patched Rom',
                            command=generateRom)

    seedLabel = Label(generateSeedFrame, text='Seed')
    guivars['seed'] = StringVar()
    seedEntry = Entry(generateSeedFrame,
                      textvariable=guivars['seed'],
                      width=25)
    seedLabel.pack(side=LEFT, padx=(55, 5))
    seedEntry.pack(side=LEFT)
    generateButton.pack(side=LEFT, padx=(5, 0))

    generateSeedFrame.pack(side=BOTTOM, anchor=W, padx=5, pady=10)

    guivars['checked_version'] = StringVar()

    if settings is not None:
        # load values from commandline args
        settings_to_guivars(settings, guivars)
    else:
        # try to load saved settings
        try:
            settingsFile = os.path.join(
                os.path.dirname(os.path.abspath(__file__)), 'settings.sav')
            with open(settingsFile) as f:
                settings = Settings(json.load(f))
                settings.update_seed("")
                settings_to_guivars(settings, guivars)
        except:
            pass

    show_settings()

    def gui_check_version():
        task = BackgroundTask(mainWindow, check_version,
                              guivars['checked_version'].get())
        while task.running:
            mainWindow.update()

        if task.status:
            dialog = Dialog(mainWindow,
                            title="Version Error",
                            question=task.status,
                            oktext='Don\'t show again',
                            canceltext='OK')
            if dialog.result:
                guivars['checked_version'].set(ESVersion)

    mainWindow.after(1000, gui_check_version)
    mainWindow.mainloop()

    # save settings on close
    with open('settings.sav', 'w') as outfile:
        settings = guivars_to_settings(guivars)
        json.dump(settings.__dict__, outfile)
Exemplo n.º 7
0
def adjustGUI():
    from tkinter import Checkbutton, OptionMenu, Toplevel, LabelFrame, PhotoImage, Tk, LEFT, RIGHT, BOTTOM, TOP, \
        StringVar, IntVar, Frame, Label, W, E, X, BOTH, Entry, Spinbox, Button, filedialog, messagebox, ttk
    from Gui import get_rom_options_frame, get_rom_frame
    from GuiUtils import set_icon
    from argparse import Namespace
    from Main import __version__ as MWVersion
    adjustWindow = Tk()
    adjustWindow.wm_title("Berserker's Multiworld %s LttP Adjuster" % MWVersion)
    set_icon(adjustWindow)

    rom_options_frame, rom_vars, set_sprite = get_rom_options_frame(adjustWindow)

    bottomFrame2 = Frame(adjustWindow)

    romFrame, romVar = get_rom_frame(adjustWindow)

    romDialogFrame = Frame(adjustWindow)
    baseRomLabel2 = Label(romDialogFrame, text='Rom to adjust')
    romVar2 = StringVar()
    romEntry2 = Entry(romDialogFrame, textvariable=romVar2)

    def RomSelect2():
        rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc", ".bmbp")), ("All Files", "*")])
        romVar2.set(rom)
    romSelectButton2 = Button(romDialogFrame, text='Select Rom', command=RomSelect2)
    romDialogFrame.pack(side=TOP, expand=True, fill=X)
    baseRomLabel2.pack(side=LEFT)
    romEntry2.pack(side=LEFT, expand=True, fill=X)
    romSelectButton2.pack(side=LEFT)

    def adjustRom():
        guiargs = Namespace()
        guiargs.heartbeep = rom_vars.heartbeepVar.get()
        guiargs.heartcolor = rom_vars.heartcolorVar.get()
        guiargs.fastmenu = rom_vars.fastMenuVar.get()
        guiargs.ow_palettes = rom_vars.owPalettesVar.get()
        guiargs.uw_palettes = rom_vars.uwPalettesVar.get()
        guiargs.hud_palettes = rom_vars.hudPalettesVar.get()
        guiargs.sword_palettes = rom_vars.swordPalettesVar.get()
        guiargs.shield_palettes = rom_vars.shieldPalettesVar.get()
        guiargs.quickswap = bool(rom_vars.quickSwapVar.get())
        guiargs.disablemusic = bool(rom_vars.disableMusicVar.get())
        guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get())
        guiargs.rom = romVar2.get()
        guiargs.baserom = romVar.get()
        guiargs.sprite = rom_vars.sprite
        if rom_vars.sprite_pool:
            guiargs.world = AdjusterWorld(rom_vars.sprite_pool)

        try:
            guiargs, path = adjust(args=guiargs)
            if rom_vars.sprite_pool:
                guiargs.sprite_pool = rom_vars.sprite_pool
                delattr(guiargs, "world")
        except Exception as e:
            logging.exception(e)
            messagebox.showerror(title="Error while adjusting Rom", message=str(e))
        else:
            messagebox.showinfo(title="Success", message=f"Rom patched successfully to {path}")
            from Utils import persistent_store
            from Rom import Sprite
            if isinstance(guiargs.sprite, Sprite):
                guiargs.sprite = guiargs.sprite.name
            persistent_store("adjuster", "last_settings_3", guiargs)

    adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
    rom_options_frame.pack(side=TOP)
    adjustButton.pack(side=BOTTOM, padx=(5, 5))

    bottomFrame2.pack(side=BOTTOM, pady=(5, 5))

    adjustWindow.mainloop()