From c3775623aa6bd5084fee7e0fc86a68c04192d4b1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 9 Oct 2015 17:23:52 -0700 Subject: [PATCH] Splitting files, adding test skeleton --- .../src/controllers/ControllerMapping.cpp | 190 ------------------ .../src/controllers/ControllerMapping.h | 149 -------------- .../controllers/src/controllers/Endpoint.cpp | 59 ++++-- .../controllers/src/controllers/Filter.cpp | 41 ++++ .../controllers/src/controllers/Filter.h | 29 +++ .../controllers/src/controllers/Mapping.cpp | 9 + .../controllers/src/controllers/Mapping.h | 87 ++++++++ libraries/controllers/src/controllers/Route.h | 32 +++ tests/controllers/CMakeLists.txt | 13 ++ tests/controllers/src/main.cpp | 38 ++++ 10 files changed, 295 insertions(+), 352 deletions(-) delete mode 100644 libraries/controllers/src/controllers/ControllerMapping.cpp delete mode 100644 libraries/controllers/src/controllers/ControllerMapping.h create mode 100644 libraries/controllers/src/controllers/Filter.cpp create mode 100644 libraries/controllers/src/controllers/Filter.h create mode 100644 libraries/controllers/src/controllers/Mapping.cpp create mode 100644 libraries/controllers/src/controllers/Mapping.h create mode 100644 libraries/controllers/src/controllers/Route.h create mode 100644 tests/controllers/CMakeLists.txt create mode 100644 tests/controllers/src/main.cpp diff --git a/libraries/controllers/src/controllers/ControllerMapping.cpp b/libraries/controllers/src/controllers/ControllerMapping.cpp deleted file mode 100644 index 59f8789d31..0000000000 --- a/libraries/controllers/src/controllers/ControllerMapping.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include - -#include -#include - -extern float currentTime(); - -namespace Controllers { - - /* - * Encapsulates a particular input / output, - * i.e. Hydra.Button0, Standard.X, Action.Yaw - */ - class Endpoint { - public: - virtual float value() = 0; - virtual void apply(float newValue, float oldValue, const Endpoint& source) = 0; - }; - - using EndpointList = std::list; - - const EndpointList& getHardwareEndpoints(); - - // Ex: xbox.RY, xbox.A .... - class HardwareEndpoint : public Endpoint { - public: - virtual float value() override { - // ... - } - - virtual void apply(float newValue, float oldValue, const Endpoint& source) override { - // Default does nothing, but in theory this could be something like vibration - // mapping.from(xbox.X).to(xbox.Vibrate) - } - }; - - class VirtualEndpoint : public Endpoint { - public: - virtual void apply(float newValue) { - if (newValue != _lastValue) { - _lastValue = newValue; - } - } - - virtual float value() { - return _lastValue; - } - - float _lastValue; - }; - - /* - * A function which provides input - */ - class FunctionEndpoint : public Endpoint { - public: - - virtual float value() override { - float now = currentTime(); - float delta = now - _lastCalled; - float result = _inputFunction.call(_object, QScriptValue(delta)).toNumber(); - _lastCalled = now; - return result; - } - - virtual void apply(float newValue, float oldValue, const Endpoint& source) override { - if (newValue != oldValue) { - //_outputFunction.call(newValue, oldValue, source); - } - } - - float _lastValue{ NAN }; - float _lastCalled{ 0 }; - QScriptValue _outputFunction; - QScriptValue _inputFunction; - QScriptValue _object; - }; - - - // Encapsulates part of a filter chain - class Filter { - public: - virtual float apply(float newValue, float oldValue) = 0; - }; - - class ScaleFilter : public Filter { - public: - virtual float apply(float newValue, float oldValue) { - return newValue * _scale; - } - - float _scale{ 1.0 }; - }; - - class PulseFilter : public Filter { - public: - virtual float apply(float newValue, float oldValue) { - // ??? - } - - float _lastEmitValue{ 0 }; - float _lastEmitTime{ 0 }; - float _interval{ -1.0f }; - }; - - using FilterList = std::list; - - /* - * encapsulates a source, destination and filters to apply - */ - class Route { - public: - Endpoint* _source; - Endpoint* _destination; - FilterList _filters; - }; - - using ValueMap = std::map; - - class Mapping { - public: - // List of routes - using List = std::list; - // Map of source channels to route lists - using Map = std::map; - - Map _channelMappings; - ValueMap _lastValues; - }; - - class MappingsStack { - std::list _stack; - ValueMap _lastValues; - - void update() { - EndpointList hardwareInputs = getHardwareEndpoints(); - ValueMap currentValues; - - for (auto input : hardwareInputs) { - currentValues[input] = input->value(); - } - - // Now process the current values for each level of the stack - for (auto& mapping : _stack) { - update(mapping, currentValues); - } - - _lastValues = currentValues; - } - - void update(Mapping& mapping, ValueMap& values) { - ValueMap updates; - EndpointList consumedEndpoints; - for (const auto& entry : values) { - Endpoint* endpoint = entry.first; - if (!mapping._channelMappings.count(endpoint)) { - continue; - } - - const Mapping::List& routes = mapping._channelMappings[endpoint]; - consumedEndpoints.push_back(endpoint); - for (const auto& route : routes) { - float lastValue = 0; - if (mapping._lastValues.count(endpoint)) { - lastValue = mapping._lastValues[endpoint]; - } - float value = entry.second; - for (const auto& filter : route._filters) { - value = filter->apply(value, lastValue); - } - updates[route._destination] = value; - } - } - - // Update the last seen values - mapping._lastValues = values; - - // Remove all the consumed inputs - for (auto endpoint : consumedEndpoints) { - values.erase(endpoint); - } - - // Add all the updates (may restore some of the consumed data if a passthrough was created (i.e. source == dest) - for (const auto& entry : updates) { - values[entry.first] = entry.second; - } - } - }; -} diff --git a/libraries/controllers/src/controllers/ControllerMapping.h b/libraries/controllers/src/controllers/ControllerMapping.h deleted file mode 100644 index ade9984309..0000000000 --- a/libraries/controllers/src/controllers/ControllerMapping.h +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include - -#include -#include - -extern float currentTime(); - -namespace Controllers { - - - /* - * A function which provides input - */ - class FunctionEndpoint : public Endpoint { - public: - - virtual float value() override { - float now = currentTime(); - float delta = now - _lastCalled; - float result = _inputFunction.call(_object, QScriptValue(delta)).toNumber(); - _lastCalled = now; - return result; - } - - virtual void apply(float newValue, float oldValue, const Endpoint& source) override { - if (newValue != oldValue) { - //_outputFunction.call(newValue, oldValue, source); - } - } - - float _lastValue{ NAN }; - float _lastCalled{ 0 }; - QScriptValue _outputFunction; - QScriptValue _inputFunction; - QScriptValue _object; - }; - - - // Encapsulates part of a filter chain - class Filter { - public: - virtual float apply(float newValue, float oldValue) = 0; - }; - - class ScaleFilter : public Filter { - public: - virtual float apply(float newValue, float oldValue) { - return newValue * _scale; - } - - float _scale{ 1.0 }; - }; - - class PulseFilter : public Filter { - public: - virtual float apply(float newValue, float oldValue) { - // ??? - } - - float _lastEmitValue{ 0 }; - float _lastEmitTime{ 0 }; - float _interval{ -1.0f }; - }; - - using FilterList = std::list; - - /* - * encapsulates a source, destination and filters to apply - */ - class Route { - public: - Endpoint* _source; - Endpoint* _destination; - FilterList _filters; - }; - - using ValueMap = std::map; - - class Mapping { - public: - // List of routes - using List = std::list; - // Map of source channels to route lists - using Map = std::map; - - Map _channelMappings; - ValueMap _lastValues; - }; - - class MappingsStack { - std::list _stack; - ValueMap _lastValues; - - void update() { - EndpointList hardwareInputs = getHardwareEndpoints(); - ValueMap currentValues; - - for (auto input : hardwareInputs) { - currentValues[input] = input->value(); - } - - // Now process the current values for each level of the stack - for (auto& mapping : _stack) { - update(mapping, currentValues); - } - - _lastValues = currentValues; - } - - void update(Mapping& mapping, ValueMap& values) { - ValueMap updates; - EndpointList consumedEndpoints; - for (const auto& entry : values) { - Endpoint* endpoint = entry.first; - if (!mapping._channelMappings.count(endpoint)) { - continue; - } - - const Mapping::List& routes = mapping._channelMappings[endpoint]; - consumedEndpoints.push_back(endpoint); - for (const auto& route : routes) { - float lastValue = 0; - if (mapping._lastValues.count(endpoint)) { - lastValue = mapping._lastValues[endpoint]; - } - float value = entry.second; - for (const auto& filter : route._filters) { - value = filter->apply(value, lastValue); - } - updates[route._destination] = value; - } - } - - // Update the last seen values - mapping._lastValues = values; - - // Remove all the consumed inputs - for (auto endpoint : consumedEndpoints) { - values.erase(endpoint); - } - - // Add all the updates (may restore some of the consumed data if a passthrough was created (i.e. source == dest) - for (const auto& entry : updates) { - values[entry.first] = entry.second; - } - } - }; -} diff --git a/libraries/controllers/src/controllers/Endpoint.cpp b/libraries/controllers/src/controllers/Endpoint.cpp index 5f9e0b0efa..dddacc5ae5 100644 --- a/libraries/controllers/src/controllers/Endpoint.cpp +++ b/libraries/controllers/src/controllers/Endpoint.cpp @@ -13,19 +13,6 @@ namespace Controllers { - // FIXME how do we handle dynamic changes in connected hardware? - const Endpoint::List& Endpoint::getHardwareEndpoints() { - static Endpoint::List ACTIVE_HARDWARE; - static std::once_flag once; - std::call_once(once, [&] { - auto userInputMapper = DependencyManager::get(); - // TODO populate ACTIVE_HARDWARE with all the connected devices - // For each connected device - // for each input channel - // build a HardwareEndpoint instance around the input channel and add it to the list - }); - } - // Ex: xbox.RY, xbox.A .... class HardwareEndpoint : public Endpoint { public: @@ -55,4 +42,50 @@ namespace Controllers { float _lastValue; }; + float currentTime() { + return 0; + } + /* + * A function which provides input + */ + class FunctionEndpoint : public Endpoint { + public: + + virtual float value() override { + float now = currentTime(); + float delta = now - _lastCalled; + float result = _inputFunction.call(_object, QScriptValue(delta)).toNumber(); + _lastCalled = now; + return result; + } + + virtual void apply(float newValue, float oldValue, const Endpoint& source) override { + if (newValue != oldValue) { + //_outputFunction.call(newValue, oldValue, source); + } + } + + float _lastValue{ NAN }; + float _lastCalled{ 0 }; + QScriptValue _outputFunction; + QScriptValue _inputFunction; + QScriptValue _object; + }; + + + + // FIXME how do we handle dynamic changes in connected hardware? + const Endpoint::List& Endpoint::getHardwareEndpoints() { + static Endpoint::List ACTIVE_HARDWARE_ENDPOINTS; + static std::once_flag once; + std::call_once(once, [&] { + auto userInputMapper = DependencyManager::get(); + // TODO populate ACTIVE_HARDWARE with all the connected devices + // For each connected device + // for each input channel + // build a HardwareEndpoint instance around the input channel and add it to the list + }); + + return ACTIVE_HARDWARE_ENDPOINTS; + } } diff --git a/libraries/controllers/src/controllers/Filter.cpp b/libraries/controllers/src/controllers/Filter.cpp new file mode 100644 index 0000000000..93f5528073 --- /dev/null +++ b/libraries/controllers/src/controllers/Filter.cpp @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis 2015/10/09 +// 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 "Filter.h" + +#include +#include + +namespace Controllers { + + class ScaleFilter : public Filter { + public: + virtual float apply(float newValue, float oldValue) { + return newValue * _scale; + } + + private: + float _scale{ 1.0 }; + }; + + class PulseFilter : public Filter { + public: + virtual float apply(float newValue, float oldValue) { + // ??? + } + + private: + + float _lastEmitValue{ 0 }; + float _lastEmitTime{ 0 }; + float _interval{ -1.0f }; + }; + + +} + diff --git a/libraries/controllers/src/controllers/Filter.h b/libraries/controllers/src/controllers/Filter.h new file mode 100644 index 0000000000..9a0e4d975c --- /dev/null +++ b/libraries/controllers/src/controllers/Filter.h @@ -0,0 +1,29 @@ +// +// Created by Bradley Austin Davis 2015/10/09 +// 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_Filter_h +#define hifi_Controllers_Filter_h + +#include +#include + +namespace Controllers { + + // Encapsulates part of a filter chain + class Filter { + public: + virtual float apply(float newValue, float oldValue) = 0; + + using Pointer = std::shared_ptr; + using List = std::list; + }; + +} + +#endif diff --git a/libraries/controllers/src/controllers/Mapping.cpp b/libraries/controllers/src/controllers/Mapping.cpp new file mode 100644 index 0000000000..dbcc6407f1 --- /dev/null +++ b/libraries/controllers/src/controllers/Mapping.cpp @@ -0,0 +1,9 @@ +#include "Mapping.h" + +#include +#include + +extern float currentTime(); + +namespace Controllers { +} diff --git a/libraries/controllers/src/controllers/Mapping.h b/libraries/controllers/src/controllers/Mapping.h new file mode 100644 index 0000000000..46ed0f1a35 --- /dev/null +++ b/libraries/controllers/src/controllers/Mapping.h @@ -0,0 +1,87 @@ +#include +#include + +#include +#include + +extern float currentTime(); + +#include "Endpoint.h" +#include "Filter.h" +#include "Route.h" + +namespace Controllers { + + using ValueMap = std::map; + + class Mapping { + public: + // Map of source channels to route lists + using Map = std::map; + + Map _channelMappings; + ValueMap _lastValues; + + void parse(const QString& json); + QString serialize(); + }; + +// class MappingsStack { +// std::list _stack; +// ValueMap _lastValues; +// +// void update() { +// EndpointList hardwareInputs = getHardwareEndpoints(); +// ValueMap currentValues; +// +// for (auto input : hardwareInputs) { +// currentValues[input] = input->value(); +// } +// +// // Now process the current values for each level of the stack +// for (auto& mapping : _stack) { +// update(mapping, currentValues); +// } +// +// _lastValues = currentValues; +// } +// +// void update(Mapping& mapping, ValueMap& values) { +// ValueMap updates; +// EndpointList consumedEndpoints; +// for (const auto& entry : values) { +// Endpoint* endpoint = entry.first; +// if (!mapping._channelMappings.count(endpoint)) { +// continue; +// } +// +// const Mapping::List& routes = mapping._channelMappings[endpoint]; +// consumedEndpoints.push_back(endpoint); +// for (const auto& route : routes) { +// float lastValue = 0; +// if (mapping._lastValues.count(endpoint)) { +// lastValue = mapping._lastValues[endpoint]; +// } +// float value = entry.second; +// for (const auto& filter : route._filters) { +// value = filter->apply(value, lastValue); +// } +// updates[route._destination] = value; +// } +// } +// +// // Update the last seen values +// mapping._lastValues = values; +// +// // Remove all the consumed inputs +// for (auto endpoint : consumedEndpoints) { +// values.erase(endpoint); +// } +// +// // Add all the updates (may restore some of the consumed data if a passthrough was created (i.e. source == dest) +// for (const auto& entry : updates) { +// values[entry.first] = entry.second; +// } +// } +// }; +} diff --git a/libraries/controllers/src/controllers/Route.h b/libraries/controllers/src/controllers/Route.h new file mode 100644 index 0000000000..616a5ebc23 --- /dev/null +++ b/libraries/controllers/src/controllers/Route.h @@ -0,0 +1,32 @@ +// +// Created by Bradley Austin Davis 2015/10/09 +// 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_Route_h +#define hifi_Controllers_Route_h + +#include "Endpoint.h" +#include "Filter.h" + +namespace Controllers { + + /* + * encapsulates a source, destination and filters to apply + */ + class Route { + public: + Endpoint::Pointer _source; + Endpoint::Pointer _destination; + Filter::List _filters; + + using Pointer = std::shared_ptr; + using List = std::list; + }; +} + +#endif diff --git a/tests/controllers/CMakeLists.txt b/tests/controllers/CMakeLists.txt new file mode 100644 index 0000000000..4e31881141 --- /dev/null +++ b/tests/controllers/CMakeLists.txt @@ -0,0 +1,13 @@ + +set(TARGET_NAME controllers-test) + +AUTOSCRIBE_SHADER_LIB(gpu model render-utils ) + +# This is not a testcase -- just set it up as a regular hifi project +setup_hifi_project(Script) +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") + +# link in the shared libraries +link_hifi_libraries(shared script-engine input-plugins controllers) + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/controllers/src/main.cpp b/tests/controllers/src/main.cpp new file mode 100644 index 0000000000..88d29214d3 --- /dev/null +++ b/tests/controllers/src/main.cpp @@ -0,0 +1,38 @@ +// +// main.cpp +// tests/gpu-test/src +// +// 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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int main(int argc, char** argv) { + QGuiApplication app(argc, argv); + QWindow window; + app.exec(); + return 0; +} + +#include "main.moc" +