mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 07:23:51 +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}
|
${GAME} ${GAME_HEADER}
|
||||||
${APPLE_BUNDLE_RESOURCES}
|
${APPLE_BUNDLE_RESOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
configure_resource_file(${OpenMW_SOURCE_DIR}/files/xrcontrollersuggestions.xml
|
||||||
|
"${OpenMW_BINARY_DIR}" "xrcontrollersuggestions.xml")
|
||||||
|
|
||||||
########### Import the OpenXR SDK
|
########### Import the OpenXR SDK
|
||||||
# Force the openxr-sdk to use its bundled jsoncpp to avoid problems from system jsoncpp if present
|
# 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());
|
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
|
||||||
mEnvironment.setWindowManager (window);
|
mEnvironment.setWindowManager (window);
|
||||||
|
|
||||||
MWInput::InputManager* input =
|
|
||||||
#ifdef USE_OPENXR
|
#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
|
#else
|
||||||
|
MWInput::InputManager* input =
|
||||||
new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||||
#endif
|
#endif
|
||||||
mEnvironment.setInputManager (input);
|
mEnvironment.setInputManager (input);
|
||||||
|
|
|
@ -120,7 +120,8 @@ namespace MWVR
|
||||||
const std::string& actionName,
|
const std::string& actionName,
|
||||||
const std::string& localName)
|
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
|
XrActionSet
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace MWVR
|
||||||
XrActionSet mActionSet{ nullptr };
|
XrActionSet mActionSet{ nullptr };
|
||||||
std::string mLocalizedName{};
|
std::string mLocalizedName{};
|
||||||
std::string mInternalName{};
|
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<PoseAction>> mTrackerMap;
|
||||||
std::map<TrackedLimb, std::unique_ptr<HapticsAction>> mHapticsMap;
|
std::map<TrackedLimb, std::unique_ptr<HapticsAction>> mHapticsMap;
|
||||||
std::deque<const Action*> mActionQueue{};
|
std::deque<const Action*> mActionQueue{};
|
||||||
|
|
|
@ -28,9 +28,9 @@ namespace MWVR
|
||||||
return it->second;
|
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()
|
void OpenXRInput::attachActionSets()
|
||||||
|
@ -48,6 +48,8 @@ namespace MWVR
|
||||||
xrProfileSuggestedBindings.suggestedBindings = profile.second.data();
|
xrProfileSuggestedBindings.suggestedBindings = profile.second.data();
|
||||||
xrProfileSuggestedBindings.countSuggestedBindings = (uint32_t)profile.second.size();
|
xrProfileSuggestedBindings.countSuggestedBindings = (uint32_t)profile.second.size();
|
||||||
CHECK_XRCMD(xrSuggestInteractionProfileBindings(xr->impl().xrInstance(), &xrProfileSuggestedBindings));
|
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.
|
// OpenXR requires that xrAttachSessionActionSets be called at most once per session.
|
||||||
|
@ -62,4 +64,49 @@ namespace MWVR
|
||||||
attachInfo.actionSets = actionSets.data();
|
attachInfo.actionSets = actionSets.data();
|
||||||
CHECK_XRCMD(xrAttachSessionActionSets(xr->impl().xrSession(), &attachInfo));
|
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.
|
//! Set bindings and attach actionSets to the session.
|
||||||
void attachActionSets();
|
void attachActionSets();
|
||||||
|
|
||||||
|
//! Notify that active interaction profile has changed
|
||||||
|
void notifyInteractionProfileChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::map<ActionSet, OpenXRActionSet> mActionSets{};
|
std::map<ActionSet, OpenXRActionSet> mActionSets{};
|
||||||
|
std::map<XrPath, std::string> mInteractionProfileNames{};
|
||||||
|
std::map<std::string, XrPath> mInteractionProfilePaths{};
|
||||||
|
std::map<XrPath, XrPath> mActiveInteractionProfiles;
|
||||||
XrProfileSuggestedBindings mSuggestedBindings{};
|
XrProfileSuggestedBindings mSuggestedBindings{};
|
||||||
bool mAttached = false;
|
bool mAttached = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "openxrdebug.hpp"
|
#include "openxrdebug.hpp"
|
||||||
#include "openxrswapchain.hpp"
|
#include "openxrswapchain.hpp"
|
||||||
#include "openxrswapchainimpl.hpp"
|
#include "openxrswapchainimpl.hpp"
|
||||||
|
#include "vrenvironment.hpp"
|
||||||
|
#include "vrinputmanager.hpp"
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
||||||
|
@ -685,8 +687,10 @@ namespace MWVR
|
||||||
return handleSessionStateChanged(*stateChangeEvent);
|
return handleSessionStateChanged(*stateChangeEvent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
|
||||||
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
|
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:
|
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
|
||||||
default:
|
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).
|
/// \brief Suggest a binding by binding an action to a path on a given hand (left or right).
|
||||||
struct SuggestedBinding
|
struct SuggestedBinding
|
||||||
{
|
{
|
||||||
int action;
|
|
||||||
std::string path;
|
std::string path;
|
||||||
|
std::string action;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SuggestedBindings = std::vector<SuggestedBinding>;
|
using SuggestedBindings = std::vector<SuggestedBinding>;
|
||||||
|
@ -124,7 +124,6 @@ namespace MWVR
|
||||||
void updateAndQueue(std::deque<const Action*>& queue);
|
void updateAndQueue(std::deque<const Action*>& queue);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::unique_ptr<OpenXRAction> mXRAction;
|
std::unique_ptr<OpenXRAction> mXRAction;
|
||||||
int mOpenMWAction;
|
int mOpenMWAction;
|
||||||
float mValue{ 0.f };
|
float mValue{ 0.f };
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "../mwrender/camera.hpp"
|
#include "../mwrender/camera.hpp"
|
||||||
|
|
||||||
#include <extern/oics/ICSInputControlSystem.h>
|
#include <extern/oics/ICSInputControlSystem.h>
|
||||||
|
#include <extern/oics/tinyxml.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -57,6 +58,11 @@ namespace MWVR
|
||||||
return mXRInput->getActionSet(ActionSet::Gameplay);
|
return mXRInput->getActionSet(ActionSet::Gameplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VRInputManager::notifyInteractionProfileChanged()
|
||||||
|
{
|
||||||
|
mXRInput->notifyInteractionProfileChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void VRInputManager::updateActivationIndication(void)
|
void VRInputManager::updateActivationIndication(void)
|
||||||
{
|
{
|
||||||
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
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.
|
* 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";
|
std::stringstream ss;
|
||||||
// Set up default bindings for the khronos simple controller.
|
ss << mXrControllerSuggestionsFile << "." << element->Row() << "." << element->Value();
|
||||||
// Note: The simple controller is the equivalent to a universal "default".
|
ss << ": " << error;
|
||||||
// It has highly reduced functionality. Only poses and two click actions
|
throw std::runtime_error(ss.str());
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VRInputManager::suggestBindingsOculusTouch()
|
std::string VRInputManager::requireAttribute(TiXmlElement* element, std::string attribute)
|
||||||
{
|
{
|
||||||
std::string controllerProfilePath = "/interaction_profiles/oculus/touch_controller";
|
const char* value = element->Attribute(attribute.c_str());
|
||||||
|
if (!value)
|
||||||
// In-game character controls
|
throwDocumentError(element, std::string() + "Missing attribute '" + attribute + "'");
|
||||||
SuggestedBindings gameplayBindings{
|
return value;
|
||||||
{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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
Log(Debug::Verbose) << "Configuring interaction profile '" << interactionProfilePath << "' (" << mInteractionProfileLocalNames[interactionProfilePath] << ")";
|
||||||
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"},
|
|
||||||
};
|
|
||||||
|
|
||||||
// GUI controls
|
// Check extension if present
|
||||||
SuggestedBindings GUIBindings{
|
TiXmlElement* extensionElement = element->FirstChildElement("Extension");
|
||||||
{A_Recenter, "/user/hand/left/input/menu/click"},
|
if (extensionElement)
|
||||||
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
|
{
|
||||||
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
|
std::string extension = requireAttribute(extensionElement, "Name");
|
||||||
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
|
auto xr = MWVR::Environment::get().getManager();
|
||||||
{A_MenuSelect, "/user/hand/right/input/a/click"},
|
if (!xr->xrExtensionIsEnabled(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))
|
||||||
{A_MenuBack, "/user/hand/right/input/b/click"},
|
{
|
||||||
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
|
Log(Debug::Verbose) << " Required extension '" << extension << "' not supported. Skipping interaction profile.";
|
||||||
};
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
TiXmlElement* actionSetGameplay = nullptr;
|
||||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
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
|
TiXmlElement* child = element->FirstChildElement("Binding");
|
||||||
SuggestedBindings gameplayBindings{
|
while (child)
|
||||||
{A_Recenter, "/user/hand/left/input/home/click"},
|
{
|
||||||
{A_VrMetaMenu, "/user/hand/left/input/home/click"},
|
std::string action = requireAttribute(child, "ActionName");
|
||||||
{MWInput::A_Jump, "/user/hand/left/input/trigger/click"},
|
std::string path = requireAttribute(child, "Path");
|
||||||
{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"},
|
|
||||||
};
|
|
||||||
|
|
||||||
// GUI controls
|
suggestedBindings.push_back(
|
||||||
SuggestedBindings GUIBindings{
|
SuggestedBinding{
|
||||||
{A_MenuBack, "/user/hand/left/input/trackpad/click"},
|
path, action
|
||||||
{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"},
|
|
||||||
};
|
|
||||||
|
|
||||||
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
|
Log(Debug::Debug) << " " << action << ": " << path;
|
||||||
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VRInputManager::suggestBindingsMicrosoftMixedReality()
|
child = child->NextSiblingElement("Binding");
|
||||||
{
|
}
|
||||||
std::string controllerProfilePath = "/interaction_profiles/microsoft/motion_controller";
|
|
||||||
|
|
||||||
// In-game character controls
|
mXRInput->suggestBindings(actionSet, interactionProfilePath, suggestedBindings);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VRInputManager::requestRecenter()
|
void VRInputManager::requestRecenter()
|
||||||
|
@ -497,7 +286,8 @@ namespace MWVR
|
||||||
bool userFileExists,
|
bool userFileExists,
|
||||||
const std::string& userControllerBindingsFile,
|
const std::string& userControllerBindingsFile,
|
||||||
const std::string& controllerBindingsFile,
|
const std::string& controllerBindingsFile,
|
||||||
bool grab)
|
bool grab,
|
||||||
|
const std::string& xrControllerSuggestionsFile)
|
||||||
: MWInput::InputManager(
|
: MWInput::InputManager(
|
||||||
window,
|
window,
|
||||||
viewer,
|
viewer,
|
||||||
|
@ -509,23 +299,46 @@ namespace MWVR
|
||||||
controllerBindingsFile,
|
controllerBindingsFile,
|
||||||
grab)
|
grab)
|
||||||
, mXRInput(new OpenXRInput)
|
, mXRInput(new OpenXRInput)
|
||||||
|
, mXrControllerSuggestionsFile(xrControllerSuggestionsFile)
|
||||||
, mHapticsEnabled{ Settings::Manager::getBool("haptics enabled", "VR") }
|
, 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();
|
Log(Debug::Verbose) << "Reading Input Profile Path suggestions from " << xrControllerSuggestionsFile;
|
||||||
suggestBindingsOculusTouch();
|
|
||||||
suggestBindingsMicrosoftMixedReality();
|
|
||||||
suggestBindingsIndex();
|
|
||||||
suggestBindingsVive();
|
|
||||||
suggestBindingsXboxController();
|
|
||||||
|
|
||||||
if (xr->xrExtensionIsEnabled(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))
|
TiXmlDocument* xmlDoc = nullptr;
|
||||||
suggestBindingsHpMixedReality();
|
TiXmlElement* xmlRoot = nullptr;
|
||||||
if (xr->xrExtensionIsEnabled(XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME))
|
|
||||||
suggestBindingsHuaweiController();
|
xmlDoc = new TiXmlDocument(xrControllerSuggestionsFile.c_str());
|
||||||
if (xr->xrExtensionIsEnabled(XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME))
|
xmlDoc->LoadFile();
|
||||||
suggestBindingsViveCosmos();
|
|
||||||
|
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();
|
mXRInput->attachActionSets();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define VR_INPUT_MANAGER_HPP
|
#define VR_INPUT_MANAGER_HPP
|
||||||
|
|
||||||
#include "vrtypes.hpp"
|
#include "vrtypes.hpp"
|
||||||
|
#include "vrinput.hpp"
|
||||||
|
|
||||||
#include "../mwinput/inputmanagerimp.hpp"
|
#include "../mwinput/inputmanagerimp.hpp"
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
class TiXmlElement;
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
struct OpenXRInput;
|
struct OpenXRInput;
|
||||||
|
@ -31,7 +34,8 @@ namespace MWVR
|
||||||
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||||
const std::string& userFile, bool userFileExists,
|
const std::string& userFile, bool userFileExists,
|
||||||
const std::string& userControllerBindingsFile,
|
const std::string& userControllerBindingsFile,
|
||||||
const std::string& controllerBindingsFile, bool grab);
|
const std::string& controllerBindingsFile, bool grab,
|
||||||
|
const std::string& xrControllerSuggestionsFile);
|
||||||
|
|
||||||
virtual ~VRInputManager();
|
virtual ~VRInputManager();
|
||||||
|
|
||||||
|
@ -50,6 +54,9 @@ namespace MWVR
|
||||||
/// Currently active action set
|
/// Currently active action set
|
||||||
OpenXRActionSet& activeActionSet();
|
OpenXRActionSet& activeActionSet();
|
||||||
|
|
||||||
|
/// Notify input manager that the active interaction profile has changed
|
||||||
|
void notifyInteractionProfileChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void processAction(const class Action* action, float dt, bool disableControls);
|
void processAction(const class Action* action, float dt, bool disableControls);
|
||||||
|
|
||||||
|
@ -63,21 +70,19 @@ namespace MWVR
|
||||||
void applyHapticsRightHand(float intensity) override;
|
void applyHapticsRightHand(float intensity) override;
|
||||||
void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) override;
|
void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) override;
|
||||||
|
|
||||||
private:
|
void throwDocumentError(TiXmlElement* element, std::string error);
|
||||||
void suggestBindingsSimple();
|
std::string requireAttribute(TiXmlElement* element, std::string attribute);
|
||||||
void suggestBindingsOculusTouch();
|
void readInteractionProfile(TiXmlElement* element);
|
||||||
void suggestBindingsHpMixedReality();
|
void readInteractionProfileActionSet(TiXmlElement* element, ActionSet actionSet, std::string profilePath);
|
||||||
void suggestBindingsHuaweiController();
|
|
||||||
void suggestBindingsIndex();
|
|
||||||
void suggestBindingsMicrosoftMixedReality();
|
|
||||||
void suggestBindingsVive();
|
|
||||||
void suggestBindingsViveCosmos();
|
|
||||||
void suggestBindingsXboxController();
|
|
||||||
|
|
||||||
|
private:
|
||||||
std::unique_ptr<OpenXRInput> mXRInput;
|
std::unique_ptr<OpenXRInput> mXRInput;
|
||||||
std::unique_ptr<RealisticCombat::StateMachine> mRealisticCombat;
|
std::unique_ptr<RealisticCombat::StateMachine> mRealisticCombat;
|
||||||
|
std::string mXrControllerSuggestionsFile;
|
||||||
bool mActivationIndication{ false };
|
bool mActivationIndication{ false };
|
||||||
bool mHapticsEnabled{ true };
|
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