AxisValue action channels now have a 'valid' flag, like Poses do

This commit is contained in:
Seth Alves 2019-09-07 18:05:38 -07:00
parent 73e6be9c37
commit 954aeb5e25
21 changed files with 57 additions and 26 deletions

View file

@ -12,10 +12,13 @@
namespace controller {
AxisValue::AxisValue(const float value, const quint64 timestamp) :
value(value), timestamp(timestamp) { }
AxisValue::AxisValue(const float value, const quint64 timestamp, bool valid) :
value(value), timestamp(timestamp), valid(valid) {
}
bool AxisValue::operator==(const AxisValue& right) const {
return value == right.value && timestamp == right.timestamp;
return value == right.value &&
timestamp == right.timestamp &&
valid == right.valid;
}
}

View file

@ -21,14 +21,14 @@ namespace controller {
float value { 0.0f };
// The value can be timestamped to determine if consecutive identical values should be output (e.g., mouse movement).
quint64 timestamp { 0 };
bool valid { false };
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 { return !(*this == right); }
};
}
#endif // hifi_controllers_AxisValue_h

View file

@ -77,13 +77,13 @@ namespace controller {
return { getButton(channel), 0 };
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:
break;
}
return { 0.0f, 0 };
return { 0.0f, 0, false };
}
AxisValue InputDevice::getValue(const Input& input) const {

View file

@ -354,6 +354,10 @@ Input::NamedVector StandardController::getAvailableInputs() const {
makePair(HIPS, "Hips"),
makePair(SPINE2, "Spine2"),
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
makePair(LB, "L1"),

View file

@ -90,6 +90,8 @@ namespace controller {
// Grips
LEFT_GRIP,
RIGHT_GRIP,
LEFT_EYE_BLINK,
RIGHT_EYE_BLINK,
NUM_STANDARD_AXES,
LZ = LT,
RZ = RT
@ -174,6 +176,8 @@ namespace controller {
TRACKED_OBJECT_13,
TRACKED_OBJECT_14,
TRACKED_OBJECT_15,
LEFT_EYE,
RIGHT_EYE,
NUM_STANDARD_POSES
};

View file

@ -256,6 +256,9 @@ void UserInputMapper::update(float deltaTime) {
for (auto& channel : _actionStates) {
channel = 0.0f;
}
for (unsigned int i = 0; i < _actionStatesValid.size(); i++) {
_actionStatesValid[i] = true;
}
for (auto& channel : _poseStates) {
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;
}
}

View file

@ -82,13 +82,14 @@ namespace controller {
QString getActionName(Action action) const;
QString getStandardPoseName(uint16_t pose);
float getActionState(Action action) const { return _actionStates[toInt(action)]; }
bool getActionStateValid(Action action) const { return _actionStatesValid[toInt(action)]; }
Pose getPoseState(Action action) const;
int findAction(const QString& actionName) const;
QVector<QString> getActionNames() const;
Input inputFromAction(Action action) const { return getActionInputs()[toInt(action)].first; }
void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; }
void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; }
void setActionState(Action action, float value, bool valid = true);
void deltaActionState(Action action, float delta, bool valid = true);
void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; }
bool triggerHapticPulse(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> _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<bool> _actionStatesValid = std::vector<bool>(toInt(Action::NUM_ACTIONS), false);
std::vector<Pose> _poseStates = std::vector<Pose>(toInt(Action::NUM_ACTIONS));
std::vector<AxisValue> _lastStandardStates = std::vector<AxisValue>();
@ -167,7 +169,7 @@ namespace controller {
ConditionalPointer conditionalFor(const QJSValue& endpoint);
ConditionalPointer conditionalFor(const QScriptValue& endpoint);
ConditionalPointer conditionalFor(const Input& endpoint) const;
MappingPointer parseMapping(const QJsonValue& json);
RoutePointer parseRoute(const QJsonValue& value);
EndpointPointer parseDestination(const QJsonValue& value);

View file

@ -100,7 +100,7 @@ namespace controller {
_currentPose = value;
}
protected:
AxisValue _currentValue { 0.0f, 0 };
AxisValue _currentValue { 0.0f, 0, false };
Pose _currentPose {};
};

View file

@ -26,7 +26,7 @@ void ActionEndpoint::apply(AxisValue newValue, const Pointer& source) {
_currentValue.value += newValue.value;
if (_input != Input::INVALID_INPUT) {
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value);
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value, newValue.valid);
}
}

View file

@ -32,7 +32,7 @@ public:
virtual void reset() override;
private:
AxisValue _currentValue { 0.0f, 0 };
AxisValue _currentValue { 0.0f, 0, false };
Pose _currentPose{};
};

View file

@ -27,7 +27,9 @@ bool CompositeEndpoint::readable() const {
AxisValue CompositeEndpoint::peek() const {
auto negative = first->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;
}
@ -35,7 +37,9 @@ AxisValue CompositeEndpoint::peek() const {
AxisValue CompositeEndpoint::value() {
auto negative = first->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;
}

View file

@ -16,7 +16,7 @@ using namespace controller;
AxisValue InputEndpoint::peek() const {
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 deviceProxy = userInputMapper->getDevice(_input);

View file

@ -41,7 +41,7 @@ protected:
private:
QScriptValue _callable;
float _lastValueRead { 0.0f };
AxisValue _lastValueWritten { 0.0f, 0 };
AxisValue _lastValueWritten { 0.0f, 0, false };
bool _returnPose { false };
Pose _lastPoseRead;

View file

@ -19,7 +19,7 @@ class ClampFilter : public Filter {
public:
ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {};
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; }

View file

@ -20,7 +20,7 @@ public:
ConstrainToIntegerFilter() = default;
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; }

View file

@ -20,7 +20,7 @@ public:
ConstrainToPositiveIntegerFilter() = default;
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; }

View file

@ -18,7 +18,7 @@ AxisValue DeadZoneFilter::apply(AxisValue value) const {
if (magnitude < _min) {
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) {

View file

@ -19,7 +19,6 @@ HysteresisFilter::HysteresisFilter(float min, float max) : _min(min), _max(max)
}
};
AxisValue HysteresisFilter::apply(AxisValue value) const {
if (_signaled) {
if (value.value <= _min) {
@ -30,7 +29,7 @@ AxisValue HysteresisFilter::apply(AxisValue value) const {
_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) {

View file

@ -6,5 +6,5 @@ NotFilter::NotFilter() {
}
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 };
}

View file

@ -29,7 +29,7 @@ AxisValue PulseFilter::apply(AxisValue value) const {
_lastEmitTime = DEFAULT_LAST_EMIT_TIME;
}
return { result, value.timestamp };
return { result, value.timestamp, value.valid };
}
bool PulseFilter::parseParameters(const QJsonValue& parameters) {

View file

@ -23,7 +23,7 @@ public:
ScaleFilter(float scale) : _scale(scale) {}
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 {