diff --git a/README.md b/README.md index 1a5af7deb8..59d4570c0e 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ macOS ----- On macOS, 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.10.4.1/panda3d-1.10.4.1-tools-mac.tar.gz). +compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.5/panda3d-1.10.5-tools-mac.tar.gz). After placing the thirdparty directory inside the panda3d source directory, you may build Panda3D using a command like the following: diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 6a2eafb0c9..4b5749860d 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -240,6 +240,9 @@ class build_apps(setuptools.Command): 'macosx_10_6_x86_64', 'win_amd64', ] + if sys.version_info >= (3, 8): + # This version of Python is only available for 10.9+. + self.platforms[1] = 'macosx_10_9_x86_64' self.plugins = [] self.embed_prc_data = True self.extra_prc_files = [] diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index 458406a1e0..49896c2109 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -304,6 +304,7 @@ class StreamIOWrapper(io.IOBase): self.__stream.clear() # clear eof flag self.__write(b) self.__lastWrite = True + return len(b) def writelines(self, lines): if not self.__writer: diff --git a/makepanda/installpanda.py b/makepanda/installpanda.py index 83e23bac2c..6d99d5ab36 100644 --- a/makepanda/installpanda.py +++ b/makepanda/installpanda.py @@ -277,3 +277,8 @@ if (__name__ == "__main__"): outputdir=options.outputdir, python_versions=ReadPythonVersionInfoFile()) print("Installation finished!") + + if not destdir: + warn_prefix = "%sNote:%s " % (GetColor("red"), GetColor()) + print(warn_prefix + "You may need to call this command to update the library cache:") + print(" sudo ldconfig") diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 49ffcd6962..779402455b 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -837,6 +837,7 @@ if (COMPILER=="GCC"): PkgDisable("OPENCV") if GetTarget() == "darwin" and not PkgSkip("OPENAL"): + LibName("OPENAL", "-framework AudioUnit") LibName("OPENAL", "-framework AudioToolbox") LibName("OPENAL", "-framework CoreAudio") @@ -1896,6 +1897,8 @@ def CompileRsrc(target, src, opts): ipath = GetListOption(opts, "DIR:") if os.path.isfile("/usr/bin/Rez"): cmd = "Rez -useDF" + elif os.path.isfile("/Library/Developer/CommandLineTools/usr/bin/Rez"): + cmd = "/Library/Developer/CommandLineTools/usr/bin/Rez -useDF" else: cmd = "/Developer/Tools/Rez -useDF" cmd += " -o " + BracketNameWithQuotes(target) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index e56d6aa159..c2fbfd203c 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -1690,18 +1690,20 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, LibName(target_pkg, "-framework " + framework) return - if os.path.isdir(os.path.join(pkg_dir, "include")): - IncDirectory(target_pkg, os.path.join(pkg_dir, "include")) + inc_dir = os.path.join(pkg_dir, "include") + if os.path.isdir(inc_dir): + IncDirectory(target_pkg, inc_dir) # Handle cases like freetype2 where the include dir is a subdir under "include" for i in incs: - if os.path.isdir(os.path.join(pkg_dir, "include", i)): - IncDirectory(target_pkg, os.path.join(pkg_dir, "include", i)) + if os.path.isdir(os.path.join(inc_dir, i)): + IncDirectory(target_pkg, os.path.join(inc_dir, i)) - lpath = [os.path.join(pkg_dir, "lib")] + lib_dir = os.path.join(pkg_dir, "lib") + lpath = [lib_dir] if not PkgSkip("PYTHON"): - py_lib_dir = os.path.join(pkg_dir, "lib", SDK["PYTHONVERSION"]) + py_lib_dir = os.path.join(lib_dir, SDK["PYTHONVERSION"]) if os.path.isdir(py_lib_dir): lpath.append(py_lib_dir) @@ -2383,7 +2385,9 @@ def SdkLocateMacOSX(osxtarget = None): if (GetHost() != "darwin"): return if (osxtarget != None): sdkname = "MacOSX%d.%d" % osxtarget - if (os.path.exists("/Developer/SDKs/%su.sdk" % sdkname)): + if (os.path.exists("/Library/Developer/CommandLineTools/SDKs/%s.sdk" % sdkname)): + SDK["MACOSX"] = "/Library/Developer/CommandLineTools/SDKs/%s.sdk" % sdkname + elif (os.path.exists("/Developer/SDKs/%su.sdk" % sdkname)): SDK["MACOSX"] = "/Developer/SDKs/%su.sdk" % sdkname elif (os.path.exists("/Developer/SDKs/%s.sdk" % sdkname)): SDK["MACOSX"] = "/Developer/SDKs/%s.sdk" % sdkname diff --git a/panda/src/device/evdevInputDevice.cxx b/panda/src/device/evdevInputDevice.cxx index 69d2979f7f..26bb83186e 100644 --- a/panda/src/device/evdevInputDevice.cxx +++ b/panda/src/device/evdevInputDevice.cxx @@ -364,7 +364,7 @@ init_device() { // Try to detect which type of device we have here if (_device_class == DeviceClass::unknown) { - int device_scores[(size_t)DeviceClass::spatial_mouse] = {0}; + int device_scores[(size_t)DeviceClass::digitizer + 1] = {0}; // Test for specific keys if (test_bit(BTN_GAMEPAD, keys) && test_bit(ABS_X, axes) && test_bit(ABS_RX, axes)) { @@ -385,6 +385,9 @@ init_device() { if (test_bit(BTN_MOUSE, keys) && test_bit(EV_REL, evtypes)) { device_scores[(size_t)DeviceClass::mouse] += 20; } + if (test_bit(BTN_DIGI, keys) && test_bit(EV_ABS, evtypes)) { + device_scores[(size_t)DeviceClass::digitizer] += 20; + } uint8_t unknown_keys[] = {KEY_POWER}; for (int i = 0; i < 1; i++) { if (test_bit(unknown_keys[i], keys)) { @@ -424,7 +427,7 @@ init_device() { // Check which device type got the most points int highest_score = 0; - for (size_t i = 0; i < (size_t)DeviceClass::spatial_mouse; i++) { + for (size_t i = 0; i <= (size_t)DeviceClass::digitizer; i++) { if (device_scores[i] > highest_score) { highest_score = device_scores[i]; _device_class = (DeviceClass)i; @@ -619,6 +622,9 @@ init_device() { have_analog_triggers = true; } break; + case ABS_PRESSURE: + axis = InputDevice::Axis::pressure; + break; } // Check the initial value and ranges. @@ -630,7 +636,8 @@ init_device() { // Also T.Flight Hotas X throttle is reversed and can go backwards. if (axis == Axis::yaw || axis == Axis::rudder || axis == Axis::left_y || axis == Axis::right_y || (axis == Axis::throttle && (quirks & QB_reversed_throttle) != 0) || - (_device_class == DeviceClass::spatial_mouse && (axis == Axis::y || axis == Axis::z || axis == Axis::roll))) { + (_device_class == DeviceClass::spatial_mouse && (axis == Axis::y || axis == Axis::z || axis == Axis::roll)) || + (_device_class == DeviceClass::digitizer && axis == Axis::y)) { std::swap(absinfo.maximum, absinfo.minimum); } if (axis == Axis::throttle && (quirks & QB_centered_throttle) != 0) { diff --git a/panda/src/device/inputDevice.cxx b/panda/src/device/inputDevice.cxx index cce2f975b4..71869abc64 100644 --- a/panda/src/device/inputDevice.cxx +++ b/panda/src/device/inputDevice.cxx @@ -578,6 +578,9 @@ format_device_class(DeviceClass dc) { case InputDevice::DeviceClass::spatial_mouse: return "spatial_mouse"; + + case InputDevice::DeviceClass::digitizer: + return "digitizer"; } return "**invalid**"; } @@ -644,6 +647,9 @@ format_axis(Axis axis) { case InputDevice::Axis::brake: return "brake"; + + case InputDevice::Axis::pressure: + return "pressure"; } return "**invalid**"; } diff --git a/panda/src/device/inputDevice.h b/panda/src/device/inputDevice.h index f3f500e378..83038075a8 100644 --- a/panda/src/device/inputDevice.h +++ b/panda/src/device/inputDevice.h @@ -80,6 +80,9 @@ PUBLISHED: // 3D mouse, such as produced by 3Dconnexion. spatial_mouse, + + // A graphics tablet with stylus/pen. + digitizer, }; enum class Feature { @@ -128,6 +131,9 @@ PUBLISHED: wheel, accelerator, brake, + + // Pen pressure + pressure, }; enum State { diff --git a/panda/src/device/phidsdi.h b/panda/src/device/phidsdi.h index 647b3ed322..5917155b0c 100644 --- a/panda/src/device/phidsdi.h +++ b/panda/src/device/phidsdi.h @@ -28,6 +28,7 @@ typedef USHORT USAGE, *PUSAGE; #define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07) #define HID_USAGE_PAGE_LED ((USAGE) 0x08) #define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09) +#define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0d) #define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01) #define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02) diff --git a/panda/src/device/winInputDeviceManager.cxx b/panda/src/device/winInputDeviceManager.cxx index 2ca4540ae6..0d2c69f216 100644 --- a/panda/src/device/winInputDeviceManager.cxx +++ b/panda/src/device/winInputDeviceManager.cxx @@ -14,6 +14,7 @@ #include "winInputDeviceManager.h" #include "winRawInputDevice.h" #include "throw_event.h" +#include "phidsdi.h" #if defined(_WIN32) && !defined(CPPPARSER) @@ -385,7 +386,7 @@ setup_message_loop() { } // Now listen for raw input devices using the created message loop. - RAWINPUTDEVICE rid[3]; + RAWINPUTDEVICE rid[4]; rid[0].usUsagePage = 1; rid[0].usUsage = 4; // Joysticks rid[0].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; @@ -398,7 +399,11 @@ setup_message_loop() { rid[2].usUsage = 8; // Multi-axis controllers (including 3D mice) rid[2].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; rid[2].hwndTarget = _message_hwnd; - if (!RegisterRawInputDevices(rid, 3, sizeof(RAWINPUTDEVICE))) { + rid[3].usUsagePage = HID_USAGE_PAGE_DIGITIZER; + rid[3].usUsage = 1; // Digitizers + rid[3].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; + rid[3].hwndTarget = _message_hwnd; + if (!RegisterRawInputDevices(rid, 4, sizeof(RAWINPUTDEVICE))) { device_cat.warning() << "Failed to register raw input devices.\n"; } diff --git a/panda/src/device/winRawInputDevice.cxx b/panda/src/device/winRawInputDevice.cxx index 10262d124c..843e434a16 100644 --- a/panda/src/device/winRawInputDevice.cxx +++ b/panda/src/device/winRawInputDevice.cxx @@ -199,6 +199,11 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { info.hid.usUsage == HID_USAGE_GENERIC_KEYBOARD) { _device_class = DeviceClass::keyboard; + // Digitizers + } else if (info.hid.usUsagePage == HID_USAGE_PAGE_DIGITIZER && + info.hid.usUsage == 1) { + _device_class = DeviceClass::digitizer; + // 3Dconnexion SpaceNavigator and friends. } else if (_vendor_id == 0x046d && (_product_id == 0xc623 || @@ -504,6 +509,14 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { continue; } break; + + case HID_USAGE_PAGE_DIGITIZER: + switch (usage) { + case 0x30: + axis = Axis::pressure; + break; + } + break; } // If this axis already exists, don't double-map it, but take the first