From 560696e41c20294c12029b2635345e0f37c597d1 Mon Sep 17 00:00:00 2001 From: vladest Date: Fri, 11 Aug 2017 20:39:17 +0200 Subject: [PATCH 01/37] Split logic and interface for HMD and desktop devices. Added CheckBox control based on QQC2 --- .../resources/qml/controls-uit/CheckBox2.qml | 111 +++++++++ interface/resources/qml/hifi/audio/Audio.qml | 234 +++++++++++++----- .../resources/qml/hifi/audio/CheckBox.qml | 4 +- interface/src/scripting/Audio.cpp | 8 +- interface/src/scripting/Audio.h | 4 +- interface/src/scripting/AudioDevices.cpp | 161 ++++++++---- interface/src/scripting/AudioDevices.h | 28 ++- 7 files changed, 436 insertions(+), 114 deletions(-) create mode 100644 interface/resources/qml/controls-uit/CheckBox2.qml diff --git a/interface/resources/qml/controls-uit/CheckBox2.qml b/interface/resources/qml/controls-uit/CheckBox2.qml new file mode 100644 index 0000000000..612e8d2662 --- /dev/null +++ b/interface/resources/qml/controls-uit/CheckBox2.qml @@ -0,0 +1,111 @@ +// +// CheckBox2.qml +// +// Created by Vlad Stelmahovsky on 10 Aug 2017 +// Copyright 2017 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 +// + +import QtQuick 2.7 +import QtQuick.Controls 2.2 + +import "../styles-uit" +import "../controls-uit" as HiFiControls + +CheckBox { + id: checkBox + + HifiConstants { id: hifi; } + + property int colorScheme: hifi.colorSchemes.light + property string color: hifi.colors.lightGrayText + readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light + property bool isRedCheck: false + property int boxSize: 14 + property int boxRadius: 3 + property bool wrap: true; + readonly property int checkSize: Math.max(boxSize - 8, 10) + readonly property int checkRadius: 2 + focusPolicy: Qt.ClickFocus + + indicator: Rectangle { + id: box + width: boxSize + height: boxSize + radius: boxRadius + x: checkBox.leftPadding + y: parent.height / 2 - height / 2 + border.width: 1 + border.color: pressed || hovered + ? hifi.colors.checkboxCheckedBorder + : (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish) + + gradient: Gradient { + GradientStop { + position: 0.2 + color: pressed || hovered + ? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart) + : (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart) + } + GradientStop { + position: 1.0 + color: pressed || hovered + ? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish) + : (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish) + } + } + + Rectangle { + visible: pressed || hovered + anchors.centerIn: parent + id: innerBox + width: checkSize - 4 + height: width + radius: checkRadius + color: hifi.colors.checkboxCheckedBorder + } + + Rectangle { + id: check + width: checkSize + height: checkSize + radius: checkRadius + anchors.centerIn: parent + color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked + border.width: 2 + border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder + visible: checked && !pressed || !checked && pressed + } + + Rectangle { + id: disabledOverlay + visible: !enabled + width: boxSize + height: boxSize + radius: boxRadius + border.width: 1 + border.color: hifi.colors.baseGrayHighlight + color: hifi.colors.baseGrayHighlight + opacity: 0.5 + } + } + + contentItem: Text { + id: root + FontLoader { id: ralewaySemiBold; source: pathToFonts + "fonts/Raleway-SemiBold.ttf"; } + font.pixelSize: hifi.fontSizes.inputLabel + font.family: ralewaySemiBold.name + text: checkBox.text + color: checkBox.color + x: 2 + wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap + elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight + enabled: checkBox.enabled + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + leftPadding: checkBox.indicator.width + checkBox.spacing + } +} + diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 93742e39a5..3d3a9ceeaa 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -12,7 +12,7 @@ // import QtQuick 2.5 -import QtQuick.Controls 1.4 +import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import "../../styles-uit" @@ -36,13 +36,27 @@ Rectangle { return (root.parent !== null) && root.parent.objectName == "loader"; } + property bool isVR: Audio.context === "VR" + //placeholder for control sizes and paddings + //recalculates dynamically in case of UI size is changed + QtObject { + id: margins + property real paddings: parent.width / 20.25 + + property real sizeCheckBox: parent.width / 13.5 + property real sizeText: parent.width / 2.5 + property real sizeLevel: parent.width / 5.8 + property real sizeDesktop: parent.width / 5.8 + property real sizeVR: parent.width / 13.5 + } + Column { y: 16; // padding does not work spacing: 16; width: parent.width; RalewayRegular { - x: 16; // padding does not work + x: margins.paddings; // padding does not work size: 16; color: "white"; text: root.title; @@ -53,8 +67,9 @@ Rectangle { Separator { visible: root.showTitle() } ColumnLayout { - x: 16; // padding does not work + x: margins.paddings; // padding does not work spacing: 16; + width: parent.width; // mute is in its own row RowLayout { @@ -93,52 +108,106 @@ Rectangle { Separator {} RowLayout { + x: margins.paddings; + width: parent.width - margins.paddings*2 + height: 28 + spacing: 0 HiFiGlyphs { + Layout.minimumWidth: margins.sizeCheckBox + Layout.maximumWidth: margins.sizeCheckBox text: hifi.glyphs.mic; color: hifi.colors.primaryHighlight; anchors.verticalCenter: parent.verticalCenter; - size: 28; + size: 36; } RalewayRegular { + Layout.minimumWidth: margins.sizeText + margins.sizeLevel + Layout.maximumWidth: margins.sizeText + margins.sizeLevel anchors.verticalCenter: parent.verticalCenter; size: 16; color: hifi.colors.lightGrayText; text: qsTr("CHOOSE INPUT DEVICE"); } + + RalewayRegular { + Layout.minimumWidth: margins.sizeDesktop + Layout.maximumWidth: margins.sizeDesktop + anchors.verticalCenter: parent.verticalCenter; + size: 16; + color: hifi.colors.lightGrayText; + text: qsTr("DESKTOP"); + } + + RalewayRegular { + Layout.minimumWidth: margins.sizeVR + Layout.maximumWidth: margins.sizeVR + Layout.alignment: Qt.AlignRight + anchors.verticalCenter: parent.verticalCenter; + size: 16; + color: hifi.colors.lightGrayText; + text: qsTr("VR"); + } } ListView { - anchors { left: parent.left; right: parent.right; leftMargin: 70 } + id: inputView + width: parent.width - margins.paddings*2 + x: margins.paddings height: 125; spacing: 0; snapMode: ListView.SnapToItem; clip: true; model: Audio.devices.input; - delegate: Item { - width: parent.width; + delegate: RowLayout { + width: inputView.width; height: 36; - + spacing: 0 + + RalewaySemiBold { + Layout.minimumWidth: margins.sizeCheckBox + margins.sizeText + Layout.maximumWidth: margins.sizeCheckBox + margins.sizeText + Layout.alignment: Qt.AlignVCenter + clip: true + size: 16; + color: "white"; + text: devicename; + } + + //placeholder for invisible level + Item { + Layout.minimumWidth: margins.sizeLevel + Layout.maximumWidth: margins.sizeLevel + Layout.alignment: Qt.AlignVCenter + height: 8; + InputLevel { + visible: (isVR && selectedHMD) || (!isVR && selectedDesktop); + anchors.fill: parent + } + } AudioControls.CheckBox { - id: checkbox - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - text: display; - wrap: false; - checked: selected; - enabled: false; + Layout.minimumWidth: margins.sizeDesktop + Layout.maximumWidth: margins.sizeDesktop + leftPadding: margins.sizeDesktop - implicitWidth/2 + Layout.alignment: Qt.AlignCenter + checked: selectedDesktop; + onClicked: { + if (checked) { + Audio.setInputDevice(info, false); + } + } } - MouseArea { - anchors.fill: checkbox - onClicked: Audio.setInputDevice(info); - } - - InputLevel { - id: level; - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 30 - visible: selected; + AudioControls.CheckBox { + Layout.minimumWidth: margins.sizeVR + Layout.maximumWidth: margins.sizeVR + Layout.alignment: Qt.AlignCenter + leftPadding: margins.sizeVR - implicitWidth/2 + checked: selectedHMD; + onClicked: { + if (checked) { + Audio.setInputDevice(info, true); + } + } } } } @@ -146,51 +215,104 @@ Rectangle { Separator {} RowLayout { - Column { - RowLayout { - HiFiGlyphs { - text: hifi.glyphs.unmuted; - color: hifi.colors.primaryHighlight; - anchors.verticalCenter: parent.verticalCenter; - size: 36; - } - RalewayRegular { - anchors.verticalCenter: parent.verticalCenter; - size: 16; - color: hifi.colors.lightGrayText; - text: qsTr("CHOOSE OUTPUT DEVICE"); - } - } + x: margins.paddings; + width: parent.width - margins.paddings*2 + height: 28 + spacing: 0 + HiFiGlyphs { + Layout.minimumWidth: margins.sizeCheckBox + Layout.maximumWidth: margins.sizeCheckBox + text: hifi.glyphs.unmuted; + color: hifi.colors.primaryHighlight; + anchors.verticalCenter: parent.verticalCenter; + size: 28; + } + RalewayRegular { + Layout.minimumWidth: margins.sizeText + margins.sizeLevel + Layout.maximumWidth: margins.sizeText + margins.sizeLevel + anchors.verticalCenter: parent.verticalCenter; + size: 16; + color: hifi.colors.lightGrayText; + text: qsTr("CHOOSE OUTPUT DEVICE"); + } - PlaySampleSound { anchors { left: parent.left; leftMargin: 60 }} + RalewayRegular { + Layout.minimumWidth: margins.sizeDesktop + Layout.maximumWidth: margins.sizeDesktop + anchors.verticalCenter: parent.verticalCenter; + size: 16; + color: hifi.colors.lightGrayText; + text: qsTr("DESKTOP"); + } + + RalewayRegular { + Layout.minimumWidth: margins.sizeVR + Layout.maximumWidth: margins.sizeVR + Layout.alignment: Qt.AlignRight + anchors.verticalCenter: parent.verticalCenter; + size: 16; + color: hifi.colors.lightGrayText; + text: qsTr("VR"); } } ListView { - anchors { left: parent.left; right: parent.right; leftMargin: 70 } - height: Math.min(250, contentHeight); + id: outputView + width: parent.width - margins.paddings*2 + x: margins.paddings + height: Math.min(220, contentHeight); spacing: 0; snapMode: ListView.SnapToItem; clip: true; model: Audio.devices.output; - delegate: Item { - width: parent.width; + delegate: RowLayout { + width: inputView.width; height: 36; + spacing: 0 - AudioControls.CheckBox { - id: checkbox - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - text: display; - checked: selected; - enabled: false; + RalewaySemiBold { + Layout.minimumWidth: margins.sizeCheckBox + margins.sizeText + Layout.maximumWidth: margins.sizeCheckBox + margins.sizeText + Layout.alignment: Qt.AlignVCenter + clip: true + size: 16; + color: "white"; + text: devicename; } - MouseArea { - anchors.fill: checkbox - onClicked: Audio.setOutputDevice(info); + //placeholder for invisible level + Item { + Layout.minimumWidth: margins.sizeLevel + Layout.maximumWidth: margins.sizeLevel + Layout.alignment: Qt.AlignVCenter + height: 8; + } + AudioControls.CheckBox { + Layout.minimumWidth: margins.sizeDesktop + Layout.maximumWidth: margins.sizeDesktop + leftPadding: margins.sizeDesktop - implicitWidth/2 + Layout.alignment: Qt.AlignCenter + checked: selectedDesktop; + onClicked: { + if (checked) { + Audio.setOutputDevice(info, false); + } + } + } + AudioControls.CheckBox { + Layout.minimumWidth: margins.sizeVR + Layout.maximumWidth: margins.sizeVR + Layout.alignment: Qt.AlignCenter + leftPadding: margins.sizeVR - implicitWidth/2 + checked: selectedHMD; + onClicked: { + if (checked) { + Audio.setOutputDevice(info, true); + } + } } } } + PlaySampleSound { anchors { left: parent.left; leftMargin: margins.paddings }} } } diff --git a/interface/resources/qml/hifi/audio/CheckBox.qml b/interface/resources/qml/hifi/audio/CheckBox.qml index 1f632ac479..77c001816f 100644 --- a/interface/resources/qml/hifi/audio/CheckBox.qml +++ b/interface/resources/qml/hifi/audio/CheckBox.qml @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -import QtQuick 2.5 +import QtQuick 2.7 import "../../controls-uit" as HifiControls -HifiControls.CheckBox { +HifiControls.CheckBox2 { color: "white" } diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 9719c23885..f9c1a95fb5 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -135,10 +135,10 @@ void Audio::setReverbOptions(const AudioEffectOptions* options) { DependencyManager::get()->setReverbOptions(options); } -void Audio::setInputDevice(const QAudioDeviceInfo& device) { - _devices.chooseInputDevice(device); +void Audio::setInputDevice(const QAudioDeviceInfo& device, bool isHMD) { + _devices.chooseInputDevice(device, isHMD); } -void Audio::setOutputDevice(const QAudioDeviceInfo& device) { - _devices.chooseOutputDevice(device); +void Audio::setOutputDevice(const QAudioDeviceInfo& device, bool isHMD) { + _devices.chooseOutputDevice(device, isHMD); } diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index bd40de4303..abd2312cf0 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -50,8 +50,8 @@ public: void showMicMeter(bool show); void setInputVolume(float volume); - Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device); - Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device); + Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device, bool isHMD); + Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device, bool isHMD); Q_INVOKABLE void setReverb(bool enable); Q_INVOKABLE void setReverbOptions(const AudioEffectOptions* options); diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index f2e6dbf4d7..e31641389c 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -53,22 +53,28 @@ static QString getTargetDevice(bool hmd, QAudio::Mode mode) { } QHash AudioDeviceList::_roles { - { Qt::DisplayRole, "display" }, - { Qt::CheckStateRole, "selected" }, - { Qt::UserRole, "info" } + { AudioDeviceList::DeviceNameRole, "devicename" }, + { AudioDeviceList::SelectedDesktopRole, "selectedDesktop" }, + { AudioDeviceList::SelectedHMDRole, "selectedHMD" }, + { AudioDeviceList::DeviceInfoRole, "info" } }; + Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled }; +AudioDeviceList::AudioDeviceList(QAudio::Mode mode) : _mode(mode) {} + QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() >= _devices.size()) { return QVariant(); } - if (role == Qt::DisplayRole) { + if (role == DeviceNameRole) { return _devices.at(index.row()).display; - } else if (role == Qt::CheckStateRole) { - return _devices.at(index.row()).selected; - } else if (role == Qt::UserRole) { + } else if (role == SelectedDesktopRole) { + return _devices.at(index.row()).selectedDesktop; + } else if (role == SelectedHMDRole) { + return _devices.at(index.row()).selectedHMD; + } else if (role == DeviceInfoRole) { return QVariant::fromValue(_devices.at(index.row()).info); } else { return QVariant(); @@ -109,36 +115,47 @@ void AudioDeviceList::resetDevice(bool contextIsHMD) { #endif } -void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) { - auto oldDevice = _selectedDevice; - _selectedDevice = device; +void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD) { + auto oldDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; + QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; + selectedDevice = device; for (auto i = 0; i < _devices.size(); ++i) { AudioDevice& device = _devices[i]; - if (device.selected && device.info != _selectedDevice) { - device.selected = false; - } else if (device.info == _selectedDevice) { - device.selected = true; + bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; + if (isSelected && device.info != selectedDevice) { + isSelected = false; + } else if (device.info == selectedDevice) { + isSelected = true; } } - emit deviceChanged(_selectedDevice); + emit deviceChanged(selectedDevice); emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); } -void AudioDeviceList::onDevicesChanged(const QList& devices) { +void AudioDeviceList::onDevicesChanged(const QList& devices, bool isHMD) { + QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; + + const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName; beginResetModel(); _devices.clear(); foreach(const QAudioDeviceInfo& deviceInfo, devices) { AudioDevice device; + bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; device.info = deviceInfo; device.display = device.info.deviceName() .replace("High Definition", "HD") .remove("Device") .replace(" )", ")"); - device.selected = (device.info == _selectedDevice); + if (!selectedDevice.isNull()) { + isSelected = (device.info == selectedDevice); + } else { + //no selected device for context. fallback to saved + isSelected = (device.info.deviceName() == savedDeviceName); + } _devices.push_back(device); } @@ -151,11 +168,18 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { connect(client.data(), &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection); connect(client.data(), &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection); + _inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput), contextIsHMD); + _outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput), contextIsHMD); + // connections are made after client is initialized, so we must also fetch the devices - _inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput)); - _outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput)); - _inputs.onDevicesChanged(client->getAudioDevices(QAudio::AudioInput)); - _outputs.onDevicesChanged(client->getAudioDevices(QAudio::AudioOutput)); + const QList& devicesInput = client->getAudioDevices(QAudio::AudioInput); + const QList& devicesOutput = client->getAudioDevices(QAudio::AudioOutput); + //setup HMD devices + _inputs.onDevicesChanged(devicesInput, true); + _outputs.onDevicesChanged(devicesOutput, true); + //setup Desktop devices + _inputs.onDevicesChanged(devicesInput, false); + _outputs.onDevicesChanged(devicesOutput, false); } void AudioDevices::onContextChanged(const QString& context) { @@ -163,10 +187,11 @@ void AudioDevices::onContextChanged(const QString& context) { _outputs.resetDevice(_contextIsHMD); } -void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { +void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, + const QAudioDeviceInfo& previousDevice, bool isHMD) { QString deviceName = device.isNull() ? QString() : device.deviceName(); - auto& setting = getSetting(_contextIsHMD, mode); + auto& setting = getSetting(isHMD, mode); // check for a previous device auto wasDefault = setting.get().isNull(); @@ -202,42 +227,94 @@ void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& d void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device) { if (mode == QAudio::AudioInput) { if (_requestedInputDevice == device) { - onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); + onDeviceSelected(QAudio::AudioInput, device, + _contextIsHMD ? _inputs._selectedHMDDevice : _inputs._selectedDesktopDevice, + _contextIsHMD); _requestedInputDevice = QAudioDeviceInfo(); } - _inputs.onDeviceChanged(device); + _inputs.onDeviceChanged(device, _contextIsHMD); } else { // if (mode == QAudio::AudioOutput) if (_requestedOutputDevice == device) { - onDeviceSelected(QAudio::AudioOutput, device, _outputs._selectedDevice); + onDeviceSelected(QAudio::AudioOutput, device, + _contextIsHMD ? _outputs._selectedHMDDevice : _outputs._selectedDesktopDevice, + _contextIsHMD); _requestedOutputDevice = QAudioDeviceInfo(); } - _outputs.onDeviceChanged(device); + _outputs.onDeviceChanged(device, _contextIsHMD); } } void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList& devices) { static std::once_flag once; + std::call_once(once, [&] { + //readout settings + auto client = DependencyManager::get(); + + _inputs._hmdSavedDeviceName = getTargetDevice(true, QAudio::AudioInput); + _inputs._desktopSavedDeviceName = getTargetDevice(false, QAudio::AudioInput); + + //fallback to default device + if (_inputs._desktopSavedDeviceName.isEmpty()) { + _inputs._desktopSavedDeviceName = client->getActiveAudioDevice(QAudio::AudioInput).deviceName(); + } + //fallback to desktop device + if (_inputs._hmdSavedDeviceName.isEmpty()) { + _inputs._hmdSavedDeviceName = _inputs._desktopSavedDeviceName; + } + + _outputs._hmdSavedDeviceName = getTargetDevice(true, QAudio::AudioOutput); + _outputs._desktopSavedDeviceName = getTargetDevice(false, QAudio::AudioOutput); + + if (_outputs._desktopSavedDeviceName.isEmpty()) { + _outputs._desktopSavedDeviceName = client->getActiveAudioDevice(QAudio::AudioOutput).deviceName(); + } + if (_outputs._hmdSavedDeviceName.isEmpty()) { + _outputs._hmdSavedDeviceName = _outputs._desktopSavedDeviceName; + } + onContextChanged(QString()); + }); + + //set devices for both contexts if (mode == QAudio::AudioInput) { - _inputs.onDevicesChanged(devices); + _inputs.onDevicesChanged(devices, _contextIsHMD); + _inputs.onDevicesChanged(devices, !_contextIsHMD); } else { // if (mode == QAudio::AudioOutput) - _outputs.onDevicesChanged(devices); + _outputs.onDevicesChanged(devices, _contextIsHMD); + _outputs.onDevicesChanged(devices, !_contextIsHMD); } - std::call_once(once, [&] { onContextChanged(QString()); }); } -void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device) { - auto client = DependencyManager::get(); - _requestedInputDevice = device; - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Q_ARG(QAudio::Mode, QAudio::AudioInput), - Q_ARG(const QAudioDeviceInfo&, device)); +void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD) { + //check if current context equals device to change + if (_contextIsHMD == isHMD) { + auto client = DependencyManager::get(); + _requestedInputDevice = device; + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Q_ARG(QAudio::Mode, QAudio::AudioInput), + Q_ARG(const QAudioDeviceInfo&, device)); + } else { + //context is different. just save device in settings + onDeviceSelected(QAudio::AudioInput, device, + isHMD ? _inputs._selectedHMDDevice : _inputs._selectedDesktopDevice, + isHMD); + _inputs.onDeviceChanged(device, isHMD); + } } -void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device) { - auto client = DependencyManager::get(); - _requestedOutputDevice = device; - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Q_ARG(QAudio::Mode, QAudio::AudioOutput), - Q_ARG(const QAudioDeviceInfo&, device)); +void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD) { + //check if current context equals device to change + if (_contextIsHMD == isHMD) { + auto client = DependencyManager::get(); + _requestedOutputDevice = device; + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Q_ARG(QAudio::Mode, QAudio::AudioOutput), + Q_ARG(const QAudioDeviceInfo&, device)); + } else { + //context is different. just save device in settings + onDeviceSelected(QAudio::AudioOutput, device, + isHMD ? _outputs._selectedHMDDevice : _outputs._selectedDesktopDevice, + isHMD); + _outputs.onDeviceChanged(device, isHMD); + } } diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index 3278a53374..5399123329 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -22,14 +22,22 @@ class AudioDevice { public: QAudioDeviceInfo info; QString display; - bool selected { false }; + bool selectedDesktop { false }; + bool selectedHMD { false }; }; class AudioDeviceList : public QAbstractListModel { Q_OBJECT + enum AudioDeviceRoles { + DeviceNameRole = Qt::UserRole + 1, + SelectedDesktopRole, + SelectedHMDRole, + DeviceInfoRole + }; + public: - AudioDeviceList(QAudio::Mode mode) : _mode(mode) {} + AudioDeviceList(QAudio::Mode mode); int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return _devices.size(); } QHash roleNames() const override { return _roles; } @@ -45,8 +53,8 @@ signals: void deviceChanged(const QAudioDeviceInfo& device); private slots: - void onDeviceChanged(const QAudioDeviceInfo& device); - void onDevicesChanged(const QList& devices); + void onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD); + void onDevicesChanged(const QList& devices, bool isHMD); private: friend class AudioDevices; @@ -54,8 +62,11 @@ private: static QHash _roles; static Qt::ItemFlags _flags; const QAudio::Mode _mode; - QAudioDeviceInfo _selectedDevice; + QAudioDeviceInfo _selectedDesktopDevice; + QAudioDeviceInfo _selectedHMDDevice; QList _devices; + QString _hmdSavedDeviceName; + QString _desktopSavedDeviceName; }; class Audio; @@ -67,15 +78,16 @@ class AudioDevices : public QObject { public: AudioDevices(bool& contextIsHMD); - void chooseInputDevice(const QAudioDeviceInfo& device); - void chooseOutputDevice(const QAudioDeviceInfo& device); + void chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD); + void chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD); signals: void nop(); private slots: void onContextChanged(const QString& context); - void onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice); + void onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, + const QAudioDeviceInfo& previousDevice, bool isHMD); void onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device); void onDevicesChanged(QAudio::Mode mode, const QList& devices); From b22745d57a90df73b54f8d967e04c0f3fd6d92f4 Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 12 Aug 2017 12:52:35 +0200 Subject: [PATCH 02/37] Fix binding loops --- .../resources/qml/controls-uit/CheckBox2.qml | 4 +-- interface/resources/qml/hifi/audio/Audio.qml | 30 +++++++------------ 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox2.qml b/interface/resources/qml/controls-uit/CheckBox2.qml index 612e8d2662..ffdb85c1a1 100644 --- a/interface/resources/qml/controls-uit/CheckBox2.qml +++ b/interface/resources/qml/controls-uit/CheckBox2.qml @@ -32,8 +32,8 @@ CheckBox { indicator: Rectangle { id: box - width: boxSize - height: boxSize + implicitWidth: boxSize + implicitHeight: boxSize radius: boxRadius x: checkBox.leftPadding y: parent.height / 2 - height / 2 diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 3d3a9ceeaa..aa2e0e32d5 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -41,13 +41,13 @@ Rectangle { //recalculates dynamically in case of UI size is changed QtObject { id: margins - property real paddings: parent.width / 20.25 + property real paddings: root.width / 20.25 - property real sizeCheckBox: parent.width / 13.5 - property real sizeText: parent.width / 2.5 - property real sizeLevel: parent.width / 5.8 - property real sizeDesktop: parent.width / 5.8 - property real sizeVR: parent.width / 13.5 + property real sizeCheckBox: root.width / 13.5 + property real sizeText: root.width / 2.5 + property real sizeLevel: root.width / 5.8 + property real sizeDesktop: root.width / 5.8 + property real sizeVR: root.width / 13.5 } Column { @@ -166,7 +166,6 @@ Rectangle { RalewaySemiBold { Layout.minimumWidth: margins.sizeCheckBox + margins.sizeText Layout.maximumWidth: margins.sizeCheckBox + margins.sizeText - Layout.alignment: Qt.AlignVCenter clip: true size: 16; color: "white"; @@ -177,7 +176,6 @@ Rectangle { Item { Layout.minimumWidth: margins.sizeLevel Layout.maximumWidth: margins.sizeLevel - Layout.alignment: Qt.AlignVCenter height: 8; InputLevel { visible: (isVR && selectedHMD) || (!isVR && selectedDesktop); @@ -187,8 +185,7 @@ Rectangle { AudioControls.CheckBox { Layout.minimumWidth: margins.sizeDesktop Layout.maximumWidth: margins.sizeDesktop - leftPadding: margins.sizeDesktop - implicitWidth/2 - Layout.alignment: Qt.AlignCenter + leftPadding: margins.sizeDesktop/2 - boxSize/2 checked: selectedDesktop; onClicked: { if (checked) { @@ -200,8 +197,7 @@ Rectangle { AudioControls.CheckBox { Layout.minimumWidth: margins.sizeVR Layout.maximumWidth: margins.sizeVR - Layout.alignment: Qt.AlignCenter - leftPadding: margins.sizeVR - implicitWidth/2 + leftPadding: margins.sizeVR/2 - boxSize/2 checked: selectedHMD; onClicked: { if (checked) { @@ -266,14 +262,13 @@ Rectangle { clip: true; model: Audio.devices.output; delegate: RowLayout { - width: inputView.width; + width: outputView.width; height: 36; spacing: 0 RalewaySemiBold { Layout.minimumWidth: margins.sizeCheckBox + margins.sizeText Layout.maximumWidth: margins.sizeCheckBox + margins.sizeText - Layout.alignment: Qt.AlignVCenter clip: true size: 16; color: "white"; @@ -284,14 +279,12 @@ Rectangle { Item { Layout.minimumWidth: margins.sizeLevel Layout.maximumWidth: margins.sizeLevel - Layout.alignment: Qt.AlignVCenter height: 8; } AudioControls.CheckBox { Layout.minimumWidth: margins.sizeDesktop Layout.maximumWidth: margins.sizeDesktop - leftPadding: margins.sizeDesktop - implicitWidth/2 - Layout.alignment: Qt.AlignCenter + leftPadding: margins.sizeDesktop/2 - boxSize/2 checked: selectedDesktop; onClicked: { if (checked) { @@ -302,8 +295,7 @@ Rectangle { AudioControls.CheckBox { Layout.minimumWidth: margins.sizeVR Layout.maximumWidth: margins.sizeVR - Layout.alignment: Qt.AlignCenter - leftPadding: margins.sizeVR - implicitWidth/2 + leftPadding: margins.sizeVR/2 - boxSize/2 checked: selectedHMD; onClicked: { if (checked) { From d6c426d064b5313965369dade6504f8968680d26 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 17 Aug 2017 17:17:02 +0200 Subject: [PATCH 03/37] Reworking according new design --- .../resources/qml/controls-uit/CheckBox2.qml | 1 - interface/resources/qml/hifi/audio/Audio.qml | 154 +++++------------- 2 files changed, 37 insertions(+), 118 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox2.qml b/interface/resources/qml/controls-uit/CheckBox2.qml index ffdb85c1a1..7bd69f0b19 100644 --- a/interface/resources/qml/controls-uit/CheckBox2.qml +++ b/interface/resources/qml/controls-uit/CheckBox2.qml @@ -103,7 +103,6 @@ CheckBox { wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight enabled: checkBox.enabled - horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter leftPadding: checkBox.indicator.width + checkBox.spacing } diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index aa2e0e32d5..fa34ffb6d1 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -50,21 +50,38 @@ Rectangle { property real sizeVR: root.width / 13.5 } + TabBar { + id: bar + spacing: 0 + width: parent.width + height: 36 + + AudioControls.AudioTabButton { + height: parent.height + text: qsTr("Desktop") + } + AudioControls.AudioTabButton { + height: parent.height + text: qsTr("VR") + } + } + Column { - y: 16; // padding does not work - spacing: 16; + spacing: 12; + anchors.topMargin: 8 + anchors.top: bar.bottom + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 width: parent.width; RalewayRegular { - x: margins.paddings; // padding does not work + x: margins.paddings; size: 16; color: "white"; - text: root.title; - - visible: root.showTitle(); + text: qsTr("Mic Settings") } - Separator { visible: root.showTitle() } + Separator { } ColumnLayout { x: margins.paddings; // padding does not work @@ -128,80 +145,29 @@ Rectangle { color: hifi.colors.lightGrayText; text: qsTr("CHOOSE INPUT DEVICE"); } - - RalewayRegular { - Layout.minimumWidth: margins.sizeDesktop - Layout.maximumWidth: margins.sizeDesktop - anchors.verticalCenter: parent.verticalCenter; - size: 16; - color: hifi.colors.lightGrayText; - text: qsTr("DESKTOP"); - } - - RalewayRegular { - Layout.minimumWidth: margins.sizeVR - Layout.maximumWidth: margins.sizeVR - Layout.alignment: Qt.AlignRight - anchors.verticalCenter: parent.verticalCenter; - size: 16; - color: hifi.colors.lightGrayText; - text: qsTr("VR"); - } } ListView { id: inputView width: parent.width - margins.paddings*2 x: margins.paddings - height: 125; - spacing: 0; + height: 145; + spacing: 4; snapMode: ListView.SnapToItem; clip: true; model: Audio.devices.input; delegate: RowLayout { width: inputView.width; - height: 36; spacing: 0 - RalewaySemiBold { - Layout.minimumWidth: margins.sizeCheckBox + margins.sizeText - Layout.maximumWidth: margins.sizeCheckBox + margins.sizeText - clip: true - size: 16; - color: "white"; - text: devicename; - } - - //placeholder for invisible level - Item { - Layout.minimumWidth: margins.sizeLevel - Layout.maximumWidth: margins.sizeLevel - height: 8; - InputLevel { - visible: (isVR && selectedHMD) || (!isVR && selectedDesktop); - anchors.fill: parent - } - } AudioControls.CheckBox { - Layout.minimumWidth: margins.sizeDesktop - Layout.maximumWidth: margins.sizeDesktop - leftPadding: margins.sizeDesktop/2 - boxSize/2 - checked: selectedDesktop; + Layout.fillWidth: true + checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; + boxRadius: boxSize/2 + text: devicename onClicked: { if (checked) { - Audio.setInputDevice(info, false); - } - } - } - - AudioControls.CheckBox { - Layout.minimumWidth: margins.sizeVR - Layout.maximumWidth: margins.sizeVR - leftPadding: margins.sizeVR/2 - boxSize/2 - checked: selectedHMD; - onClicked: { - if (checked) { - Audio.setInputDevice(info, true); + Audio.setInputDevice(info, bar.currentIndex === 1); } } } @@ -231,25 +197,6 @@ Rectangle { color: hifi.colors.lightGrayText; text: qsTr("CHOOSE OUTPUT DEVICE"); } - - RalewayRegular { - Layout.minimumWidth: margins.sizeDesktop - Layout.maximumWidth: margins.sizeDesktop - anchors.verticalCenter: parent.verticalCenter; - size: 16; - color: hifi.colors.lightGrayText; - text: qsTr("DESKTOP"); - } - - RalewayRegular { - Layout.minimumWidth: margins.sizeVR - Layout.maximumWidth: margins.sizeVR - Layout.alignment: Qt.AlignRight - anchors.verticalCenter: parent.verticalCenter; - size: 16; - color: hifi.colors.lightGrayText; - text: qsTr("VR"); - } } ListView { @@ -257,49 +204,22 @@ Rectangle { width: parent.width - margins.paddings*2 x: margins.paddings height: Math.min(220, contentHeight); - spacing: 0; + spacing: 4; snapMode: ListView.SnapToItem; clip: true; model: Audio.devices.output; delegate: RowLayout { width: outputView.width; - height: 36; spacing: 0 - RalewaySemiBold { - Layout.minimumWidth: margins.sizeCheckBox + margins.sizeText - Layout.maximumWidth: margins.sizeCheckBox + margins.sizeText - clip: true - size: 16; - color: "white"; - text: devicename; - } - - //placeholder for invisible level - Item { - Layout.minimumWidth: margins.sizeLevel - Layout.maximumWidth: margins.sizeLevel - height: 8; - } AudioControls.CheckBox { - Layout.minimumWidth: margins.sizeDesktop - Layout.maximumWidth: margins.sizeDesktop - leftPadding: margins.sizeDesktop/2 - boxSize/2 - checked: selectedDesktop; + Layout.fillWidth: true + boxRadius: boxSize/2 + checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; + text: devicename onClicked: { if (checked) { - Audio.setOutputDevice(info, false); - } - } - } - AudioControls.CheckBox { - Layout.minimumWidth: margins.sizeVR - Layout.maximumWidth: margins.sizeVR - leftPadding: margins.sizeVR/2 - boxSize/2 - checked: selectedHMD; - onClicked: { - if (checked) { - Audio.setOutputDevice(info, true); + Audio.setOutputDevice(info, bar.currentIndex === 1); } } } From f77b913a143edeac05b8987cb8b2aa225cb9f0ca Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 17 Aug 2017 20:55:00 +0200 Subject: [PATCH 04/37] Added input meter --- interface/resources/qml/hifi/audio/Audio.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index fa34ffb6d1..dfecfbb50f 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -158,7 +158,7 @@ Rectangle { model: Audio.devices.input; delegate: RowLayout { width: inputView.width; - spacing: 0 + spacing: 5 AudioControls.CheckBox { Layout.fillWidth: true @@ -171,6 +171,10 @@ Rectangle { } } } + InputLevel { + visible: (bar.currentIndex === 1 && selectedHMD && isVR) || + (bar.currentIndex === 0 && selectedDesktop && !isVR); + } } } From 855f9d8a950481d6b583129b8ff50c09a2b35766 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 17 Aug 2017 21:47:48 +0200 Subject: [PATCH 05/37] Missed qml file added --- .../qml/hifi/audio/AudioTabButton.qml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 interface/resources/qml/hifi/audio/AudioTabButton.qml diff --git a/interface/resources/qml/hifi/audio/AudioTabButton.qml b/interface/resources/qml/hifi/audio/AudioTabButton.qml new file mode 100644 index 0000000000..bf50f1ba26 --- /dev/null +++ b/interface/resources/qml/hifi/audio/AudioTabButton.qml @@ -0,0 +1,34 @@ +// +// AudioTabButton.qml +// qml/hifi/audio +// +// Created by Vlad Stelmahovsky on 8/16/2017 +// Copyright 2017 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 +// + +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import "../../controls-uit" as HifiControls +import "../../styles-uit" + +TabButton { + id: control + + HifiConstants { id: hifi; } + + contentItem: Text { + text: control.text + font: control.font + color: "white" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + background: Rectangle { + color: control.checked ? hifi.colors.baseGray : "black" + } +} From 6f0229f450538496b63087ecb096c695596d9828 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 22 Aug 2017 23:26:27 +0200 Subject: [PATCH 06/37] Reworked according to designers request. Do not fall back to default audion output --- .../resources/qml/controls-uit/CheckBox2.qml | 5 +- interface/resources/qml/hifi/audio/Audio.qml | 74 +++++++++++-------- .../qml/hifi/audio/AudioTabButton.qml | 1 + .../resources/qml/hifi/audio/CheckBox.qml | 1 + libraries/audio-client/src/AudioClient.cpp | 8 -- 5 files changed, 47 insertions(+), 42 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox2.qml b/interface/resources/qml/controls-uit/CheckBox2.qml index 7bd69f0b19..f845d24868 100644 --- a/interface/resources/qml/controls-uit/CheckBox2.qml +++ b/interface/resources/qml/controls-uit/CheckBox2.qml @@ -23,11 +23,12 @@ CheckBox { property string color: hifi.colors.lightGrayText readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light property bool isRedCheck: false + property bool isRound: false property int boxSize: 14 - property int boxRadius: 3 + property int boxRadius: isRound ? boxSize : 3 property bool wrap: true; readonly property int checkSize: Math.max(boxSize - 8, 10) - readonly property int checkRadius: 2 + readonly property int checkRadius: isRound ? checkSize / 2 : 2 focusPolicy: Qt.ClickFocus indicator: Rectangle { diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index dfecfbb50f..ed4a74b86f 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -37,6 +37,7 @@ Rectangle { } property bool isVR: Audio.context === "VR" + property real rightMostInputLevelPos: 0 //placeholder for control sizes and paddings //recalculates dynamically in case of UI size is changed QtObject { @@ -54,7 +55,7 @@ Rectangle { id: bar spacing: 0 width: parent.width - height: 36 + height: 42 AudioControls.AudioTabButton { height: parent.height @@ -68,21 +69,20 @@ Rectangle { Column { spacing: 12; - anchors.topMargin: 8 anchors.top: bar.bottom anchors.bottom: parent.bottom anchors.bottomMargin: 5 width: parent.width; + Separator { } + RalewayRegular { - x: margins.paddings; + x: margins.paddings + margins.sizeCheckBox; size: 16; color: "white"; - text: qsTr("Mic Settings") + text: qsTr("Input Device Settings") } - Separator { } - ColumnLayout { x: margins.paddings; // padding does not work spacing: 16; @@ -118,28 +118,27 @@ Rectangle { AvatarInputs.showAudioTools = checked; checked = Qt.binding(function() { return AvatarInputs.showAudioTools; }); // restore binding } + onXChanged: rightMostInputLevelPos = x + width } } } Separator {} - RowLayout { + Row { x: margins.paddings; width: parent.width - margins.paddings*2 height: 28 spacing: 0 HiFiGlyphs { - Layout.minimumWidth: margins.sizeCheckBox - Layout.maximumWidth: margins.sizeCheckBox + width: margins.sizeCheckBox text: hifi.glyphs.mic; color: hifi.colors.primaryHighlight; anchors.verticalCenter: parent.verticalCenter; - size: 36; + size: 30; } RalewayRegular { - Layout.minimumWidth: margins.sizeText + margins.sizeLevel - Layout.maximumWidth: margins.sizeText + margins.sizeLevel + width: margins.sizeText + margins.sizeLevel anchors.verticalCenter: parent.verticalCenter; size: 16; color: hifi.colors.lightGrayText; @@ -151,19 +150,22 @@ Rectangle { id: inputView width: parent.width - margins.paddings*2 x: margins.paddings - height: 145; + height: 150 spacing: 4; snapMode: ListView.SnapToItem; clip: true; model: Audio.devices.input; - delegate: RowLayout { - width: inputView.width; - spacing: 5 + delegate: Item { + width: rightMostInputLevelPos + height: margins.sizeCheckBox AudioControls.CheckBox { - Layout.fillWidth: true + anchors.left: parent.left + width: parent.width - inputLevel.width + clip: true checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; - boxRadius: boxSize/2 + boxSize: margins.sizeCheckBox / 2 + isRound: true text: devicename onClicked: { if (checked) { @@ -172,6 +174,9 @@ Rectangle { } } InputLevel { + id: inputLevel + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter visible: (bar.currentIndex === 1 && selectedHMD && isVR) || (bar.currentIndex === 0 && selectedDesktop && !isVR); } @@ -180,22 +185,20 @@ Rectangle { Separator {} - RowLayout { + Row { x: margins.paddings; width: parent.width - margins.paddings*2 - height: 28 + height: 36 spacing: 0 HiFiGlyphs { - Layout.minimumWidth: margins.sizeCheckBox - Layout.maximumWidth: margins.sizeCheckBox + width: margins.sizeCheckBox text: hifi.glyphs.unmuted; color: hifi.colors.primaryHighlight; anchors.verticalCenter: parent.verticalCenter; - size: 28; + size: 36; } RalewayRegular { - Layout.minimumWidth: margins.sizeText + margins.sizeLevel - Layout.maximumWidth: margins.sizeText + margins.sizeLevel + width: margins.sizeText + margins.sizeLevel anchors.verticalCenter: parent.verticalCenter; size: 16; color: hifi.colors.lightGrayText; @@ -207,18 +210,19 @@ Rectangle { id: outputView width: parent.width - margins.paddings*2 x: margins.paddings - height: Math.min(220, contentHeight); + height: Math.min(210, contentHeight); spacing: 4; snapMode: ListView.SnapToItem; clip: true; model: Audio.devices.output; - delegate: RowLayout { - width: outputView.width; - spacing: 0 + delegate: Item { + width: rightMostInputLevelPos + height: margins.sizeCheckBox AudioControls.CheckBox { - Layout.fillWidth: true - boxRadius: boxSize/2 + width: parent.width + boxSize: margins.sizeCheckBox / 2 + isRound: true checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; text: devicename onClicked: { @@ -229,6 +233,12 @@ Rectangle { } } } - PlaySampleSound { anchors { left: parent.left; leftMargin: margins.paddings }} + PlaySampleSound { + x: margins.paddings + + visible: (bar.currentIndex === 1 && isVR) || + (bar.currentIndex === 0 && !isVR); + anchors { left: parent.left; leftMargin: margins.paddings } + } } } diff --git a/interface/resources/qml/hifi/audio/AudioTabButton.qml b/interface/resources/qml/hifi/audio/AudioTabButton.qml index bf50f1ba26..2e6e114039 100644 --- a/interface/resources/qml/hifi/audio/AudioTabButton.qml +++ b/interface/resources/qml/hifi/audio/AudioTabButton.qml @@ -16,6 +16,7 @@ import "../../styles-uit" TabButton { id: control + font.pixelSize: height / 2 HifiConstants { id: hifi; } diff --git a/interface/resources/qml/hifi/audio/CheckBox.qml b/interface/resources/qml/hifi/audio/CheckBox.qml index 77c001816f..806f08f439 100644 --- a/interface/resources/qml/hifi/audio/CheckBox.qml +++ b/interface/resources/qml/hifi/audio/CheckBox.qml @@ -14,5 +14,6 @@ import QtQuick 2.7 import "../../controls-uit" as HifiControls HifiControls.CheckBox2 { + spacing: 8 color: "white" } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 27bab687d5..b8f1bd876d 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1717,14 +1717,6 @@ int AudioClient::setOutputBufferSize(int numFrames, bool persist) { if (persist) { _outputBufferSizeFrames.set(numFrames); } - - if (_audioOutput) { - // The buffer size can't be adjusted after QAudioOutput::start() has been called, so - // recreate the device by switching to the default. - QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); - qCDebug(audioclient) << __FUNCTION__ << "about to send changeDevice signal outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]"; - emit changeDevice(outputDeviceInfo); // On correct thread, please, as setOutputBufferSize can be called from main thread. - } } return numFrames; } From f7a704d9f43468cdf4958f9a010d47e79ebdc3b4 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 22 Aug 2017 23:33:09 +0200 Subject: [PATCH 07/37] Added current tab selection according to context --- interface/resources/qml/hifi/audio/Audio.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index ed4a74b86f..e80f278323 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -56,6 +56,7 @@ Rectangle { spacing: 0 width: parent.width height: 42 + currentIndex: isVR ? 1 : 0 AudioControls.AudioTabButton { height: parent.height From d4332e7776faa5081a1a86e5de697e509b066a04 Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 26 Aug 2017 20:55:16 +0200 Subject: [PATCH 08/37] Adopting according comments from designers --- .../resources/qml/controls-uit/CheckBox2.qml | 2 ++ interface/resources/qml/hifi/audio/Audio.qml | 34 ++++++++++++++----- .../qml/hifi/audio/AudioTabButton.qml | 2 +- .../resources/qml/hifi/audio/CheckBox.qml | 1 - .../resources/qml/styles-uit/HiFiGlyphs.qml | 2 -- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox2.qml b/interface/resources/qml/controls-uit/CheckBox2.qml index f845d24868..92bad04d01 100644 --- a/interface/resources/qml/controls-uit/CheckBox2.qml +++ b/interface/resources/qml/controls-uit/CheckBox2.qml @@ -19,6 +19,8 @@ CheckBox { HifiConstants { id: hifi; } + padding: 0 + leftPadding: 0 property int colorScheme: hifi.colorSchemes.light property string color: hifi.colors.lightGrayText readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index e80f278323..3a9077cbb7 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -78,7 +78,7 @@ Rectangle { Separator { } RalewayRegular { - x: margins.paddings + margins.sizeCheckBox; + x: margins.paddings + muteMic.boxSize + muteMic.spacing; size: 16; color: "white"; text: qsTr("Input Device Settings") @@ -92,7 +92,9 @@ Rectangle { // mute is in its own row RowLayout { AudioControls.CheckBox { + id: muteMic text: qsTr("Mute microphone"); + spacing: 8 isRedCheck: true; checked: Audio.muted; onClicked: { @@ -105,6 +107,7 @@ Rectangle { RowLayout { spacing: 16; AudioControls.CheckBox { + spacing: muteMic.spacing text: qsTr("Enable noise reduction"); checked: Audio.noiseReduction; onClicked: { @@ -113,6 +116,7 @@ Rectangle { } } AudioControls.CheckBox { + spacing: muteMic.spacing text: qsTr("Show audio level meter"); checked: AvatarInputs.showAudioTools; onClicked: { @@ -126,20 +130,25 @@ Rectangle { Separator {} - Row { + Item { x: margins.paddings; width: parent.width - margins.paddings*2 - height: 28 - spacing: 0 + height: 36 + HiFiGlyphs { width: margins.sizeCheckBox text: hifi.glyphs.mic; color: hifi.colors.primaryHighlight; + anchors.left: parent.left + anchors.leftMargin: -size/4 //the glyph has empty space at left about 25% anchors.verticalCenter: parent.verticalCenter; size: 30; } + RalewayRegular { width: margins.sizeText + margins.sizeLevel + anchors.left: parent.left + anchors.leftMargin: margins.sizeCheckBox anchors.verticalCenter: parent.verticalCenter; size: 16; color: hifi.colors.lightGrayText; @@ -151,7 +160,7 @@ Rectangle { id: inputView width: parent.width - margins.paddings*2 x: margins.paddings - height: 150 + height: Math.min(150, contentHeight); spacing: 4; snapMode: ListView.SnapToItem; clip: true; @@ -162,6 +171,7 @@ Rectangle { AudioControls.CheckBox { anchors.left: parent.left + spacing: margins.sizeCheckBox - boxSize width: parent.width - inputLevel.width clip: true checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; @@ -186,20 +196,25 @@ Rectangle { Separator {} - Row { + Item { x: margins.paddings; width: parent.width - margins.paddings*2 height: 36 - spacing: 0 + HiFiGlyphs { + anchors.left: parent.left + anchors.leftMargin: -size/4 //the glyph has empty space at left about 25% + anchors.verticalCenter: parent.verticalCenter; width: margins.sizeCheckBox text: hifi.glyphs.unmuted; color: hifi.colors.primaryHighlight; - anchors.verticalCenter: parent.verticalCenter; size: 36; } + RalewayRegular { width: margins.sizeText + margins.sizeLevel + anchors.left: parent.left + anchors.leftMargin: margins.sizeCheckBox anchors.verticalCenter: parent.verticalCenter; size: 16; color: hifi.colors.lightGrayText; @@ -211,7 +226,7 @@ Rectangle { id: outputView width: parent.width - margins.paddings*2 x: margins.paddings - height: Math.min(210, contentHeight); + height: Math.min(360 - inputView.height, contentHeight); spacing: 4; snapMode: ListView.SnapToItem; clip: true; @@ -222,6 +237,7 @@ Rectangle { AudioControls.CheckBox { width: parent.width + spacing: margins.sizeCheckBox - boxSize boxSize: margins.sizeCheckBox / 2 isRound: true checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; diff --git a/interface/resources/qml/hifi/audio/AudioTabButton.qml b/interface/resources/qml/hifi/audio/AudioTabButton.qml index 2e6e114039..3a3ed90f5e 100644 --- a/interface/resources/qml/hifi/audio/AudioTabButton.qml +++ b/interface/resources/qml/hifi/audio/AudioTabButton.qml @@ -20,7 +20,7 @@ TabButton { HifiConstants { id: hifi; } - contentItem: Text { + contentItem: RalewaySemiBold { text: control.text font: control.font color: "white" diff --git a/interface/resources/qml/hifi/audio/CheckBox.qml b/interface/resources/qml/hifi/audio/CheckBox.qml index 806f08f439..77c001816f 100644 --- a/interface/resources/qml/hifi/audio/CheckBox.qml +++ b/interface/resources/qml/hifi/audio/CheckBox.qml @@ -14,6 +14,5 @@ import QtQuick 2.7 import "../../controls-uit" as HifiControls HifiControls.CheckBox2 { - spacing: 8 color: "white" } diff --git a/interface/resources/qml/styles-uit/HiFiGlyphs.qml b/interface/resources/qml/styles-uit/HiFiGlyphs.qml index cbd6fa1d68..f78d6c6f59 100644 --- a/interface/resources/qml/styles-uit/HiFiGlyphs.qml +++ b/interface/resources/qml/styles-uit/HiFiGlyphs.qml @@ -9,8 +9,6 @@ // import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 Text { id: root From 78aa5820d06b9fbe6e4a20bdd9fc5ff08bea9e6d Mon Sep 17 00:00:00 2001 From: vladest Date: Sun, 27 Aug 2017 11:56:28 +0200 Subject: [PATCH 09/37] Added proper destructor call for audio scripting interface. Save settings in destructor. Added logging to check readed audio settings --- interface/src/Application.cpp | 1 + interface/src/scripting/AudioDevices.cpp | 50 +++++++++++++++++++++++- interface/src/scripting/AudioDevices.h | 3 ++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d13b7880fa..3aa3fbf95d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2052,6 +2052,7 @@ void Application::cleanupBeforeQuit() { // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); qCDebug(interfaceapp) << "Application::cleanupBeforeQuit() complete"; } diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index e31641389c..cff17c1a5c 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -61,7 +61,52 @@ QHash AudioDeviceList::_roles { Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled }; -AudioDeviceList::AudioDeviceList(QAudio::Mode mode) : _mode(mode) {} +AudioDeviceList::AudioDeviceList(QAudio::Mode mode) : _mode(mode) { + auto& setting1 = getSetting(true, QAudio::AudioInput); + if (setting1.isSet()) { + qDebug() << "Device name in settings for HMD, Input" << setting1.get(); + } else { + qDebug() << "Device name in settings for HMD, Input not set"; + } + + auto& setting2 = getSetting(true, QAudio::AudioOutput); + if (setting2.isSet()) { + qDebug() << "Device name in settings for HMD, Output" << setting2.get(); + } else { + qDebug() << "Device name in settings for HMD, Output not set"; + } + + auto& setting3 = getSetting(false, QAudio::AudioInput); + if (setting3.isSet()) { + qDebug() << "Device name in settings for Desktop, Input" << setting3.get(); + } else { + qDebug() << "Device name in settings for Desktop, Input not set"; + } + + auto& setting4 = getSetting(false, QAudio::AudioOutput); + if (setting4.isSet()) { + qDebug() << "Device name in settings for Desktop, Output" << setting4.get(); + } else { + qDebug() << "Device name in settings for Desktop, Output not set"; + } +} + +AudioDeviceList::~AudioDeviceList() { + //save all selected devices + auto& settingHMD = getSetting(true, _mode); + auto& settingDesktop = getSetting(false, _mode); + // store the selected device + foreach(AudioDevice adevice, _devices) { + if (adevice.selectedDesktop) { + qDebug() << "Saving Desktop for" << _mode << "name" << adevice.info.deviceName(); + settingDesktop.set(adevice.info.deviceName()); + } + if (adevice.selectedHMD) { + qDebug() << "Saving HMD for" << _mode << "name" << adevice.info.deviceName(); + settingHMD.set(adevice.info.deviceName()); + } + } +} QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() >= _devices.size()) { @@ -156,6 +201,7 @@ void AudioDeviceList::onDevicesChanged(const QList& devices, b //no selected device for context. fallback to saved isSelected = (device.info.deviceName() == savedDeviceName); } + qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode; _devices.push_back(device); } @@ -182,6 +228,8 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { _outputs.onDevicesChanged(devicesOutput, false); } +AudioDevices::~AudioDevices() {} + void AudioDevices::onContextChanged(const QString& context) { _inputs.resetDevice(_contextIsHMD); _outputs.resetDevice(_contextIsHMD); diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index 5399123329..9b3b2bce9b 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -38,6 +38,7 @@ class AudioDeviceList : public QAbstractListModel { public: AudioDeviceList(QAudio::Mode mode); + virtual ~AudioDeviceList(); int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return _devices.size(); } QHash roleNames() const override { return _roles; } @@ -78,6 +79,8 @@ class AudioDevices : public QObject { public: AudioDevices(bool& contextIsHMD); + virtual ~AudioDevices(); + void chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD); void chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD); From e17f05a33764af13fae631b13f3bc2e56ccc3e12 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 6 Sep 2017 14:52:08 +0200 Subject: [PATCH 10/37] Correct UI --- interface/resources/qml/hifi/audio/Audio.qml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 3a9077cbb7..dd9fcdb533 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -85,7 +85,7 @@ Rectangle { } ColumnLayout { - x: margins.paddings; // padding does not work + x: margins.paddings; spacing: 16; width: parent.width; @@ -94,7 +94,7 @@ Rectangle { AudioControls.CheckBox { id: muteMic text: qsTr("Mute microphone"); - spacing: 8 + spacing: margins.sizeCheckBox - boxSize isRedCheck: true; checked: Audio.muted; onClicked: { @@ -105,7 +105,7 @@ Rectangle { } RowLayout { - spacing: 16; + spacing: muteMic.spacing*2; //make it visually distinguish AudioControls.CheckBox { spacing: muteMic.spacing text: qsTr("Enable noise reduction"); @@ -167,11 +167,14 @@ Rectangle { model: Audio.devices.input; delegate: Item { width: rightMostInputLevelPos - height: margins.sizeCheckBox + height: margins.sizeCheckBox > checkBoxInput.implicitHeight ? + margins.sizeCheckBox : checkBoxInput.implicitHeight AudioControls.CheckBox { + id: checkBoxInput anchors.left: parent.left spacing: margins.sizeCheckBox - boxSize + anchors.verticalCenter: parent.verticalCenter width: parent.width - inputLevel.width clip: true checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; @@ -233,9 +236,11 @@ Rectangle { model: Audio.devices.output; delegate: Item { width: rightMostInputLevelPos - height: margins.sizeCheckBox + height: margins.sizeCheckBox > checkBoxOutput.implicitHeight ? + margins.sizeCheckBox : checkBoxOutput.implicitHeight AudioControls.CheckBox { + id: checkBoxOutput width: parent.width spacing: margins.sizeCheckBox - boxSize boxSize: margins.sizeCheckBox / 2 From c0fb9dcf2e39452040a321844acf5d8b3b85b87a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 6 Sep 2017 09:49:33 -0700 Subject: [PATCH 11/37] Fix polyline crash and flicker --- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 3db7fb2c30..1cecb0b036 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -126,6 +126,7 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& auto textures = entity->getTextures(); QString path = textures.isEmpty() ? PathUtils::resourcesPath() + "images/paintStroke.png" : textures; if (!_texture || _lastTextures != path) { + _lastTextures = path; _texture = DependencyManager::get()->getTexture(QUrl(path)); } } @@ -220,7 +221,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { batch.setModelTransform(Transform{ _modelTransform }.setScale(vec3(1))); batch.setUniformBuffer(PAINTSTROKE_UNIFORM_SLOT, _uniformBuffer); - if (_texture->isLoaded()) { + if (_texture && _texture->isLoaded()) { batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture()); } else { batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, nullptr); From 4c4df97c42b547689ff389eaeeef1a651862726f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 6 Sep 2017 23:38:02 -0700 Subject: [PATCH 12/37] Fix transform of polylines with high update rates --- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 6 +++++- .../entities-renderer/src/RenderablePolyLineEntityItem.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 1cecb0b036..50226ef8ae 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -141,6 +141,10 @@ void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo auto normalsChanged = entity->normalsChanged(); entity->resetPolyLineChanged(); + _polylineTransform = Transform(); + _polylineTransform.setTranslation(entity->getPosition()); + _polylineTransform.setRotation(entity->getRotation()); + if (pointsChanged) { _lastPoints = entity->getLinePoints(); } @@ -218,7 +222,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - batch.setModelTransform(Transform{ _modelTransform }.setScale(vec3(1))); + batch.setModelTransform(_polylineTransform); batch.setUniformBuffer(PAINTSTROKE_UNIFORM_SLOT, _uniformBuffer); if (_texture && _texture->isLoaded()) { diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 88b5ebdb9f..b0bdcf545b 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -47,6 +47,7 @@ protected: void updateGeometry(const std::vector& vertices); static std::vector updateVertices(const QVector& points, const QVector& normals, const QVector& strokeWidths); + Transform _polylineTransform; QVector _lastPoints; QVector _lastNormals; QVector _lastStrokeWidths; From d3ac7a388c8cd53718aab05f6d4209a7fa54b4dc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 14 Sep 2017 10:48:14 -0700 Subject: [PATCH 13/37] Fix polyline rendering using default texture --- .../src/RenderablePolyLineEntityItem.cpp | 14 +++++++++----- .../src/RenderablePolyLineEntityItem.h | 1 - 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 50226ef8ae..8c1a6318f9 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -121,15 +121,19 @@ bool PolyLineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP } void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { + static const QUrl DEFAULT_POLYLINE_TEXTURE = QUrl(PathUtils::resourcesPath() + "images/paintStroke.png"); + QUrl entityTextures = DEFAULT_POLYLINE_TEXTURE; if (entity->texturesChanged()) { entity->resetTexturesChanged(); auto textures = entity->getTextures(); - QString path = textures.isEmpty() ? PathUtils::resourcesPath() + "images/paintStroke.png" : textures; - if (!_texture || _lastTextures != path) { - _lastTextures = path; - _texture = DependencyManager::get()->getTexture(QUrl(path)); + if (!textures.isEmpty()) { + entityTextures = QUrl(textures); } } + + if (!_texture || _texture->getURL() != entityTextures) { + _texture = DependencyManager::get()->getTexture(entityTextures); + } } void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { @@ -228,7 +232,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { if (_texture && _texture->isLoaded()) { batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture()); } else { - batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, nullptr); + batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, DependencyManager::get()->getWhiteTexture()); } batch.setInputFormat(polylineFormat); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index b0bdcf545b..610ee53cf7 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -55,7 +55,6 @@ protected: gpu::BufferView _uniformBuffer; uint32_t _numVertices { 0 }; bool _empty{ true }; - QString _lastTextures; NetworkTexturePointer _texture; }; From 5187ac4761b422371d4cd388e97ea952983a44b6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 15 Sep 2017 11:23:09 -0700 Subject: [PATCH 14/37] Avatar Attachments now render correctly * moved Avatar::fixupModelsInScene off the newly created render thread back to the main thread. * updated Avatar::postUpdate to take a scene pointer, necessary for Avatar::fixupModelsInScene * updated developer/tests/avatarAttachementTest.js to account for recent changes in avatar attachment scale, commit 712aff7ad. * updated initialization of anim graph to use Model::isLoaded() instead of Model::initWhenReady() to know when the model was completely loaded. --- interface/src/Application.cpp | 2 +- interface/src/avatar/AvatarManager.cpp | 4 ++-- interface/src/avatar/AvatarManager.h | 2 +- interface/src/avatar/MyAvatar.cpp | 6 +++--- interface/src/avatar/MyAvatar.h | 2 +- .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 8 +++----- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 2 +- scripts/developer/tests/avatarAttachmentTest.js | 4 ++-- 8 files changed, 14 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3650c495f2..e6524271cf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5209,7 +5209,7 @@ void Application::update(float deltaTime) { } } - avatarManager->postUpdate(deltaTime); + avatarManager->postUpdate(deltaTime, getMain3DScene()); { PROFILE_RANGE_EX(app, "PreRenderLambdas", 0xffff0000, (uint64_t)0); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index e7a83b5abc..a6d77c8d03 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -259,12 +259,12 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { simulateAvatarFades(deltaTime); } -void AvatarManager::postUpdate(float deltaTime) { +void AvatarManager::postUpdate(float deltaTime, const render::ScenePointer& scene) { auto hashCopy = getHashCopy(); AvatarHash::iterator avatarIterator = hashCopy.begin(); for (avatarIterator = hashCopy.begin(); avatarIterator != hashCopy.end(); avatarIterator++) { auto avatar = std::static_pointer_cast(avatarIterator.value()); - avatar->postUpdate(deltaTime); + avatar->postUpdate(deltaTime, scene); } } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 810d419a55..cef6bd4c9c 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -55,7 +55,7 @@ public: void updateMyAvatar(float deltaTime); void updateOtherAvatars(float deltaTime); - void postUpdate(float deltaTime); + void postUpdate(float deltaTime, const render::ScenePointer& scene); void clearOtherAvatars(); void deleteAllAvatars(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8592ff3d74..075e471cf5 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1814,11 +1814,11 @@ void MyAvatar::destroyAnimGraph() { _skeletonModel->getRig().destroyAnimGraph(); } -void MyAvatar::postUpdate(float deltaTime) { +void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { - Avatar::postUpdate(deltaTime); + Avatar::postUpdate(deltaTime, scene); - if (DependencyManager::get()->shouldRenderAvatars() && _skeletonModel->initWhenReady(qApp->getMain3DScene())) { + if (_skeletonModel->isLoaded() && !_skeletonModel->getRig().getAnimNode()) { initHeadBones(); _skeletonModel->setCauterizeBoneSet(_headBoneSet); _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 65dcc12e7d..ce70eaa9dc 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -196,7 +196,7 @@ public: Q_INVOKABLE void clearIKJointLimitHistory(); // thread-safe void update(float deltaTime); - virtual void postUpdate(float deltaTime) override; + virtual void postUpdate(float deltaTime, const render::ScenePointer& scene) override; void preDisplaySide(RenderArgs* renderArgs); const glm::mat4& getHMDSensorMatrix() const { return _hmdSensorMatrix; } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index bc6bb2a0ec..fc51501161 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -553,7 +553,7 @@ void Avatar::updateRenderItem(render::Transaction& transaction) { } } -void Avatar::postUpdate(float deltaTime) { +void Avatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { if (isMyAvatar() ? showMyLookAtVectors : showOtherLookAtVectors) { const float EYE_RAY_LENGTH = 10.0; @@ -577,6 +577,8 @@ void Avatar::postUpdate(float deltaTime) { DebugDraw::getInstance().drawRay(rightEyePosition, rightEyePosition + rightEyeRotation * Vectors::UNIT_Z * EYE_RAY_LENGTH, RED); } } + + fixupModelsInScene(scene); } void Avatar::render(RenderArgs* renderArgs) { @@ -648,10 +650,6 @@ void Avatar::render(RenderArgs* renderArgs) { return; } - if (!isMyAvatar()) { - fixupModelsInScene(renderArgs->_scene); - } - if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); const float BOUNDING_SHAPE_ALPHA = 0.7f; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index d35d6ceba0..c262ce2009 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -98,7 +98,7 @@ public: void updateRenderItem(render::Transaction& transaction); - virtual void postUpdate(float deltaTime); + virtual void postUpdate(float deltaTime, const render::ScenePointer& scene); //setters void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; } diff --git a/scripts/developer/tests/avatarAttachmentTest.js b/scripts/developer/tests/avatarAttachmentTest.js index f287013979..c9f2e1615b 100644 --- a/scripts/developer/tests/avatarAttachmentTest.js +++ b/scripts/developer/tests/avatarAttachmentTest.js @@ -89,9 +89,9 @@ var coatButton = new ToggleButtonBuddy(buttonPositionX, buttonPositionY, BUTTON_ var HAT_ATTACHMENT = { modelURL: "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx", jointName: "Head", - translation: {"x": 0, "y": 0.2, "z": 0}, + translation: {"x": 0, "y": 0.25, "z": 0.03}, rotation: {"x": 0, "y": 0, "z": 0, "w": 1}, - scale: 1, + scale: 0.052, isSoft: false }; From a8bf4efc8b44d576e341d63dcaa8703671d606da Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 14 Sep 2017 18:36:20 -0700 Subject: [PATCH 15/37] Brining the changes just to fix the tablet issue --- interface/src/ui/overlays/Base3DOverlay.cpp | 63 ++++++++++++++++++- interface/src/ui/overlays/Base3DOverlay.h | 9 +++ interface/src/ui/overlays/Planar3DOverlay.cpp | 8 +++ interface/src/ui/overlays/Planar3DOverlay.h | 4 +- interface/src/ui/overlays/Web3DOverlay.cpp | 17 +---- 5 files changed, 84 insertions(+), 17 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index c0278a6496..b450fbdc05 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -256,15 +256,74 @@ bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3 void Base3DOverlay::locationChanged(bool tellPhysics) { SpatiallyNestable::locationChanged(tellPhysics); - auto itemID = getRenderItemID(); + // Force the actual update of the render transform now that we notify for the change + // so it s captured for the time of rendering + notifyRenderTransformChange(); + + /* auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; transaction.updateItem(itemID); scene->enqueueTransaction(transaction); - } + }*/ } void Base3DOverlay::parentDeleted() { qApp->getOverlays().deleteOverlay(getOverlayID()); } + +void Base3DOverlay::update(float duration) { + if (_renderTransformDirty) { + auto self = this; + // queue up this work for later processing, at the end of update and just before rendering. + // the application will ensure only the last lambda is actually invoked. + /* void* key = (void*)this; + std::weak_ptr weakSelf = shared_from_this(); + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf]() { + // do nothing, if the model has already been destroyed. + auto spatiallyNestableSelf = weakSelf.lock(); + if (!spatiallyNestableSelf) { + return; + } + auto self = std::dynamic_pointer_cast(spatiallyNestableSelf); + */ + #ifdef UpdateInMain + self->setRenderTransform(self->evalRenderTransform()); + #else + auto renderTransform = self->evalRenderTransform(); + #endif + auto itemID = self->getRenderItemID(); + if (render::Item::isValidID(itemID)) { + render::ScenePointer scene = qApp->getMain3DScene(); + render::Transaction transaction; + #ifdef UpdateInMain + transaction.updateItem(itemID); + #else + transaction.updateItem(itemID, [renderTransform](Overlay& data) { + auto overlay3D = dynamic_cast(&data); + if (overlay3D) { + auto latestTransform = overlay3D->evalRenderTransform(); + overlay3D->setRenderTransform(latestTransform);// evalRenderTransform(); + } + }); + #endif + scene->enqueueTransaction(transaction); + + } + // }); + _renderTransformDirty = false; + } +} + +void Base3DOverlay::notifyRenderTransformChange() const { + _renderTransformDirty = true; +} + +Transform Base3DOverlay::evalRenderTransform() const { + return getTransform(); +} + +void Base3DOverlay::setRenderTransform(const Transform& transform) { + _renderTransform = transform; +} \ No newline at end of file diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 6377b46d7d..b2167852d4 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -52,6 +52,12 @@ public: virtual AABox getBounds() const override = 0; + void update(float deltatime) override; + + void notifyRenderTransformChange() const; + virtual Transform evalRenderTransform() const; + void setRenderTransform(const Transform& transform); + void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -67,12 +73,15 @@ protected: virtual void locationChanged(bool tellPhysics = true) override; virtual void parentDeleted() override; + mutable Transform _renderTransform; + float _lineWidth; bool _isSolid; bool _isDashedLine; bool _ignoreRayIntersection; bool _drawInFront; bool _isGrabbable { false }; + mutable bool _renderTransformDirty{ true }; QString _name; }; diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 58d72b100b..e2877e1e07 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -66,3 +66,11 @@ bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve // FIXME - face and surfaceNormal not being returned return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), getDimensions(), distance); } + +Transform Planar3DOverlay::evalRenderTransform() const { + auto transform = getTransform(); + if (glm::length2(getDimensions()) != 1.0f) { + transform.postScale(vec3(getDimensions(), 1.0f)); + } + return transform; +} \ No newline at end of file diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index 8127d4ebb9..2ed90ab4ed 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -32,7 +32,9 @@ public: virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal) override; - + + Transform evalRenderTransform() const override; + protected: glm::vec2 _dimensions; }; diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 104082dee4..fd3763624e 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -184,6 +184,7 @@ void Web3DOverlay::update(float deltatime) { // update globalPosition _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } + Billboard3DOverlay::update(deltatime); } QString Web3DOverlay::pickURL() { @@ -306,19 +307,6 @@ void Web3DOverlay::render(RenderArgs* args) { vec2 halfSize = getSize() / 2.0f; vec4 color(toGlm(getColor()), getAlpha()); - Transform transform = getTransform(); - - // FIXME: applyTransformTo causes tablet overlay to detach from tablet entity. - // Perhaps rather than deleting the following code it should be run only if isFacingAvatar() is true? - /* - applyTransformTo(transform, true); - setTransform(transform); - */ - - if (glm::length2(getDimensions()) != 1.0f) { - transform.postScale(vec3(getDimensions(), 1.0f)); - } - if (!_texture) { _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture->setSource(__FUNCTION__); @@ -332,7 +320,8 @@ void Web3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setResourceTexture(0, _texture); - batch.setModelTransform(transform); + batch.setModelTransform(_renderTransform); + auto geometryCache = DependencyManager::get(); if (color.a < OPAQUE_ALPHA_THRESHOLD) { geometryCache->bindWebBrowserProgram(batch, true); From f82a507d09f8cdf4df45f840a219c5257cec5f69 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 14 Sep 2017 20:33:08 -0700 Subject: [PATCH 16/37] Cleanup --- interface/src/ui/overlays/Base3DOverlay.cpp | 52 +++++---------------- interface/src/ui/overlays/Base3DOverlay.h | 5 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- 3 files changed, 16 insertions(+), 43 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index b450fbdc05..53af2ea882 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -256,17 +256,8 @@ bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3 void Base3DOverlay::locationChanged(bool tellPhysics) { SpatiallyNestable::locationChanged(tellPhysics); - // Force the actual update of the render transform now that we notify for the change - // so it s captured for the time of rendering + // Force the actual update of the render transform through the notify call notifyRenderTransformChange(); - - /* auto itemID = getRenderItemID(); - if (render::Item::isValidID(itemID)) { - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - transaction.updateItem(itemID); - scene->enqueueTransaction(transaction); - }*/ } void Base3DOverlay::parentDeleted() { @@ -274,44 +265,25 @@ void Base3DOverlay::parentDeleted() { } void Base3DOverlay::update(float duration) { + + // In Base3DOverlay, if its location or bound changed, the renderTrasnformDirty flag is true. + // then the correct transform used for rendering is computed in the update transaction and assigned. + // TODO: Fix the value to be computed in main thread now and passed by value to the render item. + // This is the simplest fix for the web overlay of the tablet for now if (_renderTransformDirty) { - auto self = this; - // queue up this work for later processing, at the end of update and just before rendering. - // the application will ensure only the last lambda is actually invoked. - /* void* key = (void*)this; - std::weak_ptr weakSelf = shared_from_this(); - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf]() { - // do nothing, if the model has already been destroyed. - auto spatiallyNestableSelf = weakSelf.lock(); - if (!spatiallyNestableSelf) { - return; - } - auto self = std::dynamic_pointer_cast(spatiallyNestableSelf); - */ - #ifdef UpdateInMain - self->setRenderTransform(self->evalRenderTransform()); - #else - auto renderTransform = self->evalRenderTransform(); - #endif - auto itemID = self->getRenderItemID(); - if (render::Item::isValidID(itemID)) { + auto itemID = getRenderItemID(); + if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; - #ifdef UpdateInMain - transaction.updateItem(itemID); - #else - transaction.updateItem(itemID, [renderTransform](Overlay& data) { + transaction.updateItem(itemID, [](Overlay& data) { auto overlay3D = dynamic_cast(&data); if (overlay3D) { auto latestTransform = overlay3D->evalRenderTransform(); - overlay3D->setRenderTransform(latestTransform);// evalRenderTransform(); + overlay3D->setRenderTransform(latestTransform); } }); - #endif - scene->enqueueTransaction(transaction); - + scene->enqueueTransaction(transaction); } - // }); _renderTransformDirty = false; } } @@ -326,4 +298,4 @@ Transform Base3DOverlay::evalRenderTransform() const { void Base3DOverlay::setRenderTransform(const Transform& transform) { _renderTransform = transform; -} \ No newline at end of file +} diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index b2167852d4..55b55ed16f 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -55,8 +55,6 @@ public: void update(float deltatime) override; void notifyRenderTransformChange() const; - virtual Transform evalRenderTransform() const; - void setRenderTransform(const Transform& transform); void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -74,6 +72,9 @@ protected: virtual void parentDeleted() override; mutable Transform _renderTransform; + virtual Transform evalRenderTransform() const; + virtual void setRenderTransform(const Transform& transform); + const Transform& getRenderTransform() const { return _renderTransform; } float _lineWidth; bool _isSolid; diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index fd3763624e..809536add9 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -320,7 +320,7 @@ void Web3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setResourceTexture(0, _texture); - batch.setModelTransform(_renderTransform); + batch.setModelTransform(getRenderTransform()); auto geometryCache = DependencyManager::get(); if (color.a < OPAQUE_ALPHA_THRESHOLD) { From fd440aeeaae6179980e559cd995ab6915ab62386 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Sep 2017 11:10:25 -0700 Subject: [PATCH 17/37] addressing review comments --- interface/src/ui/overlays/Base3DOverlay.cpp | 4 ++-- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.h | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 53af2ea882..6f55260133 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -271,11 +271,12 @@ void Base3DOverlay::update(float duration) { // TODO: Fix the value to be computed in main thread now and passed by value to the render item. // This is the simplest fix for the web overlay of the tablet for now if (_renderTransformDirty) { + _renderTransformDirty = false; auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; - transaction.updateItem(itemID, [](Overlay& data) { + transaction.updateItem(itemID, [](Overlay& data) { auto overlay3D = dynamic_cast(&data); if (overlay3D) { auto latestTransform = overlay3D->evalRenderTransform(); @@ -284,7 +285,6 @@ void Base3DOverlay::update(float duration) { }); scene->enqueueTransaction(transaction); } - _renderTransformDirty = false; } } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 809536add9..eb8451e5c3 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -184,7 +184,7 @@ void Web3DOverlay::update(float deltatime) { // update globalPosition _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } - Billboard3DOverlay::update(deltatime); + Parent::update(deltatime); } QString Web3DOverlay::pickURL() { diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 2eae7f33da..18cac96d65 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -21,6 +21,8 @@ class Web3DOverlay : public Billboard3DOverlay { Q_OBJECT public: + using Parent = Billboard3DOverlay; + static const QString QML; static QString const TYPE; virtual QString getType() const override { return TYPE; } From 0e83065a6db8471cdeed35cff39294d27c97113a Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Sep 2017 11:44:35 -0700 Subject: [PATCH 18/37] One more: --- interface/src/ui/overlays/Web3DOverlay.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 18cac96d65..6bd540d120 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -19,9 +19,9 @@ class OffscreenQmlSurface; class Web3DOverlay : public Billboard3DOverlay { Q_OBJECT + using Parent = Billboard3DOverlay; public: - using Parent = Billboard3DOverlay; static const QString QML; static QString const TYPE; From 93d6c3a1aaeb23a45a2e9bbb468287feb4fb35ee Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Sep 2017 14:35:45 -0700 Subject: [PATCH 19/37] Adding more comments for future fixmes --- interface/src/ui/overlays/Circle3DOverlay.cpp | 1 + interface/src/ui/overlays/Cube3DOverlay.cpp | 1 + interface/src/ui/overlays/Grid3DOverlay.cpp | 1 + interface/src/ui/overlays/Image3DOverlay.cpp | 1 + interface/src/ui/overlays/Line3DOverlay.cpp | 1 + interface/src/ui/overlays/ModelOverlay.cpp | 1 + interface/src/ui/overlays/Rectangle3DOverlay.cpp | 1 + interface/src/ui/overlays/Shape3DOverlay.cpp | 1 + interface/src/ui/overlays/Sphere3DOverlay.cpp | 1 + interface/src/ui/overlays/Text3DOverlay.cpp | 1 + 10 files changed, 10 insertions(+) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 242021d698..57911c0786 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -85,6 +85,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } // FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround + // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform() auto transform = getTransform(); transform.postScale(glm::vec3(getDimensions(), 1.0f)); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 5ab32d21fe..ca7355b86f 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -54,6 +54,7 @@ void Cube3DOverlay::render(RenderArgs* args) { glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); // TODO: handle registration point?? + // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform() glm::vec3 position = getPosition(); glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 1c2b4c162d..3172403731 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -79,6 +79,7 @@ void Grid3DOverlay::render(RenderArgs* args) { position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z); } + // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform() Transform transform; transform.setRotation(getRotation()); transform.setScale(glm::vec3(getDimensions(), 1.0f)); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 6949848208..c79d363811 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -117,6 +117,7 @@ void Image3DOverlay::render(RenderArgs* args) { xColor color = getColor(); float alpha = getAlpha(); + // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform() Transform transform = getTransform(); bool transformChanged = applyTransformTo(transform, true); // If the transform is not modified, setting the transform to diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index cc8ed8e1a8..534261c839 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -132,6 +132,7 @@ void Line3DOverlay::render(RenderArgs* args) { glm::vec4 colorv4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); auto batch = args->_batch; if (batch) { + // FIXME Start using the _renderTransform instead of calling for Transform and start and end from here, do the custom things needed in evalRenderTransform() batch->setModelTransform(Transform()); glm::vec3 start = getStart(); glm::vec3 end = getEnd(); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 0bed07891e..0cdcf012b8 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -281,6 +281,7 @@ ModelOverlay* ModelOverlay::createClone() const { void ModelOverlay::locationChanged(bool tellPhysics) { Base3DOverlay::locationChanged(tellPhysics); + // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() if (_model && _model->isActive()) { _model->setRotation(getRotation()); _model->setTranslation(getPosition()); diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 22124a0a97..dc8badbbd1 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -66,6 +66,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) { auto batch = args->_batch; if (batch) { + // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() Transform transform; transform.setTranslation(position); transform.setRotation(rotation); diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index df0ecba307..fc54cc19ff 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -33,6 +33,7 @@ void Shape3DOverlay::render(RenderArgs* args) { const float MAX_COLOR = 255.0f; glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); + // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() // TODO: handle registration point?? glm::vec3 position = getPosition(); glm::vec3 dimensions = getDimensions(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 9309316d6e..d01da231cf 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -39,6 +39,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { auto batch = args->_batch; if (batch) { + // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() Transform transform = getTransform(); transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE); batch->setModelTransform(transform); diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index bb8c24aa11..43a2854206 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -96,6 +96,7 @@ void Text3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); auto& batch = *args->_batch; + // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() Transform transform = getTransform(); applyTransformTo(transform, true); setTransform(transform); From dbe7cc5d1af8a2a5702f1c6051f2ff13d6addce4 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 18 Sep 2017 23:38:38 +0100 Subject: [PATCH 20/37] 21540 - Make Rotation using Vive Controller Work --- interface/resources/controllers/standard.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 0d5c095585..28f15605e0 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -25,7 +25,7 @@ }, { "from": "Standard.RX", - "when": [ "Application.InHMD", "Application.SnapTurn" ], + "when": [ "Application.SnapTurn" ], "to": "Actions.StepYaw", "filters": [ @@ -128,4 +128,4 @@ { "from": "Standard.TrackedObject14", "to" : "Actions.TrackedObject14" }, { "from": "Standard.TrackedObject15", "to" : "Actions.TrackedObject15" } ] -} +} \ No newline at end of file From 57a92adc73ad08df6e43057ab7d8b3e893975104 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 18 Sep 2017 15:39:38 -0700 Subject: [PATCH 21/37] flag node as local by sending address, not by local from packet --- domain-server/src/DomainGatekeeper.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 620d593ebc..dbbcc004ca 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -272,22 +272,22 @@ void DomainGatekeeper::updateNodePermissions() { userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer; userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent; } else { - // this node is an agent - const QHostAddress& addr = node->getLocalSocket().getAddress(); - bool isLocalUser = (addr == limitedNodeList->getLocalSockAddr().getAddress() || - addr == QHostAddress::LocalHost); - // at this point we don't have a sending socket for packets from this node - assume it is the active socket // or the public socket if we haven't activated a socket for the node yet HifiSockAddr connectingAddr = node->getActiveSocket() ? *node->getActiveSocket() : node->getPublicSocket(); QString hardwareAddress; QUuid machineFingerprint; + bool isLocalUser { false }; DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); if (nodeData) { hardwareAddress = nodeData->getHardwareAddress(); machineFingerprint = nodeData->getMachineFingerprint(); + + auto sendingAddress = nodeData->getSendingSockAddr().getAddress(); + isLocalUser = (sendingAddress == limitedNodeList->getLocalSockAddr().getAddress() || + sendingAddress == QHostAddress::LocalHost); } userPerms = setPermissionsForUser(isLocalUser, verifiedUsername, connectingAddr.getAddress(), hardwareAddress, machineFingerprint); From 6297448e907660bf508db14ff2f635775346c9e7 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 19 Sep 2017 19:49:19 +0200 Subject: [PATCH 22/37] Build fix --- interface/resources/qml/hifi/audio/Audio.qml | 7 ++- interface/src/scripting/AudioDevices.cpp | 46 ++++++++++++-------- interface/src/scripting/AudioDevices.h | 4 +- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 0abd166b06..5a2ee86c09 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -70,6 +70,7 @@ Rectangle { } property bool showPeaks: true; + function enablePeakValues() { Audio.devices.input.peakValuesEnabled = true; Audio.devices.input.peakValuesEnabledChanged.connect(function(enabled) { @@ -78,6 +79,7 @@ Rectangle { } }); } + function disablePeakValues() { root.showPeaks = false; Audio.devices.input.peakValuesEnabled = false; @@ -202,12 +204,13 @@ Rectangle { } } } - InputLevel { + InputPeak { id: inputLevel anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter visible: (bar.currentIndex === 1 && selectedHMD && isVR) || - (bar.currentIndex === 0 && selectedDesktop && !isVR); + (bar.currentIndex === 0 && selectedDesktop && !isVR) && + Audio.devices.input.peakValuesAvailable; } } } diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index c79db91dfc..a130b46877 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -105,14 +105,14 @@ AudioDeviceList::~AudioDeviceList() { auto& settingHMD = getSetting(true, _mode); auto& settingDesktop = getSetting(false, _mode); // store the selected device - foreach(AudioDevice adevice, _devices) { - if (adevice.selectedDesktop) { - qDebug() << "Saving Desktop for" << _mode << "name" << adevice.info.deviceName(); - settingDesktop.set(adevice.info.deviceName()); + foreach(std::shared_ptr adevice, _devices) { + if (adevice->selectedDesktop) { + qDebug() << "Saving Desktop for" << _mode << "name" << adevice->info.deviceName(); + settingDesktop.set(adevice->info.deviceName()); } - if (adevice.selectedHMD) { - qDebug() << "Saving HMD for" << _mode << "name" << adevice.info.deviceName(); - settingHMD.set(adevice.info.deviceName()); + if (adevice->selectedHMD) { + qDebug() << "Saving HMD for" << _mode << "name" << adevice->info.deviceName(); + settingHMD.set(adevice->info.deviceName()); } } } @@ -123,18 +123,30 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { } if (role == DeviceNameRole) { - return _devices.at(index.row()).display; + return _devices.at(index.row())->display; } else if (role == SelectedDesktopRole) { - return _devices.at(index.row()).selectedDesktop; + return _devices.at(index.row())->selectedDesktop; } else if (role == SelectedHMDRole) { - return _devices.at(index.row()).selectedHMD; - } else if (role == DeviceInfoRole) { - return QVariant::fromValue(_devices.at(index.row()).info); + return _devices.at(index.row())->selectedHMD; + } else if (role == InfoRole) { + return QVariant::fromValue(_devices.at(index.row())->info); } else { return QVariant(); } } +QVariant AudioInputDeviceList::data(const QModelIndex& index, int role) const { + if (!index.isValid() || index.row() >= rowCount()) { + return QVariant(); + } + + if (role == PeakRole) { + return std::static_pointer_cast(_devices.at(index.row()))->peak; + } else { + return AudioDeviceList::data(index, role); + } +} + void AudioDeviceList::resetDevice(bool contextIsHMD) { auto client = DependencyManager::get().data(); QString deviceName = getTargetDevice(contextIsHMD, _mode); @@ -175,11 +187,11 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD selectedDevice = device; for (auto i = 0; i < _devices.size(); ++i) { - AudioDevice& device = _devices[i]; - bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; - if (isSelected && device.info != selectedDevice) { + std::shared_ptr device = _devices[i]; + bool &isSelected = isHMD ? device->selectedHMD : device->selectedDesktop; + if (isSelected && device->info != selectedDevice) { isSelected = false; - } else if (device.info == selectedDevice) { + } else if (device->info == selectedDevice) { isSelected = true; } } @@ -211,7 +223,7 @@ void AudioDeviceList::onDevicesChanged(const QList& devices, b isSelected = (device.info.deviceName() == savedDeviceName); } qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode; - _devices.push_back(device); + _devices.push_back(newDevice(device)); } endResetModel(); diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index 162092f358..36f1653e38 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -33,8 +33,8 @@ class AudioDeviceList : public QAbstractListModel { Q_OBJECT public: - AudioDeviceList(QAudio::Mode mode = QAudio::AudioOutput) : _mode(mode) {} - ~AudioDeviceList() = default; + AudioDeviceList(QAudio::Mode mode = QAudio::AudioOutput); + virtual ~AudioDeviceList(); virtual std::shared_ptr newDevice(const AudioDevice& device) { return std::make_shared(device); } From 1f485ac8f80e176c209945130f45d46b56c860c9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 19 Sep 2017 12:05:15 -0700 Subject: [PATCH 23/37] Fix OpenSSL build instructions --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 30302d611b..4d321146c3 100644 --- a/BUILD.md +++ b/BUILD.md @@ -2,7 +2,7 @@ - [cmake](https://cmake.org/download/): 3.9 - [Qt](https://www.qt.io/download-open-source): 5.9.1 -- [OpenSSL](https://www.openssl.org/): Use the latest available version of OpenSSL to avoid security vulnerabilities. +- [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities. - [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) ### CMake External Project Dependencies From 10f7f081713e491549bb9d5ceb4471cc262f98ef Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 19 Sep 2017 21:42:52 +0200 Subject: [PATCH 24/37] Added peak model, missed during merging --- interface/resources/qml/hifi/audio/Audio.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 5a2ee86c09..bc55175f18 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -207,6 +207,7 @@ Rectangle { InputPeak { id: inputLevel anchors.right: parent.right + peak: model.peak; anchors.verticalCenter: parent.verticalCenter visible: (bar.currentIndex === 1 && selectedHMD && isVR) || (bar.currentIndex === 0 && selectedDesktop && !isVR) && From 7a36894f76e9f17b754e4e2c4e6aab9961769739 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 19 Sep 2017 23:25:41 +0200 Subject: [PATCH 25/37] Make sure audio device not gets unchecked --- interface/resources/qml/hifi/audio/Audio.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index bc55175f18..b1f80ac5e8 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -194,12 +194,13 @@ Rectangle { anchors.verticalCenter: parent.verticalCenter width: parent.width - inputLevel.width clip: true + checkable: !checked checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; boxSize: margins.sizeCheckBox / 2 isRound: true text: devicename - onClicked: { - if (checked) { + onPressed: { + if (!checked) { Audio.setInputDevice(info, bar.currentIndex === 1); } } @@ -265,9 +266,10 @@ Rectangle { boxSize: margins.sizeCheckBox / 2 isRound: true checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD; + checkable: !checked text: devicename - onClicked: { - if (checked) { + onPressed: { + if (!checked) { Audio.setOutputDevice(info, bar.currentIndex === 1); } } From 9c66a25d837268615ce7d6cbf670377f438452eb Mon Sep 17 00:00:00 2001 From: druiz17 Date: Tue, 19 Sep 2017 17:03:53 -0700 Subject: [PATCH 26/37] fixing and cleanup tablet inputs --- .../controllers/controllerDispatcher.js | 6 +- .../controllerModules/overlayLaserInput.js | 344 ++++-------------- .../controllerModules/tabletStylusInput.js | 268 ++------------ .../libraries/controllerDispatcherUtils.js | 4 +- scripts/system/libraries/touchEventUtils.js | 270 ++++++++++++++ 5 files changed, 375 insertions(+), 517 deletions(-) create mode 100644 scripts/system/libraries/touchEventUtils.js diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 63657e9b6f..22987245a4 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -140,10 +140,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.setIgnoreTablet = function() { - if (HMD.tabletID !== _this.tabletID) { - RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]); - RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]); - } + RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]); + RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]); }; this.update = function () { diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 218122e876..9bf7ed23da 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -16,6 +16,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { + var touchEvent = Script.require("/~/system/libraries/touchEventUtils.js"); var halfPath = { type: "line3d", color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, @@ -88,186 +89,6 @@ Script.include("/~/system/libraries/controllers.js"); var HAPTIC_STYLUS_STRENGTH = 1.0; var HAPTIC_STYLUS_DURATION = 20.0; - function laserTargetHasKeyboardFocus(laserTarget) { - if (laserTarget && laserTarget !== NULL_UUID) { - return Overlays.keyboardFocusOverlay === laserTarget; - } - } - - function setKeyboardFocusOnLaserTarget(laserTarget) { - if (laserTarget && laserTarget !== NULL_UUID) { - Overlays.keyboardFocusOverlay = laserTarget; - Entities.keyboardFocusEntity = NULL_UUID; - } - } - - function sendHoverEnterEventToLaserTarget(hand, laserTarget) { - if (!laserTarget) { - return; - } - var pointerEvent = { - type: "Move", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: laserTarget.position2D, - pos3D: laserTarget.position, - normal: laserTarget.normal, - direction: Vec3.subtract(ZERO_VEC, laserTarget.normal), - button: "None" - }; - - if (laserTarget.overlayID && laserTarget.overlayID !== NULL_UUID) { - Overlays.sendHoverEnterOverlay(laserTarget.overlayID, pointerEvent); - } - } - - function sendHoverOverEventToLaserTarget(hand, laserTarget) { - - if (!laserTarget) { - return; - } - var pointerEvent = { - type: "Move", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: laserTarget.position2D, - pos3D: laserTarget.position, - normal: laserTarget.normal, - direction: Vec3.subtract(ZERO_VEC, laserTarget.normal), - button: "None" - }; - - if (laserTarget.overlayID && laserTarget.overlayID !== NULL_UUID) { - Overlays.sendMouseMoveOnOverlay(laserTarget.overlayID, pointerEvent); - Overlays.sendHoverOverOverlay(laserTarget.overlayID, pointerEvent); - } - } - - function sendTouchStartEventToLaserTarget(hand, laserTarget) { - if (!laserTarget) { - return; - } - - var pointerEvent = { - type: "Press", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: laserTarget.position2D, - pos3D: laserTarget.position, - normal: laserTarget.normal, - direction: Vec3.subtract(ZERO_VEC, laserTarget.normal), - button: "Primary", - isPrimaryHeld: true - }; - - if (laserTarget.overlayID && laserTarget.overlayID !== NULL_UUID) { - Overlays.sendMousePressOnOverlay(laserTarget.overlayID, pointerEvent); - } - } - - function sendTouchEndEventToLaserTarget(hand, laserTarget) { - if (!laserTarget) { - return; - } - var pointerEvent = { - type: "Release", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: laserTarget.position2D, - pos3D: laserTarget.position, - normal: laserTarget.normal, - direction: Vec3.subtract(ZERO_VEC, laserTarget.normal), - button: "Primary" - }; - - if (laserTarget.overlayID && laserTarget.overlayID !== NULL_UUID) { - Overlays.sendMouseReleaseOnOverlay(laserTarget.overlayID, pointerEvent); - Overlays.sendMouseReleaseOnOverlay(laserTarget.overlayID, pointerEvent); - } - } - - function sendTouchMoveEventToLaserTarget(hand, laserTarget) { - if (!laserTarget) { - return; - } - var pointerEvent = { - type: "Move", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: laserTarget.position2D, - pos3D: laserTarget.position, - normal: laserTarget.normal, - direction: Vec3.subtract(ZERO_VEC, laserTarget.normal), - button: "Primary", - isPrimaryHeld: true - }; - - if (laserTarget.overlayID && laserTarget.overlayID !== NULL_UUID) { - Overlays.sendMouseReleaseOnOverlay(laserTarget.overlayID, pointerEvent); - } - } - - // will return undefined if overlayID does not exist. - function calculateLaserTargetFromOverlay(worldPos, overlayID) { - var overlayPosition = Overlays.getProperty(overlayID, "position"); - if (overlayPosition === undefined) { - return null; - } - - // project stylusTip onto overlay plane. - var overlayRotation = Overlays.getProperty(overlayID, "rotation"); - if (overlayRotation === undefined) { - return null; - } - var normal = Vec3.multiplyQbyV(overlayRotation, {x: 0, y: 0, z: 1}); - var distance = Vec3.dot(Vec3.subtract(worldPos, overlayPosition), normal); - - // calclulate normalized position - var invRot = Quat.inverse(overlayRotation); - var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(worldPos, overlayPosition)); - var dpi = Overlays.getProperty(overlayID, "dpi"); - - var dimensions; - if (dpi) { - // Calculate physical dimensions for web3d overlay from resolution and dpi; "dimensions" property - // is used as a scale. - var resolution = Overlays.getProperty(overlayID, "resolution"); - if (resolution === undefined) { - return null; - } - resolution.z = 1;// Circumvent divide-by-zero. - var scale = Overlays.getProperty(overlayID, "dimensions"); - if (scale === undefined) { - return null; - } - scale.z = 0.01;// overlay dimensions are 2D, not 3D. - dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale); - } else { - dimensions = Overlays.getProperty(overlayID, "dimensions"); - if (dimensions === undefined) { - return null; - } - if (!dimensions.z) { - dimensions.z = 0.01;// sometimes overlay dimensions are 2D, not 3D. - } - } - var invDimensions = { x: 1 / dimensions.x, y: 1 / dimensions.y, z: 1 / dimensions.z }; - var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), DEFAULT_REGISTRATION_POINT); - - // 2D position on overlay plane in meters, relative to the bounding box upper-left hand corner. - var position2D = { - x: normalizedPosition.x * dimensions.x, - y: (1 - normalizedPosition.y) * dimensions.y // flip y-axis - }; - - return { - entityID: null, - overlayID: overlayID, - distance: distance, - position: worldPos, - position2D: position2D, - normal: normal, - normalizedPosition: normalizedPosition, - dimensions: dimensions, - valid: true - }; - } - function distance2D(a, b) { var dx = (a.x - b.x); var dy = (a.y - b.y); @@ -277,16 +98,11 @@ Script.include("/~/system/libraries/controllers.js"); function OverlayLaserInput(hand) { this.hand = hand; this.active = false; - this.previousLaserClikcedTarget = false; + this.previousLaserClickedTarget = false; this.laserPressingTarget = false; - this.tabletScreenID = null; this.mode = "none"; - this.laserTargetID = null; this.laserTarget = null; this.pressEnterLaserTarget = null; - this.hover = false; - this.target = null; - this.lastValidTargetID = this.tabletTargetID; this.parameters = makeDispatcherModuleParameters( @@ -307,23 +123,35 @@ Script.include("/~/system/libraries/controllers.js"); return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; }; - this.stealTouchFocus = function(laserTarget) { - this.requestTouchFocus(laserTarget); + this.hasTouchFocus = function(laserTarget) { + return (laserTarget.overlayID === this.hoverOverlay); }; this.requestTouchFocus = function(laserTarget) { - if (laserTarget !== null || laserTarget !== undefined) { - sendHoverEnterEventToLaserTarget(this.hand, this.laserTarget); - this.lastValidTargetID = laserTarget; + if (laserTarget.overlayID && + laserTarget.overlayID !== this.hoverOverlay) { + this.hoverOverlay = laserTarget.overlayID; + touchEvent.sendHoverEnterEventToTouchTarget(this.hand, laserTarget); } }; this.relinquishTouchFocus = function() { // send hover leave event. - var pointerEvent = { type: "Move", id: this.hand + 1 }; - Overlays.sendMouseMoveOnOverlay(this.lastValidTargetID, pointerEvent); - Overlays.sendHoverOverOverlay(this.lastValidTargetID, pointerEvent); - Overlays.sendHoverLeaveOverlay(this.lastValidID, pointerEvent); + if (this.hoverOverlay) { + var pointerEvent = { type: "Move", id: this.hand + 1 }; + Overlays.sendMouseMoveOnOverlay(this.hoverOverlay, pointerEvent); + Overlays.sendHoverOverOverlay(this.hoverOverlay, pointerEvent); + Overlays.sendHoverLeaveOverlay(this.hoverOverlay, pointerEvent); + this.hoverOverlay = null; + } + }; + + this.stealTouchFocus = function(laserTarget) { + if (laserTarget.overlayID === this.getOtherModule().hoverOverlay) { + this.getOtherModule().relinquishTouchFocus(); + } + + this.requestTouchFocus(laserTarget); }; this.updateLaserPointer = function(controllerData) { @@ -345,38 +173,23 @@ Script.include("/~/system/libraries/controllers.js"); this.processControllerTriggers = function(controllerData) { if (controllerData.triggerClicks[this.hand]) { this.mode = "full"; - this.laserPressingTarget = true; - this.hover = false; } else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { this.mode = "half"; - this.laserPressingTarget = false; - this.hover = true; - this.requestTouchFocus(this.laserTargetID); } else { this.mode = "none"; - this.laserPressingTarget = false; - this.hover = false; - this.relinquishTouchFocus(); - } }; - this.hovering = function() { - if (!laserTargetHasKeyboardFocus(this.laserTagetID)) { - setKeyboardFocusOnLaserTarget(this.laserTargetID); - } - sendHoverOverEventToLaserTarget(this.hand, this.laserTarget); - }; - this.laserPressEnter = function () { - sendTouchStartEventToLaserTarget(this.hand, this.laserTarget); + this.stealTouchFocus(this.laserTarget); + touchEvent.sendTouchStartEventToTouchTarget(this.hand, this.laserTarget); Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand); this.touchingEnterTimer = 0; this.pressEnterLaserTarget = this.laserTarget; this.deadspotExpired = false; - var LASER_PRESS_TO_MOVE_DEADSPOT = 0.026; + var LASER_PRESS_TO_MOVE_DEADSPOT = 0.094; this.deadspotRadius = Math.tan(LASER_PRESS_TO_MOVE_DEADSPOT) * this.laserTarget.distance; }; @@ -386,15 +199,15 @@ Script.include("/~/system/libraries/controllers.js"); } // special case to handle home button. - if (this.laserTargetID === HMD.homeButtonID) { - Messages.sendLocalMessage("home", this.laserTargetID); + if (this.laserTarget.overlayID === HMD.homeButtonID) { + Messages.sendLocalMessage("home", this.laserTarget.overlayID); } // send press event if (this.deadspotExpired) { - sendTouchEndEventToLaserTarget(this.hand, this.laserTarget); + touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.laserTarget); } else { - sendTouchEndEventToLaserTarget(this.hand, this.pressEnterLaserTarget); + touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.pressEnterLaserTarget); } }; @@ -402,27 +215,49 @@ Script.include("/~/system/libraries/controllers.js"); this.touchingEnterTimer += dt; if (this.laserTarget) { - var POINTER_PRESS_TO_MOVE_DELAY = 0.33; // seconds - if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY || - distance2D( this.laserTarget.position2D, - this.pressEnterLaserTarget.position2D) > this.deadspotRadius) { - sendTouchMoveEventToLaserTarget(this.hand, this.laserTarget); - this.deadspotExpired = true; + if (controllerData.triggerClicks[this.hand]) { + var POINTER_PRESS_TO_MOVE_DELAY = 0.33; // seconds + if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY || + distance2D(this.laserTarget.position2D, + this.pressEnterLaserTarget.position2D) > this.deadspotRadius) { + touchEvent.sendTouchMoveEventToTouchTarget(this.hand, this.laserTarget); + this.deadspotExpired = true; + } + } else { + this.laserPressingTarget = false; } } else { this.laserPressingTarget = false; } }; - this.releaseTouchEvent = function() { - sendTouchEndEventToLaserTarget(this.hand, this.pressEnterLaserTarget); - }; - - - this.updateLaserTargets = function(controllerData) { + this.processLaser = function(controllerData) { + if (this.shouldExit(controllerData) || this.getOtherModule().active) { + this.exitModule(); + return false; + } var intersection = controllerData.rayPicks[this.hand]; - this.laserTargetID = intersection.objectID; - this.laserTarget = calculateLaserTargetFromOverlay(intersection.intersection, intersection.objectID); + var laserTarget = touchEvent.composeTouchTargetFromIntersection(intersection); + + if (controllerData.triggerClicks[this.hand]) { + this.laserTarget = laserTarget; + this.laserPressingTarget = true; + } else { + this.requestTouchFocus(laserTarget); + + if (!touchEvent.touchTargetHasKeyboardFocus(laserTarget)) { + touchEvent.setKeyboardFocusOnTouchTarget(laserTarget); + } + + if (this.hasTouchFocus(laserTarget) && !this.laserPressingTarget) { + touchEvent.sendHoverOverEventToTouchTarget(this.hand, laserTarget); + } + } + + this.processControllerTriggers(controllerData); + this.updateLaserPointer(controllerData); + this.active = true; + return true; }; this.shouldExit = function(controllerData) { @@ -436,7 +271,12 @@ Script.include("/~/system/libraries/controllers.js"); }; this.exitModule = function() { - this.releaseTouchEvent(); + if (this.laserPressingTarget) { + this.deadspotExpired = true; + this.laserPressExit(); + this.laserPressingTarget = false; + } + this.deleteContextOverlay(); this.relinquishTouchFocus(); this.reset(); this.updateLaserPointer(); @@ -444,12 +284,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.reset = function() { - this.hover = false; - this.pressEnterLaserTarget = null; - this.laserTarget = null; - this.laserTargetID = null; - this.laserPressingTarget = false; - this.previousLaserClickedTarget = null; this.mode = "none"; this.active = false; }; @@ -467,35 +301,13 @@ Script.include("/~/system/libraries/controllers.js"); }; this.isReady = function (controllerData) { - this.target = null; - var intersection = controllerData.rayPicks[this.hand]; - if (intersection.type === RayPick.INTERSECTED_OVERLAY) { - if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE && !this.getOtherModule().active) { - this.target = intersection.objectID; - this.active = true; - return makeRunningValues(true, [], []); - } else { - this.deleteContextOverlay(); - } + if (this.processLaser(controllerData)) { + return makeRunningValues(true, [], []); } - this.reset(); return makeRunningValues(false, [], []); }; this.run = function (controllerData, deltaTime) { - if (this.shouldExit(controllerData)) { - this.exitModule(); - return makeRunningValues(false, [], []); - } - - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { - this.deleteContextOverlay(); - } - - this.updateLaserTargets(controllerData); - this.processControllerTriggers(controllerData); - this.updateLaserPointer(controllerData); - if (!this.previousLaserClickedTarget && this.laserPressingTarget) { this.laserPressEnter(); } @@ -508,11 +320,11 @@ Script.include("/~/system/libraries/controllers.js"); this.laserPressing(controllerData, deltaTime); } - if (this.hover) { - this.hovering(); + if (this.processLaser(controllerData)) { + return makeRunningValues(true, [], []); + } else { + return makeRunningValues(false, [], []); } - - return makeRunningValues(true, [], []); }; this.cleanup = function () { diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index 230038adb5..52706fc6d7 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -16,7 +16,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { - + var touchEvent = Script.require("/~/system/libraries/touchEventUtils.js"); // triggered when stylus presses a web overlay/entity var HAPTIC_STYLUS_STRENGTH = 1.0; var HAPTIC_STYLUS_DURATION = 20.0; @@ -25,230 +25,6 @@ Script.include("/~/system/libraries/controllers.js"); var WEB_STYLUS_LENGTH = 0.2; var WEB_TOUCH_Y_OFFSET = 0.05; // how far forward (or back with a negative number) to slide stylus in hand - - function stylusTargetHasKeyboardFocus(stylusTarget) { - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID) { - return Entities.keyboardFocusEntity === stylusTarget.entityID; - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - return Overlays.keyboardFocusOverlay === stylusTarget.overlayID; - } - } - - function setKeyboardFocusOnStylusTarget(stylusTarget) { - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID && - Entities.wantsHandControllerPointerEvents(stylusTarget.entityID)) { - Overlays.keyboardFocusOverlay = NULL_UUID; - Entities.keyboardFocusEntity = stylusTarget.entityID; - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - Overlays.keyboardFocusOverlay = stylusTarget.overlayID; - Entities.keyboardFocusEntity = NULL_UUID; - } - } - - function sendHoverEnterEventToStylusTarget(hand, stylusTarget) { - var pointerEvent = { - type: "Move", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: stylusTarget.position2D, - pos3D: stylusTarget.position, - normal: stylusTarget.normal, - direction: Vec3.subtract(ZERO_VEC, stylusTarget.normal), - button: "None" - }; - - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID) { - Entities.sendHoverEnterEntity(stylusTarget.entityID, pointerEvent); - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - Overlays.sendHoverEnterOverlay(stylusTarget.overlayID, pointerEvent); - } - } - - function sendHoverOverEventToStylusTarget(hand, stylusTarget) { - var pointerEvent = { - type: "Move", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: stylusTarget.position2D, - pos3D: stylusTarget.position, - normal: stylusTarget.normal, - direction: Vec3.subtract(ZERO_VEC, stylusTarget.normal), - button: "None" - }; - - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID) { - Entities.sendMouseMoveOnEntity(stylusTarget.entityID, pointerEvent); - Entities.sendHoverOverEntity(stylusTarget.entityID, pointerEvent); - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - Overlays.sendMouseMoveOnOverlay(stylusTarget.overlayID, pointerEvent); - Overlays.sendHoverOverOverlay(stylusTarget.overlayID, pointerEvent); - } - } - - function sendTouchStartEventToStylusTarget(hand, stylusTarget) { - var pointerEvent = { - type: "Press", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: stylusTarget.position2D, - pos3D: stylusTarget.position, - normal: stylusTarget.normal, - direction: Vec3.subtract(ZERO_VEC, stylusTarget.normal), - button: "Primary", - isPrimaryHeld: true - }; - - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID) { - Entities.sendMousePressOnEntity(stylusTarget.entityID, pointerEvent); - Entities.sendClickDownOnEntity(stylusTarget.entityID, pointerEvent); - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - Overlays.sendMousePressOnOverlay(stylusTarget.overlayID, pointerEvent); - } - } - - function sendTouchEndEventToStylusTarget(hand, stylusTarget) { - var pointerEvent = { - type: "Release", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: stylusTarget.position2D, - pos3D: stylusTarget.position, - normal: stylusTarget.normal, - direction: Vec3.subtract(ZERO_VEC, stylusTarget.normal), - button: "Primary" - }; - - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID) { - Entities.sendMouseReleaseOnEntity(stylusTarget.entityID, pointerEvent); - Entities.sendClickReleaseOnEntity(stylusTarget.entityID, pointerEvent); - Entities.sendHoverLeaveEntity(stylusTarget.entityID, pointerEvent); - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - Overlays.sendMouseReleaseOnOverlay(stylusTarget.overlayID, pointerEvent); - } - } - - function sendTouchMoveEventToStylusTarget(hand, stylusTarget) { - var pointerEvent = { - type: "Move", - id: hand + 1, // 0 is reserved for hardware mouse - pos2D: stylusTarget.position2D, - pos3D: stylusTarget.position, - normal: stylusTarget.normal, - direction: Vec3.subtract(ZERO_VEC, stylusTarget.normal), - button: "Primary", - isPrimaryHeld: true - }; - - if (stylusTarget.entityID && stylusTarget.entityID !== NULL_UUID) { - Entities.sendMouseMoveOnEntity(stylusTarget.entityID, pointerEvent); - Entities.sendHoldingClickOnEntity(stylusTarget.entityID, pointerEvent); - } else if (stylusTarget.overlayID && stylusTarget.overlayID !== NULL_UUID) { - Overlays.sendMouseMoveOnOverlay(stylusTarget.overlayID, pointerEvent); - } - } - - // will return undefined if overlayID does not exist. - function calculateStylusTargetFromOverlay(stylusTip, overlayID) { - var overlayPosition = Overlays.getProperty(overlayID, "position"); - if (overlayPosition === undefined) { - return; - } - - // project stylusTip onto overlay plane. - var overlayRotation = Overlays.getProperty(overlayID, "rotation"); - if (overlayRotation === undefined) { - return; - } - var normal = Vec3.multiplyQbyV(overlayRotation, {x: 0, y: 0, z: 1}); - var distance = Vec3.dot(Vec3.subtract(stylusTip.position, overlayPosition), normal); - var position = Vec3.subtract(stylusTip.position, Vec3.multiply(normal, distance)); - - // calclulate normalized position - var invRot = Quat.inverse(overlayRotation); - var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, overlayPosition)); - var dpi = Overlays.getProperty(overlayID, "dpi"); - - var dimensions; - if (dpi) { - // Calculate physical dimensions for web3d overlay from resolution and dpi; "dimensions" property - // is used as a scale. - var resolution = Overlays.getProperty(overlayID, "resolution"); - if (resolution === undefined) { - return; - } - resolution.z = 1; // Circumvent divide-by-zero. - var scale = Overlays.getProperty(overlayID, "dimensions"); - if (scale === undefined) { - return; - } - scale.z = 0.01; // overlay dimensions are 2D, not 3D. - dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale); - } else { - dimensions = Overlays.getProperty(overlayID, "dimensions"); - if (dimensions === undefined) { - return; - } - if (!dimensions.z) { - dimensions.z = 0.01; // sometimes overlay dimensions are 2D, not 3D. - } - } - var invDimensions = { x: 1 / dimensions.x, y: 1 / dimensions.y, z: 1 / dimensions.z }; - var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), DEFAULT_REGISTRATION_POINT); - - // 2D position on overlay plane in meters, relative to the bounding box upper-left hand corner. - var position2D = { - x: normalizedPosition.x * dimensions.x, - y: (1 - normalizedPosition.y) * dimensions.y // flip y-axis - }; - - return { - entityID: null, - overlayID: overlayID, - distance: distance, - position: position, - position2D: position2D, - normal: normal, - normalizedPosition: normalizedPosition, - dimensions: dimensions, - valid: true - }; - } - - // will return undefined if entity does not exist. - function calculateStylusTargetFromEntity(stylusTip, props) { - if (props.rotation === undefined) { - // if rotation is missing from props object, then this entity has probably been deleted. - return; - } - - // project stylus tip onto entity plane. - var normal = Vec3.multiplyQbyV(props.rotation, {x: 0, y: 0, z: 1}); - Vec3.multiplyQbyV(props.rotation, {x: 0, y: 1, z: 0}); - var distance = Vec3.dot(Vec3.subtract(stylusTip.position, props.position), normal); - var position = Vec3.subtract(stylusTip.position, Vec3.multiply(normal, distance)); - - // generate normalized coordinates - var invRot = Quat.inverse(props.rotation); - var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, props.position)); - var invDimensions = { x: 1 / props.dimensions.x, y: 1 / props.dimensions.y, z: 1 / props.dimensions.z }; - var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), props.registrationPoint); - - // 2D position on entity plane in meters, relative to the bounding box upper-left hand corner. - var position2D = { - x: normalizedPosition.x * props.dimensions.x, - y: (1 - normalizedPosition.y) * props.dimensions.y // flip y-axis - }; - - return { - entityID: props.id, - entityProps: props, - overlayID: null, - distance: distance, - position: position, - position2D: position2D, - normal: normal, - normalizedPosition: normalizedPosition, - dimensions: props.dimensions, - valid: true - }; - } - function isNearStylusTarget(stylusTargets, edgeBorder, minNormalDistance, maxNormalDistance) { for (var i = 0; i < stylusTargets.length; i++) { var stylusTarget = stylusTargets[i]; @@ -330,7 +106,7 @@ Script.include("/~/system/libraries/controllers.js"); 100); this.getOtherHandController = function() { - return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand; + return (this.hand === RIGHT_HAND) ? leftTabletStylusInput : rightTabletStylusInput; }; this.handToController = function() { @@ -430,12 +206,12 @@ Script.include("/~/system/libraries/controllers.js"); stylusTarget.entityID !== this.hoverEntity && stylusTarget.entityID !== this.getOtherHandController().hoverEntity) { this.hoverEntity = stylusTarget.entityID; - sendHoverEnterEventToStylusTarget(this.hand, stylusTarget); + touchEvent.sendHoverEnterEventToTouchTarget(this.hand, stylusTarget); } else if (stylusTarget.overlayID && stylusTarget.overlayID !== this.hoverOverlay && stylusTarget.overlayID !== this.getOtherHandController().hoverOverlay) { this.hoverOverlay = stylusTarget.overlayID; - sendHoverEnterEventToStylusTarget(this.hand, stylusTarget); + touchEvent.sendHoverEnterEventToTouchTarget(this.hand, stylusTarget); } }; @@ -492,7 +268,7 @@ Script.include("/~/system/libraries/controllers.js"); for (i = 0; i < candidateEntities.length; i++) { props = candidateEntities[i]; if (props && props.type === "Web") { - stylusTarget = calculateStylusTargetFromEntity(this.stylusTip, candidateEntities[i]); + stylusTarget = touchEvent.calculateTouchTargetFromEntity(this.stylusTip, candidateEntities[i]); if (stylusTarget) { stylusTargets.push(stylusTarget); } @@ -502,7 +278,7 @@ Script.include("/~/system/libraries/controllers.js"); // add the tabletScreen, if it is valid if (HMD.tabletScreenID && HMD.tabletScreenID !== NULL_UUID && Overlays.getProperty(HMD.tabletScreenID, "visible")) { - stylusTarget = calculateStylusTargetFromOverlay(this.stylusTip, HMD.tabletScreenID); + stylusTarget = touchEvent.calculateTouchTargetFromOverlay(this.stylusTip, HMD.tabletScreenID); if (stylusTarget) { stylusTargets.push(stylusTarget); } @@ -511,7 +287,7 @@ Script.include("/~/system/libraries/controllers.js"); // add the tablet home button. if (HMD.homeButtonID && HMD.homeButtonID !== NULL_UUID && Overlays.getProperty(HMD.homeButtonID, "visible")) { - stylusTarget = calculateStylusTargetFromOverlay(this.stylusTip, HMD.homeButtonID); + stylusTarget = touchEvent.calculateTouchTargetFromOverlay(this.stylusTip, HMD.homeButtonID); if (stylusTarget) { stylusTargets.push(stylusTarget); } @@ -530,9 +306,9 @@ Script.include("/~/system/libraries/controllers.js"); var sensorScaleFactor = MyAvatar.sensorToWorldScale; this.isNearStylusTarget = isNearStylusTarget(stylusTargets, - (EDGE_BORDER + hysteresisOffset) * sensorScaleFactor, - (TABLET_MIN_TOUCH_DISTANCE - hysteresisOffset) * sensorScaleFactor, - (WEB_DISPLAY_STYLUS_DISTANCE + hysteresisOffset) * sensorScaleFactor); + (EDGE_BORDER + hysteresisOffset) * sensorScaleFactor, + (TABLET_MIN_TOUCH_DISTANCE - hysteresisOffset) * sensorScaleFactor, + (WEB_DISPLAY_STYLUS_DISTANCE + hysteresisOffset) * sensorScaleFactor); if (this.isNearStylusTarget) { if (!this.useFingerInsteadOfStylus) { @@ -556,12 +332,12 @@ Script.include("/~/system/libraries/controllers.js"); this.requestTouchFocus(nearestStylusTarget); - if (!stylusTargetHasKeyboardFocus(nearestStylusTarget)) { - setKeyboardFocusOnStylusTarget(nearestStylusTarget); + if (!touchEvent.touchTargetHasKeyboardFocus(nearestStylusTarget)) { + touchEvent.setKeyboardFocusOnTouchTarget(nearestStylusTarget); } - if (this.hasTouchFocus(nearestStylusTarget)) { - sendHoverOverEventToStylusTarget(this.hand, nearestStylusTarget); + if (this.hasTouchFocus(nearestStylusTarget) && !this.stylusTouchingTarget) { + touchEvent.sendHoverOverEventToTouchTarget(this.hand, nearestStylusTarget); } // filter out presses when tip is moving away from tablet. @@ -592,14 +368,14 @@ Script.include("/~/system/libraries/controllers.js"); this.stylusTouchingEnter = function () { this.stealTouchFocus(this.stylusTarget); - sendTouchStartEventToStylusTarget(this.hand, this.stylusTarget); + touchEvent.sendTouchStartEventToTouchTarget(this.hand, this.stylusTarget); Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand); this.touchingEnterTimer = 0; this.touchingEnterStylusTarget = this.stylusTarget; this.deadspotExpired = false; - var TOUCH_PRESS_TO_MOVE_DEADSPOT = 0.0381; + var TOUCH_PRESS_TO_MOVE_DEADSPOT = 0.0481; this.deadspotRadius = TOUCH_PRESS_TO_MOVE_DEADSPOT; }; @@ -616,9 +392,9 @@ Script.include("/~/system/libraries/controllers.js"); // send press event if (this.deadspotExpired) { - sendTouchEndEventToStylusTarget(this.hand, this.stylusTarget); + touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.stylusTarget); } else { - sendTouchEndEventToStylusTarget(this.hand, this.touchingEnterStylusTarget); + touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.touchingEnterStylusTarget); } }; @@ -627,9 +403,9 @@ Script.include("/~/system/libraries/controllers.js"); this.touchingEnterTimer += dt; if (this.stylusTarget.entityID) { - this.stylusTarget = calculateStylusTargetFromEntity(this.stylusTip, this.stylusTarget.entityProps); + this.stylusTarget = touchEvent.calculateTouchTargetFromEntity(this.stylusTip, this.stylusTarget.entityProps); } else if (this.stylusTarget.overlayID) { - this.stylusTarget = calculateStylusTargetFromOverlay(this.stylusTip, this.stylusTarget.overlayID); + this.stylusTarget = touchEvent.calculateTouchTargetFromOverlay(this.stylusTip, this.stylusTarget.overlayID); } var TABLET_MIN_TOUCH_DISTANCE = -0.1; @@ -642,7 +418,7 @@ Script.include("/~/system/libraries/controllers.js"); if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY || distance2D(this.stylusTarget.position2D, this.touchingEnterStylusTarget.position2D) > this.deadspotRadius) { - sendTouchMoveEventToStylusTarget(this.hand, this.stylusTarget); + touchEvent.sendTouchMoveEventToTouchTarget(this.hand, this.stylusTarget); this.deadspotExpired = true; } } else { @@ -657,7 +433,7 @@ Script.include("/~/system/libraries/controllers.js"); var overlayLaserModule = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightOverlayLaserInput" : "LeftOverlayLaserInput"); if (overlayLaserModule) { - return overlayLaserModule.isReady(controllerData).active; + return !overlayLaserModule.shouldExit(controllerData); } return false; }; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 33eec74111..10931e4e93 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -318,6 +318,8 @@ if (typeof module !== 'undefined') { makeRunningValues: makeRunningValues, LEFT_HAND: LEFT_HAND, RIGHT_HAND: RIGHT_HAND, - BUMPER_ON_VALUE: BUMPER_ON_VALUE + BUMPER_ON_VALUE: BUMPER_ON_VALUE, + projectOntoOverlayXYPlane: projectOntoOverlayXYPlane, + projectOntoEntityXYPlane: projectOntoEntityXYPlane }; } diff --git a/scripts/system/libraries/touchEventUtils.js b/scripts/system/libraries/touchEventUtils.js new file mode 100644 index 0000000000..fbd56e16ae --- /dev/null +++ b/scripts/system/libraries/touchEventUtils.js @@ -0,0 +1,270 @@ +"use strict"; + +// touchEventUtils.js +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, + controllerDispatcher.NULL_UUID, enableDispatcherModule, disableDispatcherModule, makeRunningValues, + Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, controllerDispatcher.ZERO_VEC, + AVATAR_SELF_ID, HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset +*/ + +var controllerDispatcher = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); +function touchTargetHasKeyboardFocus(touchTarget) { + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID) { + return Entities.keyboardFocusEntity === touchTarget.entityID; + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + return Overlays.keyboardFocusOverlay === touchTarget.overlayID; + } +} + +function setKeyboardFocusOnTouchTarget(touchTarget) { + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID && + Entities.wantsHandControllerPointerEvents(touchTarget.entityID)) { + Overlays.keyboardFocusOverlay = controllerDispatcher.NULL_UUID; + Entities.keyboardFocusEntity = touchTarget.entityID; + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + Overlays.keyboardFocusOverlay = touchTarget.overlayID; + Entities.keyboardFocusEntity = controllerDispatcher.NULL_UUID; + } +} + +function sendHoverEnterEventToTouchTarget(hand, touchTarget) { + var pointerEvent = { + type: "Move", + id: hand + 1, // 0 is reserved for hardware mouse + pos2D: touchTarget.position2D, + pos3D: touchTarget.position, + normal: touchTarget.normal, + direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal), + button: "None" + }; + + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID) { + Entities.sendHoverEnterEntity(touchTarget.entityID, pointerEvent); + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + Overlays.sendHoverEnterOverlay(touchTarget.overlayID, pointerEvent); + } +} + +function sendHoverOverEventToTouchTarget(hand, touchTarget) { + var pointerEvent = { + type: "Move", + id: hand + 1, // 0 is reserved for hardware mouse + pos2D: touchTarget.position2D, + pos3D: touchTarget.position, + normal: touchTarget.normal, + direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal), + button: "None" + }; + + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID) { + Entities.sendMouseMoveOnEntity(touchTarget.entityID, pointerEvent); + Entities.sendHoverOverEntity(touchTarget.entityID, pointerEvent); + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + Overlays.sendMouseMoveOnOverlay(touchTarget.overlayID, pointerEvent); + Overlays.sendHoverOverOverlay(touchTarget.overlayID, pointerEvent); + } +} + +function sendTouchStartEventToTouchTarget(hand, touchTarget) { + var pointerEvent = { + type: "Press", + id: hand + 1, // 0 is reserved for hardware mouse + pos2D: touchTarget.position2D, + pos3D: touchTarget.position, + normal: touchTarget.normal, + direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal), + button: "Primary", + isPrimaryHeld: true + }; + + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID) { + Entities.sendMousePressOnEntity(touchTarget.entityID, pointerEvent); + Entities.sendClickDownOnEntity(touchTarget.entityID, pointerEvent); + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + Overlays.sendMousePressOnOverlay(touchTarget.overlayID, pointerEvent); + } +} + +function sendTouchEndEventToTouchTarget(hand, touchTarget) { + var pointerEvent = { + type: "Release", + id: hand + 1, // 0 is reserved for hardware mouse + pos2D: touchTarget.position2D, + pos3D: touchTarget.position, + normal: touchTarget.normal, + direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal), + button: "Primary" + }; + + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID) { + Entities.sendMouseReleaseOnEntity(touchTarget.entityID, pointerEvent); + Entities.sendClickReleaseOnEntity(touchTarget.entityID, pointerEvent); + Entities.sendHoverLeaveEntity(touchTarget.entityID, pointerEvent); + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + Overlays.sendMouseReleaseOnOverlay(touchTarget.overlayID, pointerEvent); + } +} + +function sendTouchMoveEventToTouchTarget(hand, touchTarget) { + var pointerEvent = { + type: "Move", + id: hand + 1, // 0 is reserved for hardware mouse + pos2D: touchTarget.position2D, + pos3D: touchTarget.position, + normal: touchTarget.normal, + direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal), + button: "Primary", + isPrimaryHeld: true + }; + + if (touchTarget.entityID && touchTarget.entityID !== controllerDispatcher.NULL_UUID) { + Entities.sendMouseMoveOnEntity(touchTarget.entityID, pointerEvent); + Entities.sendHoldingClickOnEntity(touchTarget.entityID, pointerEvent); + } else if (touchTarget.overlayID && touchTarget.overlayID !== controllerDispatcher.NULL_UUID) { + Overlays.sendMouseMoveOnOverlay(touchTarget.overlayID, pointerEvent); + } +} + +function composeTouchTargetFromIntersection(intersection) { + var isEntity = (intersection.type === RayPick.INTERSECTED_ENTITY); + var objectID = intersection.objectID; + var worldPos = intersection.intersection; + var props = null; + if (isEntity) { + props = Entities.getProperties(intersection.objectID); + } + + var position2D =(isEntity ? controllerDispatcher.projectOntoEntityXYPlane(objectID, worldPos, props) : + controllerDispatcher.projectOntoOverlayXYPlane(objectID, worldPos)); + return { + entityID: isEntity ? objectID : null, + overlayID: isEntity ? null : objectID, + distance: intersection.distance, + position: worldPos, + position2D: position2D, + normal: intersection.surfaceNormal + }; +} + +// will return undefined if overlayID does not exist. +function calculateTouchTargetFromOverlay(touchTip, overlayID) { + var overlayPosition = Overlays.getProperty(overlayID, "position"); + if (overlayPosition === undefined) { + return; + } + + // project touchTip onto overlay plane. + var overlayRotation = Overlays.getProperty(overlayID, "rotation"); + if (overlayRotation === undefined) { + return; + } + var normal = Vec3.multiplyQbyV(overlayRotation, {x: 0, y: 0, z: 1}); + var distance = Vec3.dot(Vec3.subtract(touchTip.position, overlayPosition), normal); + var position = Vec3.subtract(touchTip.position, Vec3.multiply(normal, distance)); + + // calclulate normalized position + var invRot = Quat.inverse(overlayRotation); + var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, overlayPosition)); + var dpi = Overlays.getProperty(overlayID, "dpi"); + + var dimensions; + if (dpi) { + // Calculate physical dimensions for web3d overlay from resolution and dpi; "dimensions" property + // is used as a scale. + var resolution = Overlays.getProperty(overlayID, "resolution"); + if (resolution === undefined) { + return; + } + resolution.z = 1; // Circumvent divide-by-zero. + var scale = Overlays.getProperty(overlayID, "dimensions"); + if (scale === undefined) { + return; + } + scale.z = 0.01; // overlay dimensions are 2D, not 3D. + dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale); + } else { + dimensions = Overlays.getProperty(overlayID, "dimensions"); + if (dimensions === undefined) { + return; + } + if (!dimensions.z) { + dimensions.z = 0.01; // sometimes overlay dimensions are 2D, not 3D. + } + } + var invDimensions = { x: 1 / dimensions.x, y: 1 / dimensions.y, z: 1 / dimensions.z }; + var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), DEFAULT_REGISTRATION_POINT); + + // 2D position on overlay plane in meters, relative to the bounding box upper-left hand corner. + var position2D = { + x: normalizedPosition.x * dimensions.x, + y: (1 - normalizedPosition.y) * dimensions.y // flip y-axis + }; + + return { + entityID: null, + overlayID: overlayID, + distance: distance, + position: position, + position2D: position2D, + normal: normal, + normalizedPosition: normalizedPosition, + dimensions: dimensions, + valid: true + }; +} + +// will return undefined if entity does not exist. +function calculateTouchTargetFromEntity(touchTip, props) { + if (props.rotation === undefined) { + // if rotation is missing from props object, then this entity has probably been deleted. + return; + } + + // project touch tip onto entity plane. + var normal = Vec3.multiplyQbyV(props.rotation, {x: 0, y: 0, z: 1}); + Vec3.multiplyQbyV(props.rotation, {x: 0, y: 1, z: 0}); + var distance = Vec3.dot(Vec3.subtract(touchTip.position, props.position), normal); + var position = Vec3.subtract(touchTip.position, Vec3.multiply(normal, distance)); + + // generate normalized coordinates + var invRot = Quat.inverse(props.rotation); + var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, props.position)); + var invDimensions = { x: 1 / props.dimensions.x, y: 1 / props.dimensions.y, z: 1 / props.dimensions.z }; + var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), props.registrationPoint); + + // 2D position on entity plane in meters, relative to the bounding box upper-left hand corner. + var position2D = { + x: normalizedPosition.x * props.dimensions.x, + y: (1 - normalizedPosition.y) * props.dimensions.y // flip y-axis + }; + + return { + entityID: props.id, + entityProps: props, + overlayID: null, + distance: distance, + position: position, + position2D: position2D, + normal: normal, + normalizedPosition: normalizedPosition, + dimensions: props.dimensions, + valid: true + }; +} + +module.exports = { + calculateTouchTargetFromEntity: calculateTouchTargetFromEntity, + calculateTouchTargetFromOverlay: calculateTouchTargetFromOverlay, + touchTargetHasKeyboardFocus: touchTargetHasKeyboardFocus, + setKeyboardFocusOnTouchTarget: setKeyboardFocusOnTouchTarget, + sendHoverEnterEventToTouchTarget: sendHoverEnterEventToTouchTarget, + sendHoverOverEventToTouchTarget: sendHoverOverEventToTouchTarget, + sendTouchStartEventToTouchTarget: sendTouchStartEventToTouchTarget, + sendTouchEndEventToTouchTarget: sendTouchEndEventToTouchTarget, + sendTouchMoveEventToTouchTarget: sendTouchMoveEventToTouchTarget, + composeTouchTargetFromIntersection: composeTouchTargetFromIntersection +}; From 80f56e48caff308426c4a06cbf36aa24e924a93a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 20 Sep 2017 16:50:19 +1200 Subject: [PATCH 27/37] Fix Record app's toolbar button not highlighting when app dialog open --- unpublishedScripts/marketplace/record/record.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 5439d68c9a..6110721ff9 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -571,7 +571,7 @@ function onTabletScreenChanged(type, url) { // Opened/closed dialog in tablet or window. - var RECORD_URL = "/scripts/system/html/record.html"; + var RECORD_URL = "/html/record.html"; if (type === "Web" && url.slice(-RECORD_URL.length) === RECORD_URL) { if (Dialog.finishOnOpen()) { From e78d8bc13259cd991fafcaf0f7179daaee79e4ce Mon Sep 17 00:00:00 2001 From: druiz17 Date: Wed, 20 Sep 2017 09:11:06 -0700 Subject: [PATCH 28/37] tablet on wiki planet --- scripts/system/libraries/WebTablet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index d1182f197c..21f0fac01a 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -51,7 +51,7 @@ function calcSpawnInfo(hand, landscape) { var forward = Quat.getForward(headRot); var FORWARD_OFFSET = 0.6 * MyAvatar.sensorToWorldScale; finalPosition = Vec3.sum(headPos, Vec3.multiply(FORWARD_OFFSET, forward)); - var orientation = Quat.lookAt({x: 0, y: 0, z: 0}, forward, {x: 0, y: 1, z: 0}); + var orientation = Quat.lookAt({x: 0, y: 0, z: 0}, forward, Vec3.multiplyQbyV(MyAvatar.orientation, Vec3.UNIT_Y)); return { position: finalPosition, rotation: landscape ? Quat.multiply(orientation, ROT_LANDSCAPE) : Quat.multiply(orientation, ROT_Y_180) From 5d87036f321aaefc6c5d55ef0aa3779d14973792 Mon Sep 17 00:00:00 2001 From: druiz17 Date: Wed, 20 Sep 2017 11:41:31 -0700 Subject: [PATCH 29/37] make changes requests and slight fixes --- .../controllerModules/overlayLaserInput.js | 40 ++++++++++++------ .../controllerModules/tabletStylusInput.js | 41 +++++++++---------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 9bf7ed23da..a5057f98cd 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -16,7 +16,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { - var touchEvent = Script.require("/~/system/libraries/touchEventUtils.js"); + var TouchEventUtils = Script.require("/~/system/libraries/touchEventUtils.js"); var halfPath = { type: "line3d", color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, @@ -131,7 +131,7 @@ Script.include("/~/system/libraries/controllers.js"); if (laserTarget.overlayID && laserTarget.overlayID !== this.hoverOverlay) { this.hoverOverlay = laserTarget.overlayID; - touchEvent.sendHoverEnterEventToTouchTarget(this.hand, laserTarget); + TouchEventUtils.sendHoverEnterEventToTouchTarget(this.hand, laserTarget); } }; @@ -146,11 +146,27 @@ Script.include("/~/system/libraries/controllers.js"); } }; + this.relinquishStylusTargetTouchFocus = function(laserTarget) { + var stylusModuleNames = ["LeftTabletStylusInput", "RightTabletStylusError"]; + for (var i = 0; i < stylusModuleNames.length; i++) { + var stylusModule = getEnabledModuleByName(stylusModuleNames[i]); + if (stylusModule) { + if (stylusModule.hoverOverlay === laserTarget.overlayID) { + stylusModule.relinquishTouchFocus(); + } + } + } + }; + this.stealTouchFocus = function(laserTarget) { if (laserTarget.overlayID === this.getOtherModule().hoverOverlay) { this.getOtherModule().relinquishTouchFocus(); } + // If the focus target we want to request is the same of one of the stylus + // tell the stylus to relinquish it focus on out target + this.relinquishStylusTargetTouchFocus(laserTarget); + this.requestTouchFocus(laserTarget); }; @@ -182,7 +198,7 @@ Script.include("/~/system/libraries/controllers.js"); this.laserPressEnter = function () { this.stealTouchFocus(this.laserTarget); - touchEvent.sendTouchStartEventToTouchTarget(this.hand, this.laserTarget); + TouchEventUtils.sendTouchStartEventToTouchTarget(this.hand, this.laserTarget); Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand); this.touchingEnterTimer = 0; @@ -205,9 +221,9 @@ Script.include("/~/system/libraries/controllers.js"); // send press event if (this.deadspotExpired) { - touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.laserTarget); + TouchEventUtils.sendTouchEndEventToTouchTarget(this.hand, this.laserTarget); } else { - touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.pressEnterLaserTarget); + TouchEventUtils.sendTouchEndEventToTouchTarget(this.hand, this.pressEnterLaserTarget); } }; @@ -219,8 +235,8 @@ Script.include("/~/system/libraries/controllers.js"); var POINTER_PRESS_TO_MOVE_DELAY = 0.33; // seconds if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY || distance2D(this.laserTarget.position2D, - this.pressEnterLaserTarget.position2D) > this.deadspotRadius) { - touchEvent.sendTouchMoveEventToTouchTarget(this.hand, this.laserTarget); + this.pressEnterLaserTarget.position2D) > this.deadspotRadius) { + TouchEventUtils.sendTouchMoveEventToTouchTarget(this.hand, this.laserTarget); this.deadspotExpired = true; } } else { @@ -237,7 +253,7 @@ Script.include("/~/system/libraries/controllers.js"); return false; } var intersection = controllerData.rayPicks[this.hand]; - var laserTarget = touchEvent.composeTouchTargetFromIntersection(intersection); + var laserTarget = TouchEventUtils.composeTouchTargetFromIntersection(intersection); if (controllerData.triggerClicks[this.hand]) { this.laserTarget = laserTarget; @@ -245,12 +261,12 @@ Script.include("/~/system/libraries/controllers.js"); } else { this.requestTouchFocus(laserTarget); - if (!touchEvent.touchTargetHasKeyboardFocus(laserTarget)) { - touchEvent.setKeyboardFocusOnTouchTarget(laserTarget); + if (!TouchEventUtils.touchTargetHasKeyboardFocus(laserTarget)) { + TouchEventUtils.setKeyboardFocusOnTouchTarget(laserTarget); } - + if (this.hasTouchFocus(laserTarget) && !this.laserPressingTarget) { - touchEvent.sendHoverOverEventToTouchTarget(this.hand, laserTarget); + TouchEventUtils.sendHoverOverEventToTouchTarget(this.hand, laserTarget); } } diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index 52706fc6d7..c61a236bb6 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -16,7 +16,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { - var touchEvent = Script.require("/~/system/libraries/touchEventUtils.js"); + var TouchEventUtils = Script.require("/~/system/libraries/touchEventUtils.js"); // triggered when stylus presses a web overlay/entity var HAPTIC_STYLUS_STRENGTH = 1.0; var HAPTIC_STYLUS_DURATION = 20.0; @@ -206,12 +206,12 @@ Script.include("/~/system/libraries/controllers.js"); stylusTarget.entityID !== this.hoverEntity && stylusTarget.entityID !== this.getOtherHandController().hoverEntity) { this.hoverEntity = stylusTarget.entityID; - touchEvent.sendHoverEnterEventToTouchTarget(this.hand, stylusTarget); + TouchEventUtils.sendHoverEnterEventToTouchTarget(this.hand, stylusTarget); } else if (stylusTarget.overlayID && stylusTarget.overlayID !== this.hoverOverlay && stylusTarget.overlayID !== this.getOtherHandController().hoverOverlay) { this.hoverOverlay = stylusTarget.overlayID; - touchEvent.sendHoverEnterEventToTouchTarget(this.hand, stylusTarget); + TouchEventUtils.sendHoverEnterEventToTouchTarget(this.hand, stylusTarget); } }; @@ -268,7 +268,7 @@ Script.include("/~/system/libraries/controllers.js"); for (i = 0; i < candidateEntities.length; i++) { props = candidateEntities[i]; if (props && props.type === "Web") { - stylusTarget = touchEvent.calculateTouchTargetFromEntity(this.stylusTip, candidateEntities[i]); + stylusTarget = TouchEventUtils.calculateTouchTargetFromEntity(this.stylusTip, candidateEntities[i]); if (stylusTarget) { stylusTargets.push(stylusTarget); } @@ -278,7 +278,7 @@ Script.include("/~/system/libraries/controllers.js"); // add the tabletScreen, if it is valid if (HMD.tabletScreenID && HMD.tabletScreenID !== NULL_UUID && Overlays.getProperty(HMD.tabletScreenID, "visible")) { - stylusTarget = touchEvent.calculateTouchTargetFromOverlay(this.stylusTip, HMD.tabletScreenID); + stylusTarget = TouchEventUtils.calculateTouchTargetFromOverlay(this.stylusTip, HMD.tabletScreenID); if (stylusTarget) { stylusTargets.push(stylusTarget); } @@ -287,7 +287,7 @@ Script.include("/~/system/libraries/controllers.js"); // add the tablet home button. if (HMD.homeButtonID && HMD.homeButtonID !== NULL_UUID && Overlays.getProperty(HMD.homeButtonID, "visible")) { - stylusTarget = touchEvent.calculateTouchTargetFromOverlay(this.stylusTip, HMD.homeButtonID); + stylusTarget = TouchEventUtils.calculateTouchTargetFromOverlay(this.stylusTip, HMD.homeButtonID); if (stylusTarget) { stylusTargets.push(stylusTarget); } @@ -332,12 +332,12 @@ Script.include("/~/system/libraries/controllers.js"); this.requestTouchFocus(nearestStylusTarget); - if (!touchEvent.touchTargetHasKeyboardFocus(nearestStylusTarget)) { - touchEvent.setKeyboardFocusOnTouchTarget(nearestStylusTarget); + if (!TouchEventUtils.touchTargetHasKeyboardFocus(nearestStylusTarget)) { + TouchEventUtils.setKeyboardFocusOnTouchTarget(nearestStylusTarget); } if (this.hasTouchFocus(nearestStylusTarget) && !this.stylusTouchingTarget) { - touchEvent.sendHoverOverEventToTouchTarget(this.hand, nearestStylusTarget); + TouchEventUtils.sendHoverOverEventToTouchTarget(this.hand, nearestStylusTarget); } // filter out presses when tip is moving away from tablet. @@ -368,7 +368,7 @@ Script.include("/~/system/libraries/controllers.js"); this.stylusTouchingEnter = function () { this.stealTouchFocus(this.stylusTarget); - touchEvent.sendTouchStartEventToTouchTarget(this.hand, this.stylusTarget); + TouchEventUtils.sendTouchStartEventToTouchTarget(this.hand, this.stylusTarget); Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand); this.touchingEnterTimer = 0; @@ -392,9 +392,9 @@ Script.include("/~/system/libraries/controllers.js"); // send press event if (this.deadspotExpired) { - touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.stylusTarget); + TouchEventUtils.sendTouchEndEventToTouchTarget(this.hand, this.stylusTarget); } else { - touchEvent.sendTouchEndEventToTouchTarget(this.hand, this.touchingEnterStylusTarget); + TouchEventUtils.sendTouchEndEventToTouchTarget(this.hand, this.touchingEnterStylusTarget); } }; @@ -403,9 +403,9 @@ Script.include("/~/system/libraries/controllers.js"); this.touchingEnterTimer += dt; if (this.stylusTarget.entityID) { - this.stylusTarget = touchEvent.calculateTouchTargetFromEntity(this.stylusTip, this.stylusTarget.entityProps); + this.stylusTarget = TouchEventUtils.calculateTouchTargetFromEntity(this.stylusTip, this.stylusTarget.entityProps); } else if (this.stylusTarget.overlayID) { - this.stylusTarget = touchEvent.calculateTouchTargetFromOverlay(this.stylusTip, this.stylusTarget.overlayID); + this.stylusTarget = TouchEventUtils.calculateTouchTargetFromOverlay(this.stylusTip, this.stylusTarget.overlayID); } var TABLET_MIN_TOUCH_DISTANCE = -0.1; @@ -418,7 +418,7 @@ Script.include("/~/system/libraries/controllers.js"); if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY || distance2D(this.stylusTarget.position2D, this.touchingEnterStylusTarget.position2D) > this.deadspotRadius) { - touchEvent.sendTouchMoveEventToTouchTarget(this.hand, this.stylusTarget); + TouchEventUtils.sendTouchMoveEventToTouchTarget(this.hand, this.stylusTarget); this.deadspotExpired = true; } } else { @@ -430,12 +430,11 @@ Script.include("/~/system/libraries/controllers.js"); }; this.overlayLaserActive = function(controllerData) { - var overlayLaserModule = - getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightOverlayLaserInput" : "LeftOverlayLaserInput"); - if (overlayLaserModule) { - return !overlayLaserModule.shouldExit(controllerData); - } - return false; + var rightOverlayLaserModule = getEnabledModuleByName("RightOverlayLaserInput"); + var leftOverlayLaserModule = getEnabledModuleByName("LeftOverlayLaserInput"); + var rightModuleRunning = rightOverlayLaserModule ? !rightOverlayLaserModule.shouldExit(controllerData) : false; + var leftModuleRunning = leftOverlayLaserModule ? !leftOverlayLaserModule.shouldExit(controllerData) : false; + return leftModuleRunning || rightModuleRunning; }; this.isReady = function (controllerData) { From 2ce6dcf89dbb8a2368c1a9fcd486b15384e3a55d Mon Sep 17 00:00:00 2001 From: druiz17 Date: Wed, 20 Sep 2017 11:45:42 -0700 Subject: [PATCH 30/37] fixing spelling error --- .../system/controllers/controllerModules/overlayLaserInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index a5057f98cd..e21776ab0a 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -164,7 +164,7 @@ Script.include("/~/system/libraries/controllers.js"); } // If the focus target we want to request is the same of one of the stylus - // tell the stylus to relinquish it focus on out target + // tell the stylus to relinquish it focus on our target this.relinquishStylusTargetTouchFocus(laserTarget); this.requestTouchFocus(laserTarget); From c48aba423ac7c168377d3c73fac0e5bca8155d4b Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 20 Sep 2017 22:48:39 +0200 Subject: [PATCH 31/37] Rename check box --- .../qml/controls-uit/{CheckBox2.qml => CheckBoxQQC2.qml} | 0 interface/resources/qml/hifi/audio/CheckBox.qml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename interface/resources/qml/controls-uit/{CheckBox2.qml => CheckBoxQQC2.qml} (100%) diff --git a/interface/resources/qml/controls-uit/CheckBox2.qml b/interface/resources/qml/controls-uit/CheckBoxQQC2.qml similarity index 100% rename from interface/resources/qml/controls-uit/CheckBox2.qml rename to interface/resources/qml/controls-uit/CheckBoxQQC2.qml diff --git a/interface/resources/qml/hifi/audio/CheckBox.qml b/interface/resources/qml/hifi/audio/CheckBox.qml index 77c001816f..3a954d4004 100644 --- a/interface/resources/qml/hifi/audio/CheckBox.qml +++ b/interface/resources/qml/hifi/audio/CheckBox.qml @@ -13,6 +13,6 @@ import QtQuick 2.7 import "../../controls-uit" as HifiControls -HifiControls.CheckBox2 { +HifiControls.CheckBoxQQC2 { color: "white" } From c20c5ee2b5e812c9c4c8322945abec8ec99b6788 Mon Sep 17 00:00:00 2001 From: druiz17 Date: Wed, 20 Sep 2017 14:10:10 -0700 Subject: [PATCH 32/37] fixed tablet grabbing issue --- .../controllerModules/overlayLaserInput.js | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index e21776ab0a..d67672ca7c 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -276,14 +276,30 @@ Script.include("/~/system/libraries/controllers.js"); return true; }; + this.grabModuleWantsNearbyOverlay = function(controllerData) { + if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { + var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; + var nearGrabModule = getEnabledModuleByName(nearGrabName); + if (nearGrabModule) { + var candidateOverlays = controllerData.nearbyOverlayIDs[this.hand]; + var grabbableOverlays = candidateOverlays.filter(function(overlayID) { + return Overlays.getProperty(overlayID, "grabbable"); + }); + var target = nearGrabModule.getTargetID(grabbableOverlays, controllerData); + if (target) { + return true; + } + } + } + return false; + }; + this.shouldExit = function(controllerData) { var intersection = controllerData.rayPicks[this.hand]; - var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; - var nearGrabModule = getEnabledModuleByName(nearGrabName); - var status = nearGrabModule ? nearGrabModule.isReady(controllerData) : makeRunningValues(false, [], []); var offOverlay = (intersection.type !== RayPick.INTERSECTED_OVERLAY); var triggerOff = (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE); - return offOverlay || status.active || triggerOff; + var grabbingOverlay = this.grabModuleWantsNearbyOverlay(controllerData); + return offOverlay || grabbingOverlay || triggerOff; }; this.exitModule = function() { From 92f3dfe2ab02159c13203f148e414672ddc3bb9b Mon Sep 17 00:00:00 2001 From: druiz17 Date: Wed, 20 Sep 2017 14:23:43 -0700 Subject: [PATCH 33/37] move the stylus back a bit --- .../system/controllers/controllerModules/tabletStylusInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index 230038adb5..4fe1f7a23f 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -23,7 +23,7 @@ Script.include("/~/system/libraries/controllers.js"); var WEB_DISPLAY_STYLUS_DISTANCE = 0.5; var WEB_STYLUS_LENGTH = 0.2; - var WEB_TOUCH_Y_OFFSET = 0.05; // how far forward (or back with a negative number) to slide stylus in hand + var WEB_TOUCH_Y_OFFSET = 0.105; // how far forward (or back with a negative number) to slide stylus in hand function stylusTargetHasKeyboardFocus(stylusTarget) { From f21c99257e24c8b6dcfc22890ab2800ef07b6379 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 20 Sep 2017 14:35:29 -0700 Subject: [PATCH 34/37] don't let scripts control visibility of laser pointers --- interface/src/Application.cpp | 12 ++++++------ interface/src/raypick/LaserPointer.cpp | 4 +++- .../src/raypick/LaserPointerScriptingInterface.cpp | 3 +++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5700bb6a72..a5353a58ad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5159,12 +5159,6 @@ void Application::update(float deltaTime) { } } - { - PROFILE_RANGE_EX(app, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); - PerformanceTimer perfTimer("overlays"); - _overlays.update(deltaTime); - } - { PROFILE_RANGE(app, "RayPickManager"); _rayPickManager.update(); @@ -5175,6 +5169,12 @@ void Application::update(float deltaTime) { _laserPointerManager.update(); } + { + PROFILE_RANGE_EX(app, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PerformanceTimer perfTimer("overlays"); + _overlays.update(deltaTime); + } + // Update _viewFrustum with latest camera and view frustum data... // NOTE: we get this from the view frustum, to make it simpler, since the // loadViewFrumstum() method will get the correct details from the camera diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 9d64bcc476..b696afa8e5 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -86,7 +86,9 @@ void LaserPointer::editRenderState(const std::string& state, const QVariant& sta void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) { if (!id.isNull() && props.isValid()) { - qApp->getOverlays().editOverlay(id, props); + QVariantMap propMap = props.toMap(); + propMap.remove("visible"); + qApp->getOverlays().editOverlay(id, propMap); } } diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index a976a00893..d5e435f490 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -95,6 +95,7 @@ const RenderState LaserPointerScriptingInterface::buildRenderState(const QVarian if (propMap["start"].isValid()) { QVariantMap startMap = propMap["start"].toMap(); if (startMap["type"].isValid()) { + startMap.remove("visible"); startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); } } @@ -104,6 +105,7 @@ const RenderState LaserPointerScriptingInterface::buildRenderState(const QVarian QVariantMap pathMap = propMap["path"].toMap(); // right now paths must be line3ds if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { + pathMap.remove("visible"); pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); } } @@ -112,6 +114,7 @@ const RenderState LaserPointerScriptingInterface::buildRenderState(const QVarian if (propMap["end"].isValid()) { QVariantMap endMap = propMap["end"].toMap(); if (endMap["type"].isValid()) { + endMap.remove("visible"); endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); } } From 60a566768a1cf96ca485309202a1218d0de0e081 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 20 Sep 2017 14:39:13 -0700 Subject: [PATCH 35/37] removed debug spam from makeUserConnection, to reactivate it set `Settings.setValue('MAKE_USER_CONNECTION_DEBUG', true);` and reload the script --- scripts/system/makeUserConnection.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index d95ad919b6..51390d4a78 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -16,6 +16,7 @@ var request = Script.require('request').request; + var WANT_DEBUG = Settings.getValue('MAKE_USER_CONNECTION_DEBUG', false); var LABEL = "makeUserConnection"; var MAX_AVATAR_DISTANCE = 0.2; // m var GRIP_MIN = 0.75; // goes from 0-1, so 75% pressed is pressed @@ -120,6 +121,9 @@ var successfulHandshakeSound; function debug() { + if (!WANT_DEBUG) { + return; + } var stateString = "<" + STATE_STRINGS[state] + ">"; var connecting = "[" + connectingId + "/" + connectingHandJointIndex + "]"; var current = "[" + currentHand + "/" + currentHandJointIndex + "]" @@ -372,7 +376,7 @@ var myHeadIndex = MyAvatar.getJointIndex("Head"); var otherHeadIndex = avatar.getJointIndex("Head"); var diff = (avatar.getJointPosition(otherHeadIndex).y - MyAvatar.getJointPosition(myHeadIndex).y) / 2; - print("head height difference: " + diff); + debug("head height difference: " + diff); updateAnimationData(diff); } } From 7ea1968b337f0e32c9d9e60cdc4c003fa1c6d562 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 20 Sep 2017 14:59:15 -0700 Subject: [PATCH 36/37] Tip, `Code Writer` which comes standard with Windows 10, does enter tabs by default when using the tab key. >=) --- scripts/system/makeUserConnection.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index 51390d4a78..bfad959ffc 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -16,7 +16,7 @@ var request = Script.require('request').request; - var WANT_DEBUG = Settings.getValue('MAKE_USER_CONNECTION_DEBUG', false); + var WANT_DEBUG = Settings.getValue('MAKE_USER_CONNECTION_DEBUG', false); var LABEL = "makeUserConnection"; var MAX_AVATAR_DISTANCE = 0.2; // m var GRIP_MIN = 0.75; // goes from 0-1, so 75% pressed is pressed @@ -121,9 +121,9 @@ var successfulHandshakeSound; function debug() { - if (!WANT_DEBUG) { - return; - } + if (!WANT_DEBUG) { + return; + } var stateString = "<" + STATE_STRINGS[state] + ">"; var connecting = "[" + connectingId + "/" + connectingHandJointIndex + "]"; var current = "[" + currentHand + "/" + currentHandJointIndex + "]" From 2c55419c603856336b7ef5efeb5d27b3049977c2 Mon Sep 17 00:00:00 2001 From: druiz17 Date: Wed, 20 Sep 2017 16:49:45 -0700 Subject: [PATCH 37/37] change tablet forward offset --- scripts/system/libraries/WebTablet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 21f0fac01a..c5f8168c30 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -49,7 +49,7 @@ function calcSpawnInfo(hand, landscape) { var headRot = (HMD.active && Camera.mode === "first person") ? HMD.orientation : Camera.orientation; var forward = Quat.getForward(headRot); - var FORWARD_OFFSET = 0.6 * MyAvatar.sensorToWorldScale; + var FORWARD_OFFSET = 0.5 * MyAvatar.sensorToWorldScale; finalPosition = Vec3.sum(headPos, Vec3.multiply(FORWARD_OFFSET, forward)); var orientation = Quat.lookAt({x: 0, y: 0, z: 0}, forward, Vec3.multiplyQbyV(MyAvatar.orientation, Vec3.UNIT_Y)); return {