diff --git a/.gitignore b/.gitignore index 5dd284f9..04bc2055 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ dist build .idea *.sfc -*_Spoiler.txt \ No newline at end of file +*_Spoiler.txt +bundle/components.wxs +*.wixobj +README.html diff --git a/Gui.py b/Gui.py index feee07c7..6ddc29ca 100644 --- a/Gui.py +++ b/Gui.py @@ -1,14 +1,18 @@ -from Main import main, __version__ as ESVersion +from Main import main, __version__ as ESVersion, get_output_path from argparse import Namespace import random - -from tkinter import Checkbutton, OptionMenu, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, Entry, Spinbox, Button, filedialog, messagebox +import subprocess +import os +import sys +from tkinter import Checkbutton, OptionMenu, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, X, Entry, Spinbox, Button, filedialog, messagebox, PhotoImage def guiMain(args=None): mainWindow = Tk() mainWindow.wm_title("Entrance Shuffle %s" % ESVersion) + set_icon(mainWindow) + topFrame = Frame(mainWindow) rightHalfFrame = Frame(topFrame) checkBoxFrame = Frame(rightHalfFrame) @@ -164,6 +168,7 @@ def guiMain(args=None): heartbeepFrame.pack(expand=True, anchor=E) bottomFrame = Frame(mainWindow) + farBottomFrame = Frame(mainWindow) seedLabel = Label(bottomFrame, text='Seed #') seedVar = StringVar() @@ -212,15 +217,29 @@ def guiMain(args=None): generateButton = Button(bottomFrame, text='Generate Patched Rom', command=generateRom) + def open_output(): + open_file(get_output_path()) + + openOutputButton = Button(farBottomFrame, text='Open Output Directory', command=open_output) + + if os.path.exists('README.html'): + def open_readme(): + open_file('README.html') + openReadmeButton = Button(farBottomFrame, text='Open Documentation', command=open_readme) + openReadmeButton.pack(side=LEFT) + seedLabel.pack(side=LEFT) seedEntry.pack(side=LEFT) - countLabel.pack(side=LEFT) + countLabel.pack(side=LEFT, padx=(5,0)) countSpinbox.pack(side=LEFT) - generateButton.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) + farBottomFrame.pack(side=BOTTOM, fill=X, padx=5, pady=5) bottomFrame.pack(side=BOTTOM) if args is not None: @@ -254,6 +273,18 @@ def guiMain(args=None): mainWindow.mainloop() +def open_file(filename): + if sys.platform == 'win32': + os.startfile(filename) + else: + open_Command = 'open' if sys.plaform == 'darwin' else 'xdg-open' + subprocess.call([open_command, filename]) + +def set_icon(window): + er16 = PhotoImage(file='data/ER16.gif') + er32 = PhotoImage(file='data/ER32.gif') + er48 = PhotoImage(file='data/ER32.gif') + window.tk.call('wm', 'iconphoto', window._w, er16, er32, er48) if __name__ == '__main__': guiMain() diff --git a/Main.py b/Main.py index 8b49044e..3cbc8758 100644 --- a/Main.py +++ b/Main.py @@ -12,6 +12,8 @@ import random import time import logging import json +import sys +import os __version__ = '0.5.0-dev' @@ -105,16 +107,53 @@ def main(args, seed=None): if args.jsonout: print(json.dumps({'patch': rom.patches, 'spoiler': world.spoiler.to_json()})) else: - rom.write_to_file(args.jsonout or '%s.sfc' % outfilebase) + rom.write_to_file(args.jsonout or os.path.join(get_output_path(),'%s.sfc' % outfilebase)) if args.create_spoiler and not args.jsonout: - world.spoiler.to_file('%s_Spoiler.txt' % outfilebase) + world.spoiler.to_file(os.path.join(get_output_path(),'%s_Spoiler.txt' % outfilebase)) logger.info('Done. Enjoy.') logger.debug('Total Time: %s' % (time.clock() - start)) return world +def get_output_path(): + if get_output_path.cached_path is not None: + return get_output_path.cached_path + + if not hasattr(sys, 'frozen'): + get_output_path.cached_path = '.' + return get_output_path.cached_path + else: + # has been packaged, so cannot use CWD for output. + if sys.platform == 'win32': + #windows + import ctypes.wintypes + CSIDL_PERSONAL = 5 # My Documents + SHGFP_TYPE_CURRENT = 0 # Get current, not default value + + buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) + ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, buf) + + documents = buf.value + + elif sys.platform == 'darwin': + from AppKit import NSSearchPathForDirectoriesInDomains + # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains + NSDocumentDirectory = 9 + NSUserDomainMask = 1 + # True for expanding the tilde into a fully qualified path + documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0] + else: + raise NotImplementedError('Not supported yet') + + get_output_path.cached_path = os.path.join(documents, 'ALttPEntranceRandomizer') + if not os.path.exists(get_output_path.cached_path): + os.mkdir(get_output_path.cached_path) + return get_output_path.cached_path + +get_output_path.cached_path = None + def copy_world(world): # ToDo: Not good yet ret = World(world.shuffle, world.logic, world.mode, world.difficulty, world.timer, world.progressive, world.goal, world.algorithm, world.place_dungeon_items, world.check_beatable_only, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.keysanity) diff --git a/appveyor.yml b/appveyor.yml index eec0e1ef..19d5b530 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,22 +11,24 @@ install: - '%PYTHON%\Scripts\pip install pyinstaller' - '%PYTHON%\Scripts\pip install markdown' - '%PYTHON%\python.exe -m markdown README.md > README.html' - - 'copy LICENSE LICENSE.txt' - '%PYTHON%\Scripts\pyinstaller bundle\EntranceRandomizer.spec' - 'mkdir dist\EntranceRandomizer\ext' - 'move dist\EntranceRandomizer\*.pyd dist\EntranceRandomizer\ext' - 'move dist\EntranceRandomizer\tcl*.dll dist\EntranceRandomizer\ext' - 'move dist\EntranceRandomizer\tk*.dll dist\EntranceRandomizer\ext' + - '"%WIX%\bin\heat.exe" dir "dist\EntranceRandomizer" -sfrag -srd -suid -dr INSTALLDIR -cg ERFiles -ag -template fragment -t bundle\components.xslt -out build\components.wxs' + - '"%WIX%\bin\candle.exe" -out build\ bundle\*.wxs build\*.wxs' + - '"%WIX%\bin\light.exe" -ext WixUIExtension build\*.wixobj -o dist\EntranceRandomizer.msi -b dist\EntranceRandomizer' build: off artifacts: -- path: dist/EntranceRandomizer/ - name: EntranceRandomizer-$(ProjectVersion)-win32 +- path: dist/EntranceRandomizer.msi + name: EntranceRandomizer-$(ProjectVersion)-win32.msi deploy: - provider: GitHub tag: $(APPVEYOR_REPO_TAG_NAME) auth_token: secure: wQH+KnogyjYcDdo/srOQeoYEVIbH1uoYA5Iajdy/sR0Tbme7gOt15u2FBIkTg9/x - artifact: /.*-win32.zip/ + artifact: /.*-win32.*/ force_update: false on: appveyor_repo_tag: true diff --git a/bundle/EntranceRandomizer.spec b/bundle/EntranceRandomizer.spec index 2e73e6ab..c01d6155 100644 --- a/bundle/EntranceRandomizer.spec +++ b/bundle/EntranceRandomizer.spec @@ -6,7 +6,7 @@ block_cipher = None a = Analysis(['../EntranceRandomizer.py'], pathex=['bundle'], binaries=[], - datas=[('../data/', 'data/'), ('../README.html', '.'), ('../LICENSE.txt', '.')], + datas=[('../data/', 'data/'), ('../README.html', '.')], hiddenimports=[], hookspath=[], runtime_hooks=['bundle/_rt_hook.py'], @@ -24,6 +24,7 @@ exe = EXE(pyz, debug=False, strip=False, upx=False, + icon='data/ER.ico', console=is_win ) coll = COLLECT(exe, a.binaries, @@ -34,5 +35,5 @@ coll = COLLECT(exe, name='EntranceRandomizer') app = BUNDLE(coll, name ='EntranceRandomizer.app', - icon = None, + icon = 'data/ER.icns', bundle_identifier = None) diff --git a/bundle/components.xslt b/bundle/components.xslt new file mode 100644 index 00000000..1b4c7132 --- /dev/null +++ b/bundle/components.xslt @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundle/installer.wxs b/bundle/installer.wxs new file mode 100644 index 00000000..c6ef2185 --- /dev/null +++ b/bundle/installer.wxs @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + INSTALLDIR + + + + + 1 + 1 + + + diff --git a/data/ER.icns b/data/ER.icns new file mode 100644 index 00000000..e3a6fbfa Binary files /dev/null and b/data/ER.icns differ diff --git a/data/ER.ico b/data/ER.ico new file mode 100644 index 00000000..b9b60360 Binary files /dev/null and b/data/ER.ico differ diff --git a/data/ER16.gif b/data/ER16.gif new file mode 100644 index 00000000..5806c8fd Binary files /dev/null and b/data/ER16.gif differ diff --git a/data/ER32.gif b/data/ER32.gif new file mode 100644 index 00000000..b72c0bcc Binary files /dev/null and b/data/ER32.gif differ diff --git a/data/ER48.gif b/data/ER48.gif new file mode 100644 index 00000000..06d7af55 Binary files /dev/null and b/data/ER48.gif differ