Merge branch 'release/1.9.x'

Conflicts:
	direct/src/p3d/DeploymentTools.py
This commit is contained in:
rdb 2015-11-24 13:39:36 +01:00
commit 3c2f820ad8
20 changed files with 580 additions and 156 deletions

View File

@ -31,8 +31,8 @@ are included as part of the Windows 7.1 SDK.
You will also need to have the third-party dependency libraries available for You will also need to have the third-party dependency libraries available for
the build scripts to use. These are available from one of these two URLs, the build scripts to use. These are available from one of these two URLs,
depending on whether you are on a 32-bit or 64-bit system: depending on whether you are on a 32-bit or 64-bit system:
https://www.panda3d.org/download/panda3d-1.9.0/panda3d-1.9.0-tools-win32.zip https://www.panda3d.org/download/panda3d-1.9.1/panda3d-1.9.1-tools-win32.zip
https://www.panda3d.org/download/panda3d-1.9.0/panda3d-1.9.0-tools-win64.zip https://www.panda3d.org/download/panda3d-1.9.1/panda3d-1.9.1-tools-win64.zip
After acquiring these dependencies, you may simply build Panda3D from the After acquiring these dependencies, you may simply build Panda3D from the
command prompt using the following command: command prompt using the following command:
@ -97,7 +97,7 @@ Mac OS X
-------- --------
On Mac OS X, you will need to download a set of precompiled thirdparty packages in order to On Mac OS X, you will need to download a set of precompiled thirdparty packages in order to
compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.0/panda3d-1.9.0-tools-mac.tar.gz). compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.1/panda3d-1.9.1-tools-mac.tar.gz).
After placing the thirdparty directory inside the panda3d source directory, After placing the thirdparty directory inside the panda3d source directory,
you may build Panda3D using a command like the following: you may build Panda3D using a command like the following:

View File

@ -1,7 +1,7 @@
# ClockDelta provides the ability to use clock synchronization for # ClockDelta provides the ability to use clock synchronization for
# distributed objects # distributed objects
from pandac.PandaModules import * from panda3d.core import ClockObject
from direct.directnotify import DirectNotifyGlobal from direct.directnotify import DirectNotifyGlobal
from direct.showbase import DirectObject from direct.showbase import DirectObject
import math import math

View File

@ -94,8 +94,8 @@ class DirectDialog(DirectFrame):
('text', '', None), ('text', '', None),
('text_align', TextNode.ALeft, None), ('text_align', TextNode.ALeft, None),
('text_scale', 0.06, None), ('text_scale', 0.06, None),
('image', None, None), ('image', DGG.getDefaultDialogGeom(), None),
('relief', DGG.RAISED, None), ('relief', DGG.getDefaultDialogRelief(), None),
('borderWidth', (0.01, 0.01), None), ('borderWidth', (0.01, 0.01), None),
('buttonTextList', [], DGG.INITOPT), ('buttonTextList', [], DGG.INITOPT),
('buttonGeomList', [], DGG.INITOPT), ('buttonGeomList', [], DGG.INITOPT),
@ -316,6 +316,7 @@ class DirectDialog(DirectFrame):
# reduce bottom by pad, button height and 2*button pad # reduce bottom by pad, button height and 2*button pad
b = min(b - self['midPad'] - bpad[1] - bHeight - bpad[1], b) - pad[1] b = min(b - self['midPad'] - bpad[1] - bHeight - bpad[1], b) - pad[1]
t = t + self['topPad'] + pad[1] t = t + self['topPad'] + pad[1]
if self['frameSize'] is None:
self['frameSize'] = (l, r, b, t) self['frameSize'] = (l, r, b, t)
self['image_scale'] = (r - l, 1, t - b) self['image_scale'] = (r - l, 1, t - b)
# Center frame about text and buttons # Center frame about text and buttons

View File

@ -14,6 +14,7 @@ defaultFontFunc = TextNode.getDefaultFont
defaultClickSound = None defaultClickSound = None
defaultRolloverSound = None defaultRolloverSound = None
defaultDialogGeom = None defaultDialogGeom = None
defaultDialogRelief = PGFrameStyle.TBevelOut
drawOrder = 100 drawOrder = 100
panel = None panel = None
@ -132,13 +133,16 @@ def setDefaultFontFunc(newFontFunc):
def getDefaultDialogGeom(): def getDefaultDialogGeom():
global defaultDialogGeom global defaultDialogGeom
if defaultDialogGeom == None:
defaultDialogGeom = loader.loadModel('models/gui/dialog_box_gui', okMissing = True)
return defaultDialogGeom return defaultDialogGeom
def setDefaultDialogGeom(newDialogGeom): def getDefaultDialogRelief():
global defaultDialogGeom global defaultDialogRelief
return defaultDialogRelief
def setDefaultDialogGeom(newDialogGeom, relief=None):
global defaultDialogGeom, defaultDialogRelief
defaultDialogGeom = newDialogGeom defaultDialogGeom = newDialogGeom
defaultDialogRelief = relief
def getDefaultDrawOrder(): def getDefaultDrawOrder():
return drawOrder return drawOrder

View File

