Preliminary msi support

Added a proper icon

Fix output directory for packaged builds

Added a button to open the ouput directory, and a button to open
documentation for packaged builds.
This commit is contained in:
Kevin Cathcart 2017-11-25 21:49:36 -05:00
parent 91c7fdaf2d
commit 0de4a5857c
12 changed files with 174 additions and 14 deletions

5
.gitignore vendored
View File

@ -3,4 +3,7 @@ dist
build build
.idea .idea
*.sfc *.sfc
*_Spoiler.txt *_Spoiler.txt
bundle/components.wxs
*.wixobj
README.html

41
Gui.py
View File

@ -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 from argparse import Namespace
import random import random
import subprocess
from tkinter import Checkbutton, OptionMenu, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, Entry, Spinbox, Button, filedialog, messagebox 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): def guiMain(args=None):
mainWindow = Tk() mainWindow = Tk()
mainWindow.wm_title("Entrance Shuffle %s" % ESVersion) mainWindow.wm_title("Entrance Shuffle %s" % ESVersion)
set_icon(mainWindow)
topFrame = Frame(mainWindow) topFrame = Frame(mainWindow)
rightHalfFrame = Frame(topFrame) rightHalfFrame = Frame(topFrame)
checkBoxFrame = Frame(rightHalfFrame) checkBoxFrame = Frame(rightHalfFrame)
@ -164,6 +168,7 @@ def guiMain(args=None):
heartbeepFrame.pack(expand=True, anchor=E) heartbeepFrame.pack(expand=True, anchor=E)
bottomFrame = Frame(mainWindow) bottomFrame = Frame(mainWindow)
farBottomFrame = Frame(mainWindow)
seedLabel = Label(bottomFrame, text='Seed #') seedLabel = Label(bottomFrame, text='Seed #')
seedVar = StringVar() seedVar = StringVar()
@ -212,15 +217,29 @@ def guiMain(args=None):
generateButton = Button(bottomFrame, text='Generate Patched Rom', command=generateRom) 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) seedLabel.pack(side=LEFT)
seedEntry.pack(side=LEFT) seedEntry.pack(side=LEFT)
countLabel.pack(side=LEFT) countLabel.pack(side=LEFT, padx=(5,0))
countSpinbox.pack(side=LEFT) countSpinbox.pack(side=LEFT)
generateButton.pack(side=LEFT) generateButton.pack(side=LEFT, padx=(5,0))
openOutputButton.pack(side=RIGHT)
drowDownFrame.pack(side=LEFT) drowDownFrame.pack(side=LEFT)
rightHalfFrame.pack(side=RIGHT) rightHalfFrame.pack(side=RIGHT)
topFrame.pack(side=TOP) topFrame.pack(side=TOP)
farBottomFrame.pack(side=BOTTOM, fill=X, padx=5, pady=5)
bottomFrame.pack(side=BOTTOM) bottomFrame.pack(side=BOTTOM)
if args is not None: if args is not None:
@ -254,6 +273,18 @@ def guiMain(args=None):
mainWindow.mainloop() 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__': if __name__ == '__main__':
guiMain() guiMain()

43
Main.py
View File

@ -12,6 +12,8 @@ import random
import time import time
import logging import logging
import json import json
import sys
import os
__version__ = '0.5.0-dev' __version__ = '0.5.0-dev'
@ -105,16 +107,53 @@ def main(args, seed=None):
if args.jsonout: if args.jsonout:
print(json.dumps({'patch': rom.patches, 'spoiler': world.spoiler.to_json()})) print(json.dumps({'patch': rom.patches, 'spoiler': world.spoiler.to_json()}))
else: 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: 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.info('Done. Enjoy.')
logger.debug('Total Time: %s' % (time.clock() - start)) logger.debug('Total Time: %s' % (time.clock() - start))
return world 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): def copy_world(world):
# ToDo: Not good yet # 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) 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)

View File

@ -11,22 +11,24 @@ install:
- '%PYTHON%\Scripts\pip install pyinstaller' - '%PYTHON%\Scripts\pip install pyinstaller'
- '%PYTHON%\Scripts\pip install markdown' - '%PYTHON%\Scripts\pip install markdown'
- '%PYTHON%\python.exe -m markdown README.md > README.html' - '%PYTHON%\python.exe -m markdown README.md > README.html'
- 'copy LICENSE LICENSE.txt'
- '%PYTHON%\Scripts\pyinstaller bundle\EntranceRandomizer.spec' - '%PYTHON%\Scripts\pyinstaller bundle\EntranceRandomizer.spec'
- 'mkdir dist\EntranceRandomizer\ext' - 'mkdir dist\EntranceRandomizer\ext'
- 'move dist\EntranceRandomizer\*.pyd dist\EntranceRandomizer\ext' - 'move dist\EntranceRandomizer\*.pyd dist\EntranceRandomizer\ext'
- 'move dist\EntranceRandomizer\tcl*.dll dist\EntranceRandomizer\ext' - 'move dist\EntranceRandomizer\tcl*.dll dist\EntranceRandomizer\ext'
- 'move dist\EntranceRandomizer\tk*.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 build: off
artifacts: artifacts:
- path: dist/EntranceRandomizer/ - path: dist/EntranceRandomizer.msi
name: EntranceRandomizer-$(ProjectVersion)-win32 name: EntranceRandomizer-$(ProjectVersion)-win32.msi
deploy: deploy:
- provider: GitHub - provider: GitHub
tag: $(APPVEYOR_REPO_TAG_NAME) tag: $(APPVEYOR_REPO_TAG_NAME)
auth_token: auth_token:
secure: wQH+KnogyjYcDdo/srOQeoYEVIbH1uoYA5Iajdy/sR0Tbme7gOt15u2FBIkTg9/x secure: wQH+KnogyjYcDdo/srOQeoYEVIbH1uoYA5Iajdy/sR0Tbme7gOt15u2FBIkTg9/x
artifact: /.*-win32.zip/ artifact: /.*-win32.*/
force_update: false force_update: false
on: on:
appveyor_repo_tag: true appveyor_repo_tag: true

