mirror of
https://github.com/overte-org/overte.git
synced 2025-08-12 01:42:46 +02:00
AxisValue action channels now have a 'valid' flag, like Poses do
This commit is contained in:
parent
73e6be9c37
commit
954aeb5e25
21 changed files with 57 additions and 26 deletions
|
@ -12,10 +12,13 @@
|
||||||
|
|
||||||
namespace controller {
|
namespace controller {
|
||||||
|
|
||||||
AxisValue::AxisValue(const float value, const quint64 timestamp) :
|
AxisValue::AxisValue(const float value, const quint64 timestamp, bool valid) :
|
||||||
value(value), timestamp(timestamp) { }
|
value(value), timestamp(timestamp), valid(valid) {
|
||||||
|
}
|
||||||
|
|
||||||
bool AxisValue::operator==(const AxisValue& right) const {
|
bool AxisValue::operator==(const AxisValue& right) const {
|
||||||
return value == right.value && timestamp == right.timestamp;
|
return value == right.value &&
|
||||||
|
timestamp == right.timestamp &&
|
||||||
|
valid == right.valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,14 @@ namespace controller {
|
||||||
float value { 0.0f };
|
float value { 0.0f };
|
||||||
// The value can be timestamped to determine if consecutive identical values should be output (e.g., mouse movement).
|
// The value can be timestamped to determine if consecutive identical values should be output (e.g., mouse movement).
|
||||||
quint64 timestamp { 0 };
|
quint64 timestamp { 0 };
|
||||||
|
bool valid { false };
|
||||||
|
|
||||||
AxisValue() {}
|
AxisValue() {}
|
||||||
AxisValue(const float value, const quint64 timestamp);
|
AxisValue(const float value, const quint64 timestamp, bool valid = true);
|
||||||
|
|
||||||
bool operator ==(const AxisValue& right) const;
|
bool operator ==(const AxisValue& right) const;
|
||||||
bool operator !=(const AxisValue& right) const { return !(*this == right); }
|
bool operator !=(const AxisValue& right) const { return !(*this == right); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_controllers_AxisValue_h
|
#endif // hifi_controllers_AxisValue_h
|
||||||
|
|
|
@ -77,13 +77,13 @@ namespace controller {
|
||||||
return { getButton(channel), 0 };
|
return { getButton(channel), 0 };
|
||||||
|
|
||||||
case ChannelType::POSE:
|
case ChannelType::POSE:
|
||||||
return { getPose(channel).valid ? 1.0f : 0.0f, 0 };
|
return { getPose(channel).valid ? 1.0f : 0.0f, 0, getPose(channel).valid };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { 0.0f, 0 };
|
return { 0.0f, 0, false };
|
||||||
}
|
}
|
||||||
|
|
||||||
AxisValue InputDevice::getValue(const Input& input) const {
|
AxisValue InputDevice::getValue(const Input& input) const {
|
||||||
|
|
|
@ -354,6 +354,10 @@ Input::NamedVector StandardController::getAvailableInputs() const {
|
||||||
makePair(HIPS, "Hips"),
|
makePair(HIPS, "Hips"),
|
||||||
makePair(SPINE2, "Spine2"),
|
makePair(SPINE2, "Spine2"),
|
||||||
makePair(HEAD, "Head"),
|
makePair(HEAD, "Head"),
|
||||||
|
makePair(LEFT_EYE, "LeftEye"),
|
||||||
|
makePair(RIGHT_EYE, "RightEye"),
|
||||||
|
makePair(LEFT_EYE_BLINK, "LeftEyeBlink"),
|
||||||
|
makePair(RIGHT_EYE_BLINK, "RightEyeBlink"),
|
||||||
|
|
||||||
// Aliases, PlayStation style names
|
// Aliases, PlayStation style names
|
||||||
makePair(LB, "L1"),
|
makePair(LB, "L1"),
|
||||||
|
|
|
@ -90,6 +90,8 @@ namespace controller {
|
||||||
// Grips
|
// Grips
|
||||||
LEFT_GRIP,
|
LEFT_GRIP,
|
||||||
RIGHT_GRIP,
|
RIGHT_GRIP,
|
||||||
|
LEFT_EYE_BLINK,
|
||||||
|
RIGHT_EYE_BLINK,
|
||||||
NUM_STANDARD_AXES,
|
NUM_STANDARD_AXES,
|
||||||
LZ = LT,
|
LZ = LT,
|
||||||
RZ = RT
|
RZ = RT
|
||||||
|
@ -174,6 +176,8 @@ namespace controller {
|
||||||
TRACKED_OBJECT_13,
|
TRACKED_OBJECT_13,
|
||||||
TRACKED_OBJECT_14,
|
TRACKED_OBJECT_14,
|
||||||
TRACKED_OBJECT_15,
|
TRACKED_OBJECT_15,
|
||||||
|
LEFT_EYE,
|
||||||
|
RIGHT_EYE,
|
||||||
NUM_STANDARD_POSES
|
NUM_STANDARD_POSES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,9 @@ void UserInputMapper::update(float deltaTime) {
|
||||||
for (auto& channel : _actionStates) {
|
for (auto& channel : _actionStates) {
|
||||||
channel = 0.0f;
|
channel = 0.0f;
|
||||||
}
|
}
|
||||||
|
for (unsigned int i = 0; i < _actionStatesValid.size(); i++) {
|
||||||
|
_actionStatesValid[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& channel : _poseStates) {
|
for (auto& channel : _poseStates) {
|
||||||
channel = Pose();
|
channel = Pose();
|
||||||
|
@ -1233,5 +1236,17 @@ void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UserInputMapper::setActionState(Action action, float value, bool valid) {
|
||||||
|
_actionStates[toInt(action)] = value;
|
||||||
|
_actionStatesValid[toInt(action)] = valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserInputMapper::deltaActionState(Action action, float delta, bool valid) {
|
||||||
|
_actionStates[toInt(action)] += delta;
|
||||||
|
bool wasValid = _actionStatesValid[toInt(action)];
|
||||||
|
_actionStatesValid[toInt(action)] = wasValid & valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,13 +82,14 @@ namespace controller {
|
||||||
QString getActionName(Action action) const;
|
QString getActionName(Action action) const;
|
||||||
QString getStandardPoseName(uint16_t pose);
|
QString getStandardPoseName(uint16_t pose);
|
||||||
float getActionState(Action action) const { return _actionStates[toInt(action)]; }
|
float getActionState(Action action) const { return _actionStates[toInt(action)]; }
|
||||||
|
bool getActionStateValid(Action action) const { return _actionStatesValid[toInt(action)]; }
|
||||||
Pose getPoseState(Action action) const;
|
Pose getPoseState(Action action) const;
|
||||||
int findAction(const QString& actionName) const;
|
int findAction(const QString& actionName) const;
|
||||||
QVector<QString> getActionNames() const;
|
QVector<QString> getActionNames() const;
|
||||||
Input inputFromAction(Action action) const { return getActionInputs()[toInt(action)].first; }
|
Input inputFromAction(Action action) const { return getActionInputs()[toInt(action)].first; }
|
||||||
|
|
||||||
void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; }
|
void setActionState(Action action, float value, bool valid = true);
|
||||||
void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; }
|
void deltaActionState(Action action, float delta, bool valid = true);
|
||||||
void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; }
|
void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; }
|
||||||
bool triggerHapticPulse(float strength, float duration, controller::Hand hand);
|
bool triggerHapticPulse(float strength, float duration, controller::Hand hand);
|
||||||
bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand);
|
bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand);
|
||||||
|
@ -146,6 +147,7 @@ namespace controller {
|
||||||
std::vector<float> _actionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
|
std::vector<float> _actionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
|
||||||
std::vector<float> _actionScales = std::vector<float>(toInt(Action::NUM_ACTIONS), 1.0f);
|
std::vector<float> _actionScales = std::vector<float>(toInt(Action::NUM_ACTIONS), 1.0f);
|
||||||
std::vector<float> _lastActionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
|
std::vector<float> _lastActionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
|
||||||
|
std::vector<bool> _actionStatesValid = std::vector<bool>(toInt(Action::NUM_ACTIONS), false);
|
||||||
std::vector<Pose> _poseStates = std::vector<Pose>(toInt(Action::NUM_ACTIONS));
|
std::vector<Pose> _poseStates = std::vector<Pose>(toInt(Action::NUM_ACTIONS));
|
||||||
std::vector<AxisValue> _lastStandardStates = std::vector<AxisValue>();
|
std::vector<AxisValue> _lastStandardStates = std::vector<AxisValue>();
|
||||||
|
|
||||||
|
@ -167,7 +169,7 @@ namespace controller {
|
||||||
ConditionalPointer conditionalFor(const QJSValue& endpoint);
|
ConditionalPointer conditionalFor(const QJSValue& endpoint);
|
||||||
ConditionalPointer conditionalFor(const QScriptValue& endpoint);
|
ConditionalPointer conditionalFor(const QScriptValue& endpoint);
|
||||||
ConditionalPointer conditionalFor(const Input& endpoint) const;
|
ConditionalPointer conditionalFor(const Input& endpoint) const;
|
||||||
|
|
||||||
MappingPointer parseMapping(const QJsonValue& json);
|
MappingPointer parseMapping(const QJsonValue& json);
|
||||||
RoutePointer parseRoute(const QJsonValue& value);
|
RoutePointer parseRoute(const QJsonValue& value);
|
||||||
EndpointPointer parseDestination(const QJsonValue& value);
|
EndpointPointer parseDestination(const QJsonValue& value);
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace controller {
|
||||||
_currentPose = value;
|
_currentPose = value;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
AxisValue _currentValue { 0.0f, 0 };
|
AxisValue _currentValue { 0.0f, 0, false };
|
||||||
Pose _currentPose {};
|
Pose _currentPose {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ void ActionEndpoint::apply(AxisValue newValue, const Pointer& source) {
|
||||||
_currentValue.value += newValue.value;
|
_currentValue.value += newValue.value;
|
||||||
|
|
||||||
if (_input != Input::INVALID_INPUT) {
|
if (_input != Input::INVALID_INPUT) {
|
||||||
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value);
|
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value, newValue.valid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AxisValue _currentValue { 0.0f, 0 };
|
AxisValue _currentValue { 0.0f, 0, false };
|
||||||
Pose _currentPose{};
|
Pose _currentPose{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,9 @@ bool CompositeEndpoint::readable() const {
|
||||||
AxisValue CompositeEndpoint::peek() const {
|
AxisValue CompositeEndpoint::peek() const {
|
||||||
auto negative = first->peek();
|
auto negative = first->peek();
|
||||||
auto positive = second->peek();
|
auto positive = second->peek();
|
||||||
auto result = AxisValue(positive.value - negative.value, std::max(positive.timestamp, negative.timestamp));
|
auto result = AxisValue(positive.value - negative.value,
|
||||||
|
std::max(positive.timestamp, negative.timestamp),
|
||||||
|
negative.valid && positive.valid);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +37,9 @@ AxisValue CompositeEndpoint::peek() const {
|
||||||
AxisValue CompositeEndpoint::value() {
|
AxisValue CompositeEndpoint::value() {
|
||||||
auto negative = first->value();
|
auto negative = first->value();
|
||||||
auto positive = second->value();
|
auto positive = second->value();
|
||||||
auto result = AxisValue(positive.value - negative.value, std::max(positive.timestamp, negative.timestamp));
|
auto result = AxisValue(positive.value - negative.value,
|
||||||
|
std::max(positive.timestamp, negative.timestamp),
|
||||||
|
negative.valid && positive.valid);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ using namespace controller;
|
||||||
|
|
||||||
AxisValue InputEndpoint::peek() const {
|
AxisValue InputEndpoint::peek() const {
|
||||||
if (isPose()) {
|
if (isPose()) {
|
||||||
return peekPose().valid ? AxisValue(1.0f, 0) : AxisValue(0.0f, 0);
|
return peekPose().valid ? AxisValue(1.0f, 0) : AxisValue(0.0f, 0, false);
|
||||||
}
|
}
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
auto deviceProxy = userInputMapper->getDevice(_input);
|
auto deviceProxy = userInputMapper->getDevice(_input);
|
||||||
|
|
|
@ -41,7 +41,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
QScriptValue _callable;
|
QScriptValue _callable;
|
||||||
float _lastValueRead { 0.0f };
|
float _lastValueRead { 0.0f };
|
||||||
AxisValue _lastValueWritten { 0.0f, 0 };
|
AxisValue _lastValueWritten { 0.0f, 0, false };
|
||||||
|
|
||||||
bool _returnPose { false };
|
bool _returnPose { false };
|
||||||
Pose _lastPoseRead;
|
Pose _lastPoseRead;
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ClampFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {};
|
ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {};
|
||||||
virtual AxisValue apply(AxisValue value) const override {
|
virtual AxisValue apply(AxisValue value) const override {
|
||||||
return { glm::clamp(value.value, _min, _max), value.timestamp };
|
return { glm::clamp(value.value, _min, _max), value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
ConstrainToIntegerFilter() = default;
|
ConstrainToIntegerFilter() = default;
|
||||||
|
|
||||||
virtual AxisValue apply(AxisValue value) const override {
|
virtual AxisValue apply(AxisValue value) const override {
|
||||||
return { glm::sign(value.value), value.timestamp };
|
return { glm::sign(value.value), value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
ConstrainToPositiveIntegerFilter() = default;
|
ConstrainToPositiveIntegerFilter() = default;
|
||||||
|
|
||||||
virtual AxisValue apply(AxisValue value) const override {
|
virtual AxisValue apply(AxisValue value) const override {
|
||||||
return { (value.value <= 0.0f) ? 0.0f : 1.0f, value.timestamp };
|
return { (value.value <= 0.0f) ? 0.0f : 1.0f, value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
|
@ -18,7 +18,7 @@ AxisValue DeadZoneFilter::apply(AxisValue value) const {
|
||||||
if (magnitude < _min) {
|
if (magnitude < _min) {
|
||||||
return { 0.0f, value.timestamp };
|
return { 0.0f, value.timestamp };
|
||||||
}
|
}
|
||||||
return { (magnitude - _min) * scale, value.timestamp };
|
return { (magnitude - _min) * scale, value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeadZoneFilter::parseParameters(const QJsonValue& parameters) {
|
bool DeadZoneFilter::parseParameters(const QJsonValue& parameters) {
|
||||||
|
|
|
@ -19,7 +19,6 @@ HysteresisFilter::HysteresisFilter(float min, float max) : _min(min), _max(max)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AxisValue HysteresisFilter::apply(AxisValue value) const {
|
AxisValue HysteresisFilter::apply(AxisValue value) const {
|
||||||
if (_signaled) {
|
if (_signaled) {
|
||||||
if (value.value <= _min) {
|
if (value.value <= _min) {
|
||||||
|
@ -30,7 +29,7 @@ AxisValue HysteresisFilter::apply(AxisValue value) const {
|
||||||
_signaled = true;
|
_signaled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { _signaled ? 1.0f : 0.0f, value.timestamp };
|
return { _signaled ? 1.0f : 0.0f, value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HysteresisFilter::parseParameters(const QJsonValue& parameters) {
|
bool HysteresisFilter::parseParameters(const QJsonValue& parameters) {
|
||||||
|
|
|
@ -6,5 +6,5 @@ NotFilter::NotFilter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
AxisValue NotFilter::apply(AxisValue value) const {
|
AxisValue NotFilter::apply(AxisValue value) const {
|
||||||
return { (value.value == 0.0f) ? 1.0f : 0.0f, value.timestamp };
|
return { (value.value == 0.0f) ? 1.0f : 0.0f, value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ AxisValue PulseFilter::apply(AxisValue value) const {
|
||||||
_lastEmitTime = DEFAULT_LAST_EMIT_TIME;
|
_lastEmitTime = DEFAULT_LAST_EMIT_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { result, value.timestamp };
|
return { result, value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PulseFilter::parseParameters(const QJsonValue& parameters) {
|
bool PulseFilter::parseParameters(const QJsonValue& parameters) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
ScaleFilter(float scale) : _scale(scale) {}
|
ScaleFilter(float scale) : _scale(scale) {}
|
||||||
|
|
||||||
virtual AxisValue apply(AxisValue value) const override {
|
virtual AxisValue apply(AxisValue value) const override {
|
||||||
return { value.value * _scale, value.timestamp };
|
return { value.value * _scale, value.timestamp, value.valid };
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override {
|
virtual Pose apply(Pose value) const override {
|
||||||
|
|
Loading…
Reference in a new issue