mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-13 22:27:13 +02:00
Moving conditionals and endpoints out of UserInputMapper
Conflicts: libraries/controllers/src/controllers/UserInputMapper.cpp
This commit is contained in:
parent
2c2273df0b
commit
0fdd32709f
37 changed files with 766 additions and 332 deletions
|
@ -24,9 +24,22 @@
|
|||
|
||||
#include "Logging.h"
|
||||
|
||||
#include "Endpoint.h"
|
||||
#include "Route.h"
|
||||
#include "Mapping.h"
|
||||
#include "impl/conditionals/AndConditional.h"
|
||||
#include "impl/conditionals/EndpointConditional.h"
|
||||
#include "impl/conditionals/ScriptConditional.h"
|
||||
|
||||
#include "impl/endpoints/ActionEndpoint.h"
|
||||
#include "impl/endpoints/AnyEndpoint.h"
|
||||
#include "impl/endpoints/ArrayEndpoint.h"
|
||||
#include "impl/endpoints/CompositeEndpoint.h"
|
||||
#include "impl/endpoints/InputEndpoint.h"
|
||||
#include "impl/endpoints/JSEndpoint.h"
|
||||
#include "impl/endpoints/ScriptEndpoint.h"
|
||||
#include "impl/endpoints/StandardEndpoint.h"
|
||||
|
||||
#include "impl/Route.h"
|
||||
#include "impl/Mapping.h"
|
||||
|
||||
|
||||
namespace controller {
|
||||
const uint16_t UserInputMapper::ACTIONS_DEVICE = Input::INVALID_DEVICE - 0xFF;
|
||||
|
@ -42,300 +55,6 @@ controller::UserInputMapper::UserInputMapper() {
|
|||
|
||||
namespace controller {
|
||||
|
||||
class ScriptEndpoint : public Endpoint {
|
||||
Q_OBJECT;
|
||||
public:
|
||||
ScriptEndpoint(const QScriptValue& callable)
|
||||
: Endpoint(Input::INVALID_INPUT), _callable(callable) {
|
||||
}
|
||||
|
||||
virtual float value();
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void updateValue();
|
||||
Q_INVOKABLE virtual void internalApply(float newValue, float oldValue, int sourceID);
|
||||
private:
|
||||
QScriptValue _callable;
|
||||
float _lastValue = 0.0f;
|
||||
};
|
||||
|
||||
class StandardEndpoint : public VirtualEndpoint {
|
||||
public:
|
||||
StandardEndpoint(const Input& input) : VirtualEndpoint(input) {}
|
||||
virtual bool writeable() const override { return !_written; }
|
||||
virtual bool readable() const override { return !_read; }
|
||||
virtual void reset() override {
|
||||
apply(0.0f, 0.0f, Endpoint::Pointer());
|
||||
apply(Pose(), Pose(), Endpoint::Pointer());
|
||||
_written = _read = false;
|
||||
}
|
||||
|
||||
virtual float value() override {
|
||||
_read = true;
|
||||
return VirtualEndpoint::value();
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override {
|
||||
// For standard endpoints, the first NON-ZERO write counts.
|
||||
if (newValue != 0.0) {
|
||||
_written = true;
|
||||
}
|
||||
VirtualEndpoint::apply(newValue, oldValue, source);
|
||||
}
|
||||
|
||||
virtual Pose pose() override {
|
||||
_read = true;
|
||||
return VirtualEndpoint::pose();
|
||||
}
|
||||
|
||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override {
|
||||
if (newValue != Pose()) {
|
||||
_written = true;
|
||||
}
|
||||
VirtualEndpoint::apply(newValue, oldValue, source);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _written { false };
|
||||
bool _read { false };
|
||||
};
|
||||
|
||||
|
||||
class JSEndpoint : public Endpoint {
|
||||
public:
|
||||
JSEndpoint(const QJSValue& callable)
|
||||
: Endpoint(Input::INVALID_INPUT), _callable(callable) {
|
||||
}
|
||||
|
||||
virtual float value() {
|
||||
float result = (float)_callable.call().toNumber();;
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) {
|
||||
_callable.call(QJSValueList({ QJSValue(newValue) }));
|
||||
}
|
||||
|
||||
private:
|
||||
QJSValue _callable;
|
||||
};
|
||||
|
||||
float ScriptEndpoint::value() {
|
||||
updateValue();
|
||||
return _lastValue;
|
||||
}
|
||||
|
||||
void ScriptEndpoint::updateValue() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
_lastValue = (float)_callable.call().toNumber();
|
||||
}
|
||||
|
||||
void ScriptEndpoint::apply(float newValue, float oldValue, const Pointer& source) {
|
||||
internalApply(newValue, oldValue, source->getInput().getID());
|
||||
}
|
||||
|
||||
void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection,
|
||||
Q_ARG(float, newValue),
|
||||
Q_ARG(float, oldValue),
|
||||
Q_ARG(int, sourceID));
|
||||
return;
|
||||
}
|
||||
_callable.call(QScriptValue(),
|
||||
QScriptValueList({ QScriptValue(newValue), QScriptValue(oldValue), QScriptValue(sourceID) }));
|
||||
}
|
||||
|
||||
static const Input INVALID_STANDARD_INPUT = Input(UserInputMapper::STANDARD_DEVICE, Input::INVALID_CHANNEL, ChannelType::INVALID);
|
||||
|
||||
class CompositeEndpoint : public Endpoint, Endpoint::Pair {
|
||||
public:
|
||||
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second)
|
||||
: Endpoint(Input::INVALID_INPUT), Pair(first, second) {
|
||||
if (first->getInput().device == UserInputMapper::STANDARD_DEVICE &&
|
||||
second->getInput().device == UserInputMapper::STANDARD_DEVICE) {
|
||||
this->_input = INVALID_STANDARD_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
virtual float value() {
|
||||
float result = first->value() * -1.0f + second->value();
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) {
|
||||
// Composites are read only
|
||||
}
|
||||
};
|
||||
|
||||
class ArrayEndpoint : public Endpoint {
|
||||
friend class UserInputMapper;
|
||||
public:
|
||||
using Pointer = std::shared_ptr<ArrayEndpoint>;
|
||||
ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { }
|
||||
|
||||
virtual float value() override {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override {
|
||||
for (auto& child : _children) {
|
||||
if (child->writeable()) {
|
||||
child->apply(newValue, oldValue, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool readable() const override { return false; }
|
||||
|
||||
private:
|
||||
Endpoint::List _children;
|
||||
};
|
||||
|
||||
class AnyEndpoint : public Endpoint {
|
||||
friend class UserInputMapper;
|
||||
public:
|
||||
using Pointer = std::shared_ptr<AnyEndpoint>;
|
||||
AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPUT), _children(children) {
|
||||
bool standard = true;
|
||||
// Ensure if we're building a composite of standard devices the composite itself
|
||||
// is treated as a standard device for rule processing order
|
||||
for (auto endpoint : children) {
|
||||
if (endpoint->getInput().device != UserInputMapper::STANDARD_DEVICE) {
|
||||
standard = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (standard) {
|
||||
this->_input = INVALID_STANDARD_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
virtual float value() override {
|
||||
float result = 0.0f;
|
||||
for (auto& child : _children) {
|
||||
float childResult = child->value();
|
||||
if (childResult != 0.0f && result == 0.0f) {
|
||||
result = childResult;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override {
|
||||
qFatal("AnyEndpoint is read only");
|
||||
}
|
||||
|
||||
// AnyEndpoint is used for reading, so return false if any child returns false (has been written to)
|
||||
virtual bool writeable() const override {
|
||||
for (auto& child : _children) {
|
||||
if (!child->writeable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool readable() const override {
|
||||
for (auto& child : _children) {
|
||||
if (!child->readable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Endpoint::List _children;
|
||||
};
|
||||
|
||||
class InputEndpoint : public Endpoint {
|
||||
public:
|
||||
InputEndpoint(const Input& id = Input::INVALID_INPUT)
|
||||
: Endpoint(id) {
|
||||
}
|
||||
|
||||
virtual float value() override {
|
||||
_read = true;
|
||||
if (isPose()) {
|
||||
return pose().valid ? 1.0f : 0.0f;
|
||||
}
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
auto deviceProxy = userInputMapper->getDeviceProxy(_input);
|
||||
if (!deviceProxy) {
|
||||
return 0.0f;
|
||||
}
|
||||
return deviceProxy->getValue(_input, 0);
|
||||
}
|
||||
|
||||
// FIXME need support for writing back to vibration / force feedback effects
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override {}
|
||||
|
||||
virtual Pose pose() override {
|
||||
_read = true;
|
||||
if (!isPose()) {
|
||||
return Pose();
|
||||
}
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
auto deviceProxy = userInputMapper->getDeviceProxy(_input);
|
||||
if (!deviceProxy) {
|
||||
return Pose();
|
||||
}
|
||||
return deviceProxy->getPose(_input, 0);
|
||||
}
|
||||
|
||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { }
|
||||
|
||||
virtual bool writeable() const { return false; }
|
||||
virtual bool readable() const { return !_read; }
|
||||
virtual void reset() { _read = false; }
|
||||
|
||||
private:
|
||||
bool _read { false };
|
||||
};
|
||||
|
||||
class ActionEndpoint : public Endpoint {
|
||||
public:
|
||||
ActionEndpoint(const Input& id = Input::INVALID_INPUT)
|
||||
: Endpoint(id) {
|
||||
}
|
||||
|
||||
virtual float value() override { return _currentValue; }
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override {
|
||||
_currentValue += newValue;
|
||||
if (_input != Input::INVALID_INPUT) {
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Pose pose() override { return _currentPose; }
|
||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override {
|
||||
_currentPose = newValue;
|
||||
if (!_currentPose.isValid()) {
|
||||
return;
|
||||
}
|
||||
if (_input != Input::INVALID_INPUT) {
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->setActionState(Action(_input.getChannel()), _currentPose);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void reset() override {
|
||||
_currentValue = 0.0f;
|
||||
_currentPose = Pose();
|
||||
}
|
||||
|
||||
private:
|
||||
float _currentValue{ 0.0f };
|
||||
Pose _currentPose{};
|
||||
};
|
||||
|
||||
UserInputMapper::~UserInputMapper() {
|
||||
}
|
||||
|
||||
|
@ -1019,33 +738,6 @@ Endpoint::Pointer UserInputMapper::parseEndpoint(const QJsonValue& value) {
|
|||
return result;
|
||||
}
|
||||
|
||||
class AndConditional : public Conditional {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<AndConditional>;
|
||||
|
||||
AndConditional(Conditional::List children) : _children(children) { }
|
||||
|
||||
virtual bool satisfied() override {
|
||||
for (auto& conditional : _children) {
|
||||
if (!conditional->satisfied()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Conditional::List _children;
|
||||
};
|
||||
|
||||
class EndpointConditional : public Conditional {
|
||||
public:
|
||||
EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {}
|
||||
virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0; }
|
||||
private:
|
||||
Endpoint::Pointer _endpoint;
|
||||
};
|
||||
|
||||
Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) {
|
||||
if (value.isArray()) {
|
||||
// Support "when" : [ "GamePad.RB", "GamePad.LB" ]
|
||||
|
@ -1290,4 +982,3 @@ void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
|
|||
|
||||
}
|
||||
|
||||
#include "UserInputMapper.moc"
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "Input.h"
|
||||
#include "Pose.h"
|
||||
#include "../Input.h"
|
||||
#include "../Pose.h"
|
||||
|
||||
class QScriptValue;
|
||||
|
|
@ -12,8 +12,8 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "../Mapping.h"
|
||||
#include "../Endpoint.h"
|
||||
#include "Mapping.h"
|
||||
#include "Endpoint.h"
|
||||
|
||||
class QJSValue;
|
||||
class QScriptValue;
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "../Filter.h"
|
||||
#include "../Route.h"
|
||||
#include "../Mapping.h"
|
||||
#include "Filter.h"
|
||||
#include "Route.h"
|
||||
#include "Mapping.h"
|
||||
|
||||
#include "../UserInputMapper.h"
|
||||
|
||||
class QJSValue;
|
||||
class QScriptValue;
|
||||
class QJsonValue;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AndConditional.h"
|
||||
|
||||
using namespace controller;
|
||||
|
||||
bool AndConditional::satisfied() {
|
||||
for (auto& conditional : _children) {
|
||||
if (!conditional->satisfied()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/20
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_AndConditional_h
|
||||
#define hifi_Controllers_AndConditional_h
|
||||
|
||||
#include "../Conditional.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class AndConditional : public Conditional {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<AndConditional>;
|
||||
|
||||
AndConditional(Conditional::List children) : _children(children) { }
|
||||
|
||||
virtual bool satisfied() override;
|
||||
|
||||
private:
|
||||
Conditional::List _children;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EndpointConditional.h"
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/20
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_EndpointConditional_h
|
||||
#define hifi_Controllers_EndpointConditional_h
|
||||
|
||||
#include "../Conditional.h"
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class EndpointConditional : public Conditional {
|
||||
public:
|
||||
EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {}
|
||||
virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0; }
|
||||
private:
|
||||
Endpoint::Pointer _endpoint;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "NotConditional.h"
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/20
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_NotConditional_h
|
||||
#define hifi_Controllers_NotConditional_h
|
||||
|
||||
#include "../Conditional.h"
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptConditional.h"
|
||||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
using namespace controller;
|
||||
|
||||
bool ScriptConditional::satisfied() {
|
||||
updateValue();
|
||||
return _lastValue;
|
||||
}
|
||||
|
||||
void ScriptConditional::updateValue() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
_lastValue = _callable.call().toBool();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/20
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_ScriptConditional_h
|
||||
#define hifi_Controllers_ScriptConditional_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#include "../Conditional.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class ScriptConditional : public QObject, public Conditional {
|
||||
Q_OBJECT;
|
||||
public:
|
||||
ScriptConditional(const QScriptValue& callable) : _callable(callable) { }
|
||||
virtual bool satisfied() override;
|
||||
protected:
|
||||
Q_INVOKABLE void updateValue();
|
||||
private:
|
||||
QScriptValue _callable;
|
||||
bool _lastValue { false };
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ActionEndpoint.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "../../UserInputMapper.h"
|
||||
|
||||
using namespace controller;
|
||||
|
||||
void ActionEndpoint::apply(float newValue, float oldValue, const Pointer& source) {
|
||||
_currentValue += newValue;
|
||||
if (_input != Input::INVALID_INPUT) {
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionEndpoint::apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) {
|
||||
_currentPose = newValue;
|
||||
if (!_currentPose.isValid()) {
|
||||
return;
|
||||
}
|
||||
if (_input != Input::INVALID_INPUT) {
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->setActionState(Action(_input.getChannel()), _currentPose);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionEndpoint::reset() {
|
||||
_currentValue = 0.0f;
|
||||
_currentPose = Pose();
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_ActionEndpoint_h
|
||||
#define hifi_Controllers_ActionEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
#include "../../Actions.h"
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "../../UserInputMapper.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class ActionEndpoint : public Endpoint {
|
||||
public:
|
||||
ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { }
|
||||
|
||||
virtual float value() override { return _currentValue; }
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override;
|
||||
|
||||
virtual Pose pose() override { return _currentPose; }
|
||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override;
|
||||
|
||||
virtual void reset() override;
|
||||
|
||||
private:
|
||||
float _currentValue{ 0.0f };
|
||||
Pose _currentPose{};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AnyEndpoint.h"
|
||||
|
||||
#include "../../UserInputMapper.h"
|
||||
|
||||
using namespace controller;
|
||||
|
||||
AnyEndpoint::AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPUT), _children(children) {
|
||||
bool standard = true;
|
||||
// Ensure if we're building a composite of standard devices the composite itself
|
||||
// is treated as a standard device for rule processing order
|
||||
for (auto endpoint : children) {
|
||||
if (endpoint->getInput().device != UserInputMapper::STANDARD_DEVICE) {
|
||||
standard = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (standard) {
|
||||
this->_input.device = UserInputMapper::STANDARD_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
float AnyEndpoint::value() {
|
||||
float result = 0;
|
||||
for (auto& child : _children) {
|
||||
float childResult = child->value();
|
||||
if (childResult != 0.0f) {
|
||||
result = childResult;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void AnyEndpoint::apply(float newValue, float oldValue, const Endpoint::Pointer& source) {
|
||||
qFatal("AnyEndpoint is read only");
|
||||
}
|
||||
|
||||
// AnyEndpoint is used for reading, so return false if any child returns false (has been written to)
|
||||
bool AnyEndpoint::writeable() const {
|
||||
for (auto& child : _children) {
|
||||
if (!child->writeable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnyEndpoint::readable() const {
|
||||
for (auto& child : _children) {
|
||||
if (!child->readable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_AnyEndpoint_h
|
||||
#define hifi_Controllers_AnyEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class AnyEndpoint : public Endpoint {
|
||||
friend class UserInputMapper;
|
||||
public:
|
||||
AnyEndpoint(Endpoint::List children);
|
||||
virtual float value() override;
|
||||
virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override;
|
||||
virtual bool writeable() const override;
|
||||
virtual bool readable() const override;
|
||||
|
||||
private:
|
||||
Endpoint::List _children;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ArrayEndpoint.h"
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_ArrayEndpoint_h
|
||||
#define hifi_Controllers_ArrayEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class ArrayEndpoint : public Endpoint {
|
||||
friend class UserInputMapper;
|
||||
public:
|
||||
using Pointer = std::shared_ptr<ArrayEndpoint>;
|
||||
ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { }
|
||||
|
||||
virtual float value() override {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override {
|
||||
for (auto& child : _children) {
|
||||
if (child->writeable()) {
|
||||
child->apply(newValue, oldValue, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool readable() const override { return false; }
|
||||
|
||||
private:
|
||||
Endpoint::List _children;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "CompositeEndpoint.h"
|
||||
|
||||
#include "../../UserInputMapper.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
CompositeEndpoint::CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second)
|
||||
: Endpoint(Input::INVALID_INPUT), Pair(first, second) {
|
||||
if (first->getInput().device == UserInputMapper::STANDARD_DEVICE &&
|
||||
second->getInput().device == UserInputMapper::STANDARD_DEVICE) {
|
||||
this->_input.device = UserInputMapper::STANDARD_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
float CompositeEndpoint::value() {
|
||||
float result = first->value() * -1.0f + second->value();
|
||||
return result;
|
||||
}
|
||||
|
||||
void CompositeEndpoint::apply(float newValue, float oldValue, const Pointer& source) {
|
||||
// Composites are read only
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_CompositeEndpoint_h
|
||||
#define hifi_Controllers_CompositeEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
class CompositeEndpoint : public Endpoint, Endpoint::Pair {
|
||||
public:
|
||||
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second);
|
||||
|
||||
virtual float value() override;
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "InputEndpoint.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "../../UserInputMapper.h"
|
||||
|
||||
using namespace controller;
|
||||
float InputEndpoint::value(){
|
||||
_read = true;
|
||||
if (isPose()) {
|
||||
return pose().valid ? 1.0f : 0.0f;
|
||||
}
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
auto deviceProxy = userInputMapper->getDeviceProxy(_input);
|
||||
if (!deviceProxy) {
|
||||
return 0.0f;
|
||||
}
|
||||
return deviceProxy->getValue(_input, 0);
|
||||
}
|
||||
|
||||
Pose InputEndpoint::pose() {
|
||||
_read = true;
|
||||
if (!isPose()) {
|
||||
return Pose();
|
||||
}
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
auto deviceProxy = userInputMapper->getDeviceProxy(_input);
|
||||
if (!deviceProxy) {
|
||||
return Pose();
|
||||
}
|
||||
return deviceProxy->getPose(_input, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_InputEndpoint_h
|
||||
#define hifi_Controllers_InputEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class InputEndpoint : public Endpoint {
|
||||
public:
|
||||
InputEndpoint(const Input& id = Input::INVALID_INPUT)
|
||||
: Endpoint(id) {
|
||||
}
|
||||
|
||||
virtual float value() override;
|
||||
// FIXME need support for writing back to vibration / force feedback effects
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override {}
|
||||
virtual Pose pose() override;
|
||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { }
|
||||
|
||||
virtual bool writeable() const { return false; }
|
||||
virtual bool readable() const { return !_read; }
|
||||
virtual void reset() { _read = false; }
|
||||
|
||||
private:
|
||||
bool _read { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "JSEndpoint.h"
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_JSEndpoint_h
|
||||
#define hifi_Controllers_JSEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
#include <QtQml/QJSValue>
|
||||
#include <QtQml/QJSValueList>
|
||||
|
||||
namespace controller {
|
||||
|
||||
class JSEndpoint : public Endpoint {
|
||||
public:
|
||||
JSEndpoint(const QJSValue& callable)
|
||||
: Endpoint(Input::INVALID_INPUT), _callable(callable) {
|
||||
}
|
||||
|
||||
virtual float value() {
|
||||
float result = (float)_callable.call().toNumber();
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) {
|
||||
_callable.call(QJSValueList({ QJSValue(newValue) }));
|
||||
}
|
||||
|
||||
private:
|
||||
QJSValue _callable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptEndpoint.h"
|
||||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
using namespace controller;
|
||||
|
||||
float ScriptEndpoint::value() {
|
||||
updateValue();
|
||||
return _lastValue;
|
||||
}
|
||||
|
||||
void ScriptEndpoint::updateValue() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
_lastValue = (float)_callable.call().toNumber();
|
||||
}
|
||||
|
||||
void ScriptEndpoint::apply(float newValue, float oldValue, const Pointer& source) {
|
||||
internalApply(newValue, oldValue, source->getInput().getID());
|
||||
}
|
||||
|
||||
void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection,
|
||||
Q_ARG(float, newValue),
|
||||
Q_ARG(float, oldValue),
|
||||
Q_ARG(int, sourceID));
|
||||
return;
|
||||
}
|
||||
_callable.call(QScriptValue(),
|
||||
QScriptValueList({ QScriptValue(newValue), QScriptValue(oldValue), QScriptValue(sourceID) }));
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_ScriptEndpoint_h
|
||||
#define hifi_Controllers_ScriptEndpoint_h
|
||||
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class ScriptEndpoint : public Endpoint {
|
||||
Q_OBJECT;
|
||||
public:
|
||||
ScriptEndpoint(const QScriptValue& callable)
|
||||
: Endpoint(Input::INVALID_INPUT), _callable(callable) {
|
||||
}
|
||||
|
||||
virtual float value();
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void updateValue();
|
||||
Q_INVOKABLE virtual void internalApply(float newValue, float oldValue, int sourceID);
|
||||
private:
|
||||
QScriptValue _callable;
|
||||
float _lastValue = 0.0f;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "StandardEndpoint.h"
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/23
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Controllers_StandardEndpoint_h
|
||||
#define hifi_Controllers_StandardEndpoint_h
|
||||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class StandardEndpoint : public VirtualEndpoint {
|
||||
public:
|
||||
StandardEndpoint(const Input& input) : VirtualEndpoint(input) {}
|
||||
virtual bool writeable() const override { return !_written; }
|
||||
virtual bool readable() const override { return !_read; }
|
||||
virtual void reset() override {
|
||||
apply(0.0f, 0.0f, Endpoint::Pointer());
|
||||
apply(Pose(), Pose(), Endpoint::Pointer());
|
||||
_written = _read = false;
|
||||
}
|
||||
|
||||
virtual float value() override {
|
||||
_read = true;
|
||||
return VirtualEndpoint::value();
|
||||
}
|
||||
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) override {
|
||||
// For standard endpoints, the first NON-ZERO write counts.
|
||||
if (newValue != 0.0) {
|
||||
_written = true;
|
||||
}
|
||||
VirtualEndpoint::apply(newValue, oldValue, source);
|
||||
}
|
||||
|
||||
virtual Pose pose() override {
|
||||
_read = true;
|
||||
return VirtualEndpoint::pose();
|
||||
}
|
||||
|
||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override {
|
||||
if (newValue != Pose()) {
|
||||
_written = true;
|
||||
}
|
||||
VirtualEndpoint::apply(newValue, oldValue, source);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _written { false };
|
||||
bool _read { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue