From 0fa73c73ce24c107d6dc519607e95930881f0386 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 15 Mar 2018 10:14:11 -0700 Subject: [PATCH 1/2] stats --- interface/resources/icons/+android/stats.svg | 16 +++++ interface/resources/qml/+android/StatText.qml | 9 +++ .../resources/qml/hifi/+android/StatsBar.qml | 71 +++++++++++++++++++ scripts/+android/defaultScripts.js | 3 +- scripts/system/+android/stats.js | 39 ++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 interface/resources/icons/+android/stats.svg create mode 100644 interface/resources/qml/+android/StatText.qml create mode 100644 interface/resources/qml/hifi/+android/StatsBar.qml create mode 100644 scripts/system/+android/stats.js diff --git a/interface/resources/icons/+android/stats.svg b/interface/resources/icons/+android/stats.svg new file mode 100644 index 0000000000..f642650c66 --- /dev/null +++ b/interface/resources/icons/+android/stats.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/interface/resources/qml/+android/StatText.qml b/interface/resources/qml/+android/StatText.qml new file mode 100644 index 0000000000..5dc8377030 --- /dev/null +++ b/interface/resources/qml/+android/StatText.qml @@ -0,0 +1,9 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +Text { + color: "white"; + style: Text.Outline; + styleColor: "black"; + font.pixelSize: 15; +} diff --git a/interface/resources/qml/hifi/+android/StatsBar.qml b/interface/resources/qml/hifi/+android/StatsBar.qml new file mode 100644 index 0000000000..aee438b44f --- /dev/null +++ b/interface/resources/qml/hifi/+android/StatsBar.qml @@ -0,0 +1,71 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls +import ".." + +Item { + id: bar + x:300 + y:0 + width: 300 + height: 300 + z: -1 + + signal sendToScript(var message); + signal windowClosed(); + + property bool shown: true + + onShownChanged: { + bar.visible = shown; + } + + Rectangle { + anchors.fill : parent + color: "transparent" + Flow { + id: flowMain + spacing: 10 + flow: Flow.TopToBottom + layoutDirection: Flow.TopToBottom + anchors.fill: parent + anchors.margins: 4 + } + } + + Component.onCompleted: { + // put on bottom + x = 300; + y = 0; + width = 300; + height = 300; + } + + function addButton(properties) { + var component = Qt.createComponent("button.qml"); + if (component.status == Component.Ready) { + var button = component.createObject(flowMain); + // copy all properites to button + var keys = Object.keys(properties).forEach(function (key) { + button[key] = properties[key]; + }); + return button; + } else if( component.status == Component.Error) { + console.log("Load button errors " + component.errorString()); + } + } + + function urlHelper(src) { + if (src.match(/\bhttp/)) { + return src; + } else { + return "../../../" + src; + } + } + +} diff --git a/scripts/+android/defaultScripts.js b/scripts/+android/defaultScripts.js index a8f6bf42a1..11aee6a9d2 100644 --- a/scripts/+android/defaultScripts.js +++ b/scripts/+android/defaultScripts.js @@ -16,7 +16,8 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/+android/touchscreenvirtualpad.js", "system/+android/bottombar.js", "system/+android/audio.js" , - "system/+android/modes.js"/*, + "system/+android/modes.js", + "system/+android/stats.js"/*, "system/away.js", "system/controllers/controllerDisplayManager.js", "system/controllers/handControllerGrabAndroid.js", diff --git a/scripts/system/+android/stats.js b/scripts/system/+android/stats.js new file mode 100644 index 0000000000..a93bcb5794 --- /dev/null +++ b/scripts/system/+android/stats.js @@ -0,0 +1,39 @@ +"use strict"; +// +// stats.js +// scripts/system/ +// +// Created by Sam Gondelman on 3/14/18 +// Copyright 2018 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 +// + +(function() { // BEGIN LOCAL_SCOPE + +var statsbar; +var statsButton; + +function init() { + statsbar = new QmlFragment({ + qml: "hifi/StatsBar.qml" + }); + + statsButton = statsbar.addButton({ + icon: "icons/stats.svg", + activeIcon: "icons/stats.svg", + textSize: 45, + bgOpacity: 0.0, + activeBgOpacity: 0.0, + bgColor: "#FFFFFF", + text: "STATS" + }); + statsButton.clicked.connect(function() { + Menu.triggerOption("Stats"); + }); +} + +init(); + +}()); // END LOCAL_SCOPE From 06c0b3afd3e9c324e6e9fc4858dfb1adfdc6d46d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 16 Mar 2018 16:52:12 -0700 Subject: [PATCH 2/2] disable IK on android, input recorder doesn't do anything if off --- .../animation/src/AnimInverseKinematics.cpp | 5 ++ .../src/controllers/UserInputMapper.cpp | 62 +++++++++++-------- .../impl/endpoints/ActionEndpoint.cpp | 19 +++--- 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 849ea5ee6b..dc004fe60d 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -882,6 +882,11 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar //virtual const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { +#ifdef Q_OS_ANDROID + // disable IK on android + return underPoses; +#endif + // allows solutionSource to be overridden by an animVar auto solutionSource = animVars.lookup(_solutionSourceVar, (int)_solutionSource); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 29f011fba2..371deec7d5 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -73,7 +73,8 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) { qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID; - for (const auto& inputMapping : device->getAvailableInputs()) { + auto inputs = device->getAvailableInputs(); + for (const auto& inputMapping : inputs) { const auto& input = inputMapping.first; // Ignore aliases if (_endpointsByInput.count(input)) { @@ -126,7 +127,8 @@ void UserInputMapper::removeDevice(int deviceID) { _mappingsByDevice.erase(mappingsEntry); } - for (const auto& inputMapping : device->getAvailableInputs()) { + auto inputs = device->getAvailableInputs(); + for (const auto& inputMapping : inputs) { const auto& input = inputMapping.first; auto endpoint = _endpointsByInput.find(input); if (endpoint != _endpointsByInput.end()) { @@ -171,7 +173,7 @@ InputDevice::Pointer UserInputMapper::getDevice(const Input& input) { } } -QString UserInputMapper::getDeviceName(uint16 deviceID) { +QString UserInputMapper::getDeviceName(uint16 deviceID) { Locker locker(_lock); if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { return _registeredDevices[deviceID]->_name; @@ -181,7 +183,7 @@ QString UserInputMapper::getDeviceName(uint16 deviceID) { int UserInputMapper::findDevice(QString name) const { Locker locker(_lock); - for (auto device : _registeredDevices) { + for (const auto& device : _registeredDevices) { if (device.second->_name == name) { return device.first; } @@ -192,7 +194,7 @@ int UserInputMapper::findDevice(QString name) const { QVector UserInputMapper::getDeviceNames() { Locker locker(_lock); QVector result; - for (auto device : _registeredDevices) { + for (const auto& device : _registeredDevices) { QString deviceName = device.second->_name.split(" (")[0]; result << deviceName; } @@ -218,7 +220,7 @@ Input UserInputMapper::findDeviceInput(const QString& inputName) const { const auto& device = _registeredDevices.at(deviceID); auto deviceInputs = device->getAvailableInputs(); - for (auto input : deviceInputs) { + for (const auto& input : deviceInputs) { if (input.second == inputName) { return input.first; } @@ -321,7 +323,8 @@ QVector UserInputMapper::getAllActions() const { QString UserInputMapper::getActionName(Action action) const { Locker locker(_lock); - for (auto actionPair : getActionInputs()) { + auto inputs = getActionInputs(); + for (const auto& actionPair : inputs) { if (actionPair.first.channel == toInt(action)) { return actionPair.second; } @@ -331,18 +334,20 @@ QString UserInputMapper::getActionName(Action action) const { QString UserInputMapper::getStandardPoseName(uint16_t pose) { Locker locker(_lock); - for (auto posePair : getStandardInputs()) { + auto inputs = getStandardInputs(); + for (const auto& posePair : inputs) { if (posePair.first.channel == pose && posePair.first.getType() == ChannelType::POSE) { return posePair.second; } } return QString(); -} +} QVector UserInputMapper::getActionNames() const { Locker locker(_lock); QVector result; - for (auto actionPair : getActionInputs()) { + auto inputs = getActionInputs(); + for (const auto& actionPair : inputs) { result << actionPair.second; } return result; @@ -357,7 +362,7 @@ Pose UserInputMapper::getPoseState(Action action) const { bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) { Locker locker(_lock); bool toReturn = false; - for (auto device : _registeredDevices) { + for (const auto& device : _registeredDevices) { toReturn = toReturn || device.second->triggerHapticPulse(strength, duration, hand); } return toReturn; @@ -469,7 +474,7 @@ void UserInputMapper::runMappings() { if (debugRoutes) { qCDebug(controllers) << "Beginning mapping frame"; } - for (auto endpointEntry : this->_endpointsByInput) { + for (const auto& endpointEntry : _endpointsByInput) { endpointEntry.second->reset(); } @@ -542,9 +547,9 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { } - // 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 - // and someone else wires it to CONTEXT_MENU, I don't want both to occur when + // and someone else wires it to CONTEXT_MENU, I don't want both to occur when // I press the button. The exception is if I'm wiring a control back to itself // in order to adjust my interface, like inverting the Y axis on an analog stick if (!route->peek && !source->readable()) { @@ -897,7 +902,8 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) if (value.isArray()) { // Support "when" : [ "GamePad.RB", "GamePad.LB" ] Conditional::List children; - for (auto arrayItem : value.toArray()) { + auto array = value.toArray(); + for (const auto& arrayItem : array) { Conditional::Pointer childConditional = parseConditional(arrayItem); if (!childConditional) { return Conditional::Pointer(); @@ -908,7 +914,7 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) } else if (value.isString()) { // Support "when" : "GamePad.RB" auto conditionalToken = value.toString(); - + // Detect for modifier case (Not...) QString conditionalModifier; const QString JSON_CONDITIONAL_MODIFIER_NOT("!"); @@ -943,12 +949,12 @@ Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) { result = Filter::getFactory().create(value.toString()); } else if (value.isObject()) { result = Filter::parse(value.toObject()); - } + } if (!result) { qWarning() << "Invalid filter definition " << value; } - + return result; } @@ -960,7 +966,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) { if (value.isArray()) { Filter::List result; auto filtersArray = value.toArray(); - for (auto filterValue : filtersArray) { + for (const auto& filterValue : filtersArray) { Filter::Pointer filter = parseFilter(filterValue); if (!filter) { return Filter::List(); @@ -968,7 +974,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) { result.push_back(filter); } return result; - } + } Filter::Pointer filter = parseFilter(value); if (!filter) { @@ -980,7 +986,8 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) { Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) { if (value.isArray()) { ArrayEndpoint::Pointer result = std::make_shared(); - for (auto arrayItem : value.toArray()) { + auto array = value.toArray(); + for (const auto& arrayItem : array) { Endpoint::Pointer destination = parseEndpoint(arrayItem); if (!destination) { return Endpoint::Pointer(); @@ -988,14 +995,14 @@ Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) { result->_children.push_back(destination); } return result; - } - + } + return parseEndpoint(value); } Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) { if (value.isObject()) { - auto object = value.toObject(); + auto object = value.toObject(); if (object.contains("makeAxis")) { auto axisValue = object.value("makeAxis"); if (axisValue.isArray()) { @@ -1017,7 +1024,8 @@ Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) { Endpoint::Pointer UserInputMapper::parseAny(const QJsonValue& value) { if (value.isArray()) { Endpoint::List children; - for (auto arrayItem : value.toArray()) { + auto array = value.toArray(); + for (const auto& arrayItem : array) { Endpoint::Pointer destination = parseEndpoint(arrayItem); if (!destination) { return Endpoint::Pointer(); @@ -1162,7 +1170,7 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) { template bool hasDebuggableRoute(const T& routes) { - for (auto route : routes) { + for (const auto& route : routes) { if (route->debug) { return true; } @@ -1174,7 +1182,7 @@ bool hasDebuggableRoute(const T& routes) { void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) { Locker locker(_lock); // New routes for a device get injected IN FRONT of existing routes. Routes - // are processed in order so this ensures that the standard -> action processing + // are processed in order so this ensures that the standard -> action processing // takes place after all of the hardware -> standard or hardware -> action processing // because standard -> action is the first set of routes added. Route::List standardRoutes = mapping->routes; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp index ef9f04402b..f73268b41f 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp @@ -16,11 +16,14 @@ using namespace controller; void ActionEndpoint::apply(float newValue, const Pointer& source) { - InputRecorder* inputRecorder = InputRecorder::getInstance(); auto userInputMapper = DependencyManager::get(); - QString actionName = userInputMapper->getActionName(Action(_input.getChannel())); - if(inputRecorder->isPlayingback()) { - newValue = inputRecorder->getActionState(actionName); + InputRecorder* inputRecorder = InputRecorder::getInstance(); + QString actionName; + if (inputRecorder->isPlayingback() || inputRecorder->isRecording()) { + actionName = userInputMapper->getActionName(Action(_input.getChannel())); + if (inputRecorder->isPlayingback()) { + newValue = inputRecorder->getActionState(actionName); + } } _currentValue += newValue; @@ -32,10 +35,12 @@ void ActionEndpoint::apply(float newValue, const Pointer& source) { void ActionEndpoint::apply(const Pose& value, const Pointer& source) { _currentPose = value; - InputRecorder* inputRecorder = InputRecorder::getInstance(); auto userInputMapper = DependencyManager::get(); - QString actionName = userInputMapper->getActionName(Action(_input.getChannel())); - inputRecorder->setActionState(actionName, _currentPose); + InputRecorder* inputRecorder = InputRecorder::getInstance(); + if (inputRecorder->isRecording()) { + QString actionName = userInputMapper->getActionName(Action(_input.getChannel())); + inputRecorder->setActionState(actionName, _currentPose); + } if (!_currentPose.isValid()) { return;