diff --git a/doc/makepanda/makepanda.py b/doc/makepanda/makepanda.py index 958ce9e55f..dcaa79ec2c 100755 --- a/doc/makepanda/makepanda.py +++ b/doc/makepanda/makepanda.py @@ -190,6 +190,7 @@ PREFIX="built" COMPILER=COMPILERS[0] OPTIMIZE="3" INSTALLER=0 +PPGAME=0 COMPLETE=0 THIRDPARTY="thirdparty" VERSION="0.0.0" @@ -459,6 +460,7 @@ def usage(problem): print " --thirdparty X (directory containing third-party software)" print " --complete (copy samples and direct into the build)" print " --installer (build an executable installer)" + print " --ppgame X (build a prepackaged game - see manual)" print " --v1 X (set the major version number)" print " --v2 X (set the minor version number)" print " --v3 X (set the sequence version number)" @@ -481,11 +483,11 @@ def usage(problem): sys.exit(1) def parseopts(args): - global PREFIX,COMPILER,OPTIMIZE,OMIT,THIRDPARTY,INSTALLER + global PREFIX,COMPILER,OPTIMIZE,OMIT,THIRDPARTY,INSTALLER,PPGAME global COPYEXTRAS,VERSION,COMPRESSOR,DIRECTXSDK,VERBOSE longopts = [ "help","package-info","prefix=","compiler=","directx-sdk=","thirdparty=", - "optimize=","everything","nothing","installer","quiet","verbose", + "optimize=","everything","nothing","installer","ppgame=","quiet","verbose", "complete","version=","lzma"] anything = 0 for pkg in PACKAGES: longopts.append("no-"+pkg.lower()) @@ -503,6 +505,7 @@ def parseopts(args): elif (option=="--quiet"): VERBOSE-=1 elif (option=="--verbose"): VERBOSE+=1 elif (option=="--installer"): INSTALLER=1 + elif (option=="--ppgame"): PPGAME=value elif (option=="--complete"): COMPLETE=1 elif (option=="--everything"): OMIT=[] elif (option=="--nothing"): OMIT=PACKAGES[:] @@ -821,7 +824,11 @@ def printStatus(header,warnings): print "Makepanda: Thirdparty dir:",THIRDPARTY print "Makepanda: DirectX SDK dir:",DIRECTXSDK print "Makepanda: Verbose vs. Quiet Level:",VERBOSE - print "Makepanda: Build installer:",INSTALLER,COMPRESSOR + if (sys.platform == "win32"): + if INSTALLER: print "Makepanda: Build installer, using",COMPRESSOR + else : print "Makepanda: Don't build installer" + if PPGAME!=0: print "Makepanda: Build pprepackaged game ",PPGAME,"using",COMPRESSOR + else : print "Makepanda: Don't build pprepackaged game" print "Makepanda: Version ID: "+VERSION for x in warnings: print "Makepanda: "+x print "-------------------------------------------------------------------" @@ -6203,23 +6210,43 @@ if (COMPLETE): ########################################################################################## # -# The Installer +# The Installers # ########################################################################################## -if (INSTALLER): - if (sys.platform == "win32"): - if (older('panda3d-install.exe', ALLTARGETS)): - VERSION = str(VERSION1)+"-"+str(VERSION2)+"-"+str(VERSION3) - print("Building installer. This can take up to an hour.") - if (COMPRESSOR != "lzma"): print("Note: you are using zlib, which is faster, but lzma gives better compression.") - if (os.path.exists("panda3d-"+VERSION+".exe")): - os.remove("panda3d-"+VERSION+".exe") - oscmd("thirdparty/win-nsis/makensis.exe /V2 /DCOMPRESSOR="+COMPRESSOR+" /DVERSION="+VERSION+" thirdparty/win-nsis/panda.nsi") - os.rename("panda3d-install-TMP.exe", "panda3d-"+VERSION+".exe") - else: - # Do an rpmbuild or something like that. - pass +if (sys.platform == "win32"): + + def MakeInstaller(file,fullname,smdirectory,uninstallkey,installdir,ppgame): + if (older(file, ALLTARGETS)): + print "Building "+fullname+" installer. This can take up to an hour." + if (COMPRESSOR != "lzma"): + print("Note: you are using zlib, which is faster, but lzma gives better compression.") + if (os.path.exists(file)): + os.remove(file) + if (os.path.exists("nsis-output.exe")): + os.remove("nsis-output.exe") + def0 = '/DCOMPRESSOR="' + COMPRESSOR + '" ' + def1 = '/DFULLNAME="' + fullname + '" ' + def2 = '/DSMDIRECTORY="' + smdirectory + '" ' + def3 = '/DUNINSTALLKEY="' + uninstallkey + '" ' + def4 = '/DINSTALLDIR="' + installdir + '" ' + def5 = '' + if (ppgame): def5 = '/DPPGAME="' + ppgame + '" ' + oscmd("thirdparty/win-nsis/makensis.exe /V2 "+def0+def1+def2+def3+def4+def5+" thirdparty/win-nsis/panda.nsi") + os.rename("nsis-output.exe", file) + + if (INSTALLER!=0): + MakeInstaller("Panda3D-"+VERSION+".exe", "Panda3D", "Panda3D "+VERSION, + "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION, 0) + + if (PPGAME!=0): + if (os.path.isdir(PPGAME)==0): + sys.exit("No such directory "+PPGAME) + if (os.path.exists(os.path.join(PPGAME,PPGAME+".py"))==0): + sys.exit("No such file "+PPGAME+"/"+PPGAME+".py") + MakeInstaller(PPGAME+"-"+VERSION+".exe", PPGAME, PPGAME, + PPGAME+" "+VERSION, "C:\\"+PPGAME+"-"+VERSION, PPGAME) + ########################################################################################## # diff --git a/doc/makepanda/panda.nsi b/doc/makepanda/panda.nsi new file mode 100755 index 0000000000..0acfd68f19 --- /dev/null +++ b/doc/makepanda/panda.nsi @@ -0,0 +1,525 @@ +; Panda3D installation script for the Nullsoft Installation System (NSIS). +; Jon Parise +; with Ben Johnson +; with Jason Pratt +; mangled by Josh Yelon + +; Caller needs to define these variables: +; COMPRESSOR - either zlib or lzma +; FULLNAME - full name of what we're building (ie, "Panda3D") +; SMDIRECTORY - where to put this in the start menu (ie, "Panda3D VERSION") +; UNINSTALLKEY - what registry key to use for uninstaller (ie, "Panda3D VERSION") +; INSTALLDIR - where to install the program (ie, "C:\Panda3D-VERSION") +; PPGAME - only if making a prepackaged game. (ie, "Airblade") + +!define PANDA ..\..\built +!define PSOURCE ..\.. + +; Use the Modern UI +!include "MUI.nsh" +; Windows system messaging support +!include "${NSISDIR}\Include\WinMessages.nsh" + +Name "${FULLNAME}" +InstallDir "${INSTALLDIR}" +OutFile "..\..\nsis-output.exe" + +SetCompress auto +SetCompressor ${COMPRESSOR} + +!define MUI_ABORTWARNING +!define MUI_FINISHPAGE_NOREBOOTSUPPORT + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "${PSOURCE}\doc\LICENSE" +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_WELCOME +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES +!insertmacro MUI_UNPAGE_FINISH + +!insertmacro MUI_LANGUAGE "English" + +ShowInstDetails show +ShowUninstDetails show +LicenseData ${PSOURCE}\doc\LICENSE + +InstType "Typical" + +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +Section "${FULLNAME}" SecCore + SectionIn 1 2 3 RO + + SetOutPath $INSTDIR + SetOverwrite try + + SetOutPath $INSTDIR + File ${PSOURCE}\doc\LICENSE + SetOutPath $INSTDIR\bin + File /r ${PANDA}\bin\*.dll + SetOutPath $INSTDIR\etc + File /r ${PANDA}\etc\* + SetOutPath $INSTDIR\direct + File /r /x CVS /x Opt?-Win32 ${PSOURCE}\direct\*.py + File ${PANDA}\direct\__init__.py + SetOutPath $INSTDIR\pandac + File /r ${PANDA}\pandac\* + SetOutPath $INSTDIR\python + File /r /x CVS /x *.pyc ${PANDA}\python\* + + RMDir /r "$SMPROGRAMS\${SMDIRECTORY}" + CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}" + + !ifdef PPGAME + + SetOutPath $INSTDIR\bin + File /r ${PANDA}\bin\ppython.exe + SetOutpath $INSTDIR\${PPGAME} + File /r ${PSOURCE}\${PPGAME}\* + SetOutPath $INSTDIR\${PPGAME} + CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\${FULLNAME}.lnk" "$INSTDIR\bin\ppython.exe" "${PPGAME}.py" "$INSTDIR\bin\ppython.exe" 0 "" "" "${FULLNAME}" + + !else + + SetOutPath $INSTDIR\bin + File /r ${PANDA}\bin\*.exe + SetOutPath $INSTDIR + File ${PSOURCE}\doc\InstallerNotes + SetOutPath $INSTDIR\lib + File /r /x *.exp ${PANDA}\lib\* + SetOutPath $INSTDIR\SceneEditor + File /r /x CVS ${PSOURCE}\SceneEditor + + SetOutPath $INSTDIR + CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\ppython.exe" 0 "" "" "Panda Manual" + SetOutPath $INSTDIR\samples\RubiksCube + CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Test - Rubiks Cube.lnk" "$INSTDIR\bin\ppython.exe" "rubiksCube.py" "$INSTDIR\bin\ppython.exe" 0 "" "" "Panda Test" + !endif + +SectionEnd + +!ifndef PPGAME +Section "Sample Worlds" SecSamples + SectionIn 1 2 3 + + DetailPrint "Extracting samples ..." + SetDetailsPrint textonly + SetOutPath $INSTDIR\models + File /r /x CVS ${PSOURCE}\models\* + + DetailPrint "Extracting models ..." + SetDetailsPrint textonly + SetOutPath $INSTDIR\samples + File /r /x CVS ${PSOURCE}\samples\* + + SetDetailsPrint both +SectionEnd +!endif + + +Section -post + + !ifndef PPGAME + # Add the "bin" directory to the PATH. + DetailPrint "Adding 'bin' directory to the PATH..." + Push "$INSTDIR\bin" + Call AddToPath + !endif + + DetailPrint "Registering Helix Preferences..." + WriteRegStr HKLM "Software\Helix\HelixSDK\10.0\Preferences\UseOverlay" "" "0" + WriteRegStr HKLM "Software\Helix\HelixSDK\10.0\Preferences\UseWinDraw" "" "0" + WriteRegStr HKCU "Software\Helix\HelixSDK\10.0\Preferences\UseOverlay" "" "0" + WriteRegStr HKCU "Software\Helix\HelixSDK\10.0\Preferences\UseWinDraw" "" "0" + + DetailPrint "Adding the uninstaller ..." + Delete "$INSTDIR\uninst.exe" + WriteUninstaller "$INSTDIR\uninst.exe" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTALLKEY}" "DisplayName" "${FULLNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTALLKEY}" "UninstallString" '"$INSTDIR\uninst.exe"' + CreateShortcut "$SMPROGRAMS\${SMDIRECTORY}\Uninstall ${FULLNAME}.lnk" "$INSTDIR\uninst.exe" "" +SectionEnd + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SecCore} "The core files required to use ${FULLNAME}." + !ifndef PPGAME + !insertmacro MUI_DESCRIPTION_TEXT ${SecSamples} "Sample worlds, scripts, models and tutorials." + !endif +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +Section Uninstall + +!ifndef PPGAME + DetailPrint "Removing $FULLNAME from PATH ..." + Push "$INSTDIR\bin" + Call un.RemoveFromPath +!endif + + Delete "$INSTDIR\uninst.exe" + DetailPrint "Removing Start Menu folder ..." + RMDir /r "$SMPROGRAMS\${SMDIRECTORY}" + DetailPrint "Completely removing the directory ($INSTDIR)..." + RMDir /r "$INSTDIR" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTALLKEY}" + +SectionEnd + +# --[ Utility Functions ]------------------------------------------------------ + +; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 +Function IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd + +; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 +Function un.IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 unIsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + unIsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd + +; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 +Function un.StrStr + Push $0 + Exch + Pop $0 ; $0 now have the string to find + Push $1 + Exch 2 + Pop $1 ; $1 now have the string to find in + Exch + Push $2 + Push $3 + Push $4 + Push $5 + StrCpy $2 -1 + StrLen $3 $0 + StrLen $4 $1 + IntOp $4 $4 - $3 + unStrStr_loop: + IntOp $2 $2 + 1 + IntCmp $2 $4 0 0 unStrStrReturn_notFound + StrCpy $5 $1 $3 $2 + StrCmp $5 $0 unStrStr_done unStrStr_loop + unStrStrReturn_notFound: + StrCpy $2 -1 + unStrStr_done: + Pop $5 + Pop $4 + Pop $3 + Exch $2 + Exch 2 + Pop $0 + Pop $1 +FunctionEnd + +; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 +; Commentary and smarter ';' checking by Jon Parise +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + Call IsNT + Pop $1 + + StrCmp $1 1 AddToPath_NT + ; We're not on NT, so modify the AUTOEXEC.BAT file. + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 0 END + GetFullPathName /SHORT $0 $0 + FileWrite $1 "$\r$\nSET PATH=%PATH%;$0$\r$\n" + FileClose $1 + Goto AddToPath_done + + AddToPath_NT: + ReadRegStr $1 HKCU "Environment" "PATH" + Call IsUserAdmin + Pop $3 + ; If this is an Admin user, use the System env. variable instead of the user's env. variable + StrCmp $3 1 0 +2 + ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" + + ; If the PATH string is empty, jump over the mangling routines. + StrCmp $1 "" AddToPath_NTdoIt + + ; Pull off the last character of the PATH string. If it's a semicolon, + ; we don't need to add another one, so jump to the section where we + ; append the new PATH component(s). + StrCpy $2 $1 1 -1 + StrCmp $2 ";" AddToPath_NTAddPath AddToPath_NTAddSemi + + AddToPath_NTAddSemi: + StrCpy $1 "$1;" + Goto AddToPath_NTAddPath + AddToPath_NTAddPath: + StrCpy $0 "$1$0" + Goto AddToPath_NTdoIt + AddToPath_NTdoIt: + Call IsUserAdmin + Pop $3 + StrCmp $3 1 0 NotAdmin + WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0 + Goto AddToPath_done + + NotAdmin: + WriteRegExpandStr HKCU "Environment" "PATH" $0 + AddToPath_done: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop + StrCmp $3 "$0" unRemoveFromPath_dosLoop + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + StrLen $2 $0 + Call un.IsUserAdmin + Pop $5 + StrCmp $5 1 0 NotAdmin + ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" + Push $1 + Push $0 + Call un.StrStr ; Find $0 in $1 + Pop $0 ; pos of our dir + IntCmp $0 -1 unRemoveFromPath_done + ; else, it is in path + StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir + IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';') + IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon. + StrLen $0 $1 + StrCpy $1 $1 $0 $2 + StrCpy $3 "$3$1" + WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + Goto unRemoveFromPath_done + + + NotAdmin: + ReadRegStr $1 HKCU "Environment" "PATH" + Push $1 + Push $0 + Call un.StrStr ; Find $0 in $1 + Pop $0 ; pos of our dir + IntCmp $0 -1 unRemoveFromPath_done + ; else, it is in path + StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir + IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';') + IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon. + StrLen $0 $1 + StrCpy $1 $1 $0 $2 + StrCpy $3 "$3$1" + WriteRegExpandStr HKCU "Environment" "PATH" $3 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +; From: http://nsis.sourceforge.net/archive/nsisweb.php?page=329&instances=0,11 +; Localized by Ben Johnson (bkj@andrew.cmu.edu) +Function IsUserAdmin + Push $0 + Push $1 + Push $2 + Push $3 + Call IsNT + Pop $1 + + ClearErrors + UserInfo::GetName + ;IfErrors Win9x + Pop $2 + UserInfo::GetAccountType + Pop $3 + + ; Compare results of IsNT with "1" + StrCmp $1 1 0 NotNT + ;This is NT + + + StrCmp $3 "Admin" 0 NotAdmin + ; Observation: I get here when running Win98SE. (Lilla) + ; The functions UserInfo.dll looks for are there on Win98 too, + ; but just don't work. So UserInfo.dll, knowing that admin isn't required + ; on Win98, returns admin anyway. (per kichik) + ; MessageBox MB_OK 'User "$R1" is in the Administrators group' + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + Push 1 + Return + + NOtAdmin: + ; You should still check for an empty string because the functions + ; UserInfo.dll looks for may not be present on Windows 95. (per kichik) + + #StrCmp $2 "" Win9x + #StrCpy $0 0 + ;MessageBox MB_OK 'User "$2" is in the "$3" group' + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + Push 0 + Return + + ;Because we use IsNT, this is redundant. + #Win9x: + # ; comment/message below is by UserInfo.nsi author: + # ; This one means you don't need to care about admin or + # ; not admin because Windows 9x doesn't either + # ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!" + # StrCpy $0 0 + + NotNT: + ;We are not NT + ;Win9x doesn't have "admin" users. + ;Let the user do whatever. + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + Push 1 + +FunctionEnd + +Function un.IsUserAdmin + Push $0 + Push $1 + Push $2 + Push $3 + Call un.IsNT + Pop $1 + + ClearErrors + UserInfo::GetName + ;IfErrors Win9x + Pop $2 + UserInfo::GetAccountType + Pop $3 + + ; Compare results of IsNT with "1" + StrCmp $1 1 0 NotNT + ;This is NT + + + StrCmp $3 "Admin" 0 NotAdmin + ; Observation: I get here when running Win98SE. (Lilla) + ; The functions UserInfo.dll looks for are there on Win98 too, + ; but just don't work. So UserInfo.dll, knowing that admin isn't required + ; on Win98, returns admin anyway. (per kichik) + ; MessageBox MB_OK 'User "$R1" is in the Administrators group' + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + Push 1 + Return + + NOtAdmin: + ; You should still check for an empty string because the functions + ; UserInfo.dll looks for may not be present on Windows 95. (per kichik) + + #StrCmp $2 "" Win9x + #StrCpy $0 0 + ;MessageBox MB_OK 'User "$2" is in the "$3" group' + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + Push 0 + Return + + ;Because we use IsNT, this is redundant. + #Win9x: + # ; comment/message below is by UserInfo.nsi author: + # ; This one means you don't need to care about admin or + # ; not admin because Windows 9x doesn't either + # ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!" + # StrCpy $0 0 + + NotNT: + ;We are not NT + ;Win9x doesn't have "admin" users. + ;Let the user do whatever. + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + Push 1 + +FunctionEnd