@ -5,6 +5,7 @@ to build for as many platforms as possible. """
__all__ = ["Standalone", "Installer"] __all__ = ["Standalone", "Installer"]
import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct
import gzip
from io import BytesIO, TextIOWrapper from io import BytesIO, TextIOWrapper
from direct.directnotify.DirectNotifyGlobal import * from direct.directnotify.DirectNotifyGlobal import *
from direct.showbase.AppRunnerGlobal import appRunner from direct.showbase.AppRunnerGlobal import appRunner
@ -994,7 +995,7 @@ class Installer:
if self.licensefile: if self.licensefile:
shutil.copyfile(self.licensefile.toOsSpecific(), Filename(output, "Contents/Resources/License.txt").toOsSpecific()) shutil.copyfile(self.licensefile.toOsSpecific(), Filename(output, "Contents/Resources/License.txt").toOsSpecific())
pkginfo = open(Filename(output, "Contents/PkgInfo").toOsSpecific(), "w") pkginfo = open(Filename(output, "Contents/PkgInfo").toOsSpecific(), "w")
pkginfo.write("pkmkrpkg1") pkginfo.write("pmkrpkg1")
pkginfo.close() pkginfo.close()
pkginfo = open(Filename(output, "Contents/Resources/package_version").toOsSpecific(), "w") pkginfo = open(Filename(output, "Contents/Resources/package_version").toOsSpecific(), "w")
pkginfo.write("major: 1\nminor: 9") pkginfo.write("major: 1\nminor: 9")
@ -1079,18 +1080,18 @@ class Installer:
plist.write('</plist>\n') plist.write('</plist>\n')
plist.close() plist.close()
if hasattr(tarfile, "PAX_FORMAT"): # OS X El Capitan no longer accepts .pax archives - it must be a CPIO archive named .pax.
archive = tarfile.open(Filename(output, "Contents/Archive.pax.gz").toOsSpecific(), "w:gz", format = tarfile.PAX_FORMAT, tarinfo = TarInfoRootOSX) archive = gzip.open(Filename(output, "Contents/Archive.pax.gz").toOsSpecific(), 'wb')
else: self.__ino = 0
archive = tarfile.open(Filename(output, "Contents/Archive.pax.gz").toOsSpecific(), "w:gz", tarinfo = TarInfoRootOSX) self.__writeCPIO(archive, appfn, appname)
archive.add(appfn.toOsSpecific(), appname) archive.write(b"0707070000000000000000000000000000000000010000000000000000000001300000000000TRAILER!!!\0")
archive.close() archive.close()
# Put the .pkg into a zipfile # Put the .pkg into a zipfile
archive = Filename(output.getDirname(), "%s %s.zip" % (self.fullname, self.version)) zip_fn = Filename(output.getDirname(), "%s %s.pkg.zip" % (self.fullname, self.version))
dir = Filename(output.getDirname()) dir = Filename(output.getDirname())
dir.makeAbsolute() dir.makeAbsolute()
zip = zipfile.ZipFile(archive.toOsSpecific(), 'w') zip = zipfile.ZipFile(zip_fn.toOsSpecific(), 'w')
for root, dirs, files in self.os_walk(output.toOsSpecific()): for root, dirs, files in self.os_walk(output.toOsSpecific()):
for name in files: for name in files:
file = Filename.fromOsSpecific(os.path.join(root, name)) file = Filename.fromOsSpecific(os.path.join(root, name))
@ -1101,6 +1102,61 @@ class Installer:
return output return output
def __writeCPIO(self, archive, fn, name):
""" Adds the given fn under the given name to the CPIO archive. """
st = os.lstat(fn.toOsSpecific())
archive.write(b"070707") # magic
archive.write(b"000000") # dev
# Synthesize an inode number, different for each entry.
self.__ino += 1
archive.write("%06o" % (self.__ino))
# Determine based on the type which mode to write.
if os.path.islink(fn.toOsSpecific()):
archive.write("%06o" % (st.st_mode))
target = os.path.readlink(fn.toOsSpecific()).encode('utf-8')
size = len(target)
elif os.path.isdir(fn.toOsSpecific()):
archive.write(b"040755")
size = 0
elif not fn.getExtension(): # Binary file?
archive.write(b"100755")
size = st.st_size
else:
archive.write(b"100644")
size = st.st_size
archive.write("000000") # uid (root)
archive.write("000000") # gid (wheel)
archive.write("%06o" % (st.st_nlink))
archive.write("000000") # rdev
archive.write("%011o" % (st.st_mtime))
archive.write("%06o" % (len(name) + 1))
archive.write("%011o" % (size))
# Write the filename, plus terminating NUL byte.
archive.write(name.encode('utf-8'))
archive.write(b"\0")
# Copy the file data to the archive.
if os.path.islink(fn.toOsSpecific()):
archive.write(target)
elif size:
handle = open(fn.toOsSpecific(), 'rb')
data = handle.read(1024 * 1024)
while data:
archive.write(data)
data = handle.read(1024 * 1024)
handle.close()
# If this is a directory, recurse.
if os.path.isdir(fn.toOsSpecific()):
for child in os.listdir(fn.toOsSpecific()):
self.__writeCPIO(archive, Filename(fn, child), name + "/" + child)
def buildNSIS(self, output, platform): def buildNSIS(self, output, platform):
# Check if we have makensis first # Check if we have makensis first
makensis = None makensis = None

View File

@ -2427,7 +2427,7 @@ class Packager:
# Binary files that are considered uncompressible, and are # Binary files that are considered uncompressible, and are
# copied without compression. # copied without compression.
self.uncompressibleExtensions = [ 'mp3', 'ogg', 'wav', 'rml', 'rcss', 'otf' ] self.uncompressibleExtensions = [ 'mp3', 'ogg', 'ogv', 'wav', 'rml', 'rcss', 'otf' ]
# wav files are compressible, but p3openal_audio won't load # wav files are compressible, but p3openal_audio won't load
# them compressed. # them compressed.
# rml, rcss and otf files must be added here because # rml, rcss and otf files must be added here because
@ -3744,8 +3744,7 @@ class Packager:
self.__recurseDir(dirname, newDir, unprocessed = unprocessed) self.__recurseDir(dirname, newDir, unprocessed = unprocessed)
def __recurseDir(self, filename, newName, unprocessed = None, packageTree = None): def __recurseDir(self, filename, newName, unprocessed = None, packageTree = None):
dirList = vfs.scanDirectory(filename) if filename.isDirectory():
if dirList:
# It's a directory name. Recurse. # It's a directory name. Recurse.
prefix = newName prefix = newName
if prefix and prefix[-1] != '/': if prefix and prefix[-1] != '/':
@ -3753,6 +3752,7 @@ class Packager:
# First check if this is a Python package tree. If so, add it # First check if this is a Python package tree. If so, add it
# implicitly as a module. # implicitly as a module.
dirList = vfs.scanDirectory(filename)
for subfile in dirList: for subfile in dirList:
filename = subfile.getFilename() filename = subfile.getFilename()
if filename.getBasename() == '__init__.py': if filename.getBasename() == '__init__.py':
@ -3764,6 +3764,9 @@ class Packager:
self.__recurseDir(filename, prefix + filename.getBasename(), self.__recurseDir(filename, prefix + filename.getBasename(),
unprocessed = unprocessed) unprocessed = unprocessed)
return return
elif not filename.exists():
# It doesn't exist. Perhaps it's a virtual file. Ignore it.
return
# It's a file name. Add it. # It's a file name. Add it.
ext = filename.getExtension() ext = filename.getExtension()

View File

@ -103,8 +103,6 @@ class panda3d(package):
excludeModule('MySQLdb', '_mysql') excludeModule('MySQLdb', '_mysql')
excludeModule('xml', 'xml.parsers.expat', 'xml.sax')
# Most of the core Panda3D DLL's will be included implicitly due to # Most of the core Panda3D DLL's will be included implicitly due to
# being referenced by the above Python code. Here we name a few more # being referenced by the above Python code. Here we name a few more
# that are also needed, but aren't referenced by any code. Again, # that are also needed, but aren't referenced by any code. Again,

View File

@ -3,31 +3,107 @@
This minor release fixes some important regressions and bugs found This minor release fixes some important regressions and bugs found
in 1.9.0, but also introduces a few minor features. in 1.9.0, but also introduces a few minor features.
It also reintroduces the deployment pipeline that was absent from It also reintroduces the deployment tools that were absent from
the previous release. the previous release.
* Textures were not being scaled to power-of-2 in some cases The following issues were fixed:
* Fix various issues with shader inputs * SDK now properly installs in Mac OS X 10.11 "El Capitan"
* Bullet step function accidentally defaulted to step size of 0 * Windows 8.1+ no longer applies DPI virtualization to Panda window
* Use model-path for finding libRocket assets * Fix ffmpeg library load issue on Mac OS X
* Fix inconsistent behavior with non-power-of-2 textures in rocket
* Fix regression with memoryviews
* Fix symbol error when loading libp3ffmpeg on Mac OS X
* Fix issues running maya2egg on Mac OS X * Fix issues running maya2egg on Mac OS X
* PStats now tracks memory residency of graphics buffers * Fix compiler errors on different platforms
* Support wireframe and point rendering modes in OpenGL ES * Fix various rare crashes
* Add missing keys to libRocket keymap * Fix crashes on shutdown in threaded pipeline
* Fix low-level threading crash on ARM machines
* More reliably and robustly handle failures opening OpenAL device
* Textures were not being scaled to power-of-2 in some cases
* Correct scaling of normal vectors with flatten operation
* Correct positioning of viewing axis when showing lens frustum
* Add dpi-window-resize option to auto-resize window on DPI change
* Fix assertions when alpha-file-channel references unknown channel
* Use OpenGL-style vertex colors by default on non-Windows systems
* Default vertex column alignment is now 4 bytes
* Add PNMImage premultiply/unpremultiply methods.
* Fix incorrect parsing of numbers with exponents in Config.prc * Fix incorrect parsing of numbers with exponents in Config.prc
* Various performance optimizations
* Fix for reading URLs mounted via the virtual file system * Fix for reading URLs mounted via the virtual file system
* Improve GLSL error reporting
* Fix issue with model disappearing in rare cases with GLSL
* Fix shader generator memory leaks and runtime performance * Fix shader generator memory leaks and runtime performance
* Add M_confined mouse mode that keeps cursor in window * Fix shader generator scaling of binormals and tangents
* Expose _NET_WM_PID to window managers in X11 * Expose _NET_WM_PID to window managers in X11
* bam2egg supports collision sphere and plane solids * Fix a range of bugs in tinydisplay renderer.
* Add sample program demonstrating mouse modes * Don't error when setting lens far distance to infinity
* Allow passing custom lens to saveCubeMap/saveSphereMap
* Fix errors in saveCubeMap/saveSphereMap in threaded pipeline
* Fix DynamicTextFont.makeCopy()
* Make Texture memory size estimation more accurate
* Fix various window resizing issues
* Fix PandaSystem.getCompiler() value for clang (it reported gcc)
* x2egg no longer replaces face normals with vertex normals
* Include Eigen headers in Mac and Windows SDK
* Added geomipterrain-incorrect-normals setting, default=true
* DisplayInformation resolution list was missing on Windows
* Upgrade FMOD and Bullet versions on Windows and Mac OS X
* Various performance optimizations
* Fixed various other bugs not listed here.
Fixes and improvements for the runtime:
* Fix splash screen freezing in the X11 web plug-in
* pdeploy will now handle extracted files (eg. .ico and .cur)
* Added more options for customizing splash screen
* Fix missing xml and ast modules from morepy package
* Certificate dialog is now localized to various languages
* Fix packp3d error when Python file is not in a package
* Pass on failing exit status from packaged application
* Remove annoying ":Packager(warning): No such file" warning
* Fix issue installing pdeploy-generated .pkg on OS X 10.11
Fixes for the Python API:
* Fix mysterious and rare crash in tp_traverse
* Bullet step function accidentally defaulted to step size of 0
* Fix overflow of file offsets (eg. when seeking in huge files)
* Fix regression with memoryviews
* Fix hasattr/getattr of vector classes for invalid attributes
* Allow passing a long to methods accepting an int
* Fix crash when passing None to Filename constructor
* MouseWatcherGroup was erroneously not exposed in 1.9.0
* ShowBase no longer unmounts VFS when shutting down
* No longer requires setting PATH to import panda3d.*
* DirectDialog default geom is once again respected
* DirectDialog no longer overrides custom frameSize
* Fix WebcamVideo/MicrophoneAudio.getOptions() methods
Changes relating to the OpenGL renderer:
* Various performance improvements
* Fix point/line thickness setting
* Improve GLSL error reporting
* Fix Intel driver issues, particularly with geometry shaders
* Add more error checking for parameter types
* Integer shader inputs were not being converted to float properly
* Fix crash passing an undersized array to a GLSL shader input
* p3d_ColorScale et al may now be declared as vec3
* Fix flickering when using trans_model_to_apiview in Cg
* Support wireframe and point rendering modes in OpenGL ES
* Fix issue with model disappearing in rare cases with GLSL
* Fix ColorWriteAttrib not working as it should
* Allow deactivating PStats collectors for GPU timers
* Memory residency of graphics buffers now tracked by PStats
* Allow changing OpenGL coordinate system with gl-coordinate-system
Fixes for libRocket integration:
* libRocket did not work on Mac OS X in 1.9.0
* Fix inconsistent behavior with non-power-of-2 textures in rocket
* Use model-path for finding libRocket assets
* Add missing keys to libRocket keymap
* libRocket elements showed up white in tinydisplay
New features:
* Add -L (lighting) and -P (graphics pipe) pview options * Add -L (lighting) and -P (graphics pipe) pview options
* Add M_confined mouse mode that keeps cursor in window
* Add sample program demonstrating mouse modes
* bam2egg supports collision sphere and plane solids
* p3d_TransformTable GLSL input backported from 1.10 branch
* Add openal-device setting for selecting OpenAL audio output
* Add limited modification timestamp tracking for Ramdisk mounts
* Support for Autodesk Maya 2016
------------------------ RELEASE 1.9.0 ------------------------ ------------------------ RELEASE 1.9.0 ------------------------

View File

@ -327,7 +327,7 @@ def parseopts(args):
else: else:
PkgDisable("TOUCHINPUT") PkgDisable("TOUCHINPUT")
if clean_build: if clean_build and os.path.isdir(GetOutputDir()):
print("Deleting %s" % (GetOutputDir())) print("Deleting %s" % (GetOutputDir()))
shutil.rmtree(GetOutputDir()) shutil.rmtree(GetOutputDir())
@ -783,8 +783,6 @@ if (COMPILER=="GCC"):
rocket_libs = ("RocketCore", "RocketControls") rocket_libs = ("RocketCore", "RocketControls")
if (GetOptimize() <= 3): if (GetOptimize() <= 3):
rocket_libs += ("RocketDebugger",) rocket_libs += ("RocketDebugger",)
if (GetHost() != "darwin"):
# We use a statically linked libboost_python on OSX
rocket_libs += ("boost_python",) rocket_libs += ("boost_python",)
SmartPkgEnable("ROCKET", "", rocket_libs, "Rocket/Core.h") SmartPkgEnable("ROCKET", "", rocket_libs, "Rocket/Core.h")
@ -2762,9 +2760,15 @@ if tp_dir is not None:
dylibs = set() dylibs = set()
if GetTarget() == 'darwin': if GetTarget() == 'darwin':
# Make a list of all the dylibs we ship, to figure out whether we should use
# install_name_tool to correct the library reference to point to our copy.
for lib in glob.glob(tp_dir + "/*/lib/*.dylib"): for lib in glob.glob(tp_dir + "/*/lib/*.dylib"):
dylibs.add(os.path.basename(lib)) dylibs.add(os.path.basename(lib))
if not PkgSkip("PYTHON"):
for lib in glob.glob(tp_dir + "/*/lib/" + SDK["PYTHONVERSION"] + "/*.dylib"):
dylibs.add(os.path.basename(lib))
for pkg in PkgListGet(): for pkg in PkgListGet():
if PkgSkip(pkg): if PkgSkip(pkg):
continue continue
@ -2775,49 +2779,69 @@ if tp_dir is not None:
CopyAllFiles(GetOutputDir() + "/bin/", tp_pkg + "/bin/") CopyAllFiles(GetOutputDir() + "/bin/", tp_pkg + "/bin/")
if (PkgSkip("PYTHON")==0 and os.path.exists(tp_pkg + "/bin/" + SDK["PYTHONVERSION"])): if (PkgSkip("PYTHON")==0 and os.path.exists(tp_pkg + "/bin/" + SDK["PYTHONVERSION"])):
CopyAllFiles(GetOutputDir() + "/bin/", tp_pkg + "/bin/" + SDK["PYTHONVERSION"] + "/") CopyAllFiles(GetOutputDir() + "/bin/", tp_pkg + "/bin/" + SDK["PYTHONVERSION"] + "/")
else:
for tp_lib in glob.glob(tp_pkg + "/lib/*.so*"):
CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
if not PkgSkip("PYTHON"): elif GetTarget() == 'darwin':
for tp_lib in glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.so*")):
CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
if GetTarget() == 'darwin':
tp_libs = glob.glob(tp_pkg + "/lib/*.dylib") tp_libs = glob.glob(tp_pkg + "/lib/*.dylib")
if not PkgSkip("PYTHON"): if not PkgSkip("PYTHON"):
tp_libs += glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.dylib")) tp_libs += glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.dylib"))
tp_libs += glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.so"))
if pkg != 'PYTHON':
tp_libs += glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.py"))
for tp_lib in tp_libs: for tp_lib in tp_libs:
basename = os.path.basename(tp_lib) basename = os.path.basename(tp_lib)
if basename.endswith('.dylib'):
# It's a dynamic link library. Put it in the lib directory.
target = GetOutputDir() + "/lib/" + basename target = GetOutputDir() + "/lib/" + basename
dep_prefix = "@loader_path/../lib/"
lib_id = dep_prefix + basename
else:
# It's a Python module, like _rocketcore.so. Copy it to the root, because
# nowadays the 'lib' directory may no longer be on the PYTHONPATH.
target = GetOutputDir() + "/" + basename
dep_prefix = "@loader_path/lib/"
lib_id = basename
if not NeedsBuild([target], [tp_lib]): if not NeedsBuild([target], [tp_lib]):
continue continue
CopyFile(target, tp_lib) CopyFile(target, tp_lib)
if os.path.islink(target): if os.path.islink(target) or target.endswith('.py'):
continue continue
# Correct the inter-library dependencies so that the build is relocatable. # Correct the inter-library dependencies so that the build is relocatable.
oscmd('install_name_tool -id @loader_path/../lib/%s %s' % (basename, target)) oscmd('install_name_tool -id %s %s' % (lib_id, target))
oscmd("otool -L %s | grep .dylib > %s/tmp/otool-libs.txt" % (target, GetOutputDir()), True) oscmd("otool -L %s | grep .dylib > %s/tmp/otool-libs.txt" % (target, GetOutputDir()), True)
for line in open(GetOutputDir() + "/tmp/otool-libs.txt", "r"): for line in open(GetOutputDir() + "/tmp/otool-libs.txt", "r"):
line = line.strip() line = line.strip()
if not line or line.startswith('@loader_path/../lib/') or line.endswith(":"): if not line or line.startswith(dep_prefix) or line.endswith(":"):
continue continue
libdep = line.split(" ", 1)[0] libdep = line.split(" ", 1)[0]
dep_basename = os.path.basename(libdep) dep_basename = os.path.basename(libdep)
if dep_basename in dylibs: if dep_basename in dylibs:
oscmd("install_name_tool -change %s @loader_path/../lib/%s %s" % (libdep, dep_basename, target), True) oscmd("install_name_tool -change %s %s%s %s" % (libdep, dep_prefix, dep_basename, target), True)
JustBuilt([target], [tp_lib]) JustBuilt([target], [tp_lib])
for fwx in glob.glob(tp_pkg + "/*.framework"): for fwx in glob.glob(tp_pkg + "/*.framework"):
CopyTree(GetOutputDir() + "/Frameworks/" + os.path.basename(fwx), fwx) CopyTree(GetOutputDir() + "/Frameworks/" + os.path.basename(fwx), fwx)
else: # Linux / FreeBSD case.
for tp_lib in glob.glob(tp_pkg + "/lib/*.so*"):
CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
if not PkgSkip("PYTHON"):
for tp_lib in glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.so*")):
base = os.path.basename(tp_lib)
if base.startswith('lib'):
CopyFile(GetOutputDir() + "/lib/" + base, tp_lib)
else:
# It's a Python module, like _rocketcore.so.
CopyFile(GetOutputDir() + "/" + base, tp_lib)
if GetTarget() == 'windows': if GetTarget() == 'windows':
CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/") CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/")
if not PkgSkip("PYTHON"): if not PkgSkip("PYTHON"):
@ -2853,8 +2877,8 @@ if (PkgSkip("PYTHON")==0 and os.path.isdir(GetThirdpartyBase()+"/Pmw")):
ConditionalWriteFile(GetOutputDir()+'/include/ctl3d.h', '/* dummy file to make MAX happy */') ConditionalWriteFile(GetOutputDir()+'/include/ctl3d.h', '/* dummy file to make MAX happy */')
# Since Eigen is included by all sorts of core headers, as a convenience # Since Eigen is included by all sorts of core headers, as a convenience
# to C++ users on Windows, we include it in the Panda include directory. # to C++ users on Win and Mac, we include it in the Panda include directory.
if not PkgSkip("EIGEN") and GetTarget() == "windows" and GetThirdpartyDir(): if not PkgSkip("EIGEN") and GetTarget() in ("windows", "darwin") and GetThirdpartyDir():
CopyTree(GetOutputDir()+'/include/Eigen', GetThirdpartyDir()+'eigen/include/Eigen') CopyTree(GetOutputDir()+'/include/Eigen', GetThirdpartyDir()+'eigen/include/Eigen')
######################################################################## ########################################################################
@ -6799,7 +6823,6 @@ def MakeInstallerOSX():
if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg') if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg')
oscmd("mkdir -p dstroot/base/Developer/Panda3D/lib") oscmd("mkdir -p dstroot/base/Developer/Panda3D/lib")
oscmd("mkdir -p dstroot/base/Developer/Panda3D/panda3d")
oscmd("mkdir -p dstroot/base/Developer/Panda3D/etc") oscmd("mkdir -p dstroot/base/Developer/Panda3D/etc")
oscmd("cp %s/etc/Config.prc dstroot/base/Developer/Panda3D/etc/Config.prc" % GetOutputDir()) oscmd("cp %s/etc/Config.prc dstroot/base/Developer/Panda3D/etc/Config.prc" % GetOutputDir())
oscmd("cp %s/etc/Confauto.prc dstroot/base/Developer/Panda3D/etc/Confauto.prc" % GetOutputDir()) oscmd("cp %s/etc/Confauto.prc dstroot/base/Developer/Panda3D/etc/Confauto.prc" % GetOutputDir())
@ -6810,43 +6833,42 @@ def MakeInstallerOSX():
if os.path.isdir(GetOutputDir()+"/plugins"): if os.path.isdir(GetOutputDir()+"/plugins"):
oscmd("cp -R %s/plugins dstroot/base/Developer/Panda3D/plugins" % GetOutputDir()) oscmd("cp -R %s/plugins dstroot/base/Developer/Panda3D/plugins" % GetOutputDir())
install_libs = [] # Libraries that shouldn't be in base, but are instead in other modules.
for base in os.listdir(GetOutputDir()+"/lib"): no_base_libs = ['libp3ffmpeg', 'libp3fmod_audio', 'libfmodex', 'libfmodexL']
if (not base.endswith(".a")):
install_libs.append("lib/"+base)
for base in os.listdir(GetOutputDir()+"/panda3d"):
if (not base.endswith(".a")):
install_libs.append("panda3d/"+base)
for base in install_libs: for base in os.listdir(GetOutputDir()+"/lib"):
libname = "dstroot/base/Developer/Panda3D/" + base if not base.endswith(".a") and base.split('.')[0] not in no_base_libs:
libname = "dstroot/base/Developer/Panda3D/lib/" + base
# We really need to specify -R in order not to follow symlinks # We really need to specify -R in order not to follow symlinks
# On OSX, just specifying -P is not enough to do that. # On OSX, just specifying -P is not enough to do that.
oscmd("cp -R -P " + GetOutputDir() + "/" + base + " " + libname) oscmd("cp -R -P " + GetOutputDir() + "/lib/" + base + " " + libname)
oscmd("mkdir -p dstroot/tools/Developer/Tools/Panda3D") oscmd("mkdir -p dstroot/tools/Developer/Panda3D/bin")
oscmd("mkdir -p dstroot/tools/Developer/Panda3D") oscmd("mkdir -p dstroot/tools/Developer/Tools")
oscmd("ln -s ../Panda3D/bin dstroot/tools/Developer/Tools/Panda3D")
oscmd("mkdir -p dstroot/tools/etc/paths.d") oscmd("mkdir -p dstroot/tools/etc/paths.d")
# Trailing newline is important, works around a bug in OSX # Trailing newline is important, works around a bug in OSX
WriteFile("dstroot/tools/etc/paths.d/Panda3D", "/Developer/Tools/Panda3D\n") WriteFile("dstroot/tools/etc/paths.d/Panda3D", "/Developer/Panda3D/bin\n")
oscmd("mkdir -p dstroot/tools/usr/local/share/man/man1") oscmd("mkdir -p dstroot/tools/usr/local/share/man/man1")
oscmd("cp doc/man/*.1 dstroot/tools/usr/local/share/man/man1/") oscmd("cp doc/man/*.1 dstroot/tools/usr/local/share/man/man1/")
for base in os.listdir(GetOutputDir()+"/bin"): for base in os.listdir(GetOutputDir()+"/bin"):
binname = "dstroot/tools/Developer/Tools/Panda3D/" + base binname = "dstroot/tools/Developer/Panda3D/bin/" + base
# OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird. # OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird.
oscmd("cp -R " + GetOutputDir() + "/bin/" + base + " " + binname) oscmd("cp -R " + GetOutputDir() + "/bin/" + base + " " + binname)
if PkgSkip("PYTHON")==0: if PkgSkip("PYTHON")==0:
PV = SDK["PYTHONVERSION"].replace("python", "") PV = SDK["PYTHONVERSION"].replace("python", "")
oscmd("mkdir -p dstroot/pythoncode/usr/local/bin") oscmd("mkdir -p dstroot/pythoncode/usr/local/bin")
oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D") oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/panda3d")
oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV) oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV)
WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D") WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D")
oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir()) oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir())
oscmd("cp -R %s/direct dstroot/pythoncode/Developer/Panda3D/direct" % GetOutputDir()) oscmd("cp -R %s/direct dstroot/pythoncode/Developer/Panda3D/direct" % GetOutputDir())
oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % SDK["PYTHONEXEC"]) oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % SDK["PYTHONEXEC"])
oscmd("cp -R %s/*.so dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir())
oscmd("cp -R %s/*.py dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir())
if os.path.isdir(GetOutputDir()+"/Pmw"): if os.path.isdir(GetOutputDir()+"/Pmw"):
oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir()) oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir())
compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw") compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw")
@ -6855,6 +6877,26 @@ def MakeInstallerOSX():
if ((base != "extensions") and (base != "extensions_native")): if ((base != "extensions") and (base != "extensions_native")):
compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/direct/"+base) compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/direct/"+base)
for base in os.listdir(GetOutputDir()+"/panda3d"):
if base.endswith('.py') or base.endswith('.so'):
libname = "dstroot/pythoncode/Developer/Panda3D/panda3d/" + base
# We really need to specify -R in order not to follow symlinks
# On OSX, just specifying -P is not enough to do that.
oscmd("cp -R -P " + GetOutputDir() + "/panda3d/" + base + " " + libname)
if not PkgSkip("FFMPEG"):
oscmd("mkdir -p dstroot/ffmpeg/Developer/Panda3D/lib")
oscmd("cp -R %s/lib/libp3ffmpeg.* dstroot/ffmpeg/Developer/Panda3D/lib/" % GetOutputDir())
#if not PkgSkip("OPENAL"):
# oscmd("mkdir -p dstroot/openal/Developer/Panda3D/lib")
# oscmd("cp -R %s/lib/libp3openal_audio.* dstroot/openal/Developer/Panda3D/lib/" % GetOutputDir())
if not PkgSkip("FMODEX"):
oscmd("mkdir -p dstroot/fmodex/Developer/Panda3D/lib")
oscmd("cp -R %s/lib/libp3fmod_audio.* dstroot/fmodex/Developer/Panda3D/lib/" % GetOutputDir())
oscmd("cp -R %s/lib/libfmodex* dstroot/fmodex/Developer/Panda3D/lib/" % GetOutputDir())
oscmd("mkdir -p dstroot/headers/Developer/Panda3D") oscmd("mkdir -p dstroot/headers/Developer/Panda3D")
oscmd("cp -R %s/include dstroot/headers/Developer/Panda3D/include" % GetOutputDir()) oscmd("cp -R %s/include dstroot/headers/Developer/Panda3D/include" % GetOutputDir())
@ -6873,7 +6915,10 @@ def MakeInstallerOSX():
oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Resources/en.lproj/") oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Resources/en.lproj/")
pkgs = ["base", "tools", "headers"] pkgs = ["base", "tools", "headers"]
if PkgSkip("PYTHON")==0: pkgs.append("pythoncode") if not PkgSkip("PYTHON"): pkgs.append("pythoncode")
if not PkgSkip("FFMPEG"): pkgs.append("ffmpeg")
#if not PkgSkip("OPENAL"): pkgs.append("openal")
if not PkgSkip("FMODEX"): pkgs.append("fmodex")
if os.path.isdir("samples"): pkgs.append("samples") if os.path.isdir("samples"): pkgs.append("samples")
for pkg in pkgs: for pkg in pkgs:
identifier = "org.panda3d.panda3d.%s.pkg" % pkg identifier = "org.panda3d.panda3d.%s.pkg" % pkg
@ -6918,38 +6963,51 @@ def MakeInstallerOSX():
dist.write(' <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>\n') dist.write(' <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>\n')
dist.write(' <license language="en" mime-type="text/plain">%s</license>\n' % ReadFile("doc/LICENSE")) dist.write(' <license language="en" mime-type="text/plain">%s</license>\n' % ReadFile("doc/LICENSE"))
dist.write(' <choices-outline>\n') dist.write(' <choices-outline>\n')
dist.write(' <line choice="base"/>\n') for pkg in pkgs:
dist.write(' <line choice="tools"/>\n') dist.write(' <line choice="%s"/>\n' % (pkg))
if PkgSkip("PYTHON")==0:
dist.write(' <line choice="pythoncode"/>\n')
if os.path.isdir("samples"):
dist.write(' <line choice="samples"/>\n')
dist.write(' <line choice="headers"/>\n')
dist.write(' </choices-outline>\n') dist.write(' </choices-outline>\n')
dist.write(' <choice id="base" title="Panda3D Base Installation" description="This package contains the Panda3D libraries, configuration files and models/textures that are needed to use Panda3D. Location: /Developer/Panda3D/" start_enabled="false">\n') dist.write(' <choice id="base" title="Panda3D Base Installation" description="This package contains the Panda3D libraries, configuration files and models/textures that are needed to use Panda3D. Location: /Developer/Panda3D/" start_enabled="false">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.base.pkg"/>\n') dist.write(' <pkg-ref id="org.panda3d.panda3d.base.pkg"/>\n')
dist.write(' </choice>\n') dist.write(' </choice>\n')
dist.write(' <choice id="tools" title="Tools" tooltip="Useful tools and model converters to help with Panda3D development" description="This package contains the various utilities that ship with Panda3D, including packaging tools, model converters, and many more. Location: /Developer/Tools/Panda3D/">\n') dist.write(' <choice id="tools" title="Tools" tooltip="Useful tools and model converters to help with Panda3D development" description="This package contains the various utilities that ship with Panda3D, including packaging tools, model converters, and many more. Location: /Developer/Panda3D/bin/">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.tools.pkg"/>\n') dist.write(' <pkg-ref id="org.panda3d.panda3d.tools.pkg"/>\n')
dist.write(' </choice>\n') dist.write(' </choice>\n')
if PkgSkip("PYTHON")==0:
dist.write(' <choice id="pythoncode" title="Python Code" tooltip="Code you\'ll need for Python development" description="This package contains the \'direct\', \'pandac\' and \'panda3d\' python packages that are needed to do Python development with Panda3D. Location: /Developer/Panda3D/">\n') if not PkgSkip("PYTHON"):
dist.write(' <choice id="pythoncode" title="Python Support" tooltip="Python bindings for the Panda3D libraries" description="This package contains the \'direct\', \'pandac\' and \'panda3d\' python packages that are needed to do Python development with Panda3D. Location: /Developer/Panda3D/">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg"/>\n') dist.write(' <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg"/>\n')
dist.write(' </choice>\n') dist.write(' </choice>\n')
if not PkgSkip("FFMPEG"):
dist.write(' <choice id="ffmpeg" title="FFMpeg Plug-In" tooltip="FFMpeg video and audio decoding plug-in" description="This package contains the FFMpeg plug-in, which is used for decoding video and audio files with OpenAL.')
if PkgSkip("VORBIS"):
dist.write(' It is not required for loading .wav files, which Panda3D can read out of the box.">\n')
else:
dist.write(' It is not required for loading .wav or .ogg files, which Panda3D can read out of the box.">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.ffmpeg.pkg"/>\n')
dist.write(' </choice>\n')
#if not PkgSkip("OPENAL"):
# dist.write(' <choice id="openal" title="OpenAL Audio Plug-In" tooltip="OpenAL audio output plug-in" description="This package contains the OpenAL audio plug-in, which is an open-source library for playing sounds.">\n')
# dist.write(' <pkg-ref id="org.panda3d.panda3d.openal.pkg"/>\n')
# dist.write(' </choice>\n')
if not PkgSkip("FMODEX"):
dist.write(' <choice id="fmodex" title="FMOD Ex Plug-In" tooltip="FMOD Ex audio output plug-in" description="This package contains the FMOD Ex audio plug-in, which is a commercial library for playing sounds. It is an optional component as Panda3D can use the open-source alternative OpenAL instead.">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.fmodex.pkg"/>\n')
dist.write(' </choice>\n')
if os.path.isdir("samples"): if os.path.isdir("samples"):
dist.write(' <choice id="samples" title="Sample Programs" tooltip="Python sample programs that use Panda3D" description="This package contains the Python sample programs that can help you with learning how to use Panda3D. Location: /Developer/Examples/Panda3D/">\n') dist.write(' <choice id="samples" title="Sample Programs" tooltip="Python sample programs that use Panda3D" description="This package contains the Python sample programs that can help you with learning how to use Panda3D. Location: /Developer/Examples/Panda3D/">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.samples.pkg"/>\n') dist.write(' <pkg-ref id="org.panda3d.panda3d.samples.pkg"/>\n')
dist.write(' </choice>\n') dist.write(' </choice>\n')
dist.write(' <choice id="headers" title="C++ Header Files" tooltip="Header files for C++ development with Panda3D" description="This package contains the C++ header files that are needed in order to do C++ development with Panda3D. You don\'t need this if you want to develop in Python. Location: /Developer/Panda3D/include/" start_selected="false">\n') dist.write(' <choice id="headers" title="C++ Header Files" tooltip="Header files for C++ development with Panda3D" description="This package contains the C++ header files that are needed in order to do C++ development with Panda3D. You don\'t need this if you want to develop in Python. Location: /Developer/Panda3D/include/" start_selected="false">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.headers.pkg"/>\n') dist.write(' <pkg-ref id="org.panda3d.panda3d.headers.pkg"/>\n')
dist.write(' </choice>\n') dist.write(' </choice>\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.base.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/base.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/base") // 1024)) for pkg in pkgs:
dist.write(' <pkg-ref id="org.panda3d.panda3d.tools.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/tools.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/tools") // 1024)) size = GetDirectorySize("dstroot/" + pkg) // 1024
if PkgSkip("PYTHON")==0: dist.write(' <pkg-ref id="org.panda3d.panda3d.%s.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/%s.pkg</pkg-ref>\n' % (pkg, size, pkg))
dist.write(' <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/pythoncode.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/pythoncode") // 1024))
if os.path.isdir("samples"):
dist.write(' <pkg-ref id="org.panda3d.panda3d.samples.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/samples.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/samples") // 1024))
dist.write(' <pkg-ref id="org.panda3d.panda3d.headers.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/headers.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/headers") // 1024))
dist.write('</installer-script>\n') dist.write('</installer-script>\n')
dist.close() dist.close()

View File

@ -2546,6 +2546,10 @@ def SetupBuildEnvironment(compiler):
dyldpath.insert(0, os.path.join(builtdir, 'lib')) dyldpath.insert(0, os.path.join(builtdir, 'lib'))
os.environ["DYLD_LIBRARY_PATH"] = os.pathsep.join(dyldpath) os.environ["DYLD_LIBRARY_PATH"] = os.pathsep.join(dyldpath)
# OS X 10.11 removed DYLD_LIBRARY_PATH, but we still need to pass
# on our lib directory to ppackage, so add it to PATH instead.
os.environ["PATH"] = os.path.join(builtdir, 'lib') + ':' + os.environ.get("PATH", "")
# Workaround around compile issue on PCBSD # Workaround around compile issue on PCBSD
if (os.path.exists("/usr/PCBSD")): if (os.path.exists("/usr/PCBSD")):
os.environ["LD_LIBRARY_PATH"] += os.pathsep + "/usr/PCBSD/local/lib" os.environ["LD_LIBRARY_PATH"] += os.pathsep + "/usr/PCBSD/local/lib"
@ -2563,8 +2567,12 @@ def CopyFile(dstfile, srcfile):
if NeedsBuild([dstfile], [srcfile]): if NeedsBuild([dstfile], [srcfile]):
if os.path.islink(srcfile): if os.path.islink(srcfile):
# Preserve symlinks # Preserve symlinks
if os.path.exists(dstfile): if os.path.isfile(dstfile) or os.path.islink(dstfile):
print("Removing file %s" % (dstfile))
os.unlink(dstfile) os.unlink(dstfile)
elif os.path.isdir(dstfile):
print("Removing directory %s" % (dstfile))
shutil.rmtree(dstfile)
os.symlink(os.readlink(srcfile), dstfile) os.symlink(os.readlink(srcfile), dstfile)
else: else:
WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) WriteBinaryFile(dstfile, ReadBinaryFile(srcfile))
@ -2595,24 +2603,37 @@ def CopyAllJavaSources(dir, skip=[]):
JustBuilt([dstfile], [srcfile]) JustBuilt([dstfile], [srcfile])
def CopyTree(dstdir, srcdir, omitVCS=True): def CopyTree(dstdir, srcdir, omitVCS=True):
if (os.path.isdir(dstdir)): if os.path.isdir(dstdir):
for entry in os.listdir(srcdir): source_entries = os.listdir(srcdir)
for entry in source_entries:
srcpth = os.path.join(srcdir, entry) srcpth = os.path.join(srcdir, entry)
dstpth = os.path.join(dstdir, entry) dstpth = os.path.join(dstdir, entry)
if (os.path.isfile(srcpth)):
if os.path.islink(srcpth) or os.path.isfile(srcpth):
if not omitVCS or entry not in VCS_FILES: if not omitVCS or entry not in VCS_FILES:
CopyFile(dstpth, srcpth) CopyFile(dstpth, srcpth)
else: else:
if not omitVCS or entry not in VCS_DIRS: if not omitVCS or entry not in VCS_DIRS:
CopyTree(dstpth, srcpth) CopyTree(dstpth, srcpth)
# Delete files in dstdir that are not in srcdir.
for entry in os.listdir(dstdir):
if entry not in source_entries:
path = os.path.join(dstdir, entry)
if os.path.islink(path) or os.path.isfile(path):
os.remove(path)
elif os.path.isdir(path):
shutil.rmtree(path)
else: else:
if GetHost() == 'windows': if GetHost() == 'windows':
srcdir = srcdir.replace('/', '\\') srcdir = srcdir.replace('/', '\\')
dstdir = dstdir.replace('/', '\\') dstdir = dstdir.replace('/', '\\')
cmd = 'xcopy /I/Y/E/Q "' + srcdir + '" "' + dstdir + '"' cmd = 'xcopy /I/Y/E/Q "' + srcdir + '" "' + dstdir + '"'
else:
cmd = 'cp -R -f ' + srcdir + ' ' + dstdir
oscmd(cmd) oscmd(cmd)
else:
if subprocess.call(['cp', '-R', '-f', srcdir, dstdir]) != 0:
exit("Copy failed.")
if omitVCS: if omitVCS:
DeleteVCS(dstdir) DeleteVCS(dstdir)

View File

@ -27,6 +27,12 @@ ConfigureFn(config_openalAudio) {
init_libOpenALAudio(); init_libOpenALAudio();
} }
ConfigVariableString openal_device
("openal-device", "",
PRC_DESC("Specify the OpenAL device string for audio playback (no quotes). If this "
"is not specified, the OpenAL default device is used."));
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: init_libOpenALAudio // Function: init_libOpenALAudio
// Description: Initializes the library. This must be called at // Description: Initializes the library. This must be called at

View File

@ -27,4 +27,6 @@ NotifyCategoryDecl(openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO);
extern EXPCL_OPENAL_AUDIO void init_libOpenALAudio(); extern EXPCL_OPENAL_AUDIO void init_libOpenALAudio();
extern "C" EXPCL_OPENAL_AUDIO Create_AudioManager_proc *get_audio_manager_func_openal_audio(); extern "C" EXPCL_OPENAL_AUDIO Create_AudioManager_proc *get_audio_manager_func_openal_audio();
extern ConfigVariableString openal_device;
#endif // CONFIG_OPENALAUDIO_H #endif // CONFIG_OPENALAUDIO_H

View File

@ -19,6 +19,7 @@
#include "config_audio.h" #include "config_audio.h"
#include "config_util.h" #include "config_util.h"
#include "config_express.h" #include "config_express.h"
#include "config_openalAudio.h"
#include "openalAudioManager.h" #include "openalAudioManager.h"
#include "openalAudioSound.h" #include "openalAudioSound.h"
#include "virtualFileSystem.h" #include "virtualFileSystem.h"
@ -27,6 +28,14 @@
#include <algorithm> #include <algorithm>
#ifndef ALC_DEFAULT_ALL_DEVICES_SPECIFIER
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
#endif
#ifndef ALC_ALL_DEVICES_SPECIFIER
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
#endif
TypeHandle OpenALAudioManager::_type_handle; TypeHandle OpenALAudioManager::_type_handle;
ReMutex OpenALAudioManager::_lock; ReMutex OpenALAudioManager::_lock;
@ -116,12 +125,41 @@ OpenALAudioManager() {
_forward_up[5] = 0; _forward_up[5] = 0;
// Initialization // Initialization
audio_cat.init();
if (_active_managers == 0 || !_openal_active) { if (_active_managers == 0 || !_openal_active) {
_device = alcOpenDevice(NULL); // select the "preferred device" _device = NULL;
if (!_device) { string dev_name = select_audio_device();
// this is a unique kind of error
audio_error("OpenALAudioManager: alcOpenDevice(NULL): ALC couldn't open device"); if (!dev_name.empty()) {
// Open a specific device by name.
audio_cat.info() << "Using OpenAL device " << dev_name << "\n";
_device = alcOpenDevice(dev_name.c_str());
if (_device == NULL) {
audio_cat.error()
<< "Couldn't open OpenAL device \"" << dev_name << "\", falling back to default device\n";
}
} else { } else {
audio_cat.info() << "Using default OpenAL device\n";
}
if (_device == NULL) {
// Open the default device.
_device = alcOpenDevice(NULL);
if (_device == NULL && dev_name != "OpenAL Soft") {
// Try the OpenAL Soft driver instead, which is fairly reliable.
_device = alcOpenDevice("OpenAL Soft");
if (_device == NULL) {
audio_cat.error()
<< "Couldn't open default OpenAL device\n";
}
}
}
if (_device != NULL) {
// We managed to get a device open.
alcGetError(_device); // clear errors alcGetError(_device); // clear errors
_context = alcCreateContext(_device, NULL); _context = alcCreateContext(_device, NULL);
alc_audio_errcheck("alcCreateContext(_device, NULL)", _device); alc_audio_errcheck("alcCreateContext(_device, NULL)", _device);
@ -130,6 +168,7 @@ OpenALAudioManager() {
} }
} }
} }
// We increment _active_managers regardless of possible errors above. // We increment _active_managers regardless of possible errors above.
// The shutdown call will do the right thing when it's called, // The shutdown call will do the right thing when it's called,
// either way. // either way.
@ -150,15 +189,15 @@ OpenALAudioManager() {
audio_3d_set_drop_off_factor(audio_drop_off_factor); audio_3d_set_drop_off_factor(audio_drop_off_factor);
if (audio_cat.is_debug()) { if (audio_cat.is_debug()) {
audio_cat->debug() audio_cat.debug()
<< "ALC_DEVICE_SPECIFIER:" << alcGetString(_device, ALC_DEVICE_SPECIFIER) << endl; << "ALC_DEVICE_SPECIFIER:" << alcGetString(_device, ALC_DEVICE_SPECIFIER) << endl;
} }
} }
if (audio_cat.is_debug()) { if (audio_cat.is_debug()) {
audio_cat->debug() << "AL_RENDERER:" << alGetString(AL_RENDERER) << endl; audio_cat.debug() << "AL_RENDERER:" << alGetString(AL_RENDERER) << endl;
audio_cat->debug() << "AL_VENDOR:" << alGetString(AL_VENDOR) << endl; audio_cat.debug() << "AL_VENDOR:" << alGetString(AL_VENDOR) << endl;
audio_cat->debug() << "AL_VERSION:" << alGetString(AL_VERSION) << endl; audio_cat.debug() << "AL_VERSION:" << alGetString(AL_VERSION) << endl;
} }
} }
@ -212,6 +251,82 @@ is_valid() {
return _is_valid; return _is_valid;
} }
////////////////////////////////////////////////////////////////////
// Function: OpenALAudioManager::select_audio_device
// Access: Private
// Description: Enumerate the audio devices, selecting the one that
// is most appropriate or has been selected by the user.
////////////////////////////////////////////////////////////////////
string OpenALAudioManager::
select_audio_device() {
string selected_device = openal_device;
const char *devices = NULL;
// This extension gives us all audio paths on all drivers.
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE) {
string default_device = alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
devices = (const char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
if (devices) {
audio_cat.debug() << "All OpenAL devices:\n";
while (*devices) {
string device(devices);
devices += device.size() + 1;
if (audio_cat.is_debug()) {
if (device == selected_device) {
audio_cat.debug() << " " << device << " [selected]\n";
} else if (device == default_device) {
audio_cat.debug() << " " << device << " [default]\n";
} else {
audio_cat.debug() << " " << device << "\n";
}
}
}
}
} else {
audio_cat.debug() << "ALC_ENUMERATE_ALL_EXT not supported\n";
}
// This extension just gives us generic driver names, like "OpenAL Soft"
// and "Generic Software", rather than individual outputs.
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) {
string default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
devices = (const char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
if (devices) {
audio_cat.debug() << "OpenAL drivers:\n";
while (*devices) {
string device(devices);
devices += device.size() + 1;
if (selected_device.empty() && device == "OpenAL Soft" &&
default_device == "Generic Software") {
// Prefer OpenAL Soft over the buggy Generic Software driver.
selected_device = "OpenAL Soft";
}
if (audio_cat.is_debug()) {
if (device == selected_device) {
audio_cat.debug() << " " << device << " [selected]\n";
} else if (device == default_device) {
audio_cat.debug() << " " << device << " [default]\n";
} else {
audio_cat.debug() << " " << device << "\n";
}
}
}
}
} else {
audio_cat.debug() << "ALC_ENUMERATION_EXT not supported\n";
}
return selected_device;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: OpenALAudioManager::make_current // Function: OpenALAudioManager::make_current
// Access: Private // Access: Private

View File

@ -116,6 +116,8 @@ class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager {
virtual void update(); virtual void update();
private: private:
string select_audio_device();
void make_current() const; void make_current() const;
bool can_use_audio(MovieAudioCursor *source); bool can_use_audio(MovieAudioCursor *source);

View File

@ -177,7 +177,7 @@ set_stop_erp(const LVecBase3 &erp) {
INLINE int BulletTranslationalLimitMotor:: INLINE int BulletTranslationalLimitMotor::
get_current_limit(int axis) const { get_current_limit(int axis) const {
nassertr((0 <- axis) && (axis <=2), false); nassertr((0 <= axis) && (axis <= 2), false);
return _motor.m_currentLimit[axis]; return _motor.m_currentLimit[axis];
} }

View File

@ -798,16 +798,20 @@ set_properties_now(WindowProperties &properties) {
int height = properties.get_y_size(); int height = properties.get_y_size();
if (!_properties.get_fullscreen()) { if (!_properties.get_fullscreen()) {
_properties.set_size(width, height);
if (_window != nil) { if (_window != nil) {
[_window setContentSize:NSMakeSize(width, height)]; [_window setContentSize:NSMakeSize(width, height)];
} }
[_view setFrameSize:NSMakeSize(width, height)]; [_view setFrameSize:NSMakeSize(width, height)];
if (cocoadisplay_cat.is_debug()) {
cocoadisplay_cat.debug() cocoadisplay_cat.debug()
<< "Setting size to " << width << ", " << height << "\n"; << "Setting size to " << width << ", " << height << "\n";
}
_context_needs_update = true; // Cocoa doesn't send an event, and the other
// resize-window handlers will do nothing once the properties
// have been changed, so do this now
handle_resize_event();
properties.clear_size(); properties.clear_size();
} else { } else {
@ -1022,6 +1026,23 @@ set_properties_now(WindowProperties &properties) {
} }
properties.clear_z_order(); properties.clear_z_order();
} }
if (properties.has_mouse_mode()) {
switch (properties.get_mouse_mode()) {
case WindowProperties::M_absolute:
case WindowProperties::M_confined: // confined is maintained in mouse move event
CGAssociateMouseAndMouseCursorPosition(true);
_properties.set_mouse_mode(properties.get_mouse_mode());
properties.clear_mouse_mode();
break;
case WindowProperties::M_relative:
CGAssociateMouseAndMouseCursorPosition(false);
_properties.set_mouse_mode(properties.get_mouse_mode());
properties.clear_mouse_mode();
break;
}
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1670,6 +1691,8 @@ handle_mouse_button_event(int button, bool down) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CocoaGraphicsWindow:: void CocoaGraphicsWindow::
handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) { handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
double nx, ny;
if (absolute) { if (absolute) {
if (cocoadisplay_cat.is_spam()) { if (cocoadisplay_cat.is_spam()) {
if (in_window != _input_devices[0].get_pointer().get_in_window()) { if (in_window != _input_devices[0].get_pointer().get_in_window()) {
@ -1682,15 +1705,40 @@ handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
} }
// Strangely enough, in Cocoa, mouse Y coordinates are 1-based. // Strangely enough, in Cocoa, mouse Y coordinates are 1-based.
_input_devices[0].set_pointer(in_window, x, y - 1, nx = x;
ClockObject::get_global_clock()->get_frame_time()); ny = y - 1;
} else { } else {
// We received deltas, so add it to the current mouse position. // We received deltas, so add it to the current mouse position.
MouseData md = _input_devices[0].get_pointer(); MouseData md = _input_devices[0].get_pointer();
_input_devices[0].set_pointer_in_window(md.get_x() + x, md.get_y() + y); nx = md.get_x() + x;
ny = md.get_y() + y;
} }
if (_properties.get_mouse_mode() == WindowProperties::M_confined
&& !in_window) {
CGPoint point;
nx = std::max(0., std::min((double) get_x_size() - 1, nx));
ny = std::max(0., std::min((double) get_y_size() - 1, ny));
if (_properties.get_fullscreen()) {
point = CGPointMake(nx, ny + 1);
} else {
point = CGPointMake(nx + _properties.get_x_origin(),
ny + _properties.get_y_origin() + 1);
}
if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
in_window = true;
} else {
cocoadisplay_cat.warning() << "Failed to return mouse pointer to window\n";
}
}
_input_devices[0].set_pointer(in_window, nx, ny,
ClockObject::get_global_clock()->get_frame_time());
if (in_window != _mouse_hidden && _properties.get_cursor_hidden()) { if (in_window != _mouse_hidden && _properties.get_cursor_hidden()) {
// Hide the cursor if the mouse enters the window, // Hide the cursor if the mouse enters the window,
// and unhide it when the mouse leaves the window. // and unhide it when the mouse leaves the window.

View File

@ -45,9 +45,11 @@
- (void) drawRect:(NSRect)dirtyRect { - (void) drawRect:(NSRect)dirtyRect {
// Do nothing. We draw from another thread. // Do nothing. We draw from another thread.
if (cocoadisplay_cat.is_spam()) {
cocoadisplay_cat.spam() cocoadisplay_cat.spam()
<< "drawRect was called.\n"; << "drawRect was called.\n";
} }
}
- (void) finalize { - (void) finalize {
_graphicsWindow->handle_close_event(); _graphicsWindow->handle_close_event();
@ -116,7 +118,10 @@
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
BOOL inside = [self mouse:loc inRect:[self bounds]]; BOOL inside = [self mouse:loc inRect:[self bounds]];
if (_graphicsWindow->get_properties().get_mouse_mode() == WindowProperties::M_relative) { // the correlation between mouse deltas and location
// are "debounced" apparently, so send deltas for both
// relative and confined modes
if (_graphicsWindow->get_properties().get_mouse_mode() != WindowProperties::M_absolute) {
_graphicsWindow->handle_mouse_moved_event(inside, [event deltaX], [event deltaY], false); _graphicsWindow->handle_mouse_moved_event(inside, [event deltaX], [event deltaY], false);
} else { } else {
_graphicsWindow->handle_mouse_moved_event(inside, loc.x, loc.y, true); _graphicsWindow->handle_mouse_moved_event(inside, loc.x, loc.y, true);

View File

@ -2064,6 +2064,25 @@ set_properties_now(WindowProperties &properties) {
properties.clear_minimized(); properties.clear_minimized();
} }
if (properties.has_mouse_mode()) {
switch (properties.get_mouse_mode()) {
case WindowProperties::M_absolute:
CGAssociateMouseAndMouseCursorPosition(true);
_properties.set_mouse_mode(WindowProperties::M_absolute);
properties.clear_mouse_mode();
break;
case WindowProperties::M_relative:
CGAssociateMouseAndMouseCursorPosition(false);
_properties.set_mouse_mode(WindowProperties::M_relative);
properties.clear_mouse_mode();
break;
case WindowProperties::M_confined:
break;
}
}
if (osxdisplay_cat.is_debug()) { if (osxdisplay_cat.is_debug()) {
osxdisplay_cat.debug() osxdisplay_cat.debug()
<< "set_properties_now Out....." << _properties << "\n"; << "set_properties_now Out....." << _properties << "\n";

View File

@ -53,6 +53,10 @@ init_librocket() {
RocketInputHandler::init_type(); RocketInputHandler::init_type();
RocketRegion::init_type(); RocketRegion::init_type();
if (rocket_cat->is_debug()) {
rocket_cat->debug() << "Initializing libRocket library.\n";
}
RocketFileInterface* fi = new RocketFileInterface; RocketFileInterface* fi = new RocketFileInterface;
Rocket::Core::SetFileInterface(fi); Rocket::Core::SetFileInterface(fi);
@ -61,6 +65,10 @@ init_librocket() {
Rocket::Core::Initialise(); Rocket::Core::Initialise();
// Register that we have the libRocket system.
PandaSystem *ps = PandaSystem::get_global_ptr();
ps->add_system("libRocket");
#ifdef COMPILE_IN_DEFAULT_FONT #ifdef COMPILE_IN_DEFAULT_FONT
#ifdef HAVE_FREETYPE #ifdef HAVE_FREETYPE
// Load Panda's default compiled-in freetype font (Perspective Sans). // Load Panda's default compiled-in freetype font (Perspective Sans).

18
samples/mouse-modes/main.py Normal file → Executable file
View File

@ -34,7 +34,8 @@ class App(ShowBase):
# Disable the camera trackball controls. # Disable the camera trackball controls.
self.disableMouse() self.disableMouse()
self.mouseMagnitude = 144 # control mapping of mouse movement to box movement
self.mouseMagnitude = 1
self.rotateX, self.rotateY = 0, 0 self.rotateX, self.rotateY = 0, 0
@ -66,7 +67,7 @@ class App(ShowBase):
self.manualRecenterMouse = True self.manualRecenterMouse = True
# make a box to move with the mouse # make a box to move with the mouse
self.model = self.loader.loadModel("box.egg") self.model = self.loader.loadModel("box")
self.model.reparentTo(self.render) self.model.reparentTo(self.render)
self.cam.setPos(0, -5, 0) self.cam.setPos(0, -5, 0)
@ -75,7 +76,7 @@ class App(ShowBase):
self.mouseTask = taskMgr.add(self.mouseTask, "Mouse Task") self.mouseTask = taskMgr.add(self.mouseTask, "Mouse Task")
def setMouseMode(self, mode): def setMouseMode(self, mode):
print "Changing mode to",mode print("Changing mode to %s" % mode)
self.mouseMode = mode self.mouseMode = mode
@ -91,7 +92,7 @@ class App(ShowBase):
actualMode = wp.getMouseMode() actualMode = wp.getMouseMode()
if self.mouseMode != actualMode: if self.mouseMode != actualMode:
print "ACTUAL MOUSE MODE:", actualMode print("ACTUAL MOUSE MODE: %s" % actualMode)
self.mouseMode = actualMode self.mouseMode = actualMode
@ -106,11 +107,11 @@ class App(ShowBase):
def toggleRecenter(self): def toggleRecenter(self):
print "Toggling re-center behavior" print("Toggling re-center behavior")
self.manualRecenterMouse = not self.manualRecenterMouse self.manualRecenterMouse = not self.manualRecenterMouse
def toggleMouse(self): def toggleMouse(self):
print "Toggling mouse visibility" print("Toggling mouse visibility")
self.hideMouse = not self.hideMouse self.hideMouse = not self.hideMouse
@ -146,6 +147,7 @@ class App(ShowBase):
if self.manualRecenterMouse: if self.manualRecenterMouse:
# move mouse back to center # move mouse back to center
self.recenterMouse() self.recenterMouse()
self.lastMouseX, self.lastMouseY = 0, 0
# scale position and delta to pixels for user # scale position and delta to pixels for user
w, h = self.win.getSize() w, h = self.win.getSize()
@ -158,8 +160,8 @@ class App(ShowBase):
int(dx*w), int(dy*h))) int(dx*w), int(dy*h)))
# rotate box by delta # rotate box by delta
self.rotateX += dx * 10 self.rotateX += dx * 10 * self.mouseMagnitude
self.rotateY += dy * 10 self.rotateY += dy * 10 * self.mouseMagnitude
self.positionText.setText("Model rotation: {0}, {1}".format( self.positionText.setText("Model rotation: {0}, {1}".format(
int(self.rotateX*1000)/1000., int(self.rotateY*1000)/1000.)) int(self.rotateX*1000)/1000., int(self.rotateY*1000)/1000.))