From a56b85dbedc68c16d4eb97ce10b7ecc0c0451b0b Mon Sep 17 00:00:00 2001 From: LD Date: Tue, 7 Jan 2020 14:09:05 +0100 Subject: [PATCH 1/8] cocoadisplay: Fix switch to fullscreen on macOS 10.9 using current display resolution --- panda/src/cocoadisplay/cocoaGraphicsWindow.mm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index 6f4689bda0..53e5f6f6a2 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -1143,13 +1143,14 @@ find_display_mode(int width, int height) { int refresh_rate; mode = CGDisplayCopyDisplayMode(_display); -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080 // First check if the current mode is adequate. - if (CGDisplayModeGetWidth(mode) == width && + // This test not done for macOS 10.15 and above as the mode resolution is + // not enough to identify a mode. + if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_14 && + CGDisplayModeGetWidth(mode) == width && CGDisplayModeGetHeight(mode) == height) { return mode; } -#endif current_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); refresh_rate = CGDisplayModeGetRefreshRate(mode); From 201f9a48beec12cc77b0121aa9e74a2f6b55827a Mon Sep 17 00:00:00 2001 From: LD Date: Tue, 7 Jan 2020 09:29:45 +0100 Subject: [PATCH 2/8] dist: Also use copy_with_dependencies() for executables to flatten their dependencies Closes #837 --- direct/src/dist/commands.py | 47 +++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index a84d7f5fae..1b70a980f0 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -642,6 +642,28 @@ class build_apps(setuptools.Command): freezer_modules = set() freezer_modpaths = set() ext_suffixes = set() + + def get_search_path_for(source_path): + search_path = [os.path.dirname(source_path)] + if use_wheels: + search_path.append(os.path.join(p3dwhlfn, 'deploy_libs')) + + # If the .whl containing this file has a .libs directory, add + # it to the path. This is an auditwheel/numpy convention. + if '.whl' + os.sep in source_path: + whl, wf = source_path.split('.whl' + os.path.sep) + whl += '.whl' + rootdir = wf.split(os.path.sep, 1)[0] + search_path.append(os.path.join(whl, rootdir, '.libs')) + + # Also look for more specific per-package cases, defined in + # PACKAGE_LIB_DIRS at the top of this file. + whl_name = os.path.basename(whl).split('-', 1)[0] + extra_dirs = PACKAGE_LIB_DIRS.get(whl_name, []) + for extra_dir in extra_dirs: + search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep))) + return search_path + def create_runtime(appname, mainscript, use_console): freezer = FreezeTool.Freezer(platform=platform, path=path) freezer.addModule('__main__', filename=mainscript) @@ -784,26 +806,8 @@ class build_apps(setuptools.Command): continue # If this is a dynamic library, search for dependencies. - search_path = [os.path.dirname(source_path)] - if use_wheels: - search_path.append(os.path.join(p3dwhlfn, 'deploy_libs')) - - # If the .whl containing this file has a .libs directory, add - # it to the path. This is an auditwheel/numpy convention. - if '.whl' + os.sep in source_path: - whl, wf = source_path.split('.whl' + os.path.sep) - whl += '.whl' - rootdir = wf.split(os.path.sep, 1)[0] - search_path.append(os.path.join(whl, rootdir, '.libs')) - - # Also look for more specific per-package cases, defined in - # PACKAGE_LIB_DIRS at the top of this file. - whl_name = os.path.basename(whl).split('-', 1)[0] - extra_dirs = PACKAGE_LIB_DIRS.get(whl_name, []) - for extra_dir in extra_dirs: - search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep))) - target_path = os.path.join(builddir, basename) + search_path = get_search_path_for(source_path) self.copy_with_dependencies(source_path, target_path, search_path) # Copy over the tcl directory. @@ -849,12 +853,15 @@ class build_apps(setuptools.Command): relpath = wf[len(source_dir) + 1:] source_path = os.path.join(whl, wf) target_path = os.path.join(target_dir, relpath) - self.copy(source_path, target_path) if 'PKG_DATA_MAKE_EXECUTABLE' in flags: + search_path = get_search_path_for(source_path) + self.copy_with_dependencies(source_path, target_path, search_path) mode = os.stat(target_path).st_mode mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH os.chmod(target_path, mode) + else: + self.copy(source_path, target_path) # Copy Game Files self.announce('Copying game files for platform: {}'.format(platform), distutils.log.INFO) From 1c4773a8e4f7505c18542e7216a03d8bff0d992f Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 7 Jan 2020 14:52:06 +0100 Subject: [PATCH 3/8] dist: move "import pip" from module level to download_wheels The aim of this is that pip is no longer a dependency to be able to run test_imports. --- direct/src/dist/commands.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 1b70a980f0..c9682bc864 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -8,7 +8,6 @@ from __future__ import print_function import collections import os -import pip import plistlib import sys import subprocess @@ -396,6 +395,8 @@ class build_apps(setuptools.Command): directory containing the Python runtime libraries, which will be added to sys.path.""" + import pip + self.announce('Gathering wheels for platform: {}'.format(platform), distutils.log.INFO) whldir = os.path.join(self.build_base, '__whl_cache__') From 27fe133df51423218bb8febcf55d19ef8cf9d2e9 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 7 Jan 2020 15:23:14 +0100 Subject: [PATCH 4/8] device: attempt to fix DualShock 4 analog axis mapping --- panda/src/device/winRawInputDevice.cxx | 28 ++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/panda/src/device/winRawInputDevice.cxx b/panda/src/device/winRawInputDevice.cxx index 3651f14fb8..2f36451cda 100644 --- a/panda/src/device/winRawInputDevice.cxx +++ b/panda/src/device/winRawInputDevice.cxx @@ -70,16 +70,16 @@ static const struct DeviceMapping { {"face_a", "face_b", 0, "face_x", "face_y", "rshoulder", "lshoulder", "rshoulder", 0, 0, 0, "start", 0, "lstick", "rstick", 0} }, // Dualshock (PS4) - {0x054c, 0x05c4, InputDevice::DeviceClass::gamepad, 0, - {"face_x", "face_a", "face_b", "face_y", "lshoulder", "rshoulder", "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} + {0x054c, 0x05c4, InputDevice::DeviceClass::gamepad, QB_rstick_from_z, + {"face_x", "face_a", "face_b", "face_y", 0, 0, "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} }, // Dualshock 2nd Gen (PS4 Slim) - {0x054c, 0x09cc, InputDevice::DeviceClass::gamepad, 0, - {"face_x", "face_a", "face_b", "face_y", "lshoulder", "rshoulder", "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} + {0x054c, 0x09cc, InputDevice::DeviceClass::gamepad, QB_rstick_from_z, + {"face_x", "face_a", "face_b", "face_y", 0, 0, "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} }, // Dualshock 2nd Gen (PS4 wireless adapter) - {0x054c, 0x0ba0, InputDevice::DeviceClass::gamepad, 0, - {"face_x", "face_a", "face_b", "face_y", "lshoulder", "rshoulder", "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} + {0x054c, 0x0ba0, InputDevice::DeviceClass::gamepad, QB_rstick_from_z, + {"face_x", "face_a", "face_b", "face_y", 0, 0, "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} }, {0}, }; @@ -475,14 +475,26 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { break; case HID_USAGE_GENERIC_RX: if (_device_class == DeviceClass::gamepad) { - axis = Axis::right_x; + if (quirks & QB_rstick_from_z) { + if ((quirks & QB_no_analog_triggers) == 0) { + axis = Axis::left_trigger; + } + } else { + axis = Axis::right_x; + } } else { axis = Axis::pitch; } break; case HID_USAGE_GENERIC_RY: if (_device_class == DeviceClass::gamepad) { - axis = Axis::right_y; + if (quirks & QB_rstick_from_z) { + if ((quirks & QB_no_analog_triggers) == 0) { + axis = Axis::right_trigger; + } + } else { + axis = Axis::right_y; + } } else { axis = Axis::roll; } From c9fb371e8734ec6eb06845152ea3822deedcb7ad Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 7 Jan 2020 21:25:26 +0100 Subject: [PATCH 5/8] device: correction for DualShock 4 support on Windows --- panda/src/device/winRawInputDevice.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/panda/src/device/winRawInputDevice.cxx b/panda/src/device/winRawInputDevice.cxx index 2f36451cda..9411ad508b 100644 --- a/panda/src/device/winRawInputDevice.cxx +++ b/panda/src/device/winRawInputDevice.cxx @@ -71,15 +71,15 @@ static const struct DeviceMapping { }, // Dualshock (PS4) {0x054c, 0x05c4, InputDevice::DeviceClass::gamepad, QB_rstick_from_z, - {"face_x", "face_a", "face_b", "face_y", 0, 0, "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} + {"face_x", "face_a", "face_b", "face_y", "lshoulder", "rshoulder", 0, 0, "back", "start", "lstick", "rstick", "guide", 0} }, // Dualshock 2nd Gen (PS4 Slim) {0x054c, 0x09cc, InputDevice::DeviceClass::gamepad, QB_rstick_from_z, - {"face_x", "face_a", "face_b", "face_y", 0, 0, "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} + {"face_x", "face_a", "face_b", "face_y", "lshoulder", "rshoulder", 0, 0, "back", "start", "lstick", "rstick", "guide", 0} }, // Dualshock 2nd Gen (PS4 wireless adapter) {0x054c, 0x0ba0, InputDevice::DeviceClass::gamepad, QB_rstick_from_z, - {"face_x", "face_a", "face_b", "face_y", 0, 0, "ltrigger", "rtrigger", "back", "start", "lstick", "rstick", "guide", 0} + {"face_x", "face_a", "face_b", "face_y", "lshoulder", "rshoulder", 0, 0, "back", "start", "lstick", "rstick", "guide", 0} }, {0}, }; @@ -494,11 +494,12 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { } } else { axis = Axis::right_y; + swap(cap.LogicalMin, cap.LogicalMax); } } else { axis = Axis::roll; + swap(cap.LogicalMin, cap.LogicalMax); } - swap(cap.LogicalMin, cap.LogicalMax); break; case HID_USAGE_GENERIC_RZ: if (_device_class == DeviceClass::gamepad) { From 6b12fbe6f23d3b8b8e0e80b86472c911bc4afa18 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 7 Jan 2020 21:41:04 +0100 Subject: [PATCH 6/8] dgui: show assertion when passing a NaN into DirectSlider If we don't do this, we get an assertion somewhere in the bowels of the scene graph, which will be much less helpful for tracking down the origin of the NaN. --- direct/src/gui/DirectSlider.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/direct/src/gui/DirectSlider.py b/direct/src/gui/DirectSlider.py index ddcd35d05d..037ffcfdf8 100644 --- a/direct/src/gui/DirectSlider.py +++ b/direct/src/gui/DirectSlider.py @@ -10,6 +10,7 @@ from panda3d.core import * from . import DirectGuiGlobals as DGG from .DirectFrame import * from .DirectButton import * +from math import isfinite """ import DirectSlider @@ -89,12 +90,15 @@ class DirectSlider(DirectFrame): def __setValue(self): # This is the internal function that is called when # self['value'] is directly assigned. - self.guiItem.setValue(self['value']) + value = self['value'] + assert isfinite(value) + self.guiItem.setValue(value) def setValue(self, value): # This is the public function that is meant to be called by a # user that doesn't like to use (or doesn't understand) the # preferred interface of self['value']. + assert isfinite(value) self['value'] = value def getValue(self): From cae7d55c8d3c795d3e903c4c732fd17625acc85c Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 7 Jan 2020 21:43:04 +0100 Subject: [PATCH 7/8] doc: add some more release notes for 1.10.5 --- doc/ReleaseNotes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index a89062a341..f706d7e495 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -11,8 +11,11 @@ This is a recommended bugfix release, especially for macOS users. * Fix NaN assertions when particles get very large positions (#822) * Add support for Autodesk Maya 2020 * Fix maya2egg erroring when running from a pip installation (#709) +* Support DualShock 4 (2nd gen) controller on Windows * Support .pz and .gz compressed models in deployment system * Support implicit namespace packages in deployment system (#778) +* Fix issues when using CEF Python on macOS with deployment system +* Fix deployment system issues reading .pyc files in some Python versions * Fix error with distutils package when deploying in a "virtualenv" env (#747) * Fix "NameError: name 'mdef' is not defined" error when deploying (#721) * Deployment system now strips weird -psn_* argument passed to macOS GUI apps From a50d375c35f65d35a17895b68b1769592adc4e3d Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 7 Jan 2020 22:07:39 +0100 Subject: [PATCH 8/8] dgui: fix DirectSlider regression on Python 2 --- direct/src/gui/DirectSlider.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/direct/src/gui/DirectSlider.py b/direct/src/gui/DirectSlider.py index 037ffcfdf8..c5823a9efc 100644 --- a/direct/src/gui/DirectSlider.py +++ b/direct/src/gui/DirectSlider.py @@ -10,7 +10,7 @@ from panda3d.core import * from . import DirectGuiGlobals as DGG from .DirectFrame import * from .DirectButton import * -from math import isfinite +from math import isnan """ import DirectSlider @@ -91,14 +91,14 @@ class DirectSlider(DirectFrame): # This is the internal function that is called when # self['value'] is directly assigned. value = self['value'] - assert isfinite(value) + assert not isnan(value) self.guiItem.setValue(value) def setValue(self, value): # This is the public function that is meant to be called by a # user that doesn't like to use (or doesn't understand) the # preferred interface of self['value']. - assert isfinite(value) + assert not isnan(value) self['value'] = value def getValue(self):