mirror of
https://github.com/lubosz/overte.git
synced 2025-04-29 19:03:10 +02:00
Taking a different tack on proper ordering of routes
This commit is contained in:
parent
4110324b35
commit
54c20a8dd7
3 changed files with 60 additions and 42 deletions
|
@ -36,7 +36,6 @@ namespace controller {
|
||||||
using WriteLambda = std::function<void(float)>;
|
using WriteLambda = std::function<void(float)>;
|
||||||
|
|
||||||
Endpoint(const Input& input) : _input(input) {}
|
Endpoint(const Input& input) : _input(input) {}
|
||||||
virtual uint8_t priority() const { return 0x7f; }
|
|
||||||
virtual float value() = 0;
|
virtual float value() = 0;
|
||||||
virtual void apply(float newValue, float oldValue, const Pointer& source) = 0;
|
virtual void apply(float newValue, float oldValue, const Pointer& source) = 0;
|
||||||
virtual Pose pose() { return Pose(); }
|
virtual Pose pose() { return Pose(); }
|
||||||
|
|
|
@ -216,9 +216,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process later than normal
|
|
||||||
virtual uint8_t priority() const override { return 0x6F; }
|
|
||||||
|
|
||||||
virtual float value() override {
|
virtual float value() override {
|
||||||
float result = 0;
|
float result = 0;
|
||||||
for (auto& child : _children) {
|
for (auto& child : _children) {
|
||||||
|
@ -234,7 +231,15 @@ public:
|
||||||
qFatal("AnyEndpoint is read only");
|
qFatal("AnyEndpoint is read only");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool writeable() const override { return false; }
|
// 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 {
|
virtual bool readable() const override {
|
||||||
for (auto& child : _children) {
|
for (auto& child : _children) {
|
||||||
|
@ -286,13 +291,11 @@ public:
|
||||||
|
|
||||||
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { }
|
virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { }
|
||||||
|
|
||||||
virtual bool writeable() const { return !_written; }
|
virtual bool writeable() const { return false; }
|
||||||
virtual bool readable() const { return !_read; }
|
virtual bool readable() const { return !_read; }
|
||||||
virtual void reset() { _written = _read = false; }
|
virtual void reset() { _read = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _written { false };
|
|
||||||
bool _read { false };
|
bool _read { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -695,7 +698,6 @@ void UserInputMapper::runMappings() {
|
||||||
if (debugRoutes) {
|
if (debugRoutes) {
|
||||||
qCDebug(controllers) << "Beginning mapping frame";
|
qCDebug(controllers) << "Beginning mapping frame";
|
||||||
}
|
}
|
||||||
static auto deviceNames = getDeviceNames();
|
|
||||||
for (auto endpointEntry : this->_endpointsByInput) {
|
for (auto endpointEntry : this->_endpointsByInput) {
|
||||||
endpointEntry.second->reset();
|
endpointEntry.second->reset();
|
||||||
}
|
}
|
||||||
|
@ -704,22 +706,12 @@ void UserInputMapper::runMappings() {
|
||||||
qCDebug(controllers) << "Processing device routes";
|
qCDebug(controllers) << "Processing device routes";
|
||||||
}
|
}
|
||||||
// Now process the current values for each level of the stack
|
// Now process the current values for each level of the stack
|
||||||
for (const auto& route : _deviceRoutes) {
|
applyRoutes(_deviceRoutes);
|
||||||
if (!route) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
applyRoute(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugRoutes) {
|
if (debugRoutes) {
|
||||||
qCDebug(controllers) << "Processing standard routes";
|
qCDebug(controllers) << "Processing standard routes";
|
||||||
}
|
}
|
||||||
for (const auto& route : _standardRoutes) {
|
applyRoutes(_standardRoutes);
|
||||||
if (!route) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
applyRoute(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugRoutes) {
|
if (debugRoutes) {
|
||||||
qCDebug(controllers) << "Done with mappings";
|
qCDebug(controllers) << "Done with mappings";
|
||||||
|
@ -727,21 +719,53 @@ void UserInputMapper::runMappings() {
|
||||||
debugRoutes = false;
|
debugRoutes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInputMapper::applyRoute(const Route::Pointer& route) {
|
// Encapsulate the logic that routes should not be read before they are written
|
||||||
|
void UserInputMapper::applyRoutes(const Route::List& routes) {
|
||||||
|
Route::List deferredRoutes;
|
||||||
|
|
||||||
|
for (const auto& route : routes) {
|
||||||
|
if (!route) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try all the deferred routes
|
||||||
|
deferredRoutes.remove_if([](Route::Pointer route) {
|
||||||
|
return UserInputMapper::applyRoute(route);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!applyRoute(route)) {
|
||||||
|
deferredRoutes.push_back(route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool force = true;
|
||||||
|
for (const auto& route : deferredRoutes) {
|
||||||
|
UserInputMapper::applyRoute(route, force);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) {
|
||||||
if (debugRoutes && route->debug) {
|
if (debugRoutes && route->debug) {
|
||||||
qCDebug(controllers) << "Applying route " << route->json;
|
qCDebug(controllers) << "Applying route " << route->json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the source hasn't been written yet, defer processing of this route
|
||||||
|
auto source = route->source;
|
||||||
|
if (!force && source->writeable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (route->conditional) {
|
if (route->conditional) {
|
||||||
|
// FIXME for endpoint conditionals we need to check if they've been written
|
||||||
if (!route->conditional->satisfied()) {
|
if (!route->conditional->satisfied()) {
|
||||||
if (debugRoutes && route->debug) {
|
if (debugRoutes && route->debug) {
|
||||||
qCDebug(controllers) << "Conditional failed";
|
qCDebug(controllers) << "Conditional failed";
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto source = route->source;
|
|
||||||
|
|
||||||
// Most endpoints can only be read once (though a given mapping can route them to
|
// Most endpoints can only be read once (though a given mapping can route them to
|
||||||
// multiple places). Consider... If the default is to wire the A button to JUMP
|
// multiple places). Consider... If the default is to wire the A button to JUMP
|
||||||
|
@ -752,7 +776,7 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) {
|
||||||
if (debugRoutes && route->debug) {
|
if (debugRoutes && route->debug) {
|
||||||
qCDebug(controllers) << "Source unreadable";
|
qCDebug(controllers) << "Source unreadable";
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto destination = route->destination;
|
auto destination = route->destination;
|
||||||
|
@ -762,14 +786,14 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) {
|
||||||
if (debugRoutes && route->debug) {
|
if (debugRoutes && route->debug) {
|
||||||
qCDebug(controllers) << "Bad Destination";
|
qCDebug(controllers) << "Bad Destination";
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!destination->writeable()) {
|
if (!destination->writeable()) {
|
||||||
if (debugRoutes && route->debug) {
|
if (debugRoutes && route->debug) {
|
||||||
qCDebug(controllers) << "Destination unwritable";
|
qCDebug(controllers) << "Destination unwritable";
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the value, may have been overriden by previous loopback routes
|
// Fetch the value, may have been overriden by previous loopback routes
|
||||||
|
@ -805,6 +829,7 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) {
|
||||||
|
|
||||||
destination->apply(value, 0, source);
|
destination->apply(value, 0, source);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint::Pointer UserInputMapper::endpointFor(const QJSValue& endpoint) {
|
Endpoint::Pointer UserInputMapper::endpointFor(const QJSValue& endpoint) {
|
||||||
|
@ -910,12 +935,12 @@ void UserInputMapper::enableMapping(const QString& mappingName, bool enable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float UserInputMapper::getValue(const Endpoint::Pointer& endpoint) const {
|
float UserInputMapper::getValue(const Endpoint::Pointer& endpoint) {
|
||||||
Locker locker(_lock);
|
|
||||||
return endpoint->value();
|
return endpoint->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
float UserInputMapper::getValue(const Input& input) const {
|
float UserInputMapper::getValue(const Input& input) const {
|
||||||
|
Locker locker(_lock);
|
||||||
auto endpoint = endpointFor(input);
|
auto endpoint = endpointFor(input);
|
||||||
if (!endpoint) {
|
if (!endpoint) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -923,7 +948,7 @@ float UserInputMapper::getValue(const Input& input) const {
|
||||||
return endpoint->value();
|
return endpoint->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint) const {
|
Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint) {
|
||||||
if (!endpoint->isPose()) {
|
if (!endpoint->isPose()) {
|
||||||
return Pose();
|
return Pose();
|
||||||
}
|
}
|
||||||
|
@ -931,6 +956,7 @@ Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Pose UserInputMapper::getPose(const Input& input) const {
|
Pose UserInputMapper::getPose(const Input& input) const {
|
||||||
|
Locker locker(_lock);
|
||||||
auto endpoint = endpointFor(input);
|
auto endpoint = endpointFor(input);
|
||||||
if (!endpoint) {
|
if (!endpoint) {
|
||||||
return Pose();
|
return Pose();
|
||||||
|
@ -1207,12 +1233,6 @@ bool hasDebuggableRoute(const T& routes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sortRoutes(Route::List& routes) {
|
|
||||||
std::stable_sort(routes.begin(), routes.end(), [](const Route::Pointer a, const Route::Pointer b) {
|
|
||||||
return a->source->priority() < b->source->priority();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
|
@ -1225,14 +1245,12 @@ void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
||||||
return (value->source->getInput().device != STANDARD_DEVICE);
|
return (value->source->getInput().device != STANDARD_DEVICE);
|
||||||
});
|
});
|
||||||
_standardRoutes.insert(_standardRoutes.begin(), standardRoutes.begin(), standardRoutes.end());
|
_standardRoutes.insert(_standardRoutes.begin(), standardRoutes.begin(), standardRoutes.end());
|
||||||
sortRoutes(_standardRoutes);
|
|
||||||
|
|
||||||
Route::List deviceRoutes = mapping->routes;
|
Route::List deviceRoutes = mapping->routes;
|
||||||
deviceRoutes.remove_if([](const Route::Pointer& value) {
|
deviceRoutes.remove_if([](const Route::Pointer& value) {
|
||||||
return (value->source->getInput().device == STANDARD_DEVICE);
|
return (value->source->getInput().device == STANDARD_DEVICE);
|
||||||
});
|
});
|
||||||
_deviceRoutes.insert(_deviceRoutes.begin(), deviceRoutes.begin(), deviceRoutes.end());
|
_deviceRoutes.insert(_deviceRoutes.begin(), deviceRoutes.begin(), deviceRoutes.end());
|
||||||
sortRoutes(_standardRoutes);
|
|
||||||
|
|
||||||
if (!debuggableRoutes) {
|
if (!debuggableRoutes) {
|
||||||
debuggableRoutes = hasDebuggableRoute(_deviceRoutes) || hasDebuggableRoute(_standardRoutes);
|
debuggableRoutes = hasDebuggableRoute(_deviceRoutes) || hasDebuggableRoute(_standardRoutes);
|
||||||
|
|
|
@ -136,14 +136,15 @@ namespace controller {
|
||||||
int recordDeviceOfType(const QString& deviceName);
|
int recordDeviceOfType(const QString& deviceName);
|
||||||
QHash<const QString&, int> _deviceCounts;
|
QHash<const QString&, int> _deviceCounts;
|
||||||
|
|
||||||
float getValue(const EndpointPointer& endpoint) const;
|
static float getValue(const EndpointPointer& endpoint);
|
||||||
Pose getPose(const EndpointPointer& endpoint) const;
|
static Pose getPose(const EndpointPointer& endpoint);
|
||||||
|
|
||||||
friend class RouteBuilderProxy;
|
friend class RouteBuilderProxy;
|
||||||
friend class MappingBuilderProxy;
|
friend class MappingBuilderProxy;
|
||||||
|
|
||||||
void runMappings();
|
void runMappings();
|
||||||
void applyRoute(const RoutePointer& route);
|
static void applyRoutes(const RouteList& route);
|
||||||
|
static bool applyRoute(const RoutePointer& route, bool force = false);
|
||||||
void enableMapping(const MappingPointer& mapping);
|
void enableMapping(const MappingPointer& mapping);
|
||||||
void disableMapping(const MappingPointer& mapping);
|
void disableMapping(const MappingPointer& mapping);
|
||||||
EndpointPointer endpointFor(const QJSValue& endpoint);
|
EndpointPointer endpointFor(const QJSValue& endpoint);
|
||||||
|
|
Loading…
Reference in a new issue