View File

@ -6,7 +6,7 @@ block_cipher = None
a = Analysis(['../EntranceRandomizer.py'], a = Analysis(['../EntranceRandomizer.py'],
pathex=['bundle'], pathex=['bundle'],
binaries=[], binaries=[],
datas=[('../data/', 'data/'), ('../README.html', '.'), ('../LICENSE.txt', '.')], datas=[('../data/', 'data/'), ('../README.html', '.')],
hiddenimports=[], hiddenimports=[],
hookspath=[], hookspath=[],
runtime_hooks=['bundle/_rt_hook.py'], runtime_hooks=['bundle/_rt_hook.py'],
@ -24,6 +24,7 @@ exe = EXE(pyz,
debug=False, debug=False,
strip=False, strip=False,
upx=False, upx=False,
icon='data/ER.ico',
console=is_win ) console=is_win )
coll = COLLECT(exe, coll = COLLECT(exe,
a.binaries, a.binaries,
@ -34,5 +35,5 @@ coll = COLLECT(exe,
name='EntranceRandomizer') name='EntranceRandomizer')
app = BUNDLE(coll, app = BUNDLE(coll,
name ='EntranceRandomizer.app', name ='EntranceRandomizer.app',
icon = None, icon = 'data/ER.icns',
bundle_identifier = None) bundle_identifier = None)

35
bundle/components.xslt Normal file
View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
<xsl:output method="xml" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="wix:File[@Source='SourceDir\EntranceRandomizer.exe']">
<xsl:copy-of select="." />
<wix:Shortcut Id="ProgramShortcut"
Name="ALttP Entrance Randomizer"
Advertise="yes"
Description="ALttP Entrance Randomizer"
Directory="ApplicationProgramsFolder" />
</xsl:template>
<xsl:template match="wix:File[@Source='SourceDir\README.hmtl']">
<xsl:copy-of select="." />
<wix:Shortcut Id="ReadmeShortcut"
Name="ALttP Entrance Randomizer README"
Advertise="yes"
Description="ALttP Entrance Randomizer README"
Directory="ApplicationProgramsFolder" />
</xsl:template>
</xsl:stylesheet>

49
bundle/installer.wxs Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="ALttP Entrance Randomizer" Language="1033" Version="0.5.0" Manufacturer="Randomizer Community" UpgradeCode="0229C621-5F8A-4D59-962A-5826C58B93DD" >
<Package Id="*" InstallerVersion="400" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade AllowDowngrades="yes"/>
<Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='INSTALLDIR' Name='ALttP Entrance Randomizer'/>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="ALttP Entrance Randomizer"/>
</Directory>
</Directory>
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcut" Guid="0054698A-5A56-4B36-8176-8FEC1762EF2D">
<RemoveFolder Id="CleanUpShortCut" Directory="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\ALttPEntranceRandomizer" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
<Feature Id="Complete"
Title="ALttP Entrance Randomizer"
Description="ALttP Entrance Randomizer"
Level="1">
<ComponentGroupRef Id="ERFiles"/>
<ComponentRef Id="ApplicationShortcut"/>
</Feature>
<Icon Id="ER.ico" SourceFile="Data/ER.ico" />
<Property Id="DISABLEADVTSHORTCUTS" Secure="yes">1</Property>
<Property Id="ARPPRODUCTICON" Value="ER.ico" />
<Property Id="WIXUI_INSTALLDIR">INSTALLDIR</Property>
<UI>
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
<!-- Skip license page -->
<Publish Dialog="WelcomeDlg"
Control="Next"
Event="NewDialog"
Value="InstallDirDlg"
Order="2">1</Publish>
<Publish Dialog="InstallDirDlg"
Control="Back"
Event="NewDialog"
Value="WelcomeDlg"
Order="2">1</Publish>
</UI>
</Product>
</Wix>

BIN
data/ER.icns Normal file

Binary file not shown.

BIN
data/ER.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
data/ER16.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

BIN
data/ER32.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

BIN
data/ER48.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B