mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +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 {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace controller {
|
|||
_currentPose = value;
|
||||
}
|
||||
protected:
|
||||
AxisValue _currentValue { 0.0f, 0 };
|
||||
AxisValue _currentValue { 0.0f, 0, false };
|
||||
Pose _currentPose {};
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
virtual void reset() override;
|
||||
|
||||
private:
|
||||
AxisValue _currentValue { 0.0f, 0 };
|
||||
AxisValue _currentValue { 0.0f, 0, false };
|
||||
Pose _currentPose{};
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue