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 @@
-
-
\ 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", {