mirror of
https://github.com/lubosz/overte.git
synced 2025-04-15 18:48:32 +02:00
Moving omniTool to a route mapped input
This commit is contained in:
parent
be148686a7
commit
56deef9d6e
7 changed files with 139 additions and 51 deletions
|
@ -22,10 +22,10 @@ OmniTool = function(left) {
|
|||
this.MAX_FRAMERATE = 60;
|
||||
this.UPDATE_INTERVAL = 1.0 / this.MAX_FRAMERATE
|
||||
this.left = left;
|
||||
this.triggered = false;
|
||||
var actions = Controller.Actions;
|
||||
var standard = Controller.Standard;
|
||||
this.palmControl = left ? actions.LeftHand : actions.RightHand;
|
||||
this.action = left ? standard.LeftPrimaryThumb : standard.RightPrimaryThumb;
|
||||
logDebug("Init OmniTool " + (left ? "left" : "right"));
|
||||
this.highlighter = new Highlighter();
|
||||
this.ignoreEntities = {};
|
||||
|
@ -50,9 +50,6 @@ OmniTool = function(left) {
|
|||
|
||||
// Connect to desired events
|
||||
var that = this;
|
||||
Controller.inputEvent.connect(function(action, state) {
|
||||
that.onInputEvent(action, state);
|
||||
});
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
that.lastUpdateInterval += deltaTime;
|
||||
|
@ -65,6 +62,12 @@ OmniTool = function(left) {
|
|||
Script.scriptEnding.connect(function() {
|
||||
that.onCleanup();
|
||||
});
|
||||
|
||||
this.mapping = Controller.newMapping();
|
||||
this.mapping.from(left ? standard.LeftPrimaryThumb : standard.RightPrimaryThumb).to(function(value){
|
||||
that.onUpdateTrigger(value);
|
||||
})
|
||||
this.mapping.enable();
|
||||
}
|
||||
|
||||
OmniTool.prototype.showWand = function(show) {
|
||||
|
@ -83,29 +86,23 @@ OmniTool.prototype.showWand = function(show) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
OmniTool.prototype.onCleanup = function(action) {
|
||||
this.mapping.disable();
|
||||
this.unloadModule();
|
||||
}
|
||||
|
||||
OmniTool.prototype.onInputEvent = function(action, state) {
|
||||
// FIXME figure out the issues when only one spatial controller is active
|
||||
var actionNames = Controller.getActionNames();
|
||||
if (this.module && this.module.onInputEvent) {
|
||||
this.module.onInputEvent(action, state);
|
||||
}
|
||||
|
||||
if (action == this.action) {
|
||||
if (state) {
|
||||
OmniTool.prototype.onUpdateTrigger = function (value) {
|
||||
//logDebug("Trigger update value " + value);
|
||||
var triggered = value != 0;
|
||||
if (triggered != this.triggered) {
|
||||
this.triggered = triggered;
|
||||
if (this.triggered) {
|
||||
this.onClick();
|
||||
} else {
|
||||
this.onRelease();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME Does not work
|
||||
//// with only one controller active (listed as 2 here because 'tip' + 'palm')
|
||||
//// then treat the alt action button as the action button
|
||||
}
|
||||
|
||||
OmniTool.prototype.getOmniToolData = function(entityId) {
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace controller {
|
|||
using WriteLambda = std::function<void(float)>;
|
||||
|
||||
Endpoint(const Input& input) : _input(input) {}
|
||||
virtual uint8_t priority() const { return 0x7f; }
|
||||
virtual float value() = 0;
|
||||
virtual void apply(float newValue, float oldValue, const Pointer& source) = 0;
|
||||
virtual Pose pose() { return Pose(); }
|
||||
|
|
37
libraries/controllers/src/controllers/Forward.h
Normal file
37
libraries/controllers/src/controllers/Forward.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// 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_Forward_h
|
||||
#define hifi_Controllers_Forward_h
|
||||
|
||||
namespace controller {
|
||||
|
||||
class Endpoint;
|
||||
using EndpointPointer = std::shared_ptr<Endpoint>;
|
||||
using EndpointList = std::list<EndpointPointer>;
|
||||
|
||||
class Filter;
|
||||
using FilterPointer = std::shared_ptr<Filter>;
|
||||
using FilterList = std::list<FilterPointer>;
|
||||
|
||||
class Route;
|
||||
using RoutePointer = std::shared_ptr<Route>;
|
||||
using RouteList = std::list<RoutePointer>;
|
||||
|
||||
class Conditional;
|
||||
using ConditionalPointer = std::shared_ptr<Conditional>;
|
||||
using ConditionalList = std::list<ConditionalPointer>;
|
||||
|
||||
class Mapping;
|
||||
using MappingPointer = std::shared_ptr<Mapping>;
|
||||
using MappingList = std::list<MappingPointer>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -21,8 +21,13 @@
|
|||
#include <NumericalConstants.h>
|
||||
|
||||
#include "StandardController.h"
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
#include "Endpoint.h"
|
||||
#include "Route.h"
|
||||
#include "Mapping.h"
|
||||
|
||||
namespace controller {
|
||||
const uint16_t UserInputMapper::ACTIONS_DEVICE = Input::INVALID_DEVICE - 0xFF;
|
||||
const uint16_t UserInputMapper::STANDARD_DEVICE = 0;
|
||||
|
@ -211,6 +216,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Process later than normal
|
||||
virtual uint8_t priority() const override { return 0x6F; }
|
||||
|
||||
virtual float value() override {
|
||||
float result = 0;
|
||||
for (auto& child : _children) {
|
||||
|
@ -674,19 +682,27 @@ Input UserInputMapper::makeStandardInput(controller::StandardPoseChannel pose) {
|
|||
|
||||
static auto lastDebugTime = usecTimestampNow();
|
||||
static auto debugRoutes = false;
|
||||
static auto debuggableRoutes = false;
|
||||
static const auto DEBUG_INTERVAL = USECS_PER_SECOND;
|
||||
|
||||
void UserInputMapper::runMappings() {
|
||||
auto now = usecTimestampNow();
|
||||
if (now - lastDebugTime > DEBUG_INTERVAL) {
|
||||
if (debuggableRoutes && now - lastDebugTime > DEBUG_INTERVAL) {
|
||||
lastDebugTime = now;
|
||||
debugRoutes = true;
|
||||
}
|
||||
|
||||
if (debugRoutes) {
|
||||
qCDebug(controllers) << "Beginning mapping frame";
|
||||
}
|
||||
static auto deviceNames = getDeviceNames();
|
||||
for (auto endpointEntry : this->_endpointsByInput) {
|
||||
endpointEntry.second->reset();
|
||||
}
|
||||
|
||||
if (debugRoutes) {
|
||||
qCDebug(controllers) << "Processing device routes";
|
||||
}
|
||||
// Now process the current values for each level of the stack
|
||||
for (const auto& route : _deviceRoutes) {
|
||||
if (!route) {
|
||||
|
@ -695,12 +711,19 @@ void UserInputMapper::runMappings() {
|
|||
applyRoute(route);
|
||||
}
|
||||
|
||||
if (debugRoutes) {
|
||||
qCDebug(controllers) << "Processing standard routes";
|
||||
}
|
||||
for (const auto& route : _standardRoutes) {
|
||||
if (!route) {
|
||||
continue;
|
||||
}
|
||||
applyRoute(route);
|
||||
}
|
||||
|
||||
if (debugRoutes) {
|
||||
qCDebug(controllers) << "Done with mappings";
|
||||
}
|
||||
debugRoutes = false;
|
||||
}
|
||||
|
||||
|
@ -1174,6 +1197,22 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) {
|
|||
return parseMapping(doc.object());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool hasDebuggableRoute(const T& routes) {
|
||||
for (auto route : routes) {
|
||||
if (route->debug) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
Locker locker(_lock);
|
||||
|
@ -1186,12 +1225,18 @@ void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
|||
return (value->source->getInput().device != STANDARD_DEVICE);
|
||||
});
|
||||
_standardRoutes.insert(_standardRoutes.begin(), standardRoutes.begin(), standardRoutes.end());
|
||||
sortRoutes(_standardRoutes);
|
||||
|
||||
Route::List deviceRoutes = mapping->routes;
|
||||
deviceRoutes.remove_if([](const Route::Pointer& value) {
|
||||
return (value->source->getInput().device == STANDARD_DEVICE);
|
||||
});
|
||||
_deviceRoutes.insert(_deviceRoutes.begin(), deviceRoutes.begin(), deviceRoutes.end());
|
||||
sortRoutes(_standardRoutes);
|
||||
|
||||
if (!debuggableRoutes) {
|
||||
debuggableRoutes = hasDebuggableRoute(_deviceRoutes) || hasDebuggableRoute(_standardRoutes);
|
||||
}
|
||||
}
|
||||
|
||||
void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
|
||||
|
@ -1204,6 +1249,10 @@ void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
|
|||
_standardRoutes.remove_if([&](const Route::Pointer& value) {
|
||||
return routeSet.count(value) != 0;
|
||||
});
|
||||
|
||||
if (debuggableRoutes) {
|
||||
debuggableRoutes = hasDebuggableRoute(_deviceRoutes) || hasDebuggableRoute(_standardRoutes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,13 +23,12 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Forward.h"
|
||||
#include "Pose.h"
|
||||
#include "Input.h"
|
||||
#include "InputDevice.h"
|
||||
#include "DeviceProxy.h"
|
||||
#include "StandardControls.h"
|
||||
#include "Mapping.h"
|
||||
#include "Endpoint.h"
|
||||
#include "Actions.h"
|
||||
|
||||
namespace controller {
|
||||
|
@ -45,15 +44,14 @@ namespace controller {
|
|||
public:
|
||||
using InputPair = Input::NamedPair;
|
||||
// FIXME move to unordered set / map
|
||||
using EndpointToInputMap = std::map<Endpoint::Pointer, Input>;
|
||||
using MappingNameMap = std::map<QString, Mapping::Pointer>;
|
||||
using MappingDeviceMap = std::map<uint16_t, Mapping::Pointer>;
|
||||
using MappingStack = std::list<Mapping::Pointer>;
|
||||
using InputToEndpointMap = std::map<Input, Endpoint::Pointer>;
|
||||
using EndpointSet = std::unordered_set<Endpoint::Pointer>;
|
||||
using EndpointOverrideMap = std::map<Endpoint::Pointer, Endpoint::Pointer>;
|
||||
using EndpointPair = std::pair<Endpoint::Pointer, Endpoint::Pointer>;
|
||||
using EndpointPairMap = std::map<EndpointPair, Endpoint::Pointer>;
|
||||
using EndpointToInputMap = std::map<EndpointPointer, Input>;
|
||||
using MappingNameMap = std::map<QString, MappingPointer>;
|
||||
using MappingDeviceMap = std::map<uint16_t, MappingPointer>;
|
||||
using MappingStack = std::list<MappingPointer>;
|
||||
using InputToEndpointMap = std::map<Input, EndpointPointer>;
|
||||
using EndpointSet = std::unordered_set<EndpointPointer>;
|
||||
using EndpointPair = std::pair<EndpointPointer, EndpointPointer>;
|
||||
using EndpointPairMap = std::map<EndpointPair, EndpointPointer>;
|
||||
using DevicesMap = std::map<int, DeviceProxy::Pointer>;
|
||||
using uint16 = uint16_t;
|
||||
using uint32 = uint32_t;
|
||||
|
@ -107,9 +105,9 @@ namespace controller {
|
|||
uint16 getStandardDeviceID() const { return STANDARD_DEVICE; }
|
||||
DeviceProxy::Pointer getStandardDevice() { return _registeredDevices[getStandardDeviceID()]; }
|
||||
|
||||
Mapping::Pointer newMapping(const QString& mappingName);
|
||||
Mapping::Pointer parseMapping(const QString& json);
|
||||
Mapping::Pointer loadMapping(const QString& jsonFile);
|
||||
MappingPointer newMapping(const QString& mappingName);
|
||||
MappingPointer parseMapping(const QString& json);
|
||||
MappingPointer loadMapping(const QString& jsonFile);
|
||||
|
||||
void enableMapping(const QString& mappingName, bool enable = true);
|
||||
float getValue(const Input& input) const;
|
||||
|
@ -138,30 +136,30 @@ namespace controller {
|
|||
int recordDeviceOfType(const QString& deviceName);
|
||||
QHash<const QString&, int> _deviceCounts;
|
||||
|
||||
float getValue(const Endpoint::Pointer& endpoint) const;
|
||||
Pose getPose(const Endpoint::Pointer& endpoint) const;
|
||||
float getValue(const EndpointPointer& endpoint) const;
|
||||
Pose getPose(const EndpointPointer& endpoint) const;
|
||||
|
||||
friend class RouteBuilderProxy;
|
||||
friend class MappingBuilderProxy;
|
||||
|
||||
void runMappings();
|
||||
void applyRoute(const Route::Pointer& route);
|
||||
void enableMapping(const Mapping::Pointer& mapping);
|
||||
void disableMapping(const Mapping::Pointer& mapping);
|
||||
Endpoint::Pointer endpointFor(const QJSValue& endpoint);
|
||||
Endpoint::Pointer endpointFor(const QScriptValue& endpoint);
|
||||
Endpoint::Pointer endpointFor(const Input& endpoint) const;
|
||||
Endpoint::Pointer compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second);
|
||||
void applyRoute(const RoutePointer& route);
|
||||
void enableMapping(const MappingPointer& mapping);
|
||||
void disableMapping(const MappingPointer& mapping);
|
||||
EndpointPointer endpointFor(const QJSValue& endpoint);
|
||||
EndpointPointer endpointFor(const QScriptValue& endpoint);
|
||||
EndpointPointer endpointFor(const Input& endpoint) const;
|
||||
EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second);
|
||||
|
||||
Mapping::Pointer parseMapping(const QJsonValue& json);
|
||||
Route::Pointer parseRoute(const QJsonValue& value);
|
||||
Endpoint::Pointer parseDestination(const QJsonValue& value);
|
||||
Endpoint::Pointer parseSource(const QJsonValue& value);
|
||||
Endpoint::Pointer parseEndpoint(const QJsonValue& value);
|
||||
Conditional::Pointer parseConditional(const QJsonValue& value);
|
||||
MappingPointer parseMapping(const QJsonValue& json);
|
||||
RoutePointer parseRoute(const QJsonValue& value);
|
||||
EndpointPointer parseDestination(const QJsonValue& value);
|
||||
EndpointPointer parseSource(const QJsonValue& value);
|
||||
EndpointPointer parseEndpoint(const QJsonValue& value);
|
||||
ConditionalPointer parseConditional(const QJsonValue& value);
|
||||
|
||||
static Filter::Pointer parseFilter(const QJsonValue& value);
|
||||
static Filter::List parseFilters(const QJsonValue& value);
|
||||
static FilterPointer parseFilter(const QJsonValue& value);
|
||||
static FilterList parseFilters(const QJsonValue& value);
|
||||
|
||||
InputToEndpointMap _endpointsByInput;
|
||||
EndpointToInputMap _inputsByEndpoint;
|
||||
|
@ -170,8 +168,8 @@ namespace controller {
|
|||
MappingNameMap _mappingsByName;
|
||||
MappingDeviceMap _mappingsByDevice;
|
||||
|
||||
Route::List _deviceRoutes;
|
||||
Route::List _standardRoutes;
|
||||
RouteList _deviceRoutes;
|
||||
RouteList _standardRoutes;
|
||||
|
||||
using Locker = std::unique_lock<std::recursive_mutex>;
|
||||
|
||||
|
|
|
@ -39,6 +39,11 @@ void RouteBuilderProxy::to(const Endpoint::Pointer& destination) {
|
|||
deleteLater();
|
||||
}
|
||||
|
||||
QObject* RouteBuilderProxy::debug(bool enable) {
|
||||
_route->debug = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
QObject* RouteBuilderProxy::filterQml(const QJSValue& expression) {
|
||||
if (expression.isCallable()) {
|
||||
addFilter([=](float value) {
|
||||
|
|
|
@ -35,6 +35,7 @@ class RouteBuilderProxy : public QObject {
|
|||
Q_INVOKABLE QObject* filterQml(const QJSValue& expression);
|
||||
|
||||
Q_INVOKABLE void to(const QScriptValue& destination);
|
||||
Q_INVOKABLE QObject* debug(bool enable = true);
|
||||
Q_INVOKABLE QObject* filter(const QScriptValue& expression);
|
||||
Q_INVOKABLE QObject* clamp(float min, float max);
|
||||
Q_INVOKABLE QObject* pulse(float interval);
|
||||
|
|
Loading…
Reference in a new issue