mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-29 18:08:29 +00:00
st/oxr: Improve xrSuggestInteractionProfileBindings validation of input
This commit is contained in:
parent
cdde7cd2c2
commit
2dcf4a819b
2
doc/changes/state_trackers/mr.377.md
Normal file
2
doc/changes/state_trackers/mr.377.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
OpenXR: More correctly verify the interactive profile binding data, including
|
||||
the given interactive profile is correct and the binding point is valid.
|
|
@ -1,7 +1,32 @@
|
|||
# Copyright 2019-2020, Collabora, Ltd.
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
|
||||
###
|
||||
# Binding generation
|
||||
#
|
||||
|
||||
function(bindings_gen output)
|
||||
add_custom_command(OUTPUT ${output}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/bindings.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bindings.json
|
||||
${output}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bindings.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bindings.json
|
||||
)
|
||||
endfunction(bindings_gen)
|
||||
|
||||
bindings_gen(${CMAKE_CURRENT_BINARY_DIR}/oxr_generated_bindings.h)
|
||||
bindings_gen(${CMAKE_CURRENT_BINARY_DIR}/oxr_generated_bindings.c)
|
||||
|
||||
|
||||
###
|
||||
# Main code
|
||||
#
|
||||
|
||||
set(OXR_SOURCE_FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/oxr_generated_bindings.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/oxr_generated_bindings.c
|
||||
oxr_api_action.c
|
||||
oxr_api_funcs.h
|
||||
oxr_api_instance.c
|
||||
|
@ -52,4 +77,14 @@ if(XRT_HAVE_EGL)
|
|||
endif()
|
||||
|
||||
add_library(st_oxr STATIC ${OXR_SOURCE_FILES})
|
||||
target_link_libraries(st_oxr PRIVATE xrt-interfaces xrt-external-openxr aux_util aux_math Vulkan::Vulkan comp_client)
|
||||
target_link_libraries(st_oxr PRIVATE
|
||||
xrt-interfaces
|
||||
xrt-external-openxr
|
||||
aux_util
|
||||
aux_math
|
||||
Vulkan::Vulkan
|
||||
comp_client
|
||||
)
|
||||
target_include_directories(st_oxr PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
|
245
src/xrt/state_trackers/oxr/bindings.json
Normal file
245
src/xrt/state_trackers/oxr/bindings.json
Normal file
|
@ -0,0 +1,245 @@
|
|||
{
|
||||
"/interaction_profiles/khr/simple_controller": {
|
||||
"title": "Khronos Simple Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/select/click"},
|
||||
{"subpath": "/input/menu/click"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"},
|
||||
{"subpath": "/output/haptic"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/google/daydream_controller": {
|
||||
"title": "Google Daydream Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/select/click"},
|
||||
{"subpath": "/input/trackpad/x"},
|
||||
{"subpath": "/input/trackpad/y"},
|
||||
{"subpath": "/input/trackpad/click"},
|
||||
{"subpath": "/input/trackpad/touch"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/htc/vive_controller": {
|
||||
"title": "HTC Vive Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/system/click", "system": "true"},
|
||||
{"subpath": "/input/squeeze/click"},
|
||||
{"subpath": "/input/menu/click"},
|
||||
{"subpath": "/input/trigger/click"},
|
||||
{"subpath": "/input/trigger/value"},
|
||||
{"subpath": "/input/trackpad/x"},
|
||||
{"subpath": "/input/trackpad/y"},
|
||||
{"subpath": "/input/trackpad/click"},
|
||||
{"subpath": "/input/trackpad/touch"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"},
|
||||
{"subpath": "/output/haptic"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/htc/vive_pro": {
|
||||
"title": "HTC Vive Pro",
|
||||
"user_paths": [
|
||||
"/user/head"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/system/click", "system": "true"},
|
||||
{"subpath": "/input/volume_up/click"},
|
||||
{"subpath": "/input/volume_down/click"},
|
||||
{"subpath": "/input/mute_mic/click"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/microsoft/motion_controller": {
|
||||
"title": "Microsoft Mixed Reality Motion Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/menu/click"},
|
||||
{"subpath": "/input/squeeze/click"},
|
||||
{"subpath": "/input/trigger/value"},
|
||||
{"subpath": "/input/thumbstick/x"},
|
||||
{"subpath": "/input/thumbstick/y"},
|
||||
{"subpath": "/input/thumbstick/click"},
|
||||
{"subpath": "/input/trackpad/x"},
|
||||
{"subpath": "/input/trackpad/y"},
|
||||
{"subpath": "/input/trackpad/click"},
|
||||
{"subpath": "/input/trackpad/touch"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"},
|
||||
{"subpath": "/output/haptic"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/microsoft/xbox_controller": {
|
||||
"title": "Microsoft Xbox Controller",
|
||||
"user_paths": [
|
||||
"/user/gamepad"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/menu/click"},
|
||||
{"subpath": "/input/view/click"},
|
||||
{"subpath": "/input/a/click"},
|
||||
{"subpath": "/input/b/click"},
|
||||
{"subpath": "/input/x/click"},
|
||||
{"subpath": "/input/y/click"},
|
||||
{"subpath": "/input/dpad_down/click"},
|
||||
{"subpath": "/input/dpad_right/click"},
|
||||
{"subpath": "/input/dpad_up/click"},
|
||||
{"subpath": "/input/dpad_left/click"},
|
||||
{"subpath": "/input/shoulder_left/click"},
|
||||
{"subpath": "/input/shoulder_right/click"},
|
||||
{"subpath": "/input/thumbstick_left/click"},
|
||||
{"subpath": "/input/thumbstick_right/click"},
|
||||
{"subpath": "/input/trigger_left/value"},
|
||||
{"subpath": "/input/trigger_right/value"},
|
||||
{"subpath": "/input/thumbstick_left/x"},
|
||||
{"subpath": "/input/thumbstick_left/y"},
|
||||
{"subpath": "/input/thumbstick_right/x"},
|
||||
{"subpath": "/input/thumbstick_right/y"},
|
||||
{"subpath": "/output/haptic_left"},
|
||||
{"subpath": "/output/haptic_right"},
|
||||
{"subpath": "/output/haptic_left_trigger"},
|
||||
{"subpath": "/output/haptic_right_trigger"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/oculus/go_controller": {
|
||||
"title": "Oculus Go Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/system/click", "system": "true"},
|
||||
{"subpath": "/input/trigger/click"},
|
||||
{"subpath": "/input/back/click"},
|
||||
{"subpath": "/input/trackpad/x"},
|
||||
{"subpath": "/input/trackpad/y"},
|
||||
{"subpath": "/input/trackpad/click"},
|
||||
{"subpath": "/input/trackpad/touch"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/oculus/touch_controller": {
|
||||
"title": "Oculus Touch Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"user_paths": "/user/hand/left", "subpath": "/input/x/click"},
|
||||
{"user_paths": "/user/hand/left", "subpath": "/input/x/touch"},
|
||||
{"user_paths": "/user/hand/left", "subpath": "/input/y/click"},
|
||||
{"user_paths": "/user/hand/left", "subpath": "/input/y/touch"},
|
||||
{"user_paths": "/user/hand/left", "subpath": "/input/menu/click"},
|
||||
{"user_paths": "/user/hand/right", "subpath": "/input/a/click"},
|
||||
{"user_paths": "/user/hand/right", "subpath": "/input/a/touch"},
|
||||
{"user_paths": "/user/hand/right", "subpath": "/input/b/click"},
|
||||
{"user_paths": "/user/hand/right", "subpath": "/input/b/touch"},
|
||||
{"user_paths": "/user/hand/right", "subpath": "/input/system/click", "system": "true"},
|
||||
{"subpath": "/input/squeeze/value"},
|
||||
{"subpath": "/input/trigger/value"},
|
||||
{"subpath": "/input/trigger/touch"},
|
||||
{"subpath": "/input/thumbstick/x"},
|
||||
{"subpath": "/input/thumbstick/y"},
|
||||
{"subpath": "/input/thumbstick/click"},
|
||||
{"subpath": "/input/thumbstick/touch"},
|
||||
{"subpath": "/input/thumbrest/touch"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"},
|
||||
{"subpath": "/output/haptic"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/valve/index_controller": {
|
||||
"title": "Valve Index Controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/system/click", "system": "true"},
|
||||
{"subpath": "/input/system/touch", "system": "true"},
|
||||
{"subpath": "/input/a/click"},
|
||||
{"subpath": "/input/a/touch"},
|
||||
{"subpath": "/input/b/click"},
|
||||
{"subpath": "/input/b/touch"},
|
||||
{"subpath": "/input/squeeze/value"},
|
||||
{"subpath": "/input/squeeze/force"},
|
||||
{"subpath": "/input/trigger/click"},
|
||||
{"subpath": "/input/trigger/value"},
|
||||
{"subpath": "/input/trigger/touch"},
|
||||
{"subpath": "/input/thumbstick/x"},
|
||||
{"subpath": "/input/thumbstick/y"},
|
||||
{"subpath": "/input/thumbstick/click"},
|
||||
{"subpath": "/input/thumbstick/touch"},
|
||||
{"subpath": "/input/trackpad/x"},
|
||||
{"subpath": "/input/trackpad/y"},
|
||||
{"subpath": "/input/trackpad/force"},
|
||||
{"subpath": "/input/trackpad/touch"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"},
|
||||
{"subpath": "/output/haptic"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/microsoft/hand_interaction": {
|
||||
"title": "Microsoft hand interaction",
|
||||
"extension": "XR_MSFT_hand_interaction",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/select/value"},
|
||||
{"subpath": "/input/squeeze/value"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/aim/pose"}
|
||||
]
|
||||
},
|
||||
|
||||
"/interaction_profiles/mnd/ball_on_a_stick_controller": {
|
||||
"title": "Monado ball on a stick controller",
|
||||
"extension": "XR_MND_ball_on_a_stick_controller",
|
||||
"user_paths": [
|
||||
"/user/hand/left",
|
||||
"/user/hand/right"
|
||||
],
|
||||
"components": [
|
||||
{"subpath": "/input/system/click", "system": "true"},
|
||||
{"subpath": "/input/menu/click"},
|
||||
{"subpath": "/input/start/click"},
|
||||
{"subpath": "/input/select/click"},
|
||||
{"subpath": "/input/square_mnd/click"},
|
||||
{"subpath": "/input/cross_mnd/click"},
|
||||
{"subpath": "/input/circle_mnd/click"},
|
||||
{"subpath": "/input/triangle_mnd/click"},
|
||||
{"subpath": "/input/trigger/value"},
|
||||
{"subpath": "/input/grip/pose"},
|
||||
{"subpath": "/input/ball_mnd/pose"},
|
||||
{"subpath": "/input/aim/pose"},
|
||||
{"subpath": "/output/haptic"}
|
||||
]
|
||||
}
|
||||
}
|
175
src/xrt/state_trackers/oxr/bindings.py
Executable file
175
src/xrt/state_trackers/oxr/bindings.py
Executable file
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright 2020, Collabora, Ltd.
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
"""Generate code from a JSON file describing interaction profiles and bindings."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
|
||||
|
||||
def strip_subpath_end(path):
|
||||
if (path.endswith("/value")):
|
||||
return True, path[:-6]
|
||||
if (path.endswith("/click")):
|
||||
return True, path[:-6]
|
||||
if (path.endswith("/touch")):
|
||||
return True, path[:-6]
|
||||
if (path.endswith("/pose")):
|
||||
return True, path[:-5]
|
||||
if (path.endswith("/x")):
|
||||
return True, path[:-2]
|
||||
if (path.endswith("/y")):
|
||||
return True, path[:-2]
|
||||
if (path.endswith("/output/haptic")):
|
||||
return False, path
|
||||
return False, path
|
||||
|
||||
|
||||
class Component:
|
||||
|
||||
@classmethod
|
||||
def parse_array(cls, user_paths, arr):
|
||||
"""Turn an array of data into an array of Component objects.
|
||||
Creates a Component for each user_path and stripped subpaths.
|
||||
"""
|
||||
check = {}
|
||||
ret = []
|
||||
for elm in arr:
|
||||
ups = user_paths
|
||||
if ("user_paths" in elm):
|
||||
ups = [elm["user_paths"]]
|
||||
for up in ups:
|
||||
subpath = elm["subpath"]
|
||||
did_strip, stripped_path = strip_subpath_end(subpath)
|
||||
fullpath = up + stripped_path
|
||||
if (did_strip and not fullpath in check):
|
||||
check[fullpath] = True
|
||||
ret.append(cls(fullpath, elm))
|
||||
fullpath = up + subpath
|
||||
ret.append(cls(fullpath, elm))
|
||||
return ret
|
||||
|
||||
def __init__(self, path, elm):
|
||||
"""Construct an component."""
|
||||
self.path = path
|
||||
|
||||
|
||||
class Profile:
|
||||
"""An interctive bindings profile."""
|
||||
def __init__(self, name, data):
|
||||
"""Construct an profile."""
|
||||
self.name = name
|
||||
self.func = name[22:].replace("/", "_")
|
||||
self.components = Component.parse_array(data["user_paths"], data["components"])
|
||||
self.by_length = {}
|
||||
for component in self.components:
|
||||
l = len(component.path)
|
||||
if (l in self.by_length):
|
||||
self.by_length[l].append(component)
|
||||
else:
|
||||
self.by_length[l] = [component]
|
||||
|
||||
|
||||
class Bindings:
|
||||
"""A group of interactive profiles used in bindings."""
|
||||
|
||||
@classmethod
|
||||
def parse(cls, data):
|
||||
"""Parse a dictionary defining a protocol into Profile objects."""
|
||||
return cls(data)
|
||||
|
||||
@classmethod
|
||||
def load_and_parse(cls, file):
|
||||
"""Load a JSON file and parse it into Profile objects."""
|
||||
with open(file) as infile:
|
||||
return cls.parse(json.loads(infile.read()))
|
||||
|
||||
def __init__(self, data):
|
||||
"""Construct a bindings from a dictionary of profiles."""
|
||||
self.profiles = [Profile(name, call) for name, call in data.items()]
|
||||
|
||||
|
||||
header = '''// Copyright 2020, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief {brief}.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup {group}
|
||||
*/
|
||||
'''
|
||||
|
||||
func_start = '''
|
||||
bool
|
||||
oxr_verify_{func}_subpath(const char *str, size_t length)
|
||||
{{
|
||||
\tswitch (length) {{
|
||||
'''
|
||||
|
||||
if_strcmp = '''if (strcmp(str, "{check}") == 0) {{
|
||||
\t\t\treturn true;
|
||||
\t\t}} else '''
|
||||
|
||||
def generate_bindings_c(file, p):
|
||||
"""Generate the file to verify subpaths on a interaction profile."""
|
||||
f = open(file, "w")
|
||||
f.write(header.format(brief='Generated bindings data', group='oxr_main'))
|
||||
f.write('''
|
||||
#include "xrt/xrt_compiler.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// clang-format off
|
||||
''')
|
||||
|
||||
for profile in p.profiles:
|
||||
f.write(func_start.format(func=profile.func))
|
||||
for length in profile.by_length:
|
||||
f.write("\tcase " + str(length) + ":\n\t\t")
|
||||
for component in profile.by_length[length]:
|
||||
f.write(if_strcmp.format(check=component.path))
|
||||
f.write("{\n\t\t\treturn false;\n\t\t}\n")
|
||||
f.write("\tdefault:\n\t\treturn false;\n\t}\n}\n")
|
||||
f.write("\n// clang-format on\n")
|
||||
f.close()
|
||||
|
||||
|
||||
def generate_bindings_h(file, p):
|
||||
"""Generate header for the verify subpaths functions."""
|
||||
f = open(file, "w")
|
||||
f.write(header.format(brief='Generated bindings data header', group='oxr_api'))
|
||||
f.write('''
|
||||
#include "xrt/xrt_compiler.h"
|
||||
|
||||
|
||||
// clang-format off
|
||||
''')
|
||||
|
||||
for profile in p.profiles:
|
||||
f.write("\nbool\noxr_verify_" + profile.func + "_subpath(const char *str, size_t length);\n")
|
||||
f.write("\n// clang-format on\n")
|
||||
f.close()
|
||||
|
||||
|
||||
def main():
|
||||
"""Handle command line and generate a file."""
|
||||
parser = argparse.ArgumentParser(description='Bindings generator.')
|
||||
parser.add_argument(
|
||||
'bindings', help='Bindings file to use')
|
||||
parser.add_argument(
|
||||
'output', type=str, nargs='+',
|
||||
help='Output file, uses the name to choose output type')
|
||||
args = parser.parse_args()
|
||||
|
||||
p = Bindings.load_and_parse(args.bindings)
|
||||
|
||||
for output in args.output:
|
||||
if output.endswith("oxr_generated_bindings.c"):
|
||||
generate_bindings_c(output, p)
|
||||
if output.endswith("oxr_generated_bindings.h"):
|
||||
generate_bindings_h(output, p)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,6 +1,27 @@
|
|||
# Copyright 2019-2020, Collabora, Ltd.
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
|
||||
###
|
||||
# Binding generation
|
||||
#
|
||||
|
||||
prog_python = import('python').find_installation('python3')
|
||||
|
||||
generated = custom_target('bindings code',
|
||||
command: [prog_python, '@INPUT@', '@OUTPUT@'],
|
||||
input: ['bindings.py', 'bindings.json'],
|
||||
output: [
|
||||
'oxr_generated_bindings.h',
|
||||
'oxr_generated_bindings.c',
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
###
|
||||
# Main code
|
||||
#
|
||||
|
||||
compile_args = []
|
||||
if build_opengl
|
||||
compile_args += ['-DXR_USE_GRAPHICS_API_OPENGL', '-DXR_USE_GRAPHICS_API_OPENGL_ES']
|
||||
|
@ -16,7 +37,9 @@ endif
|
|||
|
||||
lib_st_oxr = static_library(
|
||||
'st_oxr',
|
||||
files(
|
||||
[
|
||||
generated[0],
|
||||
generated[1],
|
||||
'oxr_api_action.c',
|
||||
'oxr_api_funcs.h',
|
||||
'oxr_api_instance.c',
|
||||
|
@ -50,7 +73,7 @@ lib_st_oxr = static_library(
|
|||
'oxr_verify.c',
|
||||
'oxr_vulkan.c',
|
||||
'oxr_xdev.c',
|
||||
),
|
||||
],
|
||||
include_directories: [
|
||||
xrt_include,
|
||||
openxr_include,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "oxr_api_funcs.h"
|
||||
#include "oxr_api_verify.h"
|
||||
#include "oxr_generated_bindings.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
@ -105,6 +106,51 @@ oxr_xrSuggestInteractionProfileBindings(
|
|||
"== 0) can not suggest 0 bindings");
|
||||
}
|
||||
|
||||
XrPath ip = suggestedBindings->interactionProfile;
|
||||
const char *str = NULL;
|
||||
size_t length;
|
||||
|
||||
XrResult ret = oxr_path_get_string(&log, inst, ip, &str, &length);
|
||||
if (ret != XR_SUCCESS) {
|
||||
oxr_error(
|
||||
&log, ret,
|
||||
"(suggestedBindings->countSuggestedBindings == 0x%08" PRIx64
|
||||
") invalid path",
|
||||
ip);
|
||||
}
|
||||
|
||||
// Used in the loop that verifies the suggested bindings paths.
|
||||
bool (*func)(const char *, size_t) = NULL;
|
||||
|
||||
if (ip == inst->path_cache.khr_simple_controller) {
|
||||
func = oxr_verify_khr_simple_controller_subpath;
|
||||
} else if (ip == inst->path_cache.google_daydream_controller) {
|
||||
func = oxr_verify_google_daydream_controller_subpath;
|
||||
} else if (ip == inst->path_cache.htc_vive_controller) {
|
||||
func = oxr_verify_htc_vive_controller_subpath;
|
||||
} else if (ip == inst->path_cache.htc_vive_pro) {
|
||||
func = oxr_verify_htc_vive_pro_subpath;
|
||||
} else if (ip == inst->path_cache.microsoft_motion_controller) {
|
||||
func = oxr_verify_microsoft_motion_controller_subpath;
|
||||
} else if (ip == inst->path_cache.microsoft_xbox_controller) {
|
||||
func = oxr_verify_microsoft_xbox_controller_subpath;
|
||||
} else if (ip == inst->path_cache.oculus_go_controller) {
|
||||
func = oxr_verify_oculus_go_controller_subpath;
|
||||
} else if (ip == inst->path_cache.oculus_touch_controller) {
|
||||
func = oxr_verify_oculus_touch_controller_subpath;
|
||||
} else if (ip == inst->path_cache.valve_index_controller) {
|
||||
func = oxr_verify_valve_index_controller_subpath;
|
||||
} else if (ip == inst->path_cache.mnd_ball_on_stick_controller) {
|
||||
func = oxr_verify_mnd_ball_on_a_stick_controller_subpath;
|
||||
} else {
|
||||
return oxr_error(
|
||||
&log, XR_ERROR_PATH_UNSUPPORTED,
|
||||
"(suggestedBindings->interactionProfile == \"%s\") is not "
|
||||
"a supported interaction profile",
|
||||
str);
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < suggestedBindings->countSuggestedBindings; i++) {
|
||||
const XrActionSuggestedBinding *s =
|
||||
&suggestedBindings->suggestedBindings[i];
|
||||
|
@ -120,7 +166,9 @@ oxr_xrSuggestInteractionProfileBindings(
|
|||
i, act->act_set->name, act->name);
|
||||
}
|
||||
|
||||
if (!oxr_path_is_valid(&log, inst, s->binding)) {
|
||||
ret =
|
||||
oxr_path_get_string(&log, inst, s->binding, &str, &length);
|
||||
if (ret != XR_SUCCESS) {
|
||||
return oxr_error(
|
||||
&log, XR_ERROR_PATH_INVALID,
|
||||
"(suggestedBindings->suggestedBindings[%zu]->"
|
||||
|
@ -128,7 +176,13 @@ oxr_xrSuggestInteractionProfileBindings(
|
|||
i, s->binding);
|
||||
}
|
||||
|
||||
//! @todo verify path (s->binding).
|
||||
if (!func(str, length)) {
|
||||
return oxr_error(
|
||||
&log, XR_ERROR_PATH_UNSUPPORTED,
|
||||
"(suggestedBindings->suggestedBindings[%zu]->"
|
||||
"binding == \"%s\") is not a valid path",
|
||||
i, str);
|
||||
}
|
||||
}
|
||||
|
||||
return oxr_action_suggest_interaction_profile_bindings(
|
||||
|
|
Loading…
Reference in a new issue