mirror of
https://github.com/JulianGro/overte.git
synced 2025-05-08 05:29:46 +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.MAX_FRAMERATE = 60;
|
||||||
this.UPDATE_INTERVAL = 1.0 / this.MAX_FRAMERATE
|
this.UPDATE_INTERVAL = 1.0 / this.MAX_FRAMERATE
|
||||||
this.left = left;
|
this.left = left;
|
||||||
|
this.triggered = false;
|
||||||
var actions = Controller.Actions;
|
var actions = Controller.Actions;
|
||||||
var standard = Controller.Standard;
|
var standard = Controller.Standard;
|
||||||
this.palmControl = left ? actions.LeftHand : actions.RightHand;
|
this.palmControl = left ? actions.LeftHand : actions.RightHand;
|
||||||
this.action = left ? standard.LeftPrimaryThumb : standard.RightPrimaryThumb;
|
|
||||||
logDebug("Init OmniTool " + (left ? "left" : "right"));
|
logDebug("Init OmniTool " + (left ? "left" : "right"));
|
||||||
this.highlighter = new Highlighter();
|
this.highlighter = new Highlighter();
|
||||||
this.ignoreEntities = {};
|
this.ignoreEntities = {};
|
||||||
|
@ -50,9 +50,6 @@ OmniTool = function(left) {
|
||||||
|
|
||||||
// Connect to desired events
|
// Connect to desired events
|
||||||
var that = this;
|
var that = this;
|
||||||
Controller.inputEvent.connect(function(action, state) {
|
|
||||||
that.onInputEvent(action, state);
|
|
||||||
});
|
|
||||||
|
|
||||||
Script.update.connect(function(deltaTime) {
|
Script.update.connect(function(deltaTime) {
|
||||||
that.lastUpdateInterval += deltaTime;
|
that.lastUpdateInterval += deltaTime;
|
||||||
|
@ -65,6 +62,12 @@ OmniTool = function(left) {
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
that.onCleanup();
|
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) {
|
OmniTool.prototype.showWand = function(show) {
|
||||||
|
@ -83,29 +86,23 @@ OmniTool.prototype.showWand = function(show) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OmniTool.prototype.onCleanup = function(action) {
|
OmniTool.prototype.onCleanup = function(action) {
|
||||||
|
this.mapping.disable();
|
||||||
this.unloadModule();
|
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) {
|
OmniTool.prototype.onUpdateTrigger = function (value) {
|
||||||
if (state) {
|
//logDebug("Trigger update value " + value);
|
||||||
|
var triggered = value != 0;
|
||||||
|
if (triggered != this.triggered) {
|
||||||
|
this.triggered = triggered;
|
||||||
|
if (this.triggered) {
|
||||||
this.onClick();
|
this.onClick();
|
||||||
} else {
|
} else {
|
||||||
this.onRelease();
|
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) {
|
OmniTool.prototype.getOmniToolData = function(entityId) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ 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(); }
|
||||||
|
|
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 <NumericalConstants.h>
|
||||||
|
|
||||||
#include "StandardController.h"
|
#include "StandardController.h"
|
||||||
|
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
|
#include "Endpoint.h"
|
||||||
|
#include "Route.h"
|
||||||
|
#include "Mapping.h"
|
||||||
|
|
||||||
namespace controller {
|
namespace controller {
|
||||||
const uint16_t UserInputMapper::ACTIONS_DEVICE = Input::INVALID_DEVICE - 0xFF;
|
const uint16_t UserInputMapper::ACTIONS_DEVICE = Input::INVALID_DEVICE - 0xFF;
|
||||||
const uint16_t UserInputMapper::STANDARD_DEVICE = 0;
|
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 {
|
virtual float value() override {
|
||||||
float result = 0;
|
float result = 0;
|
||||||
for (auto& child : _children) {
|
for (auto& child : _children) {
|
||||||
|
@ -674,19 +682,27 @@ Input UserInputMapper::makeStandardInput(controller::StandardPoseChannel pose) {
|
||||||
|
|
||||||
static auto lastDebugTime = usecTimestampNow();
|
static auto lastDebugTime = usecTimestampNow();
|
||||||
static auto debugRoutes = false;
|
static auto debugRoutes = false;
|
||||||
|
static auto debuggableRoutes = false;
|
||||||
static const auto DEBUG_INTERVAL = USECS_PER_SECOND;
|
static const auto DEBUG_INTERVAL = USECS_PER_SECOND;
|
||||||
|
|
||||||
void UserInputMapper::runMappings() {
|
void UserInputMapper::runMappings() {
|
||||||
auto now = usecTimestampNow();
|
auto now = usecTimestampNow();
|
||||||
if (now - lastDebugTime > DEBUG_INTERVAL) {
|
if (debuggableRoutes && now - lastDebugTime > DEBUG_INTERVAL) {
|
||||||
lastDebugTime = now;
|
lastDebugTime = now;
|
||||||
debugRoutes = true;
|
debugRoutes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debugRoutes) {
|
||||||
|
qCDebug(controllers) << "Beginning mapping frame";
|
||||||
|
}
|
||||||
static auto deviceNames = getDeviceNames();
|
static auto deviceNames = getDeviceNames();
|
||||||
for (auto endpointEntry : this->_endpointsByInput) {
|
for (auto endpointEntry : this->_endpointsByInput) {
|
||||||
endpointEntry.second->reset();
|
endpointEntry.second->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debugRoutes) {
|
||||||
|
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) {
|
for (const auto& route : _deviceRoutes) {
|
||||||
if (!route) {
|
if (!route) {
|
||||||
|
@ -695,12 +711,19 @@ void UserInputMapper::runMappings() {
|
||||||
applyRoute(route);
|
applyRoute(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debugRoutes) {
|
||||||
|
qCDebug(controllers) << "Processing standard routes";
|
||||||
|
}
|
||||||
for (const auto& route : _standardRoutes) {
|
for (const auto& route : _standardRoutes) {
|
||||||
if (!route) {
|
if (!route) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
applyRoute(route);
|
applyRoute(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debugRoutes) {
|
||||||
|
qCDebug(controllers) << "Done with mappings";
|
||||||
|
}
|
||||||
debugRoutes = false;
|
debugRoutes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,6 +1197,22 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) {
|
||||||
return parseMapping(doc.object());
|
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) {
|
void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
|
@ -1186,12 +1225,18 @@ 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) {
|
||||||
|
debuggableRoutes = hasDebuggableRoute(_deviceRoutes) || hasDebuggableRoute(_standardRoutes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
|
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) {
|
_standardRoutes.remove_if([&](const Route::Pointer& value) {
|
||||||
return routeSet.count(value) != 0;
|
return routeSet.count(value) != 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (debuggableRoutes) {
|
||||||
|
debuggableRoutes = hasDebuggableRoute(_deviceRoutes) || hasDebuggableRoute(_standardRoutes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,12 @@
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
|
#include "Forward.h"
|
||||||
#include "Pose.h"
|
#include "Pose.h"
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
#include "InputDevice.h"
|
#include "InputDevice.h"
|
||||||
#include "DeviceProxy.h"
|
#include "DeviceProxy.h"
|
||||||
#include "StandardControls.h"
|
#include "StandardControls.h"
|
||||||
#include "Mapping.h"
|
|
||||||
#include "Endpoint.h"
|
|
||||||
#include "Actions.h"
|
#include "Actions.h"
|
||||||
|
|
||||||
namespace controller {
|
namespace controller {
|
||||||
|
@ -45,15 +44,14 @@ namespace controller {
|
||||||
public:
|
public:
|
||||||
using InputPair = Input::NamedPair;
|
using InputPair = Input::NamedPair;
|
||||||
// FIXME move to unordered set / map
|
// FIXME move to unordered set / map
|
||||||
using EndpointToInputMap = std::map<Endpoint::Pointer, Input>;
|
using EndpointToInputMap = std::map<EndpointPointer, Input>;
|
||||||
using MappingNameMap = std::map<QString, Mapping::Pointer>;
|
using MappingNameMap = std::map<QString, MappingPointer>;
|
||||||
using MappingDeviceMap = std::map<uint16_t, Mapping::Pointer>;
|
using MappingDeviceMap = std::map<uint16_t, MappingPointer>;
|
||||||
using MappingStack = std::list<Mapping::Pointer>;
|
using MappingStack = std::list<MappingPointer>;
|
||||||
using InputToEndpointMap = std::map<Input, Endpoint::Pointer>;
|
using InputToEndpointMap = std::map<Input, EndpointPointer>;
|
||||||
using EndpointSet = std::unordered_set<Endpoint::Pointer>;
|
using EndpointSet = std::unordered_set<EndpointPointer>;
|
||||||
using EndpointOverrideMap = std::map<Endpoint::Pointer, Endpoint::Pointer>;
|
using EndpointPair = std::pair<EndpointPointer, EndpointPointer>;
|
||||||
using EndpointPair = std::pair<Endpoint::Pointer, Endpoint::Pointer>;
|
using EndpointPairMap = std::map<EndpointPair, EndpointPointer>;
|
||||||
using EndpointPairMap = std::map<EndpointPair, Endpoint::Pointer>;
|
|
||||||
using DevicesMap = std::map<int, DeviceProxy::Pointer>;
|
using DevicesMap = std::map<int, DeviceProxy::Pointer>;
|
||||||
using uint16 = uint16_t;
|
using uint16 = uint16_t;
|
||||||
using uint32 = uint32_t;
|
using uint32 = uint32_t;
|
||||||
|
@ -107,9 +105,9 @@ namespace controller {
|
||||||
uint16 getStandardDeviceID() const { return STANDARD_DEVICE; }
|
uint16 getStandardDeviceID() const { return STANDARD_DEVICE; }
|
||||||
DeviceProxy::Pointer getStandardDevice() { return _registeredDevices[getStandardDeviceID()]; }
|
DeviceProxy::Pointer getStandardDevice() { return _registeredDevices[getStandardDeviceID()]; }
|
||||||
|
|
||||||
Mapping::Pointer newMapping(const QString& mappingName);
|
MappingPointer newMapping(const QString& mappingName);
|
||||||
Mapping::Pointer parseMapping(const QString& json);
|
MappingPointer parseMapping(const QString& json);
|
||||||
Mapping::Pointer loadMapping(const QString& jsonFile);
|
MappingPointer loadMapping(const QString& jsonFile);
|
||||||
|
|
||||||
void enableMapping(const QString& mappingName, bool enable = true);
|
void enableMapping(const QString& mappingName, bool enable = true);
|
||||||
float getValue(const Input& input) const;
|
float getValue(const Input& input) const;
|
||||||
|
@ -138,30 +136,30 @@ 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 Endpoint::Pointer& endpoint) const;
|
float getValue(const EndpointPointer& endpoint) const;
|
||||||
Pose getPose(const Endpoint::Pointer& endpoint) const;
|
Pose getPose(const EndpointPointer& endpoint) const;
|
||||||
|
|
||||||
friend class RouteBuilderProxy;
|
friend class RouteBuilderProxy;
|
||||||
friend class MappingBuilderProxy;
|
friend class MappingBuilderProxy;
|
||||||
|
|
||||||
void runMappings();
|
void runMappings();
|
||||||
void applyRoute(const Route::Pointer& route);
|
void applyRoute(const RoutePointer& route);
|
||||||
void enableMapping(const Mapping::Pointer& mapping);
|
void enableMapping(const MappingPointer& mapping);
|
||||||
void disableMapping(const Mapping::Pointer& mapping);
|
void disableMapping(const MappingPointer& mapping);
|
||||||
Endpoint::Pointer endpointFor(const QJSValue& endpoint);
|
EndpointPointer endpointFor(const QJSValue& endpoint);
|
||||||
Endpoint::Pointer endpointFor(const QScriptValue& endpoint);
|
EndpointPointer endpointFor(const QScriptValue& endpoint);
|
||||||
Endpoint::Pointer endpointFor(const Input& endpoint) const;
|
EndpointPointer endpointFor(const Input& endpoint) const;
|
||||||
Endpoint::Pointer compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second);
|
EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second);
|
||||||
|
|
||||||
Mapping::Pointer parseMapping(const QJsonValue& json);
|
MappingPointer parseMapping(const QJsonValue& json);
|
||||||
Route::Pointer parseRoute(const QJsonValue& value);
|
RoutePointer parseRoute(const QJsonValue& value);
|
||||||
Endpoint::Pointer parseDestination(const QJsonValue& value);
|
EndpointPointer parseDestination(const QJsonValue& value);
|
||||||
Endpoint::Pointer parseSource(const QJsonValue& value);
|
EndpointPointer parseSource(const QJsonValue& value);
|
||||||
Endpoint::Pointer parseEndpoint(const QJsonValue& value);
|
EndpointPointer parseEndpoint(const QJsonValue& value);
|
||||||
Conditional::Pointer parseConditional(const QJsonValue& value);
|
ConditionalPointer parseConditional(const QJsonValue& value);
|
||||||
|
|
||||||
static Filter::Pointer parseFilter(const QJsonValue& value);
|
static FilterPointer parseFilter(const QJsonValue& value);
|
||||||
static Filter::List parseFilters(const QJsonValue& value);
|
static FilterList parseFilters(const QJsonValue& value);
|
||||||
|
|
||||||
InputToEndpointMap _endpointsByInput;
|
InputToEndpointMap _endpointsByInput;
|
||||||
EndpointToInputMap _inputsByEndpoint;
|
EndpointToInputMap _inputsByEndpoint;
|
||||||
|
@ -170,8 +168,8 @@ namespace controller {
|
||||||
MappingNameMap _mappingsByName;
|
MappingNameMap _mappingsByName;
|
||||||
MappingDeviceMap _mappingsByDevice;
|
MappingDeviceMap _mappingsByDevice;
|
||||||
|
|
||||||
Route::List _deviceRoutes;
|
RouteList _deviceRoutes;
|
||||||
Route::List _standardRoutes;
|
RouteList _standardRoutes;
|
||||||
|
|
||||||
using Locker = std::unique_lock<std::recursive_mutex>;
|
using Locker = std::unique_lock<std::recursive_mutex>;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,11 @@ void RouteBuilderProxy::to(const Endpoint::Pointer& destination) {
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject* RouteBuilderProxy::debug(bool enable) {
|
||||||
|
_route->debug = enable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
QObject* RouteBuilderProxy::filterQml(const QJSValue& expression) {
|
QObject* RouteBuilderProxy::filterQml(const QJSValue& expression) {
|
||||||
if (expression.isCallable()) {
|
if (expression.isCallable()) {
|
||||||
addFilter([=](float value) {
|
addFilter([=](float value) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ class RouteBuilderProxy : public QObject {
|
||||||
Q_INVOKABLE QObject* filterQml(const QJSValue& expression);
|
Q_INVOKABLE QObject* filterQml(const QJSValue& expression);
|
||||||
|
|
||||||
Q_INVOKABLE void to(const QScriptValue& destination);
|
Q_INVOKABLE void to(const QScriptValue& destination);
|
||||||
|
Q_INVOKABLE QObject* debug(bool enable = true);
|
||||||
Q_INVOKABLE QObject* filter(const QScriptValue& expression);
|
Q_INVOKABLE QObject* filter(const QScriptValue& expression);
|
||||||
Q_INVOKABLE QObject* clamp(float min, float max);
|
Q_INVOKABLE QObject* clamp(float min, float max);
|
||||||
Q_INVOKABLE QObject* pulse(float interval);
|
Q_INVOKABLE QObject* pulse(float interval);
|
||||||
|
|
Loading…
Reference in a new issue