diff --git a/PsychPython/psychtoolbox/_version.py b/PsychPython/psychtoolbox/_version.py index c0fc086fe9..2b0559013d 100644 --- a/PsychPython/psychtoolbox/_version.py +++ b/PsychPython/psychtoolbox/_version.py @@ -1 +1 @@ -__version__ = '3.0.19.13' +__version__ = '3.0.19.14' diff --git a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.pbxproj b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.pbxproj index aae62da60f..c5081eac9f 100644 --- a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.pbxproj +++ b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.pbxproj @@ -88,7 +88,7 @@ /* Begin PBXFileReference section */ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 32BAE0B70371A74B00C91783 /* HID Utilities_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HID Utilities_Prefix.pch"; sourceTree = ""; }; - 83571B171551F7FD00EE961F /* libstatic library.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libstatic library.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; + 83571B171551F7FD00EE961F /* libHIDUtilities.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libHIDUtilities.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8D07F2C80486CC7A007CD1D0 /* HID Utilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "HID Utilities.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 97876DB31033682400AD1095 /* HID_Utilities_External.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HID_Utilities_External.h; sourceTree = ""; }; @@ -152,7 +152,7 @@ children = ( 8D07F2C80486CC7A007CD1D0 /* HID Utilities.framework */, 97F808C710347C9A00D58924 /* libHID_Utilities.dylib */, - 83571B171551F7FD00EE961F /* libstatic library.dylib */, + 83571B171551F7FD00EE961F /* libHIDUtilities.dylib */, ); name = Products; sourceTree = ""; @@ -267,7 +267,7 @@ ); name = "static library"; productName = "HID Utilities dylib"; - productReference = 83571B171551F7FD00EE961F /* libstatic library.dylib */; + productReference = 83571B171551F7FD00EE961F /* libHIDUtilities.dylib */; productType = "com.apple.product-type.library.dynamic"; }; 8D07F2BC0486CC7A007CD1D0 /* Framework */ = { @@ -319,6 +319,7 @@ developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( + English, en, ); mainGroup = 0867D691FE84028FC02AAC07 /* HID Utilities */; @@ -480,7 +481,7 @@ 4FADC24708B4156D00ABE55E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; DEPLOYMENT_LOCATION = YES; @@ -494,6 +495,7 @@ "DEBUG=1", "_NDEBUG=1", "NDEBUG=1", + "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=1", ); GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -512,8 +514,13 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LD_DYLIB_INSTALL_NAME = /usr/local/lib/libHID_Utilities64.a; - MACOSX_DEPLOYMENT_TARGET = 10.5; + INSTALL_PATH = ""; + "INSTALL_PATH[sdk=*]" = /usr/local/lib/; + LD_DYLIB_INSTALL_NAME = libHID_Utilities64.a; + MACOSX_DEPLOYMENT_TARGET = 10.13; + NEW_SETTING = ""; + NEW_SETTING1 = ""; + "NEW_SETTING[arch=*]" = " __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(value)", @@ -541,7 +548,7 @@ 4FADC24808B4156D00ABE55E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEPLOYMENT_LOCATION = YES; @@ -550,10 +557,17 @@ GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PRECOMPILE_PREFIX_HEADER = YES; + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = " __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=1"; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - LD_DYLIB_INSTALL_NAME = /usr/local/lib/libHID_Utilities64.a; - MACOSX_DEPLOYMENT_TARGET = 10.5; - ONLY_ACTIVE_ARCH = NO; + INSTALL_PATH = ""; + "INSTALL_PATH[sdk=*]" = /usr/local/lib/; + LD_DYLIB_INSTALL_NAME = libHID_Utilities64.a; + "LD_DYLIB_INSTALL_NAME[sdk=macosx*]" = libHID_Utilities64.a; + MACOSX_DEPLOYMENT_TARGET = 10.13; + NEW_SETTING = ""; + NEW_SETTING1 = ""; + "NEW_SETTING[arch=*]" = " __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"; + ONLY_ACTIVE_ARCH = YES; ZERO_LINK = NO; }; name = Release; @@ -565,6 +579,7 @@ GCC_DYNAMIC_NO_PIC = NO; INSTALL_PATH = /usr/local/lib; MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_NAME = HIDUtilities; }; name = Debug; @@ -575,6 +590,7 @@ EXECUTABLE_PREFIX = lib; INSTALL_PATH = /usr/local/lib; MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_NAME = HIDUtilities; }; name = Release; @@ -582,6 +598,7 @@ 97F808C810347C9C00D58924 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; EXECUTABLE_PREFIX = lib; GCC_DYNAMIC_NO_PIC = NO; INSTALL_PATH = /usr/local/lib; @@ -592,6 +609,7 @@ 97F808C910347C9C00D58924 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; EXECUTABLE_PREFIX = lib; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = HID_Utilities; diff --git a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/UserInterfaceState.xcuserstate b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/UserInterfaceState.xcuserstate index 955b9bedf8..3af1e786d6 100644 Binary files a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/UserInterfaceState.xcuserstate and b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/WorkspaceSettings.xcsettings b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/WorkspaceSettings.xcsettings index 659c8766e0..4eff6a6bad 100644 --- a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/WorkspaceSettings.xcsettings +++ b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/project.xcworkspace/xcuserdata/kleinerm.xcuserdatad/WorkspaceSettings.xcsettings @@ -2,8 +2,16 @@ + BuildLocationStyle + UseAppPreferences + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + ShowSharedSchemesAutomaticallyEnabled + SnapshotAutomaticallyBeforeSignificantChanges diff --git a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/xcuserdata/kleinerm.xcuserdatad/xcschemes/dynamic library copy.xcscheme b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/xcuserdata/kleinerm.xcuserdatad/xcschemes/dynamic library copy.xcscheme index 0af7c90453..86127a66cb 100644 --- a/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/xcuserdata/kleinerm.xcuserdatad/xcschemes/dynamic library copy.xcscheme +++ b/PsychSourceGL/Cohorts/HID_Utilities_64Bit/HID Utilities.xcodeproj/xcuserdata/kleinerm.xcuserdatad/xcschemes/dynamic library copy.xcscheme @@ -14,7 +14,7 @@ @@ -22,30 +22,29 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> - - 1) ? "MIGHT leak if caller does not take care." : ""); + pStructInner, Py_REFCNT(pStructInner), + (Py_REFCNT(pStructInner) > 1) ? "MIGHT leak if caller does not take care." : ""); if (!mxIsStruct(pStructOuter)) { Py_XDECREF(pStructInner); @@ -1123,9 +1123,9 @@ PyObject* PsychScriptingGluePythonDispatch(PyObject* self, PyObject* args) // and just need to return return arguments and clean up: if (psych_refcount_debug) { for (i = 0; i < MAX_OUTPUT_ARGS; i++) { - if (plhsGLUE[recLevel][i] && (PyArray_REFCOUNT(plhsGLUE[recLevel][i]) >= psych_refcount_debug)) + if (plhsGLUE[recLevel][i] && (Py_REFCNT(plhsGLUE[recLevel][i]) >= psych_refcount_debug)) printf("PTB-DEBUG: At non-error exit of PsychScriptingGluePythonDispatch: Refcount of plhsGLUE[recLevel %i][arg %i] = %li.\n", - recLevel, i, PyArray_REFCOUNT(plhsGLUE[recLevel][i])); + recLevel, i, Py_REFCNT(plhsGLUE[recLevel][i])); } } @@ -1202,9 +1202,9 @@ PyObject* PsychScriptingGluePythonDispatch(PyObject* self, PyObject* args) // Release "orphaned" output arguments that haven't been returned to the interpreter, // e.g., because of a PythonFunctionCleanup - error return: for (i = 0; i < MAX_OUTPUT_ARGS; i++) { - if (psych_refcount_debug && plhsGLUE[recLevel][i] && (PyArray_REFCOUNT(plhsGLUE[recLevel][i]) >= psych_refcount_debug)) + if (psych_refcount_debug && plhsGLUE[recLevel][i] && (Py_REFCNT(plhsGLUE[recLevel][i]) >= psych_refcount_debug)) printf("PTB-DEBUG: Orphaned output argument at cleanup: Refcount of plhsGLUE[recLevel %i][arg %i] = %li --> unref --> %li.\n", - recLevel, i, PyArray_REFCOUNT(plhsGLUE[recLevel][i]), PyArray_REFCOUNT(plhsGLUE[recLevel][i]) - 1); + recLevel, i, Py_REFCNT(plhsGLUE[recLevel][i]), Py_REFCNT(plhsGLUE[recLevel][i]) - 1); Py_XDECREF(plhsGLUE[recLevel][i]); plhsGLUE[recLevel][i] = NULL; @@ -1254,9 +1254,9 @@ static PyObject* PsychPyArgGet(int position) { PyObject *ret = prhsGLUE[recLevel][position]; - if (psych_refcount_debug && (PyArray_REFCOUNT(prhsGLUE[recLevel][position]) >= psych_refcount_debug)) + if (psych_refcount_debug && (Py_REFCNT(prhsGLUE[recLevel][position]) >= psych_refcount_debug)) printf("PTB-DEBUG:%s:PsychPyArgGet: Before convert: Refcount of prhsGLUE[recLevel %i][arg %i] = %li.\n", - PsychGetFunctionName(), recLevel, position, PyArray_REFCOUNT(prhsGLUE[recLevel][position])); + PsychGetFunctionName(), recLevel, position, Py_REFCNT(prhsGLUE[recLevel][position])); // Does this input argument need conversion to a NumPy array of suitable format? if (prhsNeedsConversion[recLevel][position]) { @@ -1279,7 +1279,7 @@ static PyObject* PsychPyArgGet(int position) if (DEBUG_PTBPYTHONGLUE || psych_refcount_debug) printf("PTB-DEBUG:%s:PsychPyArgGet: Arg %i: Conversion to NumPy array of %s triggered [refcount now %li]: %s\n", PsychGetFunctionName(), - position, use_C_memory_layout[recLevel] ? "C layout" : "Fortran layout", PyArray_REFCOUNT(ret), + position, use_C_memory_layout[recLevel] ? "C layout" : "Fortran layout", Py_REFCNT(ret), (ret == prhsGLUE[recLevel][position]) ? "No-Op passthrough." : "New object."); // Now that the new ret is a NumPy array in the wanted final format, @@ -1296,9 +1296,9 @@ static PyObject* PsychPyArgGet(int position) // by dropping its refcount by one to zero. } - if (psych_refcount_debug && (PyArray_REFCOUNT(prhsGLUE[recLevel][position]) >= psych_refcount_debug)) + if (psych_refcount_debug && (Py_REFCNT(prhsGLUE[recLevel][position]) >= psych_refcount_debug)) printf("PTB-DEBUG:%s:PsychPyArgGet: After convert: Refcount of prhsGLUE[recLevel %i][arg %i] = %li.\n", - PsychGetFunctionName(), recLevel, position, PyArray_REFCOUNT(prhsGLUE[recLevel][position])); + PsychGetFunctionName(), recLevel, position, Py_REFCNT(prhsGLUE[recLevel][position])); return(ret); } @@ -2980,8 +2980,8 @@ int PsychRuntimePutVariable(const char* workspace, const char* variable, PsychGe if (psych_refcount_debug && pcontent) printf("PTB-DEBUG: In mxSetField: refcount of external object %p at enter is %li. %s\n", - pcontent, PyArray_REFCOUNT(pcontent), - (PyArray_REFCOUNT(pcontent) > 1) ? "MIGHT leak if caller does not take care." : ""); + pcontent, Py_REFCNT(pcontent), + (Py_REFCNT(pcontent) > 1) ? "MIGHT leak if caller does not take care." : ""); // Drop one reference, so the function steals a reference to pcontent and the // calling client is no longer responsible for managing it, regardless of success diff --git a/PsychSourceGL/Source/Common/PsychOpenXRCore/PsychOpenXRCore.c b/PsychSourceGL/Source/Common/PsychOpenXRCore/PsychOpenXRCore.c index f4b4611d2f..81d1ec49b7 100644 --- a/PsychSourceGL/Source/Common/PsychOpenXRCore/PsychOpenXRCore.c +++ b/PsychSourceGL/Source/Common/PsychOpenXRCore/PsychOpenXRCore.c @@ -162,6 +162,8 @@ typedef struct PsychOpenXRDevice { XrSpace gazePoseSpace; XrSpace handPoseSpace[2]; int hasEyeTracking; + int hasHandTracking; + XrHandTrackerEXT handTracker[2]; psych_bool isTracking; // MT mutex. psych_bool needLocate; // MT mutex. int viewLayerType; // MT mutex. @@ -221,6 +223,7 @@ static psych_bool has_XR_HTC_vive_cosmos_controller_interaction = FALSE; static psych_bool has_XR_HTC_vive_focus3_controller_interaction = FALSE; static psych_bool has_XR_EXT_eye_gaze_interaction = FALSE; static psych_bool has_XR_EXT_dpad_binding = FALSE; +static psych_bool has_XR_EXT_hand_tracking = FALSE; // Shared debug messenger for the whole process: XrDebugUtilsMessengerEXT debugMessenger = XR_NULL_HANDLE; @@ -236,6 +239,7 @@ static unsigned int devicecount = 0; // List and count of available XR system devices for use: XrSystemEyeGazeInteractionPropertiesEXT eyeGazeAvailable[MAX_PSYCH_OPENXR_DEVS]; +XrSystemHandTrackingPropertiesEXT handTrackingAvailable[MAX_PSYCH_OPENXR_DEVS]; XrSystemProperties availableSystems[MAX_PSYCH_OPENXR_DEVS]; static int numAvailableDevices = 0; @@ -263,6 +267,11 @@ PFN_xrGetOpenGLGraphicsRequirementsKHR pxrGetOpenGLGraphicsRequirementsKHR = NUL // XR_FB_display_refresh_rate for HMD video refresh rate query and control: PFN_xrGetDisplayRefreshRateFB pxrGetDisplayRefreshRateFB = NULL; +// XR_EXT_hand_tracking for articulated hand and finger tracking: +PFN_xrCreateHandTrackerEXT pxrCreateHandTrackerEXT = NULL; +PFN_xrLocateHandJointsEXT pxrLocateHandJointsEXT = NULL; +PFN_xrDestroyHandTrackerEXT pxrDestroyHandTrackerEXT = NULL; + #if defined(XR_USE_PLATFORM_WIN32) // XR_KHR_WIN32_convert_performance_counter_time for MS-Windows timestamp mapping: PFN_xrConvertWin32PerformanceCounterToTimeKHR pxrConvertWin32PerformanceCounterToTimeKHR = NULL; @@ -327,7 +336,7 @@ void InitializeSynopsis(void) synopsis[i++] = ""; synopsis[i++] = "oldVerbosity = PsychOpenXRCore('Verbosity' [, verbosity]);"; synopsis[i++] = "numDevices = PsychOpenXRCore('GetCount');"; - synopsis[i++] = "[openxrPtr, modelName, runtimeName, hasEyeTracking] = PsychOpenXRCore('Open' [, deviceIndex=0]);"; + synopsis[i++] = "[openxrPtr, modelName, runtimeName, hasEyeTracking, hasHandTracking] = PsychOpenXRCore('Open' [, deviceIndex=0]);"; synopsis[i++] = "PsychOpenXRCore('Close' [, openxrPtr]);"; synopsis[i++] = "controllerTypes = PsychOpenXRCore('Controllers', openxrPtr);"; synopsis[i++] = "[oldType, spaceSize] = PsychOpenXRCore('ReferenceSpaceType', openxrPtr [, newType]);"; @@ -337,7 +346,7 @@ void InitializeSynopsis(void) synopsis[i++] = "oldEnable = PsychOpenXRCore('PresenterThreadEnable', openxrPtr [, enableThread]);"; synopsis[i++] = "PsychOpenXRCore('Start', openxrPtr);"; synopsis[i++] = "PsychOpenXRCore('Stop', openxrPtr);"; - synopsis[i++] = "[state, touch, gaze] = PsychOpenXRCore('GetTrackingState', openxrPtr [, predictionTime=nextFrame][, reqMask=all]);"; + synopsis[i++] = "[state, touch, gaze, hands] = PsychOpenXRCore('GetTrackingState', openxrPtr [, predictionTime=nextFrame][, reqMask=all]);"; synopsis[i++] = "input = PsychOpenXRCore('GetInputState', openxrPtr, controllerType);"; synopsis[i++] = "pulseEndTime = PsychOpenXRCore('HapticPulse', openxrPtr, controllerType [, duration=2.5][, freq][, amplitude=1.0]);"; synopsis[i++] = "[projL, projR, fovL, fovR] = PsychOpenXRCore('GetStaticRenderParameters', openxrPtr [, clipNear=0.01][, clipFar=10000.0]);"; @@ -885,6 +894,11 @@ static int enumerateXRDevices(XrInstance instance) { if (has_XR_EXT_eye_gaze_interaction) availableSystems[numAvailableDevices].next = &eyeGazeAvailable[numAvailableDevices]; + if (has_XR_EXT_hand_tracking) { + handTrackingAvailable[numAvailableDevices].next = availableSystems[numAvailableDevices].next; + availableSystems[numAvailableDevices].next = &handTrackingAvailable[numAvailableDevices]; + } + // Got a hardware XR system. Query and store its properties and systemId: result = xrGetSystemProperties(instance, systemId, &availableSystems[numAvailableDevices]); if (!resultOK(result)) { @@ -896,7 +910,7 @@ static int enumerateXRDevices(XrInstance instance) { } if (verbosity > 3) { - printf("PsychOpenXRCore-INFO: %i. XR system: VendorId 0x%x : \"%s\" : orientationTracking %i : positionTracking %i : %i layers of max size %i x %i : Gaze tracking: %i.\n", + printf("PsychOpenXRCore-INFO: %i. XR system: VendorId 0x%x : \"%s\" : orientationTracking %i : positionTracking %i : %i layers of max size %i x %i : Gaze tracking: %i : Hand tracking: %i.\n", numAvailableDevices, availableSystems[numAvailableDevices].vendorId, availableSystems[numAvailableDevices].systemName, availableSystems[numAvailableDevices].trackingProperties.orientationTracking, @@ -904,7 +918,8 @@ static int enumerateXRDevices(XrInstance instance) { availableSystems[numAvailableDevices].graphicsProperties.maxLayerCount, availableSystems[numAvailableDevices].graphicsProperties.maxSwapchainImageWidth, availableSystems[numAvailableDevices].graphicsProperties.maxSwapchainImageHeight, - eyeGazeAvailable[numAvailableDevices].supportsEyeGazeInteraction); + eyeGazeAvailable[numAvailableDevices].supportsEyeGazeInteraction, + handTrackingAvailable[numAvailableDevices].supportsHandTracking); } // Increment count of available devices: @@ -2162,6 +2177,9 @@ void PsychOpenXRCheckInit(psych_bool dontfail) // Enable basic eye tracking extension: has_XR_EXT_eye_gaze_interaction = addInstanceExtension(instanceExtensions, instanceExtensionsCount, XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME); + // Enable basic hand tracking extension: + has_XR_EXT_hand_tracking = addInstanceExtension(instanceExtensions, instanceExtensionsCount, XR_EXT_HAND_TRACKING_EXTENSION_NAME); + // XR_KHR_binding_modification supported? If so, try to enable extensions which depend on it: if (addInstanceExtension(instanceExtensions, instanceExtensionsCount, XR_KHR_BINDING_MODIFICATION_EXTENSION_NAME)) { has_XR_EXT_dpad_binding = addInstanceExtension(instanceExtensions, instanceExtensionsCount, XR_EXT_DPAD_BINDING_EXTENSION_NAME); @@ -2239,6 +2257,13 @@ void PsychOpenXRCheckInit(psych_bool dontfail) GET_INSTANCE_PROC_ADDR(xrInstance, xrGetDisplayRefreshRateFB); } + // Bind optional articulated hand and finger tracking functions: + if (has_XR_EXT_hand_tracking) { + GET_INSTANCE_PROC_ADDR(xrInstance, xrCreateHandTrackerEXT); + GET_INSTANCE_PROC_ADDR(xrInstance, xrLocateHandJointsEXT); + GET_INSTANCE_PROC_ADDR(xrInstance, xrDestroyHandTrackerEXT); + } + #if defined(XR_USE_PLATFORM_WIN32) GET_INSTANCE_PROC_ADDR(xrInstance, xrConvertWin32PerformanceCounterToTimeKHR); GET_INSTANCE_PROC_ADDR(xrInstance, xrConvertTimeToWin32PerformanceCounterKHR); @@ -2372,6 +2397,16 @@ void PsychOpenXRClose(int handle) openxr->textureSwapChainLength[1] = 0; } + // Destroy hand trackers, if any active: + if (openxr->handTracker[0]) + pxrDestroyHandTrackerEXT(openxr->handTracker[0]); + + if (openxr->handTracker[1]) + pxrDestroyHandTrackerEXT(openxr->handTracker[1]); + + openxr->handTracker[0] = XR_NULL_HANDLE; + openxr->handTracker[1] = XR_NULL_HANDLE; + // Close the HMD aka XrSession: xrDestroySession(openxr->hmd); hasHadSession = TRUE; @@ -2456,6 +2491,8 @@ void PsychOpenXRCoreInit(void) { } for (handle = 0 ; handle < MAX_PSYCH_OPENXR_DEVS; handle++) { + memset(&handTrackingAvailable[handle], 0, sizeof(handTrackingAvailable[0])); + handTrackingAvailable[handle].type = XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT; memset(&eyeGazeAvailable[handle], 0, sizeof(eyeGazeAvailable[0])); eyeGazeAvailable[handle].type = XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT; memset(&availableSystems[handle], 0, sizeof(availableSystems[0])); @@ -2532,8 +2569,8 @@ PsychError PSYCHOPENXRGetCount(void) PsychError PSYCHOPENXROpen(void) { - static char useString[] = "[openxrPtr, modelName, runtimeName, hasEyeTracking] = PsychOpenXRCore('Open' [, deviceIndex=0]);"; - // 1 2 3 4 1 + static char useString[] = "[openxrPtr, modelName, runtimeName, hasEyeTracking, hasHandTracking] = PsychOpenXRCore('Open' [, deviceIndex=0]);"; + // 1 2 3 4 5 1 static char synopsisString[] = "Open connection to OpenXR device, return a 'openxrPtr' handle to it.\n\n" "The call tries to open the device with index 'deviceIndex', or the first detected " @@ -2543,7 +2580,8 @@ PsychError PSYCHOPENXROpen(void) "The returned handle can be passed to the other subfunctions to operate the device.\n" "'modelName' returns the model name string of the OpenXR device.\n" "'runtimeName' returns the name of the OpenXR runtime.\n" - "'hasEyeTracking' returns the level of eye tracking support: 0 = None, 1 = Basic.\n"; + "'hasEyeTracking' returns the level of eye tracking support: 0 = None, 1 = Basic.\n" + "'hasHandTracking' returns the level of hand tracking support: 0 = None, 1 = Basic.\n"; static char seeAlsoString[] = "GetCount Close"; PsychOpenXRDevice* openxr; @@ -2556,7 +2594,7 @@ PsychError PSYCHOPENXROpen(void) if (PsychIsGiveHelp()) { PsychGiveHelp(); return(PsychError_none); }; // Check to see if the user supplied superfluous arguments: - PsychErrorExit(PsychCapNumOutputArgs(4)); + PsychErrorExit(PsychCapNumOutputArgs(5)); PsychErrorExit(PsychCapNumInputArgs(1)); // Make sure driver is initialized: @@ -2596,14 +2634,17 @@ PsychError PSYCHOPENXROpen(void) // Record if basic eye gaze tracking is available: openxr->hasEyeTracking = eyeGazeAvailable[deviceIndex].supportsEyeGazeInteraction ? 1 : 0; + // Record if basic hand tracking is available: + openxr->hasHandTracking = handTrackingAvailable[deviceIndex].supportsHandTracking ? 0 : 0; + // Use a fixed stereo view type by default for now, for typical HMD use: openxr->viewType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; // Stats for nerds: if (verbosity >= 3) { printf("PsychOpenXRCore-INFO: Opened OpenXR device with deviceIndex %i as handle %i.\n", deviceIndex, handle + 1); - printf("PsychOpenXRCore-INFO: Product: \"%s\" - [VendorId: 0x%x eyeTracking: %i]\n", availableSystems[deviceIndex].systemName, availableSystems[deviceIndex].vendorId, openxr->hasEyeTracking); - printf("PsychOpenXRCore-INFO: ----------------------------------------------------------------------------------\n"); + printf("PsychOpenXRCore-INFO: Product: \"%s\" - [VendorId: 0x%x eyeTracking: %i handJointsTracking: %i]\n", availableSystems[deviceIndex].systemName, availableSystems[deviceIndex].vendorId, openxr->hasEyeTracking, openxr->hasHandTracking); + printf("PsychOpenXRCore-INFO: -----------------------------------------------------------------------------------------------\n"); } // Assign multi-threading mode as "off" by default: @@ -2644,6 +2685,9 @@ PsychError PSYCHOPENXROpen(void) // Return eye tracking support level: PsychCopyOutDoubleArg(4, kPsychArgOptional, openxr->hasEyeTracking); + // Return hand tracking support level: + PsychCopyOutDoubleArg(5, kPsychArgOptional, openxr->hasHandTracking); + return(PsychError_none); } @@ -3210,10 +3254,30 @@ PsychError PSYCHOPENXRStop(void) return(PsychError_none); } +static PsychError PsychOpenXRTrackHands(PsychOpenXRDevice* openxr, int outArgPos, XrTime xrPredictionTime) +{ + const char *FieldNamesHand[] = { "Tracked", "Joints" }; + const int FieldCountHand = 2; + + int StatusFlags; + PsychGenericScriptType *status; + PsychGenericScriptType *outMat; + double *v; + + if (openxr->hasHandTracking) { + } + else { + // Allocate out an empty struct: + PsychAllocOutStructArray(outArgPos, kPsychArgOptional, -1, FieldCountHand, FieldNamesHand, &status); + } + + return(PsychError_none); +} + PsychError PSYCHOPENXRGetTrackingState(void) { - static char useString[] = "[state, touch, gaze] = PsychOpenXRCore('GetTrackingState', openxrPtr [, predictionTime=nextFrame][, reqMask=all]);"; - // 1 2 3 1 2 3 + static char useString[] = "[state, touch, gaze, hands] = PsychOpenXRCore('GetTrackingState', openxrPtr [, predictionTime=nextFrame][, reqMask=all]);"; + // 1 2 3 4 1 2 3 static char synopsisString[] = "Return current state of position and orientation tracking for OpenXR device 'openxrPtr'.\n" "Position and orientation is predicted for target time 'predictionTime' in seconds if provided, " @@ -3221,7 +3285,8 @@ PsychError PSYCHOPENXRGetTrackingState(void) "then the prediction is performed for the mid-point of the next possible video frame of the device, ie. " "the most likely presentation time for immediately rendered images.\n" "'reqMask' mask defining which information to return. Defaults to all information. Values are " - "+1 for head/eye tracking, +2 for hand controller tracking, +4 for eye gaze tracking.\n\n" + "+1 for head/eye tracking, +2 for hand controller tracking, +4 for eye gaze tracking, " + "+8 for articulated hand and finger tracking (Not yet supported in this driver release).\n\n" "'state' is a struct with fields reporting the following values:\n" "'Time' = Time in seconds of returned tracking state.\n" "'Status' = Tracking status flags:\n" @@ -3279,6 +3344,23 @@ PsychError PSYCHOPENXRGetTrackingState(void) "+1 = Some gaze info available, but not based on measurements. Consider this not trustworthy at all!\n" "+2 = Tracked gaze position available. This is possibly subject to interpolation or extrapolation.\n" "'GazePose' = Position and orientation of the eye, expressing a gaze vector in its usual [x,y,z,rx,ry,rz,rw] form.\n" + " \n" + "Articulated hand tracking on supported hardware: PRELIMINARY DOCS, SUBJECT TO INCOMPATIBLE CHANGES!\n" + " \n" + "The return argument 'hands' is a struct array with 2 structs, one for each hand. hands(1) returns " + "information about the left hand, hands(2) returns information about the right hand.\n" + "Each struct has the following fields:\n" + "'Tracked' The tracking status of the hand. 0 if the hand was not tracked and all further info is invalid, " + "or 1 if at least part of the hand was tracked and some of the per-joint tracking info is valid.\n" + "'Joints' A 9 rows by 26 column double matrix, where the rows of each column encode tracked info about " + "one joint. Specific column indices correspond to specific named joints on the hand. The indices are standardized " + "in the OpenXR specification for the XR_EXT_hand_tracking extension, which specifies 26 separate joints per hand. " + "See section 12.30.6 \"Conventions of hand joints\" of the OpenXR extension spec for joint names, indices and reference.\n" + " \n" + "Row 1 of the matrix encodes tracking status: 0 = No info about this joint, 1 = Some inter-/extrapolated info, 3 = Fully tracked.\n" + "Row 2 encodes the radius in meters of this joint - The estimated distance from joint axis to skin of the hand.\n" + "Rows 3-5 encode the 3D [x; y; z] position in meters of the joint in the tracking reference space.\n" + "Rows 6-9 define the [rx; ry; rz; rw] quaternion, encoding the relative orientation of the joint with respect to the tracking reference space.\n" "\n"; static char seeAlsoString[] = "Start Stop GetTrackersState GetInputState"; @@ -3304,7 +3386,7 @@ PsychError PSYCHOPENXRGetTrackingState(void) if (PsychIsGiveHelp()) { PsychGiveHelp(); return(PsychError_none); }; // Check to see if the user supplied superfluous arguments: - PsychErrorExit(PsychCapNumOutputArgs(3)); + PsychErrorExit(PsychCapNumOutputArgs(4)); PsychErrorExit(PsychCapNumInputArgs(3)); PsychErrorExit(PsychRequireNumInputArgs(1)); @@ -3320,8 +3402,8 @@ PsychError PSYCHOPENXRGetTrackingState(void) // Get optional info requirements mask: PsychCopyInIntegerArg(3, kPsychArgOptional, &reqMask); - if (reqMask < 0 || reqMask > 7) - PsychErrorExitMsg(PsychError_user, "Invalid 'reqMask' specified. Valid values are 0 to 7."); + if (reqMask < 0 || reqMask > 15) + PsychErrorExitMsg(PsychError_user, "Invalid 'reqMask' specified. Valid values are 0 to 15."); // Lock protect openxr->predictedDisplayTime and locateXRViews() and return of // all views[] info and viewState info below: @@ -3626,6 +3708,15 @@ PsychError PSYCHOPENXRGetTrackingState(void) PsychAllocOutStructArray(3, kPsychArgOptional, -1, FieldCount3, FieldNames3, &status); } + // Articulated hand tracking requested? + if (reqMask & 8) { + PsychOpenXRTrackHands(openxr, 4, xrPredictionTime); + } + else { + // Allocate out an empty struct: + PsychAllocOutStructArray(4, kPsychArgOptional, -1, 0, NULL, &status); + } + return(PsychError_none); } diff --git a/PsychSourceGL/Source/Common/Screen/PsychMovieSupportGStreamer.c b/PsychSourceGL/Source/Common/Screen/PsychMovieSupportGStreamer.c index 1b308f0e79..52ec15e5f2 100644 --- a/PsychSourceGL/Source/Common/Screen/PsychMovieSupportGStreamer.c +++ b/PsychSourceGL/Source/Common/Screen/PsychMovieSupportGStreamer.c @@ -1960,19 +1960,6 @@ void PsychGSCreateMovie(PsychWindowRecordType *win, const char* moviename, doubl return; } } - else if (PSYCH_SYSTEM == PSYCH_LINUX) { - // Need a workaround for Pulseaudio 16.x libpulse bugs shipping without fix in at least Ubuntu 22.04 - 24.04. - // See: https://github.com/Psychtoolbox-3/Psychtoolbox-3/issues/814 - // Try to use pipewiresink as audio sink, directly connecting to the pipewire audio server, as this - // circumvents the bug, at least on Ubuntu 24.04.0-LTS and later: - audiosink = gst_element_factory_make("pipewiresink", NULL); - if (audiosink) { - g_object_set(G_OBJECT(theMovie), "audio-sink", audiosink, NULL); - audiosink = NULL; - if (PsychPrefStateGet_Verbosity() > 3) - printf("PTB-INFO: Workaround: Attached pipewiresink audio sink for lag-less playback of movie on Ubuntu 24.04+.\n"); - } - } // Preload / Preroll the pipeline: if (!PsychMoviePipelineSetState(theMovie, GST_STATE_PAUSED, 30.0)) { diff --git a/PsychSourceGL/Source/Common/Screen/SCREENDrawDots.c b/PsychSourceGL/Source/Common/Screen/SCREENDrawDots.c index 5b9a1fdaaa..84043fa2a5 100644 --- a/PsychSourceGL/Source/Common/Screen/SCREENDrawDots.c +++ b/PsychSourceGL/Source/Common/Screen/SCREENDrawDots.c @@ -91,6 +91,7 @@ char PointSmoothVertexShaderSrc[] = "/* delivers individual point size (diameter) information for each point. */ \n" "\n" "uniform int useUnclampedFragColor;\n" +"uniform int drawRoundDots;\n" "varying float pointSize;\n" "varying vec4 unclampedFragColor;\n" "\n" @@ -111,7 +112,9 @@ char PointSmoothVertexShaderSrc[] = " /* Point size comes via texture coordinate set 2: Make diameter 2 pixels bigger */\n" " /* than requested, to have some 1 pixel security margin around the dot, to avoid */\n" " /* cutoff artifacts for the rendered point-sprite quad. Compensate in frag-shader. */\n" -" pointSize = gl_MultiTexCoord2[0] + 2.0;\n" +" /* Only apply the margin to round dots. */\n" +" float margin = drawRoundDots > 0 ? 2.0 : 0.0;\n" +" pointSize = gl_MultiTexCoord2[0] + margin;\n" " gl_PointSize = pointSize;\n" "}\n\0"; diff --git a/PsychSourceGL/Source/osxsetoctaverpath.m b/PsychSourceGL/Source/osxsetoctaverpath.m index 12fe603768..247e9e701d 100644 --- a/PsychSourceGL/Source/osxsetoctaverpath.m +++ b/PsychSourceGL/Source/osxsetoctaverpath.m @@ -17,8 +17,8 @@ function osxsetoctaverpath(mexfname, mexpath) % runtime libraries into the mex file folder of PTB, so the mex % files should always find a dylib for the currently running Octave. - if ~IsOSX(1) || ~IsOctave || ~compare_versions(version, '9.1.0', '==') - error('osxsetoctaverpath only works with a 64-Bit version of HomeBrew Octave-9.1.0 for macOS!'); + if ~IsOSX(1) || ~IsOctave || ~compare_versions(version, '9.2.0', '==') + error('osxsetoctaverpath only works with a 64-Bit version of HomeBrew Octave-9.2.0 for macOS!'); end % If no mex filename given, iterate over 'mexpath' - or the default install @@ -59,9 +59,9 @@ function osxsetoctaverpath(mexfname, mexpath) % the latest macOS linker crap - Hardcoding the path for a Octave install % from HomeBrew. Yes, this is sad... if IsARM - libdir = '/opt/homebrew/opt/octave/lib/octave/9.1.0'; + libdir = '/opt/homebrew/opt/octave/lib/octave/9.2.0'; else - libdir = '/usr/local/opt/octave/lib/octave/9.1.0'; + libdir = '/usr/local/opt/octave/lib/octave/9.2.0'; end % Replace absolute path to liboctinterp.12.dylib with @rpath: diff --git a/Psychtoolbox/PsychBasic/Eyelink.mexa64 b/Psychtoolbox/PsychBasic/Eyelink.mexa64 old mode 100755 new mode 100644 diff --git a/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychOpenXRCore.mexw64 b/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychOpenXRCore.mexw64 index ffdce65103..65b37e714b 100644 Binary files a/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychOpenXRCore.mexw64 and b/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychOpenXRCore.mexw64 differ diff --git a/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychPortAudio.mexw64 b/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychPortAudio.mexw64 index a6eb13bf95..0607bcaffd 100644 Binary files a/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychPortAudio.mexw64 and b/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/PsychPortAudio.mexw64 differ diff --git a/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/Screen.mexw64 b/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/Screen.mexw64 index 32078830da..7374866d3f 100644 Binary files a/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/Screen.mexw64 and b/Psychtoolbox/PsychBasic/MatlabWindowsFilesR2007a/Screen.mexw64 differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/GetSecs.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/GetSecs.mex index b5543108bc..9ebcca0258 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/GetSecs.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/GetSecs.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/IOPort.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/IOPort.mex index 16f95f57d2..09f1ca1ef3 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/IOPort.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/IOPort.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/NothingToSeeHere.txt b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/NothingToSeeHere.txt deleted file mode 100644 index 0934d0d485..0000000000 --- a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/NothingToSeeHere.txt +++ /dev/null @@ -1,6 +0,0 @@ -Current v3.0.12 of Psychtoolbox does not contain -any mex files to support ARM based systems, e.g., -tablets. We may or may not add such support back. - -Psychtoolbox-3.0.11 does support at least the -Google Nexus-7 2012 edition with Ubuntu 13.04. diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychHID.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychHID.mex index 5f00b4c116..c3311c5305 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychHID.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychHID.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychKinectCore.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychKinectCore.mex index 2f80055817..4a5c77f6de 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychKinectCore.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychKinectCore.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychOpenHMDVRCore.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychOpenHMDVRCore.mex index 7ee0b5a5e1..c36894131e 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychOpenHMDVRCore.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychOpenHMDVRCore.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychPortAudio.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychPortAudio.mex index 43d1eddabe..d70638dea1 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychPortAudio.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychPortAudio.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychVulkanCore.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychVulkanCore.mex index 0cd3a9e19a..327024b396 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychVulkanCore.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/PsychVulkanCore.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/Screen.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/Screen.mex index 99b442868a..a8a0d6eb68 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/Screen.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/Screen.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/WaitSecs.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/WaitSecs.mex index cdfed5c885..83282ebd06 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/WaitSecs.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/WaitSecs.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/moglcore.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/moglcore.mex index 3b554c6a26..79a924d34d 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/moglcore.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/moglcore.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/pnet.mex b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/pnet.mex index d997530fa4..e6eba32ef2 100644 Binary files a/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/pnet.mex and b/Psychtoolbox/PsychBasic/Octave3LinuxFilesARM/pnet.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/PsychOpenXRCore.mex b/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/PsychOpenXRCore.mex index e5221f857b..88ec5c4e33 100644 Binary files a/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/PsychOpenXRCore.mex and b/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/PsychOpenXRCore.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/Screen.mex b/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/Screen.mex index d507913e84..bb10f86ecb 100644 Binary files a/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/Screen.mex and b/Psychtoolbox/PsychBasic/Octave5LinuxFiles64/Screen.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave8OSXFiles64/Screen.mex b/Psychtoolbox/PsychBasic/Octave8OSXFiles64/Screen.mex index 5f7b7d79a6..c1ee4fc688 100755 Binary files a/Psychtoolbox/PsychBasic/Octave8OSXFiles64/Screen.mex and b/Psychtoolbox/PsychBasic/Octave8OSXFiles64/Screen.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychOpenXRCore.mex b/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychOpenXRCore.mex index 0cff911102..2cd55b43d1 100644 Binary files a/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychOpenXRCore.mex and b/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychOpenXRCore.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychPortAudio.mex b/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychPortAudio.mex index da9744c5de..755513d3fe 100644 Binary files a/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychPortAudio.mex and b/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/PsychPortAudio.mex differ diff --git a/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/Screen.mex b/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/Screen.mex index 80331dbe05..659d2fa84d 100644 Binary files a/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/Screen.mex and b/Psychtoolbox/PsychBasic/Octave8WindowsFiles64/Screen.mex differ diff --git a/Psychtoolbox/PsychBasic/PsychOpenXRCore.mexa64 b/Psychtoolbox/PsychBasic/PsychOpenXRCore.mexa64 index cd0adcb370..bb87501ea7 100644 Binary files a/Psychtoolbox/PsychBasic/PsychOpenXRCore.mexa64 and b/Psychtoolbox/PsychBasic/PsychOpenXRCore.mexa64 differ diff --git a/Psychtoolbox/PsychBasic/Screen.mexa64 b/Psychtoolbox/PsychBasic/Screen.mexa64 index b456dc4c5d..e00fdb2a89 100644 Binary files a/Psychtoolbox/PsychBasic/Screen.mexa64 and b/Psychtoolbox/PsychBasic/Screen.mexa64 differ diff --git a/Psychtoolbox/PsychBasic/Screen.mexmaci64 b/Psychtoolbox/PsychBasic/Screen.mexmaci64 index d07b49f7d5..f48974f9ef 100755 Binary files a/Psychtoolbox/PsychBasic/Screen.mexmaci64 and b/Psychtoolbox/PsychBasic/Screen.mexmaci64 differ diff --git a/Psychtoolbox/PsychHardware/PsychVRToolbox/PsychOpenXR.m b/Psychtoolbox/PsychHardware/PsychVRToolbox/PsychOpenXR.m index ed4e89a9ce..b46c565d03 100644 --- a/Psychtoolbox/PsychHardware/PsychVRToolbox/PsychOpenXR.m +++ b/Psychtoolbox/PsychHardware/PsychVRToolbox/PsychOpenXR.m @@ -1265,10 +1265,10 @@ gaze(3).sensor2D = srLastSample(31:32); % Get predicted tracking state and hand controller poses (if supported) for targetTime: - [state, touch] = PsychOpenXRCore('GetTrackingState', myhmd.handle, targetTime, reqmask - 4); + [state, touch, ~, hands] = PsychOpenXRCore('GetTrackingState', myhmd.handle, targetTime, reqmask - 4); else % Get predicted eye pose, tracking state and hand controller poses (if supported) for targetTime: - [state, touch, gaze] = PsychOpenXRCore('GetTrackingState', myhmd.handle, targetTime, reqmask); + [state, touch, gaze, hands] = PsychOpenXRCore('GetTrackingState', myhmd.handle, targetTime, reqmask); end hmd{myhmd.handle}.state = state; @@ -1515,6 +1515,44 @@ end end + % Articulated hand tracking data requested? + if bitand(reqmask, 8) + if ~hmd{myhmd.handle}.needHandTracking + error('PsychOpenXR:PrepareRender: Articulated hand tracking data requested, but not supported or enabled!'); + end + + global tHandsMsecs + handy = tic; + % Store raw data returned from driver: + result.handTrackingRaw = hands; + + for hand = 1:length(hands) + result.trackedHandStatus(hand) = hands(hand).Tracked; + jointsMatrix = hands(hand).Joints; + result.trackedJoints(hand, :) = jointsMatrix(1, :) == 3; + result.trackedJointsRadius(hand, :) = jointsMatrix(2, :); + result.trackedJointsPosition(hand, 1:3, :) = jointsMatrix(3:5, :); + result.trackedJointsOrientationQuat(hand, 1:4, :) = jointsMatrix(6:9, :); + + % Iterate over all joints: + for j = 1:size(jointsMatrix, 2) + % Joint tracked and valid? + if result.trackedJoints(hand, j) + % Convert j'th joint pose vector to 4x4 OpenGL right handed reference frame matrix: + result.localJointPoseMatrix{hand, j} = eyePoseToCameraMatrix(jointsMatrix(3:9, j)'); + + % Premultiply usercode provided global transformation matrix: + result.globalJointPoseMatrix{hand, j} = userTransformMatrix * result.localJointPoseMatrix{hand, j}; + else + % Nope: Assign identity matrices: + result.localJointPoseMatrix{hand, j} = diag([1,1,1,1]); + result.globalJointPoseMatrix{hand, j} = diag([1,1,1,1]); + end + end + end + % tHandsMsecs(end+1) = 1000 * toc(handy); + end + varargout{1} = result; return; @@ -1871,7 +1909,7 @@ fprintf('Khronos under Apache 2.0 and MIT license: SPDX license identifier “Apache-2.0 OR MIT”\n\n'); end - [handle, modelName, runtimeName, hasEyeTracking] = PsychOpenXRCore('Open', varargin{:}); + [handle, modelName, runtimeName, hasEyeTracking, hasHandTracking] = PsychOpenXRCore('Open', varargin{:}); newhmd.handle = handle; newhmd.driver = @PsychOpenXR; @@ -1888,7 +1926,7 @@ newhmd.controllerTypes = 0; newhmd.eyeTrackingSupported = hasEyeTracking; newhmd.needEyeTracking = 0; - newhmd.articulatedHandTrackingSupported = 0; + newhmd.articulatedHandTrackingSupported = hasHandTracking; newhmd.needHandTracking = 0; % Usually HMD tracking also works for mono display mode: diff --git a/Psychtoolbox/PsychOneliners/GetGitPath.m b/Psychtoolbox/PsychOneliners/GetGitPath.m index 63a938fedd..1072c5b5ac 100644 --- a/Psychtoolbox/PsychOneliners/GetGitPath.m +++ b/Psychtoolbox/PsychOneliners/GetGitPath.m @@ -65,7 +65,7 @@ elseif IsWin [returnCode,gitpath] = system('where git'); if returnCode==0 - gitpath = strtrim(gitpath); + gitpath = [fileparts(strtrim(gitpath)) filesep]; else % failed, clear whatever the command returned gitpath = ''; diff --git a/Psychtoolbox/SetupPsychtoolbox.m b/Psychtoolbox/SetupPsychtoolbox.m index 91d3309cde..cefd3f4379 100644 --- a/Psychtoolbox/SetupPsychtoolbox.m +++ b/Psychtoolbox/SetupPsychtoolbox.m @@ -21,7 +21,7 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) % folder. Obviously you need to somehow get a copy, either via conventional % download from a computer with network connection, visit this URL for that % download: http://psychtoolbox.org/download.html -% Or from a helpful colleague or copied from some other machine. +% Or from a helpful colleague, or copied from some other machine. % % 2. Change your Matlab/Octave working directory to the Psychtoolbox installation % folder, e.g., 'cd /Applications/Psychtoolbox'. @@ -55,6 +55,8 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) % 04/01/16 mk 64-Bit Octave-4 support for MS-Windows established. % 06/01/16 mk 32-Bit Octave-4 support for MS-Windows removed. % 01/25/24 mk Cleanup, dead code removal. +% 06/12/24 mk Fixup for spaces in install path on macOS for use of xattr, +% and skip xattr if installed as .mltbx file via Add-On explorer. % Flush all MEX files: This is needed at least on M$-Windows if Screen et al. are still loaded. clear mex; %#ok @@ -75,7 +77,7 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) if ~IsWin && ~IsOSX && ~IsLinux fprintf('Sorry, this updater doesn''t support your operating system: %s.\n', computer); - fprintf([mfilename ' can only install the Linux, Windows and macOS versions of the Psychtoolbox-3.\n']); + fprintf([mfilename ' can only set up the Linux, Windows and macOS versions of the Psychtoolbox-3.\n']); error(['Your operating system is not supported by ' mfilename '.']); end @@ -106,7 +108,7 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) fprintf(['Once "savepath" works (no error message), run ' mfilename ' again.\n']); fprintf('Alternatively you can choose to continue with installation, but then you will have\n'); - fprintf('to resolve this permission isssue later and add the path to the Psychtoolbox manually.\n\n'); + fprintf('to resolve this permission issue later and add the path to the Psychtoolbox manually.\n\n'); if ~tryNonInteractiveSetup answer=input('Do you want to continue the installation despite the failure of SAVEPATH (yes or no)? ','s'); else @@ -196,7 +198,8 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) fprintf('Success.\n\n'); end -if IsOSX +% macOS and not a Matlab add-on? Add-on toolboxes don't need quarantine removal. +if IsOSX && isempty(strfind(targetdirectory, 'MATLAB Add-Ons')) %#ok % Apples trainwreck needs special treatment. If Psychtoolbox has been % downloaded via a webbrowser as a zip file or tgz file and then % extracted, then all binary executable files like .dylib's and @@ -205,6 +208,10 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) % Thanks Apple! Use the xattr command to remove the quarantine flag. fprintf('Trying to fixup Apple macOS broken security workflow by removing the quarantine flag from our mex files...\n\n'); + % Escape all spaces in the path p with a backslash, so shell utilities + % like xattr can work and don't choke on pathes with blanks: + p = strrep(p, ' ', '\ '); + if IsOctave % Fix the Octave mex files: if IsARM @@ -231,7 +238,7 @@ function SetupPsychtoolbox(tryNonInteractiveSetup) if isempty(strfind(msg, 'xattr: com.apple.quarantine')) %#ok fprintf('FAILED! Psychtoolbox will likely not work correctly!\n'); PsychPaidSupportAndServices(2); - error(['Removing the quarantine flag from our mex files to workaround macOS brokeness failed! Error was: ' msg]); + warning(['Removing the quarantine flag from our mex files to workaround macOS brokeness failed! Error was: ' msg]); end end end diff --git a/pyproject.toml b/pyproject.toml index 2b0e85a044..82ce83dab5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ requires = [ "oldest-supported-numpy; python_version<'3.7'", # we need to build with at least 1.16.5 for a limited API bugfix "numpy==1.16.5; python_version=='3.7'", - "oldest-supported-numpy; python_version>='3.8'" + "oldest-supported-numpy; python_version=='3.8'", + "numpy>=2,<3; python_version>='3.9'", ] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 2e4d978a53..01a2d3c061 100644 --- a/setup.py +++ b/setup.py @@ -305,10 +305,13 @@ def get_basesources(name, osname): py_limited_api = py_limited_api, ) ext_modules.append(IOPort) +description = 'Pieces of Psychtoolbox-3 ported to CPython.' setup (name = 'psychtoolbox', version = version, - description = 'Pieces of Psychtoolbox-3 ported to CPython.', + description = description, + long_description = description, + long_description_content_type = 'text/x-rst', author = 'Mario Kleiner', author_email = 'mario.kleiner.de@gmail.com', url = 'http://psychtoolbox.org',