From 03d633f2e763ee062dfad0cc4ecc1feed1bddd74 Mon Sep 17 00:00:00 2001 From: Ed Swartz Date: Tue, 11 Aug 2015 11:11:05 -0500 Subject: [PATCH 1/9] For stdpy.file wrapper, handle mode more consistently with Python. For Python 2, ignore unknown characters in the mode rather than silently failing to open. For Python 3, fail if unknown characters appear. --- direct/src/stdpy/file.py | 74 ++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index 91cf209b04..25f5b6e1a1 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -11,6 +11,7 @@ __all__ = [ ] from panda3d import core +import sys import types _vfs = core.VirtualFileSystem.getGlobalPtr() @@ -65,12 +66,27 @@ class file: self.filename = filename self.name = filename.toOsSpecific() + if sys.version_info >= (3, 0): + # Python 3 is much stricter than Python 2, which lets + # unknown flags fall through. + for ch in mode: + if not ch in 'rwxabt+U': + raise IOError("invalid mode: " + mode) + binary = False + if 'b' in mode and 't' in mode: + raise IOError("can't have text and binary mode at once") + if 'b' in mode: # Strip 'b'. This means a binary file. i = mode.index('b') mode = mode[:i] + mode[i + 1:] binary = True + elif 't' in mode: + # Strip 't'. This means a text file (redundant, yes). + i = mode.index('t') + mode = mode[:i] + mode[i + 1:] + binary = False if 'U' in mode: # Strip 'U'. We don't use it; universal-newline support @@ -83,61 +99,69 @@ class file: mode = 'r' # Per Python docs, we insist this is true. - assert mode[0] in 'rwa' + modeType = mode[0] + assert modeType in 'rwa' if binary: filename.setBinary() else: filename.setText() - - # Actually open the streams. - if mode == 'w': - self.__stream = _vfs.openWriteFile(filename, autoUnwrap, True) - if not self.__stream: - message = 'Could not open %s for writing' % (filename) - raise IOError, message - writeMode = True - - elif mode == 'a': - self.__stream = _vfs.openAppendFile(filename) - if not self.__stream: - message = 'Could not open %s for writing' % (filename) - raise IOError, message - writeMode = True - - elif mode == 'w+': + + # Actually open the streams, taking care to + # ignore unknown chars in the mode string. + # We already asserted that it starts with a mode + # char above, so locate the '+' + if modeType == 'w' and '+' in mode: self.__stream = _vfs.openReadWriteFile(filename, True) if not self.__stream: message = 'Could not open %s for writing' % (filename) - raise IOError, message + raise IOError(message) readMode = True writeMode = True - elif mode == 'a+': + elif modeType == 'a' and '+' in mode: self.__stream = _vfs.openReadAppendFile(filename) if not self.__stream: message = 'Could not open %s for writing' % (filename) - raise IOError, message + raise IOError(message) readMode = True writeMode = True - elif mode == 'r+': + elif modeType == 'r' and '+' in mode: self.__stream = _vfs.openReadWriteFile(filename, False) if not self.__stream: message = 'Could not open %s for writing' % (filename) - raise IOError, message + raise IOError(message) readMode = True writeMode = True + + elif modeType == 'w': + self.__stream = _vfs.openWriteFile(filename, autoUnwrap, True) + if not self.__stream: + message = 'Could not open %s for writing' % (filename) + raise IOError(message) + writeMode = True - elif mode == 'r': + elif modeType == 'a': + self.__stream = _vfs.openAppendFile(filename) + if not self.__stream: + message = 'Could not open %s for writing' % (filename) + raise IOError(message) + writeMode = True + + elif modeType == 'r': self.__stream = _vfs.openReadFile(filename, autoUnwrap) if not self.__stream: if not _vfs.exists(filename): message = 'No such file: %s' % (filename) else: message = 'Could not open %s for reading' % (filename) - raise IOError, message + raise IOError(message) readMode = True + + else: + # should not get here unless there's a bug above + raise IOError("Unhandled mode flags: " + mode) self.__needsVfsClose = True From f161ce82cc43e8dd8dbe4701b4bb2a5a3f1c0a2d Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 12 Aug 2015 18:29:54 +0200 Subject: [PATCH 2/9] Add argument names to quaternion classes so they show up in the API ref --- panda/src/linmath/lorientation_src.h | 10 +++++----- panda/src/linmath/lquaternion_src.h | 6 +++--- panda/src/linmath/lrotation_src.h | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/panda/src/linmath/lorientation_src.h b/panda/src/linmath/lorientation_src.h index 350922667f..7c4e33d0a7 100644 --- a/panda/src/linmath/lorientation_src.h +++ b/panda/src/linmath/lorientation_src.h @@ -21,11 +21,11 @@ class FLOATNAME(LRotation); class EXPCL_PANDA_LINMATH FLOATNAME(LOrientation) : public FLOATNAME(LQuaternion) { PUBLISHED: INLINE_LINMATH FLOATNAME(LOrientation)(); - INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LQuaternion)&); - INLINE_LINMATH FLOATNAME(LOrientation)(FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE); - INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LVector3) &, float); - INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LMatrix3) &); - INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LMatrix4) &); + INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LQuaternion) &c); + INLINE_LINMATH FLOATNAME(LOrientation)(FLOATTYPE r, FLOATTYPE i, FLOATTYPE j, FLOATTYPE k); + INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LVector3) &point_at, float twist); + INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LMatrix3) &m); + INLINE_LINMATH FLOATNAME(LOrientation)(const FLOATNAME(LMatrix4) &m); INLINE_LINMATH FLOATNAME(LOrientation) operator * (const FLOATNAME(LRotation) &other) const; diff --git a/panda/src/linmath/lquaternion_src.h b/panda/src/linmath/lquaternion_src.h index 730c39e637..22b3f0bffe 100644 --- a/panda/src/linmath/lquaternion_src.h +++ b/panda/src/linmath/lquaternion_src.h @@ -20,10 +20,10 @@ class EXPCL_PANDA_LINMATH FLOATNAME(LQuaternion) : public FLOATNAME(LVecBase4) { PUBLISHED: INLINE_LINMATH FLOATNAME(LQuaternion)(); INLINE_LINMATH FLOATNAME(LQuaternion)(const FLOATNAME(LVecBase4) ©); - INLINE_LINMATH FLOATNAME(LQuaternion)(FLOATTYPE, const FLOATNAME(LVecBase3) ©); - INLINE_LINMATH FLOATNAME(LQuaternion)(FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE); + INLINE_LINMATH FLOATNAME(LQuaternion)(FLOATTYPE r, const FLOATNAME(LVecBase3) ©); + INLINE_LINMATH FLOATNAME(LQuaternion)(FLOATTYPE r, FLOATTYPE i, FLOATTYPE j, FLOATTYPE k); - static FLOATNAME(LQuaternion) pure_imaginary(const FLOATNAME(LVector3) &); + static FLOATNAME(LQuaternion) pure_imaginary(const FLOATNAME(LVector3) &v); INLINE_LINMATH FLOATNAME(LQuaternion) conjugate() const; diff --git a/panda/src/linmath/lrotation_src.h b/panda/src/linmath/lrotation_src.h index f71a53a3e5..374a0e17a1 100644 --- a/panda/src/linmath/lrotation_src.h +++ b/panda/src/linmath/lrotation_src.h @@ -19,13 +19,13 @@ class EXPCL_PANDA_LINMATH FLOATNAME(LRotation) : public FLOATNAME(LQuaternion) { PUBLISHED: INLINE_LINMATH FLOATNAME(LRotation)(); - INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LQuaternion) &); + INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LQuaternion) &c); INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LVecBase4) ©); - INLINE_LINMATH FLOATNAME(LRotation)(FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE); - INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LVector3) &, FLOATTYPE); - INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LMatrix3) &); - INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LMatrix4) &); - INLINE_LINMATH FLOATNAME(LRotation)(FLOATTYPE, FLOATTYPE, FLOATTYPE); + INLINE_LINMATH FLOATNAME(LRotation)(FLOATTYPE r, FLOATTYPE i, FLOATTYPE j, FLOATTYPE k); + INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LVector3) &axis, FLOATTYPE angle); + INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LMatrix3) &m); + INLINE_LINMATH FLOATNAME(LRotation)(const FLOATNAME(LMatrix4) &m); + INLINE_LINMATH FLOATNAME(LRotation)(FLOATTYPE h, FLOATTYPE p, FLOATTYPE r); INLINE_LINMATH FLOATNAME(LRotation) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LRotation) operator / (FLOATTYPE scalar) const; From 9b93b8a030e61c7a45225cd6339c5ecd63ff98b7 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 13 Aug 2015 01:59:07 +0200 Subject: [PATCH 3/9] python-pmw shouldn't be a dependency, merely a recommendency --- makepanda/makepanda.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index f72103f017..64c624100d 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -6553,8 +6553,8 @@ def MakeInstallerLinux(): depends = ReadFile("targetroot/debian/substvars_dep").replace("shlibs:Depends=", "").strip() recommends = ReadFile("targetroot/debian/substvars_rec").replace("shlibs:Depends=", "").strip() if PkgSkip("PYTHON")==0: - depends += ", " + PYTHONV + ", python-pmw" - recommends += ", python-wxversion, python-profiler (>= " + PV + "), python-tk (>= " + PV + ")" + depends += ", " + PYTHONV + recommends += ", python-wxversion, python-profiler (>= " + PV + "), python-pmw, python-tk (>= " + PV + ")" if PkgSkip("NVIDIACG")==0: depends += ", nvidia-cg-toolkit" From 9fdc2d82d143c34ec2aa975d1eb10d84b20728aa Mon Sep 17 00:00:00 2001 From: Ed Swartz Date: Thu, 13 Aug 2015 10:58:51 -0500 Subject: [PATCH 4/9] Send libRocket key events before mouse events On Linux (at least), a key event is accompanied with a mouse position event. If a libRocket UI is listening to e.g. "mouseover" events, then any keypress will first appear to be a mouse movement, tripping up code that tries to handle focus with both keyboard and mouse support. This change merely dispatches key events before any mouse events to avoid this problem. --- panda/src/rocket/rocketInputHandler.cxx | 48 ++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/panda/src/rocket/rocketInputHandler.cxx b/panda/src/rocket/rocketInputHandler.cxx index c0a4e22464..b734e59bef 100644 --- a/panda/src/rocket/rocketInputHandler.cxx +++ b/panda/src/rocket/rocketInputHandler.cxx @@ -302,30 +302,6 @@ void RocketInputHandler:: update_context(Rocket::Core::Context *context, int xoffs, int yoffs) { MutexHolder holder(_lock); - if (_mouse_xy_changed) { - _mouse_xy_changed = false; - - context->ProcessMouseMove(_mouse_xy.get_x() - xoffs, - _mouse_xy.get_y() - yoffs, _modifiers); - } - - if (_mouse_buttons.size() > 0) { - ButtonActivityMap::const_iterator it; - for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) { - if (it->second) { - context->ProcessMouseButtonDown(it->first, _modifiers); - } else { - context->ProcessMouseButtonUp(it->first, _modifiers); - } - } - _mouse_buttons.clear(); - } - - if (_wheel_delta != 0) { - context->ProcessMouseWheel(_wheel_delta, _modifiers); - _wheel_delta = 0; - } - if (_keys.size() > 0) { ButtonActivityMap::const_iterator it; for (it = _keys.begin(); it != _keys.end(); ++it) { @@ -356,5 +332,29 @@ update_context(Rocket::Core::Context *context, int xoffs, int yoffs) { _text_input.clear(); } + if (_mouse_xy_changed) { + _mouse_xy_changed = false; + + context->ProcessMouseMove(_mouse_xy.get_x() - xoffs, + _mouse_xy.get_y() - yoffs, _modifiers); + } + + if (_mouse_buttons.size() > 0) { + ButtonActivityMap::const_iterator it; + for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) { + if (it->second) { + context->ProcessMouseButtonDown(it->first, _modifiers); + } else { + context->ProcessMouseButtonUp(it->first, _modifiers); + } + } + _mouse_buttons.clear(); + } + + if (_wheel_delta != 0) { + context->ProcessMouseWheel(_wheel_delta, _modifiers); + _wheel_delta = 0; + } + context->Update(); } From 3e34233b1c86638c903c4574c7c7e0b5babf1e1c Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 14 Aug 2015 15:57:56 +0200 Subject: [PATCH 5/9] Implement extracted files for packp3d and pdeploy (only when used together) This also changes start_dir for pdeployed applications to point to the application directory, no longer to ~/.panda3d/start --- direct/src/p3d/DeploymentTools.py | 78 ++++++++-- direct/src/p3d/Packager.py | 4 + direct/src/p3d/packp3d.py | 10 ++ direct/src/plugin/load_plugin.cxx | 23 ++- direct/src/plugin/load_plugin.h | 6 +- direct/src/plugin/p3dAuthSession.cxx | 2 +- direct/src/plugin/p3dInstance.cxx | 2 +- direct/src/plugin/p3dInstanceManager.I | 12 ++ direct/src/plugin/p3dInstanceManager.cxx | 19 ++- direct/src/plugin/p3dInstanceManager.h | 5 +- direct/src/plugin/p3dSession.cxx | 2 +- direct/src/plugin/p3d_plugin.cxx | 9 +- direct/src/plugin/p3d_plugin.h | 5 +- direct/src/plugin_activex/PPInstance.cpp | 6 +- direct/src/plugin_npapi/ppInstance.cxx | 4 +- direct/src/plugin_standalone/p3dEmbed.cxx | 29 +++- direct/src/plugin_standalone/panda3d.cxx | 171 ++++++++++++--------- direct/src/plugin_standalone/panda3d.h | 1 + direct/src/plugin_standalone/panda3dBase.h | 1 + 19 files changed, 271 insertions(+), 118 deletions(-) diff --git a/direct/src/p3d/DeploymentTools.py b/direct/src/p3d/DeploymentTools.py index 5bb3f3a159..78b2378eda 100644 --- a/direct/src/p3d/DeploymentTools.py +++ b/direct/src/p3d/DeploymentTools.py @@ -444,6 +444,7 @@ class Installer: notify = directNotify.newCategory("Installer") def __init__(self, p3dfile, shortname, fullname, version, tokens = {}): + self.p3dFilename = p3dfile if not shortname: shortname = p3dfile.getBasenameWoExtension() self.shortname = shortname @@ -477,22 +478,16 @@ class Installer: if not self.authoremail and ' ' not in uname: self.authoremail = "%s@%s" % (uname, socket.gethostname()) - self.standalone = Standalone(p3dfile, tokens) - self.tempDir = Filename.temporary("", self.shortname, "") + "/" - self.tempDir.makeDir() - self.__tempRoots = {} - # Load the p3d file to read out the required packages mf = Multifile() - if not mf.openRead(p3dfile): + if not mf.openRead(self.p3dFilename): Installer.notify.error("Not a Panda3D application: %s" % (p3dfile)) return # Now load the p3dInfo file. - self.hostUrl = PandaSystem.getPackageHostUrl() - if not self.hostUrl: - self.hostUrl = self.standalone.host.hostUrl + self.hostUrl = None self.requires = [] + self.extracts = [] i = mf.findSubfile('p3d_info.xml') if i >= 0: stream = mf.openReadSubfile(i) @@ -511,14 +506,54 @@ class Installer: p3dRequires.Attribute('host'))) p3dRequires = p3dRequires.NextSiblingElement('requires') + p3dExtract = p3dPackage.FirstChildElement('extract') + while p3dExtract: + filename = p3dExtract.Attribute('filename') + self.extracts.append(filename) + p3dExtract = p3dExtract.NextSiblingElement('extract') + if not self.fullname: p3dConfig = p3dPackage.FirstChildElement('config') if p3dConfig: self.fullname = p3dConfig.Attribute('display_name') + else: + Installer.notify.warning("No p3d_info.xml was found in .p3d archive.") + + mf.close() + + if not self.hostUrl: + self.hostUrl = PandaSystem.getPackageHostUrl() + if not self.hostUrl: + self.hostUrl = self.standalone.host.hostUrl + Installer.notify.warning("No host URL was specified by .p3d archive. Falling back to %s" % (self.hostUrl)) if not self.fullname: self.fullname = self.shortname + self.tempDir = Filename.temporary("", self.shortname, "") + "/" + self.tempDir.makeDir() + self.__tempRoots = {} + + if self.extracts: + # Copy .p3d to a temporary file so we can remove the extracts. + p3dfile = Filename(self.tempDir, self.p3dFilename.getBasename()) + shutil.copyfile(self.p3dFilename.toOsSpecific(), p3dfile.toOsSpecific()) + mf = Multifile() + if not mf.openReadWrite(p3dfile): + Installer.notify.error("Failure to open %s for writing." % (p3dfile)) + + # We don't really need this silly thing when embedding, anyway. + mf.setHeaderPrefix("") + + for fn in self.extracts: + if not mf.removeSubfile(fn): + Installer.notify.error("Failure to remove %s from multifile." % (p3dfile)) + + mf.repack() + mf.close() + + self.standalone = Standalone(p3dfile, tokens) + def __del__(self): try: appRunner.rmtree(self.tempDir) @@ -533,6 +568,22 @@ class Installer: if not self.includeRequires: return + # Write out the extracts from the original .p3d. + if self.extracts: + mf = Multifile() + if not mf.openRead(self.p3dFilename): + Installer.notify.error("Failed to open .p3d archive: %s" % (filename)) + + for filename in self.extracts: + i = mf.findSubfile(filename) + if i < 0: + Installer.notify.error("Cannot find extract in .p3d archive: %s" % (filename)) + continue + + if not mf.extractSubfile(i, Filename(hostDir, filename)): + Installer.notify.error("Failed to extract file from .p3d archive: %s" % (filename)) + mf.close() + pkgTree = PackageTree(platform, hostDir, self.hostUrl) pkgTree.installPackage("images", None, self.standalone.host.hostUrl) @@ -660,7 +711,8 @@ class Installer: Filename(tempdir, "usr/bin/").makeDir() if self.includeRequires: - extraTokens = {"host_dir" : "/usr/lib/" + self.shortname.lower()} + extraTokens = {"host_dir" : "/usr/lib/" + self.shortname.lower(), + "start_dir" : "/usr/lib/" + self.shortname.lower()} else: extraTokens = {} self.standalone.build(Filename(tempdir, "usr/bin/" + self.shortname.lower()), platform, extraTokens) @@ -712,7 +764,7 @@ class Installer: print >>desktop, "Type=Application" desktop.close() - if self.includeRequires: + if self.includeRequires or self.extracts: hostDir = Filename(tempdir, "usr/lib/%s/" % self.shortname.lower()) hostDir.makeDir() self.installPackagesInto(hostDir, platform) @@ -853,7 +905,7 @@ class Installer: exefile = Filename(output, "Contents/MacOS/" + self.shortname) exefile.makeDir() if self.includeRequires: - extraTokens = {"host_dir" : "../Resources"} + extraTokens = {"host_dir": "../Resources", "start_dir": "../Resources"} else: extraTokens = {} self.standalone.build(exefile, platform, extraTokens) @@ -1064,7 +1116,7 @@ class Installer: exefile = Filename(Filename.getTempDirectory(), self.shortname + ".exe") exefile.unlink() if self.includeRequires: - extraTokens = {"host_dir" : "."} + extraTokens = {"host_dir": ".", "start_dir": "."} else: extraTokens = {} self.standalone.build(exefile, platform, extraTokens) diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index 40c30d8485..b0a44d7fa2 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -1496,6 +1496,10 @@ class Packager: xhost = he.makeXml(packager = self.packager) xpackage.InsertEndChild(xhost) + self.extracts.sort() + for name, xextract in self.extracts: + xpackage.InsertEndChild(xextract) + doc.InsertEndChild(xpackage) # Write the xml file to a temporary file on disk, so we diff --git a/direct/src/p3d/packp3d.py b/direct/src/p3d/packp3d.py index 3544022fd6..b26c6d5b22 100755 --- a/direct/src/p3d/packp3d.py +++ b/direct/src/p3d/packp3d.py @@ -57,6 +57,14 @@ Options: instead of -e for files that are uncompressible by their nature (e.g. mpg files). This option may be repeated as necessary. + -x ext + Marks files with the given extensions of needing to be physically + extracted to disk before they can be loaded. This is used for + file types that cannot be loaded via the virtual file system, + such as .ico files on Windows. + This option is currently only implemented when deploying the + application with pdeploy. + -p python_lib_dir Adds a directory to search for additional Python modules. You can use this to add your system's Python path, to allow packp3d @@ -134,6 +142,8 @@ def makePackedApp(args): packager.binaryExtensions.append(value) elif option == '-n': packager.uncompressibleExtensions.append(value) + elif option == '-x': + packager.extractExtensions.append(value) elif option == '-p': sys.path.append(value) elif option == '-c': diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index a9276b9e99..8a8e5ef179 100644 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -140,7 +140,7 @@ load_plugin(const string &p3d_plugin_filename, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, const string &root_dir, const string &host_dir, - ostream &logfile) { + const string &start_dir, ostream &logfile) { if (plugin_loaded) { return true; } @@ -259,7 +259,7 @@ load_plugin(const string &p3d_plugin_filename, verify_contents, platform, log_directory, log_basename, trusted_environment, console_environment, - root_dir, host_dir, logfile)) { + root_dir, host_dir, start_dir, logfile)) { unload_dso(); return false; } @@ -283,7 +283,7 @@ init_plugin(const string &contents_filename, const string &host_url, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, const string &root_dir, const string &host_dir, - ostream &logfile) { + const string &start_dir, ostream &logfile) { // Ensure that all of the function pointers have been found. if (P3D_initialize_ptr == NULL || @@ -371,15 +371,26 @@ init_plugin(const string &contents_filename, const string &host_url, return false; } - if (!P3D_initialize_ptr(P3D_API_VERSION, contents_filename.c_str(), + // A bit of extra hand-hacked compatibility for using newer plug-ins + // with an older version of the core API. + int api_version = P3D_API_VERSION; + if (api_version == 17 && start_dir.empty()) { + api_version = 16; + if (host_dir.empty()) { + api_version = 15; + } + } + + if (!P3D_initialize_ptr(api_version, contents_filename.c_str(), host_url.c_str(), verify_contents, platform.c_str(), log_directory.c_str(), log_basename.c_str(), trusted_environment, console_environment, - root_dir.c_str(), host_dir.c_str())) { + root_dir.c_str(), host_dir.c_str(), + start_dir.c_str())) { // Oops, failure to initialize. logfile << "Failed to initialize plugin (passed API version " - << P3D_API_VERSION << ")\n"; + << api_version << ")\n"; return false; } diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index 985eef7261..f9f89565e5 100644 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -67,13 +67,15 @@ load_plugin(const string &p3d_plugin_filename, P3D_verify_contents verify_contents, const string &platform, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir, const string &host_dir, ostream &logfile); + const string &root_dir, const string &host_dir, + const string &start_dir, ostream &logfile); bool init_plugin(const string &contents_filename, const string &host_url, P3D_verify_contents verify_contents, const string &platform, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir, const string &host_dir, ostream &logfile); + const string &root_dir, const string &host_dir, + const string &start_dir, ostream &logfile); void unload_plugin(ostream &logfile); bool is_plugin_loaded(); diff --git a/direct/src/plugin/p3dAuthSession.cxx b/direct/src/plugin/p3dAuthSession.cxx index 6130119223..103c372f0a 100644 --- a/direct/src/plugin/p3dAuthSession.cxx +++ b/direct/src/plugin/p3dAuthSession.cxx @@ -163,7 +163,7 @@ start_p3dcert() { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - _start_dir = inst_mgr->get_root_dir() + "/start"; + _start_dir = inst_mgr->get_start_dir(); string root_dir = _inst->_p3dcert_package->get_package_dir(); mkdir_complete(_start_dir, nout); diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index d81a271d1e..3f84bb441e 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -1564,7 +1564,7 @@ uninstall_packages() { if (inst_mgr->get_verify_contents() != P3D_VC_never) { string start_dir_suffix = get_start_dir_suffix(); if (!start_dir_suffix.empty()) { - string start_dir = inst_mgr->get_root_dir() + "/start" + start_dir_suffix; + string start_dir = inst_mgr->get_start_dir() + start_dir_suffix; nout << "Cleaning up start directory " << start_dir << "\n"; inst_mgr->delete_directory_recursively(start_dir); } diff --git a/direct/src/plugin/p3dInstanceManager.I b/direct/src/plugin/p3dInstanceManager.I index caadc083b3..af5b6de16c 100644 --- a/direct/src/plugin/p3dInstanceManager.I +++ b/direct/src/plugin/p3dInstanceManager.I @@ -111,6 +111,18 @@ get_root_dir() const { return _root_dir; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::get_start_dir +// Access: Public +// Description: Returns the directory that the .p3d file should be +// mounted to and run from. This is usually the +// "start" subdirectory of the root_dir. +//////////////////////////////////////////////////////////////////// +inline const string &P3DInstanceManager:: +get_start_dir() const { + return _start_dir; +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::get_platform // Access: Public diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 793e6cf36e..fa8c70def2 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -201,7 +201,8 @@ initialize(int api_version, const string &contents_filename, const string &platform, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, - const string &root_dir, const string &host_dir) { + const string &root_dir, const string &host_dir, + const string &start_dir) { _api_version = api_version; _host_url = host_url; _verify_contents = verify_contents; @@ -298,12 +299,18 @@ initialize(int api_version, const string &contents_filename, } else { _root_dir = root_dir; } - + _host_dir = host_dir; + if (start_dir.empty()) { + _start_dir = _root_dir + "/start"; + } else { + _start_dir = start_dir; + } + // Allow the caller (e.g. panda3d.exe) to specify a log directory. // Or, allow the developer to compile one in. - + // // Failing that, we write logfiles to Panda3D/log. if (_log_directory.empty()) { _log_directory = _root_dir + "/log"; @@ -1515,8 +1522,10 @@ create_runtime_environment() { // Make the certificate directory. _certs_dir = _root_dir + "/certs"; - if (!mkdir_complete(_certs_dir, nout)) { - nout << "Couldn't mkdir " << _certs_dir << "\n"; + if (!get_trusted_environment()) { + if (!mkdir_complete(_certs_dir, nout)) { + nout << "Couldn't mkdir " << _certs_dir << "\n"; + } } _created_runtime_environment = true; diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index 78cfcfbdce..b051c01310 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -59,7 +59,8 @@ public: bool trusted_environment, bool console_environment, const string &root_dir = "", - const string &host_dir = ""); + const string &host_dir = "", + const string &start_dir = ""); inline bool is_initialized() const; inline void reconsider_runtime_environment(); @@ -69,6 +70,7 @@ public: inline int get_api_version() const; inline const string &get_host_url() const; inline const string &get_root_dir() const; + inline const string &get_start_dir() const; inline const string &get_platform() const; inline const string &get_temp_directory() const; inline const string &get_log_directory() const; @@ -173,6 +175,7 @@ private: string _host_url; string _root_dir; string _host_dir; + string _start_dir; string _certs_dir; P3D_verify_contents _verify_contents; string _platform; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index e0b9c73f08..3e6189ce4d 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -717,7 +717,7 @@ start_p3dpython(P3DInstance *inst) { _keep_user_env = true; } if (!_keep_user_env) { - _start_dir = inst_mgr->get_root_dir() + "/start" + inst->get_start_dir_suffix(); + _start_dir = inst_mgr->get_start_dir() + inst->get_start_dir_suffix(); mkdir_complete(_start_dir, nout); } replace_slashes(_start_dir); diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 8641a72121..241a59d253 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -39,7 +39,8 @@ P3D_initialize(int api_version, const char *contents_filename, const char *platform, const char *log_directory, const char *log_basename, bool trusted_environment, bool console_environment, - const char *root_dir, const char *host_dir) { + const char *root_dir, const char *host_dir, + const char *start_dir) { if (api_version < 10 || api_version > P3D_API_VERSION) { // Can't accept an incompatible version. return false; @@ -89,12 +90,16 @@ P3D_initialize(int api_version, const char *contents_filename, host_dir = ""; } + if (api_version < 17 || start_dir == NULL) { + start_dir = ""; + } + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); bool result = inst_mgr->initialize(api_version, contents_filename, host_url, verify_contents, platform, log_directory, log_basename, trusted_environment, console_environment, - root_dir, host_dir); + root_dir, host_dir, start_dir); RELEASE_LOCK(_api_lock); return result; } diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index e053e6e21b..916763c036 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -79,7 +79,7 @@ extern "C" { (below). This number will be incremented whenever there are changes to any of the interface specifications defined in this header file. */ -#define P3D_API_VERSION 16 +#define P3D_API_VERSION 17 /************************ GLOBAL FUNCTIONS **************************/ @@ -161,7 +161,8 @@ P3D_initialize_func(int api_version, const char *contents_filename, const char *platform, const char *log_directory, const char *log_basename, bool trusted_environment, bool console_environment, - const char *root_dir, const char *host_dir); + const char *root_dir, const char *host_dir, + const char *start_dir); /* This function should be called to unload the core API. It will release all internally-allocated memory and return the core API to diff --git a/direct/src/plugin_activex/PPInstance.cpp b/direct/src/plugin_activex/PPInstance.cpp index a0984a27f6..2151fc63f1 100644 --- a/direct/src/plugin_activex/PPInstance.cpp +++ b/direct/src/plugin_activex/PPInstance.cpp @@ -581,12 +581,12 @@ int PPInstance::LoadPlugin( const std::string& dllFilename ) pathname = override_filename; } #endif // P3D_PLUGIN_P3D_PLUGIN - + nout << "Attempting to load core API from " << pathname << "\n"; string contents_filename = m_rootDir + "/contents.xml"; if (!load_plugin(pathname, contents_filename, PANDA_PACKAGE_HOST_URL, - P3D_VC_normal, "", "", "", false, false, - m_rootDir, "", nout)) { + P3D_VC_normal, "", "", "", false, false, + m_rootDir, "", "", nout)) { nout << "Unable to launch core API in " << pathname << "\n"; error = 1; } else { diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 55b9757a04..209204652d 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -1738,8 +1738,8 @@ do_load_plugin() { nout << "Attempting to load core API from " << pathname << "\n"; string contents_filename = _root_dir + "/contents.xml"; if (!load_plugin(pathname, contents_filename, PANDA_PACKAGE_HOST_URL, - P3D_VC_normal, "", "", "", false, false, - _root_dir, "", nout)) { + P3D_VC_normal, "", "", "", false, false, + _root_dir, "", "", nout)) { nout << "Unable to launch core API in " << pathname << "\n"; set_failed(); return; diff --git a/direct/src/plugin_standalone/p3dEmbed.cxx b/direct/src/plugin_standalone/p3dEmbed.cxx index 4ee1ff31ca..a09c13423b 100644 --- a/direct/src/plugin_standalone/p3dEmbed.cxx +++ b/direct/src/plugin_standalone/p3dEmbed.cxx @@ -53,7 +53,8 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { // the + 1 from the test. _read_offset_check = read_offset + (streampos)1; if (_read_offset_check == (streampos)0xFF3D3D01) { - cerr << "This program is not intended to be run directly.\nIt is used by pdeploy to construct an embedded Panda3D application.\n"; + cerr << "This program is not intended to be run directly.\nIt is used " + "by pdeploy to construct an embedded Panda3D application.\n"; return 1; } @@ -86,22 +87,30 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { string value; string root_dir; string host_dir; + string start_dir; + while (true) { if (curchr == EOF) { cerr << "Truncated stream\n"; - return(1); + return 1; } else if (curchr == 0) { // Two null bytes in a row means we've reached the end of the data. if (havenull) { break; } - + // This means we haven't seen an '=' character yet. if (keyword == "") { if (curstr != "") { cerr << "Ignoring token '" << curstr << "' without value\n"; } + + } else if (keyword == "start_dir") { + // Don't pass this on as a token, since it has slightly different + // semantics when used as an HTML token. + start_dir = curstr; + } else { value.assign(curstr); P3D_token token; @@ -118,6 +127,8 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { _got_win_size = true; } else if (keyword == "log_basename") { _log_basename = value; + } else if (keyword == "log_directory") { + _log_dirname = value; } else if (keyword == "root_dir") { root_dir = value; } else if (keyword == "host_dir") { @@ -168,6 +179,13 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { _host_dir = host_dir_f.to_os_specific(); } + // Make the start directory absolute + if (!start_dir.empty()) { + Filename start_dir_f(start_dir); + start_dir_f.make_absolute(f.get_dirname()); + _start_dir = start_dir_f.to_os_specific(); + } + // Initialize the core API by directly assigning all of the function // pointers. P3D_initialize_ptr = &P3D_initialize; @@ -229,18 +247,17 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { // function pointers. This will also call P3D_initialize(). if (!init_plugin("", _host_url, _verify_contents, _this_platform, _log_dirname, _log_basename, true, _console_environment, - _root_dir, _host_dir, cerr)) { + _root_dir, _host_dir, _start_dir, cerr)) { cerr << "Unable to launch core API\n"; return 1; } - + // Create a plugin instance and run the program P3D_instance *inst = create_instance(f, true, argv, argc, read_offset); _instances.insert(inst); run_main_loop(); - unload_plugin(cerr); return 0; } diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index ab0219f7cf..fd0d2f44b7 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -690,7 +690,6 @@ choose_random_mirrors(vector_string &result, int num_mirrors) { } } - //////////////////////////////////////////////////////////////////// // Function: Panda3D::get_core_api // Access: Protected @@ -700,78 +699,12 @@ choose_random_mirrors(vector_string &result, int num_mirrors) { //////////////////////////////////////////////////////////////////// bool Panda3D:: get_core_api() { + bool is_fresh = false; if (!_coreapi_dll.quick_verify(_root_dir)) { - // The DLL file needs to be downloaded. Build up our list of - // URL's to attempt to download it from, in reverse order. - string url; - vector_string core_urls; - - // Our last act of desperation: hit the original host, with a - // query uniquifier, to break through any caches. - ostringstream strm; - strm << _download_url_prefix << _coreapi_dll.get_filename() - << "?" << time(NULL); - url = strm.str(); - core_urls.push_back(url); - - // Before we try that, we'll hit the original host, without a - // uniquifier. - url = _download_url_prefix; - url += _coreapi_dll.get_filename(); - core_urls.push_back(url); - - // And before we try that, we'll try two mirrors, at random. - vector_string mirrors; - choose_random_mirrors(mirrors, 2); - for (vector_string::iterator si = mirrors.begin(); - si != mirrors.end(); - ++si) { - url = (*si) + _coreapi_dll.get_filename(); - core_urls.push_back(url); - } - - // The very first thing we'll try is the super_mirror, if we have - // one. - if (!_super_mirror_url_prefix.empty()) { - url = _super_mirror_url_prefix + _coreapi_dll.get_filename(); - core_urls.push_back(url); - } - - // Now pick URL's off the list, and try them, until we have - // success. - Filename pathname = Filename::from_os_specific(_coreapi_dll.get_pathname(_root_dir)); - pathname.make_dir(); - HTTPClient *http = HTTPClient::get_global_ptr(); - - bool success = false; - while (!core_urls.empty()) { - url = core_urls.back(); - core_urls.pop_back(); - - PT(HTTPChannel) channel = http->get_document(url); - if (!channel->download_to_file(pathname)) { - cerr << "Unable to download " << url << "\n"; - - } else if (!_coreapi_dll.full_verify(_root_dir)) { - cerr << "Mismatched download for " << url << "\n"; - - } else { - // successfully downloaded! - success = true; - break; - } - } - - if (!success) { - cerr << "Couldn't download core API.\n"; + if (!download_core_api()) { return false; } - - // Since we had to download some of it, might as well ask the core - // API to check all of it. - if (_verify_contents == P3D_VC_none) { - _verify_contents = P3D_VC_normal; - } + is_fresh = true; } // Now we've got the DLL. Load it. @@ -795,9 +728,19 @@ get_core_api() { if (!load_plugin(pathname, contents_filename.to_os_specific(), _host_url, _verify_contents, _this_platform, _log_dirname, _log_basename, trusted_environment, _console_environment, - _root_dir, "", cerr)) { - cerr << "Unable to launch core API in " << pathname << "\n"; - return false; + _root_dir, _host_dir, _start_dir, cerr)) { + + // If we're not sure this is the latest version, make sure it is + // up-to-date, and then try again. + if (is_fresh || !download_core_api() || + !load_plugin(pathname, contents_filename.to_os_specific(), + _host_url, _verify_contents, _this_platform, _log_dirname, + _log_basename, trusted_environment, _console_environment, + _root_dir, _host_dir, _start_dir, cerr)) { + + cerr << "Unable to launch core API in " << pathname << "\n"; + return false; + } } // Successfully loaded. @@ -822,6 +765,88 @@ get_core_api() { return true; } +//////////////////////////////////////////////////////////////////// +// Function: Panda3D::download_core_api +// Access: Protected +// Description: Downloads the latest version of the core API from +// the plug-in server. +//////////////////////////////////////////////////////////////////// +bool Panda3D:: +download_core_api() { + // The DLL file needs to be downloaded. Build up our list of + // URL's to attempt to download it from, in reverse order. + string url; + vector_string core_urls; + + // Our last act of desperation: hit the original host, with a + // query uniquifier, to break through any caches. + ostringstream strm; + strm << _download_url_prefix << _coreapi_dll.get_filename() + << "?" << time(NULL); + url = strm.str(); + core_urls.push_back(url); + + // Before we try that, we'll hit the original host, without a + // uniquifier. + url = _download_url_prefix; + url += _coreapi_dll.get_filename(); + core_urls.push_back(url); + + // And before we try that, we'll try two mirrors, at random. + vector_string mirrors; + choose_random_mirrors(mirrors, 2); + for (vector_string::iterator si = mirrors.begin(); + si != mirrors.end(); + ++si) { + url = (*si) + _coreapi_dll.get_filename(); + core_urls.push_back(url); + } + + // The very first thing we'll try is the super_mirror, if we have + // one. + if (!_super_mirror_url_prefix.empty()) { + url = _super_mirror_url_prefix + _coreapi_dll.get_filename(); + core_urls.push_back(url); + } + + // Now pick URL's off the list, and try them, until we have + // success. + Filename pathname = Filename::from_os_specific(_coreapi_dll.get_pathname(_root_dir)); + pathname.make_dir(); + HTTPClient *http = HTTPClient::get_global_ptr(); + + bool success = false; + while (!core_urls.empty()) { + url = core_urls.back(); + core_urls.pop_back(); + + PT(HTTPChannel) channel = http->get_document(url); + if (!channel->download_to_file(pathname)) { + cerr << "Unable to download " << url << "\n"; + + } else if (!_coreapi_dll.full_verify(_root_dir)) { + cerr << "Mismatched download for " << url << "\n"; + + } else { + // successfully downloaded! + success = true; + break; + } + } + + if (!success) { + cerr << "Couldn't download core API.\n"; + return false; + } + + // Since we had to download some of it, might as well ask the core + // API to check all of it. + if (_verify_contents == P3D_VC_none) { + _verify_contents = P3D_VC_normal; + } + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Panda3D::usage // Access: Protected diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index 36603b93e6..94efc0c41f 100644 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -48,6 +48,7 @@ protected: void add_mirror(string mirror_url); void choose_random_mirrors(vector_string &result, int num_mirrors); bool get_core_api(); + bool download_core_api(); void usage(); diff --git a/direct/src/plugin_standalone/panda3dBase.h b/direct/src/plugin_standalone/panda3dBase.h index 0f577f39fe..f53e59b14c 100644 --- a/direct/src/plugin_standalone/panda3dBase.h +++ b/direct/src/plugin_standalone/panda3dBase.h @@ -74,6 +74,7 @@ protected: string _host_url; string _root_dir; string _host_dir; + string _start_dir; string _log_dirname; string _log_basename; string _this_platform; From 6b7cbc5f2fe746a2600c3f1c9f819b4d52a6b12c Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 16 Aug 2015 13:51:25 +0200 Subject: [PATCH 6/9] Fix issue running makepanda on German computers --- makepanda/makepandacore.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 3d45411016..7b1770fe77 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2290,6 +2290,9 @@ def SetupBuildEnvironment(compiler): print("Target OS: %s" % GetTarget()) print("Target arch: %s" % GetTargetArch()) + # Set to English so we can safely parse the result of gcc commands. + os.environ["LC_ALL"] = "C" + if compiler == "MSVC": # Add the visual studio tools to PATH et al. SetupVisualStudioEnviron() From e178ca4c9bed35a026d8a64b735d7abe25f4bce3 Mon Sep 17 00:00:00 2001 From: tobspr Date: Sun, 16 Aug 2015 10:45:59 +0200 Subject: [PATCH 7/9] Fix missing imports in showbase when using sticky keys (was broken with commit 0aa0f34c7498131ab67077be83be3c93a0e9ca83) --- direct/src/showbase/ShowBase.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 9ab3184d6a..e6c0f623e4 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -9,6 +9,8 @@ __all__ = ['ShowBase', 'WindowControls'] from panda3d.core import * from panda3d.direct import get_config_showbase, throw_new_frame, init_app_for_gui +from panda3d.direct import storeAccessibilityShortcutKeys, allowAccessibilityShortcutKeys + # This needs to be available early for DirectGUI imports import __builtin__ as builtins From 1c1efa7f17981ee559f150effbc444878e1077f4 Mon Sep 17 00:00:00 2001 From: tobspr Date: Sat, 15 Aug 2015 21:35:18 +0200 Subject: [PATCH 8/9] Fix Texture:estimate_texture_memory() --- panda/src/gobj/texture.cxx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index e2cd069a75..4131da068c 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -502,11 +502,14 @@ estimate_texture_memory() const { case Texture::F_green: case Texture::F_blue: case Texture::F_luminance: + case Texture::F_sluminance: + bpp = 1; + break; + case Texture::F_luminance_alpha: case Texture::F_luminance_alphamask: - case Texture::F_sluminance: case Texture::F_sluminance_alpha: - bpp = 4; + bpp = 2; break; case Texture::F_rgba: @@ -529,13 +532,16 @@ estimate_texture_memory() const { break; case Texture::F_depth_stencil: + bpp = 4; + break; + case Texture::F_depth_component: - bpp = 32; + bpp = 2; break; case Texture::F_rgba12: case Texture::F_rgb12: - bpp = 6; + bpp = 8; break; case Texture::F_rgba16: @@ -554,7 +560,7 @@ estimate_texture_memory() const { bpp = 4; break; case Texture::F_rgb16: - bpp = 6; + bpp = 8; break; case Texture::F_r32i: From 2ea3e3f65a6454f003cae25f441df451a185be63 Mon Sep 17 00:00:00 2001 From: tobspr Date: Sun, 16 Aug 2015 08:29:14 +0200 Subject: [PATCH 9/9] Fix occasional crash when connecting to pstats --- panda/src/display/graphicsStateGuardian.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index ee69ed5fba..9fbe8b9606 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1960,7 +1960,7 @@ flush_timer_queries() { if (_pending_timer_queries[i]->is_answer_ready()) { first = count; - while (i < count) { + while (i < count - 1) { if (!_pending_timer_queries[++i]->is_answer_ready()) { first = i; break;