24 const char *action_name,
25 const char *profile_path,
26 XrPath subaction_path,
27 const char *subaction_path_str,
28 const GHOST_XrPose &pose)
30 XrActionSpaceCreateInfo action_space_info{XR_TYPE_ACTION_SPACE_CREATE_INFO};
31 action_space_info.action = action;
32 action_space_info.subactionPath = subaction_path;
35 CHECK_XR(xrCreateActionSpace(session, &action_space_info, &m_space),
36 (std::string(
"Failed to create space \"") + subaction_path_str +
"\" for action \"" +
37 action_name +
"\" and profile \"" + profile_path +
"\".")
43 if (m_space != XR_NULL_HANDLE) {
63 GHOST_XrActionType
type,
64 const GHOST_XrActionProfileInfo &info)
67 (std::string(
"Failed to get interaction profile path \"") + info.profile_path +
"\".")
70 const bool is_float_action = (
type == GHOST_kXrActionTypeFloatInput ||
71 type == GHOST_kXrActionTypeVector2fInput);
72 const bool is_button_action = (is_float_action ||
type == GHOST_kXrActionTypeBooleanInput);
73 const bool is_pose_action = (
type == GHOST_kXrActionTypePoseInput);
76 XrInteractionProfileSuggestedBinding bindings_info{
77 XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING};
78 bindings_info.interactionProfile = m_profile;
79 bindings_info.countSuggestedBindings = 1;
81 for (
uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) {
82 const char *subaction_path_str = info.subaction_paths[subaction_idx];
83 const GHOST_XrActionBindingInfo &binding_info = info.bindings[subaction_idx];
85 const std::string interaction_path = std::string(subaction_path_str) +
86 binding_info.component_path;
87 if (m_bindings.find(interaction_path) != m_bindings.end()) {
91 XrActionSuggestedBinding sbinding;
92 sbinding.action = action;
93 CHECK_XR(xrStringToPath(
instance, interaction_path.data(), &sbinding.binding),
94 (std::string(
"Failed to get interaction path \"") + interaction_path +
"\".").data());
95 bindings_info.suggestedBindings = &sbinding;
100 (std::string(
"Failed to create binding for action \"") + info.action_name +
101 "\" and profile \"" + info.profile_path +
102 "\". Are the action and profile paths correct?")
105 m_bindings.insert({interaction_path, sbinding.binding});
107 if (m_subaction_data.find(subaction_path_str) == m_subaction_data.end()) {
108 std::map<std::string, GHOST_XrSubactionData>::iterator it =
111 std::piecewise_construct, std::make_tuple(subaction_path_str), std::make_tuple())
116 (std::string(
"Failed to get user path \"") + subaction_path_str +
"\".").data());
118 if (is_float_action || is_button_action) {
119 if (is_float_action) {
122 if (is_button_action) {
123 subaction.
axis_flag = binding_info.axis_flag;
126 else if (is_pose_action) {
128 subaction.
space = std::make_unique<GHOST_XrActionSpace>(session,
147 for (
auto &[subaction_path_str, subaction] : m_subaction_data) {
148 if (subaction.subaction_path == subaction_path) {
156 XrAction action,
std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings)
const
158 std::map<XrPath, std::vector<XrActionSuggestedBinding>>::iterator it = r_bindings.find(
160 if (it == r_bindings.end()) {
162 .emplace(std::piecewise_construct, std::make_tuple(m_profile), std::make_tuple())
166 std::vector<XrActionSuggestedBinding> &sbindings = it->second;
168 for (
auto &[path, binding] : m_bindings) {
169 XrActionSuggestedBinding sbinding;
170 sbinding.action = action;
171 sbinding.binding = binding;
173 sbindings.push_back(std::move(sbinding));
185 XrActionSet action_set,
186 const GHOST_XrActionInfo &info)
188 m_states(info.states),
189 m_float_thresholds(info.float_thresholds),
190 m_axis_flags(info.axis_flags),
194 m_subaction_paths.resize(info.count_subaction_paths);
196 for (
uint32_t i = 0; i < info.count_subaction_paths; ++i) {
197 const char *subaction_path_str = info.subaction_paths[i];
198 CHECK_XR(xrStringToPath(
instance, subaction_path_str, &m_subaction_paths[i]),
199 (std::string(
"Failed to get user path \"") + subaction_path_str +
"\".").
data());
200 m_subaction_indices.insert({subaction_path_str, i});
203 XrActionCreateInfo action_info{XR_TYPE_ACTION_CREATE_INFO};
204 strcpy(action_info.actionName, info.name);
207 strcpy(action_info.localizedActionName, info.name);
210 case GHOST_kXrActionTypeBooleanInput:
211 action_info.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
213 case GHOST_kXrActionTypeFloatInput:
214 action_info.actionType = XR_ACTION_TYPE_FLOAT_INPUT;
216 case GHOST_kXrActionTypeVector2fInput:
217 action_info.actionType = XR_ACTION_TYPE_VECTOR2F_INPUT;
219 case GHOST_kXrActionTypePoseInput:
220 action_info.actionType = XR_ACTION_TYPE_POSE_INPUT;
222 case GHOST_kXrActionTypeVibrationOutput:
223 action_info.actionType = XR_ACTION_TYPE_VIBRATION_OUTPUT;
226 action_info.countSubactionPaths = info.count_subaction_paths;
227 action_info.subactionPaths = m_subaction_paths.data();
229 CHECK_XR(xrCreateAction(action_set, &action_info, &m_action),
230 (std::string(
"Failed to create action \"") + info.name +
231 "\". Action name and/or paths are invalid. Name must not contain upper "
232 "case letters or special characters other than '-', '_', or '.'.")
238 if (m_action != XR_NULL_HANDLE) {
245 const GHOST_XrActionProfileInfo &info)
247 if (m_profiles.find(info.profile_path) != m_profiles.end()) {
251 m_profiles.emplace(std::piecewise_construct,
252 std::make_tuple(info.profile_path),
253 std::make_tuple(
instance, session, m_action, m_type, info));
260 if (m_profiles.find(profile_path) != m_profiles.end()) {
261 m_profiles.erase(profile_path);
266 const char *action_name,
267 XrSpace reference_space,
268 const XrTime &predicted_display_time)
270 const bool is_float_action = (m_type == GHOST_kXrActionTypeFloatInput ||
271 m_type == GHOST_kXrActionTypeVector2fInput);
272 const bool is_button_action = (is_float_action || m_type == GHOST_kXrActionTypeBooleanInput);
274 XrActionStateGetInfo state_info{XR_TYPE_ACTION_STATE_GET_INFO};
275 state_info.action = m_action;
277 const size_t count_subaction_paths = m_subaction_paths.size();
278 for (
size_t subaction_idx = 0; subaction_idx < count_subaction_paths; ++subaction_idx) {
279 state_info.subactionPath = m_subaction_paths[subaction_idx];
282 XrInteractionProfileState profile_state{XR_TYPE_INTERACTION_PROFILE_STATE};
283 CHECK_XR(xrGetCurrentInteractionProfile(session, state_info.subactionPath, &profile_state),
284 "Failed to get current interaction profile.");
287 for (
auto &[profile_path, profile] : m_profiles) {
288 if (profile.getProfile() == profile_state.interactionProfile) {
289 subaction = profile.getSubaction(state_info.subactionPath);
294 if (subaction !=
nullptr) {
295 if (is_float_action) {
298 if (is_button_action) {
299 m_axis_flags[subaction_idx] = subaction->
axis_flag;
304 case GHOST_kXrActionTypeBooleanInput: {
305 XrActionStateBoolean
state{XR_TYPE_ACTION_STATE_BOOLEAN};
306 CHECK_XR(xrGetActionStateBoolean(session, &state_info, &
state),
307 (std::string(
"Failed to get state for boolean action \"") + action_name +
"\".")
309 if (
state.isActive) {
310 ((
bool *)m_states)[subaction_idx] =
state.currentState;
314 case GHOST_kXrActionTypeFloatInput: {
315 XrActionStateFloat
state{XR_TYPE_ACTION_STATE_FLOAT};
317 xrGetActionStateFloat(session, &state_info, &
state),
318 (std::string(
"Failed to get state for float action \"") + action_name +
"\".").
data());
319 if (
state.isActive) {
320 ((
float *)m_states)[subaction_idx] =
state.currentState;
324 case GHOST_kXrActionTypeVector2fInput: {
325 XrActionStateVector2f
state{XR_TYPE_ACTION_STATE_VECTOR2F};
326 CHECK_XR(xrGetActionStateVector2f(session, &state_info, &
state),
327 (std::string(
"Failed to get state for vector2f action \"") + action_name +
"\".")
329 if (
state.isActive) {
330 memcpy(((
float(*)[2])m_states)[subaction_idx], &
state.currentState,
sizeof(
float[2]));
334 case GHOST_kXrActionTypePoseInput: {
336 if (predicted_display_time > 0) {
337 XrActionStatePose
state{XR_TYPE_ACTION_STATE_POSE};
339 (std::string(
"Failed to get state for pose action \"") + action_name +
"\".")
341 if (
state.isActive) {
342 XrSpace pose_space = ((subaction !=
nullptr) && (subaction->
space !=
nullptr)) ?
343 subaction->
space->getSpace() :
345 if (pose_space != XR_NULL_HANDLE) {
346 XrSpaceLocation space_location{XR_TYPE_SPACE_LOCATION};
349 pose_space, reference_space, predicted_display_time, &space_location),
350 (std::string(
"Failed to query pose space for action \"") + action_name +
"\".")
353 ((GHOST_XrPose *)m_states)[subaction_idx]);
359 case GHOST_kXrActionTypeVibrationOutput: {
367 const char *action_name,
368 const char *subaction_path_str,
370 const float &frequency,
371 const float &litude)
373 XrHapticVibration vibration{XR_TYPE_HAPTIC_VIBRATION};
374 vibration.duration = (duration == 0) ? XR_MIN_HAPTIC_DURATION :
375 static_cast<XrDuration
>(duration);
376 vibration.frequency = frequency;
377 vibration.amplitude = amplitude;
379 XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO};
380 haptic_info.action = m_action;
382 if (subaction_path_str !=
nullptr) {
383 SubactionIndexMap::iterator it = m_subaction_indices.find(subaction_path_str);
384 if (it != m_subaction_indices.end()) {
385 haptic_info.subactionPath = m_subaction_paths[it->second];
387 xrApplyHapticFeedback(session, &haptic_info, (
const XrHapticBaseHeader *)&vibration),
388 (std::string(
"Failed to apply haptic action \"") + action_name +
"\".").
data());
392 for (
const XrPath &subaction_path : m_subaction_paths) {
393 haptic_info.subactionPath = subaction_path;
395 xrApplyHapticFeedback(session, &haptic_info, (
const XrHapticBaseHeader *)&vibration),
396 (std::string(
"Failed to apply haptic action \"") + action_name +
"\".").
data());
402 const char *action_name,
403 const char *subaction_path_str)
405 XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO};
406 haptic_info.action = m_action;
408 if (subaction_path_str !=
nullptr) {
409 SubactionIndexMap::iterator it = m_subaction_indices.find(subaction_path_str);
410 if (it != m_subaction_indices.end()) {
411 haptic_info.subactionPath = m_subaction_paths[it->second];
412 CHECK_XR(xrStopHapticFeedback(session, &haptic_info),
413 (std::string(
"Failed to stop haptic action \"") + action_name +
"\".").
data());
417 for (
const XrPath &subaction_path : m_subaction_paths) {
418 haptic_info.subactionPath = subaction_path;
419 CHECK_XR(xrStopHapticFeedback(session, &haptic_info),
420 (std::string(
"Failed to stop haptic action \"") + action_name +
"\".").
data());
427 if (m_custom_data_ ==
nullptr) {
430 return m_custom_data_->custom_data_;
434 std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings)
const
436 for (
auto &[path, profile] : m_profiles) {
437 profile.getBindings(m_action, r_bindings);
452 XrActionSetCreateInfo action_set_info{XR_TYPE_ACTION_SET_CREATE_INFO};
453 strcpy(action_set_info.actionSetName, info.name);
456 strcpy(action_set_info.localizedActionSetName, info.name);
458 action_set_info.priority = 0;
461 (std::string(
"Failed to create action set \"") + info.name +
462 "\". Name must not contain upper case letters or special characters "
463 "other than '-', '_', or '.'.")
473 if (m_action_set != XR_NULL_HANDLE) {
480 if (m_actions.find(info.name) != m_actions.end()) {
484 m_actions.emplace(std::piecewise_construct,
485 std::make_tuple(info.name),
486 std::make_tuple(
instance, m_action_set, info));
493 if (m_actions.find(action_name) != m_actions.end()) {
494 m_actions.erase(action_name);
500 std::map<std::string, GHOST_XrAction>::iterator it = m_actions.find(action_name);
501 if (it == m_actions.end()) {
508 XrSpace reference_space,
509 const XrTime &predicted_display_time)
511 for (
auto &[name, action] : m_actions) {
512 action.updateState(session, name.data(), reference_space, predicted_display_time);
523 if (m_custom_data_ ==
nullptr) {
526 return m_custom_data_->custom_data_;
537 for (
auto &[name, action] : m_actions) {
538 r_customdata_array[i++] = action.getCustomdata();
543 std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings)
const
545 for (
auto &[name, action] : m_actions) {
546 action.getBindings(r_bindings);
void copy_openxr_pose_to_ghost_pose(const XrPosef &oxr_pose, GHOST_XrPose &r_ghost_pose)
void copy_ghost_pose_to_openxr_pose(const GHOST_XrPose &ghost_pose, XrPosef &r_oxr_pose)
#define CHECK_XR_ASSERT(call)
#define CHECK_XR(call, error_msg)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object instance
void getBindings(XrAction action, std::map< XrPath, std::vector< XrActionSuggestedBinding >> &r_bindings) const
const GHOST_XrSubactionData * getSubaction(XrPath subaction_path) const
XrPath getProfile() const
GHOST_XrActionProfile()=delete
GHOST_XrActionSet()=delete
void updateStates(XrSession session, XrSpace reference_space, const XrTime &predicted_display_time)
GHOST_XrAction * findAction(const char *action_name)
void getBindings(std::map< XrPath, std::vector< XrActionSuggestedBinding >> &r_bindings) const
bool createAction(XrInstance instance, const GHOST_XrActionInfo &info)
XrActionSet getActionSet() const
void getActionCustomdataArray(void **r_customdata_array)
uint32_t getActionCount() const
void destroyAction(const char *action_name)
GHOST_XrActionSpace()=delete
bool createBinding(XrInstance instance, XrSession session, const GHOST_XrActionProfileInfo &info)
void updateState(XrSession session, const char *action_name, XrSpace reference_space, const XrTime &predicted_display_time)
void getBindings(std::map< XrPath, std::vector< XrActionSuggestedBinding >> &r_bindings) const
void stopHapticFeedback(XrSession session, const char *action_name, const char *subaction_path)
void applyHapticFeedback(XrSession session, const char *action_name, const char *subaction_path, const int64_t &duration, const float &frequency, const float &litude)
void destroyBinding(const char *profile_path)
SocketIndexByIdentifierMap * map
std::unique_ptr< GHOST_XrActionSpace > space