// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/vr/openxr/openxr_path_helper.h"
#include "base/check.h"
#include "base/containers/contains.h"
#include "device/vr/openxr/openxr_interaction_profiles.h"
#include "device/vr/openxr/openxr_util.h"
#include "device/vr/public/mojom/openxr_interaction_profile_type.mojom.h"
namespace device {
using device::mojom::OpenXrInteractionProfileType;
namespace {
constexpr std::array<OpenXrInteractionProfileType, 3> kHandProfiles{
OpenXrInteractionProfileType::kHandSelectGrasp,
OpenXrInteractionProfileType::kExtHand,
OpenXrInteractionProfileType::kMetaHandAim,
};
} // namespace
OpenXRPathHelper::OpenXRPathHelper() = default;
OpenXRPathHelper::~OpenXRPathHelper() = default;
XrResult OpenXRPathHelper::Initialize(XrInstance instance, XrSystemId system) {
DCHECK(!initialized_);
// Get the system properties, which is needed to determine the name of the
// hardware being used. This helps disambiguate certain sets of controllers.
XrSystemProperties system_properties = {XR_TYPE_SYSTEM_PROPERTIES};
RETURN_IF_XR_FAILED(
xrGetSystemProperties(instance, system, &system_properties));
system_name_ = std::string(system_properties.systemName);
// Create path declarations
for (const auto& profile : GetOpenXrControllerInteractionProfiles()) {
RETURN_IF_XR_FAILED(
xrStringToPath(instance, profile.path.c_str(),
&(declared_interaction_profile_paths_[profile.type])));
}
initialized_ = true;
return XR_SUCCESS;
}
OpenXrInteractionProfileType OpenXRPathHelper::GetInputProfileType(
XrPath interaction_profile) const {
DCHECK(initialized_);
for (auto it : declared_interaction_profile_paths_) {
if (it.second == interaction_profile) {
return it.first;
}
}
return OpenXrInteractionProfileType::kInvalid;
}
std::vector<std::string> OpenXRPathHelper::GetInputProfiles(
OpenXrInteractionProfileType interaction_profile,
bool hand_joints_enabled) const {
DCHECK(initialized_);
bool can_use_hand_joint_profile =
hand_joints_enabled && base::Contains(kHandProfiles, interaction_profile);
const auto& input_profiles_map = GetOpenXrInputProfilesMap();
if (input_profiles_map.contains(interaction_profile)) {
const OpenXrSystemInputProfiles* active_system = nullptr;
for (const auto& system : input_profiles_map.at(interaction_profile)) {
if ((!can_use_hand_joint_profile && system.system_name.empty()) ||
(can_use_hand_joint_profile &&
system.system_name.compare(kOpenXrHandJointSystem) == 0)) {
active_system = &system;
} else if (system_name_.compare(system.system_name) == 0) {
active_system = &system;
break;
}
}
// Each interaction profile should always at least have a null system_name
// entry. Profiles that support hand joints should have both a null
// system_name and a `kOpenXrHandJointSystem` system_name.
DCHECK(active_system);
return active_system->input_profiles;
}
return {};
}
XrPath OpenXRPathHelper::GetInteractionProfileXrPath(
OpenXrInteractionProfileType type) const {
if (type == OpenXrInteractionProfileType::kInvalid) {
return XR_NULL_PATH;
}
return declared_interaction_profile_paths_.at(type);
}
} // namespace device