mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-14 01:21:42 +00:00
Load interaction profile suggestions from xml instead of hardcoding them.
This commit is contained in:
parent
c3418a45ae
commit
e42dada208
11 changed files with 470 additions and 313 deletions
|
@ -258,6 +258,9 @@ if(BUILD_OPENMW_VR)
|
|||
${GAME} ${GAME_HEADER}
|
||||
${APPLE_BUNDLE_RESOURCES}
|
||||
)
|
||||
|
||||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/xrcontrollersuggestions.xml
|
||||
"${OpenMW_BINARY_DIR}" "xrcontrollersuggestions.xml")
|
||||
|
||||
########### Import the OpenXR SDK
|
||||
# Force the openxr-sdk to use its bundled jsoncpp to avoid problems from system jsoncpp if present
|
||||
|
|
|
@ -718,10 +718,29 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
|
||||
mEnvironment.setWindowManager (window);
|
||||
|
||||
MWInput::InputManager* input =
|
||||
#ifdef USE_OPENXR
|
||||
new MWVR::VRInputManager(mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||
const std::string xrinputuserdefault = mCfgMgr.getUserConfigPath().string() + "/xrcontrollersuggestions.xml";
|
||||
const std::string xrinputlocaldefault = mCfgMgr.getLocalPath().string() + "/xrcontrollersuggestions.xml";
|
||||
const std::string xrinputglobaldefault = mCfgMgr.getGlobalPath().string() + "/xrcontrollersuggestions.xml";
|
||||
|
||||
std::string xrControllerSuggestions;
|
||||
if (boost::filesystem::exists(xrinputuserdefault))
|
||||
xrControllerSuggestions = xrinputuserdefault;
|
||||
else if (boost::filesystem::exists(xrinputlocaldefault))
|
||||
xrControllerSuggestions = xrinputlocaldefault;
|
||||
else if (boost::filesystem::exists(xrinputglobaldefault))
|
||||
xrControllerSuggestions = xrinputglobaldefault;
|
||||
else
|
||||
xrControllerSuggestions = ""; //if it doesn't exist, pass in an empty string
|
||||
|
||||
Log(Debug::Verbose) << "xrinputuserdefault: " << xrinputuserdefault;
|
||||
Log(Debug::Verbose) << "xrinputlocaldefault: " << xrinputlocaldefault;
|
||||
Log(Debug::Verbose) << "xrinputglobaldefault: " << xrinputglobaldefault;
|
||||
|
||||
MWInput::InputManager* input =
|
||||
new MWVR::VRInputManager(mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab, xrControllerSuggestions);
|
||||
#else
|
||||
MWInput::InputManager* input =
|
||||
new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||
#endif
|
||||
mEnvironment.setInputManager (input);
|
||||
|
|
|
@ -120,7 +120,8 @@ namespace MWVR
|
|||
const std::string& actionName,
|
||||
const std::string& localName)
|
||||
{
|
||||
mActionMap.emplace(openMWAction, new A(openMWAction, std::move(createXRAction(AT, mInternalName + "_" + actionName, mLocalizedName + " " + localName))));
|
||||
auto xrAction = createXRAction(AT, mInternalName + "_" + actionName, mLocalizedName + " " + localName);
|
||||
mActionMap.emplace(actionName, new A(openMWAction, std::move(xrAction)));
|
||||
}
|
||||
|
||||
XrActionSet
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace MWVR
|
|||
XrActionSet mActionSet{ nullptr };
|
||||
std::string mLocalizedName{};
|
||||
std::string mInternalName{};
|
||||
std::map<int, std::unique_ptr<Action>> mActionMap;
|
||||
std::map<std::string, std::unique_ptr<Action>> mActionMap;
|
||||
std::map<TrackedLimb, std::unique_ptr<PoseAction>> mTrackerMap;
|
||||
std::map<TrackedLimb, std::unique_ptr<HapticsAction>> mHapticsMap;
|
||||
std::deque<const Action*> mActionQueue{};
|
||||
|
|
|
@ -28,9 +28,9 @@ namespace MWVR
|
|||
return it->second;
|
||||
}
|
||||
|
||||
void OpenXRInput::suggestBindings(ActionSet actionSet, std::string profile, const SuggestedBindings& mwSuggestedBindings)
|
||||
void OpenXRInput::suggestBindings(ActionSet actionSet, std::string profilePath, const SuggestedBindings& mwSuggestedBindings)
|
||||
{
|
||||
getActionSet(actionSet).suggestBindings(mSuggestedBindings[profile], mwSuggestedBindings);
|
||||
getActionSet(actionSet).suggestBindings(mSuggestedBindings[profilePath], mwSuggestedBindings);
|
||||
}
|
||||
|
||||
void OpenXRInput::attachActionSets()
|
||||
|
@ -48,6 +48,8 @@ namespace MWVR
|
|||
xrProfileSuggestedBindings.suggestedBindings = profile.second.data();
|
||||
xrProfileSuggestedBindings.countSuggestedBindings = (uint32_t)profile.second.size();
|
||||
CHECK_XRCMD(xrSuggestInteractionProfileBindings(xr->impl().xrInstance(), &xrProfileSuggestedBindings));
|
||||
mInteractionProfileNames[profilePath] = profile.first;
|
||||
mInteractionProfilePaths[profile.first] = profilePath;
|
||||
}
|
||||
|
||||
// OpenXR requires that xrAttachSessionActionSets be called at most once per session.
|
||||
|
@ -62,4 +64,49 @@ namespace MWVR
|
|||
attachInfo.actionSets = actionSets.data();
|
||||
CHECK_XRCMD(xrAttachSessionActionSets(xr->impl().xrSession(), &attachInfo));
|
||||
}
|
||||
|
||||
void OpenXRInput::notifyInteractionProfileChanged()
|
||||
{
|
||||
auto xr = MWVR::Environment::get().getManager();
|
||||
xr->impl().xrSession();
|
||||
|
||||
// Unfortunately, openxr does not tell us WHICH profile has changed.
|
||||
std::array<std::string, 5> topLevelUserPaths =
|
||||
{
|
||||
"/user/hand/left",
|
||||
"/user/hand/right",
|
||||
"/user/head",
|
||||
"/user/gamepad",
|
||||
"/user/treadmill"
|
||||
};
|
||||
|
||||
for (auto& userPath : topLevelUserPaths)
|
||||
{
|
||||
auto pathIt = mInteractionProfilePaths.find(userPath);
|
||||
if (pathIt == mInteractionProfilePaths.end())
|
||||
{
|
||||
XrPath xrUserPath = XR_NULL_PATH;
|
||||
CHECK_XRCMD(
|
||||
xrStringToPath(xr->impl().xrInstance(), userPath.c_str(), &xrUserPath));
|
||||
mInteractionProfilePaths[userPath] = xrUserPath;
|
||||
pathIt = mInteractionProfilePaths.find(userPath);
|
||||
}
|
||||
|
||||
XrInteractionProfileState interactionProfileState{
|
||||
XR_TYPE_INTERACTION_PROFILE_STATE
|
||||
};
|
||||
|
||||
xrGetCurrentInteractionProfile(xr->impl().xrSession(), pathIt->second, &interactionProfileState);
|
||||
if (interactionProfileState.interactionProfile)
|
||||
{
|
||||
auto activeProfileIt = mActiveInteractionProfiles.find(pathIt->second);
|
||||
if (activeProfileIt == mActiveInteractionProfiles.end() || interactionProfileState.interactionProfile != activeProfileIt->second)
|
||||
{
|
||||
auto activeProfileNameIt = mInteractionProfileNames.find(interactionProfileState.interactionProfile);
|
||||
Log(Debug::Verbose) << userPath << ": Interaction profile changed to '" << activeProfileNameIt->second << "'";
|
||||
mActiveInteractionProfiles[pathIt->second] = interactionProfileState.interactionProfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,14 @@ namespace MWVR
|
|||
//! Set bindings and attach actionSets to the session.
|
||||
void attachActionSets();
|
||||
|
||||
//! Notify that active interaction profile has changed
|
||||
void notifyInteractionProfileChanged();
|
||||
|
||||
protected:
|
||||
std::map<ActionSet, OpenXRActionSet> mActionSets{};
|
||||
std::map<XrPath, std::string> mInteractionProfileNames{};
|
||||
std::map<std::string, XrPath> mInteractionProfilePaths{};
|
||||
std::map<XrPath, XrPath> mActiveInteractionProfiles;
|
||||
XrProfileSuggestedBindings mSuggestedBindings{};
|
||||
bool mAttached = false;
|
||||
};
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "openxrdebug.hpp"
|
||||
#include "openxrswapchain.hpp"
|
||||
#include "openxrswapchainimpl.hpp"
|
||||
#include "vrenvironment.hpp"
|
||||
#include "vrinputmanager.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
||||
|
@ -685,8 +687,10 @@ namespace MWVR
|
|||
return handleSessionStateChanged(*stateChangeEvent);
|
||||
break;
|
||||
}
|
||||
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
||||
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
|
||||
MWVR::Environment::get().getInputManager()->notifyInteractionProfileChanged();
|
||||
break;
|
||||
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
||||
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
|
||||
default:
|
||||
{
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace MWVR
|
|||
/// \brief Suggest a binding by binding an action to a path on a given hand (left or right).
|
||||
struct SuggestedBinding
|
||||
{
|
||||
int action;
|
||||
std::string path;
|
||||
std::string action;
|
||||
};
|
||||
|
||||
using SuggestedBindings = std::vector<SuggestedBinding>;
|
||||
|
@ -124,7 +124,6 @@ namespace MWVR
|
|||
void updateAndQueue(std::deque<const Action*>& queue);
|
||||
|
||||
protected:
|
||||
|
||||
std::unique_ptr<OpenXRAction> mXRAction;
|
||||
int mOpenMWAction;
|
||||
float mValue{ 0.f };
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "../mwrender/camera.hpp"
|
||||
|
||||
#include <extern/oics/ICSInputControlSystem.h>
|
||||
#include <extern/oics/tinyxml.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -57,6 +58,11 @@ namespace MWVR
|
|||
return mXRInput->getActionSet(ActionSet::Gameplay);
|
||||
}
|
||||
|
||||
void VRInputManager::notifyInteractionProfileChanged()
|
||||
{
|
||||
mXRInput->notifyInteractionProfileChanged();
|
||||
}
|
||||
|
||||
void VRInputManager::updateActivationIndication(void)
|
||||
{
|
||||
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||
|
@ -68,7 +74,6 @@ namespace MWVR
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes it possible to use ItemModel::moveItem to move an item from an inventory to the world.
|
||||
*/
|
||||
|
@ -184,302 +189,86 @@ namespace MWVR
|
|||
}
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsSimple()
|
||||
void VRInputManager::throwDocumentError(TiXmlElement* element, std::string error)
|
||||
{
|
||||
std::string simpleProfilePath = "/interaction_profiles/khr/simple_controller";
|
||||
// Set up default bindings for the khronos simple controller.
|
||||
// Note: The simple controller is the equivalent to a universal "default".
|
||||
// It has highly reduced functionality. Only poses and two click actions
|
||||
// are available for each hand, reducing the possible functionality of the profile
|
||||
// to that of a wonky preview.
|
||||
// The available click actions are 'select' and 'menu', and i cannot control what
|
||||
// real buttons this is mapped to. On the Oculus Touch they are X, Y, A, and B.
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings simpleGameplayBindings{
|
||||
{MWInput::A_Use, "/user/hand/left/input/select/click"}, // Touch: X
|
||||
{A_VrMetaMenu, "/user/hand/left/input/menu/click"}, // Touch: Y
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"}, // Touch: Y
|
||||
{A_ActivateTouch, "/user/hand/right/input/select/click"}, // Touch: A
|
||||
{MWInput::A_AutoMove, "/user/hand/right/input/menu/click"}, // Touch: B
|
||||
};
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings simpleGUIBindings{
|
||||
{MWInput::A_Use, "/user/hand/left/input/select/click"}, // Touch: X
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"}, // Touch: Y
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"}, // Touch: Y
|
||||
{A_MenuSelect, "/user/hand/right/input/select/click"}, // Touch: A
|
||||
{A_MenuBack, "/user/hand/right/input/menu/click"}, // Touch: B
|
||||
};
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, simpleProfilePath, simpleGameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, simpleProfilePath, simpleGUIBindings);
|
||||
std::stringstream ss;
|
||||
ss << mXrControllerSuggestionsFile << "." << element->Row() << "." << element->Value();
|
||||
ss << ": " << error;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsOculusTouch()
|
||||
std::string VRInputManager::requireAttribute(TiXmlElement* element, std::string attribute)
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/oculus/touch_controller";
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{A_VrMetaMenu, "/user/hand/left/input/menu/click"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/value"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
|
||||
{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/x/click"},
|
||||
{MWInput::A_Rest, "/user/hand/left/input/y/click"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
|
||||
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/value"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/value"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
};
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{A_MenuSelect, "/user/hand/right/input/a/click"},
|
||||
{A_MenuBack, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
};
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
const char* value = element->Attribute(attribute.c_str());
|
||||
if (!value)
|
||||
throwDocumentError(element, std::string() + "Missing attribute '" + attribute + "'");
|
||||
return value;
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsHpMixedReality()
|
||||
void VRInputManager::readInteractionProfile(TiXmlElement* element)
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/hp/mixed_reality_controller";
|
||||
std::string interactionProfilePath = requireAttribute(element, "Path");
|
||||
mInteractionProfileLocalNames[interactionProfilePath] = requireAttribute(element, "LocalName");
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{A_VrMetaMenu, "/user/hand/left/input/menu/click"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/value"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
|
||||
{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/x/click"},
|
||||
{MWInput::A_Rest, "/user/hand/left/input/y/click"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
|
||||
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/value"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/value"},
|
||||
};
|
||||
Log(Debug::Verbose) << "Configuring interaction profile '" << interactionProfilePath << "' (" << mInteractionProfileLocalNames[interactionProfilePath] << ")";
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
|
||||
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{A_MenuSelect, "/user/hand/right/input/a/click"},
|
||||
{A_MenuBack, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
};
|
||||
// Check extension if present
|
||||
TiXmlElement* extensionElement = element->FirstChildElement("Extension");
|
||||
if (extensionElement)
|
||||
{
|
||||
std::string extension = requireAttribute(extensionElement, "Name");
|
||||
auto xr = MWVR::Environment::get().getManager();
|
||||
if (!xr->xrExtensionIsEnabled(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))
|
||||
{
|
||||
Log(Debug::Verbose) << " Required extension '" << extension << "' not supported. Skipping interaction profile.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
TiXmlElement* actionSetGameplay = nullptr;
|
||||
TiXmlElement* actionSetGUI = nullptr;
|
||||
TiXmlElement* child = element->FirstChildElement("ActionSet");
|
||||
while (child)
|
||||
{
|
||||
std::string name = requireAttribute(child, "Name");
|
||||
if (name == "Gameplay")
|
||||
actionSetGameplay = child;
|
||||
else if (name == "GUI")
|
||||
actionSetGUI = child;
|
||||
|
||||
child = child->NextSiblingElement("ActionSet");
|
||||
}
|
||||
|
||||
if (!actionSetGameplay)
|
||||
throwDocumentError(element, "Gameplay action set missing");
|
||||
if (!actionSetGUI)
|
||||
throwDocumentError(element, "GUI action set missing");
|
||||
|
||||
readInteractionProfileActionSet(actionSetGameplay, ActionSet::Gameplay, interactionProfilePath);
|
||||
readInteractionProfileActionSet(actionSetGUI, ActionSet::GUI, interactionProfilePath);
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsHuaweiController()
|
||||
void VRInputManager::readInteractionProfileActionSet(TiXmlElement* element, ActionSet actionSet, std::string interactionProfilePath)
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/huawei/controller";
|
||||
SuggestedBindings suggestedBindings;
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{A_Recenter, "/user/hand/left/input/home/click"},
|
||||
{A_VrMetaMenu, "/user/hand/left/input/home/click"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/click"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/trackpad/y"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/trackpad/x"},
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/trackpad/click"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/back/click"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/trackpad/x"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/trackpad/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/click"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/click"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/click"},
|
||||
};
|
||||
TiXmlElement* child = element->FirstChildElement("Binding");
|
||||
while (child)
|
||||
{
|
||||
std::string action = requireAttribute(child, "ActionName");
|
||||
std::string path = requireAttribute(child, "Path");
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_MenuBack, "/user/hand/left/input/trackpad/click"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/home/click"},
|
||||
{A_Recenter, "/user/hand/left/input/home/click"},
|
||||
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{A_MenuSelect, "/user/hand/right/input/trackpad/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/click"},
|
||||
};
|
||||
suggestedBindings.push_back(
|
||||
SuggestedBinding{
|
||||
path, action
|
||||
});
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
}
|
||||
Log(Debug::Debug) << " " << action << ": " << path;
|
||||
|
||||
void VRInputManager::suggestBindingsMicrosoftMixedReality()
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/microsoft/motion_controller";
|
||||
child = child->NextSiblingElement("Binding");
|
||||
}
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{A_VrMetaMenu, "/user/hand/right/input/squeeze/click"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/trackpad/y"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/trackpad/x"},
|
||||
{MWInput::A_Rest, "/user/hand/left/input/thumbstick/click"},
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/trackpad/click"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/click"},
|
||||
{MWInput::A_Inventory, "/user/hand/right/input/thumbstick/click"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/trackpad/x"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/trackpad/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/click"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/click"},
|
||||
};
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_MenuBack, "/user/hand/left/input/trackpad/click"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{A_MenuUpDown, "/user/hand/right/input/trackpad/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/trackpad/x"},
|
||||
{A_MenuSelect, "/user/hand/right/input/trackpad/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
};
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsIndex()
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/valve/index_controller";
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/a/click"},
|
||||
{MWInput::A_Rest, "/user/hand/left/input/b/click"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
|
||||
{A_Recenter, "/user/hand/left/input/trackpad/force"},
|
||||
{A_VrMetaMenu, "/user/hand/left/input/trackpad/force"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/force"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
|
||||
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/force"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/force"},
|
||||
};
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_Recenter, "/user/hand/left/input/thumbstick/click"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/trackpad/force"},
|
||||
{A_MenuSelect, "/user/hand/right/input/a/click"},
|
||||
{A_MenuBack, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
};
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsVive()
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/htc/vive_controller";
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{A_VrMetaMenu, "/user/hand/left/input/menu/click"},
|
||||
{A_VrMetaMenu, "/user/hand/right/input/squeeze/click"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/trackpad/y"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/trackpad/x"},
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/trackpad/click"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/click"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/trackpad/x"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/trackpad/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/click"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/click"},
|
||||
};
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_MenuUpDown, "/user/hand/right/input/trackpad/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/trackpad/x"},
|
||||
{A_MenuSelect, "/user/hand/right/input/trackpad/click"},
|
||||
{A_MenuBack, "/user/hand/left/input/trackpad/click"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
};
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsViveCosmos()
|
||||
{
|
||||
std::string controllerProfilePath = "/interaction_profiles/htc/vive_cosmos_controller";
|
||||
|
||||
// In-game character controls
|
||||
SuggestedBindings gameplayBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{A_VrMetaMenu, "/user/hand/left/input/menu/click"},
|
||||
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/value"},
|
||||
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
|
||||
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
|
||||
{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
|
||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/click"},
|
||||
{MWInput::A_ToggleSpell, "/user/hand/left/input/x/click"},
|
||||
{MWInput::A_Rest, "/user/hand/left/input/y/click"},
|
||||
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
|
||||
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/click"},
|
||||
{A_ActivateTouch, "/user/hand/right/input/squeeze/value"},
|
||||
{MWInput::A_Activate, "/user/hand/right/input/squeeze/value"},
|
||||
};
|
||||
|
||||
// GUI controls
|
||||
SuggestedBindings GUIBindings{
|
||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
|
||||
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
|
||||
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
|
||||
{A_MenuSelect, "/user/hand/right/input/a/click"},
|
||||
{A_MenuBack, "/user/hand/right/input/b/click"},
|
||||
{MWInput::A_Use, "/user/hand/right/input/trigger/click"},
|
||||
};
|
||||
|
||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
||||
}
|
||||
|
||||
void VRInputManager::suggestBindingsXboxController()
|
||||
{
|
||||
//TODO
|
||||
mXRInput->suggestBindings(actionSet, interactionProfilePath, suggestedBindings);
|
||||
}
|
||||
|
||||
void VRInputManager::requestRecenter()
|
||||
|
@ -497,7 +286,8 @@ namespace MWVR
|
|||
bool userFileExists,
|
||||
const std::string& userControllerBindingsFile,
|
||||
const std::string& controllerBindingsFile,
|
||||
bool grab)
|
||||
bool grab,
|
||||
const std::string& xrControllerSuggestionsFile)
|
||||
: MWInput::InputManager(
|
||||
window,
|
||||
viewer,
|
||||
|
@ -509,23 +299,46 @@ namespace MWVR
|
|||
controllerBindingsFile,
|
||||
grab)
|
||||
, mXRInput(new OpenXRInput)
|
||||
, mXrControllerSuggestionsFile(xrControllerSuggestionsFile)
|
||||
, mHapticsEnabled{ Settings::Manager::getBool("haptics enabled", "VR") }
|
||||
{
|
||||
auto xr = MWVR::Environment::get().getManager();
|
||||
if (xrControllerSuggestionsFile.empty())
|
||||
throw std::runtime_error("No interaction profiles available (xrcontrollersuggestions.xml not found)");
|
||||
|
||||
suggestBindingsSimple();
|
||||
suggestBindingsOculusTouch();
|
||||
suggestBindingsMicrosoftMixedReality();
|
||||
suggestBindingsIndex();
|
||||
suggestBindingsVive();
|
||||
suggestBindingsXboxController();
|
||||
Log(Debug::Verbose) << "Reading Input Profile Path suggestions from " << xrControllerSuggestionsFile;
|
||||
|
||||
if (xr->xrExtensionIsEnabled(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))
|
||||
suggestBindingsHpMixedReality();
|
||||
if (xr->xrExtensionIsEnabled(XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME))
|
||||
suggestBindingsHuaweiController();
|
||||
if (xr->xrExtensionIsEnabled(XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME))
|
||||
suggestBindingsViveCosmos();
|
||||
TiXmlDocument* xmlDoc = nullptr;
|
||||
TiXmlElement* xmlRoot = nullptr;
|
||||
|
||||
xmlDoc = new TiXmlDocument(xrControllerSuggestionsFile.c_str());
|
||||
xmlDoc->LoadFile();
|
||||
|
||||
if (xmlDoc->Error())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "TinyXml reported an error reading \"" + xrControllerSuggestionsFile + "\". Row " <<
|
||||
(int)xmlDoc->ErrorRow() << ", Col " << (int)xmlDoc->ErrorCol() << ": " <<
|
||||
xmlDoc->ErrorDesc();
|
||||
Log(Debug::Error) << message.str();
|
||||
throw std::runtime_error(message.str());
|
||||
|
||||
delete xmlDoc;
|
||||
return;
|
||||
}
|
||||
|
||||
xmlRoot = xmlDoc->RootElement();
|
||||
if (std::string(xmlRoot->Value()) != "Root") {
|
||||
Log(Debug::Verbose) << "Error: Invalid xr controllers file. Missing <Root> element.";
|
||||
delete xmlDoc;
|
||||
return;
|
||||
}
|
||||
|
||||
TiXmlElement* profile = xmlRoot->FirstChildElement("Profile");
|
||||
while (profile)
|
||||
{
|
||||
readInteractionProfile(profile);
|
||||
profile = profile->NextSiblingElement("Profile");
|
||||
}
|
||||
|
||||
mXRInput->attachActionSets();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define VR_INPUT_MANAGER_HPP
|
||||
|
||||
#include "vrtypes.hpp"
|
||||
#include "vrinput.hpp"
|
||||
|
||||
#include "../mwinput/inputmanagerimp.hpp"
|
||||
|
||||
|
@ -11,6 +12,8 @@
|
|||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
class TiXmlElement;
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
struct OpenXRInput;
|
||||
|
@ -31,7 +34,8 @@ namespace MWVR
|
|||
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||
const std::string& userFile, bool userFileExists,
|
||||
const std::string& userControllerBindingsFile,
|
||||
const std::string& controllerBindingsFile, bool grab);
|
||||
const std::string& controllerBindingsFile, bool grab,
|
||||
const std::string& xrControllerSuggestionsFile);
|
||||
|
||||
virtual ~VRInputManager();
|
||||
|
||||
|
@ -50,6 +54,9 @@ namespace MWVR
|
|||
/// Currently active action set
|
||||
OpenXRActionSet& activeActionSet();
|
||||
|
||||
/// Notify input manager that the active interaction profile has changed
|
||||
void notifyInteractionProfileChanged();
|
||||
|
||||
protected:
|
||||
void processAction(const class Action* action, float dt, bool disableControls);
|
||||
|
||||
|
@ -63,21 +70,19 @@ namespace MWVR
|
|||
void applyHapticsRightHand(float intensity) override;
|
||||
void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) override;
|
||||
|
||||
private:
|
||||
void suggestBindingsSimple();
|
||||
void suggestBindingsOculusTouch();
|
||||
void suggestBindingsHpMixedReality();
|
||||
void suggestBindingsHuaweiController();
|
||||
void suggestBindingsIndex();
|
||||
void suggestBindingsMicrosoftMixedReality();
|
||||
void suggestBindingsVive();
|
||||
void suggestBindingsViveCosmos();
|
||||
void suggestBindingsXboxController();
|
||||
void throwDocumentError(TiXmlElement* element, std::string error);
|
||||
std::string requireAttribute(TiXmlElement* element, std::string attribute);
|
||||
void readInteractionProfile(TiXmlElement* element);
|
||||
void readInteractionProfileActionSet(TiXmlElement* element, ActionSet actionSet, std::string profilePath);
|
||||
|
||||
private:
|
||||
std::unique_ptr<OpenXRInput> mXRInput;
|
||||
std::unique_ptr<RealisticCombat::StateMachine> mRealisticCombat;
|
||||
std::string mXrControllerSuggestionsFile;
|
||||
bool mActivationIndication{ false };
|
||||
bool mHapticsEnabled{ true };
|
||||
|
||||
std::map<std::string, std::string> mInteractionProfileLocalNames;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
260
files/xrcontrollersuggestions.xml
Normal file
260
files/xrcontrollersuggestions.xml
Normal file
|
@ -0,0 +1,260 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2020 Mads Buvik Sandvei <madssandvei@protonmail.com>
|
||||
|
||||
Instructions:
|
||||
To edit this file. Copy it to my games/openmw/ (or equivalent for your platform)
|
||||
Consult the openxr specification for details of what Paths are available for your controllers:
|
||||
https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#semantic-path-interaction-profiles
|
||||
|
||||
Note that some controllers require OpenXR extensions. In which case consult the relevant extension section
|
||||
of the openxr spec instead of the linked section.
|
||||
You will not make an interaction profile work by removing the extension requirement form this file.
|
||||
-->
|
||||
<Root>
|
||||
<Actions>
|
||||
<!-- The <Actions> section exists for reference only and is not processed by OpenMW VR-->
|
||||
<!-- Note that some actions, such as menu_*, only take affect in GUI mode and vice versa -->
|
||||
<Action Name="game_menu" LocalName="Gameplay Game Menu"/>
|
||||
<Action Name="meta_menu" LocalName="Gameplay Meta Menu"/>
|
||||
<Action Name="reposition_menu" LocalName="Gameplay Reposition Menu"/>
|
||||
<Action Name="inventory" LocalName="Gameplay Inventory"/>
|
||||
<Action Name="activate" LocalName="Gameplay Activate"/>
|
||||
<Action Name="use" LocalName="Gameplay Use"/>
|
||||
<Action Name="jump" LocalName="Gameplay Jump"/>
|
||||
<Action Name="weapon" LocalName="Gameplay Weapon"/>
|
||||
<Action Name="spell" LocalName="Gameplay Spell"/>
|
||||
<Action Name="cycle_spell_left" LocalName="Gameplay Cycle Spell Left"/>
|
||||
<Action Name="cycle_spell_right" LocalName="Gameplay Cycle Spell Right"/>
|
||||
<Action Name="cycle_weapon_left" LocalName="Gameplay Cycle Weapon Left"/>
|
||||
<Action Name="cycle_weapon_right" LocalName="Gameplay Cycle Weapon Right"/>
|
||||
<Action Name="sneak" LocalName="Gameplay Sneak"/>
|
||||
<Action Name="quick_menu" LocalName="Gameplay Quick Menu"/>
|
||||
<Action Name="look_left_right" LocalName="Gameplay Look Left Right"/>
|
||||
<Action Name="move_forward_backward" LocalName="Gameplay Move Forward Backward"/>
|
||||
<Action Name="move_left_right" LocalName="Gameplay Move Left Right"/>
|
||||
<Action Name="journal_book" LocalName="Gameplay Journal Book"/>
|
||||
<Action Name="quick_save" LocalName="Gameplay Quick Save"/>
|
||||
<Action Name="rest" LocalName="Gameplay Rest"/>
|
||||
<Action Name="activate_touched" LocalName="Gameplay Activate Touch"/>
|
||||
<Action Name="always_run" LocalName="Gameplay Always Run"/>
|
||||
<Action Name="auto_move" LocalName="Gameplay Auto Move"/>
|
||||
<Action Name="toggle_hud" LocalName="Gameplay Toggle HUD"/>
|
||||
<Action Name="toggle_debug" LocalName="Gameplay Toggle the debug hud"/>
|
||||
<Action Name="menu_up_down" LocalName="Gameplay Menu Up Down"/>
|
||||
<Action Name="menu_left_right" LocalName="Gameplay Menu Left Right"/>
|
||||
<Action Name="menu_select" LocalName="Gameplay Menu Select"/>
|
||||
<Action Name="menu_back" LocalName="Gameplay Menu Back"/>
|
||||
</Actions>
|
||||
<Profile LocalName="Generic" Path="/interaction_profiles/khr/simple_controller">
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="use" Path="/user/hand/left/input/select/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/select/click"/>
|
||||
<Binding ActionName="auto_move" Path="/user/hand/right/input/menu/click"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="use" Path="/user/hand/left/input/select/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/select/click"/>
|
||||
<Binding ActionName="menu_back" Path="/user/hand/right/input/menu/click"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Oculus Touch Controllers" Path="/interaction_profiles/oculus/touch_controller">
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/squeeze/value"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/thumbstick/x"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/thumbstick/y"/>
|
||||
<Binding ActionName="always_run" Path="/user/hand/left/input/thumbstick/click"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/value"/>
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/x/click"/>
|
||||
<Binding ActionName="rest" Path="/user/hand/left/input/y/click"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="inventory" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/value"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/value"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="auto_move" Path="/user/hand/right/input/thumbstick/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/thumbstick/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="menu_back" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Microsoft Motion Controllers" Path="/interaction_profiles/microsoft/motion_controller">
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/right/input/squeeze/click"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/value"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/trackpad/y"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/trackpad/x"/>
|
||||
<Binding ActionName="rest" Path="/user/hand/left/input/thumbstick/click"/>
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/trackpad/click"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/squeeze/click"/>
|
||||
<Binding ActionName="inventory" Path="/user/hand/right/input/thumbstick/click"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/trackpad/x"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/trackpad/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/click"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/click"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="menu_back" Path="/user/hand/left/input/trackpad/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/trackpad/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/trackpad/x"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/trackpad/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Index Knuckles" Path="/interaction_profiles/valve/index_controller">
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/a/click"/>
|
||||
<Binding ActionName="rest" Path="/user/hand/left/input/b/click"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/thumbstick/y"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/thumbstick/x"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/trackpad/force"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/trackpad/force"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/value"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/squeeze/force"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="inventory" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/force"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/force"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/thumbstick/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/trackpad/force"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="menu_back" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/thumbstick/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Vive Wands" Path="/interaction_profiles/htc/vive_controller">
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/right/input/squeeze/click"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/trackpad/y"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/trackpad/x"/>
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/trackpad/click"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/value"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/squeeze/click"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/trackpad/x"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/trackpad/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/click"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/click"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/trackpad/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/trackpad/x"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/trackpad/click"/>
|
||||
<Binding ActionName="menu_back" Path="/user/hand/left/input/trackpad/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Hp Mixed Reality Controllers" Path="/interaction_profiles/hp/mixed_reality_controller">
|
||||
<Extension Name="XR_EXT_hp_mixed_reality_controller"/>
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/squeeze/value"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/thumbstick/y"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/thumbstick/x"/>
|
||||
<Binding ActionName="always_run" Path="/user/hand/left/input/thumbstick/click"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/value"/>
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/x/click"/>
|
||||
<Binding ActionName="rest" Path="/user/hand/left/input/y/click"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="inventory" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="auto_move" Path="/user/hand/right/input/thumbstick/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/value"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/value"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/thumbstick/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="menu_back" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/value"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Huawei Controllers" Path="/interaction_profiles/huawei/controller">
|
||||
<Extension Name="XR_HUAWEI_controller_interaction"/>
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/home/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/home/click"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/click"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/trackpad/y"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/trackpad/x"/>
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/trackpad/click"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/back/click"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/trackpad/x"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/trackpad/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/click"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/click"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/click"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="menu_back" Path="/user/hand/left/input/trackpad/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/home/click"/>
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/home/click"/>
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/thumbstick/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/trackpad/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/click"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
<Profile LocalName="Vive Cosmos Controllers" Path="/interaction_profiles/htc/vive_cosmos_controller">
|
||||
<Extension Name="XR_HTC_vive_cosmos_controller_interaction"/>
|
||||
<ActionSet Name="Gameplay">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="meta_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="sneak" Path="/user/hand/left/input/squeeze/value"/>
|
||||
<Binding ActionName="move_forward_backward" Path="/user/hand/left/input/thumbstick/y"/>
|
||||
<Binding ActionName="move_left_right" Path="/user/hand/left/input/thumbstick/x"/>
|
||||
<Binding ActionName="always_run" Path="/user/hand/left/input/thumbstick/click"/>
|
||||
<Binding ActionName="jump" Path="/user/hand/left/input/trigger/click"/>
|
||||
<Binding ActionName="spell" Path="/user/hand/left/input/x/click"/>
|
||||
<Binding ActionName="rest" Path="/user/hand/left/input/y/click"/>
|
||||
<Binding ActionName="weapon" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="inventory" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="look_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="auto_move" Path="/user/hand/right/input/thumbstick/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/click"/>
|
||||
<Binding ActionName="activate_touched" Path="/user/hand/right/input/squeeze/value"/>
|
||||
<Binding ActionName="activate" Path="/user/hand/right/input/squeeze/value"/>
|
||||
</ActionSet>
|
||||
<ActionSet Name="GUI">
|
||||
<Binding ActionName="reposition_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="game_menu" Path="/user/hand/left/input/menu/click"/>
|
||||
<Binding ActionName="menu_up_down" Path="/user/hand/right/input/thumbstick/y"/>
|
||||
<Binding ActionName="menu_left_right" Path="/user/hand/right/input/thumbstick/x"/>
|
||||
<Binding ActionName="menu_select" Path="/user/hand/right/input/a/click"/>
|
||||
<Binding ActionName="menu_back" Path="/user/hand/right/input/b/click"/>
|
||||
<Binding ActionName="use" Path="/user/hand/right/input/trigger/click"/>
|
||||
</ActionSet>
|
||||
</Profile>
|
||||
</Root>
|
Loading…
Reference in a new issue