first commit
This commit is contained in:
507
3rdparty/osgXR/src/Action.cpp
vendored
Normal file
507
3rdparty/osgXR/src/Action.cpp
vendored
Normal file
@@ -0,0 +1,507 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-only
|
||||
// Copyright (C) 2021 James Hogan <james@albanarts.com>
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionSet.h"
|
||||
|
||||
#include "OpenXR/Action.h"
|
||||
#include "OpenXR/Session.h"
|
||||
#include "OpenXR/Space.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace osgXR;
|
||||
|
||||
// Internal API
|
||||
|
||||
Action::Private::Private(ActionSet *actionSet) :
|
||||
_actionSet(actionSet),
|
||||
_updated(true)
|
||||
{
|
||||
ActionSet::Private::get(_actionSet)->registerAction(this);
|
||||
}
|
||||
|
||||
Action::Private::~Private()
|
||||
{
|
||||
ActionSet::Private::get(_actionSet)->unregisterAction(this);
|
||||
}
|
||||
|
||||
void Action::Private::setName(const std::string &name)
|
||||
{
|
||||
_updated = true;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
const std::string &Action::Private::getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
void Action::Private::setLocalizedName(const std::string &localizedName)
|
||||
{
|
||||
_updated = true;
|
||||
_localizedName = localizedName;
|
||||
}
|
||||
|
||||
const std::string &Action::Private::getLocalizedName() const
|
||||
{
|
||||
return _localizedName;
|
||||
}
|
||||
|
||||
void Action::Private::addSubaction(std::shared_ptr<Subaction::Private> subaction)
|
||||
{
|
||||
_updated = true;
|
||||
_subactions.insert(subaction);
|
||||
}
|
||||
|
||||
void Action::Private::cleanupInstance()
|
||||
{
|
||||
_updated = true;
|
||||
_action = nullptr;
|
||||
}
|
||||
|
||||
void Action::Private::getBoundSources(std::vector<std::string> &sourcePaths) const
|
||||
{
|
||||
OpenXR::Session *session = ActionSet::Private::get(_actionSet)->getSession();
|
||||
if (_action.valid() && session)
|
||||
{
|
||||
std::vector<XrPath> paths;
|
||||
if (session->getActionBoundSources(_action, paths))
|
||||
{
|
||||
// Convert XrPath's into std::string's
|
||||
OpenXR::Instance *instance = session->getInstance();
|
||||
sourcePaths.resize(paths.size());
|
||||
for (unsigned int i = 0; i < paths.size(); ++i)
|
||||
sourcePaths[i] = OpenXR::Path(instance, paths[i]).toString();
|
||||
|
||||
// Success!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Failure, clear output
|
||||
sourcePaths.resize(0);
|
||||
}
|
||||
|
||||
void Action::Private::getBoundSourcesLocalizedNames(XrInputSourceLocalizedNameFlags whichComponents,
|
||||
std::vector<std::string> &names) const
|
||||
{
|
||||
OpenXR::Session *session = ActionSet::Private::get(_actionSet)->getSession();
|
||||
if (_action.valid() && session)
|
||||
{
|
||||
std::vector<XrPath> paths;
|
||||
if (session->getActionBoundSources(_action, paths))
|
||||
{
|
||||
// Convert XrPath's into localized names
|
||||
names.resize(paths.size());
|
||||
for (unsigned int i = 0; i < paths.size(); ++i)
|
||||
names[i] = session->getInputSourceLocalizedName(paths[i],
|
||||
whichComponents);
|
||||
|
||||
// Success!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Failure, clear output
|
||||
names.resize(0);
|
||||
}
|
||||
|
||||
namespace osgXR {
|
||||
|
||||
template <typename T>
|
||||
class ActionPrivateCommon : public Action::Private
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename T::State State;
|
||||
|
||||
ActionPrivateCommon(ActionSet *actionSet) :
|
||||
Private(actionSet)
|
||||
{
|
||||
}
|
||||
|
||||
void cleanupSession() override
|
||||
{
|
||||
_states.clear();
|
||||
}
|
||||
|
||||
OpenXR::Action *setup(OpenXR::Instance *instance) override
|
||||
{
|
||||
OpenXR::ActionSet *actionSet = ActionSet::Private::get(_actionSet)->setup(instance);
|
||||
if (!actionSet)
|
||||
{
|
||||
// Can't continue without an action set
|
||||
_action = nullptr;
|
||||
_updated = true;
|
||||
}
|
||||
else if (_updated || actionSet != _action->getActionSet())
|
||||
{
|
||||
_action = new T(actionSet, _name, _localizedName);
|
||||
for (auto &subaction: _subactions)
|
||||
_action->addSubaction(subaction->setup(instance));
|
||||
_updated = false;
|
||||
}
|
||||
return _action;
|
||||
}
|
||||
|
||||
State *getState(Subaction::Private *subaction = nullptr)
|
||||
{
|
||||
auto it = _states.find(subaction);
|
||||
if (it != _states.end())
|
||||
return (*it).second.get();
|
||||
|
||||
OpenXR::Session *session = ActionSet::Private::get(_actionSet)->getSession();
|
||||
if (session)
|
||||
{
|
||||
OpenXR::Path subactionPath;
|
||||
if (subaction)
|
||||
subactionPath = subaction->setup(session->getInstance());
|
||||
OpenXR::Action *action = setup(session->getInstance());
|
||||
if (action)
|
||||
{
|
||||
osg::ref_ptr<State> ret = static_cast<T*>(_action.get())->createState(session,
|
||||
subactionPath);
|
||||
_states[subaction] = ret;
|
||||
return ret.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::map<Subaction::Private *, osg::ref_ptr<State>> _states;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ActionPrivateSimple : public ActionPrivateCommon<T>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename T::State State;
|
||||
|
||||
ActionPrivateSimple(ActionSet *actionSet) :
|
||||
ActionPrivateCommon<T>(actionSet)
|
||||
{
|
||||
}
|
||||
|
||||
auto getValue(Subaction::Private *subaction)
|
||||
{
|
||||
State *state = this->getState(subaction);
|
||||
if (state && state->update() && state->isActive())
|
||||
return state->getCurrentState();
|
||||
else
|
||||
return T::State::Info::defaultValue();
|
||||
}
|
||||
};
|
||||
|
||||
typedef ActionPrivateSimple<OpenXR::ActionBoolean> ActionPrivateBoolean;
|
||||
typedef ActionPrivateSimple<OpenXR::ActionFloat> ActionPrivateFloat;
|
||||
typedef ActionPrivateSimple<OpenXR::ActionVector2f> ActionPrivateVector2f;
|
||||
|
||||
class ActionPrivatePose : public ActionPrivateCommon<OpenXR::ActionPose>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef OpenXR::ActionPose::State State;
|
||||
|
||||
ActionPrivatePose(ActionSet *actionSet) :
|
||||
ActionPrivateCommon(actionSet)
|
||||
{
|
||||
}
|
||||
|
||||
OpenXR::Space *getSpace(Subaction::Private *subaction)
|
||||
{
|
||||
State *state = getState(subaction);
|
||||
if (state && state->update() && state->isActive())
|
||||
return state->getSpace();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool locate(Subaction::Private *subaction,
|
||||
ActionPose::Location &location)
|
||||
{
|
||||
OpenXR::Space *space = getSpace(subaction);
|
||||
OpenXR::Session *session = ActionSet::Private::get(_actionSet)->getSession();
|
||||
if (session && space)
|
||||
{
|
||||
OpenXR::Space::Location loc;
|
||||
bool ret = space->locate(session->getLocalSpace(), session->getLastDisplayTime(),
|
||||
loc);
|
||||
location = ActionPose::Location((ActionPose::Location::Flags)loc.getFlags(),
|
||||
loc.getOrientation(),
|
||||
loc.getPosition());
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
location = ActionPose::Location();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ActionPrivateVibration : public ActionPrivateCommon<OpenXR::ActionVibration>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef OpenXR::ActionVibration::State State;
|
||||
|
||||
ActionPrivateVibration(ActionSet *actionSet) :
|
||||
ActionPrivateCommon(actionSet)
|
||||
{
|
||||
}
|
||||
|
||||
bool applyHapticFeedback(Subaction::Private *subaction,
|
||||
int64_t duration_ns, float frequency,
|
||||
float amplitude)
|
||||
{
|
||||
State *state = getState(subaction);
|
||||
if (!state)
|
||||
return false;
|
||||
return state->applyHapticFeedback(duration_ns, frequency,
|
||||
amplitude);
|
||||
}
|
||||
|
||||
bool stopHapticFeedback(Subaction::Private *subaction)
|
||||
{
|
||||
State *state = getState(subaction);
|
||||
if (!state)
|
||||
return false;
|
||||
return state->stopHapticFeedback();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
Action::Action(Private *priv) :
|
||||
_private(priv)
|
||||
{
|
||||
}
|
||||
|
||||
Action::~Action()
|
||||
{
|
||||
}
|
||||
|
||||
void Action::addSubaction(Subaction *subaction)
|
||||
{
|
||||
_private->addSubaction(Subaction::Private::get(subaction));
|
||||
}
|
||||
|
||||
void Action::setName(const std::string &name,
|
||||
const std::string &localizedName)
|
||||
{
|
||||
_private->setName(name);
|
||||
_private->setLocalizedName(localizedName);
|
||||
}
|
||||
|
||||
void Action::setName(const std::string &name)
|
||||
{
|
||||
_private->setName(name);
|
||||
}
|
||||
|
||||
const std::string &Action::getName() const
|
||||
{
|
||||
return _private->getName();
|
||||
}
|
||||
|
||||
void Action::setLocalizedName(const std::string &localizedName)
|
||||
{
|
||||
_private->setLocalizedName(localizedName);
|
||||
}
|
||||
|
||||
const std::string &Action::getLocalizedName() const
|
||||
{
|
||||
return _private->getLocalizedName();
|
||||
}
|
||||
|
||||
void Action::getBoundSources(std::vector<std::string> &sourcePaths) const
|
||||
{
|
||||
_private->getBoundSources(sourcePaths);
|
||||
}
|
||||
|
||||
void Action::getBoundSourcesLocalizedNames(uint32_t whichComponents,
|
||||
std::vector<std::string> &names) const
|
||||
{
|
||||
_private->getBoundSourcesLocalizedNames(whichComponents, names);
|
||||
}
|
||||
|
||||
// ActionBoolean
|
||||
|
||||
ActionBoolean::ActionBoolean(ActionSet *actionSet) :
|
||||
Action(new ActionPrivateBoolean(actionSet))
|
||||
{
|
||||
}
|
||||
|
||||
ActionBoolean::ActionBoolean(ActionSet *actionSet,
|
||||
const std::string &name) :
|
||||
Action(new ActionPrivateBoolean(actionSet))
|
||||
{
|
||||
setName(name, name);
|
||||
}
|
||||
|
||||
ActionBoolean::ActionBoolean(ActionSet *actionSet,
|
||||
const std::string &name,
|
||||
const std::string &localizedName) :
|
||||
Action(new ActionPrivateBoolean(actionSet))
|
||||
{
|
||||
setName(name, localizedName);
|
||||
}
|
||||
|
||||
bool ActionBoolean::getValue(Subaction *subaction)
|
||||
{
|
||||
auto privSubaction = Subaction::Private::get(subaction);
|
||||
return static_cast<ActionPrivateBoolean *>(Private::get(this))->getValue(privSubaction.get());
|
||||
}
|
||||
|
||||
// ActionFloat
|
||||
|
||||
ActionFloat::ActionFloat(ActionSet *actionSet) :
|
||||
Action(new ActionPrivateFloat(actionSet))
|
||||
{
|
||||
}
|
||||
|
||||
ActionFloat::ActionFloat(ActionSet *actionSet,
|
||||
const std::string &name) :
|
||||
Action(new ActionPrivateFloat(actionSet))
|
||||
{
|
||||
setName(name, name);
|
||||
}
|
||||
|
||||
ActionFloat::ActionFloat(ActionSet *actionSet,
|
||||
const std::string &name,
|
||||
const std::string &localizedName) :
|
||||
Action(new ActionPrivateFloat(actionSet))
|
||||
{
|
||||
setName(name, localizedName);
|
||||
}
|
||||
|
||||
float ActionFloat::getValue(Subaction *subaction)
|
||||
{
|
||||
auto privSubaction = Subaction::Private::get(subaction);
|
||||
return static_cast<ActionPrivateFloat *>(Private::get(this))->getValue(privSubaction.get());
|
||||
}
|
||||
|
||||
// ActionVector2f
|
||||
|
||||
ActionVector2f::ActionVector2f(ActionSet *actionSet) :
|
||||
Action(new ActionPrivateVector2f(actionSet))
|
||||
{
|
||||
}
|
||||
|
||||
ActionVector2f::ActionVector2f(ActionSet *actionSet,
|
||||
const std::string &name) :
|
||||
Action(new ActionPrivateVector2f(actionSet))
|
||||
{
|
||||
setName(name, name);
|
||||
}
|
||||
|
||||
ActionVector2f::ActionVector2f(ActionSet *actionSet,
|
||||
const std::string &name,
|
||||
const std::string &localizedName) :
|
||||
Action(new ActionPrivateVector2f(actionSet))
|
||||
{
|
||||
setName(name, localizedName);
|
||||
}
|
||||
|
||||
osg::Vec2f ActionVector2f::getValue(Subaction *subaction)
|
||||
{
|
||||
auto privSubaction = Subaction::Private::get(subaction);
|
||||
return static_cast<ActionPrivateVector2f *>(Private::get(this))->getValue(privSubaction.get());
|
||||
}
|
||||
|
||||
// ActionPose
|
||||
|
||||
ActionPose::ActionPose(ActionSet *actionSet) :
|
||||
Action(new ActionPrivatePose(actionSet))
|
||||
{
|
||||
}
|
||||
|
||||
ActionPose::ActionPose(ActionSet *actionSet,
|
||||
const std::string &name) :
|
||||
Action(new ActionPrivatePose(actionSet))
|
||||
{
|
||||
setName(name, name);
|
||||
}
|
||||
|
||||
ActionPose::ActionPose(ActionSet *actionSet,
|
||||
const std::string &name,
|
||||
const std::string &localizedName) :
|
||||
Action(new ActionPrivatePose(actionSet))
|
||||
{
|
||||
setName(name, localizedName);
|
||||
}
|
||||
|
||||
ActionPose::Location ActionPose::getValue(Subaction *subaction)
|
||||
{
|
||||
Location location;
|
||||
auto privSubaction = Subaction::Private::get(subaction);
|
||||
static_cast<ActionPrivatePose *>(Private::get(this))->locate(privSubaction.get(),
|
||||
location);
|
||||
return location;
|
||||
}
|
||||
|
||||
ActionPose::Location::Location() :
|
||||
_flags((Flags)0)
|
||||
{
|
||||
}
|
||||
|
||||
ActionPose::Location::Location(Flags flags,
|
||||
const osg::Quat &orientation,
|
||||
const osg::Vec3f &position) :
|
||||
_flags(flags),
|
||||
_orientation(orientation),
|
||||
_position(position)
|
||||
{
|
||||
}
|
||||
|
||||
// ActionVibration
|
||||
|
||||
ActionVibration::ActionVibration(ActionSet *actionSet) :
|
||||
Action(new ActionPrivateVibration(actionSet))
|
||||
{
|
||||
}
|
||||
|
||||
ActionVibration::ActionVibration(ActionSet *actionSet,
|
||||
const std::string &name) :
|
||||
Action(new ActionPrivateVibration(actionSet))
|
||||
{
|
||||
setName(name, name);
|
||||
}
|
||||
|
||||
ActionVibration::ActionVibration(ActionSet *actionSet,
|
||||
const std::string &name,
|
||||
const std::string &localizedName) :
|
||||
Action(new ActionPrivateVibration(actionSet))
|
||||
{
|
||||
setName(name, localizedName);
|
||||
}
|
||||
|
||||
bool ActionVibration::applyHapticFeedback(int64_t duration_ns, float frequency,
|
||||
float amplitude)
|
||||
{
|
||||
auto priv = static_cast<ActionPrivateVibration *>(Private::get(this));
|
||||
return priv->applyHapticFeedback(nullptr, duration_ns, frequency,
|
||||
amplitude);
|
||||
}
|
||||
|
||||
bool ActionVibration::applyHapticFeedback(Subaction *subaction,
|
||||
int64_t duration_ns, float frequency,
|
||||
float amplitude)
|
||||
{
|
||||
auto privSubaction = Subaction::Private::get(subaction);
|
||||
auto priv = static_cast<ActionPrivateVibration *>(Private::get(this));
|
||||
return priv->applyHapticFeedback(privSubaction.get(), duration_ns, frequency,
|
||||
amplitude);
|
||||
}
|
||||
|
||||
bool ActionVibration::stopHapticFeedback(Subaction *subaction)
|
||||
{
|
||||
auto privSubaction = Subaction::Private::get(subaction);
|
||||
auto priv = static_cast<ActionPrivateVibration *>(Private::get(this));
|
||||
return priv->stopHapticFeedback(privSubaction.get());
|
||||
}
|
||||
Reference in New Issue
Block a user