diff --git a/interface/resources/icons/hud-01.svg b/interface/resources/icons/hud-01.svg deleted file mode 100644 index 4929389268..0000000000 --- a/interface/resources/icons/hud-01.svg +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/interface/resources/icons/hud.svg b/interface/resources/icons/hud.svg new file mode 100644 index 0000000000..acfd21b909 --- /dev/null +++ b/interface/resources/icons/hud.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index a48804faba..dc060b70e1 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -30,6 +30,7 @@ Window { width: addressBarDialog.implicitWidth height: addressBarDialog.implicitHeight + onShownChanged: addressBarDialog.observeShownChanged(shown); Component.onCompleted: { root.parentChanged.connect(center); center(); diff --git a/interface/resources/qml/controls-uit/SpinBox.qml b/interface/resources/qml/controls-uit/SpinBox.qml index 5d78cfc5a8..a1237d4bc7 100755 --- a/interface/resources/qml/controls-uit/SpinBox.qml +++ b/interface/resources/qml/controls-uit/SpinBox.qml @@ -36,15 +36,15 @@ SpinBox { id: spinStyle background: Rectangle { color: isLightColorScheme - ? (spinBox.focus ? hifi.colors.white : hifi.colors.lightGray) - : (spinBox.focus ? hifi.colors.black : hifi.colors.baseGrayShadow) + ? (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGray) + : (spinBox.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow) border.color: spinBoxLabelInside.visible ? spinBoxLabelInside.color : hifi.colors.primaryHighlight - border.width: spinBox.focus ? spinBoxLabelInside.visible ? 2 : 1 : 0 + border.width: spinBox.activeFocus ? spinBoxLabelInside.visible ? 2 : 1 : 0 } textColor: isLightColorScheme - ? (spinBox.focus ? hifi.colors.black : hifi.colors.lightGray) - : (spinBox.focus ? hifi.colors.white : hifi.colors.lightGrayText) + ? (spinBox.activeFocus ? hifi.colors.black : hifi.colors.lightGray) + : (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGrayText) selectedTextColor: hifi.colors.black selectionColor: hifi.colors.primaryHighlight @@ -96,7 +96,7 @@ SpinBox { anchors.fill: parent propagateComposedEvents: true onWheel: { - if(spinBox.focus) + if(spinBox.activeFocus) wheel.accepted = false else wheel.accepted = true diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index 79027cdc3b..65fab00700 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -36,14 +36,14 @@ TextField { style: TextFieldStyle { textColor: isLightColorScheme - ? (textField.focus ? hifi.colors.black : hifi.colors.lightGray) - : (textField.focus ? hifi.colors.white : hifi.colors.lightGrayText) + ? (textField.activeFocus ? hifi.colors.black : hifi.colors.lightGray) + : (textField.activeFocus ? hifi.colors.white : hifi.colors.lightGrayText) background: Rectangle { color: isLightColorScheme - ? (textField.focus ? hifi.colors.white : hifi.colors.textFieldLightBackground) - : (textField.focus ? hifi.colors.black : hifi.colors.baseGrayShadow) + ? (textField.activeFocus ? hifi.colors.white : hifi.colors.textFieldLightBackground) + : (textField.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow) border.color: hifi.colors.primaryHighlight - border.width: textField.focus ? 1 : 0 + border.width: textField.activeFocus ? 1 : 0 radius: isSearchField ? textField.height / 2 : 0 HiFiGlyphs { diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 27fa9692b9..59d5b435ba 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -30,6 +30,7 @@ FocusScope { if (!repositionLocked) { d.handleSizeChanged(); } + } onHeightChanged: d.handleSizeChanged(); @@ -66,7 +67,6 @@ FocusScope { if (desktop.repositionLocked) { return; } - var oldRecommendedRect = recommendedRect; var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, @@ -311,8 +311,8 @@ FocusScope { onPinnedChanged: { if (pinned) { - nullFocus.focus = true; - nullFocus.forceActiveFocus(); + desktop.focus = true; + desktop.forceActiveFocus(); // recalculate our non-pinned children hiddenChildren = d.findMatchingChildren(desktop, function(child){ @@ -486,17 +486,31 @@ FocusScope { } function unfocusWindows() { + // First find the active focus item, and unfocus it, all the way + // up the parent chain to the window + var currentFocus = offscreenWindow.activeFocusItem; + var targetWindow = d.getDesktopWindow(currentFocus); + while (currentFocus) { + if (currentFocus === targetWindow) { + break; + } + currentFocus.focus = false; + currentFocus = currentFocus.parent; + } + + // Unfocus all windows var windows = d.getTopLevelWindows(); for (var i = 0; i < windows.length; ++i) { windows[i].focus = false; } + + // For the desktop to have active focus desktop.focus = true; + desktop.forceActiveFocus(); } FocusHack { id: focusHack; } - FocusScope { id: nullFocus; } - Rectangle { id: focusDebugger; objectName: "focusDebugger" @@ -510,5 +524,5 @@ FocusScope { enabled: DebugQML onTriggered: focusDebugger.visible = !focusDebugger.visible } - + } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 169542c0f0..561bd722f2 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -56,13 +56,13 @@ OriginalDesktop.Desktop { var sysToolbar = desktop.getToolbar("com.highfidelity.interface.toolbar.system"); var toggleHudButton = sysToolbar.addButton({ objectName: "hudToggle", - imageURL: "../../../icons/hud-01.svg", + imageURL: "../../../icons/hud.svg", visible: true, pinned: true, }); - toggleHudButton.yOffset = Qt.binding(function(){ - return desktop.pinned ? 50 : 0 + toggleHudButton.buttonState = Qt.binding(function(){ + return desktop.pinned ? 1 : 0 }); toggleHudButton.clicked.connect(function(){ console.log("Clicked on hud button") diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 5457caccf1..3f05a140ae 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -53,11 +53,6 @@ ScrollingWindow { updateRunningScripts(); } - function setDefaultFocus() { - // Work around FocusScope of scrollable window. - filterEdit.forceActiveFocus(); - } - function updateRunningScripts() { var runningScripts = ScriptDiscoveryService.getRunning(); runningScriptsModel.clear() @@ -276,7 +271,6 @@ ScrollingWindow { isSearchField: true anchors.left: parent.left anchors.right: parent.right - focus: true colorScheme: hifi.colorSchemes.dark placeholderText: "Filter" onTextChanged: scriptsModel.filterRegExp = new RegExp("^.*" + text + ".*$", "i") diff --git a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml index a3be4533d2..4356b18253 100644 --- a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml +++ b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml @@ -8,6 +8,7 @@ Item { property var subImage; property int yOffset: 0 property int buttonState: 0 + property int hoverOffset: 0 property var toolbar; property real size: 50 // toolbar ? toolbar.buttonSize : 50 width: size; height: size @@ -36,9 +37,15 @@ Item { } } - + function updateOffset() { + yOffset = size * (buttonState + hoverOffset); + } onButtonStateChanged: { - yOffset = size * buttonState + hoverOffset = 0; // subtle: show the new state without hover. don't wait for mouse to be moved away + // The above is per UX design, but ALSO avoid a subtle issue that would be a problem because + // the hand controllers don't move the mouse when not triggered, so releasing the trigger would + // never show unhovered. + updateOffset(); } Component.onCompleted: { @@ -58,8 +65,18 @@ Item { } MouseArea { + id: mouseArea + hoverEnabled: true anchors.fill: parent onClicked: button.clicked(); + onEntered: { + hoverOffset = 2; + updateOffset(); + } + onExited: { + hoverOffset = 0; + updateOffset(); + } } } diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index c4d985419e..4051bd8a1e 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -79,10 +79,6 @@ void DiscoverabilityManager::updateLocation() { const QString FRIENDS_ONLY_KEY_IN_LOCATION = "friends_only"; locationObject.insert(FRIENDS_ONLY_KEY_IN_LOCATION, (_mode.get() == Discoverability::Friends)); - // if we have a session ID add it now, otherwise add a null value - auto sessionID = accountManager->getSessionID(); - rootObject[SESSION_ID_KEY] = sessionID.isNull() ? QJsonValue() : sessionID.toString(); - JSONCallbackParameters callbackParameters; callbackParameters.jsonCallbackReceiver = this; callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse"; @@ -110,13 +106,8 @@ void DiscoverabilityManager::updateLocation() { callbackParameters.jsonCallbackReceiver = this; callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse"; - QJsonObject heartbeatObject; - auto sessionID = accountManager->getSessionID(); - heartbeatObject[SESSION_ID_KEY] = sessionID.isNull() ? QJsonValue() : sessionID.toString(); - accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional, - QNetworkAccessManager::PutOperation, callbackParameters, - QJsonDocument(heartbeatObject).toJson()); + QNetworkAccessManager::PutOperation, callbackParameters); } } diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.cpp b/interface/src/scripting/DialogsManagerScriptingInterface.cpp index 80a8b4ac7c..cbca7ff4ff 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.cpp +++ b/interface/src/scripting/DialogsManagerScriptingInterface.cpp @@ -18,6 +18,8 @@ DialogsManagerScriptingInterface::DialogsManagerScriptingInterface() { connect(DependencyManager::get().data(), &DialogsManager::addressBarToggled, this, &DialogsManagerScriptingInterface::addressBarToggled); + connect(DependencyManager::get().data(), &DialogsManager::addressBarShown, + this, &DialogsManagerScriptingInterface::addressBarShown); } void DialogsManagerScriptingInterface::toggleAddressBar() { diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.h b/interface/src/scripting/DialogsManagerScriptingInterface.h index ef44e20d61..075b89f0e5 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.h +++ b/interface/src/scripting/DialogsManagerScriptingInterface.h @@ -24,6 +24,7 @@ public slots: signals: void addressBarToggled(); + void addressBarShown(bool visible); }; #endif diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index ba0cf18d32..6fb437e312 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -16,6 +16,7 @@ #include "DependencyManager.h" #include "AddressManager.h" +#include "DialogsManager.h" HIFI_QML_DEF(AddressBarDialog) @@ -74,3 +75,6 @@ void AddressBarDialog::displayAddressNotFoundMessage() { OffscreenUi::critical("", "There is no address information for that user or place"); } +void AddressBarDialog::observeShownChanged(bool visible) { + DependencyManager::get()->emitAddressBarShown(visible); +} diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index b2751860cc..bbce52c67c 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -38,6 +38,7 @@ protected: Q_INVOKABLE void loadHome(); Q_INVOKABLE void loadBack(); Q_INVOKABLE void loadForward(); + Q_INVOKABLE void observeShownChanged(bool visible); bool _backEnabled; bool _forwardEnabled; diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index b8fa22ec83..c48c6df0e6 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -40,6 +40,7 @@ public: QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } + void emitAddressBarShown(bool visible) { emit addressBarShown(visible); } public slots: void toggleAddressBar(); @@ -60,6 +61,7 @@ public slots: signals: void addressBarToggled(); + void addressBarShown(bool visible); private slots: void hmdToolsClosed(); diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp index 5c57e92ce5..c561231376 100644 --- a/libraries/audio/src/AudioReverb.cpp +++ b/libraries/audio/src/AudioReverb.cpp @@ -13,13 +13,13 @@ #include "AudioReverb.h" #ifdef _MSC_VER -#pragma warning(disable : 4351) // new behavior: elements of array will be default initialized #include inline static int MULHI(int a, int b) { long long c = __emul(a, b); return ((int*)&c)[1]; } + #else #define MULHI(a,b) (int)(((long long)(a) * (b)) >> 32) @@ -1725,7 +1725,7 @@ void ReverbImpl::reset() { // Public API // -static const int REVERB_BLOCK = 1024; +static const int REVERB_BLOCK = 256; AudioReverb::AudioReverb(float sampleRate) { @@ -1804,7 +1804,7 @@ void AudioReverb::render(float** inputs, float** outputs, int numFrames) { #include // convert int16_t to float, deinterleave stereo -void AudioReverb::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) { +void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) { __m128 scale = _mm_set1_ps(1/32768.0f); int i = 0; @@ -1855,8 +1855,8 @@ static inline __m128 dither4() { return _mm_mul_ps(d0, _mm_set1_ps(1/65536.0f)); } -// convert float to int16_t, interleave stereo -void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) { +// convert float to int16_t with dither, interleave stereo +void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames) { __m128 scale = _mm_set1_ps(32768.0f); int i = 0; @@ -1898,10 +1898,48 @@ void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numF } } +// deinterleave stereo +void AudioReverb::convertInput(const float* input, float** outputs, int numFrames) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&input[2*i + 0]); + __m128 f1 = _mm_loadu_ps(&input[2*i + 4]); + + // deinterleave + _mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(2,0,2,0))); + _mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(3,1,3,1))); + } + for (; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[2*i + 0]; + outputs[1][i] = input[2*i + 1]; + } +} + +// interleave stereo +void AudioReverb::convertOutput(float** inputs, float* output, int numFrames) { + + int i = 0; + for(; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&inputs[0][i]); + __m128 f1 = _mm_loadu_ps(&inputs[1][i]); + + // interleave + _mm_storeu_ps(&output[2*i + 0],_mm_unpacklo_ps(f0,f1)); + _mm_storeu_ps(&output[2*i + 4],_mm_unpackhi_ps(f0,f1)); + } + for(; i < numFrames; i++) { + // interleave + output[2*i + 0] = inputs[0][i]; + output[2*i + 1] = inputs[1][i]; + } +} + #else // convert int16_t to float, deinterleave stereo -void AudioReverb::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) { +void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) { const float scale = 1/32768.0f; for (int i = 0; i < numFrames; i++) { @@ -1919,8 +1957,8 @@ static inline float dither() { return (int32_t)(r0 - r1) * (1/65536.0f); } -// convert float to int16_t, interleave stereo -void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) { +// convert float to int16_t with dither, interleave stereo +void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames) { const float scale = 32768.0f; for (int i = 0; i < numFrames; i++) { @@ -1944,6 +1982,26 @@ void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numF } } +// deinterleave stereo +void AudioReverb::convertInput(const float* input, float** outputs, int numFrames) { + + for (int i = 0; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[2*i + 0]; + outputs[1][i] = input[2*i + 1]; + } +} + +// interleave stereo +void AudioReverb::convertOutput(float** inputs, float* output, int numFrames) { + + for (int i = 0; i < numFrames; i++) { + // interleave + output[2*i + 0] = inputs[0][i]; + output[2*i + 1] = inputs[1][i]; + } +} + #endif // @@ -1955,11 +2013,32 @@ void AudioReverb::render(const int16_t* input, int16_t* output, int numFrames) { int n = MIN(numFrames, REVERB_BLOCK); - convertInputFromInt16(input, _inout, n); + convertInput(input, _inout, n); _impl->process(_inout, _inout, n); - convertOutputToInt16(_inout, output, n); + convertOutput(_inout, output, n); + + input += 2 * n; + output += 2 * n; + numFrames -= n; + } +} + +// +// This version handles input/output as interleaved float +// +void AudioReverb::render(const float* input, float* output, int numFrames) { + + while (numFrames) { + + int n = MIN(numFrames, REVERB_BLOCK); + + convertInput(input, _inout, n); + + _impl->process(_inout, _inout, n); + + convertOutput(_inout, output, n); input += 2 * n; output += 2 * n; diff --git a/libraries/audio/src/AudioReverb.h b/libraries/audio/src/AudioReverb.h index 639d62d8ec..adb8890f6a 100644 --- a/libraries/audio/src/AudioReverb.h +++ b/libraries/audio/src/AudioReverb.h @@ -64,13 +64,20 @@ public: // interleaved int16_t input/output void render(const int16_t* input, int16_t* output, int numFrames); + // interleaved float input/output + void render(const float* input, float* output, int numFrames); + private: ReverbImpl *_impl; ReverbParameters _params; float* _inout[2]; - void convertInputFromInt16(const int16_t* input, float** outputs, int numFrames); - void convertOutputToInt16(float** inputs, int16_t* output, int numFrames); + + void convertInput(const int16_t* input, float** outputs, int numFrames); + void convertOutput(float** inputs, int16_t* output, int numFrames); + + void convertInput(const float* input, float** outputs, int numFrames); + void convertOutput(float** inputs, float* output, int numFrames); }; #endif // hifi_AudioReverb_h diff --git a/libraries/audio/src/AudioSRC.cpp b/libraries/audio/src/AudioSRC.cpp index 98de36e655..5dba63b349 100644 --- a/libraries/audio/src/AudioSRC.cpp +++ b/libraries/audio/src/AudioSRC.cpp @@ -389,7 +389,7 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* } // convert int16_t to float, deinterleave stereo -void AudioSRC::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) { +void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) { __m128 scale = _mm_set1_ps(1/32768.0f); if (_numChannels == 1) { @@ -467,8 +467,8 @@ static inline __m128 dither4() { return _mm_mul_ps(d0, _mm_set1_ps(1/65536.0f)); } -// convert float to int16_t, interleave stereo -void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) { +// convert float to int16_t with dither, interleave stereo +void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { __m128 scale = _mm_set1_ps(32768.0f); if (_numChannels == 1) { @@ -539,6 +539,58 @@ void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFram } } +// deinterleave stereo +void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) { + + if (_numChannels == 1) { + + memcpy(outputs[0], input, numFrames * sizeof(float)); + + } else if (_numChannels == 2) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&input[2*i + 0]); + __m128 f1 = _mm_loadu_ps(&input[2*i + 4]); + + // deinterleave + _mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(2,0,2,0))); + _mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(3,1,3,1))); + } + for (; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[2*i + 0]; + outputs[1][i] = input[2*i + 1]; + } + } +} + +// interleave stereo +void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) { + + if (_numChannels == 1) { + + memcpy(output, inputs[0], numFrames * sizeof(float)); + + } else if (_numChannels == 2) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&inputs[0][i]); + __m128 f1 = _mm_loadu_ps(&inputs[1][i]); + + // interleave + _mm_storeu_ps(&output[2*i + 0], _mm_unpacklo_ps(f0, f1)); + _mm_storeu_ps(&output[2*i + 4], _mm_unpackhi_ps(f0, f1)); + } + for (; i < numFrames; i++) { + // interleave + output[2*i + 0] = inputs[0][i]; + output[2*i + 1] = inputs[1][i]; + } + } +} + #else int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFrames) { @@ -674,7 +726,7 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* } // convert int16_t to float, deinterleave stereo -void AudioSRC::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) { +void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) { const float scale = 1/32768.0f; if (_numChannels == 1) { @@ -698,8 +750,8 @@ static inline float dither() { return (int32_t)(r0 - r1) * (1/65536.0f); } -// convert float to int16_t, interleave stereo -void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) { +// convert float to int16_t with dither, interleave stereo +void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { const float scale = 32768.0f; if (_numChannels == 1) { @@ -738,9 +790,41 @@ void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFram } } +// deinterleave stereo +void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) { + + if (_numChannels == 1) { + + memcpy(outputs[0], input, numFrames * sizeof(float)); + + } else if (_numChannels == 2) { + for (int i = 0; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[2*i + 0]; + outputs[1][i] = input[2*i + 1]; + } + } +} + +// interleave stereo +void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) { + + if (_numChannels == 1) { + + memcpy(output, inputs[0], numFrames * sizeof(float)); + + } else if (_numChannels == 2) { + for (int i = 0; i < numFrames; i++) { + // interleave + output[2*i + 0] = inputs[0][i]; + output[2*i + 1] = inputs[1][i]; + } + } +} + #endif -int AudioSRC::processFloat(float** inputs, float** outputs, int inputFrames) { +int AudioSRC::render(float** inputs, float** outputs, int inputFrames) { int outputFrames = 0; int nh = std::min(_numHistory, inputFrames); // number of frames from history buffer @@ -749,19 +833,19 @@ int AudioSRC::processFloat(float** inputs, float** outputs, int inputFrames) { if (_numChannels == 1) { // refill history buffers - memcpy(_history[0] + _numHistory, _inputs[0], nh * sizeof(float)); + memcpy(_history[0] + _numHistory, inputs[0], nh * sizeof(float)); // process history buffer - outputFrames += multirateFilter1(_history[0], _outputs[0], nh); + outputFrames += multirateFilter1(_history[0], outputs[0], nh); // process remaining input if (ni) { - outputFrames += multirateFilter1(_inputs[0], _outputs[0] + outputFrames, ni); + outputFrames += multirateFilter1(inputs[0], outputs[0] + outputFrames, ni); } // shift history buffers if (ni) { - memcpy(_history[0], _inputs[0] + ni, _numHistory * sizeof(float)); + memcpy(_history[0], inputs[0] + ni, _numHistory * sizeof(float)); } else { memmove(_history[0], _history[0] + nh, _numHistory * sizeof(float)); } @@ -769,15 +853,15 @@ int AudioSRC::processFloat(float** inputs, float** outputs, int inputFrames) { } else if (_numChannels == 2) { // refill history buffers - memcpy(_history[0] + _numHistory, _inputs[0], nh * sizeof(float)); - memcpy(_history[1] + _numHistory, _inputs[1], nh * sizeof(float)); + memcpy(_history[0] + _numHistory, inputs[0], nh * sizeof(float)); + memcpy(_history[1] + _numHistory, inputs[1], nh * sizeof(float)); // process history buffer - outputFrames += multirateFilter2(_history[0], _history[1], _outputs[0], _outputs[1], nh); + outputFrames += multirateFilter2(_history[0], _history[1], outputs[0], outputs[1], nh); // process remaining input if (ni) { - outputFrames += multirateFilter2(_inputs[0], _inputs[1], _outputs[0] + outputFrames, _outputs[1] + outputFrames, ni); + outputFrames += multirateFilter2(inputs[0], inputs[1], outputs[0] + outputFrames, outputs[1] + outputFrames, ni); } // shift history buffers @@ -869,12 +953,38 @@ int AudioSRC::render(const int16_t* input, int16_t* output, int inputFrames) { int ni = std::min(inputFrames, _inputBlock); - convertInputFromInt16(input, _inputs, ni); + convertInput(input, _inputs, ni); - int no = processFloat(_inputs, _outputs, ni); + int no = render(_inputs, _outputs, ni); assert(no <= SRC_BLOCK); - convertOutputToInt16(_outputs, output, no); + convertOutput(_outputs, output, no); + + input += _numChannels * ni; + output += _numChannels * no; + inputFrames -= ni; + outputFrames += no; + } + + return outputFrames; +} + +// +// This version handles input/output as interleaved float +// +int AudioSRC::render(const float* input, float* output, int inputFrames) { + int outputFrames = 0; + + while (inputFrames) { + + int ni = std::min(inputFrames, _inputBlock); + + convertInput(input, _inputs, ni); + + int no = render(_inputs, _outputs, ni); + assert(no <= SRC_BLOCK); + + convertOutput(_outputs, output, no); input += _numChannels * ni; output += _numChannels * no; diff --git a/libraries/audio/src/AudioSRC.h b/libraries/audio/src/AudioSRC.h index a4aefc5ed7..f7becc22c3 100644 --- a/libraries/audio/src/AudioSRC.h +++ b/libraries/audio/src/AudioSRC.h @@ -34,8 +34,15 @@ public: AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels); ~AudioSRC(); + // deinterleaved float input/output (native format) + int render(float** inputs, float** outputs, int inputFrames); + + // interleaved int16_t input/output int render(const int16_t* input, int16_t* output, int inputFrames); + // interleaved float input/output + int render(const float* input, float* output, int inputFrames); + int getMinOutput(int inputFrames); int getMaxOutput(int inputFrames); int getMinInput(int outputFrames); @@ -75,10 +82,11 @@ private: int multirateFilter1_AVX2(const float* input0, float* output0, int inputFrames); int multirateFilter2_AVX2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames); - void convertInputFromInt16(const int16_t* input, float** outputs, int numFrames); - void convertOutputToInt16(float** inputs, int16_t* output, int numFrames); + void convertInput(const int16_t* input, float** outputs, int numFrames); + void convertOutput(float** inputs, int16_t* output, int numFrames); - int processFloat(float** inputs, float** outputs, int inputFrames); + void convertInput(const float* input, float** outputs, int numFrames); + void convertOutput(float** inputs, float* output, int numFrames); }; #endif // AudioSRC_h diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index b72f52351f..18f39cd3df 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -647,12 +647,13 @@ void OpenGLDisplayPlugin::withMainThreadContext(std::function f) const { } QImage OpenGLDisplayPlugin::getScreenshot() const { - QImage result; + using namespace oglplus; + QImage screenshot(_compositeFramebuffer->size.x, _compositeFramebuffer->size.y, QImage::Format_RGBA8888); withMainThreadContext([&] { - static auto widget = _container->getPrimaryWidget(); - result = widget->grabFrameBuffer(); + Framebuffer::Bind(Framebuffer::Target::Read, _compositeFramebuffer->fbo); + Context::ReadPixels(0, 0, _compositeFramebuffer->size.x, _compositeFramebuffer->size.y, enums::PixelDataFormat::RGBA, enums::PixelDataType::UnsignedByte, screenshot.bits()); }); - return result; + return screenshot.mirrored(false, true); } uint32_t OpenGLDisplayPlugin::getSceneTextureId() const { diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index e49bf5d5a5..ed325b8d69 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -220,12 +220,8 @@ void AccountManager::sendRequest(const QString& path, networkRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); - // if we're allowed to send usage data, include whatever the current session ID is with this request - auto& activityLogger = UserActivityLogger::getInstance(); - if (activityLogger.isEnabled()) { - networkRequest.setRawHeader(METAVERSE_SESSION_ID_HEADER, - uuidStringWithoutCurlyBraces(_sessionID).toLocal8Bit()); - } + networkRequest.setRawHeader(METAVERSE_SESSION_ID_HEADER, + uuidStringWithoutCurlyBraces(_sessionID).toLocal8Bit()); QUrl requestURL = _authURL; diff --git a/libraries/script-engine/src/TypedArrayPrototype.cpp b/libraries/script-engine/src/TypedArrayPrototype.cpp index bb612b393f..4de948e806 100644 --- a/libraries/script-engine/src/TypedArrayPrototype.cpp +++ b/libraries/script-engine/src/TypedArrayPrototype.cpp @@ -71,8 +71,10 @@ QScriptValue TypedArrayPrototype::subarray(qint32 begin, qint32 end) { end = (end < 0) ? length + end : end; // here we clamp the indices to fit the array + // note: begin offset is *inclusive* while end offset is *exclusive* + // (see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray#Parameters) begin = glm::clamp(begin, 0, (length - 1)); - end = glm::clamp(end, 0, (length - 1)); + end = glm::clamp(end, 0, length); byteOffset += begin * bytesPerElement; length = (end - begin > 0) ? end - begin : 0; diff --git a/libraries/script-engine/src/TypedArrays.cpp b/libraries/script-engine/src/TypedArrays.cpp index c1c4117f76..4d5181ff33 100644 --- a/libraries/script-engine/src/TypedArrays.cpp +++ b/libraries/script-engine/src/TypedArrays.cpp @@ -88,7 +88,11 @@ QScriptValue TypedArray::construct(QScriptContext* context, QScriptEngine* engin if (arrayBuffer) { if (context->argumentCount() == 1) { // Case for entire ArrayBuffer - newObject = cls->newInstance(bufferArg, 0, arrayBuffer->size()); + if (arrayBuffer->size() % cls->_bytesPerElement != 0) { + engine->evaluate("throw \"RangeError: byteLength is not a multiple of BYTES_PER_ELEMENT\""); + } + quint32 length = arrayBuffer->size() / cls->_bytesPerElement; + newObject = cls->newInstance(bufferArg, 0, length); } else { QScriptValue byteOffsetArg = context->argument(1); if (!byteOffsetArg.isNumber()) { @@ -206,6 +210,7 @@ QScriptValue propertyHelper(const QByteArray* arrayBuffer, const QScriptString& QDataStream stream(*arrayBuffer); stream.skipRawData(id); + stream.setByteOrder(QDataStream::LittleEndian); T result; stream >> result; return result; @@ -218,6 +223,7 @@ void setPropertyHelper(QByteArray* arrayBuffer, const QScriptString& name, uint if (arrayBuffer && value.isNumber()) { QDataStream stream(arrayBuffer, QIODevice::ReadWrite); stream.skipRawData(id); + stream.setByteOrder(QDataStream::LittleEndian); stream << (T)value.toNumber(); } @@ -357,6 +363,7 @@ QScriptValue Float32ArrayClass::property(const QScriptValue& object, const QScri if (ok && arrayBuffer) { QDataStream stream(*arrayBuffer); stream.skipRawData(id); + stream.setByteOrder(QDataStream::LittleEndian); stream.setFloatingPointPrecision(QDataStream::SinglePrecision); float result; @@ -375,6 +382,7 @@ void Float32ArrayClass::setProperty(QScriptValue& object, const QScriptString& n if (ba && value.isNumber()) { QDataStream stream(ba, QIODevice::ReadWrite); stream.skipRawData(id); + stream.setByteOrder(QDataStream::LittleEndian); stream.setFloatingPointPrecision(QDataStream::SinglePrecision); stream << (float)value.toNumber(); @@ -392,6 +400,7 @@ QScriptValue Float64ArrayClass::property(const QScriptValue& object, const QScri if (ok && arrayBuffer) { QDataStream stream(*arrayBuffer); stream.skipRawData(id); + stream.setByteOrder(QDataStream::LittleEndian); stream.setFloatingPointPrecision(QDataStream::DoublePrecision); double result; @@ -410,6 +419,7 @@ void Float64ArrayClass::setProperty(QScriptValue& object, const QScriptString& n if (ba && value.isNumber()) { QDataStream stream(ba, QIODevice::ReadWrite); stream.skipRawData(id); + stream.setByteOrder(QDataStream::LittleEndian); stream.setFloatingPointPrecision(QDataStream::DoublePrecision); stream << (double)value.toNumber(); diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 399712d920..c93a2178b5 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -268,6 +268,7 @@ void handleOpenVrEvents() { case vr::VREvent_KeyboardClosed: _keyboardFocusObject = nullptr; _keyboardShown = false; + DependencyManager::get()->unfocusWindows(); break; default: diff --git a/scripts/developer/tests/playaPerformanceTest.qml b/scripts/developer/tests/playaPerformanceTest.qml index cd8171a0f6..028cfc9e1a 100644 --- a/scripts/developer/tests/playaPerformanceTest.qml +++ b/scripts/developer/tests/playaPerformanceTest.qml @@ -125,7 +125,6 @@ Rectangle { TextField { id: addressLine - focus: true anchors { left: parent.left; right: parent.right; top: row.bottom; margins: 16; diff --git a/scripts/developer/utilities/diagnostics/typedArraysUnitTest.js b/scripts/developer/utilities/diagnostics/typedArraysUnitTest.js index a50a40e43e..c61865c8d6 100644 --- a/scripts/developer/utilities/diagnostics/typedArraysUnitTest.js +++ b/scripts/developer/utilities/diagnostics/typedArraysUnitTest.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("../../libraries/unitTest.js"); +Script.include("../../../../script-archive/libraries/unitTest.js"); // e.g. extractbits([0xff, 0x80, 0x00, 0x00], 23, 30); inclusive function extractbits(bytes, lo, hi) { @@ -551,6 +551,20 @@ test('TypedArray.subarray', function () { this.arrayEqual(a.subarray(-1, -4), []); this.arrayEqual(a.subarray(1).subarray(1), [3, 4, 5]); this.arrayEqual(a.subarray(1, 4).subarray(1, 2), [3]); + + var a = new Float32Array(16); + a[0] = -1; + a[15] = 1/8; + this.assertEquals(a.length, 16); + this.assertEquals(a.byteLength, a.length * a.BYTES_PER_ELEMENT); + + this.assertEquals(a.subarray(-12).length, 12, '[-12,)'); + this.arrayEqual(a.subarray(-16), a, '[-16,)'); + this.arrayEqual(a.subarray(12, 16), [0,0,0,1/8], '[12,16)'); + this.arrayEqual(a.subarray(0, 4), [-1,0,0,0],'[0,4)'); + this.arrayEqual(a.subarray(-16, -12), [-1,0,0,0],'[-16,-12)'); + this.assertEquals(a.subarray(0, -12).length, 4,'[0,-12)'); + this.arrayEqual(a.subarray(-10), a.subarray(6),'[-10,)'); }); @@ -706,3 +720,45 @@ test('Regression Tests', function() { this.assertEquals(truncated, -minFloat32, 'smallest 32 bit float should not truncate to zero'); }); +test('new TypedArray(ArrayBuffer).length Tests', function() { + var uint8s = new Uint8Array([0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff]), + buffer = uint8s.buffer; + + this.assertEquals(buffer.byteLength, 8, 'buffer.length'); + + var _this = this; + [ + 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Int8Array', 'Int16Array', 'Int32Array', + 'Float32Array', 'Float64Array', 'Uint8ClampedArray' + ].forEach(function(typeArrayName) { + var typeArray = eval(typeArrayName); + var a = new typeArray(buffer); + _this.assertEquals(a.BYTES_PER_ELEMENT, typeArrayName.match(/\d+/)[0]/8, typeArrayName+'.BYTES_PER_ELEMENT'); + _this.assertEquals(a.byteLength, buffer.byteLength, typeArrayName+'.byteLength'); + _this.assertEquals(a.length, buffer.byteLength / typeArray.BYTES_PER_ELEMENT, typeArrayName+'.length'); + }); +}); + +test('Native endianness check', function() { + var buffer = ArrayBuffer(4); + new Uint8Array(buffer).set([0xaa, 0xbb, 0xcc, 0xdd]); + var endian = { aabbccdd: 'big', ddccbbaa: 'little' }[ + new Uint32Array(buffer)[0].toString(16) + ]; + this.assertEquals(endian, 'little'); +}); + +test('TypeArray byte order tests', function() { + var uint8s = new Uint8Array([0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff]), + buffer = uint8s.buffer; + + this.arrayEqual(new Uint8Array(buffer), [0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff], "Uint8Array"); + this.arrayEqual(new Uint16Array(buffer), [0x00ff, 0x0000, 0x0000, 0xff00], "Uint16Array"); + this.arrayEqual(new Uint32Array(buffer), [0x000000ff, 0xff000000], "Uint32Array"); + + this.arrayEqual(new Int8Array(buffer), [-1,0,0,0,0,0,0,-1], "Int8Array"); + this.arrayEqual(new Int16Array(buffer), [255, 0, 0, -256], "Int16Array"); + + this.arrayEqual(new Float32Array(buffer), [3.5733110840282835e-43, -1.7014118346046923e+38], "Float32Array"); + this.arrayEqual(new Float64Array(buffer), [-5.486124068793999e+303], "Float64Array"); +}); diff --git a/scripts/system/assets/images/tools/directory-01.svg b/scripts/system/assets/images/tools/directory-01.svg deleted file mode 100644 index d038611d69..0000000000 --- a/scripts/system/assets/images/tools/directory-01.svg +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/system/assets/images/tools/directory.svg b/scripts/system/assets/images/tools/directory.svg new file mode 100644 index 0000000000..09f3c14bf0 --- /dev/null +++ b/scripts/system/assets/images/tools/directory.svg @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/tools/edit-01.svg b/scripts/system/assets/images/tools/edit-01.svg deleted file mode 100644 index c661c6f678..0000000000 --- a/scripts/system/assets/images/tools/edit-01.svg +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/system/assets/images/tools/edit.svg b/scripts/system/assets/images/tools/edit.svg new file mode 100644 index 0000000000..f65e0cd84d --- /dev/null +++ b/scripts/system/assets/images/tools/edit.svg @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/tools/examples-01.svg b/scripts/system/assets/images/tools/examples-01.svg deleted file mode 100644 index ec4758dcde..0000000000 --- a/scripts/system/assets/images/tools/examples-01.svg +++ /dev/null @@ -1,306 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/system/assets/images/tools/hmd-switch-01.svg b/scripts/system/assets/images/tools/hmd-switch-01.svg deleted file mode 100644 index 31389d355c..0000000000 --- a/scripts/system/assets/images/tools/hmd-switch-01.svg +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/system/assets/images/tools/market.svg b/scripts/system/assets/images/tools/market.svg new file mode 100644 index 0000000000..0cec030933 --- /dev/null +++ b/scripts/system/assets/images/tools/market.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/tools/mic.svg b/scripts/system/assets/images/tools/mic.svg new file mode 100644 index 0000000000..0424f3eb49 --- /dev/null +++ b/scripts/system/assets/images/tools/mic.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/tools/microphone.svg b/scripts/system/assets/images/tools/microphone.svg deleted file mode 100644 index bd5e8afac7..0000000000 --- a/scripts/system/assets/images/tools/microphone.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - image/svg+xml - - - Layer 1 - - - - Mute - - - \ No newline at end of file diff --git a/scripts/system/assets/images/tools/switch.svg b/scripts/system/assets/images/tools/switch.svg new file mode 100644 index 0000000000..e67a9aac04 --- /dev/null +++ b/scripts/system/assets/images/tools/switch.svg @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 9d5585e353..6810bae590 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -192,7 +192,7 @@ var toolBar = (function() { }); activeButton = toolBar.addTool({ - imageURL: toolIconUrl + "edit-01.svg", + imageURL: toolIconUrl + "edit.svg", subImage: { x: 0, y: Tool.IMAGE_WIDTH, diff --git a/scripts/system/examples.js b/scripts/system/examples.js index a948f9e563..0ec2644f9c 100644 --- a/scripts/system/examples.js +++ b/scripts/system/examples.js @@ -53,18 +53,22 @@ function toggleExamples() { var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var browseExamplesButton = toolBar.addButton({ - imageURL: toolIconUrl + "examples-01.svg", + imageURL: toolIconUrl + "market.svg", objectName: "examples", - yOffset: 50, - alpha: 0.9, + buttonState: 1, + alpha: 0.9 }); -var browseExamplesButtonDown = false; - -browseExamplesButton.clicked.connect(function(){ +function onExamplesWindowVisibilityChanged() { + browseExamplesButton.writeProperty('buttonState', examplesWindow.visible ? 0 : 1); +} +function onClick() { toggleExamples(); -}); +} +browseExamplesButton.clicked.connect(onClick); +examplesWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); Script.scriptEnding.connect(function () { - browseExamplesButton.clicked.disconnect(); + browseExamplesButton.clicked.disconnect(onClick); + examplesWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); }); diff --git a/scripts/system/goto.js b/scripts/system/goto.js index a2ade02a78..24c402ab85 100644 --- a/scripts/system/goto.js +++ b/scripts/system/goto.js @@ -14,16 +14,22 @@ var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var button = toolBar.addButton({ objectName: "goto", - imageURL: Script.resolvePath("assets/images/tools/directory-01.svg"), + imageURL: Script.resolvePath("assets/images/tools/directory.svg"), visible: true, - yOffset: 50, + buttonState: 1, alpha: 0.9, }); - -button.clicked.connect(function(){ + +function onAddressBarShown(visible) { + button.writeProperty('buttonState', visible ? 0 : 1); +} +function onClicked(){ DialogsManager.toggleAddressBar(); -}); +} +button.clicked.connect(onClicked); +DialogsManager.addressBarShown.connect(onAddressBarShown); Script.scriptEnding.connect(function () { - button.clicked.disconnect(); + button.clicked.disconnect(onClicked); + DialogsManager.addressBarShown.disconnect(onAddressBarShown); }); diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index 2965c0d254..305557b60c 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -20,23 +20,28 @@ var desktopMenuItemName = "Desktop"; var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var button; - +function onHmdChanged(isHmd) { + button.writeProperty('buttonState', isHmd ? 0 : 1); +} +function onClicked(){ + var isDesktop = Menu.isOptionChecked(desktopMenuItemName); + Menu.setIsOptionChecked(isDesktop ? headset : desktopMenuItemName, true); +} if (headset) { button = toolBar.addButton({ objectName: "hmdToggle", - imageURL: Script.resolvePath("assets/images/tools/hmd-switch-01.svg"), + imageURL: Script.resolvePath("assets/images/tools/switch.svg"), visible: true, - yOffset: 50, alpha: 0.9, }); + onHmdChanged(HMD.active); - button.clicked.connect(function(){ - var isDesktop = Menu.isOptionChecked(desktopMenuItemName); - Menu.setIsOptionChecked(isDesktop ? headset : desktopMenuItemName, true); - }); + button.clicked.connect(onClicked); + HMD.displayModeChanged.connect(onHmdChanged); Script.scriptEnding.connect(function () { - button.clicked.disconnect(); + button.clicked.disconnect(onClicked); + HMD.displayModeChanged.disconnect(onHmdChanged); }); } diff --git a/scripts/system/mute.js b/scripts/system/mute.js index f66b6852ea..1a575efa01 100644 --- a/scripts/system/mute.js +++ b/scripts/system/mute.js @@ -14,16 +14,26 @@ var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var button = toolBar.addButton({ objectName: "mute", - imageURL: Script.resolvePath("assets/images/tools/microphone.svg"), + imageURL: Script.resolvePath("assets/images/tools/mic.svg"), visible: true, - alpha: 0.9, -}); - -button.clicked.connect(function(){ - var menuItem = "Mute Microphone"; - Menu.setIsOptionChecked(menuItem, !Menu.isOptionChecked(menuItem)); + buttonState: 1, + alpha: 0.9 }); +function onMuteToggled() { + // We could just toggle state, but we're less likely to get out of wack if we read the AudioDevice. + // muted => button "on" state => 1. go figure. + button.writeProperty('buttonState', AudioDevice.getMuted() ? 0 : 1); +} +onMuteToggled(); +function onClicked(){ + var menuItem = "Mute Microphone"; + Menu.setIsOptionChecked(menuItem, !Menu.isOptionChecked(menuItem)); +} +button.clicked.connect(onClicked); +AudioDevice.muteToggled.connect(onMuteToggled); + Script.scriptEnding.connect(function () { - button.clicked.disconnect(); + button.clicked.disconnect(onClicked); + AudioDevice.muteToggled.disconnect(onMuteToggled); }); diff --git a/scripts/system/users.js b/scripts/system/users.js index d25e1b76b4..853067b90b 100644 --- a/scripts/system/users.js +++ b/scripts/system/users.js @@ -344,6 +344,7 @@ var usersWindow = (function () { windowTextHeight, windowLineSpacing, windowLineHeight, // = windowTextHeight + windowLineSpacing + windowMinimumHeight, usersOnline, // Raw users data linesOfUsers = [], // Array of indexes pointing into usersOnline @@ -435,6 +436,11 @@ var usersWindow = (function () { } } + function saturateWindowPosition() { + windowPosition.x = Math.max(0, Math.min(viewport.x - WINDOW_WIDTH, windowPosition.x)); + windowPosition.y = Math.max(windowMinimumHeight, Math.min(viewport.y, windowPosition.y)); + } + function updateOverlayPositions() { // Overlay positions are all relative to windowPosition; windowPosition is the position of the windowPane overlay. var windowLeft = windowPosition.x, @@ -826,6 +832,10 @@ var usersWindow = (function () { function onMouseMoveEvent(event) { var isVisible; + if (!isLoggedIn) { + return; + } + if (isMovingScrollbar) { if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x && event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN @@ -850,6 +860,8 @@ var usersWindow = (function () { x: event.x - movingClickOffset.x, y: event.y - movingClickOffset.y }; + + saturateWindowPosition(); calculateWindowHeight(); updateOverlayPositions(); updateUsersDisplay(); @@ -943,6 +955,7 @@ var usersWindow = (function () { windowTextHeight = Math.floor(Overlays.textSize(textSizeOverlay, "1").height); windowLineSpacing = Math.floor(Overlays.textSize(textSizeOverlay, "1\n2").height - 2 * windowTextHeight); windowLineHeight = windowTextHeight + windowLineSpacing; + windowMinimumHeight = windowTextHeight + WINDOW_MARGIN + WINDOW_BASE_MARGIN; Overlays.deleteOverlay(textSizeOverlay); viewport = Controller.getViewportDimensions(); @@ -954,7 +967,6 @@ var usersWindow = (function () { if (offset.hasOwnProperty("x") && offset.hasOwnProperty("y")) { windowPosition.x = offset.x < 0 ? viewport.x + offset.x : offset.x; windowPosition.y = offset.y <= 0 ? viewport.y + offset.y : offset.y; - } else { hmdViewport = Controller.getRecommendedOverlayRect(); windowPosition = { @@ -963,6 +975,7 @@ var usersWindow = (function () { }; } + saturateWindowPosition(); calculateWindowHeight(); windowBorder = Overlays.addOverlay("rectangle", {