From 3d8df56baa140aebd58bb31862768536a86d8c36 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 12 Feb 2016 10:13:06 +1300 Subject: [PATCH 001/114] Copy bare minimum of files as start of restyling Running Scripts dialog And add license headers to files. --- .../qml/controls-uit/FontAwesome.qml | 26 +++ .../resources/qml/controls-uit/TextField.qml | 17 ++ .../qml/hifi/dialogs/RunningScripts.qml | 16 +- .../qml/styles-uit/HifiConstants.qml | 70 ++++++ .../qml/windows-uit/DefaultFrame.qml | 79 +++++++ .../resources/qml/windows-uit/Fadable.qml | 61 ++++++ interface/resources/qml/windows-uit/Frame.qml | 101 +++++++++ .../resources/qml/windows-uit/Window.qml | 201 ++++++++++++++++++ 8 files changed, 568 insertions(+), 3 deletions(-) create mode 100644 interface/resources/qml/controls-uit/FontAwesome.qml create mode 100644 interface/resources/qml/controls-uit/TextField.qml create mode 100644 interface/resources/qml/styles-uit/HifiConstants.qml create mode 100644 interface/resources/qml/windows-uit/DefaultFrame.qml create mode 100644 interface/resources/qml/windows-uit/Fadable.qml create mode 100644 interface/resources/qml/windows-uit/Frame.qml create mode 100644 interface/resources/qml/windows-uit/Window.qml diff --git a/interface/resources/qml/controls-uit/FontAwesome.qml b/interface/resources/qml/controls-uit/FontAwesome.qml new file mode 100644 index 0000000000..5c03ef09b2 --- /dev/null +++ b/interface/resources/qml/controls-uit/FontAwesome.qml @@ -0,0 +1,26 @@ +// +// FontAwesome.qml +// +// Created by Bradley Austin Davis on 24 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/fontawesome-webfont.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} + diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml new file mode 100644 index 0000000000..6d5b08e430 --- /dev/null +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -0,0 +1,17 @@ +// +// TextField.qml +// +// Created by Bradley Austin Davis on 4 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +TextField { + style: TextFieldStyle { renderType: Text.QtRendering } +} diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 8834c1d8bc..01f21f2c2a 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -1,11 +1,21 @@ +// +// RunningScripts.qml +// +// Created by Bradley Austin Davis on 12 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 as OriginalDialogs import Qt.labs.settings 1.0 -import "../../styles" as Hifi -import "../../controls" as HifiControls -import "../../windows" +import "../../styles-uit" as Hifi +import "../../controls-uit" as HifiControls +import "../../windows-uit" Window { id: root diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml new file mode 100644 index 0000000000..055f06d60b --- /dev/null +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -0,0 +1,70 @@ +// +// HiFiConstants.qml +// +// Created by Bradley Austin Davis on 28 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +Item { + SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } + readonly property alias colors: colors + readonly property alias layout: layout + readonly property alias fonts: fonts + readonly property alias styles: styles + readonly property alias effects: effects + + Item { + id: colors + readonly property color hifiBlue: "#0e7077" + readonly property color window: sysPalette.window + readonly property color dialogBackground: sysPalette.window + readonly property color inputBackground: "white" + readonly property color background: sysPalette.dark + readonly property color text: "#202020" + readonly property color disabledText: "gray" + readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2 + readonly property color light: sysPalette.light + readonly property alias activeWindow: activeWindow + readonly property alias inactiveWindow: inactiveWindow + QtObject { + id: activeWindow + readonly property color headerBackground: "white" + readonly property color headerText: "black" + } + QtObject { + id: inactiveWindow + readonly property color headerBackground: "gray" + readonly property color headerText: "black" + } + } + + QtObject { + id: fonts + readonly property string fontFamily: "Arial" // Available on both Windows and OSX + readonly property real pixelSize: 22 // Logical pixel size; works on Windows and OSX at varying physical DPIs + readonly property real headerPixelSize: 32 + } + + QtObject { + id: layout + property int spacing: 8 + property int rowHeight: 40 + property int windowTitleHeight: 48 + } + + QtObject { + id: styles + readonly property int borderWidth: 5 + readonly property int borderRadius: borderWidth * 2 + } + + QtObject { + id: effects + readonly property int fadeInDuration: 300 + } +} diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml new file mode 100644 index 0000000000..df632236a2 --- /dev/null +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -0,0 +1,79 @@ +// +// DefaultFrame.qml +// +// Created by Bradley Austin Davis on 12 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "." +import "../controls-uit" + +Frame { + id: frame + + property bool wideTopMargin: (window && (window.closable || window.title)); + + Rectangle { + anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); } + anchors.fill: parent; + color: "#7f7f7f7f"; + radius: 3; + + // Allow dragging of the window + MouseArea { + anchors.fill: parent + drag.target: window + } + + Row { + id: controlsRow + anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; } + spacing: iconSize / 4 + FontAwesome { + visible: false + text: "\uf08d" + style: Text.Outline; styleColor: "white" + size: frame.iconSize + rotation: !frame.parent ? 90 : frame.parent.pinned ? 0 : 90 + color: frame.pinned ? "red" : "black" + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + onClicked: { frame.pin(); mouse.accepted = false; } + } + } + FontAwesome { + visible: window ? window.closable : false + text: closeClickArea.containsMouse ? "\uf057" : "\uf05c" + style: Text.Outline; + styleColor: "white" + color: closeClickArea.containsMouse ? "red" : "black" + size: frame.iconSize + MouseArea { + id: closeClickArea + anchors.fill: parent + hoverEnabled: true + onClicked: window.visible = false; + } + } + } + + Text { + id: titleText + anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; } + text: window ? window.title : "" + elide: Text.ElideRight + font.bold: true + color: (window && window.focus) ? "white" : "gray" + style: Text.Outline; + styleColor: "black" + } + } + +} + diff --git a/interface/resources/qml/windows-uit/Fadable.qml b/interface/resources/qml/windows-uit/Fadable.qml new file mode 100644 index 0000000000..bf3a6aa2b4 --- /dev/null +++ b/interface/resources/qml/windows-uit/Fadable.qml @@ -0,0 +1,61 @@ +// +// Fadable.qml +// +// Created by Bradley Austin Davis on 15 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtGraphicalEffects 1.0 + +import "." +import "../styles-uit" + +// Enable window visibility transitions +FocusScope { + id: root + HifiConstants { id: hifi } + + Component.onCompleted: { + fadeTargetProperty = visible ? 1.0 : 0.0 + } + + // The target property to animate, usually scale or opacity + property alias fadeTargetProperty: root.opacity + // always start the property at 0 to enable fade in on creation + fadeTargetProperty: 0 + // DO NOT set visible to false or when derived types override it it + // will short circuit the fade in on initial visibility + // visible: false <--- NO + + // Some dialogs should be destroyed when they become + // invisible, so handle that + onVisibleChanged: { + // If someone directly set the visibility to false + // toggle it back on and use the targetVisible flag to transition + // via fading. + if ((!visible && fadeTargetProperty != 0.0) || (visible && fadeTargetProperty == 0.0)) { + var target = visible; + visible = !visible; + fadeTargetProperty = target ? 1.0 : 0.0; + return; + } + } + + // The actual animator + Behavior on fadeTargetProperty { + NumberAnimation { + duration: hifi.effects.fadeInDuration + easing.type: Easing.InOutCubic + } + } + + // Once we're transparent, disable the dialog's visibility + onFadeTargetPropertyChanged: { + visible = (fadeTargetProperty != 0.0); + } +} diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml new file mode 100644 index 0000000000..9654143cd8 --- /dev/null +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -0,0 +1,101 @@ +// +// Frame.qml +// +// Created by Bradley Austin Davis on 12 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "../controls-uit" +import "../js/Utils.js" as Utils + +Item { + id: frame + // Frames always fill their parents, but their decorations may extend + // beyond the window via negative margin sizes + anchors.fill: parent + + // Convenience accessor for the window + property alias window: frame.parent + readonly property int iconSize: 24 + default property var decoration; + + children: [ + decoration, + sizeOutline, + debugZ, + sizeDrag, + ] + + Text { + id: debugZ + visible: DebugQML + text: window ? "Z: " + window.z : "" + y: window ? window.height + 4 : 0 + } + + function deltaSize(dx, dy) { + var newSize = Qt.vector2d(window.width + dx, window.height + dy); + newSize = Utils.clampVector(newSize, window.minSize, window.maxSize); + window.width = newSize.x + window.height = newSize.y + } + + Rectangle { + id: sizeOutline + width: window ? window.width : 0 + height: window ? window.height : 0 + color: "#00000000" + border.width: 4 + radius: 10 + visible: window ? !window.content.visible : false + } + + MouseArea { + id: sizeDrag + width: iconSize + height: iconSize + enabled: window ? window.resizable : false + x: window ? window.width : 0 + y: window ? window.height : 0 + property vector2d pressOrigin + property vector2d sizeOrigin + property bool hid: false + onPressed: { + console.log("Pressed on size") + pressOrigin = Qt.vector2d(mouseX, mouseY) + sizeOrigin = Qt.vector2d(window.content.width, window.content.height) + hid = false; + } + onReleased: { + if (hid) { + window.content.visible = true + hid = false; + } + } + onPositionChanged: { + if (pressed) { + if (window.content.visible) { + window.content.visible = false; + hid = true; + } + var delta = Qt.vector2d(mouseX, mouseY).minus(pressOrigin); + frame.deltaSize(delta.x, delta.y) + } + } + FontAwesome { + visible: sizeDrag.enabled + rotation: -45 + anchors { centerIn: parent } + horizontalAlignment: Text.AlignHCenter + text: "\uf07d" + size: iconSize / 3 * 2 + style: Text.Outline; styleColor: "white" + } + } + +} diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml new file mode 100644 index 0000000000..435d8bdb15 --- /dev/null +++ b/interface/resources/qml/windows-uit/Window.qml @@ -0,0 +1,201 @@ +// +// Window.qml +// +// Created by Bradley Austin Davis on 12 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtGraphicalEffects 1.0 + +import "." +import "../styles-uit" + +// FIXME how do I set the initial position of a window without +// overriding places where the a individual client of the window +// might be setting the position with a Settings{} element? + +// FIXME how to I enable dragging without allowing the window to lay outside +// of the desktop? How do I ensure when the desktop resizes all the windows +// are still at least partially visible? +Fadable { + id: window + HifiConstants { id: hifi } + // The Window size is the size of the content, while the frame + // decorations can extend outside it. + implicitHeight: content ? content.height : 0 + implicitWidth: content ? content.width : 0 + x: -1; y: -1 + enabled: visible + + signal windowDestroyed(); + + property int modality: Qt.NonModal + readonly property bool topLevelWindow: true + property string title + // Should the window be closable control? + property bool closable: true + // Should the window try to remain on top of other windows? + property bool alwaysOnTop: false + // Should hitting the close button hide or destroy the window? + property bool destroyOnCloseButton: true + // Should hiding the window destroy it or just hide it? + property bool destroyOnInvisible: false + // FIXME support for pinned / unpinned pending full design + // property bool pinnable: false + // property bool pinned: false + property bool resizable: false + property vector2d minSize: Qt.vector2d(100, 100) + property vector2d maxSize: Qt.vector2d(1280, 720) + + // The content to place inside the window, determined by the client + default property var content + + property var rectifier: Timer { + property bool executing: false; + interval: 100 + repeat: false + running: false + + onTriggered: { + executing = true; + x = Math.floor(x); + y = Math.floor(y); + executing = false; + } + + function begin() { + if (!executing) { + restart(); + } + } + } + + + onXChanged: rectifier.begin(); + onYChanged: rectifier.begin(); + + // This mouse area serves to raise the window. To function, it must live + // in the window and have a higher Z-order than the content, but follow + // the position and size of frame decoration + property var activator: MouseArea { + width: frame.decoration.width + height: frame.decoration.height + x: frame.decoration.anchors.margins + y: frame.decoration.anchors.topMargin + propagateComposedEvents: true + hoverEnabled: true + acceptedButtons: Qt.AllButtons + enabled: window.visible + onPressed: { + //console.log("Pressed on activator area"); + window.raise(); + mouse.accepted = false; + } + } + + // This mouse area serves to swallow mouse events while the mouse is over the window + // to prevent things like mouse wheel events from reaching the application and changing + // the camera if the user is scrolling through a list and gets to the end. + property var swallower: MouseArea { + width: frame.decoration.width + height: frame.decoration.height + x: frame.decoration.anchors.margins + y: frame.decoration.anchors.topMargin + hoverEnabled: true + acceptedButtons: Qt.AllButtons + enabled: window.visible + onClicked: {} + onDoubleClicked: {} + onPressAndHold: {} + onReleased: {} + onWheel: {} + } + + + // Default to a standard frame. Can be overriden to provide custom + // frame styles, like a full desktop frame to simulate a modal window + property var frame: DefaultFrame { } + + + children: [ swallower, frame, content, activator ] + + Component.onCompleted: raise(); + Component.onDestruction: windowDestroyed(); + onParentChanged: raise(); + + onVisibleChanged: { + if (!visible && destroyOnInvisible) { + destroy(); + return; + } + if (visible) { + raise(); + } + enabled = visible + } + + function raise() { + if (visible && parent) { + desktop.raise(window) + } + } + + function pin() { +// pinned = ! pinned + } + + // our close function performs the same way as the OffscreenUI class: + // don't do anything but manipulate the targetVisible flag and let the other + // mechanisms decide if the window should be destroyed after the close + // animation completes + // FIXME using this close function messes up the visibility signals received by the + // type and it's derived types +// function close() { +// console.log("Closing " + window) +// if (destroyOnCloseButton) { +// destroyOnInvisible = true +// } +// visible = false; +// } + + function framedRect() { + if (!frame || !frame.decoration) { + return Qt.rect(0, 0, window.width, window.height) + } + return Qt.rect(frame.decoration.anchors.leftMargin, frame.decoration.anchors.topMargin, + window.width - frame.decoration.anchors.leftMargin - frame.decoration.anchors.rightMargin, + window.height - frame.decoration.anchors.topMargin - frame.decoration.anchors.bottomMargin) + } + + + Keys.onPressed: { + switch(event.key) { + case Qt.Key_Control: + case Qt.Key_Shift: + case Qt.Key_Meta: + case Qt.Key_Alt: + break; + + + case Qt.Key_W: + if (window.closable && (event.modifiers === Qt.ControlModifier)) { + visible = false + event.accepted = true + } + // fall through + + default: + // Consume unmodified keyboard entries while the window is focused, to prevent them + // from propagating to the application + if (event.modifiers === Qt.NoModifier) { + event.accepted = true; + } + break; + } + } +} From b3233c2d21ada3707b7807f32cbad5fc65943bc3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 12 Feb 2016 10:13:28 +1300 Subject: [PATCH 002/114] Add Running Scripts dialog to UI tests --- tests/ui/qml/main.qml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index a55f042227..4a04e4a93a 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -13,7 +13,7 @@ ApplicationWindow { id: appWindow visible: true width: 1280 - height: 720 + height: 800 title: qsTr("Scratch App") Desktop { @@ -36,6 +36,17 @@ ApplicationWindow { property var tabs: []; property var urls: []; + + Button { + text: "Running Scripts" + property var builder: Component { + RunningScripts { } + } + onClicked: { + var runningScripts = builder.createObject(desktop); + } + } + /* Button { text: "restore all" @@ -133,6 +144,7 @@ ApplicationWindow { } } + /* Window { id: blue closable: true @@ -157,6 +169,7 @@ ApplicationWindow { Component.onDestruction: console.log("Blue destroyed") } } + */ /* Window { id: green From f29b75b517bef2cfdf5f6b4426491ea6dea2c548 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 12 Feb 2016 13:17:27 +1300 Subject: [PATCH 003/114] Add fonts --- .../resources/fonts/AnonymousPro-Regular.ttf | Bin 0 -> 158080 bytes .../resources/fonts/AnonymousPro.license | 93 +++++++++++++++++ .../resources/fonts/FiraSans-SemiBold.ttf | Bin 0 -> 437824 bytes interface/resources/fonts/FiraSans.license | 94 ++++++++++++++++++ interface/resources/fonts/Raleway-Bold.ttf | Bin 0 -> 179244 bytes interface/resources/fonts/Raleway-Light.ttf | Bin 0 -> 182376 bytes interface/resources/fonts/Raleway-Regular.ttf | Bin 0 -> 178520 bytes .../resources/fonts/Raleway-SemiBold.ttf | Bin 0 -> 180492 bytes interface/resources/fonts/Raleway.license | 94 ++++++++++++++++++ interface/resources/fonts/hifi-glyphs.ttf | Bin 0 -> 17612 bytes .../qml/styles-uit/AnonymousProRegular.qml | 25 +++++ .../qml/styles-uit/FiraSansSemiBold.qml | 25 +++++ .../resources/qml/styles-uit/HiFiGlyphs.qml | 25 +++++ .../resources/qml/styles-uit/RalewayBold.qml | 25 +++++ .../resources/qml/styles-uit/RalewayLight.qml | 25 +++++ .../qml/styles-uit/RalewayRegular.qml | 25 +++++ .../qml/styles-uit/RalewaySemibold.qml | 25 +++++ 17 files changed, 456 insertions(+) create mode 100644 interface/resources/fonts/AnonymousPro-Regular.ttf create mode 100644 interface/resources/fonts/AnonymousPro.license create mode 100644 interface/resources/fonts/FiraSans-SemiBold.ttf create mode 100644 interface/resources/fonts/FiraSans.license create mode 100644 interface/resources/fonts/Raleway-Bold.ttf create mode 100644 interface/resources/fonts/Raleway-Light.ttf create mode 100644 interface/resources/fonts/Raleway-Regular.ttf create mode 100644 interface/resources/fonts/Raleway-SemiBold.ttf create mode 100644 interface/resources/fonts/Raleway.license create mode 100644 interface/resources/fonts/hifi-glyphs.ttf create mode 100644 interface/resources/qml/styles-uit/AnonymousProRegular.qml create mode 100644 interface/resources/qml/styles-uit/FiraSansSemiBold.qml create mode 100644 interface/resources/qml/styles-uit/HiFiGlyphs.qml create mode 100644 interface/resources/qml/styles-uit/RalewayBold.qml create mode 100644 interface/resources/qml/styles-uit/RalewayLight.qml create mode 100644 interface/resources/qml/styles-uit/RalewayRegular.qml create mode 100644 interface/resources/qml/styles-uit/RalewaySemibold.qml diff --git a/interface/resources/fonts/AnonymousPro-Regular.ttf b/interface/resources/fonts/AnonymousPro-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..06aafc067310fba0d33b0a133654475ac73388ab GIT binary patch literal 158080 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%0De#;=TZ#{I_Q#`DG- z#@pO``-oXG_cIrnhnvTmr<-HuMdoGZb>=$re)Dnjd2^d3TedaN`lxk)RkaSczG5x4 zzHXgjeamWC-?uKXF19YSuC}hVZno~W?zjHOdeVB{dc)cg2nBM1`GLIy<-nnVuLe#F zoD=W@KMnjMur_daU~}NFfmZ@=2d!W__@Ur};DNzf@Tv8^4f<>k1)mJQ z6#Qq1gi@hhL;Hj(p)ZAw51ko0FVqTM5n2HQ@zArOH^Ndl5*`lk8D1FvLip(L zso}H3Uii}R)#01M)8Rjcp9;Sielwy*?8s1LkH{w@2S>gVIWclpWJTnX$d!>_Mb<}t zANf<{g~&ErwWGFU?`bczKaZB|J9g8))Nb21+P||m*-zRp+5d`?XdLa>r=y2NkBOcV zZA5<<{jca`^p@y!^pDZML|=~fVu4sTR*dZvtHiz-J1+Lk*jVhM*w12}*sZY*u}5N0 z#Ga1L#&*QR@uB!0@%`hUk1vUz7(X-q{rJlG&*Hy~-x8mWKNx=^{`dH{gq#Q`@`++% zpTwfX;fbY*Qxe}v{2;L^@$0EcNYFGj&Po%GC9#^{M+) zkEWhZy_$L_9Zcub#q>VuMd`!S$ELrLZlupouS)+s{p<8^(;L%|rJqT^mhNTDOe*ui zOeu3f=8()$nUgZ#&aBA%7`?6AGXI@V{yg;D(Cn~092@@N@Pgsb4u56% z>%(UZj}3dnmkwVwJT-jx@WaD@8Gd2-_2J$;GA}-FXx?t~_L{fIc-1tNW{;Q4dxZtH-OStLLZ}sN?F-)f?42)Cbf*b4zDvNo^NxPi;gyNIODX zs-3KzseNC&P`g~aUb{ovpgpQRr)|?UJ)zIn7wC)hntrVQ4gGB0(|@90qu-?8rEk)o z(6{Pu5|u>BJhCU*pH#_L$O+_3;*yKW&&W08CUO_qOr9WH$(vNAHqFux(B0_AX_+2I zkECCxb^1Me5uKpFq-*It^g;SJ`oHv_hHltK-uSSwuTeG*F_s!98fO_}=(n|uwlQT) z8xI+OHvVQjZ@g;!)09lpjGM#ep5_7QyPar$(;PD|G=FMdVgAy*(fpnHp!pZ`74sb{ zWDQw+S_fE%T3@wJx6ZLHvM#r-w|;BgXFX^=YCT~+ZT;PP&3e z1B(LHz!w8c11ANR2UY}Hfhz;o1#S=AA9yVALg39H3C4pT4DJ>DOz^PavBA@VW5El9 zmj$m4{w8>D@Uh^t!PkR3LXl7*v`6TZq0fho44oWW9%_bGg{}_W9J(j;aOj!P>tQ(@ z4SyiKSNPN6L&IMUe*@#tiSRGOw}tNwKNfyIye*$Yr%?O}Tldw+~Rm)YO8&$lnNud#2k@3#MF|IL2c?nSL=E?SI^ zL=TF7CHnQ~S<&;NmqdRay(u~!eJJ`=^yTPVF)Nmi?H1c7_Sx8%VqcGaD|TM&N3kno zH^lCUZHhe=dnxu-oW|4fUE_Pl4~!oX|62SEv}vp3H^gs=uaEyB{zUwx_*)4pkxP6e zF_Jhau{d#jqMkT6u`+R4qLa8Su>t+CR};OYmCPhRlw6Qpl&mF>O`ewgZt}w9WywzR zw&Z=uN0ZMaUrD}`vQnAU2UB~e%BjOrN2N|kotgT6>cZ4zsb8dSPTiIIL+Y{AOzM@? zTWKR5Pdn*7)BC3nP9K>*IsNVQ`RPm3KTqG7zAOD;`pNW*>3?QuCY{+Wvrp#0%n_O6 zGG}DIm$@kOv&^-b-(>F1Jd$}j^IGPeY#^J>?v~vrdtmm6>~YyMvfs;Il)XHAUG_KG zd$W&ZpU%FPeJf|=;<;h8U!Tbxk~=bYVy>P$CwD>alHBUtwYjyqyK;ZX{VDhN+#9(a zc`KjH?~>m$KaxK%e^~yg{0aGQ<53+Ej?@0fX~&-?zoOXgiO@78(u%zJ3wlk>LD+vdnl+}YLH x*IDEo;vDH5?|jo4b3A9z$3@=3&lJeZM>;rIz)6G{bm*nrT|r{{dW1_)h=; literal 0 HcmV?d00001 diff --git a/interface/resources/fonts/AnonymousPro.license b/interface/resources/fonts/AnonymousPro.license new file mode 100644 index 0000000000..5e8b7385e7 --- /dev/null +++ b/interface/resources/fonts/AnonymousPro.license @@ -0,0 +1,93 @@ +Copyright (c) 2009, Mark Simonson (http://www.ms-studio.com, mark@marksimonson.com), +with Reserved Font Name Anonymous Pro. +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/interface/resources/fonts/FiraSans-SemiBold.ttf b/interface/resources/fonts/FiraSans-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..821a43d7fd25967a72ebe7b828fd8d1491767de6 GIT binary patch literal 437824 zcmeEv4R}>Ywf35Q&Pj4YO6keT`A>36DNU0QLK2b?LP)kWr4%Veq!bY;rHGUwQlu1- zB65*(kyeT{Qlyk(iWIp(F}EUeDI^2kx0ayT`Y$`2(dCEhnPnta~1~ zZyU}3A*B>;Axe2+_U9j*+y3R!y_7O=BGLWN&z^JN?Aty!Orwtn{-?>~f5yL=JpM-i zHuCtl`}dH?|0DlT$m4%AJ)JzH(E$I${)b8U7x=$Sntzdh5efez{zpjjf5rb*68@$B zuaV|o?q5#A|ET{_()=s@D@geN*}sZ3|6~5g$m4(9{{(6NHU4js@UQhhNt(aG-$26u zE&sPj^RM%-BjJC_{}gHd_5SrF{NMI(AkF`@|7jBbXZ+8Q@Ne>OBF+D-|5+0L&Hl}# z`5XO>r1_uoKS#p9#lM9-{_py?lIDNjzm0@{yMH?g|G)Tmkmld%-$}y%g8%y@{7wEQ z()|DG-$TOxBma*``1kquk>-EN{}KuRkNrO;&A;EjpM?J>{-2QMf7Aab()<_we%Q$B>ZosYow+7(*2~Rr>CcrKs%(1GVd|+4yzwImSXolJZB~qes<1%_fyTx zd*;rf(d6Z3GEMyLNeRk#Q3PE}*;L@7Xw-{xsE}$Yy{`WDB#o+@a7&UVeynb6l4g8t z%-AH&zrAikl9qk^j*&@PGkWChN!m2#j*lm4$5@WDZ|s=clXOJo=%MQ ziqtP3WzzN3U;Rpen?Cr<1AMfWHR*2KZax?}EP<{z3RhAGrU4`?Zts&%?jOzQ+qc06z)82!1vE5%9;up9X&} z{3Y-oho)r5TH&Mfy(CB@5BlamGWL*+xG;|DDRMH|#mwHSR$RBe)f@6MBdzci0h1d;f+tCXScH=_Fp>D^pVj3GWZhmq~kh2UCtGTeec1K2K!+oN}nAdDd(-U!kDc zY+f>(&0m2$4m$!s+*@juF>bn}w=wt0Y4QI6RH9vu3H z`4-iiEoQ6PLQ(UN7eK0 zM_Dtnj@)tnyIe=9%(Fyj11>4IV~4VJ{6&O1ctuKPw(>v5mX9)UZN051Z&+nezqyoL z-nT9Ke~;^23ad5Qp`2(%$f;^v%7=Eg${$2*E|Y3=*+NzdxOB-6F}eP%&@@W3`TV!I z4pMx0hq5`cQ}V;IuuJ+s>C~8X9Jh}97x!Qy3R2J=*F1n$l%u%WDm7@_W@q6au=tpN zG#mFNu7C?DUe2uHRx1H zxy0I1jb0wbR?k(=Y9q-(xpe4XE;oe-5wQ=)>1Cr-R|8xw-g`TnU^Td>NzYg zYdBR;wgyDMur-@i6YL~a#n#K__tOnDYTkKK%NbBc-{BXHU+t9Nd`~+fExG zId&D#P-o3%v(Y?jHnLVQn_2hqti{@gYXG&74qGK1v;*cIbBB2V|8|(ItS5M#fH|=R zTH=6tmeS1~wvBSYY=jXkMbAw0~Gc^oz4ntFaw}G0^%! zYftJ$X+d=}u3VNF@`BDqx$H4$&DnPEWTb3yYh+62B1K|7u`TPa1&%}NjQ>JD}Jz%yoo#Wy!>!en*-FyR9G;08i7N-_0Auf5@Nxfp# zk0mW~v21W_jlgRjtd$Uol?&v8-6kajM=r7IV_lv3viS?vgk3|VL+v%1&E^hhOV))g zR!_BcrgZ6u!8(?8CD#P+9kG5@s|v+Y?LnAGj}kYcHZD1K7(4EDNWBQZxaMSAGw(fi z&AzX5TDr6AruMn!mHu;T@S|~E`PmfLto*k+NN(+Rd?06)lbtO|x2|)j(<}e)IrNT> zI!C#8lTOCwUBh>)Cx_qr%@iM@IH&Di%{%YSM}B^hLU``?in-HlHBV3u z?*y?uNKv{LT8j6j-iDrUp&aPzSIjqHaR+(UFwdI5FfUP|*<$_{vrxL(V*VRNEvxnK zbMH0|KB$xPV&}H%>SPRO7Bzn>XJNFeHD}53iv8)Xwqs`pUEl54{;=-DaCyJD?-$;! zQ}h1&IeS!g8rL@6<*f0{&jwuNcXd3sb{p6!uMgwc8t5)Q_w}xHwg@EEy>H_<^BD)f zn?qUIGJGE!-f^75{Im1>Z*%Wm$L=u(yC$deTx$N2HG!44gVoz?IdG$48you z-MKc*v(mPPO~w1_j{W&JI@F;p{YULSQqCW$H*=j@wa(5h$-7}kD?>jy_NdxFv|32@ zb$bU6j_q$A8J(mw56Qe?Iom4}v|P92tFx1_cy%d5AQjuq_S2K@oR!mubMAU^yLY2^ z>q;!DU0c$oSC*^AOO>8i$e^iEW! zNeyJ>+BvU|PVVh|R8Hk()k!DUS(lrE~YBcXvvXkH~?WwrvgUs$D-z zP$~^4G7p=3FpAR67W^NLr&oMRAxJrtCwD{Mtu{V-C)cgmfp|}cm2dYm?nmn6n6dgc zJJplrnw|SQ?@6#Wz%H*f#{RpUTxXkmJeBasMe%L1Fb+hzEhoY`n;2+W4uHV3TH-<`uAChwVZ zo1uSWZ^(LrpynX7An$ha{?-A+-eE46t;+jw*n8&?es0g_0I;8A9w2SYA)IJxXc>pWw=-#7zQ)w!tQ%~wi)il*?q0uy& z>Z#f--v@P_a&er~uN`Fd|Bm*`-{b1LNj$n6+WR;z1@BMu?x|gSmbC1G6v1D%Df)C~ z#?Lq3wH|C|#jyUqhwEesba3w##`*^{E_zo7&1U{gjwCfBg9}C$KYdcCDJ;hlLO)(I z&v)cvIk(M+F)B4{E1s-&dOpM)WH_hp$j|wOy`3(5il{5ptz~iWc^p1RNSQ>Ag(r8t zQ4Ve)K8Hwj9dcGrD6Cq?(~X{ZGNzvEcbq>_cKLLpU6#x$^M`XzS*)C0&eewetfr#` z@9!LrR;^f0>B=tkXghbGwp=H>#^K(rlRZaS(ik;w;3;Kmx4f~EvCEgPdY|pg-%Hrt zQvoZkwF<|HNnYV%mD`=Rw0e^)0jIOd;{MCn`p-^=fr4`?=%d}$6P~PCc~~b_x^tG~ zj#Kp|PjO{AIl5eqOHcAUFP$BpD7~AL9C_4o473N&iLxw?{&l-NOIL6kxyN%yXSbc@ zv}dpI+<78&VjQJYA;vb3e$1U}9_^$7{#J*Xo6B&3YZMj$o)*tU9hox&Br%ngTTIL-KdE!j2s##Ac$&eF%;RL4D%j9!GJnOUi{@?24 zD6u#*7ug3S`dhg|Gg`AE#v<~;^H}NrM!ChtMjn6Urv&w;JSw6xs-jw|r;#|X-}0e- zZQ~5)*fO$ZFZt*u=xlzrf)fDb!wkw;p6BOhFRbfXAIbA8@8hf!OciD;*M zU#C5-ajTqMdh$g|!TVsWUHMEAKl9#WE;5_ViL$0(&G5M7_0b;mwpO{z2Yt+AhS$7u z?8>c81HUf-aZ+0Q(-y(Y8{!-lUBXM9V4ZaBhiY*vo&i6ZGDjCe6{DRTPTIXYF@`VQH%)QL3mRlnN4SBt$MkB++p2~ z5IZifFL>6H_7<+^Y^i&>E|h~s^a{=b2Jwc1oFjSuDsff? z%A(btn#6VVTH>`N33cWPa}#M#jX;R@+87dCdw6o(YOY2fYc?p z%_N=*aBAXr#bUl+nLB+a&7Hni&7HnKm^*!@xih7Qxiclh+?jHXxih7wxijTjb7x8~ zb7#tR=FXIWxiclx+?f(Iccx^SJ5xgD&XlmZGbLi~Oo^I1Q)1@Ml(@MwC1LJN$u@VU zvulC#eE%mkF<4jS<>@k&(G%f;bHS) zra?P&ZHxDJ*e6gUEvRH*>rt*D`02d$&PMl+#|L(s~uo`3(}Z^&VxV@}3{h&1^ri2H;a)e7=@X*fK@#3UhDXL0SVW zsz0vz<1W1MO6E@UZS!rqfymrszGD7@DnWbGe3OQd*07v=(r=HppC$nvz+AZZ@jvc? zmq=@XMfImee`+80ja&eAd+>zVZnk7Z~8^bplQ_*tSnnFt3hi2aq0TrH=1 zkz6al$zBQV;qF^XTibI&C#UjNCjf1yJ&9iQr`3O2M;gB|+_lf6_F1!vCucpmo_v%c z*3rF0*PSF0m_#Bll|*0$iNI{4>&~dZ=ZNsXl|*13iNHbqrDPk_a@CH}E2fz%~+rT_k|_5nXqc$mVlEr8`U%@RA4|B?_dI2%I1hI7Jlb zMHC1@CMn-p5`ptXfdqLoiA11H#p_KJ$WyXhBoVkm6euE3=HoE))P^aTOd@ld`a6?E<{a{5uEl?mIbY?mh(zX6$U%X6@l2p+Aed<5 ze}PyasZifQp+Y5rnm{E&hXqC_+5#gIZGmxti7Ir8jiv`?DcbbFTpL-m1%btiwk)tZ z(H2;lXbUV0G}vf^LYo6yRlFU6CWZC}_J1IBDA26p9SR&*$SKFkz!^nzN^~yJo@fiS z1}+D#W_o34W_o5Xg+iIVGZTz6^D@gai-4*!YgMR&>N7_w+L+Ao3Qe-(O_h{HTjq?+ z*(%gQPUyVMg(`GO=5mErWv)?ZUFJrG8Z);kv@7#Pg`9l%Wgd{U!1Tf&Xnc(BWwTiahLf!TfyY+*cta!mK!R;#T z?%*DYoYoJ%6g;SCcIyX^Sn_q(`oUwt7RAp-uDW;H+(s^0Y^h}X22Uqk$kkf*2ym6x z>BUapwULvXtB*Tlby)CqHEQjV7rYQOR5>mLFR41%9DGNi9a)-0S!r246>V>pr6cxc z#T4yaR#J@~j3cH>8l%j8S$$=^%&IJ0H(VMO&P;Ore!ot0i)3JgXsVgQU57 zwmkxzw3(~2HmkIDPt4kywL@`k%GxWns58nOO_Q}U>rkRCYk#6Gt2s+)uFQQ*s(f=%A-B&YN9Rca-uD(J><1fxLx*MBtP!E3ipz=6DTU64&MVXw zx~R~VFxg1y#9jx&fkaz4gIgvXktm$QH2#-)F`OUn!zf%FR@yOKZM9KY4-c2|!lS}t z6`BxM+A%yWth8h1uJ9ZcIzOy*V&GhOsiLh2Kd#W)@Op(dg||o)JQh}3FT6Xfv|f03 z_$3wZVEBk^neef&(q`e);n!tocfG`E{qO}VUf2j*dZSaDGoSD~5v4&QX%S0OqN|!{7qDn_ZtD=^* zWNV9PeN^d)(DLXQ$=Stkyrq$%lcLHt%G?)KdLueJsR_vYTuPoR*F@Mt3FJqT3Q}Su3MTgGBd5m9~f;jw&4yJsdruBz0(~qRN(vHb%Mp z=M#)h*yy4{S7J(o#8P4zl1nTQi*$pOedUA(kHw%#5{#71mDL<8R%y#))e7mcQ8DP1 z%t^5ciMH6-*kp%G=Dyf86>nxtX_eUg*wPsEN^C_;=@J)O8&g^((j40)(`N39Dg6>q z{U*^C+aBAkINQh-x+kV|PG%^kEUnm)*fE(RTpUx{Cz>8Rt+>1%yP%L^&FjS@j~0;YK;>=9#>X@)A~-E$IryiDG6HRY9x2p`ti&0 zt16z2oHkE*6X`P4X?;f)2PJwXSPQUyVI!xtoKm{_uH9o@$nMY1xQsR?ddm@-$V(_2 z#2IgyV-mJCl2F!2qBf>x$ygwv>=LJCBF7U-`@}9Kl=g|ONT^j?Y(-*{EUz;bGIu4E z9&*Nh>_|dsB&RJCv#pWh)Soi~67v#jb(dI@Q2HvdDxtKL(*xdQ@kH+4u=16_`JI)%u(>4gg*{G?_~?~M))h?e+>S&;Xef5 z1OG1g=V+`*MUC=`eZFY!t}$>gg+R5KK$`~$Ei6Oem?vH_&35|34ap& z8SGze10Dtc)A0Mj{|dORhkrNx8{w~ne<%DI@CE!)@N?mR8h!!%XW`$)K0T{dkf5zv zF?_}cfe!+o06qcy8{ppne-ZeLz)t~h1l|bzg7TT$v%tSpeg%oEZ;4tG=5DSx;fMbz zvzUbV6qix+GuHf!#c+fU2fhRN4l#j*xC4~FOwrJ$qAw`?yheyTV19}v=m}7YKq>a@ zBq0VNuR);jZA3yGh93hZhByh&S`vbvxCrq>rqdN*DHZyaKvS|#Y{rQ+kj=&J&~LZH`)`@|#?VlqN|AZ-tnx(6r;P!hn;0Y3-K``bd~ z01pJl{k!62;Fm$?C+$Mq1iTD*8Sr<2Hv>y)n}L4=`fq^wNsSOU0P{0uL4ROOKL>sS z_?ujB^lh$TdLA+V1*!f8xF0ZjvUm`!@F3`X7mX0#2Oa@D0(b-P2H+~-D&QXh{|Fd2 zXNt#xPl0}lFoWjaFnxw{b8BlK<0Ur2a%u?(IUFbdWqv;r|JAX^0}L*Q3~ zF8k7IU;}Xs;OW48MpKABOwsr}s1SMRMRmaCh*=5BkKp%!-xHx;gpT&iB_ZwveIonR z4x9se4savtN$4u*$3Q;@{A=J}1K$JxZcy$9z6SUj;O_x{54aJ2 zD@xZ2+z#9h+-A0u5Z7?+iCm=0)qY2U-a&m{^$aEDgSLu0L=}SU<75u-7I5)uO`&os+%tF8Me3FD`2*>f%AZ-Ie z(-1QgX)zDtk%SPKNyWVg-HOnyz~#W@;BXa`Z!sS&8~x<#pf`c@Sn)6kT8@@FiBe}F zZ5C1mfrG%;qDKXgsuw5$Q0Aj<{|o+aI6fH&y;*yMgeX9qz6d=7EI`+Qeel18(9_5Z z^OV4hPk%*TW$=s8Y6UEz7Kfa2rrQlH=iGD1{Ty=VGr>YM0&fT24$M!Cg(v|Y20RRy zZ!;Id2fP4y0q{onH$%1uL4OdGYvFGOeKYVj;BCO^@O4mh;Fo}30_NL@h2SUrLTEg9 zi)-L#gA&I4E;Vo(=zh=LBt!%pBB02b#RKf~l#>v$pEMxtN#;Z65LyhL#lRKdQwv-N zoD0nF?+fu6U_RX=!~l_C9~4+|VjyEJ1(a*y^Z9Hc1~aBN8Pl7birxf;-?-&o&83?U zJRkJGf`Q zBt#wPW$=9*N>>ru;#ok#Gm|Nv&m+_eKaQ4-BhH1ZCJ7M-&l-dxzE}?YL&W?c@G#(E zz_6}`Y@O?oHXZaSj5RrjP65S>-ZBSqz70wceh77S5%d8b9|=(o%C9^_xR-+BL0S#| zSK+5ahQ&y=7<@hf{0YYNdk&@FgI)!{1oU>`1@I@pp98-XKCEA{6?iZB?*$$V{8Q;O z1y8TV{4)>dJ5Qstwvz~zkO)I!0vkX;A4l5M{NH2yG_HI!z+9 zl|*OO7J!?AFXaX1++4EF^p3D+c>!j;LU z(9H0N@G#IuhbM-|C7Z%i!qdaERNB$uxe|pk!V6R>Tf&P~=(6xig;s|f6xtBptk71g zY{{ljv7|Zm9NrN|Yb2Y(d&B!xibGcYg`302742mBj6%)fbBc>o_jX-zt0tSmt;r^* z#>4I5tI4MDWp49`SB8e$Bk7VB=@m&tLd-GJJ5m(M11gKuMyi17BV!^XfyPIsMkWEx zh|G)323i@)svIXGXCtQ|-}%VJNE^_VXiAhAMKhw2DEfOeC)!7r*VQ-dUJ}iZmM5E{ z#mS~LDXJ%%qNAb{l1F<8KAvofuILcY zPT}-A2SwLfBPzPy&TW&O+ZH>w?RIXv?cDa*xjFG{6r$+CD8^6pNVFw-3?)Auy%2pJ z$cVlZ#i)sCv7RxEl~^#AjKw;|vr{-D#f36rebuPQh!sl2DPkqbrdVaHCN?5AEZGzr z9UB*$5}TN8icOEriY!@+~QSMZt+?xw|KpkTYRLI zTYQY2+ju)S8-)(WF)EWy@u~3{N|xF2c@l-@#}_KvlK66kR>jvSv@X6;p~m<&iGmIB zU5fT%e4j+2webUrb~t`ip%Ydf@l)}$Dqc(cX#9M#Dc%;p7{4NE2}-EhC6SR(vr8h9 zP_s*-PXcpGvMJt}P}(t3o>22lLbpN_!xN(vzp)85<2aHA8xoj#k}jIVFW#7#rewDB za3pp3xoXm>E4zjgGZSi7OUzHGSuL?Np=Pzjm{)} zu}78TrNlvnW+sj(bS%-L(CGxmXR;~&VnWSt2_vEAx5PWy*8Dc#ikF~HvTRB=Wv6BL zRQ&9E&JJc{Y$uztli8RBldd)j9n3D2DMAOcOKenWqZ%7wwoG!o5jJhKjmFtXjls~t z>?t;Fx{cHf8#+U}fhAw|0!zN^1(tl- z3oQAv7g+LTFR)~ZFUeN(d3;IsGAUntNw%8V<4dwv+cY)D$CqSpuxV~w}zH886h5y+e+?P)km|jYisNjE%-yD7)E0Ig@NORiXstC>@)i9N0jtxpI`Y zjW_04+O{zVb`e4?z1x_xN=g-P%&|0ZW6nC8X6xddMw_Oza=bCe(#nlFFWR9>KRbHO zjdGOEPK?btEK?-L<|yr*7@Kp#rolo=GEM36#Mm6QN=S^&fz^aitQLSQ-99!KmK4)+ zm6p%Vu=I0oh7~V2!-|)iVabx4Vabx4Vabx4Vabx4Vabx4Vabx4Vabx4Vabx4Vdtyn zmSj_IB)3m4=9k?3Ts5cUmglNDC0EZKE=!&p$sL=EStWNuu9`n`r{&H`Hs#JtHs#LG zRa!o`JaY7THpnH-&D%`fKx*7vOaM<-d|Gi|O_ zFUbW-rFUIzWY>l?2HL|tJKPa*_*GGh$(PJaG zMzY55KN8KQ2^}5#{~b#7Nh(YAe@~c@_)#Kr{P^sr^vG(IQ8K^BO!D=ceo9ya!=I9<<*xXvVqO~`i>V!F?YxX(!7oRT~lqRmBoc|L^iPZXLwX&_IMTt(E^(E3FseTx4IK7!iGOssT@+gb$%LNLvH!K5sJtPio|I zG;wNzDI&yV_!a3)nv^q zKq#J@Yx1ewBTUhXSV9j@<7hZvq~VFA2WKI)0f>V$4<3FgPiQ#nrQM8FI7_45j5vtz z!5IuK7kTA*8u*kBPJPTVD@llh@c)B-Z2|l*!~X*OFT%f{eX$qyCeOzF82QR4X#0^D ze-T@F(Cf4>fPyE*9`qA!E-0Tx9KL%@XgE2e-48qyvZ3ZhJK9~=|6e#%`~{T1fCHXr zYmH3NaE3&~lSl2lpnMl`@T^w*HYnc)g>Oj~+B2X$gS?(XxoY5l41PQOKg0ho_;0c= zWM7qMY;X=xor=MUJAv~gnmikJ0i5v^Sd%^HO;BD%?(!VVtDyW2lp9dG-!X;0$?ZaG zxLveK2t91q>0Wtr|6b&b)H2!Y6@ZdSVwvFkY6$r(dC=WPmI2q;nI_Td-eA#2a ziTF4lrO6W!-vZ?!#Dr$h@U&XP*&*#L(>t8``2*y^87=Jv#@Y*r(-*z#M)a=ppu7#9 zTjAs6kA~A++LNFxMcO668vCLVHD3<@Hu#s}zYYIY_`idHlznybq(8=He?A34Z(|g{ zjWY(<<6MO6R0B05v>7p_R*~mV9^qaTZGCp zLh^Kwb>4ta)Z`&mf5y~?_-&vUf`1|Cu5&x;{L({6^^gn&cAuGXoynmUI6Z=sPQ+g_ z5%fp!cb}87&MvY%^0Yvc;ImTloYHN;9~Yk>L3`liEEcsR_g5kFtH6ImNryw8;lS4e zUk}dLfpR-2^}t_58NZ0MICmsZBH5>>`1H|e#FwY7syx+vmI?k|_*>wghW``x#Z8`P z`IHy@8*pkX0za&s2fZJk62a-3yU;^!LfYTK-wJ;%{3GypurICyhZOkrpm-5_2>x#P z7vTSleNl?s`@-*!RDIyzz%tMg&X+!i`2FBV;okwj6n+Dzr4{hka9Vm4{&H|w!KI)_ zxfJxzo`?8M4pO}g|NHQN&%P)|zBj_Z6O>-?s}bjI`2Pm~dHAow|0(+-AMz*Q%ky&b z6kH57nLtg(QIiSC(1=u1;pf56fAk{y?UkaW-L(M#mcIkTl=iN^J zq@Wkca~-ZTKXeYg{W8u)bUm>nPfX$biTgZ^C_;SqNgLP6AL1MQtkW9uq-)ocKk^(A z&Z){%Km-j>ui`vLms3FMT#9vWiqC97tE*E$@(d?V%gD1jA`NFwUWX*FLt4!8A`=+1 zIUN+&+b5>R0Dn?UCqXZ>FUojK(VwM{9C2QVOmK)|#HI4trw-?Wu18FHZV*~x+=_7* zoKqz?Umz`i0crV*Ny}eGTK-C+n+^5%5)uBtLt6f7(()Tf%ilm+{$`?ljkNr&MEPl? z;@Dk-0lBXa+T0y#sS3;CuDP<|>MOs0KD8Gh8{w$*WVMGWYL0UnA zD1Ws2ACzUvA4gh2Z}Jv2%Df8lz+WpUBCVi|w1O(q3TjC!s3)ypBxwa>NGljmls}Ou ze~Rn(bkYhYkybF3w1OF=70f2BU><1&3rQ9^RS+ikSlMtgu>(vAFsHtmRw94^OfS_{x=-N=94 zrd%xE!a%XFh)wQdxwENIY;f(4761@3Yv7IV22BF zioFQkZ>M$Qap)n0Hrt`cb)(>nZWNp>IA_zG^0w+mK|4|~x(sx+&|8=eNg4IBQOHIK z8#(cM7v|{(QWO=I=|*8yq1Q#LEv#3eBW*OMaJ-^TviVK5(F{i5;^Z;g4xMMCg*IAZ zBcv!?t{a7`m{zz(HwxDQZ7lQ_HrnyFfwoIG3SYF*J{uhXI;! z#^^jym2MQa*|du`x?&;j8@kakZ9n4Bekr=qF9Rr`8~q|cIl9rW4^X~t^efkme#QN& zb)(;K-RP%-HVQNj9ouh0zv6zA?Re94qu(6e=r^<9e5)M&7U@R6rQo+hH~L|8_gmX< zeLsxkep~vj?}t$f8b&P;MlH}wNXsb>_B*0W8pbMU7^^^%AICe56tCNPFb(4u$gufg zB!h;L3qgO5rm;pU zYAV`Ww4-RhZWJ9tzKoh}bR6iUZWNtigjR)aFFL0iMXeUCsNF&`l;ag$M%t^gZ@ANP zXn!wKaNhtw&@fV*Jo@*t>Z&_h|B!C<$Jp-}uYYgmTzIN~UjL&0WxCP7N;mq~+O&G6 zIiWx!ZQ2-#bfbTfonn0dNh-zE{xfu=|Lp#GF50~Q3svY68!hj@O3~KXoY&cCqm3GE zw2cusLuN>|%MN|fMn(PiDbDqbR0@l>%SJES=zxu6Z5-B({z_Z)&+C7}=6uRVXKi%e zMvhd7*S}3S`d`tF{ufzq6hm78rP#H0z)D-3VWR+};)re(=Wx8@KDtqi85Rgu1|yy| zbfdUj&K2%>&OBXQtsBKU$KzgHj6MVedjkmeMyJpT;5@lQifQ0dq8r6CJMt@@qZ`HZ zkz$c<6hlh^t>}gZ%~ia%L%j9Hn{=7NNegSFc)J~Mw>8HX@6nCogSt`tQt=VpC~nb> z;$xtl2F(e5-Hzwb6w)P^3rNAgz|XN&iZ59-*6qd6YXdah7yxZ%aVdUjK+gfe0kHu| z-2mzfR9NU8P%@xW(Q53_VKy2uV6+MyXVWIy$l*7o8`^ZH_3zao-&uCNxi*RoSYS)F zz)oS&X4z=2jTYO;kzkq4Z>5b8%Dq^QeUyB)9lF>?4L}>Ld3C^M-59Wyd&Gbpx-p;$ zXs>Pz*l#2BXV97l9M>f}X@^3y4mhV91E5cxQDNC;x-p<#HwHkTGLrodw5ugv8Cn9} zS<=fLuLL$yNkUp~Dju{Wr!C222}+7|qoj-xTWKX#kg7v&CD5HE^}10q5-Avsv5`X? zZ_{8wl}xo$%#giKcUeItvvs3nVabw`c_qtrqXd>w$r{}#fn}7RqZ=g~nI8~rq>^pA zQL+npyr>%`u#8F$=tjw5(2nXx3G5;6#U-bh<{-A4N~C49yyU#h4MOp}%oBUnbI z)Ro4erBcH&f@K60;M{;kx0YR?;L9an7X+^RG z&~QM|Ye182S)kY0zAA-Ya}eUqvEsS-LDwO45r>v8)s0fO(#N?+HFQdne8yn?H`QHpp# zu+2Krpv}rOcf2y_wX&YNQ6|@0S9PNd_F7p|H_EWyDl62DvJ#fS;m0zU)szh@t1KI# z8)dM_c!gFr4w5>d6RmhI+7#U=n{LOO#ay`Lir-vIma+x9QMMR)EYpp$m7Jn%wH>cP zH_A4E#-W>mw(3UN4y0((jk3K!Oxq81NH@xw8RefYJ6;C;0tEd6bdI?ILDQ7AcZdi5 zg3zl2y}T+fJKlwMy6pJCbc8bMH83Rk4TK#A8uSYg^b5GyvJ8Y(g;3}mAm|(*Xc|T` zMd3!>7+B9TvmHASnr7e_-53Z>!|TR@&@>Kh;8fihh_%|l*}5?h>oOp$%LXpdje*OV z-@sM6F>npgIx7VvfX?B5KM*=+;5OYD2%Q6jb(xE{Pd5f)T{iHrZVZG~HSmOP421Rp zg3cLuUN;6p(+s?5b7llhQ%<^34z0qpa%dGGXcZu66{L_-aXeU1+)K)_8Y|D&jdEB} z<>k6j4qf7+>AF!4T~a8t)KPVBJ_T zS~n`7kt!zYM#c1sSrt=&<^nCyjf%z0rDB`KwpA+6-H zS2rqPzaZWr@N2f?9oLPDlc1f^jS6U$idNmIXt(pdTIsF0T$!#LmDsVV4CzK?@5;Q& zL}ig~RATH`R_R71Mm!M4IS|Hq0<~3MROpJ8b`aSp#YP!6 z3NQj^Thc)hJ2b~amAeM@vC6?nrm$#(A~wpgQND#FXYM(Jpru&SLFE?bLDe?WZ8V(G zpix#Ep=^$PNHJ)vZVZA}88lfpDxs-?U>zcle4F1i8_fjTA@!AR44R`GgJAm%TBI9; zuvP#kys*<`<1uey^{3`5Z0YP7NqCsC()mZVInG^A#xjLnQ=BgTPrKlR`Msluo zxbVzgHKl5L)x_>l)hykpn#;9YwZMv3wb(*VimGKyL%fw1Lg;GdEJK0V=7Ob#c(A^z zHe39vw(3UJ4(7u1Wfj(WReP=>E>~SGpD@^~8;l00GaB4$aAEHwI%L9SHgW2$mZVGy@Ry?%>0^F&LKH;1jwr z7?xYUZdsPR?>!hc+~D)pIASyy)*KMljX<#Gs%>kIY1OdnsxvIgVk5f)*LK6#DmpWZCicSV|Ak%8q*bTvTjsk zwOBn$BRte&qM)k}4wdQtTX-Kd8CV=K2BPu;55>qhk!-KgHg?NJRIi7k|B=(XxS zx={^nHlR>9s*hA3t3FuWq8ruFQoO5C4V$a_f^JmHwcl>tsD{l|{mu|=2<$5$=q4bn z-+-W{sxyXYU1*#Zd+4jr;VH-lFUrtx!w+Mcz++O*o3Zq!2W0zvQA z7FxQA+fC|rMzydaJJMXCuqSJ4+$mh4uqSI-A7idyF0$7-{Ax#AHPjugcARe1LT7Vm zEp&Fj`L)w)XVuQtB`UEIXwJ-pcnj>%#Wq@Iqm{M1e^*#Ly)zAI8#okbL+xgTw%TcT z*r>@y!)&yd5jfkD)|{|I_uFVz?IF7yydTK2*tD7xc4)JWj@t;FYftJ%t$fzY^>WVU z+-jqC8(p@MEtQN{dsR2;@PwD^uNJc(5LzFck6UT$(rwg>5%2id;mHNt&vn>YbZiSo zb=YI9%hQcI>?b;*gL~;l9d;MEm(*cr(Xlre)nUg02pYIkDCPysm#|Peg<`JYU9dXL z6?KzzqYkvW?I zy1lN^3T0cl4t8G?L&8S&ac$4uhPR-j={;T49CIRyxF3J~TLAj~8{cs`@^ zEQ0yN>CetM(s@3?&IAzV6d=qgK$uB%o<*E^*oEa2M=ly>7o@=KqO;A8*@brub<7_K z#q7d!vW}SqNbWs!q+w4LG}!k#j~t}nm5q-52*+yq2YDmSb%XE!-hcdI??3M5Ewnt` zA1vSg$@4sFzn4(rox*48y{WiUmhZK_(X)+&SnVkVUJiUM-#!cc4d7pS`Q3{fyeTBa z4 zjC%M_)WZ~TmT$K8(*DD~3t65zzlGl`5_sdv^EH;!gLhm!-vl@Lw%I2TN8SNk0D7s} zgM=sq=TgYb-@_K-r-+F+nM8>>f`muDHT8LZi^B5-+@IR@eZe^7PvHHV1o%fG|1!uQ zMcXYyOUZi{BcS{fDF1=h45KxdGKDUpHRVm!2}mgKuD$^+m_Q50QU9*{eLK7_DBrnB zL;c6mg6`XhQy^ha4pp};$~&iXke7VBQQjqdFUl1MpL&q>oZrFVb zG2J&kcYS+uEK-d{J9 znLh!apCfb)mqoqlg}yMew4RbHz*-j+?zqjV9J&i$U~?I^o^w^H6ryi$CfZ|Y?}+B%j&!#JXEqAlc& z#ZMs)-uR>|98-kQpC1=zth<@DN0IiQ`R-w{9r5Ko+-Ua>@1(8(=M`wvBdE_K%+rJW z)IGO?|2V`M2Wjs_UUwn>CqciB^YY+bD^EUh9EV;fThM(!dOi5pgXgD^b|U)KL~yQlbq7UZ@ zJZR3|sKdulhc}`IVko10)1~X1#63*D?X`#CQuNSXAR&5!TTirdPjKi74%e_g6#XHC zys0__EN`R#AUXQZhhIe`E(Z08% z9d8An(P%q-Q9;~>w!01WGaT)88|JUu&=&G-LU}8^yx-mZHnx0+N#20I1)LjM1}zgZ zY(ehNfsVIq#g8Gg`+e&hAoJshFW+zOi~8wlE!-}&1#bb$x2tjY zw*AEbek;+skDqZ5#JmVBZ-VcMcgU{A8)?^ic$T~tQpG*z7<(4M=bOc^_4Fqp(mfgp z@sP%L&cAqG0p&}eEaltZ`F?SAllQfr2Z32fUFZ2czdMM$BA!ox-ji?dh9uYEO}J}4 z6Zwv0uZM)X1w5ca`OUw9T9Smo+s5h+?Cs$8J*1UyqzysM)OwEb?ZPNUK2zvl=}8jy zE$=)w<@W(@MSR>buii53gOcWBto1>8uQyNQ`vY8iH{z~$yrD~fKwA0Dfk6oEdV_cj zqox=!zYo70<8CQrTM9})NQ-wpwWCbehJr5NVI8be@z^Xxs{fRs?0ZmZPc?FX4SBr= zdJUIC^Madvzt(+!zkCx>zJr)Rc`H!f1j-vm`z}TM?nV2C(Y{O3z8BHH^6vixT2{W@ zcq7_0fi{)zHOiaLakG1eF9YO3TKU!;?tmxUMlY^Gx%#qC|IU)rzk@OvJ^V{Zm4!0O zcPMc~y!$?QYUi@J-%(cg;>)iGJdLz|@a%y)mv=vJLyqsDZsohG1T5d*4PaaZP)h;S zPXMKkB9(kg^4Gxl8VUUj{H-@2xh!}eoqh-Tv*Gsw|LbwzynKsVeqqD?-GCcBE!^u+ z|EoMxc^!dN+3FGOME_x0%b0cctCdl6t^h@RdzC#`O zUA_rGD?DdO*f(czz2W;LVm7`Wuo;v;gR{IzeLLu9K`BM(i#)REHOPihAjXR$BPk^2WU*5t#9jX2k{pWtfc^VY?#@MXmLvZAxjl<&lsA{E}k*M7!vv||Xp32*&& z{d$IcUs=9+-xs~NFLLQCwHZeDDva)f=v~)ibg#nbzKYR}Zz+hIpuPJduRLgP`95?p z_a7|@Ir~6{b-;bmqi%#Yz6o<^U-)0<^3uOcA2H?K41GQS3XM98g!mQeq#2>^uYVMx z?EN5v``vf>wFLQ%5qu3s?BcZad-$zLg|C;;n-~i}<#N$-$RNLSg6{&+*N~$?fA}^0 zH@Ot_bzu2+GNG+;3k#Xxk1rv}uU@EcgS^E#(iPORU|mXAF#4{rZ=rpVc|F>q08;Hk%vPQes1>2|UW5!;1E8$ame}7O z`7+}F&U};vy@cGCpwwSuZt6QB^8N$7Bd%%8LDLW?2Q`UrC23OkmNH$F-|k4Fcjcng zxhU^t^q*XHYXa|eBq4bcdEE?dH>3aH%ON5g{U?c@lY^d<3mYI8eFN`Ft8cl;ub`x& zjPec}>z!|&m*;}>7tzDNh}<6mWf7M}EJ7UjeF^whjQXC8Kuis3Z%)-Y>_UBH~+!BfmHyzjT2wX3)PO{xZb;nYe`nod=fRa0sI;`1*(X z7DO|0Z$=#XHHoe_2YB!u53lET+>~%5+j3Y9`EU<`*Yk0{>%wyr3GsloorL&~m+eFH zYy{=IBXZU2Dfp>J^es_)%B&b8sbS%IDc=QZFXzw{z+p(uu& z*(lLGjD=R<<-pH?v-(yH+IPNKO+uT>e6$&exe7659m?;hxNfr$_nx?Xw$B@UsRxVD!``#HC%#`^)yD-uQ0MoFtVQJktMFh7^%RQ zQYtXADm^Pmh#Jpy5}N!XN-aj#K;-y5?cKEtZI%4)fd9TGt?19#F-}CVY z@c9Gg#5V5d)CN9(Kv_~1=GhRpm(e9q{*0KopF`k&CUG;b4lE26BCBcOuozsMSJQI@DwV%3HwoMrdpL3u4M|&ddXchrs_K z@c$Ah3t3vR5Ha0f+DS!d8sg*T65&IsGeEx%Et`VT@n1}*{{jcuS5q)jaDxlI#qsG1 zYVr!k-Fd_}IKI4(B+wXWBS9IomUtJEcR)`N5r3PH|DPqI^F(L?{)P|#=GM5v4MN2C z$Y9lTl!({vB0_{c{qsb;yTbcrpcNDGa|JwGU>ocd5%1-2TBOs7`0J5;cburE-gKCb z(g`|6XX!k((M7rK@#Q=GfBd{!%QV%-bv4pFbmBz66R;P_nUY+Vis~=HzV{c3G*iNMiS;KZY}ec zt3M`T4m10ZFdx3UfrRNZZy{lh=H74K4W1LO?j&J8gwW4i{SOl6rmH_BVQzpQLfSi! zV?VQ$g!%NX5i zzw?N+g+$sC#cw&0whH-Fi$<|c>=G}Eed2&PERKp3;*>Zm&Wkp2QC!hTOVKj4fELkm z#5S#umai3S-^R-3VQf-Cyxc0cVR$HsB*Vb#Bv`yL; zZHu;D+pg`_c58dIJ=#m!OWHy0ApP&N*bnh6*1U(UZL^2xdJ<+9?^>Eecr{`U;kATW z$X2+Crvl~>*4<_y@4cD@ye2Vk;$2{K74O5EpW&TZ^FiLvHSrx!^E15HZ1(3pT(gi@ z1!gI)YRsE>U16?bo8J61a-YYm0&|ro!6TYiFXr`-v;Eq|MR!)_`XQKD{+_l&GQ~Lxx_uUT)`UtALF~x5Ai)~8QL|yTv{?l#QXGoLV$N~@xO#fR1)!%YJN)2 zPfz(9sQlbSOeEs(=XKGpoTfYN%DmkgmNjm7TDCh4>(;K8mVGY`%bM1uWm#ienpW(m zEHPe85|hMKF+eOzx+}=Pa1j1D{dk3_VfNg=)Myv zGsMqGkVw0WG@43Y;wNg^R7Vl|7~M@n=u>nrjiqTcjXq5e(L*$emeX?j46UNoG?~`W zI=YY6)6+DQcF}**Z2B3!N-OC#;iIQTsu)E3#b9v@{aM^8rVA4Hi`gO~7KjBRM>L3a zB3B#`2Sji2EAfiBLHt(yR^)4$T38flF)b;IwcgrIqC&e_%NIkm&uO0%L$$fuTv4li zU;DnO)0(xP3tjt#)*|XXPk5dXBfUl5BJpwW0B^Y%<*oEqim~1*Z?*WOx6Z4J@!nzH zVPb-}-dis|yJ+z4@V+3{d0+JI5gWYcz30U<-izLgVw3lZ_lkJd=ka;OW?zOcLwv^<@C8Jp zFXD@e=X}M!0ph#9QeT;P-dFA`7vJ*@_0@{)zFU2_iXFb&eYcC9zF+xHiCweP+r{ z;z-J^DR+rKr+gu0j+T=0NXjExTFR1?C7M6wYblRv=_#vHR%zFy97;K@^-OsyHBGxQ z^|jR3w1H`3(>|${r+qDLg;triE^VDwo%T%HGujaUJpVkc#(&6vNE_-u;yfwEuah`flJx%fq z_Y9}ccxHJP&}7d-&mwxj^SEa<&GxMEY^4W1+dTVdh393@Df+hOwC6PK^qld=X_xQg zzA@D18|xcS7k!`hO`^AalYNuvZQm5%6ne)u)i;g)>YL%4A;>q|_XQz*5BeSw9^XRW zLXqZM>{}-MzU97^qL*)#?+KCRd(yXF#C@B6o5l6Mt-c+iw{Mqkx47B&1K$rsq3?&j zy`rD*pzomQ?>po>B8q)SeLoiieZTPiLR6$)pW0Vcrsk#QiJH{>)Iu>dwJ5c}&{GGb z4iv*uD^e@OZK*?2YsH9EJ@sQ^RO&6Mw}{cH!&5&l?o7QSb+ouEbxi6f#oehBQYVN{ zr+zwhl9-e_Id!p^oVq3T$KosLrRk;ODH0S(`&im7Y4vGi(ms)PSK1fS=A=ECHaG2y zY4g$^N_#l%OKFd!eI@OyY5$b=leAx_olR@?|CBWPtfUbBlZJ~wh(G-w_Rc%Lsw!Ro&uV+EwNF1u4&j8510;u#KyUL8rU^m$; zH^A<4Lpcja%N^zJI9u*1_ryhVuG||J%YEcN_?_HOF2JR7k=!3w$OGje_`N(-9))Y< zG4fd4B#)CPVwpTyo{YQXsq%E(Ew7c=;=YKmalgD--i!z2GWiG|lz)_ku`bKTjWe%(<6xwE4smMh#TsLx#4bv8|g;5(Js21uh%2=NIgn#qW9H@>I?P7 zWHYM4eULs{AES@gOY}+lW_^p<*t`#c&`oxouFGxf zc5pknUEHp2H@7zgQu-eKh<;qZs9!e1NE4cbsW4ThhnZwHFi~nW(rjU7ncd9pW)Cyh z%rl3W!_494m*zxshWWKQ)0}J0Hy4=Snaj)-<|cEqxy3wTo;1(eF}BrCwD;Nj?F05f z`;h&keb_!?AGLq7kJ-oV6ZT2_lzrMhWB+WQwa?k-?F)8!G?VNXRf2Rsvxz%pv4g9Tk1lzHL_nc8&cI76Q_5>bH%)wm--p4)`Pe z`LO;%e+i2IQhybi{MG(84E1;V`!U|XABNZf5?T+^-vS0^3Z5}j&1Isexxzdr7Dl9D zo)69ef~9sj9*ll3q=ZBq8ruNa79U^+KE$W^8$K5b9||K5#y4WI_)aX4LM{-W$wl%I zxu-l-E|>es6-vm*l~Pa157jfeM%@j8zWyM8m_O1V<&XBq`Q!Z={@4C2e~w@3&-WMl zi~VK(_x>t>wZG2a;BWLd`CI%lf2+UE-|6r1_xX?gC;sy=`iZRld7{tq&wh>v{Ga@j zetGn{ATZ7!><{sa{h|JFe~kZyKi2=!|H_}>m-rL?N&Xansz1%2?$7kU@n`$r`g8qx z{vv;gztmshuk_dWYyHjsE`P7T-@ory`w#pY|DpfL|J{G;Kl5MsFa1~kYyXY^)_)fw z6rl`F7=$)-VRVMr_Md*`@4s&MuetVDe8fNMpYTulm;B3qg@4tr{Lj9F?q8k1IVbze zA)x%P%I}FVgoFuw=z%a6W+B4ruo^zhhXsUTzp#i5B<@8&G(e+>W(W+#Ku8S2NGOcL zD0qy<80653iSU?&$;e{^Yy*vLu`Lpqh3%lRJ$8V=j@S_i?1Wul$f{YgYBgEa;v}4k z0H@(JSQ4wnQY?kVxi}w=-0JZpUV_KVco`b6;8lcJiIqs>HM|Cozv4Z_@IF339BZ%! zJ^7m($7hIkNk7Nu@c2R~q=Xh4J%kYkNnwRWN;pwKM)VPV;6-0ikBn##MPx;z7=#MZ zB3clN!D28f#Sk$DRiah2Mo+pIZKx9MVlr}K1F->YM9`>?2pS}4_=up9j|dvo5kaFm zB4||03R!`?tdu=a9dR_OBaTLO#L=jZI2zRvN26!N(Ws6%8u^H$k&ieUKH_KudYB#t zsfX*~5PF0jg;d1U(0Z&M3$4fLaj4X7x(y=YYXlKr!$o`zuQ$>gA=De|jiK}=dK0Ad zrn&=JJylPI*PH3hP#MuTl6ot>HIjN8y$#}erk)9Rt7&Ppld+T|~Mx2h6UZ591=!NFW^a>-F`}`UZUiyk4f4A*pZGw<6TH z>Dy2pxdBv1ZUEJh8$fmB22dTj0aQnB0M(HjKy~B>P#w7eR7Y+A)sY)Ob>s$+irfIS zS#Fj?m>129NST+-%h2W(^9pj2KY%wY%}NAjm01O6UN^5pn>WlG@a8S^7DDs3c^e7y zj(GB8MzbmjNAz-BX@#oNI99#cNlu17c^?o7sIGc`K<&r@Gs!zyU1$w;b6k!muMI-;o~ zj@sd<9iG~usU4o$5flAIe+;97#Hk&ls2xdaM~d2!q;|{_Q^XW>iVej^D2R>4#^@BA ziVk#&sbVS$Vl&Z+PP%|W)R&FK9%2s^=mtDOQO!m?}OLAEH@&B>s-6;$!g{YQ-1gE7VFM1;$A&HF{IyI%T!& zi6}AXg-%&3Yq6*7Et}9Oo8?p#WT)H`1vx{`K&RYVZjDa4jobzWxt-h*1-X;l8J%($ zxeEr#*>ZPu(s6XsadgsgbkcEbPQ@(JcWf>XkO!bZ_p!M=R33)S<>B&h6yy=|L=2$& z=%o7?Ab%sTK{Gu_L0%_sKr@}lAS!P&{m3A>Ox}eSdAGb9ozV#Z#>so-BN!|nm5*Ww zeac|@gj|jpbSu^JFY+(wk}Kq^=#VSrN^B`#ldqvezAj(KboqvS8y)o4qm@(=T}mm3 z(aNhBHdb+!L5Iq!Ji1hk>W2>1pvIy@jZ@>$rN*oE(4i)%3FuOj)ns(24b?{IP#dc* zbg5}-8oJaLYEN{iz0}^=OwCh^(V-4ihhdC5Tpf<->Iii*I_T89I7_sOuEyw6H>g|D zrEXJqqC?%K?naloM?H)V^@w^3)6~=IX>_P()HCQ(e^#%cRsBV+K!;kXR-#qCroP5> z^^N)#TdMEWcNndq4aVv~2k6jNTeNAX(`eUOU4eF8scWzmXPDH3^S)YPo zoO7CUZWQNSN}sKN3$2&xr5Mg>7wQZ21rVHbqx6;fN+^Amz6zQX&gpCPwNRXD>v5`S zeY3t9it}tEeY?IL1$~FU8=d+deGe-2z50F>^aJ_ zKFTPtk(p|yVzk-JOhbp+!fb)v%ycsY9cCM|Jvz(|W(VxSd~S@{$?Sv>Q-y38Ci2d$AK$2_x#*#o;r=^fh4T(d7a%zkD+w3_*5K03?-vjBUTg=Qf-%p$W0 z)6D*6e{`7x%|Yle2b+VjnK{H9g4QVQLx(xc9EMhNxH%kqnIp}S=rBi_qcGYWZH`8V zImR4=HuDSf3v`%YnqOjXbDTL2UFKKjcx-7-FejkPEHNjd!<=MJLYq0ooQ4i_x;Y)K z<_vQtI?Qj(S?Drno3qhs&N075yIE?MqAf}g&|xk%m!QM^&ioF0m`lxN=rC89D=@}f zX?~B<<|=a)Ha34S*PzQ>XRbqsx!&A>E_0K)1@p|U=5}Z|P zfO!C2=0WoyTFoEL!`Q<-Vje+<`IGq*y3AwdF^n~jo5#^%o-j{f5A&pX1|3maiQUYz z=2`4vo-@y(!#r=E$A;zw^8$vMm&{8TMw*;On$+es^BRVcCP$Da6QoH^j)LVa3Tu9Nx{kJjB++K1*Zn5qBA%>I30!H*TI=61iuM>gU%>oM9k*amdiqAg-8+u!y_N0dXO%MP$j=&;SU8Kdn$I}l^+AUg;hcCa0cE<3~yMTZ?> zN1)Y?v?I}ON7+%B8)emKvt#TS>}^|ZEB3NuZ5ujlyIl|Mc7mONE<4dq#9nrNyFNzS zNp=Ht*bVK5=&&2xjnQQ{wH@fPQ|(lA*iPGt(YDKWp(Dx?q3tv~4PAB%yCvGAToHvR z^G285)^3Z)WJ;vA_?SU9=53-k`!(MK$L6^POUWX2Qy}cLh_CC8D zdodl`-o9*KM!~MIE3kom)xL^8cBNg3_3dl+HB7Xt>?-uMuiMwrXy34Jpuc_7zKN~v zTlOu~*|+W6m}B3u?_d}Eu6-A~+P~SqVYYqGzK5Oc`}Te8Xg{efd; zH_1&x+D&$ok#QTi4baO?aZ`|W8@r7$$!+2`!DQFrI>3YyGu`HHb4+&A+%z=My%gOH zHv^O0R&Fb7;kI?#VxZg6?TAg>&TeOH>Snvy*u>3obFit~-R+KgH_y#Oz1z!1`?BI@aN1?_Y?T*F{?ihCrYTPf}FR+6< z)*Xw<^iD;0f;$0|-HGl*Omb(rvrwR$8c8=b(%tXwM=!VBEk~z&(Y=UXZk1bwUhX~j z9(wr={e~DC<$dTu-&OPn_yaK6Kj?sk_u&@Z{YXc~_8kJ$X0DGpq!8H%Z=2lXo*D z-7HBrB*%~obB1ZHcqH3Uz@0#01V zS?kSgGaDgit>Uara=unXr(;N%1!f@5VoJ~ha?qKQ!%TkmEJblCInPTXIpFwG*!~up>`-jJIoG8oLZTr zR#s9aE2xQ;)I@J5*-6mRxgLz&$ZiBrHB@#JyD7ZwupLm;L_;+UsDqw5SV;v`RJ{~c z&)I|Q5zy2-PrVDNca`j%3P_JH-nERGf#K;Y&>44L8x@mgczI3;J>2B-kX#3OA4xpp$ zPZyhEKlhWXIl76(n z&dkt*X6QjPbe|da;ZSy9h8l8Td|)?}zPwdDFba=oMOw3xlj zUeM(FS`vLo^%+X_$xwX;lHzO4q2^EwBE{E|+?&blE!3bUGJ6jyQHDy?k4lswt+$wy z&B$)RboXPWGpCUvGsooO;=nsk{aT{e>|o2iT$ z@?$fVaU_+oNM+1W6Kkl6wbaB$@?(z5*g}5nL49nbK4wUZ&D6vU2{A)9Y^DxosDq8< z!8Fw{LlR6=4M&mzo2iBw>R=;TFHOqJlI-FnyIv%_JUOm{>^9u4v1>4lq$WselBAX- zomG*}s>o$kc0`yRsVdlIwn zAMH;08{S)oU3h|t8GlZ2Qc-X#MIj}^=@VA z?U{N{V(RUgdN(okZer?PS<2(fKxrgsh%wpb(9@fGBvJYYTS#dv0!Rk z!#Ur^)HuhyxEJ%{LClL=m>0J&FV@V9tC<(KFfYzADb`Gidod$!VLCjJ>9A%lteFc7 z=E6B9!itG-3lm|(M7V{CaE@89W)|GSELbxO?!hcL#}qin6u1}j-$BfO1@qq)=D#^6 zzb(vstC{xZnD+K!+S|gkS2OMH#hkZ=Id3oKyhBJjZOnOF$vchYoi^sYMJBwhOm$mH zJ#9>NTgg6cq@HF{PaE^xBH5=u^W0V@xvk7_TbbcbAP2QEy`9AL)-%0rVtU)k+_sgu zZ7XxzB6HhT=C+f_O>HEmHYT>MOl*tHYFnAowvwLOn9LT*P5qh77MaYpGLvm3L-l7G zJA@?F#x%Cb9Ci|Us*NPoOp@x)1h$n4Y>`ye#_Y9~RMkeFYGdBoN}g(C#@fnswUs>8 z$XvCRxoRtORn0_IGEp5u!U{-Oj%?MFRMk$ZYA-vuC@oEqs)mxPvZN|Ys!EcodXlHw znTn1kPbEoGN#>#B$x{J&Doc`zlcd^7QfZP@J4q@_hDws5+JEHZvScVrhU!U%vZSYg z+|*8DY9}kD$V!&1lqD^DVS8YFsbapq_PK-$`&S-f=Oi$CY3Er zDqEOT4q{T-!lY6#scd0V*@GO{Ms{msF4@XlvW2WV$iTC0m(DZa}hYV4-1&9f`E_I(MVisv`PJeBu?Ctn6Od*!_kSh#e~pw< zAt23IZUG0}0uHzZ9C8cT$qnUnIJu?V5<uQftdk+@WaNwTMQHhwdcG}siBfuy5j^j)J2=oaCFC>>glMM zF4~NSqdWG&X~Ai5!5P7?;i!)x_0a_v1Q);smjsuqs+etqad4E;wR`j1BXk3MuBhR(y#c^G!A zq4UVmc^Ep6x^kCBn>L1?!_aLsvOlZnGpg8`jqJ=S`ivZXMvgus$7bT$(2H~+$pvw8K?}KH zFwX&pFjvYjR}##XG|&DjIsbcd{`ZWoPC#E$Ku=~ed1g#CJo~F87c`R#dh_fr%d@`< zp8aKc_E*6Ks+tK@H8UK|3`aA=(M+I9Nlra;D8)Rdo@ta~s#DKQN-^81Cw-LmCTqwb zJ$d$5NfI$kel(LG&E!Wj`O(a$`cdOT=2JDKm7Yw5G*9{}nNrp8q_2kLVn{BAXc&YB)GYmW9pP+ z>J(?{lw<0YW9n4JyeY@LDaX7iM{V{@opMZ_BvU8J)G5c*DbCa>#neeNbuvty0;Wy@ zQ>QG|y^iW$M|H2Ky7!>E*HPVjP}h4fSISY{>!|K^RQEcndmVMXj=G*FgY}}i*OS3| zQRC~V@pWXdUgex9+I*~|X4g@(>!{gv)a-g{c7dAhso4c;b{#dlK+P^tv+JnYeW}@f zsn&JW>3S-3Jt?T6Th`ORe6kZ=Q&rj|&oNI)Gf&AdPf0OPNmH}yn5P)#DH$dyIVLGN zCMl9hiei$IW0GQ+q(~+y873(?CMi`+QY4cU$s{GkB*id8$uUETle==vPz*B^$qXgO z3`H_S37DZ6W+;XkN`~o4is?y?>4{-_l4E+Jn4TD>CmE(EIi@F)=}Cs^Nsj4BhSRAB zr&ArLQw66}T{$<2t}UzMEUN2vHdI$mNurIm0%uNLIq8VD(&{)*>Pc>OrF4Tcq>j_0 zzMN}ByJkgBi5{F1b>;jb+90bdp8-YtVx_dAj&q=n6QGW&Uq{t%Aa_+TkC4nG1ogfL zlZZwp5d)Yk44~T|Ko38FzI_0_`T%M45l6uo+uUOh*zo}x?7(WOhe z^nm`{(3z*`%yV?+0iAh3XP%=oPtlnNbmloa^Bg^Sj-EV4PoASE4>+&tIIrqCsp{y- zbDU1~oJ)0_OLd$@b(}wSoIG`$Idz;lb!5dHCr=$GPaS7Y9cNA*r%fH_OdVM<$7xf? zX;a5JQ^z^usDlaWU=4M!4|Oo)oasq5>`kB9#0g_LVQM*HsySgQIbkX}TPitKJf})E zr%H@dr5`6oEhk1TCq^wNKqb#6JSRXUCqOkPK%HCamZF(+pq6u>mUEz%bD-8w^;41L z1n`^ym7D;zoB-9F0G<=T)5jXlfjZ8CI?jPQNMxxIT2Igupmmq-g4WaYH0ZT@JKB{M zdOy7%Bs*E_gY-d=`e=PLq&`L;1I518dWl{F%>*>sQ@sVUoTWv3XaW)^cRQ^p{^+!# z$hlGE+~~)-QRLhxa&82i8%55IBIibtbEB4XqsY0@hgSlXt^w-9=~3kL=-2JcqMmc3 zfpepQbEBG5!g4-X&Iil+P$cE2Na`t)dWwu*Llv(j4fkLYUZmox@=r6`doCr|iYlwA zvPG(Fkt*AVD%+PTTcp1Bp}uPBYmxdI@ZX>h_m~Y;wof^)j;_KfQeXQ~UyD@MK2+8s zm9-C*wW0j4673?Fvgjgpv`8K8O9j|JI4;55%+t^S?i_}p~9ko=@IB7dYZL`#; zIRB0NbjwREl_vO6Dp*aWDV9^g=xUfEm8K7srlDKXL-Feww}aaO!tLaCf^@sMT_D`9ZdXXRo7)ZA?d|rC zNKRCc;Yz24(Y+{kg=GH)>_5r=lf0sD2)nR_SJn(+FG}{JWG_ngVl{hFu61%4U5Ph@ zy(oD#%@B5EK$5fUMaN!rq_-^TElYZv-lEboOuPoWCj_g%O_Uc1lTu;lhVpE!f@f<(dA3%;v$YDItyS=Bt%7H36+Bx@aeJmWPuMD`E0QN{ z6+B_9;0ap=PuMDW!dAl*wi<5F^yWERf#+;PdCu0CCu|KoVQZj14WK@ilxYB2FiU+B z)F(-OlHJbJ4E0HNJ4qANCrN#3S?eS%nh~YbGf8C%s7$ikxtZ*CZsw>=B~6mlBuPyw zQJtVB$!=$2f@&nGMuI$-r5ZJn=dvWZEJ-d)lB;K)kY$n(Bg18x8w{d)4J65BNpf{0 zxhxqjONOhX_m9!<$4GBka$A;;eh}%co{m07FP|m7Wl3*Y(p#4F)`#lYRGxs*PX17G zTQj+BI8Tr&c!E^H6QmlRAl32&DZ#U&IM0r1NO;3}c2vQ$qZH4MYIt^3!&9T7-8OG3 zcwSWCc~J#VifVXLRKb&?8gAP(@Qf%*8Bv^MIh?0M z6+9iPA!QEd=}-kvhx(E@hm$y)Nu0wu2U@85l6o(@o&UJ<`A@_KiexFN`i`pasQQvj z>8SUTdM~N>k~Ar)^o}%{B~8|mCbP^v8aV+ZnX--(pdZOHOR~(8EVE2GhLJC`z*Ma%Yy@nT_s8pdZnXKrs^(`bGUBlzv&i3>DoW0?LFYgfa<} zfMoinOqHpEV)~|-e<|+1DM&2j+~~f0nIX>!PLDLHPLS#ZXUI=&V@B6dI?j;NPG*KP zq`Z^K8R9rY9G!lGljP_2Gc%kaKixe`oL zlT1XEj?z9}hFzX!XJ^>c-|yf>SBk8?eHUH-@l$(u(KR2A zef(3~chTu)n*Ee!-;_4oqC1>Sh9qTqQdXQ)r$}|0RHsOFnp77f)x}EtX6%E1+!O1` ziJ;9aGYgvfZ_HdX7uw7-^Ps8oiaM{jBOs{r(wt~cgo^Ht0&UJTXF{2C&AHI#d~-gO zxxidd-l5dyGILpZhf-6|O?2-RDC)DO{z#q%3!VTAp4LWAZ60~fl8P)TCrzdiWSTUY zMv!UJWSTUYCQYVElWEf22-c*TG&v?sj!Bba(%c1hq?t5nCM3;-Bp5-0NpNZk{)|$b znu##j#D$upJT|MW5{_~+LkZvRHQj0L(a%FXJp8^ zsJMBmITr=zVw!U?&7Wh86H##@ra2KqPDI6tnC3)Ga3U&B#1wzxiW5R`LI_TXG$(}M zUT107J-HM@4 zF-*V%>bRv(>HZs?;cs-7ztI`~MrZjOUBTbz3MLs674wWL<{4G=I62M_OOIoiXH?PSSk4m5duU3;=^7+mLn*Hm^t&a7 z6m*j%mXKtL5=E3~p>%?v`Ll_p$ASNp|B3D+u(sQY?mn`%&x!6eB7fG~MECs4l$}g; zWqyXPBSUx5eKJ(gT~yIsRMA&t=_^9|iZp#foIW94b_mgx+sX2-U3ATM=^B>OeqE0A zU&@0^-2cz9eso6=`TxZC(H%b4Cj02B=I@z4x<7{`saJ7cd9rw>Jb9w)bxV8np0r)X zN#aS>r8HEpwR071uZQJ5tLTc;_*%PF(RHK=GV%9&Q_1ejJy=1=Z?{H$4Ez|lM6vQit)^%bZ-E~ zQwdF1s`xvqn2xD#+nlBA_%+>U>5eq2+gXF=S%WU;V$oe_G|v=D*W8z`tuJkf#ON<$ zWUvg0D@KEt;>zKW5oVkD~!nJPw_%8;Wnq$WpdijkT!6Vx+7XJyVRHDMreQ(KE&9mSS{EG4fT6J}E|@6r)dyk*{Lp zs~GtzM(0tQSe~;g&RG@btcr71B{-#0W(w*G|J0_x?M@zKBeXck=Ai=HmIJeg0?1lul*5hR*kM7t~+V+ZbUnIqzNU$do z?1=<>BEg7J8g}Au0AsC3_{tZSy#HK~mf{k8|5R&K^pzhZ5X2 zk8|5R&VEX;pAy{FikIh0ba$0FceUc&)rxahE6&r%WSQ=wyE-P>g$bTUCV3i}WJe~r znHA^mNQ&K=;Ockw-W5FO71Yn zxx*Z1pC!1%9A~#B%9A2;ISKY$CAXL3++L1zdpXYYx+Hrs!R?R~cdz2ySdMdJIZh8$ z$&KYWcSKU`*FY|z-T}xEj`B48C){U<8E@k9ty0;uzw+C4_N7n5@*3FZ3 z^FOoaQBBsZChJy{b*q1Zb)##!74<1m-sgy}-;V#xR)_l${g(DQRCflZwk4=-32Iv+ z+UMYFmefp1&6Ff^!S7P=yA=E`1;0y4<&@M+2`NHSuqxjNFggWL-A(}%PXQE90W!@0 zGbCcg{9iHuFI@*)M=n-B%KuAu;#1x3#P@Ugf1X;KFK=%|Dw`)YE9z^W`kJS{=BclF z>T9068u9X$Mzn*Mr^@E3mwD=Co*J2_M&`>q8PWat>Zp8qs$HH6m;ceeMd_-VMpAhr zH!b4y#5E-J1`>LXgx-%XIZKyZLzkSTORk|yE?qraLzi4bms~@Z??;zhL!wvo$~E-L zHT23gbjdX&{Q^n9K+^BW%)fz-IZMafpPByvQvU#E{(_mm=?N6me$_4QmvjcI zTiP$_4;0gW$%&C?+F#n!&2v8FIT`ZYA?(BX(8&3ar=O_e_Fx}QgFH1p-)(Or&)vU1 zRP;P||N2nZ>*+kIm~d55%k$LlJoUSgE~JXeou_8!xw+Se%AKcX=jl<3Os{-7`H$|; z(}zh$mPtm)BqPQQqlOtq4c$zE8Ae~`|2^nwa`ZF><{70s0o2gh6qsZbm}Hc$6zRc&bWVzyzxq+;pQ3+CGxJwJ%KTNg%wI9{SIqnsGk?`B z^UrtNAj#89scsu2dCs&vHyitKrse6blALLIPP07s82fOJS0`n&<0ka?#4HJp=q<~>>FJvH=y14y$;&d)qgwi8V6dvS9mx?lMuR514_ zZK%|7LiFT>=*bDulM|w}kyyv6mFGmN(22;oRljr=&bN=Lc7v(s!ndpDf{e}e} z8xlS7B>Jz`Zd)I+>`J3M&VGO19No|H`;+FMNm|P3N^}QCLC>n0{^(MoQc6O~dl%82 zP`^LRjP83{(y!8nTImj^vV1lf-Px_QgZ8}_?4DYb@(LyuYx%8GCJ^0^NtDmDqWgDh zv)Zg)>k6h)0;SC-<`XF9P`Y%c)y;K9w;0j?aIzKMYpHYvQz^01!Pdc^Q01&3x_gl< zB><2p(6AW|$-fbZ3r?p_%#xBn{2qqkz1j`P&rmw<& zyW(qC5Pn;BibTME6(n8B?^*F0r-0wN;didtQ=ytwaXs|pDIL?1-{qkBb1`kV`Md6g z=37oUqjREoZ0h#24P z?+K((i)OT9Lu`p%upfSf-{5z+0r%ob`~`o*7s84v(N7E&>vj8k5^40tK#avkn1R`t zkK=I`F2#+w4^LqQ-oux|iJYhx!^8wkKsa&ArUfjVICFynuADS+dI2jZO`Bd2xlJd| zEQpS&ogD>nR9DBQ1+i>e=hT8&J$>Tzf~=oDZPS9BS$>TQ8Ps7A#$jV@g>MO@@XqZk!Eorqt{q6+;m6zgFsw#6Pe z07v3voQvP%R{Rmq;jj1*--(2%5d*~N=(#fdTMjwYV;Cl2Gt9!CI1oqS6r6{va2p=R z^LQN}35cZVC7Q$-F{S*sJbIu3!!Z$^*baN)ARLWTaX$Wl+wllqz#I6x5F#aNMYCuX z8P;P z96Mld9D-lqbXiH*yDD~>!GF$$A04Lf2U7UNi)fs1f0 z?!seu32)<5p+!~{M2l#Pp6f?1>nW^f zvMy!4i1l*Tt66Vky^ZxA)`wUhV||8o`RsZ7?Cn>uzRvnC>l)TiS-*~IC|MnAlC_dG z&stzDvJRXxf2Uo-VXSSeQ&_uLXR^*_oyU40>rt#rSkGj=fb~k&8|Ut^+fLzKtPik0 z%K8-R^Q^D1u3~+gbv5h9tY1bo2G)QzK6l=ty<=I{YS!MY^{h>-Ls&<#wz00yx)JMU ztkYR%vhFx{pIzq0=CICXozHq8>tU?NupZBP3hSAyOZVPw{$8<*STAS2n)OE3+gR^m zeTelj)@N9kv#wx$o%LPTHS-qjJwNs->(^0@OIF94WUXY)vldv3tOHqxv5sLK&pLUZ zd5iXrZ^GKeI)il<>&~pZv(95($a*mA5v<3uE@3^5^{jp7&z=`QkM&a4t66Vmy^HlB z)+bn>XI;ViChKa}Pg%c>Y9iQo-lDw|N!Ci%JZpiq$U2a980#3;@vM_sH(~8!oxwV5 z!A^4*CU$1sopm1TLe_&>k6=BPbqVWftY@*F$9f6tm8{n;*n5|K6F0No!FnI-!>muR zKFj(N>q^!)S>I#*i1l;UZ=;&j3l73sM1VoHff@&Dxu_p0$Z}2#hM>+!6ou%5}fl=ULk%NNdDw0G)i)*D%GW4(v< zA=bxOpJ83jx`Op})^}Oguzt$=^})N&-zP0u9cz-ck~Pm-U@fu^WF5vjhIKsaWY$es zyXZMfkFDf0>;DJ-TOiM`xGt+kJsMC%f8gKx{pik9(NBBb)>?kfbz9T?oa?ei?jwr| z;NRdqf!=(5>$c|jIoEBC@pC#>&l<7@tdV~eu&hxM5S`9OmCs~HobRvOn&RhNx3wof z=en#Cm8hbY{m;A=Oc2&}E%4{EZfo@HRI!e0AAZhtTl?~JuG`v=pL5;T1V87xtx0~) zbz7_XIoEBidi`TP4qNxK=^k{Z|1~{5Cw*YL^#959Y3WN!f4U($ zxd22%HAHa+JVdbz9*M;mey-l_;r4V7yGPuk(X09H2EL{Zqx8GsS%`+0 zqMtW_0sP1_5DgEn^^r><8lorB|Hq#>1ES%cA3h=)qTkNwiHO>FLCI#fIb_4-7;0D8 zSM5qZ0rjunKLgcux&z%=?re9C`>k8*&U06|E8XwiJ?=htzkA3%?w)c_yFa^U-E;1F z_kw%Tz2g4jK69VDFWi^zYxk}D&cmFlRer~_8U)rzi*Y+Fxt^LkLk42MCIqi(w+Rb!}-J$L(_Xl^iyT)DXu5&lLTih~t ztGmtJ?(T4Ry1U%n?s|8FyV2d`g_mA=?Trt-_0D@A`k0UVgirb&zS{Tnd0*pu`C8xG z*ZG3)UDR%y;pZ`z3k}fyX9qbPMiJ$*Zy`IberJwV^^2#RqN#FllbbBT9N@-kNRmD*a(Q8U%HYL?ngZLfAvJF1=3&T1DmTkWcLQ@hL8 z)gEe3wU?T!_Ez)MK5AbzUoB9FsD)~g+Fu=@4paxJgViBwade%DI$Ry0PEtpzW7IFy zvFexVIQ1)ayjr48QYWiZ)G~FdIz#Q}JE>~BmE7kASRq7AwYITjeR$ZsAS2w5|)lKSVb&I-H-KK6=cc?p~?HqNF zx>wz&?pF_}2h|_d!}2ZlhS^_i`m=ggJ*S>mFR10}MfH+;S-lcH zYfZhXR;t(3D)m?Ox_U#ssoqj=t9R79>Tl{j^}brIK2U4ahw3BsclELQM1870Q=h9Z z}I;GP(Bj1cRf^?;>(miyw?y2*- zM!sR5F@HACn&-?^vzh5MU1oDL&1_+&n=Q=@vz6J}Y-47cZOyFc`4wgdv!mI`>>NEM z%Is?9M7t_x53{G)%gi-8H%o(cR_kwzg07Odnfs8*I_`w~f)$du(*y^+C~- z2+`gW3?Y{%LOHoA-EI6K~MV5is(qkRrL)ovC&Ro-r4r`s)U zqutKVwAN7y6nQTAwijQxc@*8b8SXMbgnw@d8F_7r=nJ=D(_OO8$!)x3;?V`!DO;gzptD(zl;iH?_6e=4X{{ zPNZ!=Qnvl5Z9lJUN2;TLM%hkPr&HP1g|038Pn7MUNZbCqmF-{EwI8dR+CWW-o}T${ zr)kl1?Eg13?R$;C>YvcHVgI0PW9>NGX4~y}yPln3Czh42q;4e*>#lK|+i7-&-O6rl zx3M$rwsw}?&Tema_(`4Hv#fOU>^?tIy956zy*t4!u_xM-ex!Q8`AOZoh|2dnd#Szb zNBVcIz0O{5Z?HGoo9xZ@7Q3vhgm+L2@3!~Ydw)_9AG43!C+w5|sEc;_x=_a2hcL!% z=r(e@xY=%3H^=Sfc6amL0=LjDa)-IY-4X6c_h9*H_s98P`Qv|h;{C}#JoElJ|Ga;} zFZVC<3G=V`zm%RbALhbX7!MO+GE9Z(FcW6Oim);q08#q@y_7_NxO@>(tduW7N(oVW zWw-z5W&S^}@c)suXF|KcS?8RGsEz!%sEypYs6B`E0#rlPUVu1yqY=ZksdZ{o%cFKfKrW!+Y&Nyf^-b_tyL2y$L_OH}Qw}*8l!JzXPPF z2dyna)Smf+n^X|B$3xUUwbn|Llm>xVxjd&g^!fv8>B?aztYZy|bDcK=B4=@7lYKg}8d*?YF$Z5{c7k}LSP@C5%Y zj-b0Ah`hkE|0y4!9#N0|$N~Is^M5z`mv8=Szd`?3>RS7E=zoB@{Jid-^1sAfKTljg z&0Fi9wSMd&OQiMR^tVMutM_&COo%(+)T>Mt&;4R#G{YRFx{P z3aY3Es$pu38m}g+O;nefp=PO_)$VGZTBr_IN2p`f5_Ot7OP!}KQCF&K)y?V-b)R}z zJ)xdeFR7L4P4%AoNPVup)mn!-t#i7U?yDPhiyooJ>Ir&^?$Fcp)_QwATkom&)%)wk z`Y3&zK1rXU&(Rm?OZ8Rydc92Fr616b>ZkPc`W3xOzpYp6kM)-ZCNOc6HPxoKsW(k# zh#6(t%=%^{vzeK0W||$%95dInGtZdi zW`%j(yld8&PtDhX3|x>5DuaAb2#Ud|U~(`m*fE$FEDnwj&I&FKZVc`S?h76co(P@| zUJ6zQZwBuL9|d1p*uchZ)>hlzw%#_`A$F7$D49+T~m?*Vi?=7B|9; zbraka*WtR{bhove<#u$l-R^F#+t)302fHKOv2KYw%bn*gaaXzP-7~V;*jZnW`>-DfMNi%0-^{g zU_#6R6%_;oBL)x^Gv+KJDx!#4(QQtMBABxbpkhKX!h79SZ8-bveZu?w@x8)SNJjIu%`tmeip6;*Z3}2q< z%W1wm%a>>S@*H2D>&xlBoZ-uvzP!+vvwV4xFE94xCBD4WmzVkSa$nB&?RKRvukz*9 zzP!el*ZT50UtaIa8+>`AFK_ncExx?nxBOgR-r>u6zP!_yclq*eU(WaCg182n-sgMj zeqTP|%ZGgVurD9++28>#JTx3H~k^YpuPl}(V?Znm#&V_T%( zr>l|J?siMt*0xO7rE8Gb9(F6+&SvQk=@&?BPrJ2kZ}arW^h+dmGrNuLV9V+H^eZH` zm+fae+RF5&bS)Cw+xEAeY*qSm`ZW^U$8Kvo+v@a}^cy60bGx1GVq2xZrr#n;KS+PG zDKz~s{T-Tqlx~2gAEz6k=_eM@^iwO)^fRm6cgjZ4bfq=Ww8qB8r|tjcr!`&0`IdAw zBwYhZzksA)Lej4w=~_toH6;B8l70)dBkUf2*Sb+fDRvLUc0YTpJ<1+o4?}GCx5wF| z?UD9ysGVXbL+wO6wJ61Zf2X}3YVWc)K<(Z3MyQ={Z-Ux;?9EWSz}^D2v+W|Nz0y7a zwO82(q4sL~5Y%2{ABNiN>?2S+*FFlhci6|EcAkA4Y8Trlp!QySE7aa+Z-d%}cFzB& zqlvv9VsC)h8zJ^4h`kwNZ-LlbA@(+ioddDAL+$-6o!F0|PVFa97uin{+a>k``@A#u zGpLL0=TMi}m55wwYwR;nXYDGeb9ObZ3bIqZ4scQkXZ@89FyUb-!`=-mGcDXAe_Fh zuAcoCiT&07Za=awy88AzsB2)qhq{J#9n@9WAE2(0WgPhbzwYcIv7bQfrx5!Y#C{I3 zDc+VJpza{9l5hjv!BDrGI|Sc5&}=X|() z#8$<3_)RD1GzjXW3vR|jtd(u#RBf)E^mttoHHc1+E{a|>6>h0})2-zvISlo4kqr#r}fY5Hysfsya>=Cu9HB z$|ZirzGC0Dzd#ZHhvU3rUnzF3sqK%psjto6d}cfRo&UbX?`><_#jjNs+uXMDGua9w zL;Py)d$ps#f*YYo(^cuWfZfCHfs&nUC!?0V-rkN)?8o*;G;-UzZPCf?$i>F;2NP{QNQincK@<|quoKieqCVD20%NsM>RU4 z3tFQawnlsO!-437gD@VWFcH^bEN;NfxD>Zy9%kb%+=c5gAMj zz$^F)Yw-@g#X7u)AF&Z1iO4osBmHGZX=gf{bEJ!zZZ47O=5lj|aK!zPTpkaM2g#y% zd2*yY=q9_#x|^Hors`lf%}vwY-KFkQ-NRk(F4rM$wwtYcx@+BaI@I0bZqeaxuA8fS zx%qCs?(Ob%_v#3@$Su;5?s50Hj&e)gQr*YB;g;#X?qj!7_jjw^mwIriU8$WOUg}ut ztVfi(mb&WErS7HfIu?rkWv~neWQZIA@jD?lljCJP%5suSL@Svhr=pFVE@z^HoF!+Y zvz#k4&{by21?V9c$wlZTm&$DPmaF6{Y$?~sJ^mf$i!ekUmd7zv7RzFckf-D+jP!4u z8YR!mE7(_-$P$c^Lk3QC+ifv zr>E)}_`tvQ^AkN+&&B6DLuX*6&eU0`(TnwBeChX=`$`w+{gUVd`k2(xC-h~hudnJ7 zDeF>QDpmT1zA4qZLRUx|?!P2$&BJkB=@{3KTgVx49+&0(xH{fRF60i0a$j;(n#)3O zH%EB8InvwBQQmHj_I5MY+s!fFZjSYKGtS%1@!oDu@OE>ex0~_aZYFrUImz42L~l2f zz1^JV?Pi*{o3p&#oa^moIs}{B!FH%Uz>c;D+A&^RC)kthBzv+w!=7oU*|Y2$ZnB%| zrnyVqUMiPbm0FkDQCa0FMws-2bXEFY`kQ~6W*+Xs7dlF7xF*iWpY|B9pG026-Odnf zBI9McJf#h_neL?r>ft(0Pt#ZJ?tDv7{B`^d5Pu)9gC@0-wlID#o=U$LPy2N1bZd0? zJKFT%8Ugf7N2f=iS9(-B7X8xW(vz@VIw?I31N?3^d#3lL_hD3ee|kUmNgqfbz`p52 z=_A;W_uDa=SHLkXYW;cE?~AjB9e~RIOzr%c+WRwg^k?ej&$PKeQ-6P^UHq}Ql3ddE zzT}=W8h;)C03@}NBmIuTjnc}rJCOEFw?sXzc0jYVf4T!&_+wZ4V|Vn&?vhSQXP|dF zGo6WD(hJkev1>Xzy%9sWx&Zt5bMBWeNEhG`e~pLwYdp+f-Z7BVi|tNM!X{;TjPBn7n)IV zr7U~O5mHITl`W{a(vONO+shO=MRug($}Ut~8A!#I-Ke;-2NhR_QgLM%6<0=5ab=X; zFN@?@Dz1#9;>rXnuAD^0m5EebnM}o%(`2bEmD8!aa)x{?-^jVtU71bYm8+?{a*akB z$xYNaNVwrrJ#IqVCFk>aN^J-IWKmgLaUIsJrqobyrqU zaphAgu6$0#m6cRnSw+Q_FR8fl6%|+3>UbS5UsG%48)~h5N3E50dX}CoKT&Jt7iz8i zO0AXOsI@B8T2*STHmBBVnY(ssTYXYr)^_@;zN(v1akUo}S9?=&bqgx4_SH}H6WvB@ zv_|_yn?{>z|ENLKK(~!fk51R^q8ZT)-9DNb&D0&Di=vBk$LPiAMcv6%mUXpm<9;+EULL<4jf&rmKZy2^KZ-w(#>6#oO>{W- z5{r(Azlgtzj*NdyO3~QlsO0GAjO3VPd^9aNDLFNonVg>H(Pe4-w7uav&0eM#^HI~= z4z`0$e>>C;HQREBAG4i3z>YE7Q#a%6)#!0DFc#%M9d>5E~d(#YcHLk`Cb8FlhGu*9pYt3Gzic*EyyVRuA#Ed94E0xViYO)#4$Y91W zGMGac8O)(j41w{_oU{j(sSCP5F&^U);bz5E+6^nd08)YInL9QC!Mc0vOm*(-d!Zln`* z0-ESForb1<-_~ZjM3-3cj=0b=UKy`M=JyoNIj%xEUK{^_O0S>o{SIu?{obN8 z{2puPr61TBGkw0j(C4;`e5U?@AB{Zd^W2Ah2L6c8-5>RN_~Z6EyBPoQ8Td+{fv@rz z_-dblukji9mp%jk)@R_~`3!s=GjQ3|Zg8EX4l`WYhAZiXPiPF3?U;ef_RPR#2WH^1 z6GsIyfLVd;$*e$zGAoc_%nD>UvjW+RS%K`$NGv0m704)N1+ovb0@;`Ofb7S7K=x-o zAO|o$%V_2UGRCcTtL1RUXE}mdfgI&WJQpkX>Z&YyoV_W&r&K#?M?}7zjc;4NXYmKW z7xR&*O$)|Yzk}Q{enfRFYmP~*IVQ8_IGHua6xJM5S#zAin&VW~9H-NEaR##qoXPs* zEY=@qv;H`T^~braKc>5nT@B7-{c$ntk4tFHxQy0}%W2KHg4T@d__VWbr6c%suFlXA z00xHt%Kqpf+W=ZCiTF#H(a?<=p55_Z+Yj4eJ1j=+jT@sm8`cBS9C2mH_57vQ*M$Je z{y8W<`5OVsv7-U%Z|+x20iC!)%l|y$Q^WN)M?AwH?)@*v#=F|R?3?~6p*`JBex%eHy|E(>#KAZg6LB6cz{R*0 zH{xErhmY|ozQWI9rM0w^uF_4mwg=iB>=-x1?&Cg}Au?W0k?C@cJSES_3i(LZ$#1GY z1M8@J>3({k&%v(Hh5Dc_)+hBDSEFi)JJu( zKCdt9QeCDW=xSXXnW%PDCu$H?MxCP`QSWH$XuD{~Xy53-=%i?JG&MTaKPxgTx-ps? z&5Q1i?ulNAK90UObxZ?O;h&eNHeF3m)5~mO`kL*{q_}I#0WBxAyr|_9EnmputWMS- z%d^&5*Q`&rZMJi^Tef$$Pj*l?E}N8{m0glum;Icld7Zo>Z<)8vyXJlJe)*31Zu#E% z$b6rCzx;swu>9D3Tz*16K0hg+l%JeW&Ckg%%&*9=&*$Xx^M(1-`I7vN{N4P+{L}pF zd|kewY|C}Zjmpi+S-Gm*rrfREx7@G1LwP{?xbmd(spaYA3(9wv=a(NYKUP_)Y*5*# zvZ}I8WtYlfmHSs7P|zpA3DSyfimv1*s9(N%|3JyYGTx?}aL zt>?FXvF(i=(@uwW8r$iFIp@#0W6s@k9+)@uqv%)NuyNx?0JTv@H}u5~a+)sG2lNSj zR$tUtb(t>Lk92K>D2eJs^`b^mb<{Q5EZXAFc0bNPyK_o3%|D}aQFL>3M|5X2KUxsI z7=071Gj&Zv(}>Thm{z8n+067dea)6;2Q#DPfR;!5c7Hn4td!NyvaD6sCF`ASmFD^(++HRs-WLqEc=!gk;I1CZVwBu-BFOX`vv`2WetzMT2j&w=E*sS7`@`sh{YUZx|rlw!bu$p~q#??%% zIj82bnm#LM)$FwL>Y9^QJ`zq)!`)O+!wB%_*Q#;+-&Ji^y|8NFs+Kj+uBub>Ld^?6 z&3vHdo0>0ynlD!_UA5J!zN3} zD<`j<3am_km7PAH`RPTUj{lhJb@2vU0wZ1o#!TAxoDSQk?>N6=S55?EmNto&0ZH$q zf3jV&Q!)TZ1}FOi$uY?UAUPvBJGmygCs~v{{71FJ|0Pc+&jJZo7W=Q{Wds<%im&u< zSDSWAeQo$<-?J<2m-a{dQ+N*5!IfNH*T}W{ikGiMbM}Ygr{Q|h( zO7%;PN^MH*O5Fgio%rV?m%8xh{ON!Go&PCq$bXf3;7^L5bOOj9UtFWXpM-P$@l*fx z-^A(vcVe==$PQ*iwO883ZbvuJed=~KE$kU~g+18~aI4*J_BTFb?UvfN+%9%U_p$A3 zTG}&h9lMFGYlosKV$?>JkL=w2aTs>O01UyIMO^HQ1$f5C#<#H8zK7*f;Ui=n>5h+d ziX19?$|yNb4wSKSyqqEPMwLATaU+Fgg}=Jr|LU2oCZ%mwr*-B+JR zOF0UO3`HhKql=u19&#pn%30_pr(;W*iLK=V>@9a=XSoi0%3O?)`PfCS#}V=(4wL6` zl)Q{1vt)y8#HAWxwmMv{DX!F7 zxJK*aW^Il+TE?xKX-mx0)_6^K!6NO7S9C{a7WhoZV5J^{&-Gxe)#LHKPQ-UQ0pIF) z{HD|JtDb>h^mM7#dnMPqrIubLRk}c0>YY;7`O-ljmLB>K=_%Xj64_SYkp8+kBC6&f{n^a00>8;Pn4!Q#SW3()mCrx`XdV##EPng`4O=c>w zId+h%a0#x~I=Bh*wH-E*k(eT%;Q{R?o9NZjKyQ+|dcD-s8>GJ8D378-#-NEDg4S{( zj*;a!TwcJ1@;lzpL0G1{;Q)DDencN^FSBuoJd2a03+~WXD9bTuB`08o?tum}8qMW! z>>+com)wO@WF^j$ukeKS!4lmWHF_vk>(R2QUMrd2g>^a!8}w}1LSMu@3geLGppTFYn2B@~sTex|-;wT3efH6K$+*w5<%%F0z{r)RB6e9-~L;SUpk?*CY6D z7o94L>|6$PbxA{ z_m?+hnOrHC$klp@o~LKZ(^^j($jLHEFVo9SwW%_#Ob64+z3iTM&z0J`SKN#46SvI0 z=3aF#xFzl-_q2P~J>!mYM;5v68uz7J>5g_2i+vi7amTuG?gV$dJI>wWCcDes<8Hp2 z>aKIwy4&0$H`h&bPr6gxmF^06vzz4RxrOcyce{JQEp|7$``iLI$6fEPare8~?oxNJ zd&-^eu5xF(%iJmMF?YAS(>>uHb&t3Q-5Ks-_mKNX{8Msa{BttPO>ig0za$sg^W){E zic;hFYdbUkCjK`5E?yV^ker=NOQt7hCFdqHl5>*t5+qkA*Cdi?!hO`QORkE4O)iUn zOD>OpPp*hJB(vj<$(4yoZg%67IJqTBk~FzBxh=7YOG-Y&9%Fi$QD&ss*X(EZH+!2A z<^Z#u>1PI+p=LKT*z93;H$%*xX1LkQ3^V(f(dIz2+^jHfo43q6=3VoF`Ov&?J~OM$ z8uOI-hxx)hZay`in9t2hQ)50dADdO?CG)&_)4XR6GGCg5%~$3Sv(_AHzBY%MZ_MH5 zTXTf@&KzmJH%FOu=4kVS8Ebwt$C&lzSo4$VZ(cAD#@m{Q;_Xat^MpCh{A|XVU(E65 zS95~-&75d{H{;C)Gr?>$C&e%mV~KZ;cQKRV$ebJ-GbN7A)HpGx#Hl$ow&t{$ZwnY; zPLE6GjJTFLGv36U6>n-Q%XXo7~B0D-+O8PQo@a3;pCGY%7;xD>)xyPWq^{*N3E|J|f%cGBlQh(M%4*rm_#}%6_OP`=h=bfI6}- zQW*v(d!ZzIqn3<-mEjmFcVM{OiT&ge43wL&o7{rIaw~S1+b~FO#x(g7XUG~nty|$) z-3AY94?L=y;W6!n$F(;e(Vlo-`{PC34ln8Ucv*MA3%ac|)SIP|-YQLWjx^J`(p>M5 z7CKLw>h01?pOww@8R?_X%U1ewa&K~9a(}WgS(GeDo=7T^MoELDVbZwNG%c5!l-iW4 zlV!;p$(zaR$p=ZBq;1kI>7Mi`H7~U+<;m(~ZL(vsQ?h-sL#ah6E0vS=$xmsN+GMX} z?_^jqJlVZeS*j|vN-NTaX`{43nkTy@gOkz8fytOs>ryj&ft_V9wwK$>>?QV6JJFB* z$Jv2?{C_s*-|SBIcl)kg!aZe78~dw$$G+7?yWA$8JB%Sp!ceopiZ}dcrmmN#p{l0MM#~uCv z#QpvFlw(xRMR8^+!1*EW>{SWa-2lHMR~2A~0e&Z~YQXLefVp@pz%mPO9k9&Rd4IeO z;C2T5?u=~#JKWzh=Pov|V*zvs*zEyy4A@`%{1xZ0UHDLD! z&<(&AK>7gyX5f7RyDNY#19mR}TLtW!0JaX;R{(4iupDvp3)npYuwD8WqlIk&5BEyi zu7KCadK1=hhXUs1JN^xhHpqbh*cRkq0J{_%3xIVc69Mp=$$6YHEVux`pn{75us_JP z00tM_2!Q=T?ghXdKFNCk*k0sg0K7KxDS)8`UjbmhlAi&vpN0d%-3QrrdvUWT0Bq~M z0pXa1Gnyj-VLyxt2-|g^faUe>8?bDf{Q`Cjfc*oGbvhtm`MJ>n_j%D?2XZX|0Dfi+ zAmafX6p&Mjc03r6=>QH1$Ta{C4aidf4hzUL01gkx3IIn0b~b>U19l#OTLSh<0JjD#>u_7Z(cb3-9BuaYfTNAg4LI8O9Rb5# zPk+-d;#1RQ-}LBO)VX!rL4mVVD!@`Zp~ z3gG^LeG9;%fTRCC5U{L2+xJ1h(MLG1`Ve5LC7hpl7%<#rm2)nS0QO7(j|MDv#C$AZ zx#Q;J0ZV;-B4FufY%jvyE}tym{5@@yP=7gNO}P6ZpQI+VH`*@Yj(g7*a5ux}3c3T} zeqe+?{6YbBhr5Ciw&6Qxd9|_xpZA#eouNSa>ZxpcY zmld!rskwyhzr28L!Tw&sd7I*QfBgP!fCzW;4!+_E!`29zKP#f6C9|J-i{3IaMFxu;se^p7tC!klmh4pNUegi0NEtK+=2GwIUSHq1I!(0Tb`MK)D19q zka`6d0Nh}b__){r@Z1du@4L`0ChHW4|)bJ1688%rE2{K-f>r z^Vmn-3+Th_?;as83j3I>1!S`T*mu1O)&tTzfLVa_0c3MPHUP3k0G9&NH=wjf+5zLq zY(TaOC~b>&K%cuD;N4t*N0;{4FMuln=^s$q-L?T-1MqD*L}@$Q2N-YpW*egH=N$u# zt9%O$QT8G2i8_Nx>=sZSgKIV!{}%zWdqCOl zdjuF8n1>N%y=c4C&UXRtt3v^0zBnvE?G%1L98l(M%paK(tptSmpbZCjc@!K)s}n6CDo->%^S$H$V;w z=rllhZsz8{0>b(o0_YhbX85@A3n26>-W8%99$rAdp&uRr=)Hi@mk9lj{&p0g)CB4m zp*@TZ=v9CmQ$SxlHlPba9AYf;zC8{gdMAABVf^tveFFU5E#8;%cV2k+g+9mYWIp*Y z@BbFiS56A(KLBCd5&F!e0^0KAfGz=q{z+)RQv&)1AX5uyJ`2zb0ij-;9r6aD7MufsK7DQhe?Ps*{pq{Z9mYo1=ez*N zYF@jk0apNWe!<0n*KUrhXlp#*g(3b4bzxR9wz&u(9CP^3TnyN20l6f=@qth;E-l6z zmjRv+0iiB1muG#c9gLqm9(Cc$Fw_?I{Z)YS+OG~M;~q7FG4_U#L-;)6t|ES12PpNG zF@P&V9t4Dc$DIB-_&kHThEj)a3NW7&>dVc%n+eD*0p>?S9k~_YyTatQ0_q=ihcMpW z9#FOoV-<6H`sE!3tOK=X9-zEN+9+XcXT9$Nlzl)SAk<0PD`5=0C!jn(?Vd13(U%Bg z&V2>c?}Y*7_1<4V?WBG!0(1o+4+J>Y^z~zYPd#`D5c7(-Zh#v$hM z)bE-Cw)d(4s0Ym7$?t%y32=PFe4Qv`>6ZbHb%go*SAa6EGHx-CXDni_Lug0LW5|zy zFeWjNXAZ)+#XO$50Am}WW~>WvZbN=3pzZMU%;Tx$%xMVork?^FXUoq4t_>5$E#~pe z9~j#R+l29tc|8Ay*GU*pm=7_JXTNR?=pI3{I2FQoc_`PHF^?Y&KR@E_%JZ%oKAtyv3#Dj5`47J1IC700pHe}0EFXg ztzFOu&`kpzztVp^I|Eubz;T<_D>yXdVa&xiW>a1pIXcYsaK49Q0<9>x7SKik=Goe~ zfc0+@@Z+wgfQR!n%>o=7F}L%a4QPu1b5G`No)<$t$DGd3ALRg{FERfkod3|u0OOWc z1vvMi)dj=Cx|Fc<6+;JgO&NKapQeWAv1j)UV;&z6Ap2rw7do&_%ex>*7HzgGdT zyLZ7kfbVbm&=2rqT8?WO|9$;fN7^UP&3Oxcmgi$W&*N3;=uK!9@wkZd5toEXC8kkz?H3paaftZlT$-J!JI-lcezi1 zah~%6gmIm7qlEEX_YW}6`)i|iat?z1$GH6p{QN2BP#KFjuJB_E`ZaBrIofk!{J=4U z{~7alYUc-l_wz$TjPa|wn8!2rP^TCNz5|qP!94z3K#vS?ETzof3H5`zK&WAy4<^)y zV+yE4>;pm#IIe)&z;-9pjN<|2Ja8L8IS0&mH7JZvI7ab4Gy!28!@gxZ681m)iLkAy zFNEirT)?`VT)=uyDPUcv7V!FL)9fp@!D+>qhW&m<0sr>QfX}OF2h7zuA4Dx?zWxy4 zwT$`r1AzBQ`Xz0Henl<@bb0}E-x&q82l^_Z{md-jap(i&ariupxtP)hsCSIdj487U zmWRBPxu?n=?nh8a_W}j_j|Aag?y_ZZBY8%?&W`)H@0o>zJDp#-RZRqZ> zzR|Z0`{o|NFrM%_7XXHFhJJf5U|PZ7pWr8g>jvC0%JO{XCfbv++1CD*izk3mIuL550 zUIHBB2+#d8;Mni{-K&739`gGofMZ+n^REGp=b=q31>7@$@*K+mM<1n~Ee9NZYDK`& zj~EZ$0v!91ar$k*eFiAw;yZw2zW8pyQLCvt?*Z;hK;I8I<~h`<4**Af;d)c9Go+t? z959UEy#7xB!&v=kz%U;3e4hi3zRzQ=1RS-7xlRq>s5Pqsj@rXqXEorc8*2mZi11hd zZ~eMkfJg#vG9P9LxXXbk3b@CC$OPPcAW8ymDiEascO4MffV&omT)^E1M5TaR1Vpt0 zZY~gQ5^&RisCK|T2}E@Q?rI>a7jUNn5nu9CA8=O!QGs*gh^hnb zdLU{QaMu7)>wvo-h}s0)Y#?eIaF+s6yMVhFh}s9-Q$W-q;7$jkjsbTS5OoT;Gl8gc zz+DDJT?6hEAnF!yj{#BlfV&%rdIa2^K(txFJpn|$0`5^D>K$;80MQl!_aG4U4Y)Ia zXv=_m7>KqCxQBpf>wxj1$ zKLgPTfn*jCod`tZ0XG4N3gTaY=%he$5fIV7Cj;r*Ky)$?O$CyRfrxFyd#2|D5$)_$ zAYKkcw99EgsRD@33Y2JHX9wc1f#{rooe4ze0?`bBPX|Z*ekPw12BHgq=t3Y~2Slvv zEFj@ASf?9-cm)vAcIN`|Dj=d=&I95ffrx!`H^3F_5q)nykg#6&1d{1MMEiRINR9%c z7Xu0F`%)lby*CBw!N2@EH37#sQ`Tn7sj0 ztKa~@Y*MftU}_ii1I(rcg8);fU?^bf0;U0Ax&x*mU@8F92QZBQ(-bgU0;XBPwt#6K z;=I{D#C66Qvm0RA6zmaVJmb9CJ;WZ)nVBIW-ZTD~;UV5L=9^)BGP__Oz;ppjSMWhM zm~MdS2^ii}-wg0=vluYFi}rgOFntSNEb7X7y$qNg0K=!gmjh;}g0}&)bHQ7H*#$7W z0_GjS3;@hPz1bj z^ST+2_X5laz}k&nEm_`VD>9`9x(eCyvZj|3f?Q)i*0rgU=A$! z67aS~`#QMz9e@8-@jZWb$lq8Cm_z@@VSwjrz#Lw{pB+)~4PcHe;O~zr_!cln7w~V# z7JLVoV+#1WV++0q%y9)g#<+rYfH}T^$2+0m2f&${}jXTV%q zz-zs%;1|GLUcl?VqTpA+%r0OXTv_lNV6G})dt6=cJ7BIUVB1_eST5F z>44!_I2+AMY9c_5~K({}%`Uuxou zKuk@iju6^1_3>pOrpCWgK)Zf55H|+Ql0eM(@LB=weQ6+W0+`neX!~yjV#bVR0QD)R zo>G4aePTr*W;~((68Z;q`E4L(Y@rqt`pUb3xCP)fjygxbp)S7<#4QWGre@QJJ`BWJ zp{LYT`qRgOm{03be+hkyy8I~+mkWKT#?#NJ%bx>rC16$-(C2CbaaEzw)M@%33h-J?J*Hn$f4>4^#!hN3p^s8$zXoE)Qfe!qzfw=X1!BfjYAB)a zQa8T`;&y=7O6n#3nELnw5Hs#l6A68qI=CK)I{;q$sDJct>e0_Y%-Bo~BJ_3Y&aXhs zI8Ch~^n2>d??BABO-&)U0$xWp0&y33?eO|>8@ygnGvcm5tO4o-HNw*kUKhMJ+zzh= z)PuM?y#IR*U|yRR^ay_LefKW6S*t6(#DU-kZaClJ>z=mqbq-e2zu z{z)H=d&AqkxBa_=f6_~)>KyEbwi9n(*h-P}dHbM^>&js8Rpyl%ccN5U^g@8L5;5%XbdturFSrp)!h|C1|9B&o} zxIQ8)1-Ldms}j1L)0j@pI8U(loA)12i2 z-ZRcx1-L#qYaQUd(yU7WrvX{l0Pj_1y#u%k$od3$KP=<27S^og82Qpp*?`<>!vK<0k&ztQS;Jv17rvTUXW;+LX-zggq;JV;!V1W0o zvOxi^>CAQu@ZLkVM}TWcvmpWA>&W;!t}j{&WJ3eI7m^JNaJ^?XJiz-9*XvQYu9&CK=*aNa)~9pJji?7#r$&NKE0*9H9uWCsN}kDeVF;QGbvr~v1)v!erC z&zOx3aBe$0CcyQK*|7o6WoO3)xLz_F7vLOvHZj08ciE(X-UnptZ?3251Z1ZNI9HmT z5#Tzz?92e?ShHyXuCvQ{T+Y!y0%R8lxaKUoB)~b%jCR2Fo9lt>h5+AZpWPVXTBz)% z0Ga{W%>k}|%5DkpZROdm0j|}`*!Nr)UKhyb1h`f!qYZK0Yds*N-EbYr{y=s|0Q8l4 z0j}Z7?hJtbbXS1uzp}dnNP%pAfa}h(djfDkwjjVYXW6|0?t_xCO}UPQHnK1P`uF_- zu0_ih1wem!Ai#BO*@FQ-Gm){axsHT&e>lMBB{H@(*OajC>?f`f=e0i;;Chqn@c^Ig z$esvroldqmz~?%$Cj(rklRXvSa~>Hrg6m7z-cJYkyhrv-fa`a%X9Ij*BzrEvbwAnj z0nkQX2yp#E_F@3Esh0v=?~uJ5;2QMol>qOTX0Hag4n12E;Jwo9wE)-3XY^anq4xkX z`Zm{yvpwDj@V;(F`{NpMw#}OX-s8=d2e^(tTM^*>-t4Ua*WYK<5ze#s1hRJmT>G9; zD>=_jJ$o;}weK1Ag7fUOe`*BRhx1xL4Dfz!_ECWA;gA2TXTI0{p*VW@8M+Z8?G;D4rE^i zct0mw8{qoi?CSvU>tx>qxOO=EHo*Hr*>?f1fz7@T@Lo!`F2HrN8Fi5N&uK^0KCUle zJfSYE5BFEHpWxvd*zD&3@2T*Sgggb3IY4fKybkva1oFB-UI8SFfxHQjw*-x}Nah3i@j!k8z}+bF z6M=ku*p(um0OThDNez%s1oBBh@&k}h2J(}ERDgU6kWU5DdO&^}ke>r24*>bOKz<>R zusvo0`4vF29LQ$_`Sn236Uc7>@;N}-7|3r2a?a}>1myPs`2rxh7sv~e`+@wvK(Y|X z3z9`ZUXUyRa-RDEAbA4F9|ZD;fTRM*9|rPAfTRJCKN?7Q-p2x^ra=C9AZ5St^G^UJ z)}Q^l7$~&?@+SkOY9N0qkSqi8e*}^@fc)t|@+Oe8O}Wd*>p=coAo&2uX%n2U<}qIc za_;>>yLcr~Y7XSD21+e~d`X~`1Nmz}{sxe&0dlq}=b~2w`HDcY7RcWMa?U^R2;}bo z`MW@}J&?a2D764`*5d=9lmR(y@k5}*YySwyKLt_)*jYfiR={2i zls5_3%Ykz3fV~VTZwi#_0QM4~Tt8qZ0_6q)dlFD?7_bw7az((71Imp8b|6r00+gEp zb~;dQ0hC(;_8g#`1?<^CxeSym0kl{T(Qu9I)>KEKoi* zz`67CX+U{8V7mh483Fq%P(CkU-vP=q1NK#*d_GXV0I>T36W-y$&cp7O-=H%2FVG7pQCyaJvJQjRI~Dpt3691_70A0`^IuvP-}X1}cXFmBRpA z8>k!(RPGPhdO+m?0b2{GoE30Afy#>lt}{@1almy2DlZAR?m*?GK;>nC>jhL^9&noh zl~)8D&p$ihx&f6}23!xIa%I5v1uAQRO5VTj15~aFxZyyR2JCvEDh}9}fvO~6Uk9q{ z1ndT&s$PJPmsQmd*tdbIihz9%sA?LpPXkrW0(K)%l?Ch@Kvl#fL#t$9TKohfvRT$_9dXYO~8!+s@n$KUO;ubfEx)^cMQ0_f$CQSZWPdZe!%qy zTE7@@{eZSN2HciF$2j1&0Xil?#}sf|0i6yG@ENsEhXnX6LZ?FmT*uRCYyd5QPU8Z) z2Q+?Ltd1kSh>Vg!&HJ~68a+M|ft=v~#0-zc7(Ve} zFnDDD+Sb~VE!C@6uWnLm(y?`QTHT;$gX&r;v)*od<(u~{yJq_#L$1DB7ydp-tn}OP zB(QN~s7JH_RsL!C$eqQN=70Wt_MbmLo1+Mr@b_j-fr4Chvm`Y59vI$}ZpMk*0R zG-}zRQH6^|J4nfz!ic*9wIotR2l34qM&&@5O(eD^KB%^okffz#46GeF&`Fw(N(VLX z-xoG6#kO>ulQco9ow~S)4El4Rb_*6 zgS=T2)JMH~71f)T8h5Opw(Z@sN27{{X+?G6?*Gnke#@J7+Ioxr!$!2JtZ2~pKQ!8r ze;JTzvT46&y*m%8+i9fMYgo7Lh8O;A1ODMR-O&_n(G@*#Z~w-1>!={&dkk7tw`^fz z?f$PDP@u8sL7PYnV`KAQG@vP&f6;*d;`9Hx0lRf;)(q&@qg#)zT{?H_*r9#9W^J3b zsm#$7O+rgFtpt_BSn)T-5>qCrKi`nBrU zt5?y;mYR6clD2(%Hcs0%ZcyEpg4H03WO1LJ{`YpqwWUPVP( zYTB_u+dhp`f1T-HRxxAt;M0fui#+q|zq~2hfBK+X&g3-?{r#oCck&;;vjys-DJszl zclK}khxRxT)3izBh9;G2acNx0PZt;!HGJB#^p^~!DhJjQhd6QZ7^LaQfebREl0nV; zZ}H~`QgM>HBp*cpSUowZyr26k-<-9@)P|RTWUxs;X6GInP?QXx^+*MIk$z zlp1%$f0mu1>;GyIx$*CUv*FWV0!RO?an}Bm)O_Nt;rEGuZ>T@*d#Kl$pwn~zt~2F4 zYi?50L0tNWP_v~{HR<14N}xvcpnua+oB#QN)M@ID`R9iE>(l?aq1w0qj~d;wMIkS2 zsDCdnX>gUl+UuQvt1E@~jQv~F{R=_a_%B-TPt8~#G(#eHwY-9xU>B&~bJIONJN`{q zF8@X2ug8N%b$^Mbm@f{^xJ$|4OjcaLSH9BaMe;o;X!bYX& zFCqVzAEbhB^7jy!wQ6Ndt2V9LR96K%Y}&X%JyXYQ+PYrd+NH)FrLtEgd^*b*m{fZu zFLKz4uv|L)AL_mYKCY|0_dDlqGox+ptkR6OnLCSCYZ;BkmSuaqTZ=6@wk(h3 zC9)js*iPcaSxktNm^cYu5=fMdh7dx`Yx@WgitG>|r391iETs=<8cGWR0xi@J8h9;u z=Ka3!+r5oNx)O=bFO^W`%$^rJI%2Vo zj@ZS$^U|WIV?Tsdp*D?vWYgkdtd_LLUlij^a^A!KS)4;=o&9 zi|)~_S)Z3ltfrdFlFB*A(xAj(ZJ37nrNcS#NDw56O>oB8I+S z)g8>FbTy+VjHv4OrTC<`rnP6OyJ6G9k@u`wcXVV|)^+!5sqQrc!;d@|Dc|o(8cl5* zfA7E@pV+oKeeqWt7O|6=dq42gBHeDa>G=p&ucED0s3cnp&(%}e${ME1RZQY414$Yj zdNDYSS!%W=Uzv5&oQyGSsLZE^W?edQRFd`s z*jkjSoE4v(H9gx6Ds!;n9W6@e;&XUQ%Svu(F54K3x!toFoIC6e1$@Zjn#x^%(lvMq zgG;D>9~y;d*B5W_`PjEJ=LZKDFCH9R><`rh0yQCjsrvbifg=a=FASu61_pZ41D_68 z*M!40)!~cPvj{8|eqDHpZ{ojzO41^4&U$^iyIfWzHdyB3(mGV@*9yv1J5)_l7;51# zN2fB?Dd2}`7JxEFe^Fo?W1yg2@AG=As!*${@>F?zy6$y5T{URlCo^Q}W`dg6kTOXr zmDJb=k1WY7TG;Z?|M)|9#`xSLUs_tb?QA6S^qUpmewxoLtvG)1S;l_4KmWqfqc)#; z)IKBASfK~J@Gn^Jz-OQeJaErhohh=#hnqkF)uE`9F6IEHInb<=r5tIBXvski#o;y> z4rj4xg{(;OJI(QHj;{)gRzw#kVH>PzE-$isS$$39U`3nVe z9QlM8e*~+@K%zR?b$kXYAqWj{;A~}ySEd0wdnjC&LU`&V|;+V8x1DMM24x!0Q zQ_*q&WgMjwPE%kcm-SUwS5;LvRM*#qtAbU5WF+Q5C6Oetp$plpCH>~P_4KBD48xyd z|8x99r@r&b!%qzKer;WE-_jME*4?{l4VxTVf5Ub@vw6pop^7&?)xKasB5yP=+V>ZQ zf>;a5U#tw4oTm|i0>=v>T4U54e-@+OAYmdH|5H8#wGfAPxHVf=S-~Y%OE!Wy$JnDp zQ6*(clex(WgaTb80X9*WITB&YnvBjLP{&cx#(65zz@JFe)g{^!ZLQ69@w!-YFcNdR zs%;_|QNNF*M7pPUF(++hE=BmE@uyFJr?%7KnDABa-01(p!%q(Oesyi{;$=viYgU`I z8EA9Y1)A$KjVp%dP)X1O>xcOaa2ZjDPYL zj5#@*bTLJdCg}X5O;997J4i03$dWQO_aW4*!8vX{;6$2)YHPjT+GMS8UNm^a-cT~4 z>#=fIjYXKWkxpIqg!u846vjVv`rGT)ec|CJOV7#OcbnAsjrvRqgg|%(rclphfXV=!g-LlhOxFeZ-_)#0 zNDMqA4ENj_izU6WCe;;cjj5VHV5;NEOd!>bQY&L=NSBa_>k|u8-6PpZ#v5sfbhdVt zA2~gGa_fp&6iX~nV@j&2dx^VZmEP#pC*7ZW=H}Ha5UW{ZQdY_Bywf0<*h@>OOBF0gs6I`U%$k=_%EOVlCV455b)`e#3Bu$nxMiZ zhk^>;px49MI!)zZN_u}$Q$_#{OP9`8qk?P-2F!31pK%z;olCd2L}m2Wqe7h2lJ=Gd zGeHfvJt@)Ehy}fLQFvGUhL!Pzp7CzEcJ$;{qoyKL+1W7|3?KE^CzrBIQYL@m1uT9QCzr%h;c@cOSzwBJZ2x*k8>98^xs#qI;fA z$PDG1wFnY#A(=7MY=wNAy^O5Ki5$)2)XQDq04=7v{1(^JQ<^TMS;Al+`SKSZf9-6v ze{4s`hJ}1)`uv|f!)FfWW7ofL=e{_dJIwpPi|j+Zj}lvgmFz;E$#>Cx#c@N7gXDY= zt5*sI;@dYPA16dhZvS^Vgy5i9TSQ@8W#k2-o9bZb;372yw~AI7cQ6TLF3D5H$wFTl zwiRsXK&omu_3eQ^yz*< z0+!m&;uk+lM0k1opIYnXQ}%i#=YxpcLh_r@o<#+HoR1^g%BAZ!<^L4jU!tS)G@?$K z@*nrydj46=KEuwKSbNN8$e!GBuCjv5%u@QQ(dEe}6o%m_bb=PiRjV*AF;tVLRE%25 zE#@ss=_%g$4}2t(mhlITaQ2 zkz6)dQNf_XSK)P6mbsh`O@VS&?r`~9BO+{=N=MQWJ(;G3rdZv(-~WMoH{^fKo_TE5 zz1bx<+_eAJ6E|NRzTtN#L|XV_bO z2FhTwSYaJ{;Uq=?#YzqoC5J}5oC8_jCS;R<;KcQbd6FzkW9A%5UZ2Z4Nd9i{vl96UGrKz9`;}VrXLg0YvYx=cD`; zO){-yKS{mTBY$ZmQ${6D=2BdbBk8aJj;~PtSAE=-?R1KFvvR6@PeYqiUIHa7* z$win^5M+UPh#k7hr?TDl12QP8tW4SuI`FHxLlQq+D$jFS1RZLC24TH;V~H|XU29|> zxo+qY%_1tx&JyL7A7jtBiN@Wf()$KJa{$R*LOYb%f_5hmk;=4RhD~3801joVTuxPC ziVAE{;@paAL{SUB1s!QJ$5k*jM+Q2`GMyE2q{YP~6_91_wkOMqB9EC9Wo3OXi{WNn z_XagrxRq(ij3j)uL2GppJ;H~d%G~?redN<#WS<`C$0xeZ9 zwP8Gi*5-T`GwnetAlBDg|L@l5)sh+fCl#Ev#jtXd45y*m6Jdldw%7M#82j7_kr*oTg zIE-%k%RJ`-MRh5=iwD~2bc}(6o^?3a=dx~$pW?3i{6@@;XP8;p5yc3qHkSx&8pEY^ zRw&~=V#`bD@%t1ewIUg!@$C6^?- z(DjJ87E{2>7@p@Tds*|7Wzppyd`G&304OkO2AJ#XFnAG*$0*7}anR^I5z_ex)lV@{ z42WJD9qkiDTUHgXC(U&d89}+%m^ZU`4Eyf>4bSQg1`m)8l-NU{o-p%r5 z+jGz#Bc6Q(Q4mqC6)H&2h9<+e@O58xHz zyNbf1Xoy;LIM53OYW6S2UIsk+rj2zHs#B>ZD#Qlak%aL2c>)BgPt87p1 z_|F8NKX}k~;ejbu=I2#al7K28{S%67A$Yja3vP>C{j6s>eXzU~j zd$hN9qp%lN79%r^r2Q00`*D=^6Cg{nX=NoL5sO7)hGk`uJ3f#~Y35%jy~ec9Ei;9k zxpp8s)YIA5GvG;QS1e!Lx~6es?uqs9UbTH>V13_#wfy|H^?jYmwyuKNxI8~5Y_dz?uGIQ*OS8?#pV=3IivN+k|IyqGf@Q?Gbb_h zCZg3?hAO$P>$o1KN751WpQIycc0RwGmA(FY{y#7k>fjgm&m1TeupWke7wrc`=0ILl zc!|Bme*sfXk*qya)G)-HNgPAvRC&K-;I!ySC3?ZT1qptl;6-&ER`|58N<)s`WJ7; z{chH&_g19b%Q{C6bbl@XZyP(0N!{szihlI=cA?6^nrHIH7r$7%XXx)0_iP#~Mu34* zxWInPXCMqmvz`!>WIyAIi{V=XvjkCGMPHz#@I#~;vl}gqQfv?6!(-qm+camM43Z+3 z>Pv_h2cu$_@cwvW@i?72bb#OyGt;@y2V$f%k#xkbvD1gLcWxTFxn;evdcor5D_30m z+5Eq;Pk)ZRf8WHiJ&U@#hobfUy_v2ppS@xKXA1?fCekmlI|3- zijtejER3Ey)2R~!Cdm?$50Upq!DaHCh=VCgahb_Wr*Xho7<#)w88@dYxJqX%s(buV z)TGJEC#Oy(nU44)L4WaX@j&b0O(SHL-^Y-ZZk0VUW82!6rH@V4Nx7+;@z3D2Bc z!D~Wln{Mb4_Lu+q^{-E}NBO|{1Nk4Jl5g_qzb9FNT@=u!M3iM#_+TMM@8XBuSyu&< zSUKYoH{T0^FELSU60dUc#mHTV96DPIGWvl~$2Mmo$&O8BYizbfIU67o~qN|a@?1dyLHi=Wm(t${~doNVE?5+SKf+DJxp zI_VSvWiQ^)F=8xl9+?~(S+roX3JU4FS3U8}mg#N$d~4Ijy3o;kAH1#R4-e!&9*MvF zM>n6@Z2IR$Ne&~zIr=*>?L1Sxg^@66?|u2VizyU?a@ew$E`>3452@El)(Dl0y~6@`3#IGHOW zxh%GjX@X>&PDRY=3YR)FEpa>Na0q|q7c%6}T$5bebjc|hduZdzPQGc>^k}9Ag4MH* z%b_!4!423&2E7)*zQ@l)HLS^&moZ=g7XraqHx=KHB3raZO8W8xh9*hAmRh=JtK$jD z6>RlpOvAv^dy#=_nr=L{c? zlf=g?r(mMtrS2Ks&{On(gMI0T)6+kko@O2SZ}6G?zcT$I0?Go%dR+cEpCNr_pU|`- zPK_%rnM0WZlTZenmGMao)RiPTCNaH>sbiO$%5oB8D!!3NBxaNTg7Tys?M8ex`hPl= zPWkB{bbRo~`={TWUb1BR&FTKHz4<2lRo;bf%zm|H-@bkOwrmozhHoZ*fE~Fc=YuAn zK%ezy;s;{<1R^5i{6dK68a2nCMSdX8JpU%2fg0F_UQG+|8J*D$+PQUqB(Vsc}CZ*ux z4wXbFaj$S4h%Jq=caF$hsIMR%Ey?+n;=O%{*)4O}jb7Oto_uoYg)jwGW@DwFqO@gl zseq3w_DQ)j|FP*md+f2_F!s6p=hzx?PSEDMAe|!p=pm6J)PS)WRc4bI8OWh(yB+gC zU^~*Pm?~tkeHiIU~l7`Ba_)<_gsN)Kg@Xqo{`eJlFjplOMG9P*&bZ^Yz zs%-^RHB6_A$K6M9g=9)PweIkW+^ux>kB=?wkKMk-aTZR@jc?Ox8?;O-5 zRbr?Zp+|)bFY|QO&i+J}l`+$XR?t}-z|?B zPm25Ed=`axp+LQ;d?owx5LQnY3e1DdFZvw1yO8tP{)V=dA%Y5qWrYjuK0X5#ux&7FUDw zqS@mI#u++~%>W?6f5T|*Y}6Y;g&10<^})W_`+Xz~uSFAO+p@6kEFSv5gxa+sL}| zUt?W2ut1*j1M$8Mko_z6Y#O^w04w}^VJEyz@6s@XMPfoSW0%1k42M61oh5Uh2{D(y zHRDrNExDAZ_0-#$?JJUP?e6Klqx%*IuGic877*Bbp-}i`VJDlS`-@#aCFcq1nnSL!HOEg< zhduFL5A*X-1zxyUNS-n$T3jwgBzQKIKw(#1upX=RvDN2#flWuP(SRd@gU3qN@@Ik-5xpt(8} zs1M|SIX%tp!Ug|eX?J|A(%*Oy9Z05a{&PM93M>?)bqoIiwZSrvHEGt^^odb>R;-`^ zwjp;`*WGxLG7&AJr`}*5cmBZi?Y9fQhjQl^#NV)MEXtjWL{seT@^j*EH152gI-H3+ zc9HINPP_-|lnNzhqSk{6Y^rK@dqqc~b?VG1n7#_?m^DeoWJJ_@DxgAWd8qZowTN}= z{Dz-hbmtF@j!tjdbo=crb%^Qte?9by*mrzK{$+@o@Ax-}z(KN<5v{E8$Fa^3$Mdhw z8b68MrNp@^jx)*mVb1fffb-LgeK!9JCh606hKh5j7Uq5CZ^ijPN{0Dc274Rn2lyS> z9fctsxtr)Unyn}=!|0hTIg0#HCw_=7z9P|r#1JKMRjrRWk_s7J1yuNT*%d%CrL|;6 zPwAPU=I3sA{=kB+UDNOD{@m@izg0WBnC-~tH;*31jz0|Xt2p}JeX!vrk5iSHt+e`) zKS~S^2^nGE)o{r;18EFDraLPk&+zDh0P&27Atlm18Oe~a3{JxOP;ZLA^?@pl-FE7z zELXk1_w%ZM8894$vE2GV*E7K zTaj#$Ht-oR;J$2m6qD1P5(gP=PRuh7I5b7VqeyuJ+d0y)c#T8Wr>LIM6t*3G7-Z(v zW5xlK$7znRk?>1shRjfbM1$4!@Xt3a7WLu zuW7Vl-Se|D20+ zu*-TYglpLL3VTb>3_6REy`S^xeqyf?Lka}^XxMr2E%~Nb-f))P|MEZj?&tBfM>pqx z$!9LU{=gyDDbD*&=@H@!*p*a*Q`o^k+!ZcrduiNxzo?BP8L)|R;>7q{*nP^Lk3JYN z{vdXVq5H&WP1gA1mMxZlb=LSv?8;?-51s|_J*P#z1KDVz_Ct)5jb_isn35QO2sGW)R>wJ^xO$>x%DY#*}-pp);21|O8pNYabv!{{qioSUAHZkFzvc4pj%Q_9+ z8;_C8S-}z(Yn3{dxT_i-E6kGX4*2=Vb>pL%E^mDxT$gNZSr(r@R@SzCNp5>WxK0}z zc|)o@mb~~YKC`B+WiPgbEIeWEOEqlGR{62Yw}Npf$7~H#mk25{FKW7+v+ZUXMb?j> zP+zIZlJQ&?djMBMwI`O;u}p;NVnd2=pB7g^+=N}%Y*^IotM~W4{Et4olww2vYU_@c zu`*Yd|H!->!Z%HOQU@Qz*anl)@8w|<=!{d49rvV`9K5PRJ^;S~2bt`{nj& z+8Wv^^l#G^@$-8(U;H(@K)dsG+tIzI&APL3=^m1Gc&7~ZHg)-xoFA5uKck)BNp$hT znXJprm{f*EohDZf0%OvIwTE=K$Tb`uda;>~Fzqcm#qk^qcOlXZZ=R`Xpssm%zIo{K z$3|QDDdQ4i7?`=ABG4l7^*JmXBFo03dkrt12OwrR`}o>~5oeYNlH`9WeE?z=`^Q^7JK>R;NZz! zyG{)bo!U9Pe#6l4@bEA{KlahXH$T5+?D<;`JwJZqk>kgY+;RW?*eu?B*X#HU)Il@s zJXcr2i(nBUtJXj$?-*k#zIG#(C8M=wRxVI%%9=wtY?bx(_09E7%^ss>b_kAq{)u!t zCA|Ikr>b#UfQVx7$f`B(9Us4M&8lU&$J*0V(;aQO6)Tr7U$tsEyM4#ug@;q zQPXw(!;hxY`yPF`dqYkB8`;GRmn~b=mnAttHEhK9vC}*160Bq#bGF6!TiEg4^zA=H zeiSkO0CrWg$5C#H@dr(v#Hx|wh)izJ!&ritcLF<^fh^{kIYl8zzztUB6rY_rh5g;A z;#(Hkki?mberI&m!7Y?GDob460}^8tX2&TKI-9-Wa9LS65spV1%0gu|%|XnEEJ>SE zuW)Sm>0%mHY@QQTnow1KnZrah2=Rw(8W<)G&{u+8;{RXMq9ncQO0;;pm~LgvM~aff ztILt1xK>eD-VAAYW}Zwe)y~A~m@lJB1qo}R9O{IVQE*7piov1o%RS*_s*5=^)v*UO zMbXC1r!7S{Nw6Rx?WOI`L67gNhFN4xs2u1Ex+tG{b; zCLQUFbTlV_w=AtIQu3~M%G!#~cNQ<3zjYbX+I$M@(6L*td@F*r#+F3P-QcdT4q%0=Njs`@y@Yo4+zgG(RW)8?EjLr4dS~L=`KWYe&z?F_ zvmWdC^1ReBhm7b22t%}_}5(;YCwch+sP$65tVTj+m)V1{iTPYiq!`1$JPgN{+@kP|lP)9@k zOrrI^B7GVpIwd=^o&e)i3(5!UY9-DTE5P!fTwG%#9*2%ZD>?a-nPA{57x=5#w=>_p z@)|D;969)vt6pcw-oF$)bD15C6n7A7WyKCsg#}%Uoif@8U87s=Dg`X5r7iK7k z1+^kyvGj9U76rBVU5bpA^uDI1+S;a6Q}=>4^9)c$?NySfB*i854(B1>)fG>6b|tRj zTzt60h;??x4Ad|GFP{$tM7!Ga!Cv}l=G)(YhXXQp@W{(ob3m+h{s=s<0Q%tZY}i8S zX>)SMTbaV*OjZ0$Q>{FkB(g^vCQLz?FjY0Z9$0TxWTdTgXDWb+ms3ur$+9TV!s#0F z(dv#4fR4V7Md?&5S{pLqc&I$9B!}HZ0lV6x!rHCWc2ud@;VaTjdfLi!H^ISv_`A^X zQK*45EQjfA4WWdku>Mr)W(sd(s#1&M!}PS2P|(Erx(W(fGp|I!-d=#-<-OVdzSd?V zV&e1=1+8SCIWS=IRo*#9P+-}nV56_X<8lWp2YlIPe}lim>tfGbnW}ApV61CtRfW^( z55`i9D=S>i7v7n$wygT5Et5WgopebibxJq!uaIs1&qFUZjc(1lLX1f+rZNmWS^uGM zj5^`R^_Zd~O=#%hnj{1%QTkkTfS`}0nOrF5B)}r^D?EU%Ol;5%hu`@r^q*j3Rh+9x zY#hH<)a5%E0w+?bJ-(63N6?Ytr}h-h^-ZxTI-L^9sMjpEN1qeA1Lw-hRH>AdobP%p z8!&v!Y)QFiC^6EJ|94AFer4yjiw6JxpwqSU5nEdJgu)j;Xo*Ri{uomiI_*8YLFlw4 zbpS$dz&Ze-H#|b!;4M9D8R2;b!GK%NT2LiOxJCd~sACQ)#@9qeIvVL#MY>^6(U|10 z%JMm7^G`pGefvkO zB|V?2_06$?Bl(y2?CH6TnpLz%|Nmd-8?m2emS1L_e>yOB@XG5%J+PAWN%UtuaL(i6 zKma3{AyJQRd+b7c2;G6Wfs=TzZ2z(8T`bN*UnaZOo=j!s#ZN_%8}<@6@prc4bc_vE z2*+1bi;*N)B31KWQn+F2)7^o9UoBM{AKJgGm{PIw-470(+PUlG;E&DQ@XbGJWOjzd z+7A75Pak@IeC(r#e{026AFi=-o- ztELb8IYMMTdqpBi?mZWGy(6J$Z_5f7xSyYgFyc^DGcEdUg85%mZvpyI<)cmvcou}NM;o<6iR6WmH4*hO4{rx?AK6BL+6*}PsX&2?m8!RI76e6asEXuqlFyM^3pQgct711Ah z(KEU=o1Q(91Q?cvnLq>d2$izYU+v(*(2L&Dt=ZI-AEs(C5q5MqN*+Zn*kwHmPNyX| z?O&b$!E7gRaLU|?g)BBy7uK?Y1DInROVpSKlje^(5VsDam(j+kNB8J@B0?GSk%(0l zh**9REfPSWE>(-fEcCUgU)q&lmFylrJ}_{6yr-F+bLW4ssQl&6mMvqci@S$btsWRy z{eJh@^S9h|X54*X?G5{H9Xfa?`d5BS`(a@;xxiyp35E!6g2`BfBU#uKR&G@z3i-nd zGo}B$$P{H|0A-#s-CYSTaO$PV6j)wl18@De#~-_EWcpj#RSzs*$!8ATbn9*Z!e{bl z`c~fd3-XQ8yO9s<4H3g)e^WA!K1DH3_!}n9#^?DAR6`@Y>zuoaD|UuRm{2CLP!r{W zG=bg|Dy}2=_XsUYW$3xZ8$1h=!U7kosR5{ItUo)WC5UZjbd@w1rvO4tB5af})5Rvz0ro2VTn=>}= zEX?Sn!Ui7!tN1Fs9=8dqQi6|0gB}LjaD+m6MY)SmG3EqD`KMDjn}T^biKK58c0sBMVsTo6 zWUqj>v=OXOarCKL@fN6l-h6FKZt-ooi3bOS*0^;r|1A*!9$w$tSby7+rJJ9_0PxsH z58w7k^T#O$eB`*`Nij(yJgzu=N$@1Ehbg?SmaB@&m>QxQwlIxKmyDYEk`Yi8i+5pG zpI{+aLSX03h@Fg!z&*|;26mar*%(M%;gW*j1d7U)DNGqOtDx-fM3pie4#&f>MAVar zMNp+wC{H+D$~ZD+(s0Z|0u7`jEi=0Hy3EeuBdgZFXE>MD?!#2#{41U9tJVw+tooyt z9l0&pjZg2t;}hGKv|p^ty2{V?u*bTOz5g!Ec^5gQyD6V90Apv%m@qStTh`dckmedo zN?z(kiv?Vg%n7~?JGf(_DB5UPdlQQUA{I0X=F$j=I`UNi`|i4lpBzBW+E}p%I{d%@-ZsI8&;xpie z8kjm;$-vG@tR>V#O58^2My5(h9a9vcFWF&`9ZZvCO*nIL;hQQ z=xt^!b5MKp2vph z_^_({FFLcX@*HN-ziyqPD%NkU6Z3gu?6dsK5P}a0?%+f8${L>{VRyFP?Z2gy(=2+x!g;J;f+PG!r1B@ zfSpy$Bs4R}T7RQ19H{qpW68j=a{tKUczvk0KC|3C(r7Jwcc#yE+OcXyJ}PX(ioyk6 z!_Pyrg;7|IJU&>Ghc*kN(6q5Ac~n$Ya0!t^7^6B(+(C|68dy}(3{CO2xUdb2rMu|z zG=ptLLlKo&QO3LXrj9l7!IlM?U|-+fcV+Lq=9+sK3@5jwdY1lA!})<%5cXC`0xOS-FK9CKrEoIBsT zThJoKHo})Kt!pApGlw;i?qa5S4i$;@R$Y@fB^jxQJqP$q{u$&2;`=d|M*QxBgbB-_ zB3~d{_rVR>P#aU^_G&IELBGUhF3kl-6qV67FrwwbKxafF`W_@%vC60CvCf_Gw#1cz z5$7R)X|X146tB5;?<{Pk@(0FeZ^zKA4ZG!VdAt;JX_ss4lC7D&c_sUSIYokAC)ocI z)xS87q8vgw6TdSO1uesuk9;_lQIF7OF{ z9yoTc2Zp_3xsQ4+Ef)HXj)`WbMP_NI0n)Fr+LnOOY}s@UB@$M=m=Y<%`! zi(ll+57YM-3f#v(168nHe1ENs@{w_1lMan5iiNOcx6;7=8KB~4pemC{Mh0WJ7gSG+ z*OQXhi%`fU5()Xhz;cVUk&b9=?6%vcZ@cZY+~wxk&yVN7!8*o2fB3MV0j-(tF=9F+ z{>AqNE%NxTSPy&0TzoZDjUx8$3Sc!Vdo6;AyRRA6x+~D@=evgL7MbnM6mh|Gv1b&O*Xa9Z2@l~C- zevv&{*X3K}e$3!&zMen1;mH7#*zGqi547I6f!-g_EAa@icch(TV3sN zP9?4#W2eQ@4|v@{f7_DG%JuZlh1Ij(?UU?}>7Ct$3+$Iz&#e9Wm#9a&0r-%qlTV#< zXuMcn6S6IKsOsKN!d~9UbY-W|yy8$Ijn)<86o8FT47-T*&|7!sY#oeonMSUedtNLjrXS zgK;TZ$$?jqMkOvgCUw~UXHyX@>KN#aFNr^x`2VD1Bp}{qP)-L3Q_&12WrCJnlv&D4 zJ<RuJ3x?uryKfuh=R3A68kvj+ds|w&R$MdL zJGo?hGU927h2rtr`i-q^f>*_8pS-Xs>*7qtM0Kjh!SfQtEMgPw#_Hl=mQx^Cpgvxu z-5`ecK=Q6>-o%@ z)vMP~JA^_3YhU>W)U%kw)Uyz8kb|difq#(CfFJ5DpHrQN(7&96QvxbA$_;_jNm?@P zcT{DvB;Qgx3!IEO$IV$zhL}gS*lL8hA$iZ3p}OALRLo^DZr7SGfIH@?HLr6@4!hPI^L}!aIJezGEsLWM zNd-kcR64PkF}EFCZH(r!A@#iDP zZ%=PMoxbn*cdT^Fa`P{<=eBgKG|I*fl4gx0sf@9aM)pn#)E- zLh0NqVg_R>tY8dUwr0cAQk;f)&c@k!vT&a$y(aTz-(K81=avZm8zSCs@!w~ez~{e| zFF(Y7Qo@&hWY2#X3sX%#{#{A2$KTI?Q!;MxcSDSmpY31m-!DE_{Jiu%zB|wJrSJ1y z`+bVf&wj5*&G#yPKFve+`)$CyBvbx;faglaUlilm1B#am{#%kSBWQH1{p=&At-h>K zNi=PQd(rDj0R~Jhs8tnFl_$$o+(s!&mgCBF{nn7y!**Rd71NFya8Q-L^KYSz1paqFB&;(UN4#?AP6 zC%pIa(QyO?oE;sXN2<1HOp#PcDJ{h?1LSi>t523YJK9>32_s^L!=3LK4xfixu&-V* z4F1=pjN@|Q?~51aG7m;Q_m=S)P@(fI+0f<@C^vELOuNm6=o;)6g7G-(5%>xbgYfLw zknD&7%0`JSZ!c1Zz6Uz|mL`Aza1^eF=yCW1akir5l1@WZp zy2z545}q(fNoh?sKNCunvb1))#ZL2cadC9JYXp{SJJ8ERCW>`ifbaLv7225($E z-P5^jO_j%85lZ&(^BYF;gHhn6JQp(9ej!OMJCS=-qq+@jWq)`luK`!S5;=M_p5lpW??##*x2^ z@rU?;y{=DE4FA?_h0YZ2acNuz#VT?2V&o@x$r1$z35rU6+i6*(Kv-g20X~KvOpui+ zoM_V_mvzQtND8bij~GQ#P^Go$MArBhKW~#|iEGp9cqZIdS*?d^lu{D0Pmc}zyqg@( zaKw(aA~s459L|;_!e({Qf$>SRUe`m7M`X061-g)3ha0etB%i>bGI{L&OUd;EgyP`dGbGJhuEqg{}}t511tR2^fx%5`z2KZ>{xv@ zT*9Lx3JXHI2|jVd^gldz^2F0j$^VAQ?8W?R2x29}c;TjOg^O{}%Md1>QhtzC z>D0Uhb5let%gz||Bdigc)+G1^xBzBN)&Y80fFHs>(6OSuIOz9z6qnC(!3akTB0TjNM#hZiMv>XFu6>!|!HwJg;@jm1k96F(R$tiD*U`Oh zVD;_?`T5Sxy~{Vbog+j0Ka#vDv}ASLo`b25mhQgw+t7p?D4eDkWEE7yp0gE*2w(r)lU;Qw4 zbJilNktY%!AvxyF&(JM@4ild!8h{-M)0i5|ex3gdw%DC-X8rj$*{ghIzUPjc*f-GS zTqua&r~A9aAymxuBhZND+BX9t+icc=T~7&ULepqtAMoiV%a*#Hg> znLDO5hR8K4HaNqSE-V!d|;0GW0yt*f*>n;Jol_pyy z)g4TybacUL{zNKG5jDQ1D!+eZWOc9Zd2Cr<`Ksk#?{_=h-rH}_^Ob$Q{qmpZpOeZ) zE2Y!l9p)ZvXizA?8UXI#QQ-0y=qx1)zhDK9wTG}(Z2YSRi$)VefydP@v)8kZR&(~(`v82b-aXLo9CI3`R|xo4f@C?!KKs$%?EL(cKk}s>vhWiM5I7eiS>EfU23bOjy;hX9!CLK(y(`RM4Rp zYeu(bGqYy`PQ(Hza~H%jB+QJ$jktXWd*S2I?x zzrXkR>pK>^)B8tu+2c-}Q-T$6+IKYn`@JG2$Z=1LNC6U5VOV$sOCj zwPf*iTMUGzDip*TrNt0s*o#zh-pM{uGTv^FAH`gAkj?pj4if0F05b5QY<&}xl_Zno zPNu2VexJlOd9boVQzgzcD+bk!c84aZQw~IUMW6)&(kGF&hsv*Qo*~MwnF0)r6wLI% z>@9j2;}KkxU*mL*Dk(cUWVs{L(VOaOZBE1@4dEJDm)*@2luKrU+{)j|1Xb1WkaHyY zPBg8`+&l99ZR$o>OEl8v+Ne&f{o0kN%>S+H%y9niw=S=0h{YPJmT%41zBAoJoZIv@ zO!^`=(y{-VbXNZ}bS`^p!?B~k3!P64pZV*nB(rr^e*|8Lz*1NXf0J#pPy*_LE{XAl z%;C&1&5>nguBLcQQp>c#`T%EaK{M`OPRyDglUd7tjx8bwS~55&gNJc z1Lo$Sr8$8+bXA*UK3su)ft<)}u4Z#qug1*l)$3Oe53F6jtiLal?&=67Ly1U(iC#dP zb6NC)fZ#@E_o=I6O0Uh+!p~1IQCkIzS}S(#t5@Pw(wf=r{jlNR31V5aYZqU7XTEiT zbLyk!6T5Np56ZYG$gUS5`<& zRR*nEd$fnpqNPF)0GP1b%tVww+1MYFqsK5YQ>qny4_+Q%iKGXAEZvC$G>r>O>ATf%!L%32->}43#sN>k{ieVJiGYvPl~Qad#tx8XD&r?ja$F&Qt;^4FI)()FuQPBe_u~`M|(?CEE)`;#EI#F z3ajUMQP>E7_3v~u{>c(E)V?+Uy{ot*(sz4HL`>zfQ2vIixi7X3@G-&;TmowtFO@Nk z4fSE!A)^Y=%T#R{b2*bSLsDFtwSxfIw+}F81zbiH|KDW?xr57?Jaf74xcm-Y?#Zj# z!KF(9mabX4dPTNxVLH{hprxs<))Y&)gO?XeqR;MCa=0&DRvujq*OOMx6-0Tlr*B;8 zRu*N=m@R9bW};^x_A%vBwLSg}!~U9zIewqnk7gk(haY8q-OS;{tJ}xQT+xPlNi9Qb z4h2sNBRrJ2Vd@h~Img0Z3~Ejwa-pg2Rg|iGLMQ369>v1haxOVB+G%Me^FNqP&-ctF zI!J|35UpQC1u>UxT(n4*7cF0uU9uQ=xwScN)C9dcLiojXcO}LYBk2fGS~W#y41vQf zQm?L3j6IJC8~N{;?Q))MYiJ}W#Q%OJ7ArOE$-iOc=Us1R>RtTH%Wtc#KN$AjeHiT^ z8V`{TZs{Ad?W22WPun03U(5OuOx5B{Q5P_$BjEK&veVkpPK(5#fWxUcL?JiOcB-m2 z0h+dF2%SN;2U%?A0{b}*l7@R}JwN|b+3qV^& zw_~z+tR)uJMH}o$I-(M6y4bF(lY;DHxLrT%Oe6@3kr`LqrtqGb4gtw{@vkqxIrIAo z&X}4Jzj#OM?=Fwc#ud z^Gk=#8Y7V$gQ+)ripk@p$uS)Lw2}Z!zGMp4hBJf%N6;Hgl9|FJ8IZ@VY;zg#c2xud zfoLF-^u(J8w8zv!OwR$vKQbv@?aid^rhUB3Q`3^_uc{mA*nJ>9wQ^(Hao0CH0)f`r zj!f5r`=jN1UCG8o>r=aM+|vwT)1)N7OV>RK7@<+LF)FgKbW-TBaFTR3$SwR9gGMKpv<1 zhzXRZNE&Y-0D#1)4S^qgo;X5FTMc!S8p6wC%^U*C69xIcgr@yjp zq=RR=7BqAO{B5;7Y7&NBA0tvl5^ebmQl~NU&ov>N@AF^TXX;Z7`&Xl%4v0szLJvHU zt&T8RX=IYz&NQ_}uadZ?qK#*ojd9DFM6P(Yi;P836!d6oC0?lJOPx;`ZsDNKS7G69 zYisLiOSKqAtjRF2eoCIzn7cP~IhT_UkCpAp`-q*KxNc3j{8Epe$6tSroO(??;RV`+ zwj|X%6!taD_U$#)X*>7K@$YT7X?6~KrCTyl#@HgF(xXg#F&pY;s@BC6wU0R+C=-!` zS|%CVS)D~yhPxQkIJxKqN3}U(c_|-7XctTSu^+jFCzcDIXg!BKF&ka92y=;NOSh7g zd&(px?;Zx8gmg=YZn5N-zdGsm@z}RB=LZKDFCH9R><`rh0yQE36&-!j@_{1<^Dhjf zdjbE@2 z3$|BvmoFc>^@c`QpkXZ8I5imxRCZVP^&YLNX=-WdZyt*z*O`vzHIBaW4%hhd(QWd3 zcvZ#Lq_nWS*Ry5Sw=Vjp68WF^z3WWK^HdeKv$J&opM6&UnCb{QL<$$UZ2IBv%=)Uz z%Or)>Q=D7kSW;&B;jw=tmt+DgQ7Cl)*tn{wi$%AKvN0u)x-#};5K}9bpYs# zk2F9ngk!A+0)xb?dLxUyndi>Hwgp`Ci~2&gU-;jJg?y?-Fsu!Uf(;^`^D9{!n2lP(pnuFXM#DP%@0_0}cP*)gN>nK(E!qK|i>mYOel} z(R)iWKT&gdb#H1{c1zlE_rovn>dlBI(%(Ro-9|Vir`e~W3ml*3?8Pn%D{f68M0BG$^HO#*UYu8UU?({_y`)6+ihkERV$vZ)VDtO<}iOsuWDNUZBTnqEC?7fuNjM)IN}-78i+{J!_q47a4Z7A$VEIMTgq zW05r9GQQBgZu}@-h8HJCR)0TCou~w#{vlOrz9#5cRmBuJ95VTdG#H*W!c=J%AIS-~ zg~cDXUy+XpJXhp5+pmU?Ouhpj@p=J7xhJ8V>vQ=?L?dF^S^LPlzqHTf-R%0RzcN`z z9}%nO(fdY^u0{6!u1`gi`Rp~hUBfH?K3peiuGlwu6lyHIol1!_sKO==rXg3v+o9yY zV*Y^L#dr!xH8AyM)C;HN{nYlZ(s7wvHv1hPvu*?(3~x(6DrP_lCnu zmmVJG(T2!opXZZXhjm|W>8hifHy>Lkbk{`T0{bS(YXr%`Jc=*V-4f$bh|)NB{`hEd z{_7M+6Z4NFmJ6;sU!ZljB9?1ClckmhuE?zzMNqKo9k!ISOxX}9z!`StGgHz{yrexc zLEo4Fd9xu!XCMfKu?V7g32tL5W2r_SoiGP&XAjuU~q2I6aGC zs?)H6G#b77Zv6u{Z9cZHgm|d$BW+%%SeBr{6GQ{_5q*;Vm`9-jn&6&njgN8WXA)1; zaz%D&h?O?zbl3!Ug^w{x-zm!`W)aK;cY= zMh9oI7p(ywo)6Q1-G~N0mKrLQKuSJMN(rUZq}_IPMm;4V$qL?+`DU3}v^2r$n}?3@ zaVmYlOk#8fVJTw_j6}?ciBv9=I)2n9tRqvDVrHi3ibZXhDVpwCe7LW-uDvcxH*Cql zHAdJ@6Wuou{^ZtSPhdMKmvJmh=ol4f1y;TTZ`g@-8b0di z!Vrtgw4!(NVZj!H5QrHug5eTN5XJhY(bt3U%ulWDujvdQ>0cOLP`hk+`_U82?zo0W zv)6b$`JbJ>8(G3@Gk1Jy2l}KEg_qbj`8d==3~tCaRtLP2#2RbEH3(wp(j+W|8ua@( zTUTDC4QVO>j0n_2T}uorsAA%kOHV8r^g)fl zm=i&-5%sfm#ML}ecUoUJvh?t9&|lS4)sk2ms2=yY4jG%2n|I@SLEvA{UA7A|m|zYRLn!^2r0s>psHm$8IHmIkphXq~A&TS~Cy zjxA!@qInoDeoUyd=!_)`Ucg-dR;B>66<+G(C|tHUOQxuOg~#Km_tZ7Vu}pyadfL_< zU0a>ca@Xodoi)SVyZ5GduZS5UPw}!j^H+gRY9mjE=i&j-{vjMa3`}8aT1|XIJ zFaSsZ4T1{@kOVgX8Uo@9YL`q=mL*%eL`hLB!;WlA@+MvT+KwH^ORlvzi|yEnZ=B`& zIbIWIacsw1?mZ5DVLrc{>`u!gF=*~NGCZ1#y_JuigIlVGU|`ws z5FAutsnI_=vg5*m-LKOIPwY4}(l$`uzC2zWOU%v8%#HbmY1huvL%nS2^N$_9IJe{W z13S;}tPC8;Z7*wWu9L3BfvN3R{$SzQ?tv#~XW=^q7+YbIT_!2gK?cdU`8Y-rQ6>rf zec6mCOD;PjV6nu|@>_oiOc%VQTYpJV%fhl9*eq7(oHmC5Cm`fuZn~(mEuGNVYxdNo z*JYf4;89@q3({Ha1ZN*hZ+`qqc6O%IgmeyeR(gBV9cfVTDUvLx{(_6see$x`lCplj zRK3F$Qsu=Bfr`j8e$fPEe|KhJc}HnFWWUuOo#|d)tt@ZPPe#^;7wVtuEcJHwFVfY4 zo?@lLUrMmtJ1-u7aHcCiq2;@uedzFmGr264J@tRwS0B-SG`dv#BwajydVb=&S%5TY zG;mFQj$I}>`UIX^zeZo#aBeL(D6Tu~Lj?OfnZsO<$IwnMlFvd6MG=w-W>X}z#Uo)R z>FY5Mwd+#NE;GbKQ4~FK6%1u-{x>YnjxG9{rg+o%0#lsXC_4`i252&@!Hzj*PBcE z<4ae5tGSkMTAJ~UT={r&Il~2QSvTLjZl#lsURk)B)c36X8BgBME3zy zyj5A}Y}BZw)A>JE=NyV%0Lue(8%$}f1JDZuCZ07rV;4fCB}-qlKN5X?Kq%NZ+BY&( z$@XTqb#;&oNf%0aK!&&4Ax8QtS88D|8Y1AO8fpfkL>Cj5 zbYHHq?HM>xR05zu+!gs|d4lY(X0gqE|YFDN+0Ep*=)JU1i3H3Y(g(( zwkQ=Hc1lGXB~+g6C^2~^&Q)!`NbPc&3ieI=Dtce+rfk*?{8L7^n(h_uc2XN*4jVgb zr-ESmc&Wp|fdrcPi=1E?yu-uhJ;ZJ|ZXvJbZcrX0t#=b}LK8tyYD7_101*1PCI1Oj z3YtAgtUg3UhvX2Y^N@8TK;D!>1e+q9HXrGt4kA&9gf-=0F2M|_)wF0&4dHv7RYkXmcd^O0p1@L)?9+nq9AJyy0LrsEAgJK{$8&$k7&%ciu+(SgNp)Q>k+5w&~1e)ezQ*i=QjE%m$XGKrH8 z@{$&&fR;uD5~h-nPBB?>pi`004Me}flRY{Wb>$6i!u85K4~Kfd6F!U7P*}W!iW@pN z6*u@4nM~RFX7?u76J5{sqy-ZRLJ}Q`l9~l_lY;6)g?7TCpoHHDz|qk&~^q80wzgEqdh>^vA}!V}HyplNc$H3tGfSMV3l33Gj)f z7!{~E8}OrT3R4vL)=?4=F47}MXJC>VQ!1_{tjyNnWr7?M<8n=FkH_Psc(J2c$Y-H; z!vZ>PY+j(K0h2l3B8ES%&M%%DI&P}v?ZITQ{xMSufIGgjr>Ta2^;6B^eAzN0W->pB#ugS==1tp4v>CP&5!hE4RC{q-_IKE25+W)o(!ZYjl>N{(TF65s z7K;W2QOXOLdgAj!jAZUp4uCL%t3j$rKysqwDFAhXzu)KsLAI@*0E+YKPr%Ee7Ce<4*`DyXX&&#&FnbgLz!!)j3JQ8}DTFcfcq9}iLwC&12K^omhY2Yb z!fH5|N{|o>*v{mzon1 znU3i7L}{lkS#g1D-Nvnk)j4OI9Zz!z+rza9OiX~>wBACRcM!wmSeKF z!Gh}ZdEHQ&Dywo(9jtCT<11j|23zO7UlkReA0x)DyG~k=>hEb?1MjZaPvze*wDU^7 zxe$K!D|)TFx8!cyySG?7*x$M$PS-#C*6l+Tb5XeIj>|jUp>{XyOW-GwF{dp-PH7Gs zrGN@S4U~nXi9urct-&s7S|k~Z2b*J+Y;fn>efdH@hoBIxVSRnm4VKV5TVb*_YJcBj zqqol8e*arecK69&Fyr!1KX~||*|i5C7O!(i%IMF3ukO!B>=^z{ShvU9@1x%}{QOKt zJ;2*98a&kX2Fjp=^pZDf0g!>qX%|EqqJkKt%*GX)KnwMt|Hpge$*&=OA9 zozfQnwq6xv^fw}At*&rD!xYH{Bk%>a5&ZERJ>6cXvsBFIoEc|2pNoWS;9_i+1wr_v zC9?#lV3^N8`d=*7K)2t&VKSbAPXSY5Wk@oJF4h8RZG}KYq%?1g-J}5P)^^%EHyqCHptLe(9BZc^98F2`P$a!+%~Oc}SyALA{l{emoNFn_{HP8O4#fN7y->=NNx#-&o~zI2pKV&hv*pa*s(xqF zS&nuS?j3sF&M+A#m$Z1ZHdL?Mfy%)you3*;sM5?eHL7(C>0-SVh#2dwHV)7**|Oxu zc*Lf6YolA=`0B$GBV>HX*vQ~OPq|c3b7qx}>oryBTy3d*<<*LF{&~ywvvp-o{f%rTfqicG54EIW-9d(-de84E+{XYnR>SjCC z9`N=LLvFL#4z&lo{Q>J9jk$BY{gd>+;rY4P2;uMMNtrySxnPfu`RoF>RPu+e(F!o1 z2xZ`hg3yCWlgsy#R+?M@M{Vug%96VZ#5BM!$~zh4xW<#sea9rpb@=jKYG=+1s?wq# zH-Wl^AZ1fsT8*B*(Q4OFGUF(uC+GLw`ua_F@RBdm7vX8;)18jD-(}gpIhN5S`d2JR zisTM0#3+$~xhzW=jX;tiP+I9}8Gwa>ku5U{jqX0PvPO?81NETUQxHWoUZ9fz>E94k zE|NkapUoFIJ_rxVVup7`(Q`2|WrL?dRbjiW&|NE~?Wv(mzN=iCa*y_x`?lpK)bY~I z6W87Qcmnek;$G+sf9wLLFC3I`WJ|`^(B4YU$T6w6Ucw{L4bF8*6uz}!ek;z^0Ea=;zqJX2h$H>6N5@}(_{1A7?Ai0s&E@{V zUe)F)^_H@u)xk;6+aFuFf6t-mrKEFw^lB|qT~ zuw-v1ljN$zY*L59L>tuA1}GE!fblpR=hv03uImxZBC!!7*vP8x_5zox=@7SYe(^NH zt_{7>;|;fPFSz9nt&b?OBrE9amTZvey#A-wlZVwbSI%F^XVrX9*6v7_DJ+H3kOCZb zdNL2Eu0j{L2{37b5>$1PIQB|q->!MNGBUPz&!e|Iu((^*I?fCY9J22y_m%VcYHDZq z>g3=xi9>f+{Yfu9Ufek*C+$6B?auMhqf1kV!-0Kj`eZhnO8Wf=(y3IUYhui1CyeA9 zmzcnEh+FqMJpVC;67&3*2BVu%k%2np6r^|p#0iJdvmB)MNTL8_k49JUC$wZS1wuhU zstYDU2@)WFU*5vvsS9AZnnnGfRCuu#ee>Oq-FMsac6FjSyhEO`1H)7NND@MaOVEE{`UjpdnN#5=tGS>eG9ux!bZ+XJKz!n8JXc>ZRVpbx8fS| zoDkY$dPx!{ zW0f3eX@o2?bE+`N7J!g?x|A;RV0u1ZM()&L&>v7R)x=0o9SFl`Kyqc?HZ!T``!G``Wu)1Tm&WXM~!_9);oQ7VP0fJuU25}KZUOoifEQCJyhxbF3(nljw` zgl^jFRs8=otvwQnWFqNeK5q>GcugsUg53L0s*o@SBKS#lesMLPo?be6@aUN_ARGOz zudBNP9)J2h=kdM!mQNkJ@`UDavfJf}ksTWBPqgt$;}ZQI<~|+NoRAP0cEWC}>+PW7 zK*2q?xsW1YYzR=Uh1n*0=mL^WUV;}!N*jDtp3PQ5)yyd*>GvQ)G3-wV%40K&*KQ9a z!m+MvYkxWAaMTJXj{LP|cfpyj*m#-AY>A{vk(5ah(=onTm>yDocJ!WKgTHizJ~;4FOt~5rdJ`AR%f6w)x|TatV=wI8gKgi_}?wX|d=Pp`TbC z!Wx`LgMSa^PVn^59ek*He3{&w?ixwB-v%SQI_Xqkuj#!Tuz4oW-+AstWQ3HO2Z2HQJgmWS?upz zc2TEu)wtO~x4IQZq|dmOu;z_a6qPOS(|RQ!y%z;~-niFAorH-_cGf`^z#CVv0M}Sv z5TpUaZ-De~>+US^k;6ojB-E0$T60)V2xGZ!JaaJ0704!M-#cg;ddXy}KfLyq<}l~e ze>mgJ&JVEM!d(3t-T0&LEvtn>{VDnh%lPMt{nMRYc*b)!@+`y7kP$LX-laLWIT^Ll z*%7MD@H5H?A&Olg_Va+9D?_S{jld=YNELP+8G|r}Czj)&SkNnc0#N)1H{7Z?sNJU6 z;pl?TAQ09>@@n(8n&ulF9i1NCSt<{z{=!fZK~|}3@Z97|{EV+3fuZ=R62N**JjLYr zAsPNVTnPU1c0Ujp8rWU!>O44qFq`b} z8NGhzk(+kZf6&|8S?<1uUJit&`YVUGDQzK-zqGsi@N#K(B$jsP(uvgep2UzZzOOR2 z)XOrt=PTVkg9H87HX2-}=#PSPG}L-PO+9PW8+pbUV9h7U}e4zrGWBLgWzZZES7}Tob*ACHr`OKc(yLYDxpL^!kTi^cuc8|N=-JUwQ z{ZM&$Vq&;>WSoAf{xrSm%KJOA>9XJL&7kdpa{*&l{Jrm^-?X#?rWt)_+Y zc|!7i`QCCTa0?fp%)tSOwR)L@vBH7AVMw?35gZ-xuv;>H^n|DT-}Jh<^2DCW;i2Q0 z-LiM2ne{ZV%{bfr(VegFuVn^D=l8tho&)#p8HUuSH)b+_9gQA6dd&esiL>!@`W^NQ zk|8zCn+^b)r5(@Ku_zPtwH@T;a8zJ`8PGfp#H{V>kJEOq-y1Fzz#uRnJq%<|D10wr z4lb{X3)4pzcHFja=gqx)vy+A4vF#H(W@gq_S5x%48;7`02P(2h7{1tRrMxYj**%_-rJM)Ec^=oh{<^YU=A2qghR=s%+TuG3sDN=X<>y73SQd#u-Z8!%R^777rN0PZz% z384f-K#R$MSeg<<#Wu;+oP>}Fi4;0SN2px!8ocvH@e?SbaM=4L-|WKV`I)I3d-rB{ z6ow}z$NT6uC4Tz&?wiMYw(UzM_e@Og^|#mm6OMbG5c)BeBN4J^{kX$+ZH_y7)vq?f z#sF70AK;*R`{;0Wpj)k^_jH|{+;zj~f$7BBpL*P*ecP(x=xk@_@QLlS3qc!{RuO8> z#|(K$bA_lR2c3}nXw1i0lVRKN-L0FM5nvA`vIJ%wlp_-g+!go*8J&OIyuN{byQVn` zC9F&a2R{;TLuE45o^CdMsrT&Jwdv^%Gnj5Wvh?VqOBXlHV*EyP&Sc0FnkzwNDe0Ak zriB}CzPZKLZLx2oR^xTuSH5QJHbc@K@U3C6Zhd?fVTCRK;&s#PhcKb0r`J|jTjm*i zGoMx$;e(G@ryKX-!+zt%+R-BU8n-*c5h@AE1e2vU%49|7^}*Wx2$jT5uIL794ox0~ zm#ml>v+E62n7&25%vQH`c!59qGFp2B-K;1`0@zy33|qpe427H)%Tfzsm9kkHQOE2 zsVDUV^9$d;wXL2+97L8J@)l3DJV%?@@Cc=ywz-tHv&LI(e3s<_wVDNS(QOS2=%jN2dBl^yCz^!ZKu^j3={>)Aa`=Pu3{r!Xj_a1YwUyvAi zo#qZxs_=L6d6}qhswwbIi!~?&M20HPiDG%b9DhHFiZT@xQ2+uSN|hzR@q#y1;7wsu zi9uPB7X}ibxmw@0rN*EBzW&-%Q)^E=k(ujlefPzs5%=Du2a83Ww}uISMRN4pc)os| z{#)z$+U)apW}hcE>x1})zu*Od%kEn)52Ua07Y)yzc2@O7;ptKtdDrB z=JQce@KZ^QQYsr?$ z#8lO%`gQ&a%L-`yYI7}EzO{8;HNTVZ)l-c;y@Kb+W11VPOL;vM6iVtYbDtviTdyxyujMXqtW#70YjIv*lEcs17=iGiug?1`Z28$MeKcGdjwCFo%7jDOCXZ=O zV7R5TfV`%cl17ncX;~3u0S|3BprUwOG`99IUV^Lcku+ zF4qs!Jj$DoC*&yc_6PWQlHo>yUNPsE@jEKLOk;emu{hrUOG0Q4bD8-4pQI2VWQ~7l zwBvg^Ns4?%bEK%iLR2)_TQdMvgr0!2VBMob3YQytw@)DO63}<2puPvsid*%9y(Hf3 z1;l;QNwYKf2eZwq9H#0t5hV#1Ec}`XaN|hN7>fk`?)EkpaS}&faRkdg@Op8lzN%Eb zD)_xDq~6!{ae&)BYyMp(V&--1K8|IZ@4flT&rCM&YX%IRdWja0XKB9%<(9-@$wUV( zI@CdI1y0O>iw9m^N-i{0&fyAWhiZ5-b`fXJ4=3Xg=Sr>&fZ6xN%v!R|o$MU&%hst@dF8*rEjDshr9S>xI>gD8Ydkl1OH5$7y8y7-7RF**pbQ7E*6@Vm%wu=awS zBfSICbuP4YgSs18z;#4O7;p)EUXLkh0GYB%+HagYE5XXWx`^LwwPQ`$)^Gap zkI((r|B7?)TZGVE7|Y~y@N@JGwtuHl(AUaktA51xuOpXR`UOceHnSH&_+)<^xDIcu zeL6-R!E!Yq%gBuCt$e+Iak{tE9a$SXbp2%PdY`(z58RNTv%c9V=(>;pj;Z^w9dsXW zN8LvR%#XMQ#{rOKKBBqO5he+_b|{rIEh+s-rdZYqpeNzcZ-p>~5#icBM~FfJl>(yb zh(WNiCsL{kR20r{=xlvrO%GiI{7gZOMZ-a_8&|`IF*1w4A+e(3g=7n;{Kk}mXY@gP zhmltijIGhp-uh4VqzZF^T!|Q26|~ONEKc*J3flOWMuAQ;AMul&FDSAxMw(lsz--RQ zwL}nBV0A~3N|NJ|0JU?Iocd+2*BeKY?t%(?Fb*U-G%CRgojlgJxNBRf9D#ZDm3Ntg z`hj!b{Vt)6Uo;Bz?TBCSpym!zNeltj4dDGix&XMhB4CQ4KN$R5z#Rv!bxu|XN-0D{ zh;}1ow)HB~1DY4W4P)L7Y^&U;i;{@y4SRiH)cJzmN>GLOAI7tuVb>Ma|9)h_dFFUe zrC(fFdm$*=!8aOFHvkZ*rVDr^*EDqFO^aVWN>8z;Us^6~)Rj?!8^_lm7?6=+y zkcflzZ`0f*cnAJlcwYIHeqQ-s8*23T)W3-DlY>4)us=)hGT$?gc8#5Ee-To+j6A_M z2z7EAMm#e5AuE*71s(xKL;67NC7;iWOxj@QgpId+=662;Z|VD&`uAw$-_73vd9)Ef zxleP0hIUes`8`;g$wxm7sBngN7#1cBVzYWR2$%qzsKI&>0CdcDLJ${_)F2xLImq3F z_`L3R(negWAMgTvGTQSxC?W;HD*uu;EO^=u0{$q3U9Wsrx8ASZNpqKeivFj@D~&w; zE98x|lL^fUGNHx{#&HFEi374h%-aWYT1Qs-qL;JNLFh+OX~kRm9UN7VqLCINC(a|YlXH|unmt1BqLM4=L} zdRfuJV%By5>d>zuNQXV=^?UtUIA7=qQ|eH~TLnddCJNO$2Bu~f7S@g)P52zlH@Eu> z=jf!T{yXPBtI9k^c!@s1E|VlFKwWw}Rahp#1SLqRkfah7XFYE76_WrsE-(es^x#$D z%wv7k+-BF;zp^vuQv-p#KMQ#*`b%Q~6?PCnT15_Dh@w{WI*~7ZpmShq=HUG9A+K*O z&~0;-dfMF{SN+NkkKOBouX;VxMh16?)aj`ohJdnDc)ianTX=n^8kgw3Q1`0OkFSxJ zTjxik(Wo~lz0K$Y7&i1t)KydUFH+D0crWUqH0p<`#wX}kaXgdc1}zl#GJydeoPfTp z79_2p2pSS_m*C*p41L9|?T}$&Tt?s}Uoc2WFd0ll!;ngvmmR?t;1ygLt*CEnJFh<) zPG$CGme$0`WS=|fi(4^N2JT|pJXbyo*eTC+CX*c$)(*%9@-z+EJV*bm{!txo^P_;b ziG5-%GI*XsJfDJZfPIi%CMEJ_EnTF79H5F2ry@&G3Gyuv^Fy8mcv^iI=|JFm5rFFj z0l-kf#sr2mB1!A;Hu6L!f+C|QjqqDUB2i$hvpA;Fr&c1RpqhikG4QEvkvL{(ksL@4 z;566(WRX31Xm@73s3U0n6W1?OGi&ta&wu5*(>t#pJ8&c#nVi@Th#7wm`eqJP&krE8 zjDlZ`K8|}tR0{#gB%QImTQLjgX%4=?mDq5VK3+YvxVknLOa&pgQgC{H_1Buii83y* zAneO9NAZjWhXuj@9IJq=8$WMcqJISAMBbpq)2XN+3O=t(keEb?Bm+DL)M6Xa)YInNe1066M!FwNFqY zDc}CsY*kpZJ0dCX{@Bb2jlPo$@S8LiD-G_Vc~AW*ArdK7rf@D@V(-McbX;>sD5Fut z-2pd}K6gS!FdWk{xrZ141huGMzjBs9_5wmI0D&+Obmwr16xHq$IEUecROL{5LxaVl z8R5~YNO}&4~%b5tDV~q?tShl&z-lhfal7$Cx+5l zPdL;bof+S@uXEy1DIN-?{L%em*Q~&J{i<<^ovF#-m146Rv>-X54+;jOn2YP+P>bqlc#Z>z9T+A zM$dZcKj=QR@5d@%ub0?I@SQ%cIennUXKf1lxWSeMP&_?F5$qZ(K7;?zHBHbCNRI-u zPlv{{)D0L;H1j#ILGXUY*x|09F)~51>}bg>z2=W%;MJ^YcAwW*%z9vV%W}?R-4gIa znw^kk@2+1g^iIvJCEc!9{*gZZD@r}MIIp}_mFVQH=jva;HA;x!Mog!NHCHmssN{1% zv6F7Xg}^$Lmca%9Pmu_#uW7->(0v45Pu0VU&>psc#aRek z9LyK%PtltWLYfux?dFP!ujo%4A9~MBp@g_E7*xG^{^$Kr)jzM4&br;H|i#($R z)Ffka#KQz8QJ5Ays~09k3Qkk{$8Vk&2S#KL6*+V@0wWtU=(LoLD&RE$regN zAJJT?5b*Q>ii|nWZHgoa0?=cNB3VJ4L(4ojuHu@8E_4M{5U$pg41NW13HyM3O-`FV zM0%*k_uw>1!z|C|ys!sTz+8d~AYKyJ{5<`01;@RP@oV|i=ARi{8%&gg%y;Ey(?_>; zmb(|{z~w&=->3h<&lf!Ik|RFydd=aXRDhfv<178#y$=EM=0T8aCD3ko%rQVh5F-O% z@nS@vL|8x+Pa<+GB{(h$xQN>bL40XH9L6G+fE_O3N_eT>Q}_~{ zKFa;{_};iax$pE%^iPcS$rxZV>+L@#52JmVCxqR@{*|$zc|sZpmq$i{xhnw=B)Z4}K@Ge>t7bnIRatvG*k@j{%+B5CxWFj652Yp^Rx`xnM#B-cfUPvgKky%r8j})El zom0_xDM7z9-xT5r_OFG6C!IKUV<;0Zeq&*dhisbyHRG8@Q*IaO6)w*P6`gEzwrqH_*_)dL;gW`>O?4oa30N2MFyK*(J`LmTD;{FWeWI7B#r>B zi$4q5e6k|RV5f2`Wd(Bu*9V(0MUZzir=|g70H8#Q(zFZ80D3Hm6!H7<9-tp5$`TlI z1R>^mcLgEkd7@xXzT8=YM8TZb--(HWR^Ub+iZX`+V^R8X0&{~y74`)KtZ}J1zxNyj zutqoHGb(-)pK;)>PxIVg=9@mcF!xn{$Usm=>--1%R*xOf_vquLbL#2s&(o(Z>jL&O z-v5L2TgJYH-)Hm4TsFm1utY2Gw|rQ82g*G$h(1>_zqHoYwf)rbWs{sMYb^mCh;Cl8w5ESzI6 z!ZFS|oW_ZczRkJ}>iabZBrk&gX%vK_Isa99nN9Qaov^EAUi-+M5N9V0LYoZFKf13O zFud5Z2tHZUU&nPhoQyEEYoyHpq#}6pqG(_*G;zimqcuVqx|qQg=ObRPACE?miBf9) z+>IOCl@EB>aPtG3dN^RN)6b#5mg6nuSdO%jC^@We!C(~9Wf7SYjly+qJ%K}s!>2YA z29_aQHDA+wxW7c(BLN@mECq0cnAyOXdv9eUq3?Zc{EmZnJwATN{O}O`GdKj8$HyMn zga5f{;rQ_d_!r(Ca6NLUV<5vDa_9dT$BMVZo(%2G{$nVEGx|f#x}-M$AL8Kp{rAzI zTH0Z6;?KQE|J~BwYqmcP?K%d`F&!r-Lh|G(&F!$u5|tQ1A3Qiu!5B{<&JY-1Y#GjA zsI}1l42BvPass4wVXHn`8ZQGc2?S!rRY;yhxC0}ds;2p)QKvJSkE-dUGvW+)gn>~J zV%!3!Yeuhq8UcFbJog=>K5-(orDR?bvKYbQ#51&Xf^g3W1Cu zw*4$(3jH&V8Rr!Lf2pkeN~sF}R>D`2)#s|u9^6_~_WmdKUrkgTt7=5Y4FW{;uW3P} zBGXGn5{rg{qHJy!-Jl47lMiGm6Nr9`%LuP+u-*_w;a)hC@2D5{Jp$3fb@u|)-e$LH z16$o;r?P|E6xp^)6iHH+^dD1@nX>232*?IzJVg} zs&b`I7PBGF<~<6yKsRqW9p{)g;0FF~PUk&$wTa2)ozpRZwvjRN9nBvKGDhuCESyOv z;-V}X)%QJ+IU_)N3A0m9p#|c0qTC#4WN#FA9}xvv5M^M3ZM}J``?SiIw>YTm+*07F z-d;eZ?j7qL9jauvWqUe`DWo3C7xIAiL%=Zxz6oBa5H=X<wy zfrzxV*=?;1+z;YlsGDgCLk|PSkFHHe}Q8>gobAE>R?;Yp83mZ(E`>(V=FWc}ET#5s2V*JA!5ZP&SAvS*PI2 zfO^*djzuPBA&_;O{0-Xm({eeJ?(R-ghAi6MY1>AXonBq-HpsJ$KmT&GQL)G$Y<#}& zJ;!ynE`QFCog|&)ce(V-m@Wd+M}RlL0Ea~aipW8M1lK5?I%6hpb(*)>sg4S>)eSIA zHa@s!Uk8<(fYGI#C9)_YJ{bh>Wn{k2rBYnvsm@eKKIch#65${anCrrJZ6fTg1^g84 zx*d71`-*pMlxuu-HEU!D{nb_E8ABV&kSFee=KP1V5ts7^>DMjtKWesr7d8&XzUY=Z$_m|m)e zfPh{x5!5I-TxHclH*_5H|o&z|d>^xIgUp*2te< z?fck;eGlIHi`V##F>~Ao$osY!xvb$^xAMy(f(j<4oWRA?50&G_NFvRwBoKsAF*~(V zQyJGqkz+?D#AB%>tz3N`6#DxMrM~{+tIvmb_p156 zzP#G||M1fd13%V3d`q zL<>}wfcg-U^1(rmdQ)Ho5Og@I?P<`iy6*#gO*joe(Q>uS`!b@ZB$z%YQB;Q6U>QJ+gC|1Z9Q0AK$Z80q1RK_9!?D6mh2!ukFQcbnZF4CgD`+uI!WZ@lU_n0r~%mis6}@s$-gJapLj=$G;FqS)U{L1fnn6_KlbIba81IVS;_x4XhO^3OmG@v03U`W8S3vtg|GqN{0T=7{tUmDYQ_t5&_AZ^c{`ymg=Q^r)_#PbulNP_L z9c^D=I==6vb{TMkX8B}K0)dPukn>HZ6mX%g5NfI5jG3LlyG&1+eRV!k{RuiFRx=H8 z1$rN<)n3k*x>QwiM9To{VM+Mc@jeDHwpHYKA8=X@((!%+)pXCwb>nx;-}TtS!7p(a zI(+lL5`m;inSA*rpMx<8z8ai=B_hd? z91iT$;KYUKo(U}h2dF0UD`Wbk<>FjeB&wcl`y7PMjwD z>_(W_n&trU<-Hy(BhLG0Y#pD04YY92XzLx@HZ=ICTiKb5RLaxAYUwxvf#hK8#{ z<1;tC{^9XE<~^y@v4EE@9A7?`KRk}g%^3GLu^fArgh`4NfNM8Q8CBy<0ES&bm<qk=LZF{CQVlnx6nfL?NF-fI=Od{|qN@PO#fBq&Jr121421nf z71nl12-Ba8jo)#wJyN)-qdGQz$9!9)bW>M@q;8ViN5)b&2I$}1w{Yx%J?!rEy*cx5 zyFYnTkxtP12Nr8Lmg-;B-mx(}gWvviGK%LBb_ui*~PIl}#VHY!L= zIBSP`&#fE^iSF)HN))@R-NOTYsdB2Tpo&Q`kuP)ri5_f`Y)enu){X`Gv46^cyNo6o zxY^blYZDvy(>d5r-vbs|tBuxo_5JmJQ|3R`TtGV{w7HmsTzDYuA=9m8!1IIiMz4mb zA#;kd?ApSGR%zaBx^Z6hRsea@-F3!YM08R~5v8*(sL?-<{H!x&@FvrgPwfSVik79JM>{DMyO zOY`>U=<{fAr5ky69+k(+-|26i?CX8%qWv#D-?KmRhPxkieB1pa`y+RK;OP9jo%K(*HWU<&B>2Cl^A;AGU|m}wP+h;+DDiGP`-jN>vFEMG|{)rGd9*)npZDgXLGAacpMmoApUyQGVb( z->Cc`%>uQbZf>{q(NqZmF_-{BTS2747Rt}#A;gpL#KS@2ChkHWGb#+^3na=|kC)_H z8(c;n&iU;oPEx;)hav1m4$i6m`i#kSrk|Pf>;;`~`?s|Oq#uI}f>dP51d~Jur4lA9 z8Yx8pkIS_RDj2kw*E!O3{emF_gpD`ZNkI)YSA*K@!O+rZC7j@1x0)7cfsu+73LGHc z05H_SK)6UY!WQ0xxa?Jw&EP3*p|=TF*x#$q|6hFvGNn;M6Q|abwDNg#M#tm&0-ra2 zAC*8rvZPQdN2y4~**LZe>spNzPYc5(Ae3<_AW+B(r~TE%R^SO~CXDzNowYm>n8XAL zQY|Ez0mXn!07?k-x$#WEn7n#_W^>H#e#DqoS3aytf7qN^;Frh?V+@GuA$I<4F11J^$|P19$Yw-Yasg?i z02Pg7Z=7EeHo2tBFUd(np)M30w@#Y_=^Bk>dOqcVBooVj99TbY9 z!>17H;0iBkG`u3o1#Gq`y!qxOi$eZgRzvSMfHTmII-16_Wo*)gUyl zWOR=g*eUF9PWCVF$Z3(a$gYm%bCnb0g`F|wX4~je{fnLc&RA#v0zEg-Rf_fbvjZ&m zj*EvM+^6R2S3K08Ek66u;Rk05g|Uf)^%3p6xztkalZ&;Jht=fw$1x|85c(FDC2sN- zE_1hw5~xXl%s@&R;M_pi$7~gh8Tx-muArN=d;Kb6Z1H+2sA0j{6?#4yN%(sQ-D~%> z`S)#OS=$rJ&Rz9?X1?o3CU~wkeGA%Uz?27e8RlLCe*oLYa-@?Ck~5ko1;rNKg=EMf z$l&Sc^8k>)KuK}bJ7U#2acD&TA3$;e7r%ZPJ^XG$D*dFBbQC%|3JMOePTZpylq3jf z+nVeWt^)LNu>@S~m4PApKe|JmE|06-?^?>lrY0wL#xjd8f4j@$>J0WI2Pa~^eeoSb zA8@)ww-Sr7oZEd^lDy&H?3>8t^}~^*Eg5uxodq^) zg%J9mF;|ew=AzD5wY&aB9Q&N!{w(=d><<;wZ^3v8@Bbe96t)jHVlDj<3kK>!2%!(N zJZU2bG$_XgJKvNoV2v33yhhGw7`aLXioi{PKw>6hLMCe)aryEh*zShPR>2~qbDR)l zZFQ05kqD&z7`?4_Eu81T@k8j8@eWQ(8OK-S;|mC(<~#7>D=iFn!8=gO@Et(ILS2~g z4jk~r$14hWs#4|ecwJ?G^$^QnTdO}s-=sO53*g{^I!#zdQSu?(QgBj%hP+G=1*p3h z0K$GIt_3`lverwYv7(@Ugcq(u?N3uH>)Hykll4;)0aew~1mDM^No~6&J6)@E|8J0mnSOTK!vI)_`tFl6B&8p1&_zC#&Bd@XyJ4yys)P!UoGn;%_!IpKzLFy_5p1OLN9yy0kv+ zco7g~gi&%HCLQ6E&Y1Xo*11W0P&H;gR_^JC)-AN3>R~^-egyb>2x)!y#8`fe>7&a&^Y{E`snN|ewvly_TgP(gzA5tu) zd{I>qnL}qfFID+Ch3VdwX|$%#o@sg+o=*`g=>059LgeH8z1xw90N;^Pc_yy4Qz|P) zqq+MeB&xfiVJyw+K>z_X!GtoFK3D}#h*3MJ_d|MBL0*88ap0Fd+j2(}P6*yLM1qJ~ z>r)X`QQw~c2!Ug{@@?v|csS+j9&{fCNQ8S_ff>G4jgO!E%xBJBhQTt%%4gYg+wF{j znqX|!h9lK%0iTrl)jr6ZLLP?oqZQJxY#1}1pTA_}=YuEJ&~zLq&rRH_>V-WQE9xwZ zY~9#F;hZ^qK0W^NW#q^^4n_hILU@SQIig?=H94X%B-AwJqxe3YBMKC-<*l%2phyb& zZmS^>421N`X^afw^s?4h)9VfmPfw{uZ*T9hBjYz{)3=rOOwV=n`uZw|4h){0WI63{ zS1jZS1=_<0riTu8cIFQbrsKg#usw8mN6$0@gpvw{ZK>3c4TeVo3N@91E2~s2|Fp-1DgPJmU2m#{}GVXxCicoUWfXGDpMW}`b z1YSUHYIbU&6|<||MSs2nYN7L6kS1@Gdb6q>2Zw(7%zP_(^2mu?%P^d`jMCDQt7s)r zJ|T6aTgSvYWSn13*n#tH8~JNp%cWvW5Q`F%g{Xq(gSdumlC@3OawQ<0WHMO=7!ey& z01MY}(AufZW=>D8!^<1G>s5?;jI-qyZ2*YdL`eV$Q9%}kv+M7+QyZnWCF3p|0&99p zrP8)iPcY}p=K`Hsha;iW+LbKXA=RvrD_t2dS?tJgRSkwh6=6qZX7@pvRwHAt+ke|b z0$r3w2Mbzm$HE;Kw3BZf4#fTSfg$m0bhw{W*`;?JKJwtqTOUY8_DlsMho^TA0DWEk zV-tIo?bDX|4mBivK0Xce5$0+Ai#Q*R_Gf9$(jRhidH?6=EqZ&brT_DE73cMy#w9k* zE|Us*mXD$%OeqUtk!{@gA0YYC#|=D0e4G&Dlq>@VQqwUR1ur`A>OnbK6WA3~5V8;qXR)|p>J6SYDHdbf3V0W_cN2$Ts1$8?6B6w_UkhSuSr4hCGg4xL1=U+zn% zLV;AS(5DX8suP1@CL4DoQ(p?aR3l>vQ!juZpOrRD2`Pqkzj`~v;b7& zHGxHWN!}TgS`5Ia5w}BRf_N4f??~LSv17nAlPHmq#)M@JA^M{6~CJP;?qPL$N^Y{ier*pA$<@lND&U7po zHB_;7wA-qwan7{qGN_W-7ERrkooWo|&3d#NwU?Wr3 zaH8?glnZIzcUmeLx1tcr1r7g&^S}YD3SlEh+a4l8(NOE8P$g%nPwKuij5{oA? z(Lj){)TnLs_1;HU>;J2m^Yis+ykCmkra4p8PAPy`893fq1-O8yozc@xMDLY3Vz)Pi zp64LmOcYKxdlNe$_9eZa9rB~vlX0&XpuD~QoWqecUL3Inbs%p=MLGe5v(i6c&mR5> zH{RI%h%=}5;8*N9b+VZA178-%Sn!h^dl2!=zD7Pn4iOvhWgP-YCYW1dt*7uf0Mvt%ccm)fY4 z5GVY>f7S_JNWk^)?LJ?-aPtCVGl4gZItbz@TfLB}^v?sy!<@(>; zbK{Ylr-v6hKgQ=+GFKW%Ph8kPv{;;o^(QabI}dk6qPc`h zS^xIMV-L-wvkL+LC$_2i?E8B?-e@|)*L}T#>%K%D(qbxAgin>yF^YJ%ruf3yPtO9>!UoFJosA94^AWf5X!kb?*t9t6m$ z8)X%il_1?UFt25+{%ktiSMG1Sxv4$+`*v0<9RuT@wq4$g-+M0gHd746oPRm1s9;lx z4N5=2p5f~dG2#9YZ6~q*MU(}uPsD_SLkFzMPtfnPXE0CWVJ)OanT{WUu;gsUZZlK3 znkW%gjoAwNP-uexnV1s53`KYfK4>g}d(cA3Bq5NZkxfI1K5!;&g7(nVNyfYZCq}43 zpP#<|STd5{mtN%Z5dhyI>5m!EapIoj&b~MO8>*;ZMZG3?9P9-z(?{5+Nt&F~BIziT zsZC zYUa|YhLwt9oDs+BN2SM}ls z%^qLJ3_U*a`}6Z_AGvn%Cqo}m3kH*z!4f?lr@u!9m{9{qPF}giMW^cZ4#@jA?2F4J zL*Ajad#EUQDHAhPF%4TXoZNMh~oqrwU9!TweOa zIGBo4_4*K)iepwb%@aKn0`QKJ7}L7X&(E(M+cVnjOZh764VHn!r;5iM4sD#9Eja&n zx6G|i(D$J%f{jb`_YjZj)4KnSQIUG6Ai50%AiY824f>fZ1<_Vfpdy?e43tIP@NQ;B z70g4i!P&ZLXRX8RClf+t(&TOx7(?s;h#L!-3gz(n@`YlKr~Rr(vteY5aUO9aa;AE- z^wB@b_x2v>8M$ufRINOd8z>aFmD0g<;3U14e)L**=lt-B z1bz#UAcEw2;BjX#H%yy4W~L#bLmtER5R*lurwjxU0Q`VpQMNTvX$5L54%IY2f=vY5 z1Ac@t3Sg)n^ORK8TNR9>3E9eM^UdUVkb2Z`90^mLsQ&G5r@ z=esc=$4|r%vjXVUF#6#zxHZ8ONT3vp_8;%tf3&a9Th8sV7bn{J(Dw$wn!|H$P6CLcXk{Y+%+3+3q^gwSl3~|^oR9Xz`3fDd$b7H0quk_ z#YQO{cU!H1ys^Jq_I=Q89O%=ClsCKS#)8!hphh>{0`RK^6_=rD0DuJmYN@#;G>;6Y zmdbmg{h?fBr%O6`RNwtm>0ET;_)6Hf=yYm%Mz6ib*!q8-&j8dSd}E%zojpT>z`l;W>)+rfl0QJyg@^r#|&d$)$=Q>~{p{-`{5&>4L6 z&Kpm5d=h7gqUb%X28{u}gGay|k%>ZO1t|Yau;X~Zl%lS0nP+T6!LitaGJSKkSq)(iyVH8ho#v0wW->kc~}Siuq;x^ zWPhZ|1oTsk>Rwy>Qny;nb3P#2$O|gVlOiAsfDHUT%7m1ciGU0y7O8Ax^e|~%t1f{I z>R`xl!Q6E8sO>qQ7K5;v+W$b|QpD z0k4|t6CV_nUds$YnmUL`sl)h+luc%$U0}o^5^$EmXgM4l&9X_$klUmerN^NwLY{$< zq!p~4fTG2*1l~8wBzju!=wJwcnT$um7=HAtUXRm}EK?QmFZqaqs;>m`Uqg3QS?%CG zN^*X9X8(Z$Ywuk<__yy(rV;~w+Ef2J%Hr9TC!ToXiIvB?)O^;I1>j6^S=>i|V385T zrg-~B`Y)Dth!ODir(4>g)|R)w2e^^V=L2pEZ+{2aNu1s>mrS zDuR`F37EnV2@3%N`SF_ZIEh?)Gx0Kv-AXXQ(q@id)lnW|e+ zHm#e&hU`8@Wa1+!(oa6Cd3&i%$x_M2W@QLR8K_;&m09_^NI6~E|=ukCU*M^?NCdm-vQivog(rG}PSs}7b20dFdHlrzfyIDjqbkGJ+Fc3H76IjD`uicLPP-(go^Qsy}x&t~g; zebtuk5ri|j6#!|IiTUfBARpb_IwvjA(Jy7NC#$L#O-*R8`y5&9CX7^j(hdpk-PxJnk_rjV? zc;Dvr&(Z&BydP~?_LGkSwz#>U0JZ`D&Ihdf6=ECk_D|BUq76IMXh%6_$ggYeH23*1 zsD?rCPpD>2$P!{YL-sjflD39TxorkKMwHN#>$}2Uo`yzIxIjd3)3ViOy|+m+4uQoC z$*BI4ie+vTYJIFV%N8ta+%M=an}l!YL(+v4EldgF#7c2O4nI!iAF?W{>* z6ahdBT7$g+txP>e3|nGcfSf8wQ9DhTBw-`9W5@YI(0 z=Dv~T%SRS(*0xM7y}EB-Z`q!1D(>kshA&*4b*$SJdrD^mB%@u_?Y6;}^>C?bcNViM z^-Q+PGpcvfxP78}7m>h>>fN*I5serlz*^kXJIkl46U8E5!sAmgw)_D)ML?F@X16vs zq!aPFs8O(s*eV}fuzLnc!yfs-O5F!%3Z1i6>7M-TDT0R)cYU6FK!LWW5v<>2z#=k< z633^57?lnXmEF@G)kp!9GG1?nt^L$z?%lKZHtxx9W)I`N=`Fm)tvn84xXZ}<(JP8Su%WWV50UL5VAV;_DOh)mK z$(vY%mJrbE2E8F6E}(@}G#eG|sRPsTcx!i!!x>Jt_6|*-@7^}fcI6+M-MnnW?V7yJ zy>xi`7A!8Mwc{Op0Nk)juW(?#uS^jCLWX$J-v*R?P_~e@#q?c};2^oFFewggKrXEq zdj^3HWJh&#j25?)cVQLFyus5mFVRv{<#KzhwBW0j^tiWLJecKt%3dNlmlz46^CE`5 zf#mDJJvx9t?kVo2H{;bLN&BR^l_!7C9?m1jwhe&)i1;OYpLJMqoy|{m8UYv#h>}ax zj}7RbpkEZZ+@AG#RF7f3Ns>4-UT=n<`TbsweW z!zi|M3XuU{R<;FVRJ0G0c4_$za8Ld`cI@Qu#SY}x7wh}5?l%m3b!Qc(1P_O*9d?_A z8$i-klu%3={+o(?00!+SMxOBbnZkjE(X3~{_anavXX}NHf@#KB_FM@N^kXq^L?%RL zdReSivz8Yt!HIc0$3C@sR^Nr=i>9x%#n$9nmZp=v9nCyGYs0*?ht{^n{?W~Uzqp|} zf9<}J*4gv&KSI2BR`@fTFT~HeP`6ju5TmAeimQYdvUrHSqFP~;sufH+!e=}lk8vy0 zR?VBv1alcHhlh7e-v8PAKe1-j-FLkDDhvMQi6{PB$OXb&$GAejPBjWBSj`#~)o^=~ zkAM=9BD$|EW1LdO$*J>z4*WY}RYh*Au=l{Cvoc+hxj`M9h9UWcV zlOJZ!;F&Mb_tTkw(eQVCqO2WldC`6+;@}ti)dX)r`4xk9(dBV*6{wS?-$ z`hXzvRpJ_yiA70KtWCyZtaR%O(v9INx9YW?Q}fZwE;g5C>(C-`skR@y*hW4fV~tRM z7IS!1a0Q5V(kn&#=NR(0GEfS4vM&(#&u-lnWs+P={#z_^HP~DtGm_@n)>6``K^iPl z>M=o)oVlmv*3%zKs%m-iN3#&oCQ#PWGnHzqW( zj9uoX^o;lqLfmk)#PQ&C0H;d$~Pz) zK_b+o07Di7P84ADOO&H{CH-_Iy+|+UX)2sPsXsxF0ouF;PBaATkl=el;o(NXc*)H0pv2 z^1n0B$?XPtM!Rud#CZ7>jdy}xeH^EZu}c%~s;=z3$}%B{Z7jy;D0~?)q7@Sc*~|=b z4Ba00s2;&KYQ!qU5dAoCOhV>U-OJZ*%l`@o`RBYDk4WJVcjRCE1QmLf?vx7W>yAo> zXmwyU-`V=IM2zA=v>~+(vB+VeR>Fv@O_aJ)fshsJgs7ht18i6nq=Je!PW2EaRni*E zqD7oT`Zz2Nva%B{M{25jUN&^oV$=@Kc@P*^}1Tc zfCZd3tIQ$DB=St)5x^=MT1>;(!ED7X_;~p6W(jlM2=8x^MnvE~1l4IZgn@fGl}gXz zX>rP#$V?`#Tef0eL%61OupL)3|Lbgz7D?5HYwH_(eh_YmCt5UFtm{MS+}X)k#ri19 z02zQ+@IM0Qqzhnzo3WAKRXs)=xBRTyV6W|K@* z{x~p38J=Q(d<=mR$;l4m=yxdvJQH9A%x56J)?z<$E7)wMMByfoZD5mOzu8^E*pOu7 z(gZdWraShwk(fhrJ4_Z9ZECxB9l1mQ71r#ZW@zct+wKi9o!diCm^ z6Sm92s+$v3 zaV;EY#pKmoMpZgi-8t3%mihzP_UmJn zyBw*ybi?3vV;gT-7K?Z0FIZkv%L1X$Kkry8-o7vZZ{s=O5;CN)!kvW#`y9`K7drI} z*7G_@Q^Ma7+B~YOd@BZ4=&cJ`MgYJIUX;bERS7kFF>kv(@lB0czx%n*71@l~P8a+3 ztyB5Gm?TDfrjSqh-9m!B&$~c{8f2OFxhf@zv0;jb!&WrjLu{nM6G+NRb#syoCIQrs z%-UY8Iyby^SvDB28|d%vkH-Ju&i(t3{>15aIbF`^aM$vd&Yqsm^vb#H&HPSw@5w6~ z>*|`lF0~%-fCYemi07aha(YJea3H@ylm`Q zyg1~INXFERKaVO}7;Pa}UgsM7}Fug@$ZQFy{j4D{K zQwHHR54-Yru2|9E>32?d4^;LIew~=E_wD-%@9XZIFI|`aC97KLlsA5QgnLvR<51z# zyoq;#3#uWbw^bp1*D%OTJ_r&h7D<^bqgV}LrGJ=>Bw~S>s=BR8q&bOOp79%)ra?_I zEEbKqyQimfmtU5hch~*Tc4gYyJ2M~p5bs($I@UQ@^ET^hXi97J{R!U0a}b1j7}WdR zh>gf(E=udcf*>7OOM$RpuoaCHk{z@!VLnn_4NzTQT^9+_qY%&%c4bBlyntE_YH7@t zlKjTtSjs4cfBA~bbMx={#N}Oc=gx0y>&TkL@SACrZ+$2KC!G&|Jl&j5;u#q#B-pKd z5rp8{rBC=VUuI^(|6jubz&|NT$NyQO|No%Q-<;g#m4PL#HKFQ2XjZmV=f8O(o3q|x z?d{FqjdlL1!XNk|o`X7Q(_4Kapiqh=&^n7qLX;#O1qza?A0^$)K!I3V5hoCVf}dTs zc-Q#15~<6&7o`&4+?dJqU%tF@;iYS?Td{L0zHQm3){G8M#iw@0cZ{sOw3lQc0I%dZ zuz~}c^#(g82MweB3`_>JHABRw8)hRmo6TW!;LXOTBB@z5bZDm2RyOuT-LYpLfBKHD zg*}H3p``iuKl}lG81&iF7{vK+$o6@2gYXN8_NB%4x98(qC>!m+2MJUNK@AM)0};HW z!%igY=FAF90IUq@O)(V#xTNsyfZ`D|fx^;AI4sNIns801IvDW#ydGJV-Hmp|Pr(1& zOlhTjOK;iuExBt}{B)zT%Fz^$wK!HO%%ml<;` zgn4CgE^(R*vR_?E@9~UOnTKier{5zzZ>Ggcdko-)k}! z)CL_AQWiLD@^Cc385_bVaglvM#*}Qil38rBWwMGnK(RWM?O?N^jI~x^GGm381tXPJI+&t8QPq+vF+ z!(M%NiESXE)z-)sK8Kc|GL%E z!3aQ;KPw|ZKpb2uqX}fn&hI~*fxXF3yiOa$X&w}-vaak<@14otgp5u%)9I#FIeBOC zh?nlMabKBazn*;$l3;t1vnP^N-&VZq%ZhjUT}1aa)-oe~3nXv=TIYRwFZ#A+8GKl4 zN+CtO)-oJGcLQe@z8$l`i(<#?t*G$&z5WVMg-2EW0h>}y*O{e}SS%g%YH7U6-n5n7 zm%C;~ewgU&u3!K39Z{U`Z3}z&NxZ?oMjpF0hfjVDMO6N=Km5UvMRb47amQ)g<@fg+ zC?Ctl-=oiS*lku>!tqmbDWdvgpy>cHadHdW4w4iiTHY`p@p^Ias;c@)ej_uDl?HAt z+rgc8FTZy5BO5-_as72aENv1$dGp94*HOMr-d@@eAt!?}2QP#n4oN(p=KXXqnTJEw ze%Zzn%x<#`gPH6Jj?y)?aYn^&ip8#MN4l~QxsSq@5lus&BQ2>VBk@Q)R$mvbtqBH< z%UPuao52X<5xbkg5^{#EIB&+a%%3=IQ>154y^xje!q*`L_0Ry#Fr`nF?qYpi zG$LE&CT6$FI8!T^t@}$eWx!>|C$W^qqS!6l!DHa9jKLMT>SV_d>Y zlt5>_go4g4UAA}6p7r(_C$a2xly;wf?eaA3lV3D9xOkT?6L*P8_WRi5;=b`y?^|c_ zzP*R>c(536sF?$(K?+vrBT444p>8c49LNM+!O`xWtUQy5P9$VGkxHaAWB)@zuZp}{ zN!5)f0O8?*GIvPP(=bqArt_4o3%duA;q%{XX{oDkZmz$prLLZM%i2o^Tv)$LGfXtv5(W_TaY@ON#g6cLC0UD?F+spGQ+U)ae{ zm!?yalO>%fzr9>1I#k^AN7+4Rk+GR#pR3tFpW26VRnVWn`H#xJ4}JNhgErpaFc=I4L#nC} ztgUw>>lUt9+*>Ucr|0Oxo>}t*u|mgCWc!)c#yI!D9m>|SGcEgRPa|}u*Xe7Lw5x(t zrF7-FoeC3?gYop;O;Cbb`Oz*h^fgo}ev;0->}aP5>RC9k%Z~PgiSOoK9v+@IZ+Li~ zKO71KLScWo#<+Iq(7E|f4`n-shB~rCPe!Ukkw~aIa`HfNx>DiY!smG^m(GD=I3B4^O1SVaiK0;jwwE*HKkE|1IOQ&q3qu7pq_Pv=Of%>}JqEuBkC znY5Md+>y<;&x&35%w3+2x(9D~v@^Ku-f;NP3sp}Y;yJx)e_r{e#?z9)r ziVbTYffs%Yz@O(iaDfNyMHTs{(N0us76sWwfmv;+_sQf@7pfkNVS;fOMhHvQ<3@xg z7kLm>wE}Hee~gYw%&G-5el3_zTlw?(mjYjGzWcw}S6#n~eEa#DkF~Dfu>+s$sSi!w zeCa#y;QgVo;Qf*86lZx8D2Li;_nGYu4tU-r7y{sK@-YM;iYL8_EF2T`6ib~9>sAC% zgcBebbUHD}Q4@9soc>fSVZ*17q@1RbxU;5B!xlLgsJ`swk(;l0>G7*>IPdSXEwkIR zeciizvMjcsXM8Eo^)DZ zL4#&ktm}vd9(HonH$Vc5B3ULyeGh`yi6@Obeqk6%BqEVSbE2s+9nm83)Z7?Z=jPC7 z`iW3%pFR)Xg7YZ)j-I{hhV!1vwu%WY>=Y9!cO;!YHJTd$w~$|HIn4=ue$_k&DzO@l z=tC-5cF0M>Wo5F2+<;V)RIL%B5?ga#k%-5G^mPe*m7<=oCzOh*YNApJnUllJ{j=?j zAM5}AW#pzSUh3+4{Hhzye|B!`tU1}m-MjiWZ=NTnbZZ}*#HoDhLoqF0lRsSFx~jQv z_8I1a_WL{RkGv1U(4o)4nhYnRTDmY)i%v^X99WBf8`_{KN55SdLditJLgz@}or%II zvPR>EyOo{4A>H5JJ%4a;VSPt^Z){@z>dX5EE?>s`>g!iEZrwVuwYqwBeN+F9+s1Dg zps~?d=sqBZsAPW=K3dkk9O6d%@8F)Y_CBMX+fVGkJI)}LFVLJ?@WqTUSxO@UaZ7W9 z#4RRffCVo-YUo8=ECV2?Rvt+t(%wWu!3V)m2Fj}ai@szlInXI54Cih2v%@n={&!z8 zaQU*iGuEJX#hmie|Lv}Ot{uN&plms6(w3C)D~q*QR-D_rI5*<%dWZcHbqHfE-iNP> zITzmHxAQk3iBb)Le>jsNZsSb$A#s5p-@{?l>Or;u7N}CbL@lxRjDsXaCEVB~BvM!w zgzg!$2-|J$aFc-Aq@k~op+!ag&y~LID+Qj^L)RXlNuNk;}nY+f-;cRX04^~fkLU>N| z|J1zII)AXHNztno)lHu>e!~FIR&}_vRbEH_4r_Jw>PzRa4O_RO?-78fc@Au#LW|yr zjvGNSFWkO{{Iw%|i)wdQI=}|jgrXP}@+f_+s_9X@^6^KnKmJ&#ZD7gL0iHYbiH~2) zb35|4uiCwH8O2u2I76k-aY_+LI=9FmW4u+yw^mgFRE4U9^GJnCs8H2}qa^u7ZIIy4 z5>PQ2_F)`DSJz{khDHWjH*IPYg~=dEY%!FU%lXe2$dkv!!Sa~ zL(xEOO&I*(jU}v#$q;sG48fSCnqj}d85W;|u1?( zr_TvE_yO2Ac@8Q?pOME%?ZrLPL_0|K z6N1DGf6t!dIjDd}O2j}02aIM?N&yAgC_WOFM@Z3eqcmj3LGj1b82h`|o_p@6`CHk3 z_U&sX5AWc);@M!&kqk#8j@#eF=sB(jP|z|l-j>Y;}rc*ke?T1kvcGLx9R8*E?)o1JKRB)%1Efyc-ULa{i8&>vw$H)|E$rTu?X|1sTJ z7ZoAX6xvR;%{hE`&9GVNIndOYKwA3lPj8)paOj+7`<<^n_uP&h?d4d8=keUsHIv4A ze39h4nD@IhZ*spBeM|x2p;0W%q5z}X-z5MFAS^DT2uuKD=46dzkg!GUmp6#P6{12E zW`3}2?|A0!+%-QJoakwD8>J85Jm-=8TSR_-zpivF8k*(*JtA zUTZps|1!ZDc~p~ivFY&Y}PlL55CG|2!{fG*&(5S1>rX& zDjNnY8wQXZm?5Kp)uvc6`@}H@4o3*<+U#Rsw}Mb&-NmdY;DntwD;7N-%s4JMIX}A8G9h+#GW(!MlG;YpA7gpXLcKxpuVmqB0De| zC`%4Wb|4vqK@(QN2x;O2rvyNrTj9KpMQhP-lt?DfZv+TrCn}`TWe`NP1EJuZX^Khm z(IP3Bx3?h}^Ey?*5Z2o;_te=gKnLwi-_bQR_%-D)bf{i>oT-u7Hy_n+_64DIe4Z@6WI3~He z?S^2QSuNCAE|sFCLZQX;-!f%Vu|{ZiuZJWO>5z4Wx7pA505n3sz6fDLkgXkg%~PmD zGmC6NTT`4W#^^1p#hl#o0AC|CBw~qVOEJLLSz@g;An;LV&R9_uGnHrUtLM&Nws_&f zj%^DUOtlQucSTdF)}}@7wvKG3IW;%BeC>6v#$_G)kgckxqjjJml^PBPw3_<(u7;%6 z7z{5Jd2@JX?x8nrw%&r777SA%O_(DJK2tK6NIs}Ql}Hsy7fg+1@zu>_wKTgYf9p@5 zd+s$SKDRp#PhK;HX9RN#K8ZG(~PF|D0?XYp4zkt3E1&sCu5NB@SQ-vC zC6ejYH=J|M5nOW`AL$0YLeE4vIAF#(%|Qt5J11jOh{7*+95YZ_pS+)VrYtyQJ|@zJ zEEaRfiMZ}PAP-*f$r4Ue%~em=c)PDfjFdVc+)Ra;gK zZeT~wIp>=7P3d?#DC+)Dx51nrJ7|dWQ`DtIh7Tqzg(bSQZi^B!wJ1a(`oz~h_ql1d z6Z3ig0~IK-cl;RXbA5Quqz&vJ%y#Ljvi5_e_P@Qqu=lx}_dyNx>OI0vlmK(@J;Xgz zyfpygR+H&ZwqjI93$X?wh)Gp$A&PsP%WCON8FvYLX2a5GPFu8czCJ6t-1+m?3+CN; z%hKys^1gv()&7ZzyX^M078*9~vN?#MMhC>`Dpc z%x|TKmZagStJogw=*;jdx?8+;-p<}w&#CKq#ga_Z%2kGqon5SYW-RRZhX-6Mkav#q zv)Jc(KU70fk5^zmsRJYqoHEm}^pVDjDKW_uW+~-N6k{`dg!kHN^=nsmXLFg>WVXJ) zd24U~Io%_D;iJEGySnGh>I#OIG&Xi_nL9ihuzkTeYXiIw5-_X}qDS7vY*Ls&nVBpP z<4dR5P(Ugc1~Q_18MT-6s?eySY=o39Pa=`jND)tJet~Wwh?-`u9SQJ^Kf?z)&GUAk zcnmX*8#j(s{=D0WHy18eKBv19u2aGVj^LU z5H@&t`swNEr>Eb3o98ec4Q)aX0AEhIfI-X#v|G8wA#^civ_Om~Cu zA?+v7FHmepzmjNw*K99@Dc4N2qi*!5xgPLco&yQIx?5zlkt9G@ zi~4eD1AP}J-gxLfW3mjlzxhiVL*YLGSdQ+qXn*_bqWyaSYzd87w4eAwc{`3-w7+Y# zKMTOZq$6%1tlIln7sZgubi~590oVxXh~jVGdm8sfCc9;&^r{huse^fX7gj)$mBp4= zC56a1EDYIwP<4>e6h=${j3SqXT5On+V@;nGoF}_-_kf87_P%y*q;@g zbRNh%=4OC(0Vr|MozI{B0Yk_j^CAxPAAZ5ro<6M55 z;&rWh6J{zHK(oRdSe~W}RZu15K8B&OT*Q#~e$CIm?aJS^X3ddx>-O#Y)2{D*Z`aL+ z9A_`_0f^&wGRgie_*&sQ12^_M12=Y{z-T_yhy1a^cR7@QX-4~>K=@x#kA0cuucB9w zDh~k}D=6(Az+4JNQB=j9G_ohfikPl3EF%!B^FnKDJl@h0$5nb1fn@NXI3tDdjPHK{ zfdcSM6%OzxNxtAZqI~%#?Mo#9dxO@oMQ^OEaM%&U$W~0TrqbJD#xpLZUzL>rEu%G^ zQ#1Zt(CTMzxbt^4w2n?+IP0N(`<@OBXIafZEg72nINe2P0N{60u62W+^w<@Iup34( zA~D!6M3oT)_NajXUCNl2Mx+Z#lQ8y3DWu*Ezw?#~iEp`ayM;S$nf2txbx*x9IJh{O z-^-3ITRyk``#hJwl3ge65Pc_|n=1`{_Zgb+!onZ;TRaE#ut~41^K)6UN(db?EV70J zHmgO#Gb9j3u}l1#aTWDXqV>@XhG+wd3Q4ui z)O3}L;J_U&WsD zbx$t*I?v??_U#unMJQVWv|iU3>vgy&a{?3}6z#tQ!AnQ|sW#)9vVLeUU_Wj@fiTK+ z?ih_%v`h9oxFXu~FU@HG6UN#M9V$TYviQFDL11&E4u#)me$E5zk+S~iUlRTEaJ!H< zg#`7FpuZyM55V0SNuIlOeX&|d65JpAwrcV62!z%K0gAdGzlLu&d;l-)~(3R@kRY}>+55kHPe?@ zESVfxZBCJWsWlmo<#+Pj;x!vq88tby&S9)j2x5Y-lW{V7sfvPew#|YRk7e3O7{cB} zgNoVVOf?p`wC4EI%_99-R-_Qf4J_+r~G(1#3H}7VN27hN=JP?Ki@dRqCUu2 z>w9%im@ye`F%Of_*Cv^3jlAdbxPkx^Q+Sy-;))aa(3T=-LJR{;7Mbm*R86pu6MJSy zELaqM@QGj`mGv!s-k5;!seyRWp+TidgsXF<>W1q*oJ{f9sDz{jRH zet2-#_>SG1H}Bptj(3~Bo9^nZGh~ct#~cLFZps*QtlV-F%}MmbI2ZQg_P6&586(ss9cmu7dS+y?PJ6d(48E8i<>Mfey^mMNVV{c&#lK#zomk zb#+Ar7Q;nrDuNY(bP!{sWx=2_$g-L1#CMb;L(-{BRvsa0KEvu6^9l1s#rec(K4_tQ z3ZGfjlyGnVU!7N3(CDo5`qxqf>GWxpMUu`mEwL9vMvihCGO$G-KP{@HoF%HHfP`sf zHf0e*;?Xy}U=}0PVgq6Y{6jnOx1lh;V7-KqpvS*AnooU*} zycZd9r&j33eC1OjPl|{ll|3clte4PQhZdoB7NQ z&;eumI?VT^($Gpvg@ibUR*6qKncZ$3uVPkfEg@^7Gck&Z-Zg|e3eecmn3>&L(@>L+ z*O$Bz1~Q=w(?7E@f7wdSKqf5H)n{J+2hV^{=sHad^i55*n3>Mz|9|aF%T-!0^sVAr zU@Yzhk^^Fm4wL_-1{z?wz7)VFR>ICCzy!g`3TCxh#xaYo76Fk>H*{^S0B5Xis7-4z zB)1RvFsa*^K4rh2GW`#l@&%Og+?Klfw3()-rfNm%b7J;a&M-qd4`F(%%=wX|E1nb7 z`NX_Q=PS1F5$#N}PqSCZZsY9p!frF(zr*|{2tg9F^4y3_LOcV(0B1`~6bH18CCPjZ z!{Kl;oS2`rh>2R+4$NBcg8>JF&SrkNv%SuE77q!G`Z~i~$FTfXa z0V^!9FWhXrkb_b@Pz#M%_vJVZLra3 zv@zN+JK03;o^&o4_?rg&&4%xEz4ifP=C=-AbKdX%mT`xR>pKTycc-i{7VpRwd24B< zF@wik=~OBlPR&WRwKN$kPWiNd(*(*+;RmmNa?YG&x@}JCukOO#v$aH9TSA+Sc>;K+ z{`dRA{^tE)cmJ~c^;bS{LpGgv%^QDhLr^XlV?P95dTBQ68_g=9W(Q}yiCI{JDV6}U zD#|bliej0b1rNEt`?&ojYKxQjuao~H)c7DL* zrPg9b$0Q|qr;S^96H_cT%&J(*R>7#(JM$`ZbO3ZL z?C6=>)tHXg8-+o*3TH12lK-Z|{M+iPA)nq5toK!U9PXfV$fq~@>-<$-2Rr%!%fkO9 z5KPSJaaGyv{$L_A&spWLzxr1erYJWLn)1{EWJ9B^uu7`rgOrJ_>kFzGlN?N87}w%( z5YxY;aiV{#rD`cNi5V-yFa9 z%ihg@0|~6)gL=%UH|s{wVh4tNT^4EF$|OwNM(Y4LrfvKEHk&N_>-}|+kj-cFIxA(X zZ1qz`u{E8OW)ig{i55GrW%fACC9g#BXxFXBzK@ zq0w_cV7z#qob;ZDA%(VQl?53=hY`Y2mS8`*OV~DZSus~U-K53Q`#hs|sFd@9e)|;R zhLSn$XEj-)kZ5pfU+-mWuR6MQ-M58F+OxonYb=?g-gCvq4-ejdc>f*YXUR4lr`&dw z4^F;F@___VXu_zXYDWgMVX!D%LDmNbAQMn80)%cewWeByMyd(W1uT2x<+V;9Fy60W zVc2IrV9@-DsrR2Z>Y&axa0V5Hci3yZ4?;qtVcdnVlqlrU*CmPzYSGsrDh@@NhmT(6Y>cf6R&Us~W24WvI$DpX z(|l(>$`|oZQjT#0<~jKpXQ@P3lDLEF#e81Q1X~_P7>v+327t}?zpgG2sB5T8WA1Td zLMdh)3wAhBafPYp=zj?2yeTTGNu{k)Aj7$S^eT5v{hs)I{no2p;n+FaYkC7aXj2#W zczx`k+rbJqZ2rgte6nUw;)X4U@8>&f&gmc9b!8K0Q!Ib^raiqYd@O%2H*M{Ya^b5$ z%t5S|5dKi1Tcclv><@=+Tlro5A?a&P(23SZ2^m?GFS8}31VS5PX-Jbu7iSsAET$Ps zcyn_!D$C8C&DlA#qfODqMBKnDuE11gYdXiznm|~l2Ax69G}9Y`sf4G#E`6topZzF) z?!zZ!=A)81gE$g){37Y$;{12&li?7TrK(D9;rL=0mKY|%p!orE1+!SG`X9})%2UlT zu>=68E<(_+x=fIG(-ixkFUBWW)BgX#QY@UB`scrGAvhcZ?(afB6xjo6`x+||uryEk&Ub(vA=j+m~Ee)8iV%R|M@g-0V z8cQvGLS4B*a5!N`op|BU`l(&&upErU>j~Hq|Hw$lI_+$5(?`lK@Wja3i&+*|f{+QYA#lO|t%|8R1jp}e}5f{%)96RG55s#}U6bfmf zcoIS8uy_p9krURKKUQ9z6SHaoEJ##}Mqh>}S{ct@Q$K6P#kzj+iq;gn!u3`|#X}E% zy?bs~Zr*{9ckgfxet65K8<)6tbPY}3y?OV}&6{^(I+PJt#yU7eKWNiiiNlV`fWVDr zfrf~cRv`JTr$Ti*!2x!)yfg!2J;f@+4_$ZdxxLdbWjgn^XL)YRrfu85$aDE$x6E1h z6zWMBzp;=FjR_yz{wBSFoa#i*Bg~&V=+-;kE^gs$m=GSB1tw8$OT=kyhW`oXr>;6$ z8-XDBV`_N`e`Gyf{ zl}>3j@&GXZ3S`&@77ItrXkNP%NkGiRFeK45I#BEed%>xl#&lOCf|`B<5?;kHyk1Us zMM-1<#Dyaq$wWCg+^a};mEF31f7h=5*^9&W%Mn*H|EczXzoqViYzB$)HVxc=BO=4q zWlr9uJ1U;7uV=1M=%05APF_5}h)q=m0mLJ!z+5scJ-|zYB?dIyV)hq-Vo_e1z{DaT zf*FWduC8eVaOx>So63CWJ3J?lrdSR^ri?q&M0W=LY~21P=Cu{uG5#RhPxKq@`Il&n zq8;-%o~HhbaO~vge8KQ@e)%*%C&oK*e&*kbnqR~O`+tJTmBgC9)EP0ktpA5Fxr*z8 zwwRdb)$AuTZ86~B1K{11r$doi7ekW(^Wu#>Bdc&ZAaoPm?Zg~}H&fjy~l4;g=teLlC0q+|gnH>qM0iUa8%}{oAYinwGw-&99d82Ff%t#v7lg3Hs4|8g` z{Y@jzCE785Cfa|uOPoK^j^|RepTP8bU{IAW(0p@f)i*JV+#KSPrP?oXnM;_jT*&~7 zctw_fv541V5p}JW5v@7pO*CMzJfT?6P`Q;leflLXM_MHI)2Xo;HC>fGQ}OckxVmh$ zwr;CPl^1$#Q(Ee0EKd2-71s&leq!G5;=Hjv{}RnxwBvoeQ?wVtGuj^@vO26G`2+9a z{Sbp=LJ{#}+}`h_b*f+ttr}t=JiT3JGD=!Rm8-*?b&0e6AW3C;-vXSJus5|c^^oOo zF(WGqSTzR#F{t+@d|F!65c>^JO6ja+b0XbY)zps847>HZt3GwiAF2+554u&w0g`6CPFQpiy&5xz z3_J<(`lEEf{5wqVRS}E(tH-AAXRokV@>%xEx#fTF!rTxUB@VJFOxUd4Vliv}C@BP> z42^=)dI&&NV7hAAn3Z+x-aWm2`~B<{Cwpbzn*6)WzGmOK=N1ZLjCA+DO?UM~&=`BZ zKx2=HtXN(=N0=^QoD(Dqf~^>SHVc%BRSw=n3X2b8XSj4US*xb9Oh;yAZ(WxsRu|2* zv^f{x=#G^tC1W1-Jod`D=jO9`CmaPvbbSE77mu9s839hGe;V68bz0MDT z8@#9=daW|T?6KjhO3pi1Z2Z>*|D`D0qvD9F+L?DExz zX19z##?Fa0`&yjWMA_@d^Z!x1!}l`l-`?wM-M&bSH#}op4={lfjP=b9-US|r>vhNk z0Bo3!23jbluG$nUKN{q43|h&n5MzJ2ZF*iHV6~5>)(x`V>|gR7>|cEDD!;F>BfCKG znm7vmGrs$?$mKv7-EUE?Pc3|C=@YJ%8+4-YMo4xfiI;{W#RiLL7!%!2=kun5mXZZ? zRx0lq{l<`A&uti@!# zn=>27ds}8Vr27*Cv(D@9-PyfyQ|m1660IlI*S1UN{f$Fy{mW~->Du~OBsAR6+`2L| zu%_1O3;R0!)dLM_luv~O`xWUl2|cDVEVLKO^j503rYim97{Jc%s^S7`|^B?KVbYz)P_d}meI>t{7zZc~Xfv4~e)mtEbz%0Gl zYC&Ky4t5D9aNk472}lgGQ8rS8$XEo9MO7sX6RasDr4Vr_b*HFZ;FqOst99KVvvn0bOHfR zKZAx-waRp=;tL|27Bli&&ah#3o*}d4vhs6yrlgjWkDhW2>8^%Ju8I4GnQb30yTh38 zf%j0d=i%nEcB~;6clc5Eg1EzFu|AX+5AmCdeLl(0(x>?O$cOm?BpLerQTEwp)SE9X zgiD`S)|bY5THkm0nLd}sf5yJXT*^LI%*kzzp&Uz9%#C6ZxGv_nxx==$?9+=f5aYYF zeh!$ierTVI^}CwAdB*kgQmm9@po3p5^w@<3C+$@XUjtu-5y|7gOOZSxo(~bIRSaTU zNF(k5ruxJ?oN3QljT43;veGlfy#tFEXUwQrTg${wda!sde`DVcf3dtiJxg#)<2GU*xJH;8A=*XUrVVe=-w?GqO{ycaWJ^;zrNxXmjs362Y0hwu z*b^VfEBQqEl{#B+CO>$}wZgpUcLCV@9G&nHq9SFe8WVs%6*nM-q!Kh(4l``+=RSMq z!Mz{lIn;nj_gYvu!2^6T)WF)Ov3MOB?@D;-Sdu>zj33z~s7aDUR=db8Hj3H>TzU;e ze400fN#GFhn+ihl5Finxq9L!=zYg|ZG%|7FbVH)8C!$nIp+qZRJhk102Y%G<6@YZb2TUyA26qS@@uH@qb^?sz`sv^=9nHeNfwFI zuUKIrI24r-u2>m|;)S0dUU7W;k@;(HUp{andpy66=kgi$YQCL)1APzpxhP{~I(POr z;T4i$qJ3Gh{atvVti7|?{vO<0)?WIYJiJDGR0SYKc|QbTr-;*3A@P>qQ-#}uwP5(O zT>N=Vbn;@&*O*1-xI{)JL_`mY%7{`unDHCrR8&1)jmrC>)AZ>GGDV`g@Ot@huin^H zTjh0ozZYEKR6`buAd@kK_0?*|FS1RvxYeIyM~7P%?;e^r zJ)K?GG_SY4F~J8?Lm7QjPi^2Xp3~a%Kksept^JY<&s83P{e|ivQ@Z9btzL1Buw>Dw zw5)&%kH>=+M-15sC1fX*yli6E&O0B!|DJW5?)=1Ozx{1Ci`k!eBL9~>QdR*gyifc- zh;>%0hZPB=({89oC3XwHmZeW*!_zO^yKn!UufP5poBZ>iu?~_xgU$sO7jpZXc-xBY zc)mpYyKUv|c)mpYd(B3BA6+4kw982*R<7JNFMS+`DgnXhCzs4s2bgSO!+G=t8fBJga7!QdtGRgiZyZ_Yp%vdL%IS&V4E#5O$xSRbw z?}HdxxFt@(3I}I{XCo7=C0xH4)N8R8pCQS7CP`oq$51V@1eT>$u-W@A?_2tXuY0HV zwasc+sWxm%HN?8=23mIZ@V*U$yK3a#+@@>iOx3pMQnC2%fjZ4!J)BAbr*T)2P3gm! zvd@Av9BdfvFaT*3Z84C?3{#9e<-!K@cnHacX;#0MO_$jIknfLIExUO7lEJ#z(b_N8 z9*!rzap7F{+3&yp+8ZMa7A#mWa(U_ev=`UQHb<-%VzOa9qg`N}nH+j18JQ^Wq^K+# zA$~mc`mmTamSyOZdolkPW^?AZvWmCaZS2+j!~6HJiSr5t@ws%)eBvCV%~fn)4soOX zccbO)eZ}?@NGV(F-)ppEZuE7cy%45xi_gLHjS1uo{DlO2k?`^6>bcW-;fNrT0FF(U zoZ)pu^btY!hSdcuR#wS`WN*dEa#2@R7o4B}adFajnw4WX`I+mg!UBD6iASvrlh7bg zLpWE1K&@EhZPKD4Ztm%{XfHeSThCu{-=_E3Z4(2xP3_;m?3(aY*RHA# z{w%+byPUC*f33?kxa5w2-?CN;N1`)>VbPY)H|fqP> zeA4G~x}IgpRGZzJwK>%}8t$8zXBBv0RCl=H z`tWKg9r5`h_%DBbPnW058I2=82(8nNaKBUuRiHd218Zycq_Qe80V3d^wxnrwm2Btk zP>|i2OtE%b{%cj7%|py`vBp0BAb4N{GQ48;wcxIfB3Tud)dB{uCaJ)dfYc>ehV%6Y-TBbeGf4xg;^*eAq@Lgrye5C6UnHz>d{26&Da29A9s$h8$Kz z^pN0SmYIb9STG4y={DlgaDfXkOdNz^LNZ^3J#*Rb_qZJC8h>R~g*#m9;P>YLyDJ*A zER|EKOT~EW*^Mm1AA}evPq}Ch1hf%8AV$8VLCoY%@9rMM!jlqUY^Fa4tHXTTX zW(AvOwe;rrgYj7v4zHuaUYSlL+tV#o71fnadqp~?Azn%a0Q({T9Mr=;y~3l4WjPxW z>Nv>qSm_;~L4-P4dh*Xkgjx^vY9NtRy+tC_PGmwgkTVg}B-1Y99+;?RWj}Q1*KBUt z^?WSS-jtkMw{G3xft}gv+WAN3jGlk~uJN|*&Ao}{_E@U#g3S7C<8b5lj+Mo8_zb@f zDiOb-+$IL#qhuSK?Ciocb|4U2+NzPQ63k`Tp{aD^)S^}CmW_?6rR>(1USbumzWNP> zHzhgJ!|#C#P@Yn7Z|E;`g4Uh&jCFUd+qQ1Q?AEob*{ze4AGvbv+RKeG)v`W*A5;+z z0->-Fatva;Amjz?@u)!wPfL;N8i(>D-(at!Ddh}pS-YTb6+4pcu;y%`2&?$+ck!%9 z5H4)t5Ax$s4N*wI&AP+OtTqR;7q_qhtYDX{_6Y=Zht*)S$zy0QXO>nvDim3g2+5-Z zg!O_+Zpy3noNZghu@^g+wV^ayG`b&0w}tUg*>6F~+?fnr!?3pXcKEsgP^ z3^~gvDKyxb%f(blv1YQGH=9-zD}Qjen%}GL)(2Cg!#4zK?23!+`ESK?>Ez^X!TB`@ z^1prPA?6#p$$Qb>tFG?ub>|iyJNZ1jxIO%MzU80T&=f-MfmHZIVT&-|> z4OPiZPV;9nviG4IwR?Aa@?TJQw`jBdVWzLUHFfQ=2T#7=Z}+sde(4A6MjWg?|BZ)m zG1B+_-Rt?^G9UeW`5Rjvf4K357ZB5}u!Y~nkAoK`kk43P37CAw)kJ(J!)DXm$)K}@ z_B@UWXflKSm^~v)e8R$H1~N)x838h7WHGK1yrdCTRTWz`?X9M2RwuWndw9+pQ~6!H zJ$oLkaW<_S)RLOFqM1F3o5vUZ`Ou9+>K<3yx~**2$>)I;?kQ+|Ek6!HWRI_65^}AR z-$d|O8x*0$4w}K}Xh#w5Ajd}{I>JgIzyb9@JxTz@Z32$JAJbh#=^I2`Jyo^Yh)GmM zKS~L(0iAXkm9IVa3$|m!O2UrlI`#{G{NxCmo&RQfY;)6Cr9vm<%0UFFc2+p z+HJNHLr2US^P33f{tWxf^sy^`#vXPTU`3~{_x3GeUpVia3l8w(7u=kGDz~7!>lebd z#PKen@gt#t!25oW9|sF`iP0kwGKG0d=fW>2)=6aIyElfa=d!V<5&Fo6WJxMU=YNxb z=NNmE_ndr*A1{6vdrx{2;&KPxP5TY(JEiZG7J&^`9cPTQA@R)td|)M%f2VwZ#P|h6 z0{7x5HsUCj3*E~GHdXala4>!=4JXUqbK`&-q(##giEmS(%_;kOUO}vrISf08|H5H$L^qgr?eUp_1I|;Uw+o zmSi$~^By&Si@Li#P!m+c?8aL!b5undW9*NHj0-Kj;riE4KF?m;a`}-p5o3@3lkB*) zV#KxP`7wdnGk7y-^d0g@M6bt`5{7VsCg`Xn%hIUPN0OHz%{%_bt>Co~5a2O_Z~xAF zZ@j@O^Aqf2eCYT&|9EcsUj8TTWf$$`krK`*`%mdkhyx~$O7_F-kGRL^^N}v)$H5Pq zo~~d_F=cSb#uQXs6*hsmhnCFJlEkgY76mM$r}Tj_>|;Uc4#Ad}<(<5E3ljN#kNEMPGnkSOYTgbR+*0g&anD3*lvGY?H?JSm9uiH5TQ zAa1e1db1N)RtVcB4Jj=VOC+qeP;)@&Z5 zWA5xZ!-E6cZyem6TQ;;}Q{QDP+!M>{>bpBKUFXheNw>{iwsH3Ajs>gT_H`rr1l~V^ zVTrQK3G<(+lnH)GoTn=Kv3u>Ye32w(w*0b<}*z8Q_j43)iiAkBTU zyo1E8qY47z5aTa~lu^1^`LZ!R>~sP+>z(y=QGBvJs@nxsP?>bt{0MWND?ytxNz2Wg zwaP3TlvVb|gx2I(rHl=+LmPLecAE>q|GZ+6tG=eD-nD4O$xHLUedv^xIr+S~AA9KS z7!>>9F9#OQ5U?2SN5sM;8KlwjUzf}xag|lN%Eomd&4NAp<%jQIe(cz)yTs{l&wqm- zM_s|(mp!!ph@p(K`3*WFmcme~MQ$HYoC*q)?+~e>u`Wep*>I)nYJO^tD-r`62 z%iw|ttP(32#ELvYwlcTK1v8I8&}7C415$Xk3=0lFX2qE9AqKCA8;c)Y;7loa0*rfS z@)nhQv)FUD3=iM3b?f2brH8kSEL*;GWMpK7zdZWT!3!Q#-)_lvax3##cXy8eeB;P6W@`EzzMJ%Y2Imf^FZq``(-G`1xuX#UBiSu)NE!ZpP@x*?V4v>rGpkg`KtY`qF~(9LOOm{k zl1q14m;_cuvQB{lpsWW)flZu&0xKg3Y$eGDNKrU@w=umU3}W7eI!U)i~P*G@}*tWdzX8()BH&SulyLcW`Neq8uOR8)2tE9$#Q{f8cr zDM~#k-LD$_Spq&fU*&H~-zO#@D^Tk(+#|u!X+QWlD_@ofwQq zNg0s}iiWND);esKC2^>zv`rqRY*FkYQbYMNs)wDOD@(+Kik+O6ilM5B1< zp;O1fhiTr%I~+7mE*fRBTsDdtd;yF>P(CI)<4Z#*pFWzI_&8_O3?KgLZuP}uZ`^Kv zG3mf0i%?cLzzgGI#lz+4u*Mo-6qXjg9tHY=Vh^zh>&=u|8CH(zUMlVLR(MpGQQBuK zu`Xf4tWa-EL*qJYN&Ea zoc(WXDr6%l4V70OJ$A*g@Z_pU*;tNWnCGJIu(ONno2AQQ(WY?PLA;7C!aG`n&Vq9-NKJU0P0}B?r@?p zJzQ0M?aS=g|J|Agg8;$0AeLDMz#ma(*s*17wQ;;!=P%y1`^b_5^v zApq$SlCxphEp{YoSGa6t%qFu*R1q>u5qymv4zVRkL&YlVhpeAqTVL#G!#xRly#U^@ zH&h)UUo`$FQDF<442|?Y)8$h$9*kIM{*2_i^|s4?_~T>8etfL&;+};I7PI5$?%uzj z4dPe>Js6Zy^@i2(;Okx&v!3tfN&q?kZ7{7Vh z%3C({Zl5(&*P|_7Z#!{99_w%HO%A5!tbO>x3mzU#rbffnTeh9EV|QH*zAqJpx7eTf z%MgKmx~H1S7PPTUq&zb+8!b{yn8Y!2i&;E0kr)D6%92IKnFtCOihmfXJ{11I=O+UH zH+OFW9o2EA0aw-Ay0yPv)!KX2j+R!dg%F|v34stuED~BkAb~(&7Gdy$0b^{8F~;ph zwi9o0Oze!aOhRJtlEm>$;y893Z*dl9A7^4`nM_O^$6G@8f9|dKx?c-{v6Fw!e}2w! zX4GBXU9VofTlaqVyWh?8sHz`hE8Y`SZ#n`1bFz04-Ei9-huhYd%`cu+c0_sWEqTG5 zvSv?5^@cX~)FTgn`5Wbdl`hxwTQ&^l=C3RbXg(JC1^Q5zgHILzF(I@YW8cfQ*mpa= z{(gLz{0+z5fcFr5ukYb=HWo>#AL9kv?+J;F_xC|<;XDo!Tud@ zyfJ6C%N2Wx&EL863(&6*>oiXbm$0XZl@yWV+yjHamMS7jDhWd-eo{g(MTTImaD({e zlqUw_AqE0WP+^bGc!Tx{!aoqHG*OAjq9j9u4E%O8RTxoL!3`z?!)OgsTMB`spu=V( z#8zZ0%*#d5CRMfg(@a`#RA6HQ5DCv-W20uop-LvmUcI;D@an7YNMABJ*<+o&Vqr(e z!j6SEv8SH+_nn{V`|KxTuRv6E<0sDC1>X9e!{8q?A`rqIIw5Sv|^h-a328JqtMYo@mjH_hqw821erRy?()yv zvH!-Si|1e48U*((9;dE`8@5iwPX70$p(c2~(&EFozlzAFNOl1wk`?vzO$wu$Kc9yk zJ`+Xo1N`P_E*)41x{H9upd_#n9Lf{2u=Z#n;JGRyg|NkHz^&70j{y0Gw6tvMMhmZ= zTUJ$_6KpD-=`?P)13lxj9Glgu<{4ManVsi~y$t*Ai?cXh7>u75n&7!f1AiIBObEML zv*Ww?_VOj=(&5O2rfiTS)Xll>u~dM_4LFLLw0dG}icKdMYSMX+4QQ~dn{@it&6E57 z`{tV`KlQ1lml@zz)0*z?HA`a;@8*Cj_?o8$h{Js3bCE1Nl?4YCWgj(Du-_2dxD_gz zC^hTP7C)Vc*?iWMWf+)vwn*a9!cXW=Rt0pfh6l^=88aj1#FM3sHsgbpyE(mdLgzPXeLNzoUKSH9e*!lat-)D-L$g8>wE{(mrpM>922#gW7Sh=*A7P z9|IgTe7M~o=&etj2@H6>Y(M(GS!D23CN@gux7evr8LS@keE~EUV*!jkiis$T7sKC# z0>gt4xfd)ULLoB1gV`Aw8Ce-w9NR?59}i@~i=^37h2B*@QNDEYPbdC(`}Vo>s2PeL zWA9>6wENe;=C&^`T!Xn22N^qMr%D33%ui2a3ILH*A)`=75?pMS1VMX<+$Jh3RPLQR zhz{T&8J~Nb&E~Kr8Rbub4 zld=D#kuzP|yb*8pv6Dn4HnR1R>q{H41^* zokTX7lcb!`C3AXU= zzF!@TouRJS@9@7vKU}@~hu_!yv~OVkCy!hn$*@~kx{5?;>tfo@J1amBs#e}sP{ zGASjOM4Wz(B#W$55<&TrEVNn@R@o&%8Wyyg2^A^GN^;8#$*mIpo}P)5p%RbBTtGSz z;oP??3L#3V5`cc;#f3yBvSPATf^KHmsQ~vw$zq&n2Cd9^YTX+OyYVhPeJpg%p@w5a z7r#(fZz(AB-`TTj@$AT)jgQCvO26_1WpD0lS+SyJU+mWLwU2tt**TeNUgomU`fzJ@ zX1J+2)cee~EziW`1ZYT)fz6h{Uj-d99g}mA0VS`e@^PYc*7?f}Sah24%|3S!sZqtLL@ z-QKZOjy;=x%M{>lbjy~}m}%n#xOZr$9$-%qm28WonRHJ>^~WB)o46U2ou;zl1T>mRpck>bzo3h*;}%-|t1VS>z{7n9~W!$K$GhA;rXUIMU@KqrVuBw3W8nJfR0 z)~hlM#QQX_3S9==iYdQRgzguJ{u`PMK)zMuZnEWxWN|QDIx}|?^R6XJ>Nias;2C2o zqj&RP?Bvd`7Z&Z`9>ewhM|@bgj-4bfa>*mPnT#pAOX)U)_sh~1Hj+U>BZ;g@Gch<} zl80Ye${0%0dtnG#JDI}A(g71pM^lF_h+NP%OwX06VCsN}Fjvim$5wZ-lO%_1Je3Xp zsJ0T=6GM@p(;HZEvIgL^;9{tVMqdY3N`IdcNMV680W_V{snZJFYRJ~-kQ{V)AnBZM zxXGMeVr9F=EkP|0bm9o!(?lkS-$|S&A#58vNo-`(DF{*Zc^30rER!h^ff!LBD&yHU z9XT;mNl7Garw$|oA~YF<)UCnq0WT9cF+jKFF&mUsTZ01IcKm8fi!U1WwWwF!dLIpc z<}ny0{$@7=9&nnVXh*PU^S;1 zh<@Zb=gN&1%o73unCr#I?^!z8);8JKx9k(Qp1@UAhP%6mH&I*cDcIqJuxBur)^{q~ z5JBeY#1%})^BbR-Vj;K#f&|x~g_#Jn4j|gR1oRSA6cGYL#c4$VTk?C&o;iNc(%T-Q zWwvE^O!5iM-^tlQ`d$QFEL&$j{0lc>Hp!m431PuBD2zQYZrS|$FJ4s5&Zs>i&l<91}7q*|EU=tb5d4*7Eim~@$iVv;5OhiQ%ao6I;oS!o%Hkb)Wu_K=aj!}en0CG~ zr^&DIg?6jJpxXjzLCmjUY7o{J@}zs%=h;)Fj0DN{NUno2>ZBs8pn_xuE}Ljf{T0G7 zDTor1mq3mJZFAC5Lp)KWa38dBP{gweh`K}I0Co>V%;i3xFHiw^qEA+w;KG!a0zhNH z6}67KK}0+19d?;((ZkE^^NZWV#Y^p;%#zybwb7+LNBifER(CeHb@mN(r#Eg`*0bro z^76{!!eY-eSC=g+YbdBv%hGh{v9Es5!7KNyUf8o?cv(lMqbukOR6+l5>^mx8PPCkC zjMxjPz{(1lD3qr$fr`-HSa&P(h$w)gfugyTtkc_%HUqh!B=KgV2wX|>2xQFaSzU;(NrdghzUI~I)qUI^+|wMVX4H_ zEl1TL_z_@r6x!P}u5JN1k3Wkt^O~(F>SjtI{^zWM7)&K4Lk6wQ_ zow@2azgb21#-66lPzxC!M*dqi>5rJR(oK>m3Hn)Q*B?*d_5-G;=RBcCfk?f;Apu4> z|AnfB+Y5JNP@&fSja-0FNCtVin z#-X6S5!2tL{#M8OiCZeGTPr*~0bZ0b(hDi@nX{zdzGg1QI&034f|$cf`XXsLQ+Ts> zV@-kq@XZ6_>G>)ati%GqJdkCl0P{h$u`x)0GjSV_A|^|g)a#HuLZc^R|6N#QI7ghY zH*zSG(y5FgDBl|r0fq1N`rbg$EP1RL-iEya)(hA3ti9nRPOob98umsK*~OVc*&3cP z$?0yIfX)1d2Ib;>_wU#ZJj=hwPqR1KQ^ZTk$;FXur-O+ylv9{N+gp3~OH2wAp%fIf zVzpKcnDj|T0x*39GL1ulm}iWdBRM{wuiRJe^Hg~J9`u5V;!d)+ATxl?zrs!+@dP13 zQ17spqMRFhQ;Mw?dluC#4zvd^?L2r_nrYdv(>`P})#ha0wfERfH__|ob&9mzy?kvoy`sAk`f2jPqkuB)z#s419!fUQ2jpX5o>hm&5fopcDW~ip? zTztaW(;q2=sGm?a0X1x3*+2kRQLvW}rb&d=L=eIWD8WD7cumD!|CrL1AF0&GfpoAW zE9;Hl&jbM(Pw?GL=ouJ@sC9L9jdhJaPerM>%%i563XF@Uq;}d3T<8kUTfAKtznHi6 z!1~3d6a>c zEcPkXH(Qb3WRUyY37i0O28a_B7zQNU5NdCu-wjzs4;(j!HiV6s|Ij>LYfy05S*L~$ zIPweXL%Sv?m)vpd1NTA~!U1Ud_xh}+*iYb5p@p$u79bB0`1)V_zvAm7lhKfLSJ~GF z#{*l8bi8vA_R*05T!wS@ha+kF8tb(M`Wj=%!VxjVV$ND)7;vsNww<-cp-?axOR$v* z@P%STp{;DBmd?<_3e9GI_x~o=;VYVqb-oMhIeoCh&w1d0Imo6+8q`-Rpr)@GMA(8r zQ{8|Dg03-?J^+&CNqM^$-qkdNd7S~WF12GG2w{n;2dKRXoka^uOv#GJU+ww z484+b9zD4v7rN(aM-Qy0VCbNW*&A!nDhv&d2R3CZ^pYF)i(>XojbFd`q9>}*n{r** zUt^Cs=^tlzEo+PYk)4cr=`YWGQ?J(md%^29(#oOdLE?4btwSA$V7>tYaIH4?_h?^$ z=g!i~QELY@MNhLK_7t&`eBjDhC=*oF6ygu;!cq3r z$uFP!#^Vnamuy;FT(GRF>dc+%E_#mVTJd_|`o&wd>sNKZUD$)KqkT2sz_`vVa^&&# z7CxT-7S~IPpQisnuEVgter$!XTjzV5Z%M8zTY;bFeD51r1&+sj0lvOKn+FIt{{JkG zfSCJf#;^0P5ElhML!bAa_U_qQFN`$g7GeI6A zc)C_CNOUW|fCv#0{#XM9h$k<_c>za@;=G`-1MIT{JWh=JFb7dU4ns|tD1nZIZXc@& zG>>D_gaU*a6uyPF36PmI1%dX|z{MOi|0y}1NFtTQ?F6bJiOD>Y{5*0v`1k=R;vog3 z0OcRSe5RWUHCX^-(O6>$KubM;F*w%W9j-%cXfTn=_~|G067KJ-!Y$fk&z zYqw;JvZ1rHZb)R2i87nettn$uAg)5g2%z1IY$OHSO0!rj7VBAuD9qXrlm^+d7G89QmhkJvS(|qzynF>H@6xb-AK2)gV(N!!_U}gg^g#bB* zF`*ZjGi*=+J~3y}LO^ffELxnZHx$IeS0QNkvf0NE9=P`lyLaCWLG*olFU2hEoORUx z-g~kC0i(`{g%Bnp7t@m9wL%~)QmjY@GBZ>%CRidR5_C`mW-ksoH?P%_u4V!CG7a)W zSj&LnL@*dqHPsF#{&CMuH(%A=b}%vw`aM2K4QS0-5>Q+)7~=g6LJg%s(x@wt2+bWkBbPSL-qy6C^`?W}lk+Q^<(tmD zAIxbxSYJt-S_dz0>K_PhSg>pF2Qf0ZY%n}0_F7f#T?dC9rEA04}AUCcC#1sOZ zG+U|L=eBymafcOva1g|Vw2G@xumpN>IW?`}(jfcZ)th?9%a?5!o7FOB-qnX_?)(LP zwz7h%S~*H13l1G#u<(}g(9BTX<`>)hi*EK5b+2xQGYzhNn7)sEhV7@IgiObkN+5kD z3k+gz0AnCT$G(Kg63YtUyT}0k>It&sM<8sUE?Rf{AQ1pbRV}f1)-}=h$JP0_tv6iA zc667rlkxEAXS7NSp81Mz?VvwC+0T&Vwyby(nBneo$QcBe)n^DCRBD6Om;yu4|2nBHovA;!&D3vL7Y z`=^B)u5AH5 z;BF5@(ru7qP^~^lF(fWrPj^A_oPOCi;ALaLkaD#L^l&C|p_(7jgZ$tPc-?97(+sZL zN&2`AE+SC1Er~$((V6m4E0ExZx%B~{+0GvtG#}a^5fOZtywwK?eq!nf_;QhFxLfRo zg}des>_#dnScoW{)6Q?wExUHbcA;H}$I%|-;(P~izEa$W_-j7tjAYoXiU1iyt_%Wp z(4HW{q$csLS_U}fsCy*e;`2gTls~1UJ0-YXn1~ir_Z3YPckeXrsWVHo=YhvOU6HI@ zd#1!B!f0nk;+e4EEICS?IO6Oe|AG4e-XH^j6q6+bk6J1%mK@mq{7@@3Ob-?IgrWPd zK5*}ME?Z|cSFPyq`U5tlh&pC$yZGM6_yPQ*e_V3?BFpCNx}gEO2>@f{sSzST9GOj= zWE4ClSwe|p?IcdJiV1Xm)B$ZBUWKVjvLGR7h~#5FXRL$<9$ijOjx)#Mv$|CeS{NuS zl)c!22;1TijoQvep1kkD$j`f>u}}L0U}&6BQ*v1a?5` zhte>Yj;dVv0ZftSVq1p-dw#Bi*a(yl`&CuVfK<8Non+hsM;fvSrP_%uSYsDy)LZ(i zoWK9#7e|1A3;hu|{q~}hTb}#}XW;VZ@^bbt?(^61Z_u=C!Tbj#pE$M*wVpOI7*VZi zPG&}Wnj#7|3pjAvP5YSTpIC2>mE2lBIH(50KmrRYPNh^~n|T%J%#pxo_}0O(z{VP# z05IOLFf?{N+z|$0anOzM314R?Ng3G{v3V(z3oJ}v`7+~3nw}m@vTn2{4+f+MtjrYF zjReUh@f@rhPrhoI4pdX2D<yuFMu<# z2)Wex|L=3D^R0O<=Q+w_3|#6&P1xf%Pwx9|N5^dk59*~>T)e_O)YCK6oz$<;^j4vE zEt?dOt0NgUmC2&S7{yvqI6=yZD9Ms2Pv}fLaJs<6Z9q%Nsnc3uJ7elt!q`qC5J}{w zF;Qx<8uSEvxLqvB$@kmcs)v_aKBUv&PXf}mj zP9oE>d(bQdO6YnB8IhFGl0?@qzVxEtqb6C1L#IX8oX)H)XOXk8ATP_2WiR!3QBeiF z2QPohY)U|}qhsdPss7A#;G$P21~y;5<2F~sU(q{WQ@L;swO-QQ%`zN|+J!%%yR*Z%L1mfBP zGV>5SDIn`2X?p5XKdON_#T8aGH>CwuHJP`BkWcqf__(u@mS&63@AIH+gCSeVkp-Tg z#MUlBCJV7sN+j%Q@y;5U*nfEDw#7TIym4(+t^A)fy?SAbBe!Sa9ak+o*cm-gc4#j2 z5CfYbAv>^7|-~XOjUU~`q0Q_BC`|oKs9(vtUVvD~`-@*N{G?Jc` z#?B?sl3?3_Q0zw*XbIDIqL-wn6}B(%xC=66m08aGnLc#z;+=EU@horWz;AFaK0?@D zW+67x6ERz$a+)SEFFOcf3Y1JhU};#_xL zc+a57GOnBP`JUb{e7~x!pfC0y9SpV3{^#WvWaT@4jjW%+yOSe;^utAR2x3Rc3kd#WR|20oYv+`Z6wE zS;C-4)ACXDXi%BRm6dC=pdu01qtQD}Ky%s@HJW=4&)&84vg>B=>TV3dzlIR=+F(%qkq(r-lRzr_Y% zi@?5(`&c>nudGi$bLcDR&t8f51#ZHtDZdYaJtmxzu7^XbNCkCxqXKN|?}HZm(|1Jg zqd$V*r~h^l@C+fx0@s&G+95wd88B@0Q(FZ=EB-U!4q>2bBNVJGnLx2CEq)z%#G=|P z04+&L2~MjuNLQ6ye@S*%hqLa%Pi&c(q+{Dn8`Bz^m?hRpAA#%TzYn&Q!P(2w%CM$d zAeC{SU`IdRPio0^kwTY)iLAP+s8E!|G=&jK=*)F8w$N-!sPGg(x`GXv1jbm);xxr9 zKqXWn8{mOAWQyJ{z6sS*hEZ6#TM!6Df|)X2nNkkgMz(!<;;b(haHhXczN~En#DDTYnQ}+>hsSi4J@U5 z0%bKmOTfiEvETI`Xm5EhhnfnD+Yj^}o@}J%oDagW#$dd5#qd|YGQ6TL?sCQB@%O>m zVgRT?|6vL?g}%lt#0t8>mh)=lBu(4}XyjN4^p?{#a#G0<^ZC#-c>Q{=5p4uSv?0W| zlZrhbPb-I>xo=E89=$tyTw8ZIM;M&L^lfIr-uBaJ<%Fi@6faaO$C9q*WKFM?qhYJ` zz$JS}UyfFfR5ezG=+-p@18bP&v$41Pt17+(bHiM0EBYq3X|zW*^gnb~qXRCJbI0-RB*tZgf{@x4`JH={G~)(?TAz5S8SSI~SiQ zgY>LH_l7@H3E3M2Sa@vZB?=XlRWO!-ln&<9LQ{rDDs;8NDT7nA7Z`+{kSB9mEQDC{ zEFh?(YL#qW6x2ajCZxH_Pehl=^g8sNQwki`YMIzhUqzHoNex;;l*cXy31nw=jk z49yn5^R%*a&}v`VddF2O4|YU)?3PHR?|Q9Y?~`~9A4yB+!(w1iiq)!E^i~281LqN! zM^$}(9s?U|S&UjbLF(K#>(CWrU6K5{l1=H~{E7EZo2S=gjhhO?zWa zeFI-wIoQ7n&MVOHe;xhb3(&1G#AO$xTZ2)FEz7E+PHL)d4fH{5Xbd_reHNszN4q!N zxv#ux@9xI%Y77pZc;Z*~1vM-C&fK>|>syr>_v8I@lbsP8=sj9cw;QOM2O)}XO z3Wma%1#Aq`uXoq=&7Vs!^7-LdK_sQHb@Nmcwb`#Jcu@-=90Ga)cxpCT5LM?QHnBb_m=&4?QXkQ7N?FJiKu zhbMe{YNasT@D>XY$Y8QQ@sX5a5&!ff2vJt)12q+;DFS9zRrMuQlz_<2*8sAi`bk5t zy<-2)C)?Yj*JfTG*i;uRucBKAR}ZeH&#&5&bH%EWgiC^c+Gz$jottKJ9)`t6Wx-BG znStmHC1$ZRf9i|OEJBwJP*m_36l-KzKsg*ZVN&&Q;K-^lj6^3;t02)HS^g1?y1`em zmMFwT71Icm9--jQhkY(muh*YU{b(9Z(bLg?4Fz>Lkr1|<#fOEaJ|Gh6M}XmBhbD1} zgTN7FbLtCQm#o`3|uLV7@$P^@5hpX7Bov*+;&2-?P`R2{kupZgPPyW;uyy{$asp5P9f^b$ODi^4J`(}97Pk!;g7QilypdnlFo>6lyYt< z9esx31ipqdWpfLM3ua#3wl*5QYQ_DJ9$HmX^KJacET>PO`7`x=>Qnff0uBy->POPh zF@oYBUqdGWj3+d7yzJkP^fg`?>N|3D@izLx_7&e-`T3vxnNcu>jbl zljM=Dk7)8ae5-qOo~`q>|*n`6myrD*1WWRW{DUwx%@lc4}>AgR~f6VerK6lWKiF@fUg#htTo})NK{{wC3thkT;2yN%p z__vO!F$wx4VJ}P8z!s1kvMiFGMkz}dfpeo>wiO6CgbC1cDhUr165yCpVFE(fT}Z-* z{yji1VM6!7BVM1Xf##^Xl5E~cSAOo_@7mmNX`SV(D#*;vu_(+ETSJ#EY|U9KS)7RX z5W*USUg8noLEq$V`j9qnpBP~t;$hI75;Rs?(FcXI;0ZjR&!e#tN>ssqe2o=e4jXbS zzuvw*+SW$5s`SBKD}VK?mH!38Fo@FuPF4i^DlW=oz*?qqACgQDO@8-wa9tInA^cbAswAG^WNJ%svbV-8 zDLitduqJ!;4VV1s(o6ruEI-<{>qmdn`a}oV+r&o3Bk4A1_6WUVMZLX(L`7LsQBepb z3LPOPlOa^_8U~mYV(K*vL)snctwDHzN^6=*94=wf!Ny4jAon$IUi8S3rpu1q`upFr z;HshQEvx?W64+91>o+nB$s&EHvd*iYVwl|p=%>IxO+Q7Om7C9JQqbstNWP&o*gzaD138N1yLp+9HPe z{0p>2mXE39kn4eY@N|zp51#ILJj+~|40{ORpO1s7C^Lc<+ZQ#xsjuN1v zxcOls)bi%FiNgdgqOEW0VZtxzZ}WPWYI-T{4El%FgI=N_%UQzh+@>rN>{{y{ol#S6AI)ccZhh{bug{sYM`&X_!xX|Go%FO)I>h8r2^ZJ&xSI@T0 z^c9x)fQSHCnSgn_GBOsiCA3n~7`rg3l$HyWO7Z$NsTBYDrBVW3=y(WHDfE@r&hDgA zO6QvK)?Hnp-auVP?iOTfe<>F&^K{GRiAhNbhs}-VmiZ`)*7*f^~&`s^>#pWF(TF>#&+60eBW#yfcl6N;2&EFcB3*cwNM0w|Wv9Dk0QR zK^B@pL_jztZWw`N9y;oqleNRf6)CO#@;3tvSOOvx}{;O&(5JtOs5jVp1-=^G?#-o zd{B6wkO4}aD=Mh;jHw$F6K?Ou12tvBy^DW=d75}EewyuJ9#TR|$)_V0E0rZ1P0FYM zLmf)%iWR7=Pf<}xWg~J(z(+)dh^vSKW0j=hO6u51X#(+@GJGn5aUhaz@p)YUabby5 zQgH<;>;Mg(PHrX0_6V^@lsRF~Y;W_x#Kniwmv;MCm`t^D*8U9>R~}<)s_G;lHZGb4 z#Kr^L>4I6IMvtX1r+U)?&T!IWh1bS(;XFF`sYg%X4yT zbGbar+^Vd-Bh%f7c%00QpQe8HH^QKAYCO)lq{t-%u|^@SjC=*{81RD9n1$=J6i_Ca zDHTkVOs~&kz!}cc4#7HIs7S=B3hix8pT!5Ms(ekJKEc%F2~&-6r_gUl5-y>qv_Bec zxb)byw7jS7>l(c9oifiandRp{{}tFXTYQ*pKpb-{l9fY6ruS3Tx#?&1Q%#;3AFH2g zsy<8Dt+EZhV}Wra8;>4DqhZYNY8(k4a^CDv$Ej=O>d;t7& zLUPIGh}oWDmc$QHW-)|=|CBPzG`vhJ`$O+oU}Oq6GXR@(I)Y}bKhEnyktfINT++%q z4D~OV1BUt+!F(_MeF6uT(XME`I!%|w7e9^lBX&{Ece@=D&GvkIUak|<%{fSdK^ z)i#h}=ggZoCw6@Pf(7$auMzVLu;1eNdQSW_eG;$zx7xKo4zFwcQdq+u;_F|g4<}#8 z@%;6B`PyoHP{=OOaCcdmLEbyidli!caUqi z4X+#a$iL&fe$D5_;6bCfmmqJE|50^WLjNLNmV5#&$9bEQ>2+B`Ayfe6DUX4%zV2|H zz0f{uAd&poeY1AL*Yhk0k5hdt6LSZfBC5lhlPSs~kiWr|(~tOKgW?L>(T}Iea`xdF zGKQ}~JIhQ=+GB`gmud%TeIl5>8P9+OclJWGSPYdTA6bi~RDqK;$ir;VVj-UyTYt}O zL;VNt9PGbk-(cU5fBdJx??3wJ_XoNCs*ImzD)@x-dd#a<#@`eo>~ExqRFb_Br;SR? zLq*9=1qE|mW;+mELl%9#!>Kw!i9uIDK_d=GlMrd&F?ZImYxel)rqJj- z|6EtJZH*j_Nwqe6Wqw^#T@7soy@O!=hEH6*{J_FO7d7Xcd13Gi;W@GYDxdLVm#c4Z zZ4W=Ii{o#y!^}c_Wb3IsO%nyK^_*%a_{=0B#0yY6(Hk{sVkbUb>;z-66t$Cj=nG;{ zJ2~9Cv31Evg=ci6va-77&~+1+jrtruS9!G@rLFBlmo>F@H?Q-R1>EcV`ZiXz`0|$w zw9L`3YnVQbKFIb{&I{2yNxH@#S??s5;3XnaiTs7xCL*-5E{=x3Sder7y5Pwq$VN5l-_(T?vXNV#|jXFq( zCp1rx%{H}}RNx#Vb8q-yn{TKxK98sg`Jd;?{J!!Go4DbsL-ZTNtQq%Nq}~Dq$7XoJEH!M#xKhw(1=f9 z3D$30_*1w6~zW^tS$xQgR=)4yi!>t@+twcsL;j<1;d7h%sYpE$QRWVXjnkmvpG4A3 zQrddM7lHDWQ4)G!Ad*vESzc=KyZy+*Lk3qPlF%_38pKVLjvP+t9akWOE%(S`f3)Y75lyGer-&xu)$!kuYr&^A? z!EnVun8H)_>Qg*(S*@!Jam2jkJeukD?D75T&I1y3J)ZO1ntN; zh6)dCVjaJ7LMI$I1UHmd(f%*47@)^i)zqwNcrQ@ab(eN7V6CZ*_{cXS`B_wAZcqkr zIRsfWOH81$2+S79r~^>cb(I|te&3> z8%N%7?h+<|zF^`}S*m7bri32=koRO9;i-M3W`KyAYu}Kk4&|wEZ!-rsMZ&VwO zY+?b}#QDX=gcN&=z3!5t!h(FrJ35`P)iX8yLeM!0wz9C^y`ceonNlSf@>)Y)Sz)`! z)YwDnSdCC!nfZymj$E2WSH3QeuU)&}Js*7h<1~X6x0V&$zhPZ@O`0M+7VD3>x5OU5 zdUXJCsr1gGd%8N z-|y=B!yk@wDU*?b$6k8r<(J>NebFTs61T)e`L3uYF5GWOa(w>HfpA*w~PgqS--p%4)K(Q~ngv~$mL{i)f z&nZIKeaI(1=Nt^k|3{re;-qo2o36)Wg_hDU##Zu^1b#m)J}g*Jk83qwgCfYCF9%mq z7~s9JO$w8wq~R!$p|=vYnud4qc8%f~C>EB$Se&a^7^5*1MH4LJYOMS*`m5|iKf?|+ z&__B}$0E@23g#umhuP;a&vcG?K@s!6eqQWzP``a2z1gyi*KpG>Zrm7ql2>s9e*7m* zw~-Mq`hdmp(?SSi#f$NM=!=}e!i2Fu;u#Hn`6L!58N@~!Bf&&paZU1{x{~F+d88{d zlaSP^UD*lQP!zaAg+mZs!xQ%UeOF!dGQBkWr;$Lz#)d|^W3YeCIu_o%Hui3147`hKVX!NNo$t_bv)WCMgT7r6L&v`bZU1lg%6L(mgHjnd2Lv#~G>b4+j% zA@o0l0pgJW6l3N$hZD~b{SWpua7J~_DsxYN#0kBYn6Po`ujEhFtI~fyMUV>SVb=wz z{v+q7(Z8^#Z`ux%xe4l~-;NKnJQl`k?U^|?%GVzNqbG$%;t@*m^$&PYH0-C+z{12%Y9rO@D9On? zK0;SfGdv+KuKJWmx}cpXigc@Lnp_B)pqzQEV5=+b++qhGzUPMEp@w63J$(O7*VP}Y zKYAk##-4xgz4zXuK`Q?G*U)DhdWZgnKE>KdDQS<)^HWjsX?jlCl(H<;b2>}NsSvgr zMi4~=Xg#GQ;B)(Ym5K}<=>gZ&D=HKHKLg%WmU@tutPSp;w`BIV_G^|cDQ+&E(GY5E zv((P02?V?|i#z%+XKiH*sy5`A+FKfzRW4hc=PdL2%Qm@73Ox4QPWV-><>_Eyl0%9j z`B_|~2^>imsx#%0E(fSE$+?woqaG2;FgcE-rG4oON6qQ<;Rm0ew|Z`DB@4eadsVBM zej)LkFo!UccqGuvWoZ@ATS$8r9e7{ib-^4XkOW|4QGA#k5@wQ2;vtJ73yM>;m*ci&~< zUqSjzTc<_1PHS+T-XwS6J(Ey3DNM5Ac}oMPW2c#t4pd3t_YTXQ;RYimTa;1f-5@4R z--#Z`&M0VG;4LZ0GP_v#%(L|QPw(D2Umed5bPiI^e<>q`-GMf9e_}phYnZSC{|?08 zV)IxVVFKJgzL#=Ym?$Jal1nH>B^=}RYa5Aknptl2;V6BPJ{JqY1Fu~#oDWR+n*ROt zZ}|Nd{5y>h`XhWFb=2bT#@}KB+P;!VVFs>)Br?(gbJ+zJ~L z6{I8i^Vf7(XU?`)KYZ)uyKeeoTbEBBmWw>}{@9o3a-MH~iwU@QH}Sm-twM-E^5VZ{ zKV}0&CAp-S+#5+Npt6ul35Fe(p8iOHh=L$)#2WNXAg3)Wg1muX^(s*m0%`#Y>Cu2E ze_}KR{f~1EhHy_1LEZm+!vM9mI#m@+n@KK!K+Nt9VJ&kw6tp`Wb{SL$N>!i3smijQ z{rL7nM-NZp|NO9h!Q$9o7j$;DJ-Axqn$tPq!31)!Qx6PPqrD z43Ik}g#I1wg{a`Y&%;{nFtL!DNEP%v6(|)L*gc>}ZjeB0#g*Kb7J|L|WH}eTR!%%X zmS(U%tkTzy6}Oi4kKRyGHOmW|^G6Q*met?=PW_A`P({YQ79VC?6K4*{xqzGIGRW89 zc}LPoIvzS;SHYLpRa)5AF*UX#`Y0Et3C9}f_Y=?YpYVH&BLXf=UvOQS!0}GaXDUA@WnCpE73!f=YjSPZowrBO~ zbt5eN&Dj4AuKEgLa5LF5w42scpHP#0nZ_ryW?Iy2k^wi?XY>hmB^Uh7AMHDM(aX0{ z&)mUH4Pm-x&Ct3L`urB{XNiFR;A1RI(nuDulUb1_==H%-aFKy4Y6d)gH4w=2NLO|? zTxzyG+h$c$gjrHA*spp)m<1%Og93UzKKuGrS8e&;iD>jhG`P0Dp{ky4AM9VVmZrttVc}<=eKz)9Z&~RB{5;Hz zzeRt8=fShM?;)24=R+Y0M;deultR!z0lSkTd{PL^4c*=Hs1{$q11GT`4NoF}t{4i~ zp*-Vnp3&BxE9NiQyQI0lv@JL*v`~5B1+g>iomn*7UD1Bsx}j?ql$7+8FPJ~NXsHXu z3De_m(I;3N$tQCot+`Z`oKz6alrrFlin<>Nt$KJmVyYjQPx3s_n~(c}7|d(RkVcgf zkmo#j__A4jo;i8-o^A5?z9%&`xa$h$m-V->wmWXVOQk(S?ql+R|N4L8q;ZKmC z;Q85)HvAPrXczj?K+tFA4^DC0{(k&o@?SU(>pI}vWf!4e9gZ|uDV4$JV4b=cHHz$L z@dnV~^U(9KqddLEYc=r=VCOA3p*of)A{&FuJQ^*pYW7EOp^s%A3ooVnwhW&WeA2D|y_(S17) zrbnXDd6olPnrF^zZkjo>iM8E*?AU#W_Poi$KihG6%(iBHY-sh^Ch+&5`Wy5G!z7c~ z;n`ELY!I}d5fwtUUO*)h9u_*m_AFac(gcD>6@?BoNfWEq5rDoL?bvY7!BE5AE1H9w zgXM6@KKI;zJC-yLt&aWebF0cK5D&SS?POt6NSY(zd`cv)X@YVlSXcnL5(!IscM<;54p&ae*+=)paIV&VVVab=1LB@A(+0Qxgo;7w)%{R6BGRMyC-{^8>4 zA9=JZBO@a#Ba7n-U}-=$BMeczChW1^yNP-uSAF|S-#j!lv-yP=UU&h6oyxC)1g&6VGt!uy!Avq-v}B?t zi9!P$VxnX_F`4860y9DoKaX@_t8SQxSvHDU7{xbUJhrv^x|$u=e`e`1rX1`3)+KMg z{`%{$(>b4AzWlTIV%!}UR5UAkYj0@JlBT_pN4j!zbMtcZ zQgk&kQ>K!ttKoNsg;htE`mXe~UEjYW8vVg8`rIWQu|KU{`}!Miy#D&@Ed1VsD^@&s z&pn{)%}7x^OrH|kh)e<`6sdPwn8;|SEQx|h76$wbXfy)37%aF**XkX2TnrBRYE_b5 zl~nOUa+rXeaw8&!p)k0L3a5`{F}uy-ROn}p^&bmeb13%ZrOW4pMhEZyJw5a}WzFix zXH;4oxo*L9%{46p1OM<22Ai@oDyo+DPHxzE*NU#&{N{|z^bA`@H|T(9=Ok00-zIR2 zd3>Bfti(lTN18S1{}BbH|7A*PVUku{M7nG?06lFkTdvaqZf*{`xjwUO*IXz~bPaMT zI#)PIAHM0PD-YZ}_llL_Im-J=Yq)8S^nThd)^^Vg$L_l~I(WEa)54`o7smE3S$RL& zD15%^SUbrf9g%bsWyB1Emyno%09GZ8afTv7cX?3#Y9|E#VhkG=6au7|Cv*)wV)gnk zrk|oUB6!WW?_QeI)>2kkm}$+iNtb^a!;7Ad`RcHw+G3sPe*ivQCtN{1()FNMY`&X5 zNc_a~70OQdPXsG5<`2Z*5_f|=MT|iZO>8sR*?1haN8oI%j#P*cV`2+M$bRauBV&0C zPNPhciS|JS`(Q;$ES+5Y%2ik0*wH~R%c0Ni?mu&;|2NxtJmq69Joj27vvMhuA)Za< z%ZW^&uN#+ICu?;*5q-5h!0h#T6gj20a`Nm;YJ<2EwL9h2GyPEjutPmVqq;Q6PwHzt zzh&XgH&$%{fSJbs5g!)jurP6FuMe zQbBau1tvoK3(5eVQ96ws;i!;YLRnUZh@uqAT|S@N7qI%ubo>HQP$7v zbgYC*k?jc9>%b{}YHNS6zB}R$TiwO(+RD0&O>NU6q^*dc4z5Y_OTn`G**TeQYKc`{ zm)Fh{m}z4qm<=8WTo_X%He$lAO=JzE!(5mzPk>> zvK3>NdJP5q=5?^v90!C|=C~SQWSBLv8E|bTQ^;5|qOcLO28W{mZ8)FcxYjj}bm}5k zhzQ*^p4C`%J0A6$L)2Q2*BRad?k37GH{Q`bM!%8;bZ`4MrKkTlZ z4a+36h(VQY7*j`2MWd$>L;A~KSoqafIffJ;W}DG}sfd*76}W^kEk=SY>h$20hK#Cg z^O$8Ez){!<93Vxg2j}k-23eRC16q(rnKH#TDTE11^1%{C&0PQ}I!^%Ogw_cjue0R2eEu?s&wVmTNTib7F-V7yDu{%)dWT(h;<@gT?QDH( zbADq-bD*^L;3pRBT~fEiJG-*BrK59xT3KJmf>kdUd%U%|1rKa4@ki>~>dp7uJap{> zXKr8N+O?y@9pQP)yXV)<%9&N#R8pkrMgYE04)KqR3e2C!M4>#O2%sv1;k+n70(b(^ zUb0RXDk>DZe7*{w7u*lgkdTLFgHzB3O$ov&%L;wiAO*4MGLAa5*UxO}=$KQ|P%<}v z@r+rEbakQGHQ9Gvh490&^0jM6*5>9e&kx8v21$z#BTk+U`wycMx<-aDS=)e#lhFu{ zQmxA|1n0D&draMQ4}C6+J{P+W_u$s892@ut_VfVU*Tl~x?e8qeMPwj)l{k$@d5VVr z96x*Td8J?u@Ce41xOAj@V{}vZLwD_%xPy}3FMOewhTnf5_3ww7g3oGAq$(@jB#Dv$ zW{8)xgN7y;AN^sqsv$c6rZTCsW4M+D#kp`20P0_N~6-(-*^Y^~x)B1~s2J z5&JvvhCxrE8F9F#NXVMdQ-C^pS!5dk>ws>jJfo8cbREQjI5xT#c%)8+vV$sX9#cn( z=9H~kf2_Q^*?SCrTf?)1)kRc+Cz~el^IY_D?G{OpKpFx3S^`i9QV=-Qkx1_3l3csh zZNn>uFdyN5@DUAi2Z*KngIWEfHxv~I%kvRUcV-MM13bNAhJ4?rWoH6YCj|W-71leO zQjz04K#qb*@JKp|@PNXx#cKr&pE!*84p8~%qoYx@8qrXXj_Y{eV&UIa@ja^BNJKW^ z3{9glV|b3r62o4OT6bCFF={7vk81H6*BhJb;lYN?S3BE0rjF~sJTwZceG&{6{PdRL zPKYo69)F8HgfV&Jy%e-YiPldp_DVkfgdG7W@nWkmKPWyn#RBOq+_M-j!j?it5Ges&E+~jgD z_51c*vSeOKV{y5oD5rAIfxC{D-@X9)sKa_>;d<1PMsh#DK%18;vX4rNLMd^nCKMsa zPkC9?U)I*dud4!>O)Q~Kkg6U~sC4B+xs1p}$|eXACDIF{2{d_~Dm753bPYt*y1Kf? zx<;R;qSRaNR@3AH!}3fc9dJR56`VCcs7nX5_is)=-?CMxc@6noI$&W<)@2)~T|%C_ zOk%72oM!nfObWn9bWtYh@q>VST#)oLdL8#_ctizp$~j^O&3Ow4ff&F9tgf>b+h_U8 zmPez(LpR>h8qouX7fZdrW8v3c`%7jw=0c_TFk6opM}4G5ulZ;AToaLiXQE|l6L!r? ztWco{kM@)zeydw$>wCunn~eEmdM!FCDH-HMZpw!_V>|q|z6Sg`7l2#_>OE(#f#vM@ zDOsG)@)C45^uF}Vre1WxlJ@1gkLl-4Ew;Z7uJ>$54^P&-_%Qvses0(k_4Y&}0+WOd z(4c_PHOTQZq(2?Rp%u^r6-GtIeQR$hs|dTnav!G|S3oNCu}AA? z6ul2iR~8>;zhhyN3)s9p!z=(+Mwkp}8Mce$r&ek-l1p--JCSBa;c};~g#TUdSfC?a zV8hpqN-XW@jIRv#J?w)!{j-ja`Tp2NbaKhk=8~VXaBM%l2JSc1X#?jA^5&fLl~w`m z#1pSK>aUwW0LO%L$k;bA*I>qYAGlSIW8NJ(Km7BAk%IVJ%+A_~jpTvnt5PQ9U~N1c zO%g?kdja9_!X%5Vh;*S|d7j;s>jb@Wx6P0-1TZD+MoS8kk63vfq|xh+T(*C|L^mjx zmCY@lTQxp6+$6q6cd)kGZ<@UOuImd6Zpw2k_4{JB_MY4E8u;Ac+9d2{Vg3O09piB# z#s5N|#cP|ZUmJ4>wgexB?T0<||52O>Yv$i#^YFU93g?9R1EA|*FM_w|6T)obkuF2r z=3aVYDsIEM8F;OnKf#vr`;D9p{7!t`{6WC@`Yz&0Bhcd&--X{oUIC7WTof~Z;7>f? z6!?2)QU*sYFeBCgyIZ$pI{0HIW-zK?$*h`(>sEfUWK11H)F*a7Ce*hl?$2ZRTNfkW z<^%Fs^l|?;?xRnzFv$m2QYICp3@V7M6X>y&NfQe2%Mg7cA`wJkEeL3v28hYzf~;en z1RzvO$+ujn;ZV@gE-CF|K&6HfCT=i+PfaFDz7eS6{h=Ut?1K2jX;ZUA8Ol1Cg!SHf zp*J_NYhiJ~mBNLwz`wI?EU)3#eC8li6Zn+J;5#qZ?QOl$g9dy`=Y*)>!vfctVxADB z>_H5lj&heBircg#p-MCso&{hL_tfHSCmq?e@s8Wp4qppy`wbh`-TvBZv9&*Y;)$QF zjS)sHgwPi-hi}1X9_p{DupT7#r{O7B($%aCl19>eZr~|UmHP_8U`P#Nk}gPJczNrA zD<|eQgzCq@+OAnQu>PB|ny*w*q>MFKlPVltED3Bq8}W$q}0 z=O>cYQ0iSox=Kn)%1TPTHlOPE`ru-Hynq{v=P)J=VmCIuJ~JqWwNxGZ>Aa2M_4Ne{ zYwK4v?%z2#N*hY5#G|p^+=lV8l32~+^)u%CipzWFjEsLX_PNC~L$jOee${gIrphXK zDvINOWd~Rj@sqm9jC?HEmSL|-j3THqL||JOlH;~Ax6f_$0j{D=F_2Pp?S!Ih*;sXb zpn0Ta;YeWC$XIP{L+FbA`}Q`@YPNfFOUlKg@leM|&CIrqBc+w4{`ItXps^!=O^K_q zb!IJpj*H{N^areoSQ0PU0fRC!jK`a*8<;!~FRg%0C00M`uS>3_?b(60n`2qgt6A3Rx9 z4z^Y(!n(c~jfgogl-(s%Om z1Jdum&3=#aS#hkuX3kbJNSNr!f_P225=b)E)=+FP=-^Cwr==Sk!;o$)u;1Uae(i@J zS-vvTGs z&KfX!^*%IgK)hpy0p&3^}G!L)8fao+u~^qLj%Jl#-Urr4|c7 z7J>aT2;NTMp@Fd33q>5H*aplAFpHsNh{NmgTjd}J`bf_ApM7=$LLJtwl>;5t99!Lh zp$>Rj6Fp?;_Tm2OE4+yedvm%sN}-VbU)g zlpZO0)GRFJs535eT~W!L-~=jd(SgOQr7MaiYi_BBslLq5rJWF#{r8U{`Ou-Go4;FI zd-IYdv4ZgW>e?&BkYLOm#zE&02RRhWGU}L00cqnZaM5NBj`D;~m0|+{<&rSe^FRn) zBd2wuuhtG`sKT^F&a00di{<9#<~nli0kc={GXQ5LJdqPk4`63c=5Rthp>kDKXE0FQ zGV#Lx%8y6`tRud5T4sFI~gd4_HepOFj!ajw7**twcKLB7QO$>o-z$ zMkc0f$~l+Q@-*|NY<G5I~IJW4^%qcn%Z5#j9Zt3zwo8sabM*H+|t^?B6WdVOH|nFH}) zl_saO@Sl!31HbznCQ>^09DnvFKl#Z|;_-Wi4jppdbkj`|Z(7FM|6;q))Wk@z3$?G+ zPZM;mU=|`Yac4r5>_WA%NG6qYBUAo9!UVQry4@s|?#S&X5mBF}K=E`(`^3eh@-%S~ zq|!5}4Sn!)}Jh_tH+ zW9{g@>!6sP$rNlCuP%&36vLonLE@hR692L@GBUIokO`?%X>7#-DJUtE(OX{%-Ti|n zzkl!Cp`m;3VHYm<(G1!g|6)=H?ZSBl<-h5>@V5f+FnDa#5_W+IL`9k}swkuKJavT9 zc5t@93`hrvf@Un>2~l!vSn6P8VC*8~w`r`!Uav7Mgax+b@;xtIc==C<*@erWp)V%+ z9sN&sfn<_}JQvbAJ+Z4Dq+#?Zbtw8AF%MA^2nYmH&J(}{g#t?+!x%x4R)AWQO#kv? z`qvNNefedY6<l`|}#YA#RPB23Qp+2Btf$g6MCa0Ij zHj0rjefCUG&za@R&-V15T{bv4e_-C=;Jl6B`yRVAeE;s94=fsfVAqZZMz$R|apC~{ zi@!R~*N*%c&rK%9Cd zy8v<+vuyqTlPC8}dp3mh z1MsG}Y*EiHOsN5^k_a5wE!bi(pR|K30Iw31e1LosDFpjMC$&(K5=XUVO@{`WM;swUTjbj%L20aj2su%UV#=zEdKe_MBjrUMx{7+OtACG^9 zO7+yuga~Eq0?`vIagud0t(mF?CnYHF0l1zMQp40LLA{1ZL9lCxLXp~}Y1v`YNJ3O2 zsPJPIyuq zJv|vW9XxWgvbQ(m>@|y)sOZM*hadXn;9^z$!un zPOVU+Rxd|^X=17MvtR=ubeQ+Zv?vBS+g4&Vo6SmGQj?t7rVr~)7OOt2uc?XX*)yk) zojZPFqG9go)<$+A{_dv3InO?ub7&*Yi2tE^u7;kAZ`ICiq7c0lBn0oSmyAAT(L!Xg z#O`f`F`k;ykM)eW0*ZG5YB~T`7F!L7nv@Jfy(8==0D1sLW}#4`HK4bsHBuTcMnp&C z_!N`HVl|7AuteGEGiQ5Z9XsBRmEYAnU@k9uds}Nu?@deDrG&Co;`(NL= zYiNDUuyJeP*veIRFM{(4i4jk-?+~9BGuMe?1?QL0{^4Z1K-$T9q@g7QF19>gAlp;z z^lV!D0l7UfDHNu)f12Ezd`~phPAkZ-lkI8am2dI!i60U|=LvTbA31>b^s^N0?EF4K zI|U=4pgD_JyvX0_Wt71r{%#@+3M?>$M^7D-JOUQX;q=ZaCq+%vdc7V_iV@kn*Zkvi z=crd^?0bO0!5!a;vV>F<-T`}x8WI>Blw%OPg5ngC7f-U6Ft$@gm6R%nVF+%&Qr`Y# zK#e93BQh|c%Pi{I&LdmSZ8^d&#J}~z<>%SlFVSj=HiOK`6d>O)5=>O!nbeVdvh67) zgiFDxEF2t-S>)JTIFy0_pG$f$(FN#(5mt!^=*q=#s(v7ec1aRj&3i}W2L;j(fc$#B zK40%B2pM6a(o#iv7$s(k%DF2yAKr1(jw8Kimn}cj^9$fN{R6#Ueb)NbuUekDW5)v{ z!}st0Gq4+wHehXo36T}D3&cgLo^(;UUJD2u$oASnde#y6a|CF_Vqh`z#x8hELEuor zU6G0a)YOE-YCZ{z6{R9I^%oUbYN}UlTkyc%yY$y?-<03dFg`Rqe%czyGdS{1p_`Aa zx_4~f-t|qr5qq$|an1;jfC9fF$kDkHo;(53S;k_?gK01VnM{%gDYf%1;3B(;03tqA z(w;u;Shk#I9q@vjZ#2tQjxdx?{o{k78k^5j;M#SLKA~ex7qfF#W~k#oXBYOtTICW# zUtt%BhIC#~g3+1F5dfD6hG?#H$o$0)O3^NOY&QfvqjU{mBmx~6dkO*~kRqN(EJ<c`#h*O=uJ?MH{pOo==fSv%ZR^hW1tz>O1*KA-aqNM`WP$s0|6r)LFhmsP~-U~H_J3!&U0Gl2--cFJlp`cKQ z1>tcP69)ZbF)g^bM7>U}aTFWFdT~m)qbL}|f-&5E?i{OKJ2DupG`Y;R;xGT>qrW)6 z5HvFIagAkZW94)wog4pJ{CBWsAP3ydE)gTy9?RBJM)a8iQSiulz~o9r&ZBPBAppD} z+)of%@I>*;3Eu&oF{f<6ff^gT;kr%*{(H*g_v4-#g|IOy*Uy498$mC={FD36%*!8W z4MZKq`A(}-cj6ouE56v%Y&0&^=Xv8lkN*kyg@q7dGtzA%&|4KH{|0oMe-F@M6~x{O znzM}O*+ZRD(07>fCrIDH_6ag0BR@r+4*m1kCE_5%v0Sj)gxcEt>^(gIZyh|Gh< zmXZ71kP^rvs9@D0C2-oRJ0Y2vC&%_>7=@k!Hx_g=N?dVkfj`%I_EEV>^_I7nCm&UIPGR zz(v>&fK)IZaO4uiMu^adzpIzV|1quoOT?!&Olh|yWlx|bO!;D(?8#+PQ+hkM5eRn? zpArm9g60%`6W%Yi?@6|Qi2jJTCu&h9lE!Pb^iMdS@) ze7Jtl56g?|o~TV*N0F~1j1c%blq71?))V?+f1qELd_J|VB41bhg?HuOPg`GjUf|EO zIQH8TwQ1`N&x39WGkiO(UtaH-{cvv1CeMwae1$x~f0qz;Yx3McJFnRc=cYOB+`K|Z z;T)veVgA2QoByk6 z^Z#?&{9jF*|0mPt|7zO&A4{A6t7-GUKW+Z6rp^BoY4d+onm?TTPvY$~OQT3;07~QmDXo;1AHw?|*q>Qg{v9Ie&OV`Yss% zI=1umd4moo-~Tmi=ltOfTAzIXH?f`bhc{?5wp$XDlFrY+_tWH&054Tz1JY}1OWP<>{1lWYYm#{XI)DC=!w||KK5PuiwWBR_lCGQI%Q}*R8d0z;b zvM+DR`$EW+eR)gX7hDI}cfK!g$@@aclzn+i+80=dr*S-|UvJT(eG9R%Kk(`a?cycsKrW6#kM~j9IPy=n;Iu7<5(gnI6YJCGq zIOco;?J$TN+XttN0i}>B7*XuNxJiY;6kwOfcXU%gATj3U5t1k7`CR$LMyw@9Zf}PG zA*%&drx1@S#Ii8Fykbo>7!+yKyj;V+(x9ak#RiMjXcbgulT{6I zS=gpsSXm@(-<*O^NqyO`@JL!ZgZtZF+smYB+DqElWLw%WaW*qDt;wHsp zVJyo;84Z}T1a3Hh#Y$TDI=OW(=|Y^XgDadKkEhsE%3M+#9a{7m6SzIk?P`LxSIa(!216Eb8kG*zg={< zmb8pC^cxH=o6%-B#z#LIZYr~S7sUn!(9Xweg9OR8m<7r`gEQPq8MRS?z9r~>g$pg!c@u>Y!51? zZA(J+u87B9R2*u_ol{v{QRZtB8$+9$)*ZTO|BmI%=WzAubsm?~x7;gwgC@(6%Qrl* zPj6c>w;yuy5+Z$?y+ORBA(rVte8KE2JmHWs2KoUy8#}?-o8~}W3^s;&V^4WKZYR^2 ziYYFC@--SGTpd4lk}LD)dDfyTrNIkK6i#H|ywb_ThtH z9Ib0`f^WDF^|D^DLv75}XcMJ-lH@S8W`%6C;* zC#=VFwXMsUZ_&WzPv}?;)+@e+9vEuZ=T|R~{pY#t9g;~*#7Q=Ao0w-N7)ECb3A=OO|Xb=5Y}% ziAe(WWi-TnK_STG4uG?|NS^}&9XF0WX`>o*aTH)hg29MB{B2`iQBTLjBYrV!eeOUn zy_PUiotR_=%!_MM5X&|hGqp;pB3&vfIX~c);8c`e>4sNQ2)l-thC)V_1QX)N-ZvX&>T(Uo}`PRu{vc6+*^v84E=p-qLRNR#p3NsBUy^zUhH*j@VdjV84j0 zAHU_Htrca17ax!JdKoRMaAvIG>(-G7Fe5V%JL!(;&6H8QMi9VMo0BasVoVR7m#(Qn z6wt=#u5_3AQwEi z5BNx%eean^A1)iJyq^B{M-S7-T$e9@doof6_tKjX>37&WBnd~#KnN|aY7E7M!gO#v*z72C6%>^h#&RPyvAnw4 z>Us|nmfT>dt-pM{yS^o|te(B&bPX8vCBee7)v=m_%AnN}ii9|YvFoiCy(_$+WpGKh zu6s^JU$Ml)e9T9(N!~264uexS?TWDuh)|Z7V>21B3MP+rkSuRWX$2@bM0lpvz^sYD z|5Zn(RKFY^A0LK)Xp9Pr1uiml>{y5;px5VtV}~M65L{@rUerqlU9Xv`jkcnm_ER_6oR+-&x@!6y zeJC!9S?hE9`>2k_$LS}Os#RGUtkuRyOTy3m%tvyFoh*&z0;hz!fh=8ivZAvOTpoiM z3!9P$U|~5Yg&0|EM>1&0%_St)o||Vjk{psfWnm?G38FC2p=Y*)=_igzpD zNu;toQsS*+zFTjYcU@2OpLF!ClV{_#Bcm&ZMwf4|gL52Ai1d5RM|`9$mIbbI+G8>b zg6yRQg_JIaNQgn;ga!zLAan#8WL_B45<+~$8xW8#r?~g5Y%xqnhl5S_N@t|e5)QYu z3@?rp6?m)bdWxEN^)a8@J8Uuz4wXeiX3iBCSpyDRzQtCzyldzn)SZ>iYd5oF%+_w6 z(`*GWPxLu-^@5{snpo~60wYA&0FOfrhG~Oh4!NHZqF`iY@)cYv&(`T6ipO6az;Hhr zN;}u#Dl3arheRJ2!C3d!j>g>s`%j-ev+2R-%7x~3S0qCJSsmRwbhzV=6Gv~$h<815 zIPB_fgToE@|C99RSo5MImIZj?v?p7sNUndj0GbAV4e+2CK(Z5bB$36?1;Pk&bR#ha z3W1}ijmx=^^*1Y`MO1gwTbQu^HKgJ3*9$^an4{KT&Ne$=YX+#?` zOOSD=5p8ILBl?udXY>QnmJ3&6=my^OP?)K@cDIh~oS0iwZ@-BiK0bb+cGWVvDt`a? z(D-4F4PKJ)vlp0;Scym$$26i|sSucoN!4&5;*4Wfbzw~}5URnBfy@L~W{?L7NiP1G zuC|K>g?0$n0Y|tx;s-&R2i{phe5lf^xLX>W(Ps9-@f%OZ|KxStnD4G@S-a#rFV$Le zoOy2dsT(str~6mSoBcO+&O6pIG*9#PhF$SrJsIqcbq%;HI(|oJ;;lr0{x@@zT%vkX zLuo~^QY{D}Bd`(+auxdD6Fauu`gFr!#o1t3TzK2ZzHFhs_-ncJ`1Pl&N~$+)pekJ) z0M;p~Px#pnu-FGPKJ2t1WsrKmgcb*+O z)jrf4s(r-p+3Mnt%{|HO*e!`knk94)pK3Q;e61Ov+Y*Vyza%DU8`KWQcBpB*8rwgg zn56TBCz9i>5SExo@Oy#pIg0iKGx&f-g9^w4K?G=uWoa;QG$ZZUW&!`;bQ;K+9)D~^zTu#sTnva9MM_2B#WE{q z{ud^e`MlP={5jS1F8a{rn|17ZBwSbnZIV@DJ-X&tmR`d!h)8bc#-1kghX1+Avb0(t<0vzSYhm`LbHMJD;zq;?)7YK6Sxy*OC^Es08J&XHe za}Un18!v7WtHcwB0uAn_^2LqJ*M8l|@Zq^`_lQyV;9~~ULZ6HCPx=n?5yuDiJ>#rX z9{<0+?-{>PO5UYAM@yPK5noeBN23__H5HH7%|AG|?ciW-Nr~tyDe*C%%eT;ESTwq5 zKxZ6ryXPJrUT}Taw~M@<;$n{n?il)>r9GMAd(M;)aAxtd%f9DnJM;m4&%QvA`<}0~ zWmCR%_U+3^e&@_>OnoK9mibYBhZy#*r+|4XfO!I=)C&*_wObC)8iepHi_|tF+9{KZ zIiX^ZBa(~*BDEkvNR}}H@YuIz{Mh)K#@+MwpZa>FIszj6y|)>^r2C$6V&}r69e12K zpAz7?jQJ|-A_1a$GGL$;#S}n;QC9NmujaB5=>>FvH zzxs<^W99iZdq+CKpGOmaOa$0Q_71U-l30$#Y}Dmssz{ewB`f1k$>IAKc;Nm8Q$9rJ z@!SM;2$0MK(HIN~A`OP3)cf+bJi{Kh;m~#eVzK|>1oaJ^C}E#|?2nIiJvvuEap#84 z`0weNpetU*y!A~G@aIl=@H_@dDCP%jblMZ}i_UzT)uPj|Oxh(M#~#w>55Q0RE!H%& zgqny{*g^o)6wo@P#8y51oiT6aqM_PKvuJbq^71@6Kiy-@E1uit$$4$h@nF`$v89E> znOcu`p&?ob^m(bD4u~R>>yqY8v+rAAQOpeX5gYPH1@re9jnxU=`z-rnm5h8K)3_S!eJYh67Zc8f7mTAg2!Ps?iP zeeHl=G68s(Sb0{cKF}>UEE^voLLm=!kiaM<(A8JIQ z{D*jE;U*SAa5GM8tWmXG-#*IBz5{1Qw%phfEVZoKwXJ%2!}g>4f@d|6@<4I8f}W#4 z{N~E#k6&Cs>u%Ub7Y|k~tU7s!(xJ{mUnm4fvhIYR?O<;c#yHMHMq-k^gmQHe8I5I| zDNzLcCXGTxRg06`6>n>h#6ZK#GW-A;A0D>ThM$3Ef6ElONAz%^%I*7lgqD1wR z(yc7Vs6t+V`jVvFa8-o8w4}9SVPu~@x3gjXnpV5ZnwQ_%#)>{s9RG1qi^FxYrj34b z&8EK1HT#-suid?QwNkY-OY`Mri#Og}5WU85b~&W$;GLVqJC{dPPwE6(0apqP8X(Hd zxJ4k(%$;(1(qx+1?hM#AM6_+>lMvY#%k@wuSP`QK^pMWp$F1P%KxrQw9B4B_-3)^3 z`O$(vQ_480<%2k>1tbPWAajON6b0cqM(05sv(xDeIfKQ4QlPa8i&b650Avx>HhGEB z3&K=j`vBXLNbl~(e&U8XvF>5AW; zJbS}6UDx)sbb9^943;^%yt{tEz(@Fcf{e{&r1y@4oF*0h^>L6_5`1PCctG|~yqpM- zp9v!Ifeu0h&BuVWbDe|!0P6NBeujT{B%l`UJA^UN-YGFA{Olm|$DvrZ0ZM>SMtgFT z!m|l91V+gY@F8@iMJuP8DPhCtVUYBNrwld=CgpgiKu-y3W7ud6vxBE|1;w&!#ub9= zWb-3~!=Lg()ZyJ zK*s=tAgB_7w|0;N-UFQ;Q1&^XWS54jRSNa$tVqapVjMhK*1GJZ`2#K zn!I8~2mz(l5it_xZb>v}rp{VWB#DZNiHX+M1N-)a*=?l6TUQyWEY~%!U(}=_$0l~271~o?RN5^S=yP_0cOz|-gS`Rf z&+QF1@&$RH(%PBUenkG>sqGH1+wyZWWqdxQkkaqk4^!3;{mS@#+zx4z?n6HKo739uQ1T{` zNW7kyqy=g1j<4|cZzd+GC9ORlp!*PuaFX_>wL5>#$NxuSl7`dTT~Gopkx0Cjn56yq zy?j3IZ}9f-CMIcfTD#}7{Qa4UNt%b}493Ix!2z79H#x){@cVPbt1jz?dLJ>OOg0WVv=?V4-)|`8v(K;rUOn-QReLO zxS2xEB?MF+x>zMZlu9Sm#_NK}6BAJo#qKG6kehGP=@g29pXX&OauqoRYK^(rs18L{ zz~Ck8lPB%Jg`~Ux3(>mBf0XeU06|fCW8YK7E>BUh+f^+8@8xGwp#lHs zZ=&z(o2cim=&}1sz+_h9rkVI3#UA;imfTqR;8VpecQOAccX5%&HRYoecrM$82S^?u z(UE#`V@z)`Ge$KTOdzbMCc-kLjRG8DNY-CXn1%{UCP31;Lb*6otrbwg%*g12de^yq#Q}~-dp{++njCG z>TKEFrdWa1W6CyYb=I72Q><{JxY*+^DREO)QiA_cBpraumtrG7 zn6=$bZl9%{X&n+zL|HQ?@6_Lr1j+O zus%3{&4cvoY41t3UrTwNTRt9WA%B0cJ^gn<_T}$6Ou0;g7_3`g<*ch}(4v(eWnYcMO3 zy~-NMw6>i*5X(xZwfrDdq$p=rI+@K;XCs--q#8|EFVSi$CDx-5GsjF+Zoj?QOB9hWgr?S*UO>BpZHUDm?2^YI*+z`B3@+dp}e;erEc4 z<9QkE6{IoTFKd(H^SQqkv*T6mrNh;B40}z4>XDY zuA6YZn~zVmd&o0sXYS#8^rTiuS9-vkH{lO$=L@oOM<#sK@8l#X8z+Oqd zAM}R*Bn`xN;Ep2(JFj)D!&+$;;vx;PIoSwr zCI#TGh9p|F!%nTWY_;a(SY1|UzCFj1V-9-Lkkdsyc>7H1kQvRX-1z{Yfb>$|jfY-% z-@;4%P?H&YIRo{Mug zvnb-5xgjnb0L};$WQG6$$YsM~);cKaF5{P(FTehoN1na3ibdlU6w1R%SR&724W`0a zPzovs6+H!xiO^+s1=d{P6}_p5w!AQcl6~^~&p!Kl{8qYye(%`ovumM5J=}M|B)bIj zRhaN^$c?un#`^*|w`n#1Y$PAB?PTb$^qPNiG^>mBLBYR#hdnRbmTfiap{lh%V`jNO zUL^K+S1b6+8k>cIe%WN_jmK+lU?hfg6xtFYnS|do;=62+7uiE3hKxS zL_?f0yPC@g6c!m+J{FbKV_iQ$|FRkZEaAn8iMzh@;1@oB2a8^ge}$Gq8ZxYNCLzqj zqC`a;F&mh9q51$zBH9An7wnV-_vN{B-~QX4dW3!_UI7a#;eFkS>&NrHU_CAP_c2^g z!27y@a|OIF*h?A0ONzcn@akFiG9AS0{`gUPu0H-#>ZyxwqqotoZI3^-A^yodC@b?C zjSTAxa*R0}ixM?_51~}Tlb6;7!2AFr*o(j}dM~qKRV-cv3u6gj{>l_4`Aldn8O3@A zXjZC}_!Q8r>yKZzrDfuUaLwkb2#YRTvSQV9EE@l1N#&v^Vf_Fz>tR?gHLnFP|D6Rj ze6*AZDI6`K2Uav$su!`d?5q#ru~fEVDq78IK-5KetcQQ|p>uD?cRlnFouJ?SSj`<9 z);<2&wHzA@YfCW!Wq!<;%Y@&@dQbw~5B6QGV`?LAs7axuf`+Qpf@)2MmZ>3nR81f$ zNL~kn!I|%{8*B!fm4j1d0`j@{ zSFYJs?z*8ga$Qv!i~ewU zQ}!LVXKxsJ@#V6r4B8t1d`7qg@n$*pR4Z#EUO=svz^9U^Q_eKhDPAQGFr_R(y@gj( z29pC+*+on#387~SrqtYG`N5(yCns6-C9DGq7*YAiH-~y3*9?xv>=Fvph7?3p3TbyX04cebr!dKdNMR!>6hPC9 zP}L?9j?F_c4?vyr znV>I8%ojZKa=_Q&rR5!-sIRquAm*?2b&Xv!bfl~2Xn(Y@(BmmA^sqL!XV7FAU%h6r zC2z2={q&0QQyo7pbh!!&T&_akSrG3fuVVn_KND*tHGetKYs#ulLlE%?`TV)(Z|3Sw znf~l6t&nFw%Zk66HhGQ_2DAg>xC&!I2_$Sf{+E*hh`U2)4~2}d^?sFFjU;QfK&{pd z%jm@N4K3F$JaWso8yXv%8k-s)y4(EqubV%7VEk0)y=T7+Rp}S6-LO=O(|V0XiHBHY zCJ&{Za-2>c?emr~m8BSqG0KT4=>T3litF{Fg4{r;p}(l}#^q;BdwS+uqLGR^&+y{Y z)_^0|Y}VNtmv=2X-hIu;{L*Nl#pK7d6g>a3te6XR8kAJV@PfW6;9c^qO9SSD@-L|< zEVBqjVEP~e%UtN3JAtKOj%VjA&rrX@pco9t<$4C|%lKk$1m;RZ=(vl&vKxh)!a=_Bc zLo6*jg&HsjkEOZ-JeJxT?w*)nBnb!a`NHS#_`;b%KvYhafB`}9@^>U!1v&;(`;Z>X zwXd0)+xvk(xLG@4iX5cp__r`deDF76n*ZiDHK`r=25*=6MpCX|>Y60I2RV(YE0TYM zOv}_f4_=nTn7R_rPKst#$10~`Rw0#wxRfbW3RMlDPMmh8a#px`I7ywZM3H8tMELE0 zOza{*g}Dlw<+*cSrVhw|qYTM}=kagAuS&|ugdtwNHHBAC)EcTHY89YTN@cLMG$RA! zu>zoL1X-WaNQlvH%(Iw?f#|&mte>g27e`a&u(?jB5(Tc*iNCz@#)+1e7xshv8L6t- z{9IXoEY?pS0TGnio-C;ZEXwJ8`G5b0`e(4WTu%8%uLsgd(0kM5qJQ+?DLG7{3rYR> zfB#0h^fz9Qbh#bg|9{orNj?Mm`*eN&AMkgQ&j{R?Gwtu$^&+^Rpcl#d(Eoq`p03CJ z@847P+Q0dF%&-SztbYZ4hZ#sFQ9Y?5kaH+P&LOY!N8g#)zV)`J@4a zFK@wuQHYx&jEM9!tz`ER1F?~huk@}Hox5hcNTUI+_01__@c z0AEUQoxDsaA2$MiPY5tpLT;=Hr6ZfsYUa|B$)BOM7N>w8qv4?FQ-^B8mMGNc`(;;8 ztf7m2UOA^QkYCnRt2j{4?(1rc4Rp8U=FBmbd0wkmMZgvebFUUMiI(Vzjcn{ibRegU zdyyf{IAs`K48hKRUNwT(2_On3Q%EC6FsVSEv)y0-3!=ehu$oPo`b=F;HqjD|sL`6` zv`L77R;kqCAlT=lBIE^B$9g+rb346uwvSmoPCMJr98Mwgg=K42FI~C1p|YW|BK~&u zoZ1MkeGy_soF|#Y0TvL*6-ujbFqSl9uYxo^dwP8X02Gmo+=wS)0FaI>N0!|Lr%>xx z!7S5)XL1-sXost$BwKpVk)zjKbL7Z1{t~mf#P2V$SW5it{KZEedFrW09=W)weDmVP zo6E~KFIl>|lu)b#xt-llRHWx=%zs6EemEY0IXwme$>T|^Y=of(dkQqA!?s9ieq$F* zI;ORNiB}zphUxaRw>SOtFtaRPaayu>(;u_*#6}jyGA(8%L#^=TN#*Y0uOd9mI3z;k zp#h2r0D%L@@t~88K~|B3qiiGAklw1)CapATui6`FVmxOb&K|8=7b)Mlg*tTc1xI$2 zRTTy5+=~{SW#_{qk?6W(YqzaGa%fR$ag{gNwi8~AxkKkk0ofh11gSz9pn?K2R-kHb zE+sUD%_H9s2(kf;rZE6V!03D2STCU7D+DOeEssp)m&20G?HM^hWllx*hj4Eg@6_hy=ur(aX08uIgg%YYtB1HmB zB-I#Esm3662J_2SC3D!t*H;j?-$O7dpHfA~_H<07kK%3d}+kf`=*<$vjFR%8)Vzg;3D(IF>5e zj7LtCQJ|6|XC>P*4w~Bu_eTr_fovzOoE%UDaIoNupuRI+Cd`jIJyKP_rQ_(e?Z-w& znybqy8+(-XqpZBRxT%7b*U&FjukPsB5qtFRou6DyA1F_0MbP67T}iZ{eG*} zU+yonidJ8dU!}Dq(HLaRES_1W4uZ$g$}M?3vn&)sCnU>n+B49%tMTZXhV`*k*KPY) zMM;Ip?LX`^fpw}qCL^Y)zxD)yK3v!)(n*_8Cq8N^WwrlsZnjM_61Ah+Unxs zDr;8J!qRHs@9xAKOu^0*6I50LG;RTsp#{v}kZ}x5{9};0Q^Z9<=I%%bLz(fh2CV$; zHoNRL$i*y9vK*d4nX=y)qBW8mB}`8r9)A2**NM}*n$gHeIJT`VT1-o8$|IG9?EJ+3 z8=u(hS?k@nq^)Mn-1ZG~;t#Z}p5NRMtLNVVSl!$%JC8GiSx|7^2dA7~4hT7=WLm~t zEnw;?e=xo2Xj}Wyg$s^$v>hF892jVXf2^(R)cE)fJv}#!kDuz=uw>2JWy{vCS%PPm z5V{ThwKZwH5?K3tF~(_paogEDn*RMT{p9#^s9zpk-RpDD2}i5eR2GFw>Veb2{^cglF+FP|IZ)3zjn`e7nN8(n zku*-GA2=QV-j@zMd{6HF0ng1hFQs2CjqiLI@P@(Hbc+55);XLTi%sQY@0Z)?_3z1P zkkLHzZh39(Xk~0q|A|FI(f(-Dy26rG^h5MJ_gKTL+B&w>uj&OpW2I{eLmp#79^;?R zW4wPi9^=mwKM;>mA(OdrG~BSYqkdok+RC>URBd5t1K<{%(1faTKc8xHSN>6 zOm9o;9FGgw41xN|C(w4MLLX*|&!GI3R;z6qL;2mYpT&Pp&(j}Xeyo_~Z-I03e;ZFZ z&J?VTn23io#~Q3tdCFC|2C@u~+3m=C50+6Am0j<^GZsC5i|hI``dW!+SZd8>k%~xV z5o?>+fBj=yJZn9h7qvy!w6<-ijeo-DSuxa9-&{`^2_z<2CcAV6{c7dkQNOz7(BXai z4j9pleEk2jOV2#<#AiP9#1qeKs@T3_#g2;d9V=IEFDH~hfrebH88`5>8tO+U zB@qMUO!tClLNPWAb*en5n6nESrAl7BlR{BUKt|9Ktx2y3T_<4nM#89O=~-^P|Nh$> zUpu^Y>sI=ivE`>PKZ|z&;#vNTwK}e@Z>SvcC}yV{@PPZ%gSoJ!S?7JeqSf)Wp;^#K<7&5EqY3s z?y5T1%D+tKLN+AMs&fG*0+;8ft6Uu$YI|FHM_UdIbYD|6uVvw!wnH&pSyf|0dEs17 z&x(`mQu$CtY@tpwJW#)~wz{gjrLKD0n#%IxO1FCeYDt2=rDtFMJL+3gxKz)X`0HHV z>Opnu+hy_1k3UW*aV91iVHZd~**jC$0+Hr@>RKN_ftsp6d9S8F{ab=WYC(b8H}BNw zQ0-t{(^_khV>P{-^?%$RS=-UI4HT%hmP46YbSv6h3KNqomt8_^=?|not^7ypPbWvK z>Nj^BySDAR(c$KBNw~3FRX-w>mlQXb(()+%R`t5Bu3arp{L{Yk%Zo=G+t;!UHp6W3v9vVyUSUr#P3{*Nv6lO zgnXkVF-?ivmNlymweo}MP{Ckc9>lQc1@ipG0o0+=q;naF6T@S#s729lw>IwT@7>XG zw7Q~xZS%?_Tkb6{tH~0b<%QunRWVmreHC3W-ZW=vqgadzoL$8Ns3#k1PGW#!zO_3hnT>f*Pz z_ACsXxQ;MlPE0ZfYa`jj`q$}E2sLWWu^9CnYE-s3%8Fk&sYHqN_S21fhlchxo<4M- zB^qrxz}h}`hO19!KDOZt>z6E9{{=X=Wm27Z?QDEdVtIcxAIy#~xbKdpe?PK$^JW?w zUw%3cb)PALQekhiHj?+Z)UVzT7wlOd4er`at-0}@69)^ci$g8$g{8Z?QNs%NPtmZV zfSrf-kyAL=zlDx9J9A4#u+3m@YpOe&I))qe41Q?AfY@3XZN8>XR}ij?l!xZJJC`1x zO~=}}rm{F#;zVmA%-@qZ$2@-{9m_L#I{xAd2Oj!x?*75)I+iDF)a~`T$nOR9aOV7@eynm3Mg)w!0yC_%X zx~eU2sxj{dH0B{Q8f~sFt7_^|xw}hQMQKrMDJzf8wC4G}aa6P#w{ktJFmZyui8c|4 z6@9;Y)|>BM_lx-V=oe?|S)iXG=Mu-63Uw_v=vve4ckiWZy)W}zO4YjI$fENT&Qqs#^$R1T z)v;}Jqs3*_<&mla(6o*}hSs?e)U?*miGQMX#ZYryGn5A*LYglNFz8puG!DB#pC%93 z0HIVeF7`r3Ov(Y0kDe{Gs$v~IVMOjntEwdhK@R}*=-*Py+(wF81^<@S2&Pm7PP2rQ z92+z} zlC~!+Kj5C2OyF@e<(nK?#w_l0oW3VuMV-1QvQ}JOuD;t`AQqcdcbf`QYVpS1H!rKA z2hEogTogSF(ta*kM0x)+yic7w?D31gSwLyD2Z*m~Ftsp!6@`-d*Vn zq^&r2!;RMt?rl1K=vu=^&7Ny5|Hm3&ZU1!RnfrTgKtZOjl2&EL4}WP{Sa85`hB?{e*a^${JuAB{=6S*5T%}%`{DVI&+@#O z_B`*OI=`9yQ{ON5M-!hC*5La~q~8bAwvZvx|3=#GPP{{R(nm=qvHf+jIC}qWSyqE? zR_}kBKO-no`^d=r`6DCq-FbO#w>`^drjPF2ylL02O`CTPHqM*ZSU*(TU_&_#iYx@^ zgGBY$`Z5BWmX+VRk~Y?Mjez`DNC;g=A0;+263c-KMk}yb@f)-Yz~v9QY;{p1QPGi z&Gb6S0uO`x8xS(aEy?v4B-{PpuHS6p) zw>RIPS0K8c>F~|*d24;`zF<>Ttgb4*(s0sh3F=ijPNT^de>vY`b!25&O7oy{9bv?q z_%FJhK1vKEA7p+L6`**wzKhSmKIwE$af7;BbZMqhsAiPCELGwbe#LcXP|o_q}!HJ}>4mx~YopWS^r#hJz5Q zCz>Y+dxq*C4@>o%%BYS8(Dpdf|NS0zM;;djnDY=9Ch-iN#5Is_Py=1ZzJRe|v+@lI zNqT8ASr2V*@8zq&*su@EHu485*cZAu+vxA?t+eGiOx8*fSQ`mYCEd)PN3`>+@(sAr zgp%dS&@l8#VFjHfU^RTdp<#b>#=)My3gf`Na8e!J#h!m3yn|BA9$x}sdha(Tj6&Mx zOx`i1Usyrcr!fz{)|=P`l1HBSK)k~#rEI05!;XP>{N|ki&eWHcKQq zksuDLq+|SbI7flq>QG6cq_GZ4{ktn2l@p)117t){iCcJbz_CtN^nd{@GHFPI?OQOdu z(*C!k){nN(0DFV4AMdBnr1cll7P=0f2MahpKczoFYv^X|cg@=Gq%Cw8_Pb~8hvzrp z??WkoneX?~8oCXihx0pg{!v;(NAY=|+&^W04q8L^;`4C+@OdHq`@FP_ZpVH&f79L% zaX564USMyK98wg^&B@NvWT;h8y@6&ybewJw>(ebx)d{pyt+|+5)gg5#8j4y&VRh6> z{p;3tw5?rxYw)=7u<3Y+DK_?8cYV*Mygkk5Zg1Ix^l~V18+}?ROW6XHY9UIWKJ@0n zA*XN*7(XRG@*4RTJwq}9nPp~`FG5he6SPn=Fa?r$PgRv)tf~^}nJQ5Xhefdp-W4MM zM$70+AMjm2>+PLW+uK`9U+Sx^?S+46gCvCfE5=del3png8>*+F36HZZK)o1GVu@qA zFkynghJh825rGN)7{v@rj9;OIuRtRUf{2Uiuu&YAzNBuC;Vza3UjkpWEZ$BSF(fAG zH*gMxWP3~-paKg*@m?up(+yb&lnFbOY4Z{U#S*|aTm?khCyyXRDNRsNC@^{#M+u6- zu^3vlvI?^b{63o%=Lt5U^m#J04AnqU0Dz~EYiNY4qE?kke7&m5@2{-%uUS!%U*IhW z9d{PGJu@SLFqGeIo@pW&Ce&_BKMFS5{UVDeTVcD!-MS!fogRYI59P-PpUs{Q?Yp4W0?VqzY^_HM-q3@?+As&rvX4eLDNRQjqSd~Bzv0N zL&S_B0tn|~#t?-n-VA1lw(3dpuj~S1g(d^`WuXs?QzgT%V|EE1Z6zSjGhsw7{sB?c zu`GoGFhK))9VqirQ3$iN1OMqg#=An&QTZc%?(#2E=N|0k)#P94yCjq3k_USq&%x@y z089!8b_s@nj}gX}VF)->lQw}3orA3jLRz2ss!u|J+S#83aWnZs#)M(%wF2uO8ylPD z5~O{ZQ8b3{t*R3JRaO4Jy9|5iyYeNtTnAW&gppiAn2Fs_9K=m7@Eo0jToofq0Yaqd zN`RFc>&?++3u<-7SeBM$WGv~0c;@kB(0f59)nsUPr9X9r@v(9~6!7TTZg?3EBpK>e z@H8Y^!2c3D20stU7Gp6NA#Rs5pE!uao@cXK%qAmdL*xHxoy8QuRUn@q{zbz0FAOFE zXcyIC`Yn4yw{f3wr)i(5uEWvLW!PufW!Pt^dw!>VC;iMpiJc2Kyk>BPXXvc1l?u zB{W5kKo=#79fVR|g&ZvG3I)pctAJ1fyTTDl*f+u`z_1E}VniOM5ax}=j4l@;u0mIV z-$$GzzsRA6pmJ^&g6chH5g;d|5+z^~stKnbC|Wm-5Vh3+AyPn!`L6eP z4cxN7B_S{L76gww3p^=8PUp#sbNTy7$o&>avFHt!H3w3Joa32=>3#GdyFh#ykdq{2 z43kTEM#Jhzj^3ag5l4{oWfCv3n7F#*af63pZ?3}N^k~&m`apnD)j#fRr$W7vD>uI zw9B~9Sl8)j1PX)y{rpbHPWq*9bE@*~mABq{>#Zxl4L0gT5q+H*-YbS`$@|JddHv7F zei8pMeU?6Y`EW7o-@$S2aJ^Xu1fD}Y_!4?K@hu_{TMRJprffdndaKv$&7{AH=Y#<| z9{6WMWDh0YAX&s7vu0(gl!{bYr)8wi?}a=V1rRcBKaN`2vIp0#d$6bC)W;T1v{c;P z)>c2aFBF)YNRUnOPf?N9Q6Xa^A&E-RBj_`U%A_8V>fbc8pHPyW*h>RKC-IP~Sh<=C z3fe=Igea5%Mn(jx5LOfL0FNL+gb3Do7QIEEk11djs(x~FH)LLzArS+Ti6T&=2fU&* zP$rgFRaJ4+vJ;zWKxm{aV>$VqwClfvUB|jjn`sU9t(ehQm^e)R zLNR3-D`)h%6NjlC`&P~9vnCePDxsgUjIA^JjETjx6#KSK?IV!zPv8bS+s5MyW@l*!stFhywqsL<{Si7Ps_;!+kA+eZ$w!p8fiU#_{XUZ{L3YI)LZIdO>SxY5F^+f5&6^^fpdX_wV;?Cc8BY-UcquLljxD2;*tdU1Uj;3r z>#*;dtMnb5+D9n-z97(@SEH9kui0y3zq)LuJ9pr^$#cF6jm2l^kKzULGX`pAE_(94 zo-wej%Wu<@{C6rSrR&~%ZWXj9{tf({L?Zb+EaL#q^{;-%^mir_q>#i|6I)1p87D|7 z6*5jx1t}#ud9R+J{||R>0^de;?T?>xM>8YIn`Bv%7ulAq&9c19vK%k5yu|SuJI-o5 zn`38%EMy_jkPrx@P#~;j2|E-@DbN(c)|Q5?rL=ty`dCWo@?KLO(7rxM`=EU-$;|(A z?ntui#98R_dH)}+6^-WJnY*5I?peMkY0ju@JuiDXFMBz{smfwKn~#j1J7w+z5Wjc% zN$y$LOy=k9A=!x9qqWn*>iO@N^WW*+H0J@ZApI^8&I09EL)k9-!x60CyLZvIzJ>q& z`s?+-82ROiWf_&Va*Ykve{0dDmoCEYkzdrm{(3!spG#ea*TOz1(qF~jcNOLM1qM!h z6Zf-YkOq0s`;<*jN1Sd=%bXz!Isp-eCn_ zM_C&=%5sH5BodPO*{_<^Ac?Cv<*Df{y@8?%*8_=f_-3ig>?_!JM|QEZH0dkX|Gt6O zvd_RxZD-q2pw_ePkV*WTZ9f>IY1O{)adF|B@Cy43(xCB4J!gqphqNOS#qIOnP#)o! z2tt|ncuy$DJoSJppeDDuEHypa8z?F-(ps9o?{;b_&7}+9fFH2Wc)NgY*XSj0mo}#^ zbs78s_CeZd^ce9MPv|koQh6XTMEjD4h29(2r7`_1KF4PuC#(Ofu7^EBEf^^eJVQR+ zMgz~)OotZ}xi0c-Dx^Umo#3?Dn$2d5V6^jmCImtm@<;YW(t^uPn}TWVqfSHQ*k!`i z5d+0b?oro+p1-pznqfc&dYK_(-A05?ZDvfAiEk^RJ@DBfyO34;iGHI~1+@oQ-_Vn0 zvzcBi$RR?$w9EcTV{nscc`z*!5y~RRwh0$S44s{{4%F|c>!Dq!fOL`_)6-H@j0U}| z={>2yIxFcpEwsPP+#u(V*dr~qGg7KdRVg!SQ)+7k4_zI*RyZ&A1D{VmhI;l92z0KY zQA?rM5hws3Fd9Qhj;)KIYwT`wNN+OTEL^6o3!gfQZ?MO~0fW&@Q+kTP&|zi*AKmqGjpr*&#SL>loys)q}+H@=5-r4-IDp`n^G(1XJtONxYwM;=|mO`Fb5mq zxt!057Ug8yGEE}G6r*0pP$I)^1~Tljn;CW*ghbf2MaN^vV`0~TI8Jj*iZSjBsomv@ zF;ZP{U&vI4!{K-Mf~8*WY#U zY!Qt)ad_f{*9+w?NSZ5m5ycizCK)T!jV@fjXJL2O@|tE_ZOyq$SI=KR+SVQ&EDhTt zb>pKKoNKz{7XAEzw#s0h$6+d3*3&(fdgD#$t^G5+?(71Gxp3JcqWK`I9^DJ<0VswD zwBZe!=FnP*GPXDwldEI~Oy~|(Gnk#HE$r;XO&Rs93PG=n-JkB3ID2SFdvJhs(<27d z={Ok3k{*y{X~c+dXvK)%R+wQS>QjOU$I2$)%wwUeatax5tznj8g z;(1mZn2t;I?jpaHXM&D_Qt-^A_`yquZ~V~XNx7yVI5N0&*@7?USL*d6R{OHK){EI^ zyF<&P^D6i6*ijm;stA|5>e&O=fA`zBuT3ck`mhL<56kPb5!YP0cLkQ3@@*xBk;2x# zy*#sI^Jgaf=<=(SI!Z3Nc=_fT8VyTRkFuHU8{ma2qnUP;rEC;sO6W`2s&TZAfF4By zlJnT85rq__DE?7C&>Ch5>8=5BCCM12Ab~7O^4Ll15XYv)OyxDv!|QPuxty7vBD2|? z>2akR^Mf8TRam(%h~FIvh24=5N0!pE{mLQPZ4Jq8WIfGoeSz-M^RBlq%4(jM)$X`$ z?b`Vv=S*Kscjl*AAHHLG;Xt%xqs6joOJC2N4ZCJ6wpyYsb9(xSxBQRl#V6ROkPmw( zW2mUhLl9YaY6{O7O3OK$aBz5{(2*WS7Mmdf0mwxlW?ljvKdFmjlkY|yi5r3@Zc#lP z;vx!Zp9$179~^FTp4r0P=p-xk$IMT8v~&m!I_~0xDb9;cn<^K!m-~a+gM+J<_RaQ} zm9nc`{;F~1ivw$#bJt|L8!GYA@o?X$b6FOVFN)1<;QIGPA42^wCqM5QO zXxcNA28~2}a}quhXXjgzf7jUg7TOmYs?!n@J_m+|o($v^5kL1zlG`1Y{Sp2bvPSGO z|0AGO){uYI)~`nj7uGr#UUj4Mi5r}cS4HRK9$q&3ot*aK)|^?z$G_7)YhFwHta{k#69x`9$SG))WaHS$YJp}8i3Ul{vi0OeN%qz8l|@26Us+jpJ7w$0&Gu;Mu4WT$ zr%1@ExvGSCg4&od(`~kfs!2Wcrw1OmrlX^y<69SBf8FkivWr`1eyeZ8hQ66YICtZk z4QsLEzjw|cVu6V<$_MEQhmp=JZks)1bxV?Lar@n2nrnBMu*T@h#n>%%nSJfL*4D@G zyLs0|^$pUW|7dKi?PewT8e5QC-`6ylqkQt|;_?}N#cmy?q>rs#8h010C;ur?XG1}h zlKgH7IY^FCpxFMLg0ocwI-q3i6sZv}nK&uL0k=}j7O&fEGiU0Jj$my9YKumQ@4W=p zF9*jxp6kV0lhWYvq_nr6Gv2boJCs#cSR6Qf_}NI-#L`B99*4XM`7rNqmk+(u%7>iG&?Ml;bsg)MtXsciT}R!_>e?+0TskaIog^Ll zG~rNHC+{u7Qd38nK^TMpgrn6YLkTQj&rpy>CIF?7U_f^4F)k;QvNUGO_2zrI=o-u1 za3-RWVddiW7tinNT3!<+(P-JKdFxlUx3~3cqS4A-8%%c}Fb>XZuL?Rm`KF>3z1^!) z4;)Bu8>siYvkM)Wh08f6iU3B{qw8gdpcv|)4OdK+jjA=-s3tU>Y*fuJBnWz)ZpD}|Zof&O2 zNYbebL{1^;kXl?b?*-XO1sz{p(&6Y^nxJ#*^WVAp1&=4?%7W6mf#D@{I}0lG`XyQR zrE_gn?Cl*DLouIcMD!SB#OE6UeV~w)EX_ z?UntPbmtX(YQm2$yIQIH#^}JJ6+5c=ncyf3vzNg~GEO$iQVxo;h`@-hoRN&9AxnI2 z8OO(koS2N`O~^R4XCUO@tY%-kC(vEG@fzDgF6HFixO(-%ilSz3ZM*4DT*|q#&6c&% zV%c+HU(cNFdq~V_>*8V#_tybNzOK125VhsTM1gdEl9ohWOctO8cA_jW9nXI!2GohHJC82(v5TRY;6VAINVwJ` zfME#8J3=B;%a9y*2qC{EZB&Aw2L%1vcpW%Zm1udqw4f8Vf&oBpfKeGyLM9>`1yQFH z7ZD#F0-dPi(rLb<$eigiXPGliM)HM7;_E zA3-^Z$@AD6W@j&-6_1~S?Q-@!-g7!0kNP|>Hky@MuREo!ZNsY8mENJO3TL3?rI)@{ zM@+sT=v&#lUSsk()#dAYmjJ4N0AS7R5ZGYDlUX#$F{dJ@9zo_lTr2rl3pyr@8oA>O z=yb!}CD(`sFl+&xpxZjBH2I{_{0l<_Oi5m8CY#lg8Fx`JrO>pHP&Y}i6G9eC2rpT+ zZ{NOaFTecq@x!;?aQ%(Ad`@rQ1sC-7&cOxBzhOC-ZR2tY(?7zmC&|`;kfn~IDl|cm z_K?9cves0t8(!JBepyGfvm+R` z*48u+lwWwR>5iMFD&O4pieR3nz~oud-8q_m(~YDa@wx3zN2aZM4h8teWq^BPGQjQs zPsso|pIZjd$i_cgQF6xOL-=nOANog5FFxFJ-FKeV^dukSe{$(z^(B|An2;WJPa{3h zejtpYDEkKZNq)#dS;{?I`9V9Od~W%{&jpA~FV~TrT7HP1TM}B5%-N0ZR!^WKu<@F> zn&hU{;l;%vXG2kShxx;-pZ~~m=s=W95EpIj>zT9hqI}1Mres2fxDRqkpD>*aL9nMM z$`IP(J3D>C=M^pv+uOaZ_F2Bqz8w=TuH(W*T(-E6%NGBq&gy@I9J2G;xEzvnT0eIk zcKmlklpoh)c??B%ALPT)zposUKd?9&h)WhRp&~AiOe?tfr&LImLNxIw?w@_uLd#I} zR8q@HG!v(iT27{!K&ayQcmHI)#OY<0j9f2Pn3XoJm{`A}X}Nc?wItu`fBNa^6cZ=t zvM{0Bvcb&>8HTp=>17ygdpk8jW|9meY7)=c%Q|N*?CjsSZ{PT#Td&xcEbO!?@1cWq z8+sv#RT%q%7JW;*F&Z+&$Q{Rv9u!JVo%F1F!$wl)wwG2 zEID-1o6{BfeO6{_N?wjX+?HidP0h~s)wJ+-Pqh{M;BsMvwIb8M0mbCcARH`?`?A!4 z0bgU+aUb|EL5}t>eu_;0GXUP(gE=vyJAO))R5gJE!SrN8XD}1Sa1g^F#5};X{A#09 z11930TjY~M|C@8`3NzK4a1d6bpr^dw z+#ix9`$NveyKsPJ)ujBF);bF2A}0>zzhdi&a$qfChk%JZmpAxesW8HF zArE{|1)HOWih^vTPSnNEOF2f_Adt;TgyrO2&PMbCV{8czi=nR)9iMe$ycmGEh<_1b zgjeYwiaPv$hXcT0<*zIYI(!bwESU$nK94VD5+b~x+m*;vOCi(t+S(A*M&jV#It?FQ zl5HXOFDuH+N4sXO_7pE|?BL&LdsF&u70`lxR@2T=W<>cQuQC6GftsFZ`wBrpa9)*xsZ9GL(K zO#Ed?8R#Y`3eS&8mSvuMC4Rm#*VKk^xV^|<8gS*0&kICd#ihQ2{G~&}60>PpmfL&0 zVtAOox!mk0Llhv&^Uo&DJ@-=*McEtn;xCjJu(@2h0I$F|_FcB_(LImybvZHjZ=HJX z0igyiz<2Os5TPJS5!kR5$c|2NR-}Jt*k?AIxCV(pK3(|E4&@E}$_2NO&vA$9WfqnR zOgf*pvj(mB8eVoP`a!g(25(nZ;bk1(8)m9+;vi6#=+o02AJH7zOZY1sWR)oBUxnCS z!Q{Qt2pjPG_`f`Vjv?XKr3KhU@cTP<^q+rzKmWvswx2(+W5>Yx+Xr^+(E0$y_!?Ue z7HEjpnKGEzDTxecODIx`3J`UpCovQPfCVfRmtrxS4V0;Y2c`HE0V#GlWW|9Q&-}H& zD-ykQ#qVB zOr!rZzjmqb3f1gif$9G@eyw|qU;iam{|oq2Rsc-@SAHD^z<1aPxb;5+QTZ=q`oCh6 zCIxZ&O-`0g8XX6(>S49q?y2y)Spe)~VLdRt%C9M6^*`vof#?dy?&NK=f(wSC8D?ad zP0@4R)+~mxY%Ezx?n6ls7^n6sve|4do3q5{Bhf16Oq|HSS#2k6Q)cZ%-YMn5IdvO) z+s;o)FbmD5*UUCJKV{Ea>R7kAdJ?`&CJH+yuGbLH_Hhn5z(>YE#8 zQ97vjcnTbotQ5lVWsdG5VYh(TiKv^c3BCcchszAcj3}m{EQ#`%fn0t^^vH7#NfP%T z;IW;hdPD=|nGwcLtOb%zCoPJVmvsF@(W0`l{QRseovtigR#RP>Uz#8Ex(UlH$F8&J zGD}h^#25Xji^K24Sek}t8m@6qQm97R#O9$wV_8S1mGiAXANEjH5WytA*XihN+2EAw)OXFjh%EyqhnCeCn5wf9FB+#As zD4tl?hofyI=aBq3Ha$}ld9 z9MdCrdZC-AMT*PaTnSAe7@=?oTW-Gjf-ish0^Galz=2J-6WgDu?!tMn`)`uteMxfs z+0d<-_(hz@u88q1F8fa6=W)800&PzbH`Y-oJso<}wRFtff0k$Ov2dps5?)}4-(wI< z*p&h)W{ZXB5t?OkK{dO>E-QYrZ`T)RF*6GvQ%!=Ie{9%5;}NHwdT4%{0{AsoZ8E;4 z(>st+ZYRwR(W?3JlDm!eW}>ZqLr-RDf)lz0w-B*dT`*?>Z{8KCwF+UTxqS+I_PL2c` z8hR?rY~evX=(1a7m(>-H_`@#z59QYnKa7P+`^zumcUbt9$PYKH`{1_}zokM2T***7 zi|6vQcYM?3r2wX=`?VM=}r`lij_c-g=LhQBW z+F{3Ayri*%zIVnCJB@|OhnXmOc)F+*GW|lY7xaF!IW)+r@+_XR& z$N0FuHDz4iI`z2nIlllu#*0aA;&pq_itpoPBscNvd9VS0iT_J-lXf49@qI?J$}jD- ze+t#3c#OUC50*`)GTswq6V!jTFD9HU4iAOQdoC#aZfRDP(_d9x%AVc+?BxTyW5P-2 z`ilxz9=~{aNlZ8qA*{YD%wk6p{Ponbi8zgHGTL)0*<^C9f2wTqZ*kd#q>^OW zxNOp2&7~Fgwc}MY*lPvJvdO{`e`t6_dGACn$Yqm&`mXM&q_I1_Y(gV3ooq6C8rkH; zy8mZolUL%SekzG@dfDU*XX36!{EDv+B zXCMU{o{}Yjab8YrHI48lVmyvQVYFBbLc5@#D5eEmm@P5B#TmH9#F?x0i^Rk;S>ELXyByn#PrvtN(Av0>fO zKmI?=r&TqS;psWyA7DGT)P*yr!d2IyV9t?&6pVoD_3i0n^k~9IlG>>DLsZ` z9jUF2xWX=<&+m^2<;u^NugMK$AODPrdA{5=%dty&X71)ZPx>~KGk^13K)45N>^(ND zwMUPYK`%8TVi!bzge(CVVe8Y;u-m3Y<(r)bZ$P2dY(|DU+X|!)QuoT=*xskT3 zKM^w6mnO!?TU#56*byUko6T+xFt+&>9)pd&hn zmnumlrrT_GJGq(tVok0ukBP@W%MRqOS+4vH{VcjU-)Y*G?#bIc7dw&1?R?~@!<7OW@d=MDuX&-*z886 zFb}ue67tI-a|qG#H7v!_ujSeAd*GbIhtGK^)nUVQUHtkkd&SrtNp+fKou_iZPs~L;?|o6y zM4;W4n1M+{AFCT5AL$7ZklP0*#wK}CCJzU#w~6_Zo{)4nWeg^FKB?P$3>^S0m)!>< z7@#+5Fz97L_c!J<&opcKhTVcCB-kTbB*00NDc8TVY89!FG;x)=^Z?SJKQDpp!swUdY49&bg9kz1VA>RJF zN$n?*Wl}!&=t+WYPiSk-6L&oE#2wFX*|G&klm~Dahn27X`OlwfJR5*zbKcaf(6|#W z914M$?Pp3LuZB@05>g57-Mdz}UfTx~bu_dS&8|PnVONr%(c-plLOY>=X?n)qz4&e1 zcx)4H1O{Q%BfP?1hA>27e>4kGFV{s%1<>1&iIjmd?rR=2q6~VF^<#uQI|4f0XitiP zVh(xo^!ma#(Y~=b@<-C}K}ip(j+BnuV02U@{}&xMh^BnVan>skrmN`rGIBAJ|yE zro_E@$2C9Qe&IV;T=9c-H7i;pZAMFH&Eh3rILDfoms3&Y^57?>e`%^3-+JY3BloXA z_nt*r8RI4A{p704-@0(ap>;!74>SczYrn8+*R{&#`lBiHmv+n~-ARjjl>L;w422Mc z8aO9vuL*gxQ;h~$G6*aqjUo@b(=nbE+CGu7Wt4F9Ch*g8Cvu=n#8}5elr2stKy{@v z=q!OkD9AKP#;n-6UAEJx#DbQ!h~BsYoklH|4x4G(^oSp~FRSioxxtxvp|^I&`SXS^ znZ2>8wIduXU)oyebrku1UT3Q-8lF}Ab@pG_f>b5Lh zwS^8yU9gt@n*9|rpb+ZdnrMa#b#i$T6Ll3RiKI%TSV=D}O`Ry~#y|v#i4wPQFjzie z4jG}P9Mp^;G75Y#pIBoNsaZ#;(fvcw0;iMm(Kzdzk?P9Q5}(IZXe!9o^3tT7Bqugy z*s;;Nre*GP$6X;~G4p(_Ye-FhxMgVQmXVQLhlg(+>DUsDZt3VaFB(0sqo=mqT$JSr z20Yn*OQ5cMU|Csz75nSrTZV^kS*(3_wV&THds}<^w%Hx$w>MTcq^Cw2>gzHxnnJ6W zH7>3I03B4ryR46W%Ezn>YT(CD7NMw*!*W!RCxamBgv}s>K`$G|Qj%lrjfgnX1EQ!O z0lj_+k8~z&ZCRokWuag)vau8DCsm5pOkW=KAnNqusP^7PDX~mP6umzbEubNEW9gnu!rQY*=Jx8F^0P}Mf8OfiOTH(s@K_UxU#J@nZ#W4O9{ zct+iDC^THR*_qchr@_`fuchVs{PGG1`*ik2y*)cSI(GK-?3%53YM0j6FONi)*Uwm1 z`*E>x``Wdb6D;-kifD<P9T>f zl&qFkV)ltaY$L=!`iG(hpT}9?_R>!A#3Qw1c~lco{xO=s-EEUX{j+30tvx@{P@)$2 zOm6LHbYpKtbe6x|9173r4i@F*)GTibukckicX$Kls!)H=oWA_xMzc3Hy{Pi;N>6!* zKfE}QYqw(y$gO+4AVJU2ax>+ba&1{W-;@SD6L-(ihM(_eZInZg&8@B; zC@UMNuAW=!3ItsAhuZ>up-^veF?|LWl==K+rGCFAi+8Ah5YAyg;+eAaPv&Qv4XiR4 z;Z!0Ln&b*(v%0`tB*|7+_}zjp_x4<0TwizZ>hqpickZ(r&Utpz@lAO5Jqs`OanU4G^Q@rO ztPqo|R_d4=i&OIhRV`i7f@S0LX7znLU(7BG1V*J*nLV?X1gculJi4r_`IcM1)RTI`8!YkrM31EJxhgaZ~XtZZ?@n}#)oy>F#jEH3MMtLk=74(eh7bJ@72}?Fw zke?4w5-9fP`|`a-PDdV{TQky$7kMYBi3Vd@8$!2Wvsp>DviQR0kS#8=xCNKhB|JVF z+B!DArDjE|@|)*=VMw|B+5gD8{QITBVCkZN!2`-__VSF?t*bBExu#`x{qaWToxN+m z@;~g*@pt!a#>$?3v!l`3`xJ?veGu#{gIRbo*(a zFv~StHeUPOr7YvM*RU~`ljdV~AEdxq&5~vZQ5@Um7H8imJ>$7s2603$qV!-Q5lfL(Mivzf-;|RN>OKl2|QgMtTZ`NDIBtftg&8D zSMc83w%v5ow%fMu-@g^W47=4Ebk#yPWPlCw!2?04h8fTdv!E9SVKFR+)vy7!!A|f; zJv%SlvU$U~D@T_PFPuNv-!pqwYg0pAO?6qo?;(^MtC5-M@HJV`1-B&I>|vYVS{or+ zE!*t15uMM^|B*xVqs~vihCF^r4uxxFYslvZJKb>WB4M}9?y=WK+*VJ7KS^f~Q|W46 z)9SI=eSS&S@n_4r>WkmK{)rE-*k~0#K>R?kt{=~B zuPU&t>7UxO{BARd|0{o2h?|J#SlkWuASUoauClGq=Pu_~t=c)R>!XGo>0t zrmGBExE90}Q-N4W9a7{Ahh1_g?EX(p9isg8r(7FSk!Qcp=0NGE4?VG4GkE@^Pwy{?^FVa70GjV;3&Bq-hN##H)7ne6;kN6{g*)QAWJr0LW zc*LHUXFoO{8xI_4i~m2>VPogf@5isTIc}g|Z<}@d?Xzw>zR#*2iR{0%R%9f{|+9l#a1PJ2AlYmeqP`SZusPsD-5^UW!f`hj?2 z7iQu`%4Nr1L}R@DZ3p6AP;OCfn%n^kT%dj;Hu7;QgbHYeepn8h;9|HI?uKu`VR#$f zhd-f&HuPaF%xfveQuLz(?U;%(9D_f@@8JXZ1^g6Vg%{vSI0z5GJ@93?4laj1upKtT zDp&yvU;t)86v9vmUT}gHOoXxu7N|U7QZfm#)E1(gRCF?RSO1-_b${pQWhS+iqpjMA zpIbeD=hwuV?TQVH>n4Z8rdvU)>9c$CQd9Nadir?eEWYid8vBmjaTZmym;4}AUrTkD z(T6_u*cE5}gyV-&Q}t{$)ju9zov|HoSG+59^K3sJIQuHf(bQD^CyAF`y6o&9k@Qx+ zXA2-h_yYR~%#aKEC+(T3L=&JkMC*dn9j^B@N6ap+_B68{4%^){lL~O{X+@c`v_DLh3X%L z>(~x(fEUhrsxXU?JYu2BAr-Ca7Fh?3y>@yD<+U6pGBfxzBk_k z4sc`^d);P(F(-&tcRGv9cbblgGPQA}7>^`tqP=k4c-pz&x%7c=c3(2syt4L@M@%Dw zdml6}RPLIM=dCFA;%}C2dHS4(?^=G{oQioht2d>!HQlyjwXvAxbic{>?2s0Z;= z_C2V8nXoWwDdcCt3a4GqL13mo433`eFz9v_INYAZVbDF1=P-`=#!oBpgmiJxH%i5( zDT{o5zjhXUDR0NBt-a+f-NA~?@Qi^TItp$Z-88pyW^W*vSrZ=Y3wp+^>1K0Tup!r7 z^Kgx~dr^3CATQ6Bn{BeU(@D@;>+M=xH_z|LvpKR&*=>!!nf3~U*_~m@wWVhj6ggaG zRfT4}0`Fw+AT#u3Wl?MpJD8;feNfI7V0v~4Qebrt4=O&5?3(N%NJ4HLndnq5g40W` zBac41@3F`BG2d3D51$~(m1Ng=n=Ejh)}|zh^fa=ob2@=^qNRU-$#vxGU*GrjuRr$K zzDMzi16v<_aO(k0a;1G5RS)7(_89F`nXa308{SEFTtiI+4HhVCLlOd6~41 z-Rd9VIeZ0DzzzeNm$5aGtb>lu6X{9vl7FZCB=OrkKZ%xb)t+igO1PSwb|Lxub!BBv zXVM?OQmS2-Dlf;s0fQp^FFc2R!m(!O5Z0__l%TU_MiQi~hN5ZL;AH_9CBe`lxlW!G zZI({@JoSr)zLb1*Z6GDBzTI0`Qt)qyZ|oC)L59n5!Buv5zCY$LegvNAZI*_f?(b`|A7R7th_d?_69m{-rOCUqx%W0A9zh;bUNe1<|xL zk$f-Hb%a6L-E+`5usCYxkW{ND@aC5Yl)z*lFKVOeTTZw!#C5nP$SATAF{<_X{c<=G zvS!8f_#e)ZaQmhUYqRn!!SL+YTkECP@%owddc#}_frJp;fe+xbXB*EK!Y#^v{`c(o zf^q5>UWWmJR;ToYOg1q~SOdP)bYU?yjoog&+*DRFx5ZOi7|3#GIlV>x0=(`zF}V|F||*fPLIvR2PpIPh{kY(;F+D&bM++9s$tD5T^)EmLJtA^_$uK z!K+xYnhg&hr?4rSgZOi!+H=iZQ{F@M$plT%l~EfX_bn4o9;T{uwBZ&(G@EI-(d-I` z%-E;=~}-z;y5NYsz48Jl;h%f_9&fR4{es5&1(%9?y_BAY zPgZ*zE@!^4>NkfDDQ}uhCbKa;9RQU#)hzXh`qo4qHd*#Z3V!GL=`9O7FQofyi+V(8 zn7A*{{r8LCX8*dRYY*qCN(H-EJtDY3rhTf#s}Vf1T~?mo?7D8}_RvG@yY;ne`uk^( z&=@HFtVMlWpy-#-A&N-U63d+)8QH=!z6fs0hg$OFy;XOA$nF?v-Nm1IBipGS5y~J1 znx4|j)!M%AevQGbGh;bMSeFKIa5$6kuZyDB%brRotO9a3OstUa+_(k9~=;yA|L1e3Fr z#jOGq79DR8BhykWmC^2DX|A=k%`#US>J-vPI@A05(y2Xw%GcRy92ANn6>6SLl|&)_ zIu18YU?BW$ngyK0=*8Z3$Wz3v^+Zj1x}<8G9gAA_&%bM5Wj7^9>0+zB{@&JxS?vw< zo~Kn=J)%AYGPG!zH>7Z64A)FW-{#bgBXyI8J{gw#srVieT@=t^bt_L}aM7+si|<`P z#poUS*gLvn(82`7O-a%xo;6G~dQM){&TrwCsduIl7}-kO)fN8Zu0_gQix(`ohx|QM zRoTMd^*joOF9ICPiOnO0tZQp~3tOWe5quy)W;BBWDRdehxS8<41=&ptz2NG_SBLjr z#(uYVZ{rYwk^?F~VMo<}7s#(cdO{!{G1@n--+6v2%v#VzDGdOXo7hqHH^QwN*1OTb z7i|)1t+qThW2%=x=K0!;+0rGq^2x9?*H}{IDmBiPMrO04i(4`ZJ)Xjhmc@X|7WT1v zMEL5Nv|BjmqKg{m(a{Z1`42@^-vtwCP@-jkOfVu+wq=516nI9JBq&C04Vf(-FQJHQ z+1caSbx6k&30)Pc?vJ`67FVIGGFW9As1`%T)lH_fcC*uB-o@MbiF!nMB;HOQ97A~P z7Hxd}k&s<}dvEya#aGt|v*$HlbWtO3r`oT)s2)+jb;daP(j+mjvm_;>yfd$$#Mu!j zG`kCzZq4x&lmIYgt-#b@3paC_xHKA=Dp-yX2tM?urUFcncOgNKYeUYY@5&p&ptG>F zv=CWoDgPqe94sshCjSAdwd^zXH^RMVke@O+_1~PTDxa^i(kI+o;qg?^-}GzG^Sg*J zqieyr+W3j=GxY=EeaNJFHXt&xVwz9@4!OzmuK_tZa5V5C5J2d&x;;GTMu^$SWPjYk zVxjXd_6xSnA9V}HV|U*;qg3D8bUIM@)FFnxiIXqD$ihvU>Y9> zro6-cT|FYa%hy4_Muq5XL?CGtRSCe)Mx3Z>?jMOb!O4CFCp#J?&mgzml1{S5=U&_0 z-O$k8-C)hlvDtERt-`xqHQ}zVa7|ZtUUp7iUQRaIH&HpCDe8N|4WAb)giVVT@>roY z&0;iVr*&mTi|x*=v`nMPp5B!e4KO7=&1kUMJykO^(hLTx-4h}lG*muRRQ1T;k6!FO zExk}tJ)%Azrx!$zIlbWYSR`uUmz6CVL4GNT9&cfr)gwa1$?M_ddhC%{MO9VjvDxbT zLNf}6TR|sWuJH%q@;HC^2hkx^=dxDyJ)s`bz!P<8iAg4ag(tBFo_~bVSvHX~WnUmA zqpT~hAXvy+OA5_JMBm&6L7J}))vF#+e*ig97A;97k1h#;vF@BSCUjC>T1sxoIMfB@ zOe@OtdWt9ofy}L1n!A=iZqp`a6e-X(R5>ftGb){x4Z21#$8OIR=ZHD>QbTjc!eWo7 zcwvWJ#Q$ptrd-Unsz=Dv4P?+y-NT1_&mTkR+c3^zdwV0yKBh?t?g}WNd2Ku55RkM}0=c-6<|secq4AkvwS z`bjxg5Y~{k1=#}XX$%V{kL$vK+!m+YnWBRc_^M4`v|Vt#x^oVonx@>P9#LNg83Iw? z^jeh3OW&-;s~0TVy}MC)_ndxB_EOyHEcMsw*G?~!h$NG^@w?w1AE!Mq!iLl%eEn8G zA>tV?Uo-c|7G%mUTyXb?-`~OB-Zj1fP7WhtoDK zD+QdGEGwRgf*)yxDWVp;A>OYR^$6DoP`@UfTu+%ON$VFu?%4{!a z&{5en>~$h4Y<8Z((!)+Ogc4ymEO&ZVE-`6DFMUFUmpni26+w^q-xq zEoy3FU1_;5DM5A||4hrjEllLTBvc-9cD!Tv?!}8A>OTiLj+gR|@|t=?{UHj5rvQ#^ zjPb{f3I6yF8&!`8OX9LDkL5d2mgUs%A1BK$IjJnGF6C{171DVBY&qF>l9xZo%gM>@>Z}QOX>@3*@;Z$Nq(O1i8yn3rjwVMgze)Ic zX^@s>&LU+e;{v#q9Ofjql>~8nc8*PXy(?VP*_E4 zdyd$sYp8TqW~5g-XDsZH+cnWi?pRpt^%hhASWG|i0+*ozQ6K##03%f|qOgE8zO-)y z?9=IVvQEy_(#DG}t1A+ATS?oZy!D&go1blJZYKHacnYHWC(6&LKmXYO&?{6`Ie@6X z&VRd5Ss(jtn;N42qhRWOE! zXWUaehx}ttigBoEaV9{?ra!tIoc`#t=cGp$RaH#zd-Vw31cLshDj2+^b6E1EG0d!;X>@Dz7k$P&VpC)<5RWG5|Z6T56sTSj~}Kw42l5Y6+Ft< zUPAk?2*=l>*D^Yid|ZdN3k?nudDSpNwKSy*>DzmUEbz|UYC^o)2Ma%vp>fD z)9H1mv^$~Lr8TUmm<=Wn3^yT9P06423GSax_eyhgGTkdZOJI15a5J69@hRA?d423Y z7z*;e@)`U{xEBS(UGQ7&9`bwBkKKe~lGpzOULw4Kg5hg;_ta+#ChQcppS+7ug?&!O+8e2d%!$0Ig0efJZm(O*FU+l>3C z(?eM_JyhJD5LZJH-7R33;Vpk(9Y?ZPMzY5G%1H|AV6gC{Dh@uMyWmHEi;g3?1qV*5 zuM%(4h=clb`9?#7$=t z*Oa3Ps29{Gjwa;|6DO0{ni|F8f6%!gd1{k&+`pQt<39Ph01DV1y!sz1OJ+{12LJ2X z%923q={zhG=1f^Dw4Mah-QH(n{PQ|26^2mYe6~Q#3|>H@CH0rzn^K?i(cg1JJEw8C z;Rc}x1;Z}9>V*3I9;EQR(V7ALWVS?ZR+cE`Hm6$L&OM1w-Zo+8*4}wJ?ibooFkFU@ zobXP5FIlI~b0wQmvYx<;^a-7Mg62-*MW2%nOWB`;4)d|xkNbr_6bv_?q+k4Aa=&6W z2FW^=M*nca#sDtmML2Y(Hc81ExOCThG-wZcb4`_ zS^!D<mkA#*OpP#yx`MuNGGN&{m!2ntkN^bt1_?{toeCm5nx@U+t z{ERDodHw705@Bmho|rmz{N7|+#EE>PEum}V&pU{nLRL%$nc5zH?=*TnT0=3Se{g)9 zKQl)21;gV=+MmgMAU~SR89~x+=J{;hZYG@t#pi9m7>k83#AKwYW5Mt7byN{8O;Qgf z(y(fw(o;>}Q)cm$wEhbx(E;&x-Gx^R)iL>O>X`C-pUc)M**_nVzw4w51N{G&egjbX zlUk=9QGW_)uqJAxNbVGJ`;2L0GWmL14TuxA0L>$s%tquCnsj4YN700-pomBNOFnKT zh`EWr(zZ5`ZqM+SH~*k5;w>uC>t}lD*%kOhc#*vbY0&f}xgErV113ylqbImV4N=8D zO^=)gn$eS!umt_QEoSsAak3W!PP5AyGkPMF;t%2Z*!y&!?|oKs5uo=`z`5px|K(s| zUT2vph29q|@MLdY>T;T$1k+rBFW@%zT}T5n)JIcHWQ@daGsfW*2$h6(6O59TE=kcG zOBj2|#ud$$3G*CvGGdqe3QC-XC1l&Z>-_RTR-fZ8C?Wrqf~9X4d`Q8N3`+3@+!1?s zdoYP~B~HY7gFD!FOL*^{E^}evzcPQB&)f0O7=!Zj zCyhbshxr6xq>aIa|Fkg>2IrMe8UyDqGe6|*$i^|;$6kaS@WVM%HKL>+DxkEWl&y~( zO1Nrtl+YMBO3S#|n-_JFtFV^$C0Lh(-DHQPNaN&0DhmdAf_di39)=y$yT1U zq(0$tuGyZ}Wr+r2?jE-E?yP8FBv9gXmZX{OvsgJ1Lu+=jmt9`g8q7&RCE2r|xmWW1RNx zCoW5dnfExWIl0Fz#r<}38uht2omHf#8THnh;TWK#H4i=Dppdc9kS8K0>&4PnMd$6W7f{E}I39#^0+E z`eg4~jfH6bl-BrrC+PX5!GgT5vW%3HLZPvwz@4*oX@T2ZNc7ynnsFt6t{H;SVzWt~ zpsCY6-xh!VM8E8^KQhs`WAg@gOzIz}oD6bVGma;}Yl41H_pX!lg~;?oe-H-;&!5z( z7?}nJF4l}|lHd2a`*u}g-j2;1ET7ajP7$@fO?ubgqi;I?vZM)%kzdLW!P;@Ja6hL@ z>!#9Q!ntvrNO5A+clPI`zJ@cWzJEwi->l|&a*@CG*Tbp`QuL%RBmcDetL!JBjlCA(`^p_(iO@6O>ml#VKzSec_b%$0hlm z80F=dT}0>Z5gq~|PUnydbOK}ex6--n$gOkIgE2an8v7#Xs;=yPDp=qw(deA^FVQ)T z=Kh1)a>1>UJ@>|GZVLYrbP7wZtoq7Raav3NmN?0)kJ{p7%keh8*1b>#J<-kyF3h?o zreBYO$b>P@yVfR{^l?8oy)P6a21#+syLLEPg;A)A=RrOcyPd<{APXcZqSXG}Og* z_P1s@9S&zkYd^^)1?(@lLAdSAo=sa=Lckmi%m{ zeogh@9(D*UkPjo#R7)xo(8icfpmQ(D+&O?C=y+xvHq=8HM6d+7uPdKs_GXl#fF z71H6@auSz-p{L?b0is(F+!mgtTVOT!U9|Jg7ruG#x(#<8I)E#cyYPA3ue^p;3Z)DK z23=|;>tu((3?8^Ynr=oxSA>!vBS<8@Q}z}&=s=Kk!WcmcabU9^86}CIVuvZnk$k4K zmbx{tz*Cf`_WQL`3`89h$Ks`BlmMhf@kdJ>B`zZ~Gt-ml_P9!1nI63{H}0J4kKw*$ zNwVg?D^{q2>-C?y3LXBjnD1BxvRFRrKQ$uG?&-SY^^J)#?kKX^ zw5caeQLAc0mE+~XN}p09^Sp2#*33QyCXvG)LP$L-)UiY0gT+tEggX|SlRO}wADyt7 z^3c*+5(HR6^R$wBSRf(OF`jaLi^x&;c+fO2A;7>;)M#~QdaZ7cOqiLPHZ}o=NqAu# zk&5e6VgUmFkdPMKvSDwLd2r_D%|Z8-MMWjm-Pikk<>g+_em4HpC11I1XVc7E9=znK zfn|?vJ%4n?>#x_8F1ujcW6QWMzf?WSe$MmV?dAQ-0l-~+y~U!xvn7!Uf^G;1n2Vnp z$p3Dbv=k1|(M`|^qui?$7R2uZ_6XXz8_6ey@6{mgVG*ABsybScyjSC!R74%2{Hy@Ra#(Lx7GLym;2 z6DVH}IWl4nkXKg{0z9y75Bn7{>X(WnUpT_H;3d@l*qTihDo1MwY}GqJ;Rq1S9SyUb3vE8xm>>!sWv zaMN?r7LYioO@uHIeS8Bj)9#V#^8F8Ad|6XvYK7lvOzo}?2YhbKTt9Dt=|2Q{)<7tn z_DZ+Uvvg)rzH$cz9rCr#{=_0s4CRENNsB#smFFa_@&f3!x-DL-$0JLL6&wo@plF2n z60V)RhS^)LbBEgc(lUBx4Xtw(UgF602a1X=FLL=x^78iLe_lIx{}=0KHb?edJ9vHn z@++d_gMr$^hpWr_R<(U;Sz_G|^LYwHeG^MIXJX0b@?@5jGl~9_r6~&%hLyuZL)e0^ zE4Qv)i)+_V(oqIM)x%z9pMo1I;akx>JL-gNWI8iS%!ixz1acX~X=5=6G@81x)0U5V5=9wEGLy#iC_i zYyp%&Lf9;$4n#>Oj_Hwh>LTqG5MxYMuNS~u;VmyI1`oLN>=v)Vn61%r8hyX)Hv2VK zPkT6GCBQclj{Mfz+E6BK(<0eQ36b*FgqBBxvvc&jO}?Bqb4w^~zm)2?wV7I~Gje)M zs;kNx{pJb>E4p#t;KiLDSD399q+&-|6Z4tI7?XVYW%X=%kza`%9PMxaOFg$V7G;*rxol(rPVn(5hy4mNu~CKWLfD7j}O3g@TZiNn=}Unnz=M z{GO!Mjp`o&@aODPD1jeEt@$WR1t`kJ0uzjaDT4ur-6og#GK!W3fsLi05de)a2C^)T zfFzCd80hphq(@O)!pAEys6miG7A2Wrq$gKCNtI}o#x`PA^e7roCy2Vy6f`n0E=qca zk?4hy3sYGDPyzwJ&*FBQ%~n^YH`SOQ1Z`z4ash+Ergu~ z=HA@SI-|H>&MwI8&FzlNo40CdcUy6w)Z@I^v?*PWA)ZSdUqvxD*I&~Rgsp z40xN<5RKW~*DOymF&5TlAB@>M^s;f!@#gakHG^ZFOQ34%dnbV+p zK?KTSI|c>-G!WXT(I}1RWkx`gqytD=p@FG|feKL#d4!1c_(X+hDM&_?7U)q0I@)W=PHj2<%Nj?C z6(6C`cN_7}hccf2zESt)uWh#6>c+QPi%ZH%f~5<)uSAz!G;dXCpiqzxF2 zH9N$LzzIQkEShaay;y=eebDVJ)XBPxbiJqpAwI@MB!>V=`Z55@Fa~f6@y?k&9O%AKKJ_g+|p%iHH+}%11P|;o~E! zjitwK=af{Et?a>>rTcS+%l2pHq_$)HuWv9XWrj(WP z_OH=q&8=#Bt1VEnpyx`oTk{-Q($b*Y>!kp5rhZ%XumCIKJnWTdVJ=Fn*v~`>Q72k5 zGg4(q$Mk@@?)0<-fQ1K82Rek!0B|0$3JorOiDuIwCPmp<c~TXDaMT283`CtyTokV%>Ihdm!I**pVodJL+yF5qoj<{Yiu_hN9OF$P zb8L-Tvn0vQB-v`yq)60NW*GhUR#P;TlCt06&n5yY?UD-z0;@->m$x*9EJcyE6_utL zn{+67^UG!krKa^v3gnkHvfxa=|HjMb?&-o;y@emtd}9TV`=hmpzhf@&z)!V3ooho$ z=RiR!atTZ)$Ej!@>N@kHxp}A)PgX$ej!6UL!N*A@iAUOcrA)YVcAr9ADM$B|lDv#0 zi6bD2<8e|P4S-HU-2y_F7YJScB-Q>u_TE0euAvy;@Kpx58;-rw(^Z(grY)|%OCX7K80b4%tdlI;VNCzVt#$vyYu{*MZqJ%ps#p!DiA zD*5=roQRlK&Z(H5pEoHxNfN~pkJxE1Yhu53zf-<-?EB#VXy^6PXz|oY)NQy#{Mf61 z_>_Bp@AWYQquRMLe^r9v?CczOFhg~Y^h}y^{ECH3K3P(?M{xn zE6-oBs&Vd;Ma9wd^71K#8QH-)Nz0vHU3Kb=8Ie;f3nypgW~C&=dpY5P@=4LTM=zbR z@bshdveUA|DZx-6oL1oMjM$+3MDL=E+ZRrb6c<>$rlusAJM1|js6v8w(xhD9a&u3) z)ctZQsNxpwU_yNGqBwDW{Mal=l!S!84oO)+yf}A0h+Xivg%TwJ63&^BPjDO5yKfbg zF?0H~^vv{(tgMLJV%cpo9#o)bj+0c$Qe!E zgt_3IcG||zrmRdz$Q`pJlJX{BkomE2mNcJxrZ|IP$w@7(={L39X#T4aj=GO0+~n@l z42oFqG?*92pPZfM#aU5OV!&+@F2cl#C)3?4A8+b*3y;THQ)8c&J8NrvuP;BOQRQ|*r8jUNwC7Eder zz9glLUa>AADQ8OBlC0Xfk?9Qw<>qUX60!?Y7nfZyt@N_XF1Xjr%PpE+6JEaJg3Xqj zQ?%0G>nXrdvD>_@dWcWTA~{PwC2N?xC?ubeR{4ZnAg9P;IgTwXag&vbnHkk5=$zR( z*>jwU;a=kS0?o;GCx2zrMWf9P4^ocLKApW#os+ZnwBtT@<-DSg9vxR6 zi5`=sqFJSrr&Q0M7jNz-#ql}$!MNn~xbSglY17j(=jWzQ$q7V?Qxh%4^8%7zT-mm; zWI@EMoTl+pQm2)9ft=9EUby;d%dh>6W!2|SOQ=%r7O*I*!A7VuK%hvL&EaYiU^dVWcuC@(R$ zVOIKQ6LK$14;2JLnOSq^oRMRak!g}MC7fTB5(s2^DWSM3n|<=Os>o>}jSt2JHLfr| z7)XepGka3gLa$7hG?b~PWJSZFl*|M*MNN5{p<#i8`fNOne5sTQ3u>x82V zQd1)3=?NjV%)C%?X4aH&!u0r1T*kCO{Bc#DS=zLCi%Sh9Yv%N$E7Hs26SL#IDbbwj z8FBdDVc}6JPvQvZcs$Qrt%L18!XnCb3mZo{3T+dPyQ|G2zXi7LIPbD)^CPmT$ zX%;;uZ28B;$rLX+Vv=Tw!9YsJloIn&a?;h)_{5Cz;^L#Li{c7G@mX;-mUY6F$q6B` zywtQQnHG+u$0r8kLUD=N=?PQjN>w0|H#y1Eti0@;;N)ye4&+P=PRYua%rq~UTDc%> z=XesI7e6&CloHCDXPd0 z95)HwjCWJVUG`6zh>Q2Ps4XdpA6sQsuadBC` zN{tW4yP(NoA;)DorCbtUa)P?GV{E@Ww_lK3EXGbute#svr$BRjMP2Po+U&X2;q0+H zU!cwkiO#Fgu>CR6xFhZC0gb!Y??HCPJBWj7+)Bt!MI?&hE9uAZ993kRmFu; zyv#r#r6@lQ2l&5H9v#{@-FBoxWeq;%E9fO#sxQ#Bk zS?O_>XmbLVo%*p!Uj5Pe;qrK!TpWVtH$0oHz%s9{a=*FmsnDQ zI|L-D*o#X{PD(6@i%+!znUf;9BE?=(FfQ3-k){V_W@@6OB&g2t)C+kT0Xx>bbTh3D z#hVw(w4*eT5|^0zQhdV!4T4mKG(NdYSQwSzfYd;$>$%IK(>>n`af3+hk+c&C;|F3oPKWE*PWNNA=#FZo^C&qaxI$`VN7FcS0 z+)T-pl=z4x#|4wTXfR##N>vk5Br(-ySRlg-dFqv?dzNPZ*Eaf}vyHCE40#qG(n*PN zDFM~;F;nU1*0`)#zdYrce0zThJmUkNU4x0AQ5PR(inT1F2A6zzZ3grOxV~E|Y*Aw+IH+JYSKauC?c|_$M0(u8gy_b63N`_Aze=qfJUn;$f zJUxd(dz^ZSQm@N>nk3QKA0-<5jYMNFN;LL8iN<~@(b&%=O3gUpB+9IDx%VU*drhuq zfz%Q7%gv9yEAwOT$jPyH^^?>eMjQ3=9`!cQry&gybm_l^WmB((ge;HJ!?=qDx|w?W zCH0Q}Q+(0M#O~BD#_qQ7P(PNYULPf@w-EKIh%WlHJe1uCDEsj{~**8 z@bhy>(~py;W#i>GvcSh9WE|!v^8Oipngt(-zb)sU)scDCu|s+T3*0(kCz1SjxRGRk z+>VQl>WQ(D55yHmxet`oA8$@)NKkLRC_=`8BBf~b!M>ZFkj`5|?B3UwMIs@c?O zCUtTkc1VjU{MQiM_bLe3M`+f^irVbk?gL?%S1mA z2am{qonxGgp2JLCMAR;4rrym=KYal+EjZ4*>x+rnACE}8ymOf8O<|@zF-E-vX6g*0 z{}{1X|MB(rmzS4_>hVP7AaPnlR9`1fXAqGSV*f79v9HU9DcgT_R@f_T@5wwUTAH+rv^AmZFy1u!eH@*;idyEp6XJVr+EiVxEuRFOV)al72 z`_%F8$0EC&I>}?M|)Ijtxs*Y`>JU z$X}!LV!xD0u@}ejf=r6NAWLIkmlI>}$ceEbN40>u!#5lzk$nJ^uE4#6M0|y z-M<@~I$aXG!^v3l5!aRy{pX0i_0MI->$#lh2VyBvtNehrM*f;7FO&3v?YMc+LG;M^ zryF_yoIHc*1ngp>aw~NXS`vF#Ze@<#%17i@(&bj>$_*@%8(~~VTgF6Nw&~CnK>@J&r}15*zjTR|))*y3S}J&)P0R?7WEF|Y@5r7suw%-FXE^FlDxa84{M`8HgFi_)cd%L zfaX!J)#N!UF`^#^m9cAjD)o9cc|JXoe~iH4bRJpWG1NQA?>`hv$F9YGD!=!6m!2WN zr|ut=sh3wM^yPj`-h`aikS_-ajH6Jxsn?gNw_A^(i;4at$Q}Y(PgF1RZS4%7I{qT+ zrRXp`DT*DCqS(H1d{>HM&r4D4r&7eR<4BPr%A_dv2mOdE7yFA8#a{8(_M+IYWqRyg znI8L{%#Zz-R{3_IvjxX6pL+SZ4^LhpIL_Dkw0G>9{+W9D10mf_se>KM0_Pk2xA8G2 z8@p3K7Q54K8ZYPG&3_L58!}_{+(q;QaT!rN>%-fUzmW8SZ8Q+IX+(7j^*(MQ;M0r! z=M|lpXGhS*NAT|b2uqCQe*|sz}8i64mHjOA-G0ss0Nr0G1;VS5U84k*ZIEevf+l9rfz&WAAv}#Pwyu7dkmMs%_-?eQ`ehW7Jzx z>@N=PUi~q1^=)@!O}+lW*GGA_n9{>>92YNfe&!A2A0A^D-uMyIP4oZ-(rBE?@OFc-C?Yx&bO7Fy<9_B z?UnI!KCng1^lgh0BHB!yrBi1!$8FgJ>hz4*sJ=s;`r;UQC@{NS!&q@e||z-}9KWpL`oCGxn}7BI5Vu z1nP7-b$V}X)WP=$1_hyfV{}zI1F1 zCdSdHB}CjabK@nC#|~*m>|K9s&taxr%1r$_h4L(g)-SZkEYzwKg zlS%UJZf6rtq0W{Pwq?}$<&xuV`_C)LZW^T^JA0CDD>?lXZw^> zFF*M!v^+L6VOKa?#L8oCJ(Tz9*UwU~CyrwQ0bdt8Tfynj3&wPmZ$~*@@~7A#2OT8O zUyGfMcpddtMZLK=rHdEk_;!ZdwWHpO3D_yVEtaehm41@O?2p*<&UVn7Nwh`O>r_l{ zCDC7Rjt3oZ?Zyt7>(jHb5j)ejl?wDma{T*Bj2&|Dt|ThEVliiP*uwF?xpm)rhcF12RUF^xNqmL5xW3z6}b#X4IcieiJz|oJ4BiNk#c*>Pv_bYxz<3o>%SlS{wK2X zH0APB%Jf>wbvf}$cgYG?b>ziyQ zPfw&$=Mt4X7U@(fT?|K;j>*Xnnd+~t%P~ETMbhWT^P=(^rgK@OZ&D`z8GF;|4X0aN z9b+-4*bn{dPR7B-M4aw9d#qj8ru?2tjbhqJowL#0n&Z>4H9RUmVv+ogfZi5+R~J*L zb1Btn6#DUyKN8eM6uNuz*D4pcdUZT*azB}RS}Zmm_jIw(|26ny=*ICw;E$~v-~R=S zjWzj_7yG^B#r8-Z0m+NKCV8>nN?z>el1Gx{#YV>X*nY{2y(4+CC&#hJf38R9&A;Q_ z*g8x+!~ciWJ@@}D$hj2wYx}q^)llq^uR~uUYeFyjdco#)R<2vlH9xRGIe^?he-)6#h^~T!uefHhdYm`J^uS_CIClU4OWklt5qVgQ| z@?%nEG_lN6Bt7{PofhJ(@yI^*?tzN`6Y3p1@QsrBJV;P<}v~;yzP#Ha)2tAW17Y zN?suGuv`VxwSuFyf;_DtQ7b6a3Z`fUGqi$vT0wzUFjXta(h6pcUrW;pipFJ+8kco4 z{{6YO$Lq~vOYB@%&UPKfjB$SYICW{qPx+gCmp9$6qgpyBln!P|2Q#FD>C(ZJaXM8x z{OgmY!{`71k^3P@8su~anI>mZ!rK%}9~myqAXD^I*6E8(bNLQhOsaz~-$#azZ!pKj z;C=ZZr~Bhw;6H;bUoZavq@BxsEFoEzP$)~7F;3r~t|dom$viASQSNW@HAt>aCf8B9 zlM084v{sPe(nnIq>!r+akc-CPr^k6e?=hyzV-z{cTSs7GEGhtZK+Jn%-y0eGiw#3; zJ;b{4dGJ3!tRSpYN%jT^IDb}F#@^B6Dg2;oE?-ZkSSK?_izw7%Vk7TMSFqTxuYwG3 zx&NLgYX#HB-`)B#8hiT)x$wB0n+r$E9itVo5x;(Ci;s}y;QD9odlpKid*`Kt6MWpx z3I4SM^2&EKv>!|_*MhG{(C)wI8c?JB5FrMQ)dTx4XM6r9i$g&Yv(&ze52B#;-j>fm}j?)KMT? zDUi8G$oyfvo%<<}Q@Fr~lbtdy|L}OeyC(TSmOtjmclT#^|GyHU}oI@_(B%5zi#t_Ah z${q@MntYyS3QvC6GRa-@?fr7LF$K{U% z|a3N@qXd+?yu|pkTQ^3kY>=Opew+d!0Uv-0K|C^mk)6R z5Fdj0y$~FM#Ced|42i9f)CNhLA!!GMIv}(aLc1W;56Q!jk_M?Bq~=3f3#6Aq`a;ME zLPil}%!5o1GV>v`62fH=u7Rvd$f|{`A;=Cvb_B9(Ag2s+Y9Xf?a%*8yDNO2yNxd*> z2=YA0>w&yJ$Qy#m9!$=M$(1m92=YUazZ3HJLjE93X@x26Fr^EobVI>@C>VyqZYb=7 zqAf6WCrlfJ;xH7KL2)e#?H zgBh#fs9ZRzAC4MJLa1zk%C%5c0aaZv zHy7qsz})pPcN0|SLvkEZqf5`(fz_oKyiPErpXC z;p7!?@_IOV6Ev)XQAFLdND_Y@-cDQ0Qe6j(q%!ezt!>Te^RST;|;HofORR&kp!c{Ba zs`c=xHu$$q(7G9}-Ue6qz}0OJt81Mt}zSd$NH%3w_wtm%d|y|88g)_SmZFI>9`)`ei*N?6wh>o&u>9k6Z> ztm}vCHp6v0;JQ7qz5}kWh3kjlh7jD)4mWhc4c%}0G>-_C_cfk%g6M;|=a1dpwT$2#Dmy=-UK+-SF}j`0Wtv55fLzu)hcP_rd-l z_+1Eo7lGfehF2=#m44`Ng;&eq)gE|lEBt3C9O#4ByWo%W;E%&FkPib3VPF}&u@c^F zf;SJqTSG7yg26@@TmggYVQ>=+Zim6$Ft{Jy-V1LZfP+CeSOf>>!NEp2xEc<2z&l%E zC;~$x@TV~RsSN(K7XH);f7%9r-V28sVK@TAH88vthWEg5KfK!j{}qP+YJ>k8hQH*) zUpB)?1-zFF@72J2P4M1I7_EfSWiYx5Vh+v+?nCHCq#e;B#KMS;AYK^p%8PC_`Bgx%JN-L7mj-*x~ zsY{X6gLQV~Ha29Vhxb0SFPGNfuRGItX)cRNzO z1F7DFRQDs*BgnikGH(-dY%VfC4VmAK%8dM9#53v%XC`~~WLXiiY!9-m zA31j)a_%7V(IE2CBIKjL|&fkEXzXdseCvyH?;JwlKse~?Z^rbS+NJXtOmKP8@a3(xoiNr+(RzUM=q~KF5iz_K8$=K4f#YLvT_r$ zayxQGBXY$ata#bVlEO_};8uF zBUcBJtJfpffLzmtT+@ks8syVW$ft*q)vJ-uM3B!6BcE+UKD!_J>@cz>4O!EJtm#MA zZbGizgsj_&tlNXE>qo9@L$2#W*3Uz(k03YXA~)0^H#8wPMvxn8kQ*I8gtUc_whE-J z32AFV+SVdBr6D(!A~%g7pX)$Aw-vd$61lknxw!?|0J0$$+0ch<7(hP175V&52427jo}DjmN02RHWXoD)%Wh=L ze&m6C_i^ihCJAVbd@1pwMbVp z(zOfu_e$j78<2-W$U`m2Lu-+TI+2IEkcYaFhkB8R29U3M$XD}`uT~;o?MAk4M!r^x zJe-d_T!}o~fIPe#d3Zna@G$a75P75sd1M~)NF%Z>h-@oGw)G)j??t|G0QqJJ`DO&! zo{Ma+K(-Gf-%3NiRf>G80r}Pt^6hQNqix8Jg~)f7B9ARc9$Srkw+#7iBl6u9$j)43 z=WgVCE0FIOA>ZGMJl={t-i|!pg>-izKiH1^Mh@vTG&sBM-1N8AP5eLY|z5JlTjmRe?OU6nSbn^3-Z% zcPsLA8uD}_^7Ibm={?9Z&B!yY$TRK8vmxZ!2=eR(CAp7qFc9`f9F0OBQE<<|PBE6l+3uVX)wa5$2$S)Tnzg&;}stoznO5|5P$gld4UkxGqLdd=d zvTr}~>o(-q`;iwT$cr_|i%rOjE0Gu5kQX;2zbQq2(}4V@1?lsUzO_hSC(<{7yyPJ- z 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 literal 0 HcmV?d00001 diff --git a/interface/resources/fonts/FiraSans.license b/interface/resources/fonts/FiraSans.license new file mode 100644 index 0000000000..d444ea92b6 --- /dev/null +++ b/interface/resources/fonts/FiraSans.license @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/interface/resources/fonts/Raleway-Bold.ttf b/interface/resources/fonts/Raleway-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..38c099cc857f5c21ed7289d757f2f96ccd483552 GIT binary patch literal 179244 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 literal 0 HcmV?d00001 diff --git a/interface/resources/fonts/Raleway-Light.ttf b/interface/resources/fonts/Raleway-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..91aa0c701f04f5bd804362b583b44f0b4a1f9acb GIT binary patch literal 182376 zcmbrm2Yg%A^#FX%eNWT#X@11wwz2}^J_6;Ba za0tLcX~&}8?vW)UKL+wt5&(SN!$XTcM#oyfL%#!fQtVzd()OFKUt9#_@y`L6uAxO$ zkz4LLzZd|o1b~T^>nAtOyXdlw0EH(5D1Nu{2Pg0?1=hmxyz!aXFaZBLfTC^v@)h-!Qp; z$~AucJAiNX02K0@HXeV%PxrT80ro&?@DYsRP0$Y0&`#RHN>)NWUI`)m8bX8vKPdwv zv4e}GAWqESBl96jy1`B1;bG{)FTsg-LMMI+aeM;=rVXme^-xSMhf%T%MDjF@l2tHD z7Q!fb4n%SQM&Uyk#kZl9oCc$$6GoX$Fv=)klza>#Sr4P+|3D-4MVQu#r^| zAW0a6=V1_D&7McJFo+B+WG;b0dYueIKz?o&1aJff@gVS+gmTgky`&V3j0g1if4~tN zaQIi?;d5w&1CWN#p%y=c4jKRdgb5M=5&sMkVupHh71-ciScV@%7(GzWG(!#E4mHFF ze$oPiqzc;QYv(`=6%fOhVLtv4+_)9o@>-@~gbaX#;u=f9jA{_@5eO3>%wwz&##6vT zuQ6Rvjc0(H2|$oOi!XvxrU9kH^-zpS2+8gFP?f(1pFo^>H2X(#JNRV!P#VpA;X`o3 zhp-Sn1O`3?8`%fKEPW`A=6vxnXqSIeI?er3I;CNhxM5JH38l*sU*(rWJ42A%S6N~^hF8*pS949YFV1${roM-hbO{&i3U z??SEIr@TseW=;ziLnMDq#v#2=`FRZlWcus_LFO@vH@b%Z)>8hbeE1zLoDX&Ky#p{R zuk!<_CP^rS53}#U^Vt{R!|Y$+`Rp6;A=u%0D4}$rc%gfVJPV_EBMj0#1;)DYXnVB1nXsNuQ zdsgN{$_F!YgYI1_Kfckv3wELcyP^q3+1)V8E`R{*f>Fi_qxc3aWZ#ET=1mx7OfZ;V zvm$gDc9xzqJVy7G%-ebVP@Zdoz_A})gzUJLDP3Dn>? z_;DQO;iKS{W#MLU;055vrC`PF;Kd8TDc{q9K;COObbWV29k~~pWn7Lyh?xh~bWCOtL@KwLR;Z%yWjaA*I>Aln z!!&|O=R@kjPF8|~Tm}^cfhQHvN!qfX%d%a9LUK1$VFhULR%pW~VGtjMc6<~%@NdAA z7})TAu#pJZ$fICm3}9od;3c(?qWYM=lN5pv-i8!Y0~TU~Qlf_xT|2o6B63>mA@H45Y|*sFG#cTOcyaAwZ6XDjDY)u;T>~pf&}i7daYI z7z7*Xfrt#>0yU%ujKl^h(gVHZhma!YLKWo+_y{WS0F*NCf|4zPF>*hYk^vZ#zXxHA z{2j)~v0x&*VNBkS=fN1c0!GLx7-N14EVCKLWH`E~_Q4q00AsSu9|cZ+?jSg1JL4G` zBNGs2u7EM-HW(u>Ln#x4G14Qy)4@CoW8?(jNx5uqjM4GQ9Z*UNVNCws4Vo;NtV2HH9kSuGfV2Dh? z5Y<8Ws*D?s+ynvHCaHlTd<#VKAq+7r43Ro8kRQMhJ_SR>20ZyQ4B_9wk=L)J4U~8V z43P>5;6bQ_eJ}+3pcr1up2wI#%{X9)%malyk7jucj#y!ct_yF5A#xmOh#v}bmbGk$ z&RECHqrk{^vJF_~CIEO8&IBd2feYNQ5Ej7}cmSS&zazmCbYeBeuos7M3tos9t!y$?M-(1F$x>hTX|Z_CmYM-eF&AUtvGi zey06m`#tst?9bTWxBt`rIZt>!U&h;bUS31JyoM9_Gx=Zg*MH|47CDy9tbubHotD`( ztdiFNbPd_}vhQdAn7uRme)chd>@(SC0kZqDF92j;$iA3;Df?LVk?hXw@!1X8qqE0k zkIg)vt;&o8WcC1LmS;u}eRk;GL;DUr2au`BG-V18eFX5{`uB$3YkV*EUg$mRdnNDw z?cERFee2yP-@X6cyAR%e@Y;jd9K8DARR^y;c;Ufw59~d-@ZiwF-h+{YH3zE?h7XDd z`FEat=ZSY7c<26i?s;dL`Z5PTIPj+fZy$K;z?%nNKk&+drw`nE;PL~P{Gm!)t^88? z#StFZU9$J{sQmZU!=BK0d?-u~F8|q+@4!d1z5oB8n}GU||M{~O&W3Z~T-Xlh!H?m5 zxB#Aqeefc@1TVuY@G86pZ@_-|1H1)q!`(=bK^7IT1Kxz+!|QM%yZ}Ezfvg}a$tp5M z){wQNi8PZI(n^wK9%&;Tq>FTu9@0zt$ZE2V^pgQ{H0dPAkalt`UVuCC9efwx$3Nkp z@dHp2EuAjP|9|6yvz~C?BmTY*^*pH*U_k*&P=N*tpb(0n7)qcNIM9I}3}6Hkn4t_T zP!3kGK?T^M5_oWc69id4c)$xj@IwHCAVLVjPzBXc0}+TqEyN%W2~a~F)I$R_LK8GY z3$#KK=0O{@LkDz17j#1p^g!vM^OK^THzSRhND#V`U#!4gP88kWK`SPr8w2IDXR zldu9nro=^X30wu&!cFj7_zm0wx52G&J50lF*adgMop2A_1^2>z@Blmn55mLn2<(9; z;BnXsPvZS>JWRoAI2s>>Q{dOI8IHxb;3PN(KZBic9sUbWz<=ZCuoh0nzu`ytA)b$) zzvIc9$GQZ>C_O(FLTr})+UjvbS{q#aI8 zSb2%3_q4PZr@i=ubt0WkTO|yp(}D!Usi|~2Brzi2$xEzzauqKr+J{q;LTHneLYvj$ zNJ}^ol2}o22o8SLv|>dYPw&tfTXQp@e1R=6eBvmiAw zY@J+~P6=s8nwOG`QW6HObZIm14@nA9Qnd$n0m)%XDM~7#P2eRE+9oBkVzq=TC7h5H zfsmvUc{Yb9Bln7e?|EEu4X5bCvrC)%P$A_Yp>0=zmg!76 ztb!vQaD=2Hahi}$Y1L#$NGcX3oZxw>u)UA2i4oM{{lzO2pkZT}b~F5qFz}CV`h2_i$>OGP1 zQMy4wQee(a)9lU7xtqZ`H$AgAkIUV(iy##R|39p+Qk({RFeLHfG}6`~P7~TX#c77N zf;i36)+J6WXzLcIm9+JU(<<6}#c4Hded4r+wxY;4$=fF+@)Hs_!M6(%PEcN$q+3s< zyc!mzP*4g5LQ<8;^WFUSP*Iqy6R1S|j}TUhx9VBaqDiU>Oe@gXnW|391gx2hnQz~Y zh;%Y^{iSPcNB}vdeSr?LGV%Xdi zlH&gjRKoU^bs;GsP7^S>`7qy2cfLg2y*qYv3*EvbpITw1l2vHi6-P800wJkRl)xmF z3T+bWmRPq8CTZG(Q#--}&o}L;3rY3g1mVNEu_RV#qmaBbL4`(gL25VQ8Q!{^c$o5Z z8x^GLc7BH-LknFK65D>{ew^SX4CeF(X`fgnNKE_Ws^OGG+9$0N(>_53*^$po3Op~d z9-(Wp&MHXi_AZIIC3U;}mI?m5ULw%92ol>qL5ZMnPfCh!jViI8NvetDNw_Cg4d+DV z;diA&QbQgOJkLuC&kP=frn->SID1P{3-o@M&`n=Tsn?XhCog6O!>~9N=9>hEmCk<$;KLM)T~cX# zYS_9ko#LC);ps3Mf+4B(8+R94hre+*`Hj2zXXlQ09l#AKbz7 zO_aZO)O|mw#I}c}a4;mb%S)#0o2Ln7OM!3V!$RH6GCIU*HS2Dpye{*39y9-)iMzjx zrT)M0EyXYuQB6Xf)iH-d9O;=kc8b$b7tG_KOPq%Kpo3D0PI6`?vy1K)B{1eT_%5J( zSs#{a10kvBd#?A2(|`uO6bpo;K2b^pLQ+4)Tc^N>`K}$pWFAukB4uHzKNynci@N|i zf+1;8+yzKGL*g!!uMCU3P`DV*F}M&ab%atbH+M(I1-gCS{*zLR#w={sp>g1(b>CMir; zFeI&@FtoFh!qCnt3PU?n^1RxDA!)TdFWOrp&x`if%JZVVb@IGu?`U~mw0Dd=FWNg+ zo)_({7pI|NmVg`NUs6jjByG%fTZ18K6Gb`&laj%Zv{{_Sh8)asxh{n{UWTDJD9j1s zG&IhRdZPSG9`y&gE`8#pT$h5MEKXx%4&anrmjaxc>r#Nz#A#@n9q)AcmptANb6pC) zCD*0kXNc3-lmj?3*QEew<+>DLt2hnKv*T@(f63#Wo$FHYALY6f{2Xx_n{xo?=DHMM zd#+0X&J%ZQSduqZ+k%pMN@85YC+F34i0aUO$+j>xjd(%&K0w+1*)$ERwz~kjqk;kg z^hdIADLcqEr~}F}l|nspX@V>!9m)vnP{@}G+a56O(eEkVqurxSPAfElY2e!KO41Mg z!9d5f3%4&wNy+W0X=YW&w1@t>PkkmJo7}!~af*VZ)9G}wa5+27HmOBrxk^zOxCgU8 zlGyX733TjMtWrWphphSk=T8J85P}fRDHAn7Hb^th*o9z~oT<$ZY^`8T-01p)|IpOxr+tk3>detzaU6ToZeZzhOW z%hwNo0x%!0!+yMh^ph3j{}>G;GDFO%%yrC5%tx$}b+X5>*R!7}mMC^AzEG}Ko}(&O zovyk;^*1%DgX($epKDfYuF(8j+o?TEJFVScP+hRR;KYI(3SKPuzd~1GZ{d}NuNO5G zZ7aH==K4$`fm4q>38_M{m1)n^#3z39Jn>8 z2_6&tL|iVOBK|p46*?*OM7S(GKYV%k)2chGPpD~(gd>Nd@7G=vv&McL`!c>U{WRi8R0^+CER z{qoX+rKc_ZYME(SYS|mhgK8PsSQ(~uJ*3py!w}`KU_1pHnw)lx{7tDA6D{vP4D}h4 zXZ-z4+nEDr{`k!2&WfCM#nz&&XK#Ifn|s@p+dewG_3S_WsQVoCITxMFpS$VY_qKO! zU%ma}?SDFN?7Ux`_tzbY9k=fI^N&M6Uh(7CeiHu4x}WSjzxn+2=ihe$UeIyDjthQw zq4UBMFTCx-KkXEDUb-`L(bX3{deP?>FTPm1`14CHzU0YE3oqSp=|TCwuP-xSR(ILD z%YJs*vzM1#zVPxhF2DcsKVG4`;@?*mTv>VL`YV6_Q~2rKKYjUUBUcq%mAdM}tKPgi zdG+S2U%IC8n$$I~|GeerPyGUZapkqjYq$Rre|gj|e{-Ggx*uG3*Y(=#r*2T(u?KqKi(qVa@j5WZaH+T z|JIea{^2(FZCh^p?Dh+!9nuTa>FL*ZRqyKEb;_<^?Rs^$bNA-m5AJ^Jj+Q%ayyL)~ z`a3t=x%U zt&gN0+40D|j}||=?9nS9ed#gsSnRQ-kKOm!yN~N1U-J0fkN^1z&l5|ZIOmC1p7?Zc zZ11+cH|%}?$+jntfAXp)UwSh8RMk@(pSts@kDi|Y^leXn`posu9DG)M_Vj0OdiJs3 zS$}uJ@9urh_}u7o=RfzC-}nB0_3v+bUh{nS^VdHA#J=Kv4f~GXcjdl^UnqVd{KDNY zGA}w_OuzWtOYoBKrLmXJed(^3{`GS7<)dHT`-j&Nt-`M!Z+xva{*Y1CG{|9dtycv3P)ti^oav_)ifJ?}8z<>&>k|K*Vw2Nd505tUj zAMnNSc zxU{;Cp!ik$Sr=s7!U#n`@DF}C^C+8_#pjP9$&7hmze{PN2$ z`(N=s_uO;Oef`QSG`1bcUPI_+HnL*E}Siru1sc<-zbc0f%P;LN% zNH%H^KryaDg`%ThjVz1f3?g>ofVE#L9!@1)pj0Tg{WsX8kOw1YfA5Itbh5ai-p_I6 z29C3GT8aUWmy6mNqoJ4xMj__$CQK$X7iMC$EhG_(8cilMQyV5;E*goW!A{JaQc1Am z6sCT3p5SU*URQb9I;;PLp1LIsc1P1lw6bk&pwv>+AHmUenPUxNN7dK}86LpQTZI*3 zvZ|`9s%&&jJ?Rg|73eLr`WwVhPo#oOts;J3rp{3ru+pqW8#@RHLiS72 zK%Rvv2qe8#W)njI`>1g-4h+*l`4Y!LMp-CmwHWmdR$~mJM{p{QbjCBQbJC?nBk>qr zPHutGh{=p!c5YcaUKSlp&=tAcN9%7o-WuAvV04`=vAC{&Nu%A}w!E(MSdk3RA8L1o zcvIo*N{;qdB|18V8drItyp-y`Xt_TC3J7LDBNvi=pa(BB!VrwWNOIvKWDxr_NYn@l z0&744Dy2fT1{g-3e@A}-DwXWG7Fo839cXUy`-}#J?#`y6=AmefuhHLFSz+)Ry#*T3 zqrOmM2Fhp} z*=y%Aj{L1WCWpjV#uA7)=_JPgi2 zP4+XgojeZ#sDmDupX_U?au%~h5%vqnvV`;jQLqZaZUKd22JcEL)cRG(vM>$+Jun~! z0Xo}*bz&U^AmH^_%z|2D3_83@r7(ljM4pFos8^Ze@mN%;GP@)3gtwTX=w~SV#pAJB z4aF=7iLB&V(2IarOHb&6DHn-oq3@*>1paH^Mp)ZTf}3;^w>jVrlt1| zR;^u?<_*>36D#Q`Nn(aC$x~1awxp%FsIWk*QL9*nU?FtVWx#+D=>ihoggF*9Cd?|c z%Bxx$=+Jajc4|6;<$(b4H<>ERdV0z#OijAxW;$vN9>KLl0R`Yqx|9mS5Cmjk3J}>* zVA)m~I|Wc6D-M;$5=0{vl|qavDO|fXylq<;PY#@ae&GD`0bwkAJ6r@Kw3gux1p@Z= zOQpl9q>e!XKsM6yTZ;5%7_cTedXbzx=UO^h002r*avZBM1|L+gv0Vv02^Th7)tv*JT`xW_H;$< z;>ZYnixq%)$=)11<&~!X+_dMs08v2V&4lXlMY8u$1KA4%>a(Ab02z^GUq!NKQQIquy|oqj7Ts+d z7lc9!Hnz2GTo4W~*w|J--tO_VkJs0ab-3LfV{|1U0Nh3zK?gO-umTwt`+#NGZNLCQ zhOAL4DCTB}0suPD37nCWY3(*TVo|P`5n_=Rl8AD+E%V3)8c%h^V5zHdkVrTj#@`p( zEL_CutYi-TEC0UVkxrVQPI`?7BC9J}0FJOmHlo;^5d{E#@Z0=hg~l9=(tXv!HU z`7EOGRfBAVV{7}8)_7ZJ$(99t%wzPlr9Q8W_xSxi^Z~i8q_py7&mt<) z4GLLG=EN)jj?4&Kg!vp-%4p0%bi^De;N6+ccp!5{Jt?a?)Bp@bvtJMk**jyw#gY-B zgb-PD0HyVsy!p`7pBHVNFfh>9maL11#qu&2^@-+UPEY#$!{_Tn%tg7+BV{G ze6^F)IcxaJ8i!6N)KE@wXIB#|X_PsoCD~|21*_K)!jL`yC9(=&sYS~W#kaZsNM@ln zL|(Yf<@sWUs)NJ~ljKq1_H-W2F5?Mmnjfy#MU>GtA zgfx=@YtlyVQ>ithkXk8ow^d9{~WOKn4giHOI`L zQ30I)T@iqo!|0AVjGY+Fyn?}f9?uGo2N2@fFYxub?{_O=Zg)(9uV=}v@bQ&}eF(ZtCVc1b6vTQRu;PV0ag1%tD4_@$k z!zzs_n3$_izoCp&#f*^#Dy}au@djfgXtVfZw)*8}S5YX@%DX$`yv1KzZmcvG1jR?Z zb^eONLW@xAb;Vs=Q?;qG+QF4obyo!%d=-USqqElg$chzoe^h5TFdDK9Qm_GzO|J8K z3By*RmKosf69qg?}P(5N*lp`d__Q(ou?rBYsK4-O!# zKW1v>@L+%Myw*fa47h~~t5IK604Yor9o8N!-8-^>;>o#$CbMi$$%eMP+o(&D-&A=I zF&asjXI&b73loclncO|9)A8EAZ7b^;t)8!PSnQmNSktwg!;aWIN2r4o04o zwnWIX`l+8RDz1vfgVvIAL0=K*t9M83MV!*p8nRf-mF5apW3Ow6$z>@LTYD;c&l*ca zmv8CsIb$sDvHI$#&RekfycO|7f7F&&RFnizrB-Q8Zd*83MCnlsKrSVFK?Pa}CVd*D z@fQWMK#(Obq=%-p&%fd{VoIW=+r z`d2jI37MbJNY5w$SxfeU4k|&U8ln{ED2OQ~Dik;hvf<3g(A4PXd0ym$Zb#VRqP~Qz zAsn1Twg8kWlSx(z^g;_k`LC=E$Xa`Cmp5|<_Pd(`=6H2;chumjv1Q&ti#_T#WtJgZ zQ7stsjZ+pZ>_VUqrj`&ieZe^V<<}b^0NNp6!_mFJQiM^T56vY!|_>W9PQ=QslT zXk)UnV{MOH99Y}LceKQHqON6N#NT^Lss`64&sf#Eq@&CosVq*UHrBNsx1_ez8FLwZ zEdgV4%{EFsirb%&y-)}i>X!jE-*Qn%hCwQVa-NIHpy!|v3LFZJF&O1$l?qbU7dXo8 zqkms~#^OL#>WA~u?&&?c^WJ;Aj_Gley>%03^)A>p8pT!Zn-_);U0$_#Gss>5iIcrh zK;xgZQdPmQQ`7{?5t7n$j;Ao!D|8zjoMYxo;u$aQ%dEt8nJdC!vNxRhK+L>BaZcA2 zBzr*v{-g&8Ff0|Wc}KiokrQb0@lp+SI4MU)XU84I-)E+9G;=*2@=s#sHkpcFkxR+5 z;Dbc6R>u(qamoft-jKrI!H)BC(Whe~4&x@QFd#UJ(R4@-x5f;zgK zK-R9=-g8P+cfXQ_%ELmH=fY4dTV>v)>VyWf4$Sv z)f!K2YHZznRJ3W{dH&3=@~ht_W0%sD1q2qSsL#zb_0xcGGti~a#VT?F=ime`$~ic) zEt*M2qqv7|L|mM?h3w5dfE_uk!p^*}Dzgc7SdZ{+xhOXprH|5?lx9E09l5=mwCOPC zqUBs%SpxTv0k_df%|khA*g|4ll#^{-FK_7zHgvcOqQzCI{-w!2&KMXzv5%5^!H>pj z#r!%?me=V?3R;blVd)F#!Oy0CmLamT&n;A^<7DrTi*gvH?zGA{8pWSCX5PSfL*~7U z$llBXygl=DW;1TO?9Kexb!0CnpfX9%NjLQaA{k{cKdJ&0x!?gE)Io>4ne08Zmim38 z0E}MVRpDe%!&22wBdLV0e+wO+@7>5Xbu7Uav=mJM`cb&r&t!$%VTm;PS_ds z;y(1m0(9f^RL{faz6o|U5szNGtbtdvTGaW==x2rg%NSuQN9&=`V>IY9;L zq#kKl!ermCaqQ@i_4TSD8+wf_FKEy*>#zCi!#=H%KwpQ2^e){gG2s~THZpVij0 zb!8*2ZQi`3HlE(pFw^Fx)G*l##bBj6hMs643{C;d%0hzf=NYP4EnEo{L$S}H)R^dw z&bxd9Crc?=$_u0D3JoMGD`I`2e}5{}d5ttu_z$wz(>mk}4!5{7pI~D}O{-IAt+vg@ zjv1<`2W+<*nOt;3!6;bfhzKW)(=FBs1C}zcyTVphWvMFjIaL~S(0w?nnUkPOm09r8 zIA&B1Umgx9lVo73elGG7)kCptWU+H`tjQP5BhTNzw%zHOi^2YLqT>Na#p>SB3C(ly zI3wvt$zI^V4$)+F;j9jo)%1+GZR%GtdA_vU3_9R|Bd|B^o6s|M=|R7XAYy@-Ug2{^LH$yXtme0I-IT56@Z`vAoFF*!I~_iIAcbEN+^&w z2DKC9=oJ-9j+leY&wL%td`%k3m50`nE5me;F3f&Kt|NQFLNi{}%4q7RtSU>EPBMUC z&=(h~lwd&%TQ$0>)uIk>pvY~nE z%nsUb+_WSH2qggI3bGfJ;7Ho3|A2iAAv5wJx1niRQAfjydZbnkc49FW$1^WiWnLnC z51mTRkwbX7u~>yn6Hij$N(+<^Rhb>ob>-y@!5)OX*ux0A&5F z)Ksy^(nYY0yokdBy#NYyIvtgoRzgK4eId4e@p(h$11xFyzmFTSB=Z5;n|To1GgoG= z!}`pVIEHKK8}tC=M6wsuAS8Jei_CXnNeyb9j3qieCve#R`4{z>zeMFhPr~yuU71g? z81DfDI{;af*X9ZY8abx%CmM~-8GbZp3UbOcFY*#J-e5$B(P76gGQ}jEDZqandM-dV zgad~zrc!!Y_I21p-Uk&pla)YNWC$~vw-H+8fUOEt94BiIGYwpEQRA|ySj@*11`qWG z=}KwzR+HC=-xIynqku=@?uN|3Oz>9r)n13IX5S4|Mab`#eb8^cn_333C>M{%r+h(j zSMY24k9UBGRrs#ViQZ}Ds*a>hA#)?WwT&SJ@r1b{?r9}-==D*(z%b(8;1l6nB&@&0|RC9(?xVo&}_j8 zr8HL{zdUMI)zr5*$^Ma2>ValI!#@%ZywCvm_S3T?$ugsXASpr>hTVi!xlqa4QK3}y zS-<-hC>4F_+@pTV*DR{!z%R{LcJ~9zD#k&fXztgbQVHW~lv7UDr1+h%Fs`7P?VcIv z+z%K?C#`-TLZsT);BRp96}B>y98&b6SF14u&9f@dWR~+!)D4VAOh%(2YNX=cQ^ltJJzHqU=3x&wJFgsSzhWI40w}ai@{Z+ zwFDcT&N{!jq$t|Agtt38)=y+CAw;V_SQYV!E~9>VaWQ8PmY0VedLS^E{fsn_{a^q; zbR_4wU22A971#%awDf~Qk;f2XJ{?D`)gBly84-B9(Qon>YE?=F3kEdM$f?5V@ly8Z z;yD-hh#aWOXlHO<^U?Nj#68uPNH;q??aNxjvWo2$9St?!BE}PI(Iz8n$^OiP@s6tb zlacsjuNd;Q4hO^qtsb){V!fpz>NWvFAp03+2nTLziP)@1_)Fb#tca4hhx$wIZ~9Az zQA~Z3yuTFibd1$?A8V~Kk3@rg3Eq+D4_IR%hq6ZNuj_Cn#yY*IOswb$BgJ5oD0UA`Q~AFQ2;;0u=E@vs?g!;c3tx#4^jAjtsKsp1b2Q9t zN4w?-v&>A*=^0Lp$(%^*4Gw#i=!!3Ice|2HYMo8Bfs%+(sb&o}{+JqTOU%O*_-mVN zp}txhU*E3{^-tEuSM-SnhiJj}L&s7EtmGPMTS6vpq~f=>sN3XiT@VZnx45XyM6u;1 z95^8a$z-#=f@b{sRHy*LCT9zT;*_NYJQt!og^R{VVDclf8jp z?_^w2LPGQF_>ywBsnAyC)T5K~ZDnFUO=p1(04K=%V21i+yZ{+eh)6@R3?myEUHu9g z?3Nwn)_xT#mCZ`(ahSo(>D>aysWs(6S$M~4saVK4eM+N|DwC<+-oZ|LolaNmH$@Yd zUWy0&+{7`u5?4X-g84ds#vx`L4>ZDU$>NacDqW~)loy^F`m(Ftw$#lG9N(lSf(>0-fi7GK2jTYJ=H^d%SgbG(T# z2!Q`4`@uvdOtD7xn}A_jsOc$h&F;LLEO16=sX}83Is~qky6Y<0NuCjd`0vPBd~?jF zjYRm(^MWmYJvtvL6C0hGhsgfSuI3)TX(UGFF#wz?YezZmO^c>-ik_x=Tl;6iEZ-68 zrLHB7dk;n;5u!fyIoYy&Igspm*&*0Y_JbbGG@HaCb%y|HMozYlR?>j2Y!J0jY1v8! z3*jDbv)C->zZqRXhYEL>Cm8?uKs?y`$ zXHSbnu&LpVchI!?MzTLcF!)mDcd~W=C9-5clu#>DjR-WrFI#;wq4HL~TaeRB`Y0#I zQWIub?Zy^H9Tf$YMOrSR3q;BOL+4jG6$+n96P4|@K>(&t)-fj}HGH{I%TnJtx1lVc zP_)WHOXWD-(%t5Dt>Ki+d_5U){$Oxt{f{1Ho7toqjS}$ znf4wc>eE}h23yZRW&JFVb6|#5ca>;m7SAou1Ps&qZBCzAn+_0}aq4)q=J$a0`yNTB z?{;%WVRnDat|%(!BTaOF)VDb1)djSXs?w^)HesX-om0zac8L0PdySw!X=7encnEi7 z{6SXsx%fj5{J)Ps_!6TX9;y=J%VpJ&$?%E3K%lRV=j(a{fxd)88|+&VPps$*2K!bd z;w$=sSP)*&BnT}Fs=^DJU9OfzbasQ;AZZ|+Y)@U8)XdsbIfOcL0(jP}$`v@t78OPF zJh{Y>%H9f4D9AXC|4>~)lf2&m`X2^Lr<3OYWTR2xB=gX>>(pc$ZJ>P}9|`m8n&Qjb z+|Jh2yqt0$2wI!t9;V0_Y0!2@Gxw9X)<#;x{VSprBOy=gf)sU?Py#q2yb&vxIdmgYeIXSH+~kgBB$8-mYctFEXv z8+DwlmaJ&~F12JfDxHGU6XTS$s_z@NQCWORtJB-Qtd?4~MunO+S1w%dsIT@Gv#wZ+ zJv5N8+he`6hS9v5b%&0zpokS^SaNE}e Jcpr{+0 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

eix7GX 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

XDCG$Cn90yW2!TvHc6kUO~pBDt)WIi`>J zAm*FA-;JJzxJcuNtebt)&j}_t}1Q^{zm&9DH(aD2|Gx7Srzf-@DSj6)k z8Ol$#fN#qjE|a-jEF~-YlSVJ%m31Glr9m8@eOYkgs!>fpP4%15Klf#$#(lLIx4pRvk!hwA}W zvC?=bKe#XuGieK<+-4gk4@ingJF7D=D zzQVoS#f{E8?Fla8@2v2+mo@xz^I>xhmvaR-G=566?ScLNCjdX|T$WbF?D{G9LeYll*+EpWNk_Sy?S1U=bk1)JI{#Xl@q>E;Vu!4G~|l(#SV z0jv34`-W+uE!vEe_gv1k4Qcp3I5Nw%JmmBIlCN^Fj8ubuYWE06Yu588SL9IthQYyGL>M$Ij`S@SFI;CgQ0M(f`3gNymR?`_Mb)6`PL z8tyQb(w(g4`zA%&uA?obYxz7E8;jUFZZ{UOI@bEzI8Geg-&z>0`#3uI7GLx|y;N(_f8{#OKe&>WT+0{v7WeX7uH`oF;clJ&rZ&~KqH$XEwa#rc zdE$@8Z?zqk4T^u^D#u2|^0vS24_)e(Z1o3M`CplliCUeL0Czc0_?+EGf1gYAJx3mM zQ~R~`ql0g94_ELRe#RGdi^5UuGIcO_?fX8Z{#|zX9YKM zG1r^%sa5>M<_~-LEZ1=-xA8sx!`P2MvRnHX{MN~hqrsMBx<1yj&Ohe1gP-wFKHvO@ z&;7rR<8l>-LppKSXdjU;QD{-F|3GpZ32ItmYp5b-d=mUCoXC_@ugn z=6oG1{7b;;89IH#{~U+1B=7$+{ugq9+kNA-jlmUsgG-xgsg8xKbu>2<;n=}VreCQ0 zhFkU9T+6N8+M4Fr60}|m@NNE`FKB%gy07@1H6y~W1y*xE_pqAv+-vlI?~I9-TP0WX z?(Pe;pPwg-Hr$=9v$oOHDeZg9p7d>p_5>$r{E zS+DIRS~5G5p?R&^fipYP3YR-fi`M;T{om~PY8j@LTBEu;N9+Cd4Q-J!cg-A&=4j#P z=6Q>A`?!eLS~PGS%lS+5#y9>m%FLbTOuycqHN-VsZNJmz88VI~{8-V@hRv0RTif$q zxz(Ca)N%@KN}HJ#=L2_gC(F5?`}LQl+7sNVLvw6c#^QC5btlRj+77++`l~hq4|^fn|b0s z+0Yc$tZLrD`}ixq!sigp7rB|wHsf=rPB*JH-?cPJjfV6z26yp3<7<&Q{)5l)4Zh0v z^r%EzTPVNc*WBV8(_nq$Sp31ep~rw8;#%Hq{`tI{cUk% z+-3E9Tb84yd|E6^ZqZ{qzSd>pIO+2P{iLVPYdzxNHv_ye_!V!nY|Vx`qd{<26KQx* za{=ew<|OYA7pA9E%gR>d$(ZR+$k$ukO`8V5Qw_+pVc&4R;%9a=_$zyToOcfdA2fJ<|3!=lba2+kDu1%0+y| zj2mv^TYQr*@g+XbzwiaVz~^~C@8LasfY0$kfY0zRdKNkt@rk3(Mt_lu_^CJKclj(| z)r zcId0Qj*mmvf#>)NpXcAXjL-5je$3bT44>j3`4pexZ_SE~zwG3RdT<>VOoRM)O_=3_?Di*;;e~eh0O_#{%&b0R=-{MG9 z6dx;`{I$*vTdrj_VwI6(-ZdybS4*(9(n=k!d0)@A@P^Scj7I6R%pT#pX;>Q7r_KErfUR zGd|5~ebrK%Id)h!8Y>UD|MR_SnA!F}9k^MiG5dD917(#=t2>ZGL!SlmF@ zQLXz{`C>3uEIp#yLaMlqOVJN!;B+0Q(VTX2Bg_4@QEeaPHlv}hH?8U$%a+;(oPi8< zZRF40=(_#U+X>RN0G+bNGL=O`e4@q zuTH3SZSL~vb9}coS@3(kN z>68C_ySaC53K#M-KF1ovHQN|h+n~#U2Q00O_4fIA_`p$Qx{m|Ek`0>gSNh2UJuj%m z6tPmzBIG@MpHCRw?cmXP&hdfovs}+aY@ic1T654Ebn2U<%8cYT)(N%sVTYeqyxiiy zE!l>+lCSBxCbnhtD`QLghRYhP#@}i9fSLbf_`t`_X{pWQKf6Cqb2--#X3hZk5WnK< zR*P|ZhwTH~PG{;c>+N%kcABOzb)cD*M$O3>n`?Mu&@HaHcN>GBaEJdovgUHZUXi-j zXz6WUiF4xpEFNf%nwH_~N&4DD%isfC+dQW{QM6rdwkP~-%VyqX%iwxr8Q*L1CwsiT zvhg^8*`sW?lefpl&3!%7Qxi>dfSXy#rH(yTgS93HD!7-MOuwMb^31H#^Uk;UzFY5=eSFA=C;>?*5&cZMN68H1EWcQ#|`}28SQUx*jhj{61{Ek zwd#g2a@ou(YECm~J6O#sZsA6*;Q?(gZ~L2Vg{3`cdXEn+<(j{?jd?HCWQnn*-MTyDDpDnGd!;V9zl0mm96)`{#tm4&Dpz zJoNSjSL)fg4a01X&$cg)MJKdMl?(YP|E$;1wD*{iM&lef9yqnHG5qZV#|yItLho#0 z%>uV(59ytY8$i!o@ZDp1TSxyj9KGz+MANlmW`;tGR+ay>_4Q=Pt7F4|o`TkJ;v!6sA3M2qs)BpDhc9uP zWz#&derEGHnm%``KudT2$+tJ_{~jmg7QSxg{9Ef+&011cv^?g@^^Vrq7Tv?KFrTW> z^`6gj)3MI*YCGDaXLK@Q>VUS8n7Jc%9oX6OF6Lb4v~8cS+$L<3nvG9XFh)&ptTu)emUSBqx_-5N;ePV_-|*0;jxse&WDz@LjIc@{YNdiN&DwcZsn?Dim8RQu0SB#d;!_n`uRb3B;nP8!JZzjJ-#`5O2+hH_JD&r;{_=L#oXC76 z?&o@|)$60brGk5WnqgzRNn31HK4?9)aR?33S}kmm546Kdt>*b&dxYFpm>dl~y6=|e zMxD5hr1xfpKI*-!{JtH`jZGz&gVxII*rC_zwDm2n- zslPnF&wAI=Dtx+U+u+38G(UXpM?;6+Qa#o^sn&YO%~7PaN`7;EyzsvRE$8ZqIScj@5& z@p=A@PxE=Rf7kPTl`mP}JUVu8gIS+ft7rP^xBYEU{$HGS#;zUMd(N1>v73iu)zaV& zZg$oH9u3XQqn4rLZ^&`l3Wwt#Ppl^g{(4ArXh}}AM=F}PEIK`R4TtNWIILYd{o(&D ztG2?@2%R3@v4Ssfv)&P&i|x^hFS%W7Z2X$*oU(BCPHPQ1JzVd6ovJPHZygq#IFB92 zZ_9Ja+}k_$?i%9Y_^J9n@!up3j}OOR2O8u1>;W_nKEhY{K=aQu_;bB0t^@vbAB1Y>bDnzz4>?a%-H-5ST2rpBS1D0F}1I4QCB0e0R#Ua9h*gq556Xyn)_w!iza zgJ1i%nx^pIebEQgFL?J@Wbx79NXLfo?<+T62h}>bIj>mc{EWG85hX6joDySTLmR<)Jlqk(nYZ+7m{GflLu*rvug zw+8KxRZVlCt?xT%O)vMCOO0`|`$z2!M+@_z>78T2iPixNO=aJSQT4xv6PKo~h2U?m zvP;eTm7}KCjqd~g7FFL!Y+K;iD1B&pr|sYlU4MDd+85z?z&-j~LV9moOQt%bKW(K- zb1?2~x(|~RPE#~(xB5=gyA5%4&Z_sZXz2HN&~#k4HHz9BT-I{WgC8|*2Nt-pExSOS z`Y<~(+265i4o#(@#l86{S8=!AnZIGXJQnyk%CVqfyK5TzvC8PyR%$k#=i@{3J=;?k zO}{#5t-1V9g8$HK*?7>5pE=)AG+*Or9eO`Cu6AY!w*^gkY-{@9_W|ENA`VU-RZV$p zn`A+=^9MBA$3E6n18hoXd!d=Qyk9Rn9yFC>$AhNnJu#|U!vAjt&4W9d_AmX>!i*-f zlj{!%fgU?i)>W*cqr^>-bb(xx^;?#6ipc2$C)a}Zx?ofBCUg~aj zk2+o5t6o-p)nC=y>O%Ft`atEVHENBzOs!Mv)I?P;P?ID;g4LB0DxqqIgiE-}lPHN& z`4S^B$|G@-tY%7Q>7t6|G;yozq`UM~rP5pasp}NxQHUx3OmkEabOY=h4nz=K2u27(5r%L?AQDlCMhs#R>#a3$=!M=m z9evOjXW&fqLqGIKD$X*lG^8U98OXu_48$Oujlmd#?&#os|2+H%*%*f5I3JU70Y+d1 zMq(63V>HI#N0^KYaS_JiVvNIhT!KrHgC5?urOK0Vh0M`Jx7KH%1U^0NqF&)#*S0?752$OLx#-bR&X*O|lF~zvt zxDF+ljOi%CLM%inevY4`%D=K0e*^~;THVL-2D}P zj)nL+er%rK3E&3Yira7-et}=&SGe8yy36qKU*lffhx_pW9>9a<_y8U<|KH%Zco+}i z|L|*b|JQf~58x3zWS#@};!)g#-{JRmDjvZjc+7NQyvHN^ojid(uK;(P>6EL;ee-MJiUdQ`@jz3nDbzAG#c-yXh9@}rW~IyVrRjA3no3{J=NSrg z`mA(>7-Aw2fr$u1qTG$qpp!B%;XRh~`glQ(Su9#+Y8htehz+iK?45yhp zLvRk<7>Ybh!@1~&^Ne))k@2I;BmvWmzidoHH&Y%RjrOJGyT&xkGBptBj%k=`d};JB z-}V`8+!_}E=xJXKH)qYAwd_A17vOS?0E~PGMw$CJ1DI{}4A`Me#!t{23jmxB53ai zPN{x+dFhZMqX)-q~lTuHb<8^>K=qLF)9QZx8+aQI%TxoM0~E& z)XnM{xlENyZ@EnFvBS|lj?2+kLZ!D1lq`vsNJ*1aQF5A`Asr+}I!UmcF8ySP1WHHg zAw8v!oGp+5iIO-;k}l|i1SF#qx=ME>qBByEgpN??iv+{TlZ<|lg3joIuIPtzj7F@> z!_tJu8!dPOF2f{D#uQUGt`a4o5-HKTHz2(wRnjC&2HI&2fx>8nAQ4^B6K5a|12GiC z5g>!aE!`oKAp;;1FNqN8EGZBJ66AznI4XKzlNWAY;0M9eI-+ZOwNXxvOaq5hC!se ibT{o|gjin`)3jLm0Mi?CdPEUlU7YpR#RJSS>;C~8TRjs1 literal 0 HcmV?d00001 diff --git a/interface/resources/fonts/Raleway-Regular.ttf b/interface/resources/fonts/Raleway-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e570a2d5c39b2841b5753350a3822bd2b685e771 GIT binary patch literal 178520 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 G^7ub6CY{Xy literal 0 HcmV?d00001 diff --git a/interface/resources/qml/styles-uit/AnonymousProRegular.qml b/interface/resources/qml/styles-uit/AnonymousProRegular.qml new file mode 100644 index 0000000000..68dfa2d868 --- /dev/null +++ b/interface/resources/qml/styles-uit/AnonymousProRegular.qml @@ -0,0 +1,25 @@ +// +// AnonymousProRegular.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/AnonymousPro-Regular.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} diff --git a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml new file mode 100644 index 0000000000..57cbe83320 --- /dev/null +++ b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml @@ -0,0 +1,25 @@ +// +// FiraSansSemiBold.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/FiraSans-SemiBold.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} diff --git a/interface/resources/qml/styles-uit/HiFiGlyphs.qml b/interface/resources/qml/styles-uit/HiFiGlyphs.qml new file mode 100644 index 0000000000..ad216ae53d --- /dev/null +++ b/interface/resources/qml/styles-uit/HiFiGlyphs.qml @@ -0,0 +1,25 @@ +// +// HiFiGlyphs.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/hifi-glyphs.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} diff --git a/interface/resources/qml/styles-uit/RalewayBold.qml b/interface/resources/qml/styles-uit/RalewayBold.qml new file mode 100644 index 0000000000..150bde409a --- /dev/null +++ b/interface/resources/qml/styles-uit/RalewayBold.qml @@ -0,0 +1,25 @@ +// +// RalewayBold.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/Raleway-Bold.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} diff --git a/interface/resources/qml/styles-uit/RalewayLight.qml b/interface/resources/qml/styles-uit/RalewayLight.qml new file mode 100644 index 0000000000..d4bb50cd81 --- /dev/null +++ b/interface/resources/qml/styles-uit/RalewayLight.qml @@ -0,0 +1,25 @@ +// +// RalewayLight.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/Raleway-Light.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} diff --git a/interface/resources/qml/styles-uit/RalewayRegular.qml b/interface/resources/qml/styles-uit/RalewayRegular.qml new file mode 100644 index 0000000000..5eb87c868e --- /dev/null +++ b/interface/resources/qml/styles-uit/RalewayRegular.qml @@ -0,0 +1,25 @@ +// +// RalewayRegular.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/Raleway-Regular.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} diff --git a/interface/resources/qml/styles-uit/RalewaySemibold.qml b/interface/resources/qml/styles-uit/RalewaySemibold.qml new file mode 100644 index 0000000000..5a71845fe5 --- /dev/null +++ b/interface/resources/qml/styles-uit/RalewaySemibold.qml @@ -0,0 +1,25 @@ +// +// RalewaySemibold.qml +// +// Created by David Rowe on 12 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/Raleway-Semibold.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} From d6772545d5e36195f7e245aca2566a613a025de0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 13 Feb 2016 15:10:19 +1300 Subject: [PATCH 004/114] Text font sizes are specified in points --- interface/resources/qml/styles-uit/AnonymousProRegular.qml | 4 +--- interface/resources/qml/styles-uit/FiraSansSemiBold.qml | 4 +--- interface/resources/qml/styles-uit/HiFiGlyphs.qml | 2 +- interface/resources/qml/styles-uit/RalewayBold.qml | 4 +--- interface/resources/qml/styles-uit/RalewayLight.qml | 4 +--- interface/resources/qml/styles-uit/RalewayRegular.qml | 4 +--- interface/resources/qml/styles-uit/RalewaySemibold.qml | 4 +--- 7 files changed, 7 insertions(+), 19 deletions(-) diff --git a/interface/resources/qml/styles-uit/AnonymousProRegular.qml b/interface/resources/qml/styles-uit/AnonymousProRegular.qml index 68dfa2d868..1e72a31b3c 100644 --- a/interface/resources/qml/styles-uit/AnonymousProRegular.qml +++ b/interface/resources/qml/styles-uit/AnonymousProRegular.qml @@ -16,9 +16,7 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/AnonymousPro-Regular.ttf"; } property int size: 32 - width: size - height: size - font.pixelSize: size + font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name diff --git a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml index 57cbe83320..bd7cf017c1 100644 --- a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml +++ b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml @@ -16,9 +16,7 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/FiraSans-SemiBold.ttf"; } property int size: 32 - width: size - height: size - font.pixelSize: size + font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name diff --git a/interface/resources/qml/styles-uit/HiFiGlyphs.qml b/interface/resources/qml/styles-uit/HiFiGlyphs.qml index ad216ae53d..7b1d6ce441 100644 --- a/interface/resources/qml/styles-uit/HiFiGlyphs.qml +++ b/interface/resources/qml/styles-uit/HiFiGlyphs.qml @@ -16,9 +16,9 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/hifi-glyphs.ttf"; } property int size: 32 + font.pixelSize: size // Size this font in pixels because it's UI widgets. width: size height: size - font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name diff --git a/interface/resources/qml/styles-uit/RalewayBold.qml b/interface/resources/qml/styles-uit/RalewayBold.qml index 150bde409a..486289339e 100644 --- a/interface/resources/qml/styles-uit/RalewayBold.qml +++ b/interface/resources/qml/styles-uit/RalewayBold.qml @@ -16,9 +16,7 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Bold.ttf"; } property int size: 32 - width: size - height: size - font.pixelSize: size + font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name diff --git a/interface/resources/qml/styles-uit/RalewayLight.qml b/interface/resources/qml/styles-uit/RalewayLight.qml index d4bb50cd81..c007fd642c 100644 --- a/interface/resources/qml/styles-uit/RalewayLight.qml +++ b/interface/resources/qml/styles-uit/RalewayLight.qml @@ -16,9 +16,7 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Light.ttf"; } property int size: 32 - width: size - height: size - font.pixelSize: size + font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name diff --git a/interface/resources/qml/styles-uit/RalewayRegular.qml b/interface/resources/qml/styles-uit/RalewayRegular.qml index 5eb87c868e..e03b6f28ff 100644 --- a/interface/resources/qml/styles-uit/RalewayRegular.qml +++ b/interface/resources/qml/styles-uit/RalewayRegular.qml @@ -16,9 +16,7 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Regular.ttf"; } property int size: 32 - width: size - height: size - font.pixelSize: size + font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name diff --git a/interface/resources/qml/styles-uit/RalewaySemibold.qml b/interface/resources/qml/styles-uit/RalewaySemibold.qml index 5a71845fe5..e2449286e5 100644 --- a/interface/resources/qml/styles-uit/RalewaySemibold.qml +++ b/interface/resources/qml/styles-uit/RalewaySemibold.qml @@ -16,9 +16,7 @@ Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Semibold.ttf"; } property int size: 32 - width: size - height: size - font.pixelSize: size + font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name From 42a44e0f67736ee50f8292a8ace4e39a212b8abe Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 13 Feb 2016 15:15:01 +1300 Subject: [PATCH 005/114] First pass at restyling dialog frame "Pin" button is implemented but disabled (as it was before). --- .../qml/styles-uit/HifiConstants.qml | 36 +++++++++++ .../qml/windows-uit/DefaultFrame.qml | 60 ++++++++++++------- interface/resources/qml/windows-uit/Frame.qml | 12 ++-- tests/ui/qml/main.qml | 5 +- 4 files changed, 85 insertions(+), 28 deletions(-) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 055f06d60b..7de760bfd1 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -9,8 +9,43 @@ // import QtQuick 2.5 +import QtQuick.Window 2.2 Item { + readonly property alias colors: colors + readonly property alias dimensions: dimensions + readonly property alias effects: effects + + Item { + id: colors + readonly property color white: "#ffffff" + readonly property color baseGray: "#404040" + readonly property color darkGray: "#121212" + readonly property color baseGrayShadow: "#252525" + readonly property color baseGrayHighlight: "#575757" + readonly property color lightGray: "#6a6a6a" + readonly property color lightGrayText: "#afafaf" + readonly property color faintGray: "#e3e3e3" + readonly property color primaryHighlight: "#00b4ef" + readonly property color blueHighlight: "#00b4ef" + readonly property color blueAccent: "#1080b8" + readonly property color redHighlight: "#e2334d" + readonly property color redAccent: "#b70a37" + readonly property color greenHighlight: "#1ac567" + readonly property color greenShadow: "#2c8e72" + + readonly property color baseGrayHighlight40: "#66575757" + readonly property color faintGray50: "#80e3e3e3" + readonly property color baseGrayShadow60: "#99252525" + } + + Item { + id: dimensions + readonly property real borderRadius: Screen.width >= 1920 && Screen.height >= 1080 ? 7.5 : 5.0 + readonly property real borderWidth: Screen.width >= 1920 && Screen.height >= 1080 ? 2 : 1 + } + + /* SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } readonly property alias colors: colors readonly property alias layout: layout @@ -62,6 +97,7 @@ Item { readonly property int borderWidth: 5 readonly property int borderRadius: borderWidth * 2 } + */ QtObject { id: effects diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index df632236a2..34db27c663 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -9,20 +9,28 @@ // import QtQuick 2.5 +import QtGraphicalEffects 1.0 import "." import "../controls-uit" +import "../styles-uit" Frame { id: frame + HifiConstants { id: hifi } property bool wideTopMargin: (window && (window.closable || window.title)); Rectangle { + // Dialog frame anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); } - anchors.fill: parent; - color: "#7f7f7f7f"; - radius: 3; + anchors.fill: parent + color: hifi.colors.baseGrayHighlight40 + border { + width: hifi.dimensions.borderWidth + color: hifi.colors.faintGray50 + } + radius: hifi.dimensions.borderRadius // Allow dragging of the window MouseArea { @@ -34,25 +42,27 @@ Frame { id: controlsRow anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; } spacing: iconSize / 4 - FontAwesome { + + HiFiGlyphs { + // "Pin" button visible: false - text: "\uf08d" - style: Text.Outline; styleColor: "white" + text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? "z" : "y" + color: pinClickArea.containsMouse && !pinClickArea.pressed ? hifi.colors.redHighlight : hifi.colors.white size: frame.iconSize - rotation: !frame.parent ? 90 : frame.parent.pinned ? 0 : 90 - color: frame.pinned ? "red" : "black" MouseArea { + id: pinClickArea anchors.fill: parent + hoverEnabled: true propagateComposedEvents: true onClicked: { frame.pin(); mouse.accepted = false; } } } - FontAwesome { + + HiFiGlyphs { + // "Close" button visible: window ? window.closable : false - text: closeClickArea.containsMouse ? "\uf057" : "\uf05c" - style: Text.Outline; - styleColor: "white" - color: closeClickArea.containsMouse ? "red" : "black" + text: closeClickArea.containsPress ? "x" : "w" + color: closeClickArea.containsMouse ? hifi.colors.redHighlight : hifi.colors.white size: frame.iconSize MouseArea { id: closeClickArea @@ -63,17 +73,25 @@ Frame { } } - Text { + RalewayRegular { + // Title id: titleText - anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; } + anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; } // DJRTODO text: window ? window.title : "" - elide: Text.ElideRight - font.bold: true - color: (window && window.focus) ? "white" : "gray" - style: Text.Outline; - styleColor: "black" + color: hifi.colors.white + size: 16 + } + + DropShadow { + source: titleText + anchors.fill: titleText + horizontalOffset: 1 + verticalOffset: 1 + samples: 2 + color: hifi.colors.baseGrayShadow60 + visible: (window && window.focus) + cached: true } } - } diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 9654143cd8..7c946f41c7 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -11,6 +11,7 @@ import QtQuick 2.5 import "../controls-uit" +import "../styles-uit" import "../js/Utils.js" as Utils Item { @@ -56,17 +57,19 @@ Item { } MouseArea { + // Resize handle id: sizeDrag width: iconSize height: iconSize enabled: window ? window.resizable : false + hoverEnabled: true x: window ? window.width : 0 y: window ? window.height : 0 property vector2d pressOrigin property vector2d sizeOrigin property bool hid: false onPressed: { - console.log("Pressed on size") + //console.log("Pressed on size") pressOrigin = Qt.vector2d(mouseX, mouseY) sizeOrigin = Qt.vector2d(window.content.width, window.content.height) hid = false; @@ -87,14 +90,13 @@ Item { frame.deltaSize(delta.x, delta.y) } } - FontAwesome { + HiFiGlyphs { visible: sizeDrag.enabled - rotation: -45 anchors { centerIn: parent } horizontalAlignment: Text.AlignHCenter - text: "\uf07d" + text: "A" size: iconSize / 3 * 2 - style: Text.Outline; styleColor: "white" + color: sizeDrag.containsMouse ? hifi.colors.white : hifi.colors.lightGray } } diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index 4a04e4a93a..ef27ff3633 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -4,7 +4,8 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs import Qt.labs.settings 1.0 import "../../../interface/resources/qml" -import "../../../interface/resources/qml/windows" +//import "../../../interface/resources/qml/windows" +import "../../../interface/resources/qml/windows-uit" import "../../../interface/resources/qml/dialogs" import "../../../interface/resources/qml/hifi" import "../../../interface/resources/qml/hifi/dialogs" @@ -20,7 +21,7 @@ ApplicationWindow { id: desktop anchors.fill: parent rootMenu: StubMenu { id: rootMenu } - Component.onCompleted: offscreenWindow = appWindow + //Component.onCompleted: offscreenWindow = appWindow MouseArea { anchors.fill: parent From 946807431ef5941ae340f6894062027717dd773e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 13 Feb 2016 17:31:18 +1300 Subject: [PATCH 006/114] Fix frame icons not hovering --- interface/resources/qml/windows-uit/Window.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 435d8bdb15..fda82f1313 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -88,7 +88,6 @@ Fadable { x: frame.decoration.anchors.margins y: frame.decoration.anchors.topMargin propagateComposedEvents: true - hoverEnabled: true acceptedButtons: Qt.AllButtons enabled: window.visible onPressed: { From 9479da616fb297a054d5bee72c49a43384e6dcf5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 13 Feb 2016 18:24:23 +1300 Subject: [PATCH 007/114] Restyle dialog resizing --- .../resources/qml/styles-uit/HifiConstants.qml | 2 ++ .../resources/qml/windows-uit/DefaultFrame.qml | 1 + interface/resources/qml/windows-uit/Frame.qml | 17 +++++++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 7de760bfd1..fb5591334b 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -34,6 +34,8 @@ Item { readonly property color greenHighlight: "#1ac567" readonly property color greenShadow: "#2c8e72" + readonly property color white50: "#80ffffff" + readonly property color baseGrayHighlight15: "#26575757" readonly property color baseGrayHighlight40: "#66575757" readonly property color faintGray50: "#80e3e3e3" readonly property color baseGrayShadow60: "#99252525" diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index 34db27c663..652af878a8 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -23,6 +23,7 @@ Frame { Rectangle { // Dialog frame + id: frameContent anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); } anchors.fill: parent color: hifi.colors.baseGrayHighlight40 diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 7c946f41c7..af0fbc29da 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -48,11 +48,14 @@ Item { Rectangle { id: sizeOutline - width: window ? window.width : 0 - height: window ? window.height : 0 - color: "#00000000" - border.width: 4 - radius: 10 + x: -iconSize + y: -(wideTopMargin ? 2 : 1) * iconSize + width: window ? window.width + 2 * iconSize : 0 + height: window ? window.height + (1 + (wideTopMargin ? 2 : 1)) * iconSize : 0 + color: hifi.colors.baseGrayHighlight15 + border.width: 3 + border.color: hifi.colors.white50 + radius: hifi.dimensions.borderRadius visible: window ? !window.content.visible : false } @@ -77,6 +80,7 @@ Item { onReleased: { if (hid) { window.content.visible = true + frameContent.visible = true hid = false; } } @@ -84,6 +88,7 @@ Item { if (pressed) { if (window.content.visible) { window.content.visible = false; + frameContent.visible = false hid = true; } var delta = Qt.vector2d(mouseX, mouseY).minus(pressOrigin); @@ -96,7 +101,7 @@ Item { horizontalAlignment: Text.AlignHCenter text: "A" size: iconSize / 3 * 2 - color: sizeDrag.containsMouse ? hifi.colors.white : hifi.colors.lightGray + color: sizeDrag.containsMouse || !(window && window.focus) ? hifi.colors.white : hifi.colors.lightGray } } From 31930e879aa1621c935a81b2306724894564c3ac Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 14 Feb 2016 21:01:23 +1300 Subject: [PATCH 008/114] Style content background, size frame, and position frame elements --- .../qml/hifi/dialogs/RunningScripts.qml | 6 ++-- .../qml/windows-uit/DefaultFrame.qml | 30 ++++++++++++++----- interface/resources/qml/windows-uit/Frame.qml | 29 ++++++++++-------- .../resources/qml/windows-uit/Window.qml | 5 ++-- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 01f21f2c2a..d03d9a15c0 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -13,7 +13,7 @@ import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 as OriginalDialogs import Qt.labs.settings 1.0 -import "../../styles-uit" as Hifi +import "../../styles-uit" import "../../controls-uit" as HifiControls import "../../windows-uit" @@ -26,6 +26,8 @@ Window { x: 40; y: 40 implicitWidth: 384; implicitHeight: 640 + HifiConstants { id: hifi } + property var scripts: ScriptDiscoveryService; property var scriptsModel: scripts.scriptsModelFilter property var runningScriptsModel: ListModel { } @@ -77,7 +79,7 @@ Window { } Rectangle { - color: "white" + color: hifi.colors.baseGray anchors.fill: parent Item { diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index 652af878a8..81b2dd2cde 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -16,15 +16,17 @@ import "../controls-uit" import "../styles-uit" Frame { - id: frame HifiConstants { id: hifi } - property bool wideTopMargin: (window && (window.closable || window.title)); - Rectangle { // Dialog frame id: frameContent - anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); } + anchors { + topMargin: -frameMarginTop + leftMargin: -frameMarginLeft + rightMargin: -frameMarginRight + bottomMargin: -frameMarginBottom + } anchors.fill: parent color: hifi.colors.baseGrayHighlight40 border { @@ -41,7 +43,12 @@ Frame { Row { id: controlsRow - anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; } + anchors { + right: parent.right; + top: parent.top; + topMargin: frameMargin + 1 // Move down a little to visually align with the title + rightMargin: frameMarginRight; + } spacing: iconSize / 4 HiFiGlyphs { @@ -49,7 +56,7 @@ Frame { visible: false text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? "z" : "y" color: pinClickArea.containsMouse && !pinClickArea.pressed ? hifi.colors.redHighlight : hifi.colors.white - size: frame.iconSize + size: iconSize MouseArea { id: pinClickArea anchors.fill: parent @@ -64,7 +71,7 @@ Frame { visible: window ? window.closable : false text: closeClickArea.containsPress ? "x" : "w" color: closeClickArea.containsMouse ? hifi.colors.redHighlight : hifi.colors.white - size: frame.iconSize + size: iconSize MouseArea { id: closeClickArea anchors.fill: parent @@ -77,7 +84,14 @@ Frame { RalewayRegular { // Title id: titleText - anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; } // DJRTODO + anchors { + left: parent.left + leftMargin: frameMarginLeft + window.contentMarginLeft + right: controlsRow.left + rightMargin: iconSize + top: parent.top + topMargin: frameMargin + } text: window ? window.title : "" color: hifi.colors.white size: 16 diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index af0fbc29da..aad22faf86 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -20,10 +20,15 @@ Item { // beyond the window via negative margin sizes anchors.fill: parent - // Convenience accessor for the window - property alias window: frame.parent - readonly property int iconSize: 24 - default property var decoration; + property alias window: frame.parent // Convenience accessor for the window + default property var decoration + + readonly property int iconSize: 22 + readonly property int frameMargin: 9 + readonly property int frameMarginLeft: frameMargin + readonly property int frameMarginRight: frameMargin + readonly property int frameMarginTop: 2 * frameMargin + iconSize + readonly property int frameMarginBottom: iconSize + 2 children: [ decoration, @@ -48,10 +53,10 @@ Item { Rectangle { id: sizeOutline - x: -iconSize - y: -(wideTopMargin ? 2 : 1) * iconSize - width: window ? window.width + 2 * iconSize : 0 - height: window ? window.height + (1 + (wideTopMargin ? 2 : 1)) * iconSize : 0 + x: -frameMarginLeft + y: -frameMarginTop + width: window ? window.width + frameMarginLeft + frameMarginRight : 0 + height: window ? window.height + frameMarginTop + frameMarginBottom : 0 color: hifi.colors.baseGrayHighlight15 border.width: 3 border.color: hifi.colors.white50 @@ -66,7 +71,7 @@ Item { height: iconSize enabled: window ? window.resizable : false hoverEnabled: true - x: window ? window.width : 0 + x: window ? window.width + frameMarginRight - iconSize : 0 y: window ? window.height : 0 property vector2d pressOrigin property vector2d sizeOrigin @@ -97,10 +102,10 @@ Item { } HiFiGlyphs { visible: sizeDrag.enabled - anchors { centerIn: parent } - horizontalAlignment: Text.AlignHCenter + x: -5 // Move a little to visually align + y: -3 // "" text: "A" - size: iconSize / 3 * 2 + size: iconSize + 4 color: sizeDrag.containsMouse || !(window && window.focus) ? hifi.colors.white : hifi.colors.lightGray } } diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index fda82f1313..dc74d47072 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -49,6 +49,9 @@ Fadable { // property bool pinnable: false // property bool pinned: false property bool resizable: false + + readonly property int contentMarginLeft: 12 + readonly property int contentMarginRight: 12 property vector2d minSize: Qt.vector2d(100, 100) property vector2d maxSize: Qt.vector2d(1280, 720) @@ -74,8 +77,6 @@ Fadable { } } } - - onXChanged: rectifier.begin(); onYChanged: rectifier.begin(); From a5da678d6e3c3e4a8a416b9ae3b0f56a52f7e509 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 15 Feb 2016 18:02:20 +1300 Subject: [PATCH 009/114] Make Running Scripts dialog content scrollable when needed --- .../qml/hifi/dialogs/RunningScripts.qml | 40 +------------------ interface/resources/qml/windows-uit/Frame.qml | 8 ++-- .../resources/qml/windows-uit/Window.qml | 15 ++++++- 3 files changed, 20 insertions(+), 43 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index d03d9a15c0..be282a580a 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -79,11 +79,9 @@ Window { } Rectangle { - color: hifi.colors.baseGray - anchors.fill: parent - Item { - anchors { fill: parent; margins: 8 } + Column { + Text { id: title font.bold: true @@ -94,8 +92,6 @@ Window { Row { id: allButtons - anchors.top: title.bottom - anchors.topMargin: 8 spacing: 8 Button { text: "Reload all"; onClicked: reloadAll() } Button { text: "Stop all"; onClicked: stopAll() } @@ -103,14 +99,6 @@ Window { ScrollView { onActiveFocusChanged: if (activeFocus && listView.currentItem) { listView.currentItem.forceActiveFocus(); } - anchors { - top: allButtons.bottom; - left: parent.left; - right: parent.right; - topMargin: 8 - bottom: row1.top - bottomMargin: 8 - } ListView { id: listView @@ -180,20 +168,11 @@ Window { font.bold: true font.pointSize: 16 color: "#0e7077" - - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: filterEdit.top - anchors.bottomMargin: 8 } Row { id: row1 spacing: 8 - anchors.bottom: filterEdit.top - anchors.bottomMargin: 8 - anchors.right: parent.right - Button { text: "from URL"; @@ -231,10 +210,6 @@ Window { HifiControls.TextField { id: filterEdit - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: treeView.top - anchors.bottomMargin: 8 placeholderText: "filter" focus: true onTextChanged: scriptsModel.filterRegExp = new RegExp("^.*" + text + ".*$", "i") @@ -244,10 +219,6 @@ Window { TreeView { id: treeView height: 128 - anchors.bottom: loadButton.top - anchors.bottomMargin: 8 - anchors.left: parent.left - anchors.right: parent.right headerVisible: false // FIXME doesn't work? onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) @@ -288,11 +259,6 @@ Window { HifiControls.TextField { id: selectedScript readOnly: true - anchors.left: parent.left - anchors.right: loadButton.left - anchors.rightMargin: 8 - anchors.bottom: loadButton.bottom - anchors.top: loadButton.top Connections { target: treeView onCurrentIndexChanged: { @@ -309,8 +275,6 @@ Window { Button { id: loadButton - anchors.bottom: parent.bottom - anchors.right: parent.right text: "Load" enabled: selectedScript.text != "" onClicked: root.loadScript(selectedScript.text) diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index aad22faf86..23d7dc1d28 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -61,7 +61,7 @@ Item { border.width: 3 border.color: hifi.colors.white50 radius: hifi.dimensions.borderRadius - visible: window ? !window.content.visible : false + visible: window ? !windowContent.visible : false } MouseArea { @@ -84,15 +84,15 @@ Item { } onReleased: { if (hid) { - window.content.visible = true + windowContent.visible = true frameContent.visible = true hid = false; } } onPositionChanged: { if (pressed) { - if (window.content.visible) { - window.content.visible = false; + if (windowContent.visible) { + windowContent.visible = false; frameContent.visible = false hid = true; } diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index dc74d47072..5d49b2accc 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -121,8 +121,21 @@ Fadable { // frame styles, like a full desktop frame to simulate a modal window property var frame: DefaultFrame { } + // Scrollable window content. + property var scroller: Rectangle { + id: windowContent + anchors.fill: parent + color: hifi.colors.baseGray - children: [ swallower, frame, content, activator ] + ScrollView { + anchors.fill: parent + contentItem: content + horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff + verticalScrollBarPolicy: Qt.ScrollBarAsNeeded + } + } + + children: [ swallower, frame, scroller, activator ] Component.onCompleted: raise(); Component.onDestruction: windowDestroyed(); From 9a536b3b3306b9bd22031c6a3a83c9efcc2ee612 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 15 Feb 2016 18:02:59 +1300 Subject: [PATCH 010/114] Specify a minimum Running Scripts window size --- interface/resources/qml/hifi/dialogs/RunningScripts.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index be282a580a..bf8b40e157 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -25,6 +25,7 @@ Window { destroyOnInvisible: true x: 40; y: 40 implicitWidth: 384; implicitHeight: 640 + minSize: Qt.vector2d(300, 400) HifiConstants { id: hifi } From 4d74bb04b09f8d00ee89927e8bca923ad0bb76d1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 09:48:09 +1300 Subject: [PATCH 011/114] Style scrollbar --- .../qml/hifi/dialogs/RunningScripts.qml | 4 +- .../resources/qml/windows-uit/Window.qml | 60 +++++++++++++++++-- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index bf8b40e157..37ccbef849 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -79,7 +79,7 @@ Window { scripts.stopAllScripts(); } - Rectangle { + //Item { Column { @@ -281,6 +281,6 @@ Window { onClicked: root.loadScript(selectedScript.text) } } - } + //} } diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 5d49b2accc..b479e25bf5 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -10,6 +10,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 import "." @@ -116,22 +117,71 @@ Fadable { onWheel: {} } - // Default to a standard frame. Can be overriden to provide custom // frame styles, like a full desktop frame to simulate a modal window property var frame: DefaultFrame { } // Scrollable window content. - property var scroller: Rectangle { + property var scroller: Item { id: windowContent anchors.fill: parent - color: hifi.colors.baseGray + + Rectangle { + anchors { + left: parent.left + right: parent.right + top: parent.top + bottom: parent.bottom + rightMargin: theScrollView.height < theScrollView.contentItem.height ? 21 : 0 + } + color: hifi.colors.baseGray + } ScrollView { - anchors.fill: parent + id: theScrollView contentItem: content horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff verticalScrollBarPolicy: Qt.ScrollBarAsNeeded + anchors.fill: parent + anchors.rightMargin: height < contentItem.height ? 4 : 0 + + style: ScrollViewStyle { + + handle: Item { + implicitWidth: 8 + Rectangle { + radius: 4 + color: hifi.colors.lightGrayText + anchors { + fill: parent + leftMargin: 2 + topMargin: 1 + bottomMargin: 1 + } + } + } + + scrollBarBackground: Item { + implicitWidth: 10 + Rectangle { + color: hifi.colors.baseGrayHighlight + radius: 4 + anchors { + fill: parent + topMargin: -1 + bottomMargin: -2 + } + } + } + + incrementControl: Item { + visible: false + } + + decrementControl: Item { + visible: false + } + } } } @@ -185,7 +235,6 @@ Fadable { window.height - frame.decoration.anchors.topMargin - frame.decoration.anchors.bottomMargin) } - Keys.onPressed: { switch(event.key) { case Qt.Key_Control: @@ -194,7 +243,6 @@ Fadable { case Qt.Key_Alt: break; - case Qt.Key_W: if (window.closable && (event.modifiers === Qt.ControlModifier)) { visible = false From 6a22078d2c21e637edfc91629f063306a5cf5973 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 10:47:45 +1300 Subject: [PATCH 012/114] Add focus shadow --- interface/resources/qml/windows-uit/Frame.qml | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 23d7dc1d28..fb89b57d5b 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -9,6 +9,7 @@ // import QtQuick 2.5 +import QtGraphicalEffects 1.0 import "../controls-uit" import "../styles-uit" @@ -31,10 +32,11 @@ Item { readonly property int frameMarginBottom: iconSize + 2 children: [ + focusShadow, decoration, sizeOutline, debugZ, - sizeDrag, + sizeDrag ] Text { @@ -51,6 +53,22 @@ Item { window.height = newSize.y } + RadialGradient { + id: focusShadow + width: 2 * window.width + height: width + x: -width / 4 + y: window.height / 2 - width / 2 + visible: window && window.focus && windowContent.visible + gradient: Gradient { + // GradientStop position 0.5 is at full circumference of circle that fits inside the square. + GradientStop { position: 0.0; color: "#ff000000" } // black, 100% opacity + GradientStop { position: 0.333; color: "#1f000000" } // black, 12% opacity + GradientStop { position: 0.5; color: "#00000000" } // black, 0% opacity + GradientStop { position: 1.0; color: "#00000000" } + } + } + Rectangle { id: sizeOutline x: -frameMarginLeft From 615b2e6052f60e657a9c760148cf3668451048ff Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 11:01:53 +1300 Subject: [PATCH 013/114] Fix up some colors --- interface/resources/qml/styles-uit/HifiConstants.qml | 2 ++ interface/resources/qml/windows-uit/Frame.qml | 3 +-- interface/resources/qml/windows-uit/Window.qml | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index fb5591334b..12595e8c04 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -35,8 +35,10 @@ Item { readonly property color greenShadow: "#2c8e72" readonly property color white50: "#80ffffff" + readonly property color white30: "#4dffffff" readonly property color baseGrayHighlight15: "#26575757" readonly property color baseGrayHighlight40: "#66575757" + readonly property color darkGray30: "#4d121212" readonly property color faintGray50: "#80e3e3e3" readonly property color baseGrayShadow60: "#99252525" } diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index fb89b57d5b..7dad65847e 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -124,8 +124,7 @@ Item { y: -3 // "" text: "A" size: iconSize + 4 - color: sizeDrag.containsMouse || !(window && window.focus) ? hifi.colors.white : hifi.colors.lightGray + color: sizeDrag.containsMouse || sizeDrag.pressed ? hifi.colors.white : hifi.colors.white50 } } - } diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index b479e25bf5..2f63457983 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -151,7 +151,7 @@ Fadable { implicitWidth: 8 Rectangle { radius: 4 - color: hifi.colors.lightGrayText + color: hifi.colors.white30 anchors { fill: parent leftMargin: 2 @@ -164,7 +164,7 @@ Fadable { scrollBarBackground: Item { implicitWidth: 10 Rectangle { - color: hifi.colors.baseGrayHighlight + color: hifi.colors.darkGray30 radius: 4 anchors { fill: parent From 0442fcf89cec3f038e872d8ca4e19d7660d78209 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 12:20:01 +1300 Subject: [PATCH 014/114] Add shadow at bottom of content --- .../resources/qml/styles-uit/HifiConstants.qml | 1 + interface/resources/qml/windows-uit/Frame.qml | 4 ++-- interface/resources/qml/windows-uit/Window.qml | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 12595e8c04..9f1ce2ab27 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -39,6 +39,7 @@ Item { readonly property color baseGrayHighlight15: "#26575757" readonly property color baseGrayHighlight40: "#66575757" readonly property color darkGray30: "#4d121212" + readonly property color darkGray0: "#00121212" readonly property color faintGray50: "#80e3e3e3" readonly property color baseGrayShadow60: "#99252525" } diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 7dad65847e..c328c0ab28 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -29,7 +29,7 @@ Item { readonly property int frameMarginLeft: frameMargin readonly property int frameMarginRight: frameMargin readonly property int frameMarginTop: 2 * frameMargin + iconSize - readonly property int frameMarginBottom: iconSize + 2 + readonly property int frameMarginBottom: iconSize + 6 children: [ focusShadow, @@ -90,7 +90,7 @@ Item { enabled: window ? window.resizable : false hoverEnabled: true x: window ? window.width + frameMarginRight - iconSize : 0 - y: window ? window.height : 0 + y: window ? window.height + 4 : 0 property vector2d pressOrigin property vector2d sizeOrigin property bool hid: false diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 2f63457983..f483f9c19a 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -127,6 +127,7 @@ Fadable { anchors.fill: parent Rectangle { + id: contentBackground anchors { left: parent.left right: parent.right @@ -137,6 +138,21 @@ Fadable { color: hifi.colors.baseGray } + LinearGradient { + anchors { + top: contentBackground.bottom + left: contentBackground.left + } + width: contentBackground.width - 1 + height: 4 + start: Qt.point(0, 0) + end: Qt.point(0, 4) + gradient: Gradient { + GradientStop { position: 0.0; color: hifi.colors.darkGray } + GradientStop { position: 1.0; color: hifi.colors.darkGray0 } + } + } + ScrollView { id: theScrollView contentItem: content From 535b183f764345dcaa1d0a623bb565a21a699bbc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 13:44:36 +1300 Subject: [PATCH 015/114] Fix focus shadow vertical position --- interface/resources/qml/windows-uit/Frame.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index c328c0ab28..2ae8837ff3 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -58,7 +58,7 @@ Item { width: 2 * window.width height: width x: -width / 4 - y: window.height / 2 - width / 2 + y: -width / 4 visible: window && window.focus && windowContent.visible gradient: Gradient { // GradientStop position 0.5 is at full circumference of circle that fits inside the square. From d46f85c5dd4c78e8d893495eb15bc67b80058a98 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 14:50:28 +1300 Subject: [PATCH 016/114] Allow noninteger font sizes --- interface/resources/qml/styles-uit/AnonymousProRegular.qml | 2 +- interface/resources/qml/styles-uit/FiraSansSemiBold.qml | 2 +- interface/resources/qml/styles-uit/RalewayBold.qml | 2 +- interface/resources/qml/styles-uit/RalewayLight.qml | 2 +- interface/resources/qml/styles-uit/RalewayRegular.qml | 2 +- interface/resources/qml/styles-uit/RalewaySemibold.qml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/styles-uit/AnonymousProRegular.qml b/interface/resources/qml/styles-uit/AnonymousProRegular.qml index 1e72a31b3c..f2a07372a4 100644 --- a/interface/resources/qml/styles-uit/AnonymousProRegular.qml +++ b/interface/resources/qml/styles-uit/AnonymousProRegular.qml @@ -15,7 +15,7 @@ import QtQuick.Controls.Styles 1.4 Text { id: root FontLoader { id: iconFont; source: "../../fonts/AnonymousPro-Regular.ttf"; } - property int size: 32 + property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft diff --git a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml index bd7cf017c1..06ab2df0c9 100644 --- a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml +++ b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml @@ -15,7 +15,7 @@ import QtQuick.Controls.Styles 1.4 Text { id: root FontLoader { id: iconFont; source: "../../fonts/FiraSans-SemiBold.ttf"; } - property int size: 32 + property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft diff --git a/interface/resources/qml/styles-uit/RalewayBold.qml b/interface/resources/qml/styles-uit/RalewayBold.qml index 486289339e..9a9d9ccd3f 100644 --- a/interface/resources/qml/styles-uit/RalewayBold.qml +++ b/interface/resources/qml/styles-uit/RalewayBold.qml @@ -15,7 +15,7 @@ import QtQuick.Controls.Styles 1.4 Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Bold.ttf"; } - property int size: 32 + property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft diff --git a/interface/resources/qml/styles-uit/RalewayLight.qml b/interface/resources/qml/styles-uit/RalewayLight.qml index c007fd642c..5403a1bd00 100644 --- a/interface/resources/qml/styles-uit/RalewayLight.qml +++ b/interface/resources/qml/styles-uit/RalewayLight.qml @@ -15,7 +15,7 @@ import QtQuick.Controls.Styles 1.4 Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Light.ttf"; } - property int size: 32 + property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft diff --git a/interface/resources/qml/styles-uit/RalewayRegular.qml b/interface/resources/qml/styles-uit/RalewayRegular.qml index e03b6f28ff..40a34f23b8 100644 --- a/interface/resources/qml/styles-uit/RalewayRegular.qml +++ b/interface/resources/qml/styles-uit/RalewayRegular.qml @@ -15,7 +15,7 @@ import QtQuick.Controls.Styles 1.4 Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Regular.ttf"; } - property int size: 32 + property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft diff --git a/interface/resources/qml/styles-uit/RalewaySemibold.qml b/interface/resources/qml/styles-uit/RalewaySemibold.qml index e2449286e5..61ce33998b 100644 --- a/interface/resources/qml/styles-uit/RalewaySemibold.qml +++ b/interface/resources/qml/styles-uit/RalewaySemibold.qml @@ -15,7 +15,7 @@ import QtQuick.Controls.Styles 1.4 Text { id: root FontLoader { id: iconFont; source: "../../fonts/Raleway-Semibold.ttf"; } - property int size: 32 + property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft From 3c1561cc067d95491a3597cec3fce305b2655c4e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 16:03:23 +1300 Subject: [PATCH 017/114] Revise scrollbar handling to make better for content --- .../resources/qml/windows-uit/Window.qml | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index f483f9c19a..15a2044958 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -125,24 +125,18 @@ Fadable { property var scroller: Item { id: windowContent anchors.fill: parent + anchors.rightMargin: theScrollView.height < theScrollView.contentItem.height ? 11 : 0 Rectangle { id: contentBackground - anchors { - left: parent.left - right: parent.right - top: parent.top - bottom: parent.bottom - rightMargin: theScrollView.height < theScrollView.contentItem.height ? 21 : 0 - } + anchors.fill: parent + anchors.rightMargin: theScrollView.height < theScrollView.contentItem.height ? 11 : 0 color: hifi.colors.baseGray } LinearGradient { - anchors { - top: contentBackground.bottom - left: contentBackground.left - } + anchors.top: contentBackground.bottom + anchors.left: contentBackground.left width: contentBackground.width - 1 height: 4 start: Qt.point(0, 0) @@ -159,10 +153,12 @@ Fadable { horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff verticalScrollBarPolicy: Qt.ScrollBarAsNeeded anchors.fill: parent - anchors.rightMargin: height < contentItem.height ? 4 : 0 + anchors.rightMargin: height < contentItem.height ? 1 : 0 style: ScrollViewStyle { + padding.right: -7 // Move to right away from content. + handle: Item { implicitWidth: 8 Rectangle { @@ -170,7 +166,7 @@ Fadable { color: hifi.colors.white30 anchors { fill: parent - leftMargin: 2 + leftMargin: 2 // Finesse size and position. topMargin: 1 bottomMargin: 1 } @@ -184,7 +180,7 @@ Fadable { radius: 4 anchors { fill: parent - topMargin: -1 + topMargin: -1 // Finesse size bottomMargin: -2 } } From 386a247f781f8d22cfe6a3206756b8fb6fd11ea7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 17:48:21 +1300 Subject: [PATCH 018/114] Put Running Scripts content into sections --- .../qml/controls-uit/StaticSection.qml | 65 +++++++++++++++++++ .../qml/controls-uit/VerticalSpacer.qml | 18 +++++ .../qml/hifi/dialogs/RunningScripts.qml | 26 +++----- .../qml/styles-uit/HifiConstants.qml | 1 + .../qml/windows-uit/DefaultFrame.qml | 2 +- .../resources/qml/windows-uit/Window.qml | 2 - 6 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 interface/resources/qml/controls-uit/StaticSection.qml create mode 100644 interface/resources/qml/controls-uit/VerticalSpacer.qml diff --git a/interface/resources/qml/controls-uit/StaticSection.qml b/interface/resources/qml/controls-uit/StaticSection.qml new file mode 100644 index 0000000000..bcae22d8cc --- /dev/null +++ b/interface/resources/qml/controls-uit/StaticSection.qml @@ -0,0 +1,65 @@ +// +// StaticSection.qml +// +// Created by David Rowe on 16 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "../styles-uit" + +Column { + property string name: "Static Section" + property bool hasSeparator: false + + anchors { + left: parent.left + leftMargin: hifi.dimensions.contentMargin.x + right: parent.right + rightMargin: hifi.dimensions.contentMargin.x + } + + VerticalSpacer { } + + Item { + visible: hasSeparator + anchors.top: sectionName.top + + Rectangle { + width: frame.width + height: 1 + color: hifi.colors.baseGrayShadow + x: -hifi.dimensions.contentMargin.x + anchors.bottom: highlight.top + } + + Rectangle { + id: highlight + width: frame.width + height: 1 + color: hifi.colors.baseGrayHighlight + x: -hifi.dimensions.contentMargin.x + anchors.bottom: parent.top + } + } + + RalewayRegular { + id: sectionName + text: parent.name + size: 11 + font.capitalization: Font.AllUppercase + color: hifi.colors.lightGrayText + verticalAlignment: Text.AlignBottom + height: { + if (hasSeparator) { + hifi.dimensions.contentMargin.y + } + } + } + + VerticalSpacer { } +} diff --git a/interface/resources/qml/controls-uit/VerticalSpacer.qml b/interface/resources/qml/controls-uit/VerticalSpacer.qml new file mode 100644 index 0000000000..12645be412 --- /dev/null +++ b/interface/resources/qml/controls-uit/VerticalSpacer.qml @@ -0,0 +1,18 @@ +// +// VerticalSpacer.qml +// +// Created by David Rowe on 16 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "../styles-uit" + +Item { + width: 1 // Must be non-zero + height: hifi.dimensions.contentMargin.y +} diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 37ccbef849..f71de438a0 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -79,17 +79,10 @@ Window { scripts.stopAllScripts(); } - //Item { + Column { - Column { - - Text { - id: title - font.bold: true - font.pointSize: 16 - color: "#0e7077" - text: "Currently Running" - } + HifiControls.StaticSection { + name: "Currently Running" Row { id: allButtons @@ -162,14 +155,11 @@ Window { } } } + } - Text { - id: loadLabel - text: "Load Scripts" - font.bold: true - font.pointSize: 16 - color: "#0e7077" - } + HifiControls.StaticSection { + name: "Load Scripts" + hasSeparator: true Row { id: row1 @@ -281,6 +271,6 @@ Window { onClicked: root.loadScript(selectedScript.text) } } - //} + } } diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 9f1ce2ab27..fe316942c9 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -48,6 +48,7 @@ Item { id: dimensions readonly property real borderRadius: Screen.width >= 1920 && Screen.height >= 1080 ? 7.5 : 5.0 readonly property real borderWidth: Screen.width >= 1920 && Screen.height >= 1080 ? 2 : 1 + readonly property vector2d contentMargin: Qt.vector2d(12, 24) } /* diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index 81b2dd2cde..77b7fe288e 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -86,7 +86,7 @@ Frame { id: titleText anchors { left: parent.left - leftMargin: frameMarginLeft + window.contentMarginLeft + leftMargin: frameMarginLeft + hifi.dimensions.contentMargin.x right: controlsRow.left rightMargin: iconSize top: parent.top diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 15a2044958..73680229e0 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -51,8 +51,6 @@ Fadable { // property bool pinned: false property bool resizable: false - readonly property int contentMarginLeft: 12 - readonly property int contentMarginRight: 12 property vector2d minSize: Qt.vector2d(100, 100) property vector2d maxSize: Qt.vector2d(1280, 720) From 30498760b0c4601f785cb8b1b00f223d8fbe31a8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Feb 2016 21:06:06 +1300 Subject: [PATCH 019/114] Set up and use font size values --- .../qml/controls-uit/StaticSection.qml | 2 +- .../qml/styles-uit/HifiConstants.qml | 25 +++++++++++++++++-- .../qml/windows-uit/DefaultFrame.qml | 2 +- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/controls-uit/StaticSection.qml b/interface/resources/qml/controls-uit/StaticSection.qml index bcae22d8cc..d99b3a2bc0 100644 --- a/interface/resources/qml/controls-uit/StaticSection.qml +++ b/interface/resources/qml/controls-uit/StaticSection.qml @@ -50,7 +50,7 @@ Column { RalewayRegular { id: sectionName text: parent.name - size: 11 + size: hifi.fontSizes.sectionName font.capitalization: Font.AllUppercase color: hifi.colors.lightGrayText verticalAlignment: Text.AlignBottom diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index fe316942c9..c5634af7ad 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -14,6 +14,7 @@ import QtQuick.Window 2.2 Item { readonly property alias colors: colors readonly property alias dimensions: dimensions + readonly property alias fontSizes: fontSizes readonly property alias effects: effects Item { @@ -46,9 +47,29 @@ Item { Item { id: dimensions - readonly property real borderRadius: Screen.width >= 1920 && Screen.height >= 1080 ? 7.5 : 5.0 - readonly property real borderWidth: Screen.width >= 1920 && Screen.height >= 1080 ? 2 : 1 + readonly property bool largeScreen: Screen.width >= 1920 && Screen.height >= 1080 + readonly property real borderRadius: largeScreen ? 7.5 : 5.0 + readonly property real borderWidth: largeScreen ? 2 : 1 readonly property vector2d contentMargin: Qt.vector2d(12, 24) + readonly property int contentSpacing: 5 + } + + Item { + id: fontSizes + readonly property real overlayTitle: dimensions.largeScreen? 16 : 12 + readonly property real tabName: dimensions.largeScreen? 11 : 9 + readonly property real sectionName: dimensions.largeScreen? 11 : 9 + readonly property real inputLabel: dimensions.largeScreen? 11 : 9 + readonly property real textFieldInput: dimensions.largeScreen? 16 : 11 + readonly property real buttonLabel: dimensions.largeScreen? 15 : 10 + readonly property real button: dimensions.largeScreen? 15 : 10 + readonly property real listItem: dimensions.largeScreen? 11 : 9 + readonly property real tabularData: dimensions.largeScreen? 11 : 9 + readonly property real logo: dimensions.largeScreen? 15 : 10 + readonly property real code: dimensions.largeScreen? 15 : 10 + readonly property real rootMenu: dimensions.largeScreen? 11 : 9 + readonly property real menuItem: dimensions.largeScreen? 11 : 9 + readonly property real shortcutText: dimensions.largeScreen? 12 : 8 } /* diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index 77b7fe288e..ec5d3553ec 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -94,7 +94,7 @@ Frame { } text: window ? window.title : "" color: hifi.colors.white - size: 16 + size: hifi.fontSizes.overlayTitle } DropShadow { From 1164e3e303da1bea2726e7c996795ffd8e386318 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 17 Feb 2016 15:35:35 +1300 Subject: [PATCH 020/114] Set up window pane's content width so that can right-align --- .../qml/hifi/dialogs/RunningScripts.qml | 1 + interface/resources/qml/windows-uit/Frame.qml | 10 +++++----- interface/resources/qml/windows-uit/Window.qml | 16 +++++++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index f71de438a0..de0f179fe3 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -80,6 +80,7 @@ Window { } Column { + width: pane.contentWidth HifiControls.StaticSection { name: "Currently Running" diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 2ae8837ff3..8c5ac5e766 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -59,7 +59,7 @@ Item { height: width x: -width / 4 y: -width / 4 - visible: window && window.focus && windowContent.visible + visible: window && window.focus && pane.visible gradient: Gradient { // GradientStop position 0.5 is at full circumference of circle that fits inside the square. GradientStop { position: 0.0; color: "#ff000000" } // black, 100% opacity @@ -79,7 +79,7 @@ Item { border.width: 3 border.color: hifi.colors.white50 radius: hifi.dimensions.borderRadius - visible: window ? !windowContent.visible : false + visible: window ? !pane.visible : false } MouseArea { @@ -102,15 +102,15 @@ Item { } onReleased: { if (hid) { - windowContent.visible = true + pane.visible = true frameContent.visible = true hid = false; } } onPositionChanged: { if (pressed) { - if (windowContent.visible) { - windowContent.visible = false; + if (pane.visible) { + pane.visible = false; frameContent.visible = false hid = true; } diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 73680229e0..ab73566bcf 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -120,15 +120,17 @@ Fadable { property var frame: DefaultFrame { } // Scrollable window content. - property var scroller: Item { - id: windowContent + property var pane: Item { + property bool isScrolling: scrollView.height < scrollView.contentItem.height + property int contentWidth: scrollView.width - (isScrolling ? 11 : 0) + anchors.fill: parent - anchors.rightMargin: theScrollView.height < theScrollView.contentItem.height ? 11 : 0 + anchors.rightMargin: isScrolling ? 11 : 0 Rectangle { id: contentBackground anchors.fill: parent - anchors.rightMargin: theScrollView.height < theScrollView.contentItem.height ? 11 : 0 + anchors.rightMargin: parent.isScrolling ? 11 : 0 color: hifi.colors.baseGray } @@ -146,12 +148,12 @@ Fadable { } ScrollView { - id: theScrollView + id: scrollView contentItem: content horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff verticalScrollBarPolicy: Qt.ScrollBarAsNeeded anchors.fill: parent - anchors.rightMargin: height < contentItem.height ? 1 : 0 + anchors.rightMargin: parent.isScrolling ? 1 : 0 style: ScrollViewStyle { @@ -195,7 +197,7 @@ Fadable { } } - children: [ swallower, frame, scroller, activator ] + children: [ swallower, frame, pane, activator ] Component.onCompleted: raise(); Component.onDestruction: windowDestroyed(); From 61d359a9b542f5a38bfa8b6548aff4c2c84c21f9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 17 Feb 2016 16:12:11 +1300 Subject: [PATCH 021/114] Style Button controls --- .../resources/qml/controls-uit/Button.qml | 54 +++++++++++++++++++ .../qml/hifi/dialogs/RunningScripts.qml | 31 +++++++---- .../qml/styles-uit/HifiConstants.qml | 17 +++++- 3 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 interface/resources/qml/controls-uit/Button.qml diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml new file mode 100644 index 0000000000..9c7aee722b --- /dev/null +++ b/interface/resources/qml/controls-uit/Button.qml @@ -0,0 +1,54 @@ +// +// Button.qml +// +// Created by David Rowe on 16 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "../styles-uit" + +Original.Button { + id: button + property int color: 0 + width: 120 + height: 30 + + style: ButtonStyle { + + background: Rectangle { + radius: hifi.buttons.radius + gradient: Gradient { + GradientStop { + position: 0.2 + color: enabled + ? (!pressed && button.color != hifi.buttons.black || (!hovered || pressed) && button.color == hifi.buttons.black + ? hifi.buttons.colorStart[button.color] : hifi.buttons.colorFinish[button.color]) + : hifi.buttons.colorStart[hifi.buttons.white] + } + GradientStop { + position: 1.0 + color: enabled + ? ((!hovered || pressed) && button.color != hifi.buttons.black || !pressed && button.color == hifi.buttons.black + ? hifi.buttons.colorFinish[button.color] : hifi.buttons.colorStart[button.color]) + : hifi.buttons.colorFinish[hifi.buttons.white] + } + } + } + + label: RalewayBold { + font.capitalization: Font.AllUppercase + color: enabled ? hifi.buttons.textColor[button.color] : hifi.colors.lightGrayText + size: hifi.fontSizes.buttonLabel + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: control.text + } + } +} diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index de0f179fe3..ed7542c021 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -88,8 +88,16 @@ Window { Row { id: allButtons spacing: 8 - Button { text: "Reload all"; onClicked: reloadAll() } - Button { text: "Stop all"; onClicked: stopAll() } + HifiControls.Button { + text: "Reload all" + color: hifi.buttons.black + onClicked: reloadAll() + } + HifiControls.Button { + text: "Stop all" + color: hifi.buttons.red + onClicked: stopAll() + } } ScrollView { @@ -163,12 +171,14 @@ Window { hasSeparator: true Row { - id: row1 spacing: 8 + anchors.right: parent.right - Button { - text: "from URL"; - onClicked: fromUrlTimer.running = true; + HifiControls.Button { + text: "from URL" + color: hifi.buttons.black + height: 26 + onClicked: fromUrlTimer.running = true // For some reason trigginer an API that enters // an internal event loop directly from the button clicked @@ -186,9 +196,11 @@ Window { } } - Button { + HifiControls.Button { text: "from Disk" - onClicked: fromDiskTimer.running = true; + color: hifi.buttons.black + height: 26 + onClicked: fromDiskTimer.running = true Timer { id: fromDiskTimer @@ -265,9 +277,10 @@ Window { } } - Button { + HifiControls.Button { id: loadButton text: "Load" + color: hifi.buttons.blue enabled: selectedScript.text != "" onClicked: root.loadScript(selectedScript.text) } diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index c5634af7ad..9b81880332 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -15,6 +15,7 @@ Item { readonly property alias colors: colors readonly property alias dimensions: dimensions readonly property alias fontSizes: fontSizes + readonly property alias buttons: buttons readonly property alias effects: effects Item { @@ -61,8 +62,8 @@ Item { readonly property real sectionName: dimensions.largeScreen? 11 : 9 readonly property real inputLabel: dimensions.largeScreen? 11 : 9 readonly property real textFieldInput: dimensions.largeScreen? 16 : 11 - readonly property real buttonLabel: dimensions.largeScreen? 15 : 10 - readonly property real button: dimensions.largeScreen? 15 : 10 + readonly property real buttonLabel: dimensions.largeScreen? 12 : 10 + readonly property real button: dimensions.largeScreen? 12 : 10 readonly property real listItem: dimensions.largeScreen? 11 : 9 readonly property real tabularData: dimensions.largeScreen? 11 : 9 readonly property real logo: dimensions.largeScreen? 15 : 10 @@ -72,6 +73,18 @@ Item { readonly property real shortcutText: dimensions.largeScreen? 12 : 8 } + Item { + id: buttons + readonly property int white: 0 + readonly property int blue: 1 + readonly property int red: 2 + readonly property int black: 3 + readonly property var textColor: [ colors.darkGray, colors.white, colors.white, colors.white ] + readonly property var colorStart: [ "#ffffff", "#00b4ef", "#d42043", "#343434" ] + readonly property var colorFinish: [ "#afafaf", "#1080b8", "#94132e", "#000000" ] + readonly property int radius: 5 + } + /* SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } readonly property alias colors: colors From f568b1c67feb9964b84da9ea61e12c0bd35280ea Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 17 Feb 2016 16:19:00 +1300 Subject: [PATCH 022/114] Fix display of Raleway Bold --- interface/resources/qml/styles-uit/RalewayBold.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/styles-uit/RalewayBold.qml b/interface/resources/qml/styles-uit/RalewayBold.qml index 9a9d9ccd3f..1f6e536d67 100644 --- a/interface/resources/qml/styles-uit/RalewayBold.qml +++ b/interface/resources/qml/styles-uit/RalewayBold.qml @@ -20,4 +20,5 @@ Text { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: iconFont.name + font.bold: true // Font seems to need this in order to display bold. } From 2a25509f7cbf50cc318a05a63d24c7449719b8a0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 17 Feb 2016 20:38:01 +1300 Subject: [PATCH 023/114] Further font fixes --- interface/resources/qml/styles-uit/AnonymousProRegular.qml | 4 ++-- interface/resources/qml/styles-uit/FiraSansSemiBold.qml | 4 ++-- interface/resources/qml/styles-uit/HiFiGlyphs.qml | 4 ++-- interface/resources/qml/styles-uit/RalewayBold.qml | 4 ++-- interface/resources/qml/styles-uit/RalewayLight.qml | 4 ++-- interface/resources/qml/styles-uit/RalewayRegular.qml | 4 ++-- interface/resources/qml/styles-uit/RalewaySemibold.qml | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/styles-uit/AnonymousProRegular.qml b/interface/resources/qml/styles-uit/AnonymousProRegular.qml index f2a07372a4..5e226bea99 100644 --- a/interface/resources/qml/styles-uit/AnonymousProRegular.qml +++ b/interface/resources/qml/styles-uit/AnonymousProRegular.qml @@ -14,10 +14,10 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/AnonymousPro-Regular.ttf"; } + FontLoader { id: anonymousProRegular; source: "../../fonts/AnonymousPro-Regular.ttf"; } property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: anonymousProRegular.name } diff --git a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml index 06ab2df0c9..085ce0537c 100644 --- a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml +++ b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml @@ -14,10 +14,10 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/FiraSans-SemiBold.ttf"; } + FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: firaSansSemiBold.name } diff --git a/interface/resources/qml/styles-uit/HiFiGlyphs.qml b/interface/resources/qml/styles-uit/HiFiGlyphs.qml index 7b1d6ce441..854e893441 100644 --- a/interface/resources/qml/styles-uit/HiFiGlyphs.qml +++ b/interface/resources/qml/styles-uit/HiFiGlyphs.qml @@ -14,12 +14,12 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/hifi-glyphs.ttf"; } + FontLoader { id: hiFiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; } property int size: 32 font.pixelSize: size // Size this font in pixels because it's UI widgets. width: size height: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: hiFiGlyphs.name } diff --git a/interface/resources/qml/styles-uit/RalewayBold.qml b/interface/resources/qml/styles-uit/RalewayBold.qml index 1f6e536d67..359f0feda8 100644 --- a/interface/resources/qml/styles-uit/RalewayBold.qml +++ b/interface/resources/qml/styles-uit/RalewayBold.qml @@ -14,11 +14,11 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/Raleway-Bold.ttf"; } + FontLoader { id: ralewayBold; source: "../../fonts/Raleway-Bold.ttf"; } property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: ralewayBold.name font.bold: true // Font seems to need this in order to display bold. } diff --git a/interface/resources/qml/styles-uit/RalewayLight.qml b/interface/resources/qml/styles-uit/RalewayLight.qml index 5403a1bd00..8e24d74a46 100644 --- a/interface/resources/qml/styles-uit/RalewayLight.qml +++ b/interface/resources/qml/styles-uit/RalewayLight.qml @@ -14,10 +14,10 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/Raleway-Light.ttf"; } + FontLoader { id: ralewayLight; source: "../../fonts/Raleway-Light.ttf"; } property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: ralewayLight.name } diff --git a/interface/resources/qml/styles-uit/RalewayRegular.qml b/interface/resources/qml/styles-uit/RalewayRegular.qml index 40a34f23b8..c04db54e9d 100644 --- a/interface/resources/qml/styles-uit/RalewayRegular.qml +++ b/interface/resources/qml/styles-uit/RalewayRegular.qml @@ -14,10 +14,10 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/Raleway-Regular.ttf"; } + FontLoader { id: ralewayRegular; source: "../../fonts/Raleway-Regular.ttf"; } property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: ralewayRegular.name } diff --git a/interface/resources/qml/styles-uit/RalewaySemibold.qml b/interface/resources/qml/styles-uit/RalewaySemibold.qml index 61ce33998b..374696f902 100644 --- a/interface/resources/qml/styles-uit/RalewaySemibold.qml +++ b/interface/resources/qml/styles-uit/RalewaySemibold.qml @@ -14,10 +14,10 @@ import QtQuick.Controls.Styles 1.4 Text { id: root - FontLoader { id: iconFont; source: "../../fonts/Raleway-Semibold.ttf"; } + FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; } property real size: 32 font.pointSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - font.family: iconFont.name + font.family: ralewaySemibold.name } From b2314d33bad2e9a8f98a81f82fe5c0010f3be218 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 17 Feb 2016 20:44:09 +1300 Subject: [PATCH 024/114] Style and lay out text fields --- .../qml/controls-uit/StaticSection.qml | 4 +- .../resources/qml/controls-uit/TextField.qml | 40 ++++++++++++++++- .../qml/controls-uit/VerticalSpacer.qml | 2 +- .../qml/hifi/dialogs/RunningScripts.qml | 43 +++++++++++++------ .../qml/styles-uit/HifiConstants.qml | 14 +++++- 5 files changed, 84 insertions(+), 19 deletions(-) diff --git a/interface/resources/qml/controls-uit/StaticSection.qml b/interface/resources/qml/controls-uit/StaticSection.qml index d99b3a2bc0..a4857635f1 100644 --- a/interface/resources/qml/controls-uit/StaticSection.qml +++ b/interface/resources/qml/controls-uit/StaticSection.qml @@ -16,6 +16,8 @@ Column { property string name: "Static Section" property bool hasSeparator: false + spacing: hifi.dimensions.contentSpacing.y + anchors { left: parent.left leftMargin: hifi.dimensions.contentMargin.x @@ -60,6 +62,4 @@ Column { } } } - - VerticalSpacer { } } diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index 6d5b08e430..4c7cfb3679 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -1,7 +1,7 @@ // // TextField.qml // -// Created by Bradley Austin Davis on 4 Feb 2016 +// Created by David Rowe on 17 Feb 2016 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -12,6 +12,42 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 +import "../styles-uit" + TextField { - style: TextFieldStyle { renderType: Text.QtRendering } + id: textField + + property int colorScheme: hifi.colorSchemes.light + property string label: "" + + FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } + font.pointSize: 16 + + style: TextFieldStyle { + textColor: textField.colorScheme == hifi.colorSchemes.light + ? (textField.focus ? hifi.colors.black : hifi.colors.lightGray) + : (textField.focus ? hifi.colors.white : hifi.colors.lightGrayText) + background: Rectangle { + color: textField.colorScheme == hifi.colorSchemes.light + ? (textField.focus ? hifi.colors.white : hifi.colors.lightGray) + : (textField.focus ? hifi.colors.black : hifi.colors.baseGrayShadow) + border.color: hifi.colors.primaryHighlight + border.width: textField.focus ? 1 : 0 + } + placeholderTextColor: hifi.colors.lightGray + selectedTextColor: hifi.colors.black + selectionColor: hifi.colors.primaryHighlight + padding.left: hifi.dimensions.textPadding + padding.right: hifi.dimensions.textPadding + } + + RalewaySemibold { + text: textField.label + size: 13.5 + color: hifi.colors.lightGray + anchors.left: parent.left + anchors.bottom: parent.top + anchors.bottomMargin: 4 + visible: label != "" + } } diff --git a/interface/resources/qml/controls-uit/VerticalSpacer.qml b/interface/resources/qml/controls-uit/VerticalSpacer.qml index 12645be412..a3a0276f8f 100644 --- a/interface/resources/qml/controls-uit/VerticalSpacer.qml +++ b/interface/resources/qml/controls-uit/VerticalSpacer.qml @@ -14,5 +14,5 @@ import "../styles-uit" Item { width: 1 // Must be non-zero - height: hifi.dimensions.contentMargin.y + height: hifi.dimensions.contentSpacing.y } diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index ed7542c021..1d3386521a 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -25,7 +25,7 @@ Window { destroyOnInvisible: true x: 40; y: 40 implicitWidth: 384; implicitHeight: 640 - minSize: Qt.vector2d(300, 400) + minSize: Qt.vector2d(200, 300) HifiConstants { id: hifi } @@ -86,13 +86,14 @@ Window { name: "Currently Running" Row { - id: allButtons - spacing: 8 + spacing: hifi.dimensions.contentSpacing.x + HifiControls.Button { text: "Reload all" color: hifi.buttons.black onClicked: reloadAll() } + HifiControls.Button { text: "Stop all" color: hifi.buttons.red @@ -171,7 +172,7 @@ Window { hasSeparator: true Row { - spacing: 8 + spacing: hifi.dimensions.contentSpacing.x anchors.right: parent.right HifiControls.Button { @@ -214,8 +215,10 @@ Window { HifiControls.TextField { id: filterEdit - placeholderText: "filter" focus: true + colorScheme: hifi.colorSchemes.dark + //placeholderText: "filter" + label: "Filter" onTextChanged: scriptsModel.filterRegExp = new RegExp("^.*" + text + ".*$", "i") Component.onCompleted: scriptsModel.filterRegExp = new RegExp("^.*$", "i") } @@ -262,7 +265,13 @@ Window { HifiControls.TextField { id: selectedScript + anchors.left: parent.left + anchors.right: parent.right + anchors.rightMargin: loadButton.width + hifi.dimensions.contentSpacing.x + + colorScheme: hifi.colorSchemes.dark readOnly: true + Connections { target: treeView onCurrentIndexChanged: { @@ -272,18 +281,28 @@ Window { } else { selectedScript.text = "" } - } } } - HifiControls.Button { - id: loadButton - text: "Load" - color: hifi.buttons.blue - enabled: selectedScript.text != "" - onClicked: root.loadScript(selectedScript.text) + Item { + // Take the loadButton out of the column flow. + id: loadButtonContainer + anchors.top: selectedScript.top + anchors.right: parent.right + + HifiControls.Button { + id: loadButton + anchors.right: parent.right + + text: "Load" + color: hifi.buttons.blue + enabled: selectedScript.text != "" + onClicked: root.loadScript(selectedScript.text) + } } + + HifiControls.VerticalSpacer { } } } } diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 9b81880332..e12fbce4b7 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -13,6 +13,7 @@ import QtQuick.Window 2.2 Item { readonly property alias colors: colors + readonly property alias colorSchemes: colorSchemes readonly property alias dimensions: dimensions readonly property alias fontSizes: fontSizes readonly property alias buttons: buttons @@ -27,6 +28,7 @@ Item { readonly property color baseGrayHighlight: "#575757" readonly property color lightGray: "#6a6a6a" readonly property color lightGrayText: "#afafaf" + readonly property color lightGrayBackground: "#d4d4d4" readonly property color faintGray: "#e3e3e3" readonly property color primaryHighlight: "#00b4ef" readonly property color blueHighlight: "#00b4ef" @@ -35,6 +37,7 @@ Item { readonly property color redAccent: "#b70a37" readonly property color greenHighlight: "#1ac567" readonly property color greenShadow: "#2c8e72" + readonly property color black: "#000000" readonly property color white50: "#80ffffff" readonly property color white30: "#4dffffff" @@ -46,13 +49,20 @@ Item { readonly property color baseGrayShadow60: "#99252525" } + Item { + id: colorSchemes + readonly property int light: 0 + readonly property int dark: 1 + } + Item { id: dimensions readonly property bool largeScreen: Screen.width >= 1920 && Screen.height >= 1080 readonly property real borderRadius: largeScreen ? 7.5 : 5.0 readonly property real borderWidth: largeScreen ? 2 : 1 readonly property vector2d contentMargin: Qt.vector2d(12, 24) - readonly property int contentSpacing: 5 + readonly property vector2d contentSpacing: Qt.vector2d(8, 12) + readonly property real textPadding: 8 } Item { @@ -61,7 +71,7 @@ Item { readonly property real tabName: dimensions.largeScreen? 11 : 9 readonly property real sectionName: dimensions.largeScreen? 11 : 9 readonly property real inputLabel: dimensions.largeScreen? 11 : 9 - readonly property real textFieldInput: dimensions.largeScreen? 16 : 11 + readonly property real textFieldInput: dimensions.largeScreen? 13.5 : 11 readonly property real buttonLabel: dimensions.largeScreen? 12 : 10 readonly property real button: dimensions.largeScreen? 12 : 10 readonly property real listItem: dimensions.largeScreen? 11 : 9 From d32f743f529bb10d8bc7308ecf0513278ac74a72 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Feb 2016 16:35:51 +1300 Subject: [PATCH 025/114] Style running scripts and available scripts tables --- .../resources/qml/controls-uit/Table.qml | 133 ++++++++++++++++++ .../resources/qml/controls-uit/TextField.qml | 4 +- interface/resources/qml/controls-uit/Tree.qml | 88 ++++++++++++ .../qml/hifi/dialogs/RunningScripts.qml | 114 ++------------- .../qml/styles-uit/HifiConstants.qml | 8 ++ 5 files changed, 245 insertions(+), 102 deletions(-) create mode 100644 interface/resources/qml/controls-uit/Table.qml create mode 100644 interface/resources/qml/controls-uit/Tree.qml diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml new file mode 100644 index 0000000000..481705166d --- /dev/null +++ b/interface/resources/qml/controls-uit/Table.qml @@ -0,0 +1,133 @@ +// +// Table.qml +// +// Created by David Rowe on 18 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import "../styles-uit" + +TableView { + id: tableView + + property var tableModel: ListModel { } + property int colorScheme: hifi.colorSchemes.light + readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light + + model: tableModel + + TableViewColumn { + role: "name" + } + + anchors { left: parent.left; right: parent.right } + + headerVisible: false + + // Use rectangle to draw border with rounded corners. + frameVisible: false + Rectangle { + color: "#00000000" + anchors { fill: parent; margins: -2 } + radius: hifi.dimensions.borderRadius + border.color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight + border.width: 2 + } + anchors.margins: 2 // Shrink TableView to lie within border. + + backgroundVisible: true + + style: TableViewStyle { + // Needed in order for rows to keep displaying rows after end of table entries. + backgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven + alternateBackgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + } + + rowDelegate: Rectangle { + height: (styleData.selected ? 1.8 : 1) * hifi.dimensions.tableRowHeight + color: styleData.selected + ? hifi.colors.primaryHighlight + : tableView.isLightColorScheme + ? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd) + : (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd) + } + + itemDelegate: Item { + anchors { + left: parent.left + leftMargin: hifi.dimensions.tablePadding + right: parent.right + rightMargin: hifi.dimensions.tablePadding + } + + FiraSansSemiBold { + id: textItem + text: styleData.value + size: hifi.fontSizes.tableText + color: colorScheme == hifi.colorSchemes.light + ? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight) + : (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText) + anchors { + left: parent.left + right: parent.right + top: parent.top + topMargin: 3 + } + + // FIXME: Put reload item in tableModel passed in from RunningScripts. + HiFiGlyphs { + id: reloadButton + text: "a" + color: parent.color + anchors { + top: parent.top + right: stopButton.left + verticalCenter: parent.verticalCenter + } + MouseArea { + anchors { fill: parent; margins: -2 } + onClicked: reloadScript(model.url) + } + } + + // FIXME: Put stop item in tableModel passed in from RunningScripts. + HiFiGlyphs { + id: stopButton + text: "C" + color: parent.color + anchors { + top: parent.top + right: parent.right + verticalCenter: parent.verticalCenter + } + MouseArea { + anchors { fill: parent; margins: -2 } + onClicked: stopScript(model.url) + } + } + } + + // FIXME: Automatically use aux. information from tableModel + FiraSansSemiBold { + text: tableModel.get(styleData.row).url + elide: Text.ElideMiddle + size: hifi.fontSizes.tableText + color: colorScheme == hifi.colorSchemes.light + ? (styleData.selected ? hifi.colors.black : hifi.colors.lightGray) + : (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText) + anchors { + top: textItem.bottom + left: parent.left + right: parent.right + } + visible: styleData.selected + } + } +} diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index 4c7cfb3679..838008979a 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -21,9 +21,9 @@ TextField { property string label: "" FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } - font.pointSize: 16 + font.pointSize: hifi.fontSizes.textFieldInput - style: TextFieldStyle { + style: TextFieldStyle { textColor: textField.colorScheme == hifi.colorSchemes.light ? (textField.focus ? hifi.colors.black : hifi.colors.lightGray) : (textField.focus ? hifi.colors.white : hifi.colors.lightGrayText) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml new file mode 100644 index 0000000000..6a52641bbb --- /dev/null +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -0,0 +1,88 @@ +// +// Table.qml +// +// Created by David Rowe on 17 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import "../styles-uit" + +TreeView { + id: treeView + + property var treeModel: ListModel { } + property int colorScheme: hifi.colorSchemes.light + readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light + + model: treeModel + + TableViewColumn { + role: "display"; + } + + anchors { left: parent.left; right: parent.right } + + headerVisible: false + + // Use rectangle to draw border with rounded corners. + frameVisible: false + Rectangle { + color: "#00000000" + anchors.fill: parent + radius: hifi.dimensions.borderRadius + border.color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight + border.width: 2 + anchors.margins: -2 + } + anchors.margins: 2 // Shrink TreeView to lie within border. + + backgroundVisible: true + + style: TreeViewStyle { + // Needed in order for rows to keep displaying rows after end of table entries. + backgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven + alternateBackgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + } + + rowDelegate: Rectangle { + height: hifi.dimensions.tableRowHeight + color: styleData.selected + ? hifi.colors.primaryHighlight + : treeView.isLightColorScheme + ? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd) + : (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd) + } + + itemDelegate: FiraSansSemiBold { + anchors { + left: parent.left + leftMargin: (2 + styleData.depth) * hifi.dimensions.tablePadding + right: parent.right + rightMargin: hifi.dimensions.tablePadding + verticalCenter: parent.verticalCenter + } + + text: styleData.value + size: hifi.fontSizes.tableText + color: colorScheme == hifi.colorSchemes.light + ? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight) + : (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText) + } + + onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) + + // FIXME not triggered by double click? + onActivated: { + var path = scriptsModel.data(index, 0x100) + if (path) { + loadScript(path) + } + } +} diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 1d3386521a..c1421c41bc 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -101,69 +101,12 @@ Window { } } - ScrollView { - onActiveFocusChanged: if (activeFocus && listView.currentItem) { listView.currentItem.forceActiveFocus(); } - - ListView { - id: listView - clip: true - anchors { fill: parent; margins: 0 } - model: runningScriptsModel - delegate: FocusScope { - id: scope - anchors { left: parent.left; right: parent.right } - height: scriptName.height + 12 + (ListView.isCurrentItem ? scriptName.height + 6 : 0) - Keys.onDownPressed: listView.incrementCurrentIndex() - Keys.onUpPressed: listView.decrementCurrentIndex() - Rectangle { - id: rectangle - anchors.fill: parent - clip: true - radius: 3 - color: scope.ListView.isCurrentItem ? "#79f" : - index % 2 ? "#ddd" : "#eee" - - Text { - id: scriptName - anchors { left: parent.left; leftMargin: 4; top: parent.top; topMargin:6 } - text: name - } - - Text { - id: scriptUrl - anchors { left: scriptName.left; right: parent.right; rightMargin: 4; top: scriptName.bottom; topMargin: 6 } - text: url - elide: Text.ElideMiddle - } - - MouseArea { - anchors.fill: parent - onClicked: { listView.currentIndex = index; scope.forceActiveFocus(); } - } - - Row { - anchors.verticalCenter: scriptName.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 4 - spacing: 4 - HifiControls.FontAwesome { - text: "\uf021"; size: scriptName.height; - MouseArea { - anchors { fill: parent; margins: -2; } - onClicked: reloadScript(model.url) - } - } - HifiControls.FontAwesome { - size: scriptName.height; text: "\uf00d" - MouseArea { - anchors { fill: parent; margins: -2; } - onClicked: stopScript(model.url) - } - } - } - } - } - } + HifiControls.Table { + tableModel: runningScriptsModel + height: 185 + colorScheme: hifi.colorSchemes.dark + anchors.left: parent.left + anchors.right: parent.right } } @@ -215,6 +158,8 @@ Window { HifiControls.TextField { id: filterEdit + anchors.left: parent.left + anchors.right: parent.right focus: true colorScheme: hifi.colorSchemes.dark //placeholderText: "filter" @@ -223,44 +168,13 @@ Window { Component.onCompleted: scriptsModel.filterRegExp = new RegExp("^.*$", "i") } - TreeView { + HifiControls.Tree { id: treeView - height: 128 - headerVisible: false - // FIXME doesn't work? - onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) - // FIXME not triggered by double click? - onActivated: { - var path = scriptsModel.data(index, 0x100) - if (path) { - loadScript(path) - } - } - model: scriptsModel - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - onClicked: treeView.foo(); - } - - function foo() { - var localRect = Qt.rect(0, 0, width, height); - var rect = desktop.mapFromItem(treeView, 0, 0, width, height) - console.log("Local Rect " + localRect) - console.log("Rect " + rect) - console.log("Desktop size " + Qt.size(desktop.width, desktop.height)); - } - - TableViewColumn { - title: "Name"; - role: "display"; - // delegate: Text { - // text: styleData.value - // renderType: Text.QtRendering - // elite: styleData.elideMode - // } - } + height: 155 + treeModel: scriptsModel + colorScheme: hifi.colorSchemes.dark + anchors.left: parent.left + anchors.right: parent.right } HifiControls.TextField { diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index e12fbce4b7..9f7ee10dac 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -41,12 +41,17 @@ Item { readonly property color white50: "#80ffffff" readonly property color white30: "#4dffffff" + readonly property color white25: "#40ffffff" readonly property color baseGrayHighlight15: "#26575757" readonly property color baseGrayHighlight40: "#66575757" readonly property color darkGray30: "#4d121212" readonly property color darkGray0: "#00121212" readonly property color faintGray50: "#80e3e3e3" readonly property color baseGrayShadow60: "#99252525" + readonly property color tableRowLightOdd: white50 + readonly property color tableRowLightEven: "#1a575757" + readonly property color tableRowDarkOdd: "#80393939" + readonly property color tableRowDarkEven: "#a6181818" } Item { @@ -63,6 +68,8 @@ Item { readonly property vector2d contentMargin: Qt.vector2d(12, 24) readonly property vector2d contentSpacing: Qt.vector2d(8, 12) readonly property real textPadding: 8 + readonly property real tablePadding: 12 + readonly property real tableRowHeight: largeScreen ? 26 : 23 } Item { @@ -72,6 +79,7 @@ Item { readonly property real sectionName: dimensions.largeScreen? 11 : 9 readonly property real inputLabel: dimensions.largeScreen? 11 : 9 readonly property real textFieldInput: dimensions.largeScreen? 13.5 : 11 + readonly property real tableText: dimensions.largeScreen? 13.5 : 11 readonly property real buttonLabel: dimensions.largeScreen? 12 : 10 readonly property real button: dimensions.largeScreen? 12 : 10 readonly property real listItem: dimensions.largeScreen? 11 : 9 From 4df77cff317d0cdc1bfb3e13bf547daaca415fad Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Feb 2016 18:10:58 +1300 Subject: [PATCH 026/114] Add scrollbars to running scripts and available scripts tables --- .../resources/qml/controls-uit/Table.qml | 54 ++++++++++++++++++- interface/resources/qml/controls-uit/Tree.qml | 54 ++++++++++++++++++- .../qml/styles-uit/HifiConstants.qml | 2 + 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index 481705166d..77434acd0d 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -44,10 +44,60 @@ TableView { backgroundVisible: true + horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff + verticalScrollBarPolicy: Qt.ScrollBarAsNeeded + style: TableViewStyle { // Needed in order for rows to keep displaying rows after end of table entries. - backgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven - alternateBackgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven + alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + + handle: Item { + id: scrollbarHandle + implicitWidth: 8 + Rectangle { + radius: 4 + color: hifi.colors.tableScrollHandle + anchors { + fill: parent + leftMargin: 4 // Finesse size and position. + rightMargin: -1 + topMargin: 2 + bottomMargin: 3 + } + } + } + + scrollBarBackground: Item { + implicitWidth: 10 + + Rectangle { + color: hifi.colors.baseGrayHighlight + anchors { + fill: parent + leftMargin: 1 // Finesse size and position. + topMargin: -2 + bottomMargin: -2 + } + } + + Rectangle { + radius: 4 + color: hifi.colors.tableScrollBackground + anchors { + fill: parent + leftMargin: 3 // Finesse position. + } + } + } + + incrementControl: Item { + visible: false + } + + decrementControl: Item { + visible: false + } } rowDelegate: Rectangle { diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 6a52641bbb..759e69ea66 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -45,10 +45,60 @@ TreeView { backgroundVisible: true + horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff + verticalScrollBarPolicy: Qt.ScrollBarAsNeeded + style: TreeViewStyle { // Needed in order for rows to keep displaying rows after end of table entries. - backgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven - alternateBackgroundColor: treeView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven + alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + + handle: Item { + id: scrollbarHandle + implicitWidth: 8 + Rectangle { + radius: 4 + color: hifi.colors.tableScrollHandle + anchors { + fill: parent + leftMargin: 4 // Finesse size and position. + rightMargin: -1 + topMargin: 2 + bottomMargin: 3 + } + } + } + + scrollBarBackground: Item { + implicitWidth: 10 + + Rectangle { + color: hifi.colors.baseGrayHighlight + anchors { + fill: parent + leftMargin: 1 // Finesse size and position. + topMargin: -2 + bottomMargin: -2 + } + } + + Rectangle { + radius: 4 + color: hifi.colors.tableScrollBackground + anchors { + fill: parent + leftMargin: 3 // Finesse position. + } + } + } + + incrementControl: Item { + visible: false + } + + decrementControl: Item { + visible: false + } } rowDelegate: Rectangle { diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 9f7ee10dac..9896cb57c2 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -52,6 +52,8 @@ Item { readonly property color tableRowLightEven: "#1a575757" readonly property color tableRowDarkOdd: "#80393939" readonly property color tableRowDarkEven: "#a6181818" + readonly property color tableScrollHandle: "#707070" + readonly property color tableScrollBackground: "#323232" } Item { From 81169c59c8670eaadd71edb3f889e6f8e513bb4c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Feb 2016 19:52:20 +1300 Subject: [PATCH 027/114] Fix runtime warnings --- interface/resources/qml/controls-uit/Table.qml | 6 +++--- interface/resources/qml/controls-uit/Tree.qml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index 77434acd0d..6ea64e8c46 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -111,9 +111,9 @@ TableView { itemDelegate: Item { anchors { - left: parent.left + left: parent ? parent.left : undefined leftMargin: hifi.dimensions.tablePadding - right: parent.right + right: parent ? parent.right : undefined rightMargin: hifi.dimensions.tablePadding } @@ -166,7 +166,7 @@ TableView { // FIXME: Automatically use aux. information from tableModel FiraSansSemiBold { - text: tableModel.get(styleData.row).url + text: tableModel.get(styleData.row) ? tableModel.get(styleData.row).url : "" elide: Text.ElideMiddle size: hifi.fontSizes.tableText color: colorScheme == hifi.colorSchemes.light diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 759e69ea66..2cab92565a 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -112,11 +112,11 @@ TreeView { itemDelegate: FiraSansSemiBold { anchors { - left: parent.left + left: parent ? parent.left : undefined leftMargin: (2 + styleData.depth) * hifi.dimensions.tablePadding - right: parent.right + right: parent ? parent.right : undefined rightMargin: hifi.dimensions.tablePadding - verticalCenter: parent.verticalCenter + verticalCenter: parent ? parent.verticalCenter : undefined } text: styleData.value From b68837277cd1e62c2c928e988edba58656e8b7eb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Feb 2016 22:12:43 +1300 Subject: [PATCH 028/114] Fix default focus --- interface/resources/qml/hifi/dialogs/RunningScripts.qml | 5 +++++ interface/resources/qml/windows-uit/Window.qml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index c1421c41bc..55b8946805 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -46,6 +46,11 @@ Window { Component.onCompleted: updateRunningScripts() + function setDefaultFocus() { + // Work around FocusScope of scrollable window. + filterEdit.forceActiveFocus(); + } + function updateRunningScripts() { var runningScripts = ScriptDiscoveryService.getRunning(); runningScriptsModel.clear() diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index ab73566bcf..36d083dfc6 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -199,7 +199,7 @@ Fadable { children: [ swallower, frame, pane, activator ] - Component.onCompleted: raise(); + Component.onCompleted: { raise(); setDefaultFocus(); } Component.onDestruction: windowDestroyed(); onParentChanged: raise(); From c07b1f9b1e2277b8fe593dd73a50a26548a86d53 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Feb 2016 23:06:26 +1300 Subject: [PATCH 029/114] Tidying --- interface/resources/qml/controls-uit/Tree.qml | 1 - interface/resources/qml/desktop/Desktop.qml | 4 +- .../qml/styles-uit/HifiConstants.qml | 79 ++++--------------- .../qml/windows-uit/DefaultFrame.qml | 1 - .../resources/qml/windows-uit/Fadable.qml | 1 - interface/resources/qml/windows-uit/Frame.qml | 10 ++- .../resources/qml/windows-uit/Window.qml | 2 + tests/ui/qml/main.qml | 10 +++ 8 files changed, 35 insertions(+), 73 deletions(-) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 2cab92565a..9c52679d7e 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -128,7 +128,6 @@ TreeView { onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) - // FIXME not triggered by double click? onActivated: { var path = scriptsModel.data(index, 0x100) if (path) { diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 0286c45ac3..c4ca0ab9a3 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -148,12 +148,12 @@ FocusScope { } Component.onCompleted: { - offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged); + //offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged); focusHack.start(); } function onWindowFocusChanged() { - console.log("Focus item is " + offscreenWindow.activeFocusItem); + //console.log("Focus item is " + offscreenWindow.activeFocusItem); // FIXME this needs more testing before it can go into production // and I already cant produce any way to have a modal dialog lose focus diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 9896cb57c2..44745c96dc 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -21,33 +21,38 @@ Item { Item { id: colors - readonly property color white: "#ffffff" + + // Base colors readonly property color baseGray: "#404040" readonly property color darkGray: "#121212" readonly property color baseGrayShadow: "#252525" readonly property color baseGrayHighlight: "#575757" readonly property color lightGray: "#6a6a6a" readonly property color lightGrayText: "#afafaf" - readonly property color lightGrayBackground: "#d4d4d4" readonly property color faintGray: "#e3e3e3" readonly property color primaryHighlight: "#00b4ef" - readonly property color blueHighlight: "#00b4ef" readonly property color blueAccent: "#1080b8" readonly property color redHighlight: "#e2334d" readonly property color redAccent: "#b70a37" readonly property color greenHighlight: "#1ac567" readonly property color greenShadow: "#2c8e72" - readonly property color black: "#000000" + // Semitransparent + readonly property color darkGray30: "#4d121212" + readonly property color darkGray0: "#00121212" + readonly property color baseGrayShadow60: "#99252525" + readonly property color baseGrayHighlight40: "#66575757" + readonly property color baseGrayHighlight15: "#26575757" + readonly property color faintGray50: "#80e3e3e3" + // Other colors + readonly property color white: "#ffffff" + readonly property color black: "#000000" + // Semitransparent readonly property color white50: "#80ffffff" readonly property color white30: "#4dffffff" readonly property color white25: "#40ffffff" - readonly property color baseGrayHighlight15: "#26575757" - readonly property color baseGrayHighlight40: "#66575757" - readonly property color darkGray30: "#4d121212" - readonly property color darkGray0: "#00121212" - readonly property color faintGray50: "#80e3e3e3" - readonly property color baseGrayShadow60: "#99252525" + + // Control specific colors readonly property color tableRowLightOdd: white50 readonly property color tableRowLightEven: "#1a575757" readonly property color tableRowDarkOdd: "#80393939" @@ -105,60 +110,6 @@ Item { readonly property int radius: 5 } - /* - SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } - readonly property alias colors: colors - readonly property alias layout: layout - readonly property alias fonts: fonts - readonly property alias styles: styles - readonly property alias effects: effects - - Item { - id: colors - readonly property color hifiBlue: "#0e7077" - readonly property color window: sysPalette.window - readonly property color dialogBackground: sysPalette.window - readonly property color inputBackground: "white" - readonly property color background: sysPalette.dark - readonly property color text: "#202020" - readonly property color disabledText: "gray" - readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2 - readonly property color light: sysPalette.light - readonly property alias activeWindow: activeWindow - readonly property alias inactiveWindow: inactiveWindow - QtObject { - id: activeWindow - readonly property color headerBackground: "white" - readonly property color headerText: "black" - } - QtObject { - id: inactiveWindow - readonly property color headerBackground: "gray" - readonly property color headerText: "black" - } - } - - QtObject { - id: fonts - readonly property string fontFamily: "Arial" // Available on both Windows and OSX - readonly property real pixelSize: 22 // Logical pixel size; works on Windows and OSX at varying physical DPIs - readonly property real headerPixelSize: 32 - } - - QtObject { - id: layout - property int spacing: 8 - property int rowHeight: 40 - property int windowTitleHeight: 48 - } - - QtObject { - id: styles - readonly property int borderWidth: 5 - readonly property int borderRadius: borderWidth * 2 - } - */ - QtObject { id: effects readonly property int fadeInDuration: 300 diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index ec5d3553ec..4bc7fc7aec 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -12,7 +12,6 @@ import QtQuick 2.5 import QtGraphicalEffects 1.0 import "." -import "../controls-uit" import "../styles-uit" Frame { diff --git a/interface/resources/qml/windows-uit/Fadable.qml b/interface/resources/qml/windows-uit/Fadable.qml index bf3a6aa2b4..34990c2147 100644 --- a/interface/resources/qml/windows-uit/Fadable.qml +++ b/interface/resources/qml/windows-uit/Fadable.qml @@ -12,7 +12,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtGraphicalEffects 1.0 -import "." import "../styles-uit" // Enable window visibility transitions diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 8c5ac5e766..5f59c6c192 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -11,15 +11,12 @@ import QtQuick 2.5 import QtGraphicalEffects 1.0 -import "../controls-uit" import "../styles-uit" import "../js/Utils.js" as Utils Item { id: frame - // Frames always fill their parents, but their decorations may extend - // beyond the window via negative margin sizes - anchors.fill: parent + HifiConstants { id: hifi } property alias window: frame.parent // Convenience accessor for the window default property var decoration @@ -31,6 +28,10 @@ Item { readonly property int frameMarginTop: 2 * frameMargin + iconSize readonly property int frameMarginBottom: iconSize + 6 + // Frames always fill their parents, but their decorations may extend + // beyond the window via negative margin sizes + anchors.fill: parent + children: [ focusShadow, decoration, @@ -67,6 +68,7 @@ Item { GradientStop { position: 0.5; color: "#00000000" } // black, 0% opacity GradientStop { position: 1.0; color: "#00000000" } } + cached: true } Rectangle { diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 36d083dfc6..5b9f10ab9a 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -26,6 +26,7 @@ import "../styles-uit" Fadable { id: window HifiConstants { id: hifi } + // The Window size is the size of the content, while the frame // decorations can extend outside it. implicitHeight: content ? content.height : 0 @@ -145,6 +146,7 @@ Fadable { GradientStop { position: 0.0; color: hifi.colors.darkGray } GradientStop { position: 1.0; color: hifi.colors.darkGray0 } } + cached: true } ScrollView { diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index ef27ff3633..a98651df83 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -48,6 +48,16 @@ ApplicationWindow { } } + Button { + text: "Attachments" + property var builder: Component { + AttachmentsDialog { } + } + onClicked: { + var attachmentsDialog = builder.createObject(desktop); + } + } + /* Button { text: "restore all" From 91e4fb478d0bcee0ddb811f0d3dbbdb3c1d736dd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 20 Feb 2016 13:12:51 +1300 Subject: [PATCH 030/114] Don't display dialog focus or content shadows on OSX Alpha gradients display as fuchsia on OSX. --- interface/resources/qml/windows-uit/Frame.qml | 4 +++- interface/resources/qml/windows-uit/Window.qml | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 5f59c6c192..fc8697f93f 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -60,7 +60,9 @@ Item { height: width x: -width / 4 y: -width / 4 - visible: window && window.focus && pane.visible + // FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX. + // Check again when have a later version of QtQuick. + visible: window && window.focus && pane.visible && Qt.platform.os != "osx" gradient: Gradient { // GradientStop position 0.5 is at full circumference of circle that fits inside the square. GradientStop { position: 0.0; color: "#ff000000" } // black, 100% opacity diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 5b9f10ab9a..caf465fb58 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -136,6 +136,9 @@ Fadable { } LinearGradient { + // FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX. + // Check again when have a later version of QtQuick. + visible: Qt.platform.os != "osx" anchors.top: contentBackground.bottom anchors.left: contentBackground.left width: contentBackground.width - 1 From b2c74447fbeda5be5a2fbaca8c2fb5388175ffc8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 21 Feb 2016 12:44:29 +1300 Subject: [PATCH 031/114] Fix OSX scrollbars in scripts lists starting too low --- interface/resources/qml/controls-uit/Table.qml | 1 + interface/resources/qml/controls-uit/Tree.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index 6ea64e8c46..641e442a9e 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -30,6 +30,7 @@ TableView { anchors { left: parent.left; right: parent.right } headerVisible: false + headerDelegate: Item { } // Fix OSX QML bug that displays scrollbar starting too low. // Use rectangle to draw border with rounded corners. frameVisible: false diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 9c52679d7e..ed73b21db8 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -30,6 +30,7 @@ TreeView { anchors { left: parent.left; right: parent.right } headerVisible: false + headerDelegate: Item { } // Fix OSX QML bug that displays scrollbar starting too low. // Use rectangle to draw border with rounded corners. frameVisible: false From 558c8872b16ac5a729314420040bbf21c672ee06 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 21 Feb 2016 14:02:51 +1300 Subject: [PATCH 032/114] Rework scrollbar to make layout more robust --- .../resources/qml/controls-uit/Table.qml | 27 +++++++++---------- interface/resources/qml/controls-uit/Tree.qml | 27 +++++++++---------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index 641e442a9e..5fa916f0cc 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -55,40 +55,37 @@ TableView { handle: Item { id: scrollbarHandle - implicitWidth: 8 + implicitWidth: 6 Rectangle { - radius: 4 - color: hifi.colors.tableScrollHandle anchors { fill: parent - leftMargin: 4 // Finesse size and position. - rightMargin: -1 - topMargin: 2 - bottomMargin: 3 + leftMargin: 2 // Move it right + rightMargin: -2 // "" + topMargin: 3 // Shrink vertically + bottomMargin: 3 // "" } + radius: 3 + color: hifi.colors.tableScrollHandle } } scrollBarBackground: Item { implicitWidth: 10 - Rectangle { - color: hifi.colors.baseGrayHighlight anchors { fill: parent - leftMargin: 1 // Finesse size and position. - topMargin: -2 - bottomMargin: -2 + margins: -1 // Expand } + color: hifi.colors.baseGrayHighlight } Rectangle { - radius: 4 - color: hifi.colors.tableScrollBackground anchors { fill: parent - leftMargin: 3 // Finesse position. + margins: 1 // Shrink } + radius: 4 + color: hifi.colors.tableScrollBackground } } diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index ed73b21db8..18eab55563 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -56,40 +56,37 @@ TreeView { handle: Item { id: scrollbarHandle - implicitWidth: 8 + implicitWidth: 6 Rectangle { - radius: 4 - color: hifi.colors.tableScrollHandle anchors { fill: parent - leftMargin: 4 // Finesse size and position. - rightMargin: -1 - topMargin: 2 - bottomMargin: 3 + leftMargin: 2 // Move it right + rightMargin: -2 // "" + topMargin: 3 // Shrink vertically + bottomMargin: 3 // "" } + radius: 3 + color: hifi.colors.tableScrollHandle } } scrollBarBackground: Item { implicitWidth: 10 - Rectangle { - color: hifi.colors.baseGrayHighlight anchors { fill: parent - leftMargin: 1 // Finesse size and position. - topMargin: -2 - bottomMargin: -2 + margins: -1 // Expand } + color: hifi.colors.baseGrayHighlight } Rectangle { - radius: 4 - color: hifi.colors.tableScrollBackground anchors { fill: parent - leftMargin: 3 // Finesse position. + margins: 1 // Shrink } + radius: 4 + color: hifi.colors.tableScrollBackground } } From bfedd24ad73ebfacd1992f18a8b881e6f51ea782 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 21 Feb 2016 16:43:41 +1300 Subject: [PATCH 033/114] Fixes after reviewing against latest UI Toolkit doc --- interface/resources/qml/controls-uit/TextField.qml | 4 +++- .../resources/qml/styles-uit/HifiConstants.qml | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index 838008979a..76858ad83d 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -21,7 +21,9 @@ TextField { property string label: "" FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } + font.family: firaSansSemiBold.name font.pointSize: hifi.fontSizes.textFieldInput + height: implicitHeight + 4 // Make surrounding box higher so that highlight is vertically centered. style: TextFieldStyle { textColor: textField.colorScheme == hifi.colorSchemes.light @@ -43,7 +45,7 @@ TextField { RalewaySemibold { text: textField.label - size: 13.5 + size: hifi.fontSizes.inputLabel color: hifi.colors.lightGray anchors.left: parent.left anchors.bottom: parent.top diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 44745c96dc..fda90d731a 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -84,17 +84,17 @@ Item { readonly property real overlayTitle: dimensions.largeScreen? 16 : 12 readonly property real tabName: dimensions.largeScreen? 11 : 9 readonly property real sectionName: dimensions.largeScreen? 11 : 9 - readonly property real inputLabel: dimensions.largeScreen? 11 : 9 + readonly property real inputLabel: dimensions.largeScreen? 13.5 : 9 readonly property real textFieldInput: dimensions.largeScreen? 13.5 : 11 readonly property real tableText: dimensions.largeScreen? 13.5 : 11 - readonly property real buttonLabel: dimensions.largeScreen? 12 : 10 - readonly property real button: dimensions.largeScreen? 12 : 10 - readonly property real listItem: dimensions.largeScreen? 11 : 9 + readonly property real buttonLabel: dimensions.largeScreen? 12 : 8 + readonly property real iconButton: dimensions.largeScreen? 12: 8 + readonly property real listItem: dimensions.largeScreen? 13.5 : 9 readonly property real tabularData: dimensions.largeScreen? 11 : 9 - readonly property real logo: dimensions.largeScreen? 15 : 10 + readonly property real logs: dimensions.largeScreen? 15 : 10 readonly property real code: dimensions.largeScreen? 15 : 10 - readonly property real rootMenu: dimensions.largeScreen? 11 : 9 - readonly property real menuItem: dimensions.largeScreen? 11 : 9 + readonly property real rootMenu: dimensions.largeScreen? 13.5 : 9 + readonly property real menuItem: dimensions.largeScreen? 13.5 : 9 readonly property real shortcutText: dimensions.largeScreen? 12 : 8 } From 31b895058bc81ae817af1ac4f6f0af38f5f4de6f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sun, 21 Feb 2016 09:30:26 -0800 Subject: [PATCH 034/114] depth reticle work --- interface/src/ui/ApplicationCompositor.cpp | 53 ++++++++++++++++++---- interface/src/ui/ApplicationCompositor.h | 9 ++++ 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 44f37f55c7..76bf48b45e 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -283,16 +283,51 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int //Mouse Pointer if (getReticleVisible()) { - glm::mat4 overlayXfm; - _modelTransform.getMatrix(overlayXfm); + if (_drawAt3D) { + //auto headPose = qApp->getHMDSensorPose(); + auto myCamera = qApp->getCamera(); + mat4 cameraMat = myCamera->getTransform(); + auto cameraOrientation = myCamera->getOrientation(); + auto UITransform = cameraMat * glm::inverse(headPose); + auto relativePosition4 = glm::inverse(UITransform) * vec4(_drawAt3DPosition, 1); + auto relativePosition = vec3(relativePosition4) / relativePosition4.w; + auto relativeDistance = glm::length(relativePosition); - auto reticlePosition = getReticlePosition(); - glm::vec2 projection = overlayToSpherical(reticlePosition); - float cursorDepth = getReticleDepth(); - mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); - mat4 reticleXfm = overlayXfm * pointerXfm; - reticleXfm = glm::scale(reticleXfm, reticleScale); - batch.setModelTransform(reticleXfm); + // look at borrowed from overlays + float elevation = -asinf(relativePosition.y / glm::length(relativePosition)); + float azimuth = atan2f(relativePosition.x, relativePosition.z); + glm::quat faceCamera = glm::quat(glm::vec3(elevation, azimuth, 0)) * quat(vec3(0, 0, -1)); // this extra *quat(vec3(0,0,-1)) was required to get the quad to flip this seems like we could optimize + + qDebug() << "_drawAt3DPosition:" << _drawAt3DPosition; + qDebug() << "relativePosition:" << relativePosition; + qDebug() << "relativeDistance:" << relativeDistance; + + Transform transform; + transform.setTranslation(relativePosition); + transform.setScale(reticleScale); + transform.postScale(relativeDistance); // scale not quite working, distant things too large + transform.setRotation(faceCamera); + batch.setModelTransform(transform); + + /* + // this definitely doesn't work + mat4 pointerXfm = glm::scale(mat4(), vec3(relativeDistance)) * glm::mat4_cast(faceCamera) * glm::translate(mat4(), relativePosition); + batch.setModelTransform(pointerXfm); + */ + + } + else { + glm::mat4 overlayXfm; + _modelTransform.getMatrix(overlayXfm); + + auto reticlePosition = getReticlePosition(); + glm::vec2 projection = overlayToSpherical(reticlePosition); + float cursorDepth = getReticleDepth(); + mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + } geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); } }); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 0566f63944..1fb37c3085 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -90,6 +90,9 @@ public: Q_INVOKABLE glm::vec2 getReticlePosition(); Q_INVOKABLE void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); + Q_INVOKABLE void setReticleApparentPosition(glm::vec3 position) { _drawAt3D = true; _drawAt3DPosition = position; } + Q_INVOKABLE void restoreReticleApparentPosition() { _drawAt3D = false; } + Q_INVOKABLE glm::vec2 getReticleMaximumPosition() const; ReticleInterface* getReticleInterface() { return _reticleInterface; } @@ -140,6 +143,8 @@ private: bool _reticleVisible { true }; float _reticleDepth { 1.0f }; + bool _drawAt3D { false }; + glm::vec3 _drawAt3DPosition; // NOTE: when the compositor is running in HMD mode, it will control the reticle position as a custom // application specific position, when it's in desktop mode, the reticle position will simply move @@ -174,6 +179,10 @@ public: Q_INVOKABLE void setPosition(glm::vec2 position) { _compositor->setReticlePosition(position); } Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); } + + Q_INVOKABLE void setApparentPosition(glm::vec3 position) { _compositor->setReticleApparentPosition(position); } + Q_INVOKABLE void restoreApparentPosition() { _compositor->restoreReticleApparentPosition(); } + private: ApplicationCompositor* _compositor; }; From ea247cd796b51c8915301e01c866a1762a9a804d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 22 Feb 2016 14:08:00 +1300 Subject: [PATCH 035/114] Fix information, question, and warning OffscreenUI message box icons --- libraries/ui/src/OffscreenUi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index fa40fedb9b..d16f49f945 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -251,15 +251,15 @@ QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QS } QMessageBox::StandardButton OffscreenUi::information(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return DependencyManager::get()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton); + return DependencyManager::get()->messageBox(QMessageBox::Icon::Information, title, text, buttons, defaultButton); } QMessageBox::StandardButton OffscreenUi::question(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return DependencyManager::get()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton); + return DependencyManager::get()->messageBox(QMessageBox::Icon::Question, title, text, buttons, defaultButton); } QMessageBox::StandardButton OffscreenUi::warning(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return DependencyManager::get()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton); + return DependencyManager::get()->messageBox(QMessageBox::Icon::Warning, title, text, buttons, defaultButton); } From 26a46207c20ddec739828734878316887c17b050 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 22 Feb 2016 17:03:48 +1300 Subject: [PATCH 036/114] Set up QML tests for message box modal dialog restyling --- tests/ui/qml/main.qml | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index c610ab80ab..d5ef2584f5 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -81,17 +81,25 @@ ApplicationWindow { } */ Button { - text: "Show Long Error" + // Replicates message box that pops up after selecting new avatar. Includes title. + text: "Confirm Avatar" onClicked: { - desktop.messageBox({ - informativeText: "Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds ", - text: "Baloney", - icon: OriginalDialogs.StandardIcon.Warning, - detailedText: "sakjd;laskj dksa;dl jka;lsd j;lkjas ;dlkaj s;dlakjd ;alkjda; slkjda; lkjda;lksjd ;alksjd; alksjd ;alksjd; alksjd; alksdjas;ldkjas;lkdja ;kj ;lkasjd; lkj as;dlka jsd;lka jsd;laksjd a" + var messageBox = desktop.messageBox({ + title: "Set Avatar", + text: "Would you like to use 'Albert' for your avatar?", + icon: OriginalDialogs.StandardIcon.Question, + //icon: OriginalDialogs.StandardIcon.Information, // Test informaton icon + //icon: OriginalDialogs.StandardIcon.Warning, // Test warning icon + //icon: OriginalDialogs.StandardIcon.Critical, // Test critical icon + buttons: OriginalDialogs.StandardButton.Ok + OriginalDialogs.StandardButton.Cancel }); + messageBox.selected.connect(function(button) { + console.log("You clicked " + button) + }) } } Button { + // Message without title. text: "Show Error" onClicked: { var messageBox = desktop.messageBox({ @@ -103,6 +111,20 @@ ApplicationWindow { }) } } + Button { + // detailedText is not currently used anywhere in Interface but it is easier to leave in and style good enough. + text: "Show Long Error" + onClicked: { + desktop.messageBox({ + informativeText: "Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds ", + text: "Baloney", + icon: OriginalDialogs.StandardIcon.Warning, + detailedText: "sakjd;laskj dksa;dl jka;lsd j;lkjas ;dlkaj s;dlakjd ;alkjda; slkjda; lkjda;lksjd ;alksjd; alksjd ;alksjd; alksjd; alksdjas;ldkjas;lkdja ;kj ;lkasjd; lkj as;dlka jsd;lka jsd;laksjd a" + }); + } + } + /* + // There is no such desktop.queryBox() function; may need to update test to cover QueryDialog.qml? Button { text: "Show Query" onClicked: { @@ -120,6 +142,7 @@ ApplicationWindow { }) } } + */ Button { text: "Open Directory" property var builder: Component { From 72fb2ff102e10a14f4fe90c9119235b661a8e806 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 22 Feb 2016 17:05:57 +1300 Subject: [PATCH 037/114] Make copies of modal window files --- .../resources/qml/windows-uit/ModalFrame.qml | 41 +++++++++++++++++++ .../resources/qml/windows-uit/ModalWindow.qml | 22 ++++++++++ 2 files changed, 63 insertions(+) create mode 100644 interface/resources/qml/windows-uit/ModalFrame.qml create mode 100644 interface/resources/qml/windows-uit/ModalWindow.qml diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml new file mode 100644 index 0000000000..25f89a8baa --- /dev/null +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -0,0 +1,41 @@ +// +// ModalFrame.qml +// +// Created by Bradley Austin Davis on 15 Jan 2016 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "." +import "../controls" + +Frame { + id: frame + + Item { + anchors.fill: parent + + Rectangle { + id: background + anchors.fill: parent + anchors.margins: -4096 + visible: window.visible + color: "#7f7f7f7f"; + radius: 3; + } + + Text { + y: -implicitHeight - iconSize / 2 + text: window.title + elide: Text.ElideRight + font.bold: true + color: window.focus ? "white" : "gray" + style: Text.Outline; + styleColor: "black" + } + } +} diff --git a/interface/resources/qml/windows-uit/ModalWindow.qml b/interface/resources/qml/windows-uit/ModalWindow.qml new file mode 100644 index 0000000000..47da73281d --- /dev/null +++ b/interface/resources/qml/windows-uit/ModalWindow.qml @@ -0,0 +1,22 @@ +// +// ModalWindow.qml +// +// Created by Bradley Austin Davis on 22 Jan 2016 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "." + +Window { + id: root + anchors.centerIn: parent + modality: Qt.ApplicationModal + destroyOnCloseButton: true + destroyOnInvisible: true + frame: ModalFrame{} +} From 42734a0202ce53a09820b2381fcedacf9850af6c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 22 Feb 2016 21:16:00 +1300 Subject: [PATCH 038/114] Tidy desktop QML dialogs --- interface/resources/qml/desktop/Desktop.qml | 17 +++++++++++------ interface/resources/qml/desktop/FocusHack.qml | 13 ++++++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index c4ca0ab9a3..7570bf4dac 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -1,13 +1,21 @@ +// +// Desktop.qml +// +// Created by Bradley Austin Davis on 15 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 as OriginalDialogs; import "../dialogs" import "../menus" import "../js/Utils.js" as Utils -// This is our primary 'desktop' object to which all VR dialogs and -// windows will be childed. +// This is our primary 'desktop' object to which all VR dialogs and windows are childed. FocusScope { id: desktop anchors.fill: parent; @@ -316,6 +324,3 @@ FocusScope { } } - - - diff --git a/interface/resources/qml/desktop/FocusHack.qml b/interface/resources/qml/desktop/FocusHack.qml index 7514705983..e62319b5a7 100644 --- a/interface/resources/qml/desktop/FocusHack.qml +++ b/interface/resources/qml/desktop/FocusHack.qml @@ -1,3 +1,13 @@ +// +// FocusHack.qml +// +// Created by Bradley Austin Davis on 21 Jan 2015 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 FocusScope { @@ -21,6 +31,3 @@ FocusScope { focusTimer.running = true; } } - - - From 3f03678d028fb0c660047f4f9e700ddc6514bfc9 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 22 Feb 2016 09:27:27 -0800 Subject: [PATCH 039/114] add version of edit that sets reticle depth --- examples/editWithHacks.js | 1910 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1910 insertions(+) create mode 100644 examples/editWithHacks.js diff --git a/examples/editWithHacks.js b/examples/editWithHacks.js new file mode 100644 index 0000000000..3504cddb96 --- /dev/null +++ b/examples/editWithHacks.js @@ -0,0 +1,1910 @@ +// newEditEntities.js +// examples +// +// Created by Brad Hefta-Gaub on 10/2/14. +// Persist toolbar by HRS 6/11/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + +Script.include([ + "libraries/stringHelpers.js", + "libraries/dataViewHelpers.js", + "libraries/toolBars.js", + "libraries/progressDialog.js", + + "libraries/entitySelectionTool.js", + + "libraries/ToolTip.js", + + "libraries/entityCameraTool.js", + "libraries/gridTool.js", + "libraries/entityList.js", + "libraries/lightOverlayManager.js", +]); + +var selectionDisplay = SelectionDisplay; +var selectionManager = SelectionManager; + +var lightOverlayManager = new LightOverlayManager(); + +var cameraManager = new CameraManager(); + +var grid = Grid(); +// gridTool = GridTool({ +// horizontalGrid: grid +// }); +// gridTool.setVisible(false); + +var entityListTool = EntityListTool(); + +selectionManager.addEventListener(function() { + selectionDisplay.updateHandles(); + lightOverlayManager.updatePositions(); +}); + +var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; +var toolHeight = 50; +var toolWidth = 50; + +var DEGREES_TO_RADIANS = Math.PI / 180.0; +var RADIANS_TO_DEGREES = 180.0 / Math.PI; +var epsilon = 0.001; + +var MIN_ANGULAR_SIZE = 2; +var MAX_ANGULAR_SIZE = 45; +var allowLargeModels = true; +var allowSmallModels = true; +var wantEntityGlow = false; + +var SPAWN_DISTANCE = 1; +var DEFAULT_DIMENSION = 0.20; +var DEFAULT_TEXT_DIMENSION_X = 1.0; +var DEFAULT_TEXT_DIMENSION_Y = 1.0; +var DEFAULT_TEXT_DIMENSION_Z = 0.01; + +var DEFAULT_DIMENSIONS = { + x: DEFAULT_DIMENSION, + y: DEFAULT_DIMENSION, + z: DEFAULT_DIMENSION +}; + +var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); + +var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; +var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; +var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode"; +var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Edit Mode"; + +var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; +var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; +var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; +var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode"; +var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; + +var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain." +var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain." + +var modelURLs = [ + "Insert the URL to your FBX" +]; + +var mode = 0; +var isActive = false; + +var placingEntityID = null; + +IMPORTING_SVO_OVERLAY_WIDTH = 144; +IMPORTING_SVO_OVERLAY_HEIGHT = 30; +IMPORTING_SVO_OVERLAY_MARGIN = 5; +IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; +var importingSVOImageOverlay = Overlays.addOverlay("image", { + imageURL: HIFI_PUBLIC_BUCKET + "images/hourglass.svg", + width: 20, + height: 20, + alpha: 1.0, + color: { + red: 255, + green: 255, + blue: 255 + }, + x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, + y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, + visible: false, +}); +var importingSVOTextOverlay = Overlays.addOverlay("text", { + font: { + size: 14 + }, + text: "Importing SVO...", + leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN, + x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN, + y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN, + width: IMPORTING_SVO_OVERLAY_WIDTH, + height: IMPORTING_SVO_OVERLAY_HEIGHT, + backgroundColor: { + red: 80, + green: 80, + blue: 80 + }, + backgroundAlpha: 0.7, + visible: false, +}); + +var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; +var marketplaceWindow = new OverlayWebWindow({ + title: 'Marketplace', + source: "about:blank", + width: 900, + height: 700, + visible: false +}); + +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + print("setting marketplace URL to " + url); + marketplaceWindow.setURL(url); + marketplaceWindow.setVisible(true); + marketplaceWindow.raise(); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); + marketplaceWindow.setURL("about:blank"); +} + +function toggleMarketplace() { + if (marketplaceWindow.visible) { + hideMarketplace(); + } else { + showMarketplace(); + } +} + +var toolBar = (function() { + var that = {}, + toolBar, + activeButton, + newModelButton, + newCubeButton, + newSphereButton, + newLightButton, + newTextButton, + newWebButton, + newZoneButton, + newPolyVoxButton; + + function initialize() { + toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) { + return { + x: windowDimensions.x - 8 - toolbar.width, + y: (windowDimensions.y - toolbar.height) / 2 + }; + }); + + + + activeButton = toolBar.addTool({ + imageURL: toolIconUrl + "edit-status.svg", + subImage: { + x: 0, + y: Tool.IMAGE_WIDTH, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: true + }, true, false); + + newModelButton = toolBar.addTool({ + imageURL: toolIconUrl + "upload.svg", + subImage: { + x: 0, + y: Tool.IMAGE_WIDTH, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newCubeButton = toolBar.addTool({ + imageURL: toolIconUrl + "add-cube.svg", + subImage: { + x: 0, + y: Tool.IMAGE_WIDTH, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newSphereButton = toolBar.addTool({ + imageURL: toolIconUrl + "add-sphere.svg", + subImage: { + x: 0, + y: Tool.IMAGE_WIDTH, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newLightButton = toolBar.addTool({ + imageURL: toolIconUrl + "light.svg", + subImage: { + x: 0, + y: Tool.IMAGE_WIDTH, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newTextButton = toolBar.addTool({ + imageURL: toolIconUrl + "add-text.svg", + subImage: { + x: 0, + y: Tool.IMAGE_WIDTH, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newWebButton = toolBar.addTool({ + imageURL: "https://hifi-public.s3.amazonaws.com/images/www.svg", + subImage: { + x: 0, + y: 0, + width: 128, + height: 128 + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newZoneButton = toolBar.addTool({ + imageURL: toolIconUrl + "zonecube_text.svg", + subImage: { + x: 0, + y: 128, + width: 128, + height: 128 + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + newPolyVoxButton = toolBar.addTool({ + imageURL: toolIconUrl + "polyvox.svg", + subImage: { + x: 0, + y: 0, + width: 256, + height: 256 + }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); + + that.setActive(false); + } + + that.clearEntityList = function() { + entityListTool.clearEntityList(); + }; + + that.setActive = function(active) { + if (active != isActive) { + if (active && !Entities.canAdjustLocks()) { + Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG); + } else { + isActive = active; + if (!isActive) { + entityListTool.setVisible(false); + // gridTool.setVisible(false); + grid.setEnabled(false); + propertiesTool.setVisible(false); + selectionManager.clearSelections(); + cameraManager.disable(); + } else { + hasShownPropertiesTool = false; + entityListTool.setVisible(true); + // gridTool.setVisible(true); + grid.setEnabled(true); + propertiesTool.setVisible(true); + Window.setFocus(); + } + that.showTools(isActive); + } + } + toolBar.selectTool(activeButton, isActive); + lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + }; + + // Sets visibility of tool buttons, excluding the power button + that.showTools = function(doShow) { + toolBar.showTool(newModelButton, doShow); + toolBar.showTool(newCubeButton, doShow); + toolBar.showTool(newSphereButton, doShow); + toolBar.showTool(newLightButton, doShow); + toolBar.showTool(newTextButton, doShow); + toolBar.showTool(newWebButton, doShow); + toolBar.showTool(newZoneButton, doShow); + toolBar.showTool(newPolyVoxButton, doShow); + }; + + var RESIZE_INTERVAL = 50; + var RESIZE_TIMEOUT = 120000; // 2 minutes + var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; + + function addModel(url) { + var entityID = createNewEntity({ + type: "Model", + modelURL: url + }, false); + + if (entityID) { + print("Model added: " + url); + selectionManager.setSelections([entityID]); + } + } + + function createNewEntity(properties, dragOnCreate) { + // Default to true if not passed in + dragOnCreate = dragOnCreate == undefined ? true : dragOnCreate; + + var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS; + var position = getPositionToCreateEntity(); + var entityID = null; + if (position != null) { + position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions), + properties.position = position; + + entityID = Entities.addEntity(properties); + if (dragOnCreate) { + placingEntityID = entityID; + } + } else { + Window.alert("Can't create " + properties.type + ": " + properties.type + " would be out of bounds."); + } + + return entityID; + } + + var newModelButtonDown = false; + that.mousePressEvent = function(event) { + var clickedOverlay, + url, + file; + + if (!event.isLeftButton) { + // if another mouse button than left is pressed ignore it + return false; + } + + clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + if (activeButton === toolBar.clicked(clickedOverlay)) { + that.setActive(!isActive); + return true; + } + + // Handle these two buttons in the mouseRelease event handler so that we don't suppress a mouseRelease event from + // occurring when showing a modal dialog. + if (newModelButton === toolBar.clicked(clickedOverlay)) { + newModelButtonDown = true; + return true; + } + + + if (newCubeButton === toolBar.clicked(clickedOverlay)) { + createNewEntity({ + type: "Box", + dimensions: DEFAULT_DIMENSIONS, + color: { + red: 255, + green: 0, + blue: 0 + } + }); + + return true; + } + + if (newSphereButton === toolBar.clicked(clickedOverlay)) { + createNewEntity({ + type: "Sphere", + dimensions: DEFAULT_DIMENSIONS, + color: { + red: 255, + green: 0, + blue: 0 + } + }); + + return true; + } + + if (newLightButton === toolBar.clicked(clickedOverlay)) { + createNewEntity({ + type: "Light", + dimensions: DEFAULT_LIGHT_DIMENSIONS, + isSpotlight: false, + color: { + red: 150, + green: 150, + blue: 150 + }, + + constantAttenuation: 1, + linearAttenuation: 0, + quadraticAttenuation: 0, + exponent: 0, + cutoff: 180, // in degrees + }); + + return true; + } + + if (newTextButton === toolBar.clicked(clickedOverlay)) { + createNewEntity({ + type: "Text", + dimensions: { + x: 0.65, + y: 0.3, + z: 0.01 + }, + backgroundColor: { + red: 64, + green: 64, + blue: 64 + }, + textColor: { + red: 255, + green: 255, + blue: 255 + }, + text: "some text", + lineHeight: 0.06 + }); + + return true; + } + + if (newWebButton === toolBar.clicked(clickedOverlay)) { + createNewEntity({ + type: "Web", + dimensions: { + x: 1.6, + y: 0.9, + z: 0.01 + }, + sourceUrl: "https://highfidelity.com/", + }); + + return true; + } + + if (newZoneButton === toolBar.clicked(clickedOverlay)) { + createNewEntity({ + type: "Zone", + dimensions: { + x: 10, + y: 10, + z: 10 + }, + }); + + return true; + } + + if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) { + var polyVoxId = createNewEntity({ + type: "PolyVox", + dimensions: { + x: 10, + y: 10, + z: 10 + }, + voxelVolumeSize: { + x: 16, + y: 16, + z: 16 + }, + voxelSurfaceStyle: 2 + }); + for (var x = 1; x <= 14; x++) { + Entities.setVoxel(polyVoxId, { + x: x, + y: 1, + z: 1 + }, 255); + Entities.setVoxel(polyVoxId, { + x: x, + y: 14, + z: 1 + }, 255); + Entities.setVoxel(polyVoxId, { + x: x, + y: 1, + z: 14 + }, 255); + Entities.setVoxel(polyVoxId, { + x: x, + y: 14, + z: 14 + }, 255); + } + for (var y = 2; y <= 13; y++) { + Entities.setVoxel(polyVoxId, { + x: 1, + y: y, + z: 1 + }, 255); + Entities.setVoxel(polyVoxId, { + x: 14, + y: y, + z: 1 + }, 255); + Entities.setVoxel(polyVoxId, { + x: 1, + y: y, + z: 14 + }, 255); + Entities.setVoxel(polyVoxId, { + x: 14, + y: y, + z: 14 + }, 255); + } + for (var z = 2; z <= 13; z++) { + Entities.setVoxel(polyVoxId, { + x: 1, + y: 1, + z: z + }, 255); + Entities.setVoxel(polyVoxId, { + x: 14, + y: 1, + z: z + }, 255); + Entities.setVoxel(polyVoxId, { + x: 1, + y: 14, + z: z + }, 255); + Entities.setVoxel(polyVoxId, { + x: 14, + y: 14, + z: z + }, 255); + } + + + return true; + } + + return false; + }; + + that.mouseReleaseEvent = function(event) { + var handled = false; + if (newModelButtonDown) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (newModelButton === toolBar.clicked(clickedOverlay)) { + url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]); + if (url !== null && url !== "") { + addModel(url); + } + handled = true; + } + } + + newModelButtonDown = false; + + + return handled; + } + + Window.domainChanged.connect(function() { + that.setActive(false); + that.clearEntityList(); + }); + + Entities.canAdjustLocksChanged.connect(function(canAdjustLocks) { + if (isActive && !canAdjustLocks) { + that.setActive(false); + } + }); + + that.cleanup = function() { + toolBar.cleanup(); + }; + + initialize(); + return that; +}()); + + +function isLocked(properties) { + // special case to lock the ground plane model in hq. + if (location.hostname == "hq.highfidelity.io" && + properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { + return true; + } + return false; +} + + +var selectedEntityID; +var orientation; +var intersection; + + +var SCALE_FACTOR = 200.0; + +function rayPlaneIntersection(pickRay, point, normal) { + var d = -Vec3.dot(point, normal); + var t = -(Vec3.dot(pickRay.origin, normal) + d) / Vec3.dot(pickRay.direction, normal); + + return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); +} + +function findClickedEntity(event) { + var pickZones = event.isControl; + + if (pickZones) { + Entities.setZonesArePickable(true); + } + + var pickRay = Camera.computePickRay(event.x, event.y); + + var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking + var lightResult = lightOverlayManager.findRayIntersection(pickRay); + lightResult.accurate = true; + + if (pickZones) { + Entities.setZonesArePickable(false); + } + + var result; + + if (!entityResult.intersects && !lightResult.intersects) { + return null; + } else if (entityResult.intersects && !lightResult.intersects) { + result = entityResult; + } else if (!entityResult.intersects && lightResult.intersects) { + result = lightResult; + } else { + if (entityResult.distance < lightResult.distance) { + result = entityResult; + } else { + result = lightResult; + } + } + + if (!result.accurate) { + return null; + } + + var foundEntity = result.entityID; + return { + pickRay: pickRay, + entityID: foundEntity + }; +} + +var mouseHasMovedSincePress = false; +var mousePressStartTime = 0; +var mousePressStartPosition = { + x: 0, + y: 0 +}; +var mouseDown = false; + +function mousePressEvent(event) { + mouseDown = true; + mousePressStartPosition = { + x: event.x, + y: event.y + }; + mousePressStartTime = Date.now(); + mouseHasMovedSincePress = false; + mouseCapturedByTool = false; + + if (propertyMenu.mousePressEvent(event) || toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { + mouseCapturedByTool = true; + return; + } + if (isActive) { + if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { + // Event handled; do nothing. + return; + } + } +} + +var highlightedEntityID = null; +var mouseCapturedByTool = false; +var lastMousePosition = null; +var idleMouseTimerId = null; +var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms +var CLICK_MOVE_DISTANCE_THRESHOLD = 8; +var IDLE_MOUSE_TIMEOUT = 200; +var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0; + +var lastMouseMoveEvent = null; + +function mouseMoveEventBuffered(event) { + lastMouseMoveEvent = event; +} + + + +function mouseMove(event) { + if (mouseDown && !mouseHasMovedSincePress) { + var timeSincePressMicro = Date.now() - mousePressStartTime; + + var dX = mousePressStartPosition.x - event.x; + var dY = mousePressStartPosition.y - event.y; + var sqDist = (dX * dX) + (dY * dY); + + // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved + // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move + // yet. The goal is to provide mouse clicks that are more lenient to small movements. + if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) { + return; + } + mouseHasMovedSincePress = true; + } + + if (placingEntityID) { + var pickRay = Camera.computePickRay(event.x, event.y); + var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE; + var offset = Vec3.multiply(distance, pickRay.direction); + var position = Vec3.sum(Camera.position, offset); + Entities.editEntity(placingEntityID, { + position: position, + }); + return; + } + if (!isActive) { + return; + } + if (idleMouseTimerId) { + Script.clearTimeout(idleMouseTimerId); + } + + // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing + if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { + return; + } + + lastMousePosition = { + x: event.x, + y: event.y + }; + + idleMouseTimerId = Script.setTimeout(handleIdleMouse, IDLE_MOUSE_TIMEOUT); + + + // brad's hack to move an overlay to the mouse + //Overlays.editOverlay(pointerOverlay, { position: lookAt3D }); + /* + var pickRay = Camera.computePickRay(event.x, event.y); + var result = Overlays.findRayIntersection(pickRay); + print(JSON.stringify(result)); + if (result.intersects) { + Overlays.editOverlay(pointerOverlay, { position: result.intersection }); + Reticle.setVisible(false); + print("intersects..."); + } else { + var lookAt3D = HMD.getHUDLookAtPosition3D(); + Overlays.editOverlay(pointerOverlay, { position: { x: 0, y: 0, z: 0 } }); + Reticle.setVisible(true); + print("NO INTERSECTION..."); + } + */ +} + +function handleIdleMouse() { + idleMouseTimerId = null; +} + +function highlightEntityUnderCursor(position, accurateRay) { + var pickRay = Camera.computePickRay(position.x, position.y); + var entityIntersection = Entities.findRayIntersection(pickRay, accurateRay); + if (entityIntersection.accurate) { + if (highlightedEntityID && highlightedEntityID != entityIntersection.entityID) { + selectionDisplay.unhighlightSelectable(highlightedEntityID); + highlightedEntityID = { + id: -1 + }; + } + + var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), + entityIntersection.properties.position)) * 180 / 3.14; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (entityIntersection.entityID && sizeOK) { + if (wantEntityGlow) { + Entities.editEntity(entityIntersection.entityID, { + glowLevel: 0.25 + }); + } + highlightedEntityID = entityIntersection.entityID; + selectionDisplay.highlightSelectable(entityIntersection.entityID); + } + + } +} + + +function mouseReleaseEvent(event) { + mouseDown = false; + + if (lastMouseMoveEvent) { + mouseMove(lastMouseMoveEvent); + lastMouseMoveEvent = null; + } + if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) { + + return true; + } + if (placingEntityID) { + + if (isActive) { + + selectionManager.setSelections([placingEntityID]); + } + placingEntityID = null; + } + if (isActive && selectionManager.hasSelection()) { + + tooltip.show(false); + } + if (mouseCapturedByTool) { + + return; + } + + cameraManager.mouseReleaseEvent(event); + + if (!mouseHasMovedSincePress) { + mouseClickEvent(event); + } +} + +function mouseClickEvent(event) { + if (isActive && event.isLeftButton) { + var result = findClickedEntity(event); + if (result === null) { + if (!event.isShifted) { + selectionManager.clearSelections(); + } + return; + } + toolBar.setActive(true); + var pickRay = result.pickRay; + var foundEntity = result.entityID; + + var properties = Entities.getEntityProperties(foundEntity); + if (isLocked(properties)) { + print("Model locked " + properties.id); + } else { + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal); + // P P - Model + // /| A - Palm + // / | d B - unit vector toward tip + // / | X - base of the perpendicular line + // A---X----->B d - distance fom axis + // x x - distance from A + // + // |X-A| = (P-A).B + // X == A + ((P-A).B)B + // d = |P-X| + + var A = pickRay.origin; + var B = Vec3.normalize(pickRay.direction); + var P = properties.position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (0 < x && sizeOK) { + entitySelected = true; + selectedEntityID = foundEntity; + orientation = MyAvatar.orientation; + intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); + + + if (!event.isShifted) { + selectionManager.setSelections([foundEntity]); + } else { + selectionManager.addEntity(foundEntity, true); + } + + print("Model selected: " + foundEntity); + selectionDisplay.select(selectedEntityID, event); + + if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { + cameraManager.enable(); + cameraManager.focus(selectionManager.worldPosition, + selectionManager.worldDimensions, + Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + } + } + } + } else if (event.isRightButton) { + var result = findClickedEntity(event); + if (result) { + var properties = Entities.getEntityProperties(result.entityID); + if (properties.marketplaceID) { + propertyMenu.marketplaceID = properties.marketplaceID; + propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); + } else { + propertyMenu.marketplaceID = null; + propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info"); + } + propertyMenu.setPosition(event.x, event.y); + propertyMenu.show(); + } else { + propertyMenu.hide(); + } + } +} + +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + + +// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already +// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that +// added it. +var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); + +function setupModelMenus() { + print("setupModelMenus()"); + // adj our menuitems + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Entities", + isSeparator: true, + grouping: "Advanced" + }); + if (!Menu.menuItemExists("Edit", "Delete")) { + print("no delete... adding ours"); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Delete", + shortcutKeyEvent: { + text: "backspace" + }, + afterItem: "Entities", + grouping: "Advanced" + }); + modelMenuAddedDelete = true; + } else { + print("delete exists... don't add ours"); + } + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Entity List...", + shortcutKey: "CTRL+META+L", + afterItem: "Entities", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Allow Selecting of Large Models", + shortcutKey: "CTRL+META+L", + afterItem: "Entity List...", + isCheckable: true, + isChecked: true, + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Allow Selecting of Small Models", + shortcutKey: "CTRL+META+S", + afterItem: "Allow Selecting of Large Models", + isCheckable: true, + isChecked: true, + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Allow Selecting of Lights", + shortcutKey: "CTRL+SHIFT+META+L", + afterItem: "Allow Selecting of Small Models", + isCheckable: true, + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Select All Entities In Box", + shortcutKey: "CTRL+SHIFT+META+A", + afterItem: "Allow Selecting of Lights", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Select All Entities Touching Box", + shortcutKey: "CTRL+SHIFT+META+T", + afterItem: "Select All Entities In Box", + grouping: "Advanced" + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Export Entities", + shortcutKey: "CTRL+META+E", + afterItem: "Entities", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Import Entities", + shortcutKey: "CTRL+META+I", + afterItem: "Export Entities", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Import Entities from URL", + shortcutKey: "CTRL+META+U", + afterItem: "Import Entities", + grouping: "Advanced" + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_AUTO_FOCUS_ON_SELECT, + isCheckable: true, + isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_EASE_ON_FOCUS, + afterItem: MENU_AUTO_FOCUS_ON_SELECT, + isCheckable: true, + isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, + afterItem: MENU_EASE_ON_FOCUS, + isCheckable: true, + isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true", + grouping: "Advanced" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, + afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, + isCheckable: true, + isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true", + grouping: "Advanced" + }); + + Entities.setLightsArePickable(false); +} + +setupModelMenus(); // do this when first running our script. + +function cleanupModelMenus() { + Menu.removeSeparator("Edit", "Entities"); + if (modelMenuAddedDelete) { + // delete our menuitems + Menu.removeMenuItem("Edit", "Delete"); + } + + Menu.removeMenuItem("Edit", "Entity List..."); + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); + Menu.removeMenuItem("Edit", "Select All Entities In Box"); + Menu.removeMenuItem("Edit", "Select All Entities Touching Box"); + + Menu.removeMenuItem("Edit", "Export Entities"); + Menu.removeMenuItem("Edit", "Import Entities"); + Menu.removeMenuItem("Edit", "Import Entities from URL"); + + Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); + Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); + Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_IN_EDIT_MODE); + Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); +} + +Script.scriptEnding.connect(function() { + Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); + Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + Settings.setValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + + progressDialog.cleanup(); + toolBar.cleanup(); + cleanupModelMenus(); + tooltip.cleanup(); + selectionDisplay.cleanup(); + Entities.setLightsArePickable(originalLightsArePickable); + + Overlays.deleteOverlay(importingSVOImageOverlay); + Overlays.deleteOverlay(importingSVOTextOverlay); +}); + +var intersectionBeaconPosition = { x: 0, y: 0, z: 0 }; +var intersectionBeaconSize = 0.03; +var intersectionBeacon = Overlays.addOverlay("sphere", { + position: intersectionBeaconPosition, + size: intersectionBeaconSize, + color: { red: 255, green: 0, blue: 0}, + alpha: 1, + solid: true, + ignoreRayIntersection: true, // this never ray intersects + }); + +Script.scriptEnding.connect(function(){ + Overlays.deleteOverlay(intersectionBeacon); +}); + + +var lastOrientation = null; +var lastPosition = null; +var lastDepthCheckTime = 0; + +// Do some stuff regularly, like check for placement of various overlays +Script.update.connect(function(deltaTime) { + progressDialog.move(); + selectionDisplay.checkMove(); + var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); + var dPosition = Vec3.distance(Camera.position, lastPosition); + if (dOrientation > 0.001 || dPosition > 0.001) { + propertyMenu.hide(); + lastOrientation = Camera.orientation; + lastPosition = Camera.position; + } + if (lastMouseMoveEvent) { + mouseMove(lastMouseMoveEvent); + var TIME_BETWEEN_DEPTH_CHECKS = 100; + var timeSinceLastDepthCheck = Date.now() - lastDepthCheckTime; + if (timeSinceLastDepthCheck > TIME_BETWEEN_DEPTH_CHECKS) { + var pickRay = Camera.computePickRay(lastMouseMoveEvent.x, lastMouseMoveEvent.y); + var result = Overlays.findRayIntersection(pickRay); + + if (!result.intersects) { + result = Entities.findRayIntersection(pickRay, true); + } + if (result.intersects) { + // + JSON.stringify(result) + print("something hovered!! result.distance:" +result.distance); + Vec3.print("something hovered!! result.intersection:", result.intersection); + //Reticle.setDepth(result.distance); + Reticle.setApparentPosition(result.intersection); + Overlays.editOverlay(intersectionBeacon, { position: result.intersection, visible: false }); + + } else { + //Reticle.setDepth(1.0); + Reticle.restoreApparentPosition(); + print("NO INTERSECTION..."); + var pointAt2D = Reticle.position; + var pointAt3D = HMD.worldPointFromOverlay(pointAt2D); + Overlays.editOverlay(intersectionBeacon, { position: pointAt3D, visible: false }); + } + + } + lastMouseMoveEvent = null; + } +}); + +function insideBox(center, dimensions, point) { + return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); +} + +function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { + if (selectionManager.hasSelection()) { + // Get all entities touching the bounding box of the current selection + var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition, + Vec3.multiply(selectionManager.worldDimensions, 0.5)); + var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions); + + if (!keepIfTouching) { + var isValid; + if (selectionManager.localPosition === null) { + isValid = function(position) { + return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); + } + } else { + isValid = function(position) { + var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), + Vec3.subtract(position, + selectionManager.localPosition)); + return insideBox({ + x: 0, + y: 0, + z: 0 + }, selectionManager.localDimensions, localPosition); + } + } + for (var i = 0; i < entities.length; ++i) { + var properties = Entities.getEntityProperties(entities[i]); + if (!isValid(properties.position)) { + entities.splice(i, 1); + --i; + } + } + } + selectionManager.setSelections(entities); + } +} + +function deleteSelectedEntities() { + if (SelectionManager.hasSelection()) { + print(" Delete Entities"); + SelectionManager.saveProperties(); + var savedProperties = []; + for (var i = 0; i < selectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID]; + SelectionManager.savedProperties[entityID]; + savedProperties.push({ + entityID: entityID, + properties: initialProperties + }); + Entities.deleteEntity(entityID); + } + SelectionManager.clearSelections(); + pushCommandForSelections([], savedProperties); + } else { + print(" Delete Entity.... not holding..."); + } +} + +function handeMenuEvent(menuItem) { + if (menuItem == "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem == "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem == "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); + } else if (menuItem == "Delete") { + deleteSelectedEntities(); + } else if (menuItem == "Export Entities") { + if (!selectionManager.hasSelection()) { + Window.alert("No entities have been selected."); + } else { + var filename = "entities__" + Window.location.hostname + ".svo.json"; + filename = Window.save("Select where to save", filename, "*.json") + if (filename) { + var success = Clipboard.exportEntities(filename, selectionManager.selections); + if (!success) { + Window.alert("Export failed."); + } + } + } + } else if (menuItem == "Import Entities" || menuItem == "Import Entities from URL") { + + var importURL = null; + if (menuItem == "Import Entities") { + var fullPath = Window.browse("Select models to import", "", "*.json"); + if (fullPath) { + importURL = "file:///" + fullPath; + } + } else { + importURL = Window.prompt("URL of SVO to import", ""); + } + + if (importURL) { + importSVO(importURL); + } + } else if (menuItem == "Entity List...") { + entityListTool.toggleVisible(); + } else if (menuItem == "Select All Entities In Box") { + selectAllEtitiesInCurrentSelectionBox(false); + } else if (menuItem == "Select All Entities Touching Box") { + selectAllEtitiesInCurrentSelectionBox(true); + } else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) { + lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + } else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) { + Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + } + tooltip.show(false); +} + +// This function tries to find a reasonable position to place a new entity based on the camera +// position. If a reasonable position within the world bounds can't be found, `null` will +// be returned. The returned position will also take into account grid snapping settings. +function getPositionToCreateEntity() { + var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE; + var direction = Quat.getFront(Camera.orientation); + var offset = Vec3.multiply(distance, direction); + var placementPosition = Vec3.sum(Camera.position, offset); + + var cameraPosition = Camera.position; + + var HALF_TREE_SCALE = 16384; + + var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE; + var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE; + + if (cameraOutOfBounds && placementOutOfBounds) { + return null; + } + + placementPosition.x = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.x)); + placementPosition.y = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.y)); + placementPosition.z = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.z)); + + return placementPosition; +} + +function importSVO(importURL) { + print("Import URL requested: " + importURL) + if (!Entities.canAdjustLocks()) { + Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); + return; + } + + Overlays.editOverlay(importingSVOTextOverlay, { + visible: true + }); + Overlays.editOverlay(importingSVOImageOverlay, { + visible: true + }); + + var success = Clipboard.importEntities(importURL); + + if (success) { + var VERY_LARGE = 10000; + var position = { + x: 0, + y: 0, + z: 0 + }; + if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { + position = getPositionToCreateEntity(); + } + if (position != null) { + var pastedEntityIDs = Clipboard.pasteEntities(position); + + if (isActive) { + selectionManager.setSelections(pastedEntityIDs); + } + + Window.raiseMainWindow(); + } else { + Window.alert("Can't import objects: objects would be out of bounds."); + } + } else { + Window.alert("There was an error importing the entity file."); + } + + Overlays.editOverlay(importingSVOTextOverlay, { + visible: false + }); + Overlays.editOverlay(importingSVOImageOverlay, { + visible: false + }); +} +Window.svoImportRequested.connect(importSVO); + +Menu.menuItemEvent.connect(handeMenuEvent); + +Controller.keyPressEvent.connect(function(event) { + if (isActive) { + cameraManager.keyPressEvent(event); + } +}); + +Controller.keyReleaseEvent.connect(function(event) { + if (isActive) { + cameraManager.keyReleaseEvent(event); + } + // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items + if (event.text == "BACKSPACE" || event.text == "DELETE") { + deleteSelectedEntities(); + } else if (event.text == "ESC") { + selectionManager.clearSelections(); + } else if (event.text == "TAB") { + selectionDisplay.toggleSpaceMode(); + } else if (event.text == "f") { + if (isActive) { + if (selectionManager.hasSelection()) { + cameraManager.enable(); + cameraManager.focus(selectionManager.worldPosition, + selectionManager.worldDimensions, + Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + } + } + } else if (event.text == '[') { + if (isActive) { + cameraManager.enable(); + } + } else if (event.text == 'g') { + if (isActive && selectionManager.hasSelection()) { + var newPosition = selectionManager.worldPosition; + newPosition = Vec3.subtract(newPosition, { + x: 0, + y: selectionManager.worldDimensions.y * 0.5, + z: 0 + }); + grid.setPosition(newPosition); + } + } +}); + +// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently +// possible to create an entity with a specific id, earlier undo commands to the deleted entity +// will fail if there isn't a way to find the new entity id. +DELETED_ENTITY_MAP = {} + +function applyEntityProperties(data) { + var properties = data.setProperties; + var selectedEntityIDs = []; + for (var i = 0; i < properties.length; i++) { + var entityID = properties[i].entityID; + if (DELETED_ENTITY_MAP[entityID] !== undefined) { + entityID = DELETED_ENTITY_MAP[entityID]; + } + Entities.editEntity(entityID, properties[i].properties); + selectedEntityIDs.push(entityID); + } + for (var i = 0; i < data.createEntities.length; i++) { + var entityID = data.createEntities[i].entityID; + var properties = data.createEntities[i].properties; + var newEntityID = Entities.addEntity(properties); + DELETED_ENTITY_MAP[entityID] = newEntityID; + if (data.selectCreated) { + selectedEntityIDs.push(newEntityID); + } + } + for (var i = 0; i < data.deleteEntities.length; i++) { + var entityID = data.deleteEntities[i].entityID; + if (DELETED_ENTITY_MAP[entityID] !== undefined) { + entityID = DELETED_ENTITY_MAP[entityID]; + } + Entities.deleteEntity(entityID); + } + + selectionManager.setSelections(selectedEntityIDs); +}; + +// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the +// redo command, and the saved properties for the undo command. Also, include create and delete entity data. +function pushCommandForSelections(createdEntityData, deletedEntityData) { + var undoData = { + setProperties: [], + createEntities: deletedEntityData || [], + deleteEntities: createdEntityData || [], + selectCreated: true, + }; + var redoData = { + setProperties: [], + createEntities: createdEntityData || [], + deleteEntities: deletedEntityData || [], + selectCreated: false, + }; + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID]; + var currentProperties = Entities.getEntityProperties(entityID); + undoData.setProperties.push({ + entityID: entityID, + properties: { + position: initialProperties.position, + rotation: initialProperties.rotation, + dimensions: initialProperties.dimensions, + }, + }); + redoData.setProperties.push({ + entityID: entityID, + properties: { + position: currentProperties.position, + rotation: currentProperties.rotation, + dimensions: currentProperties.dimensions, + }, + }); + } + UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); +} + +PropertiesTool = function(opts) { + var that = {}; + + var url = Script.resolvePath('html/entityProperties.html'); + var webView = new OverlayWebWindow({ + title: 'Entity Properties', + source: url, + toolWindow: true + }); + + var visible = false; + + webView.setVisible(visible); + + that.setVisible = function(newVisible) { + visible = newVisible; + webView.setVisible(visible); + }; + + selectionManager.addEventListener(function() { + data = { + type: 'update', + }; + var selections = []; + for (var i = 0; i < selectionManager.selections.length; i++) { + var entity = {}; + entity.id = selectionManager.selections[i]; + entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); + if (entity.properties.rotation !== undefined) { + entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); + } + if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { + entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES, Vec3.toPolar(entity.properties.keyLight.direction)); + entity.properties.keyLight.direction.z = 0.0; + } + selections.push(entity); + } + data.selections = selections; + webView.eventBridge.emitScriptEvent(JSON.stringify(data)); + }); + + webView.eventBridge.webEventReceived.connect(function(data) { + data = JSON.parse(data); + if (data.type == "print") { + if (data.message) { + print(data.message); + } + } else if (data.type == "update") { + selectionManager.saveProperties(); + if (selectionManager.selections.length > 1) { + properties = { + locked: data.properties.locked, + visible: data.properties.visible, + }; + for (var i = 0; i < selectionManager.selections.length; i++) { + Entities.editEntity(selectionManager.selections[i], properties); + } + } else { + if (data.properties.dynamic === false) { + // this object is leaving dynamic, so we zero its velocities + data.properties["velocity"] = {x: 0, y: 0, z: 0}; + data.properties["angularVelocity"] = {x: 0, y: 0, z: 0}; + } + if (data.properties.rotation !== undefined) { + var rotation = data.properties.rotation; + data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); + } + if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) { + data.properties.keyLight.direction = Vec3.fromPolar( + data.properties.keyLight.direction.x * DEGREES_TO_RADIANS, data.properties.keyLight.direction.y * DEGREES_TO_RADIANS); + } + Entities.editEntity(selectionManager.selections[0], data.properties); + if (data.properties.name != undefined) { + entityListTool.sendUpdate(); + } + } + pushCommandForSelections(); + selectionManager._update(); + } else if (data.type == "showMarketplace") { + showMarketplace(); + } else if (data.type == "action") { + if (data.action == "moveSelectionToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); + var diff = { + x: 0, + y: dY, + z: 0 + }; + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "moveAllToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; + var dY = grid.getOrigin().y - bottomY; + var diff = { + x: 0, + y: dY, + z: 0 + }; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "resetToNaturalDimensions") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + var naturalDimensions = properties.naturalDimensions; + + // If any of the natural dimensions are not 0, resize + if (properties.type == "Model" && naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) { + Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded."); + } else { + Entities.editEntity(selectionManager.selections[i], { + dimensions: properties.naturalDimensions, + }); + } + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "previewCamera") { + if (selectionManager.hasSelection()) { + Camera.mode = "entity"; + Camera.cameraEntity = selectionManager.selections[0]; + } + } else if (data.action == "rescaleDimensions") { + var multiplier = data.percentage / 100; + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + Entities.editEntity(selectionManager.selections[i], { + dimensions: Vec3.multiply(multiplier, properties.dimensions), + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "reloadScript") { + if (selectionManager.hasSelection()) { + var timestamp = Date.now(); + for (var i = 0; i < selectionManager.selections.length; i++) { + Entities.editEntity(selectionManager.selections[i], { + scriptTimestamp: timestamp, + }); + } + } + } + } + }); + + return that; +}; + +PopupMenu = function() { + var self = this; + + var MENU_ITEM_HEIGHT = 21; + var MENU_ITEM_SPACING = 1; + var TEXT_MARGIN = 7; + + var overlays = []; + var overlayInfo = {}; + + var upColor = { + red: 0, + green: 0, + blue: 0 + }; + var downColor = { + red: 192, + green: 192, + blue: 192 + }; + var overColor = { + red: 128, + green: 128, + blue: 128 + }; + + self.onSelectMenuItem = function() {}; + + self.addMenuItem = function(name) { + var id = Overlays.addOverlay("text", { + text: name, + backgroundAlpha: 1.0, + backgroundColor: upColor, + topMargin: TEXT_MARGIN, + leftMargin: TEXT_MARGIN, + width: 210, + height: MENU_ITEM_HEIGHT, + font: { + size: 12 + }, + visible: false, + }); + overlays.push(id); + overlayInfo[id] = { + name: name + }; + return id; + }; + + self.updateMenuItemText = function(id, newText) { + Overlays.editOverlay(id, { + text: newText + }); + }; + + self.setPosition = function(x, y) { + for (var key in overlayInfo) { + Overlays.editOverlay(key, { + x: x, + y: y, + }); + y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; + } + }; + + self.onSelected = function() {}; + + var pressingOverlay = null; + var hoveringOverlay = null; + + self.mousePressEvent = function(event) { + if (event.isLeftButton) { + var overlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (overlay in overlayInfo) { + pressingOverlay = overlay; + Overlays.editOverlay(pressingOverlay, { + backgroundColor: downColor + }); + } else { + self.hide(); + } + return false; + } + }; + self.mouseMoveEvent = function(event) { + if (visible) { + var overlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (!pressingOverlay) { + if (hoveringOverlay != null && overlay != hoveringOverlay) { + Overlays.editOverlay(hoveringOverlay, { + backgroundColor: upColor + }); + hoveringOverlay = null; + } + if (overlay != hoveringOverlay && overlay in overlayInfo) { + Overlays.editOverlay(overlay, { + backgroundColor: overColor + }); + hoveringOverlay = overlay; + } + } + } + return false; + }; + self.mouseReleaseEvent = function(event) { + var overlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (pressingOverlay != null) { + if (overlay == pressingOverlay) { + self.onSelectMenuItem(overlayInfo[overlay].name); + } + Overlays.editOverlay(pressingOverlay, { + backgroundColor: upColor + }); + pressingOverlay = null; + self.hide(); + } + }; + + var visible = false; + + self.setVisible = function(newVisible) { + if (newVisible != visible) { + visible = newVisible; + for (var key in overlayInfo) { + Overlays.editOverlay(key, { + visible: newVisible + }); + } + } + } + self.show = function() { + self.setVisible(true); + } + self.hide = function() { + self.setVisible(false); + } + + function cleanup() { + for (var i = 0; i < overlays.length; i++) { + Overlays.deleteOverlay(overlays[i]); + } + } + + Controller.mousePressEvent.connect(self.mousePressEvent); + Controller.mouseMoveEvent.connect(self.mouseMoveEvent); + Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent); + Script.scriptEnding.connect(cleanup); + + return this; +}; + +var propertyMenu = PopupMenu(); + +propertyMenu.onSelectMenuItem = function(name) { + if (propertyMenu.marketplaceID) { + showMarketplace(propertyMenu.marketplaceID); + } +}; + +var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); + +propertiesTool = PropertiesTool(); From e369c1f3279a72bb8499436262f9819cb21ab39b Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 22 Feb 2016 10:28:00 -0800 Subject: [PATCH 040/114] fix unix warning --- interface/src/ui/ApplicationCompositor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 37eff80df9..38a0c6f9f9 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -287,7 +287,6 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int //auto headPose = qApp->getHMDSensorPose(); auto myCamera = qApp->getCamera(); mat4 cameraMat = myCamera->getTransform(); - auto cameraOrientation = myCamera->getOrientation(); auto UITransform = cameraMat * glm::inverse(headPose); auto relativePosition4 = glm::inverse(UITransform) * vec4(_drawAt3DPosition, 1); auto relativePosition = vec3(relativePosition4) / relativePosition4.w; From 942406e5d5a581c15bd21db883e39f43bb37cd28 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 09:58:37 +1300 Subject: [PATCH 041/114] Improve focus shadow --- interface/resources/qml/windows-uit/Frame.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index fc8697f93f..7f9e927d29 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -56,10 +56,10 @@ Item { RadialGradient { id: focusShadow - width: 2 * window.width - height: width - x: -width / 4 - y: -width / 4 + width: 1.66 * window.width + height: 1.66 * window.height + x: (window.width - width) / 2 + y: window.height / 2 - 0.375 * height // FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX. // Check again when have a later version of QtQuick. visible: window && window.focus && pane.visible && Qt.platform.os != "osx" From fc002df5e78eac9b18a36ed04a9c1511cd96af52 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 22 Feb 2016 13:24:14 -0800 Subject: [PATCH 042/114] implement Reticle.depth using the apparent 3D look at logic instead --- examples/editWithHacks.js | 6 ++-- interface/src/ui/ApplicationCompositor.cpp | 37 +++++++++------------- interface/src/ui/ApplicationCompositor.h | 13 ++------ 3 files changed, 20 insertions(+), 36 deletions(-) diff --git a/examples/editWithHacks.js b/examples/editWithHacks.js index 3504cddb96..11bf5785e2 100644 --- a/examples/editWithHacks.js +++ b/examples/editWithHacks.js @@ -1235,13 +1235,11 @@ Script.update.connect(function(deltaTime) { // + JSON.stringify(result) print("something hovered!! result.distance:" +result.distance); Vec3.print("something hovered!! result.intersection:", result.intersection); - //Reticle.setDepth(result.distance); - Reticle.setApparentPosition(result.intersection); + Reticle.setDepth(result.distance); Overlays.editOverlay(intersectionBeacon, { position: result.intersection, visible: false }); } else { - //Reticle.setDepth(1.0); - Reticle.restoreApparentPosition(); + Reticle.setDepth(100.0); print("NO INTERSECTION..."); var pointAt2D = Reticle.position; var pointAt3D = HMD.worldPointFromOverlay(pointAt2D); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 38a0c6f9f9..4fd810e22f 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -283,12 +283,18 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int //Mouse Pointer if (getReticleVisible()) { - if (_drawAt3D) { - //auto headPose = qApp->getHMDSensorPose(); + if (getReticleDepth() != 1.0f) { + // calculate the "apparent location" based on the depth and the current ray + glm::vec3 origin, direction; + auto reticlePosition = getReticlePosition(); + computeHmdPickRay(reticlePosition, origin, direction); + auto apparentPosition = origin + (direction * getReticleDepth()); + + // same code as used to render for apparent location auto myCamera = qApp->getCamera(); mat4 cameraMat = myCamera->getTransform(); auto UITransform = cameraMat * glm::inverse(headPose); - auto relativePosition4 = glm::inverse(UITransform) * vec4(_drawAt3DPosition, 1); + auto relativePosition4 = glm::inverse(UITransform) * vec4(apparentPosition, 1); auto relativePosition = vec3(relativePosition4) / relativePosition4.w; auto relativeDistance = glm::length(relativePosition); @@ -297,32 +303,19 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int float azimuth = atan2f(relativePosition.x, relativePosition.z); glm::quat faceCamera = glm::quat(glm::vec3(elevation, azimuth, 0)) * quat(vec3(0, 0, -1)); // this extra *quat(vec3(0,0,-1)) was required to get the quad to flip this seems like we could optimize - qDebug() << "_drawAt3DPosition:" << _drawAt3DPosition; - qDebug() << "relativePosition:" << relativePosition; - qDebug() << "relativeDistance:" << relativeDistance; - Transform transform; transform.setTranslation(relativePosition); transform.setScale(reticleScale); transform.postScale(relativeDistance); // scale not quite working, distant things too large transform.setRotation(faceCamera); batch.setModelTransform(transform); - - /* - // this definitely doesn't work - mat4 pointerXfm = glm::scale(mat4(), vec3(relativeDistance)) * glm::mat4_cast(faceCamera) * glm::translate(mat4(), relativePosition); - batch.setModelTransform(pointerXfm); - */ - - } - else { + } else { glm::mat4 overlayXfm; _modelTransform.getMatrix(overlayXfm); auto reticlePosition = getReticlePosition(); glm::vec2 projection = overlayToSpherical(reticlePosition); - float cursorDepth = getReticleDepth(); - mat4 pointerXfm = glm::scale(mat4(), vec3(cursorDepth)) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); mat4 reticleXfm = overlayXfm * pointerXfm; reticleXfm = glm::scale(reticleXfm, reticleScale); batch.setModelTransform(reticleXfm); @@ -334,7 +327,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int QPointF ApplicationCompositor::getMouseEventPosition(QMouseEvent* event) { if (qApp->isHMDMode()) { - QMutexLocker locker(&_reticlePositionInHMDLock); + QMutexLocker locker(&_reticleLock); return QPointF(_reticlePositionInHMD.x, _reticlePositionInHMD.y); } return event->localPos(); @@ -388,7 +381,7 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { // If we're in HMD mode if (shouldCaptureMouse()) { - QMutexLocker locker(&_reticlePositionInHMDLock); + QMutexLocker locker(&_reticleLock); auto newPosition = QCursor::pos(); auto changeInRealMouse = newPosition - _lastKnownRealMouse; auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse); @@ -404,7 +397,7 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { glm::vec2 ApplicationCompositor::getReticlePosition() { if (qApp->isHMDMode()) { - QMutexLocker locker(&_reticlePositionInHMDLock); + QMutexLocker locker(&_reticleLock); return _reticlePositionInHMD; } return toGlm(QCursor::pos()); @@ -412,7 +405,7 @@ glm::vec2 ApplicationCompositor::getReticlePosition() { void ApplicationCompositor::setReticlePosition(glm::vec2 position, bool sendFakeEvent) { if (qApp->isHMDMode()) { - QMutexLocker locker(&_reticlePositionInHMDLock); + QMutexLocker locker(&_reticleLock); const float MOUSE_EXTENTS_VERT_ANGULAR_SIZE = 170.0f; // 5deg from poles const float MOUSE_EXTENTS_VERT_PIXELS = VIRTUAL_SCREEN_SIZE_Y * (MOUSE_EXTENTS_VERT_ANGULAR_SIZE / DEFAULT_HMD_UI_VERT_ANGULAR_SIZE); const float MOUSE_EXTENTS_HORZ_ANGULAR_SIZE = 360.0f; // full sphere diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 57d8537b83..7337598d8f 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -29,6 +29,7 @@ class RenderArgs; class ReticleInterface; +const float DEFAULT_RETICLE_DEPTH = 1.0f; // FIXME - probably should be based on UI radius const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; @@ -88,13 +89,11 @@ public: float getReticleDepth() { return _reticleDepth; } void setReticleDepth(float depth) { _reticleDepth = depth; } + void resetReticleDepth() { _reticleDepth = DEFAULT_RETICLE_DEPTH; } glm::vec2 getReticlePosition(); void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); - void setReticleApparentPosition(glm::vec3 position) { _drawAt3D = true; _drawAt3DPosition = position; } - void restoreReticleApparentPosition() { _drawAt3D = false; } - glm::vec2 getReticleMaximumPosition() const; ReticleInterface* getReticleInterface() { return _reticleInterface; } @@ -150,10 +149,7 @@ private: // application specific position, when it's in desktop mode, the reticle position will simply move // the system mouse. glm::vec2 _reticlePositionInHMD { 0.0f, 0.0f }; - mutable QMutex _reticlePositionInHMDLock { QMutex::Recursive }; - - bool _drawAt3D { false }; - glm::vec3 _drawAt3DPosition; + mutable QMutex _reticleLock { QMutex::Recursive }; QPointF _lastKnownRealMouse; bool _ignoreMouseMove { false }; @@ -186,9 +182,6 @@ public: Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); } - Q_INVOKABLE void setApparentPosition(glm::vec3 position) { _compositor->setReticleApparentPosition(position); } - Q_INVOKABLE void restoreApparentPosition() { _compositor->restoreReticleApparentPosition(); } - private: ApplicationCompositor* _compositor; }; From 54b21abf02781ea4ba9a4955c713620ade0004b4 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 22 Feb 2016 13:32:19 -0800 Subject: [PATCH 043/114] remove editWithHacks and move to more generic depthReticle --- examples/depthReticle.js | 29 + examples/editWithHacks.js | 1908 ------------------------------------- 2 files changed, 29 insertions(+), 1908 deletions(-) create mode 100644 examples/depthReticle.js delete mode 100644 examples/editWithHacks.js diff --git a/examples/depthReticle.js b/examples/depthReticle.js new file mode 100644 index 0000000000..4d72836577 --- /dev/null +++ b/examples/depthReticle.js @@ -0,0 +1,29 @@ +var lastDepthCheckTime = 0; + +// Do some stuff regularly, like check for placement of various overlays +Script.update.connect(function(deltaTime) { + var TIME_BETWEEN_DEPTH_CHECKS = 100; + var timeSinceLastDepthCheck = Date.now() - lastDepthCheckTime; + if (timeSinceLastDepthCheck > TIME_BETWEEN_DEPTH_CHECKS) { + var reticlePosition = Reticle.position; + var pickRay = Camera.computePickRay(reticlePosition.x, reticlePosition.y); + var result = Overlays.findRayIntersection(pickRay); + + if (!result.intersects) { + result = Entities.findRayIntersection(pickRay, true); + } + if (result.intersects) { + // + JSON.stringify(result) + print("something hovered!! result.distance:" +result.distance); + Vec3.print("something hovered!! result.intersection:", result.intersection); + Reticle.setDepth(result.distance); + + } else { + Reticle.setDepth(100.0); + print("NO INTERSECTION..."); + var pointAt2D = Reticle.position; + var pointAt3D = HMD.worldPointFromOverlay(pointAt2D); + } + + } +}); diff --git a/examples/editWithHacks.js b/examples/editWithHacks.js deleted file mode 100644 index 11bf5785e2..0000000000 --- a/examples/editWithHacks.js +++ /dev/null @@ -1,1908 +0,0 @@ -// newEditEntities.js -// examples -// -// Created by Brad Hefta-Gaub on 10/2/14. -// Persist toolbar by HRS 6/11/15. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; - -Script.include([ - "libraries/stringHelpers.js", - "libraries/dataViewHelpers.js", - "libraries/toolBars.js", - "libraries/progressDialog.js", - - "libraries/entitySelectionTool.js", - - "libraries/ToolTip.js", - - "libraries/entityCameraTool.js", - "libraries/gridTool.js", - "libraries/entityList.js", - "libraries/lightOverlayManager.js", -]); - -var selectionDisplay = SelectionDisplay; -var selectionManager = SelectionManager; - -var lightOverlayManager = new LightOverlayManager(); - -var cameraManager = new CameraManager(); - -var grid = Grid(); -// gridTool = GridTool({ -// horizontalGrid: grid -// }); -// gridTool.setVisible(false); - -var entityListTool = EntityListTool(); - -selectionManager.addEventListener(function() { - selectionDisplay.updateHandles(); - lightOverlayManager.updatePositions(); -}); - -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; -var toolHeight = 50; -var toolWidth = 50; - -var DEGREES_TO_RADIANS = Math.PI / 180.0; -var RADIANS_TO_DEGREES = 180.0 / Math.PI; -var epsilon = 0.001; - -var MIN_ANGULAR_SIZE = 2; -var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = true; -var allowSmallModels = true; -var wantEntityGlow = false; - -var SPAWN_DISTANCE = 1; -var DEFAULT_DIMENSION = 0.20; -var DEFAULT_TEXT_DIMENSION_X = 1.0; -var DEFAULT_TEXT_DIMENSION_Y = 1.0; -var DEFAULT_TEXT_DIMENSION_Z = 0.01; - -var DEFAULT_DIMENSIONS = { - x: DEFAULT_DIMENSION, - y: DEFAULT_DIMENSION, - z: DEFAULT_DIMENSION -}; - -var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); - -var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; -var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; -var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode"; -var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Edit Mode"; - -var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; -var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; -var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; -var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode"; -var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; - -var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain." -var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain." - -var modelURLs = [ - "Insert the URL to your FBX" -]; - -var mode = 0; -var isActive = false; - -var placingEntityID = null; - -IMPORTING_SVO_OVERLAY_WIDTH = 144; -IMPORTING_SVO_OVERLAY_HEIGHT = 30; -IMPORTING_SVO_OVERLAY_MARGIN = 5; -IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; -var importingSVOImageOverlay = Overlays.addOverlay("image", { - imageURL: HIFI_PUBLIC_BUCKET + "images/hourglass.svg", - width: 20, - height: 20, - alpha: 1.0, - color: { - red: 255, - green: 255, - blue: 255 - }, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, - visible: false, -}); -var importingSVOTextOverlay = Overlays.addOverlay("text", { - font: { - size: 14 - }, - text: "Importing SVO...", - leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN, - width: IMPORTING_SVO_OVERLAY_WIDTH, - height: IMPORTING_SVO_OVERLAY_HEIGHT, - backgroundColor: { - red: 80, - green: 80, - blue: 80 - }, - backgroundAlpha: 0.7, - visible: false, -}); - -var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; -var marketplaceWindow = new OverlayWebWindow({ - title: 'Marketplace', - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -function showMarketplace(marketplaceID) { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - print("setting marketplace URL to " + url); - marketplaceWindow.setURL(url); - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); -} - -function hideMarketplace() { - marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); -} - -function toggleMarketplace() { - if (marketplaceWindow.visible) { - hideMarketplace(); - } else { - showMarketplace(); - } -} - -var toolBar = (function() { - var that = {}, - toolBar, - activeButton, - newModelButton, - newCubeButton, - newSphereButton, - newLightButton, - newTextButton, - newWebButton, - newZoneButton, - newPolyVoxButton; - - function initialize() { - toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) { - return { - x: windowDimensions.x - 8 - toolbar.width, - y: (windowDimensions.y - toolbar.height) / 2 - }; - }); - - - - activeButton = toolBar.addTool({ - imageURL: toolIconUrl + "edit-status.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - newModelButton = toolBar.addTool({ - imageURL: toolIconUrl + "upload.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newCubeButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-cube.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newSphereButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-sphere.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newLightButton = toolBar.addTool({ - imageURL: toolIconUrl + "light.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newTextButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-text.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newWebButton = toolBar.addTool({ - imageURL: "https://hifi-public.s3.amazonaws.com/images/www.svg", - subImage: { - x: 0, - y: 0, - width: 128, - height: 128 - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newZoneButton = toolBar.addTool({ - imageURL: toolIconUrl + "zonecube_text.svg", - subImage: { - x: 0, - y: 128, - width: 128, - height: 128 - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - newPolyVoxButton = toolBar.addTool({ - imageURL: toolIconUrl + "polyvox.svg", - subImage: { - x: 0, - y: 0, - width: 256, - height: 256 - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: false - }); - - that.setActive(false); - } - - that.clearEntityList = function() { - entityListTool.clearEntityList(); - }; - - that.setActive = function(active) { - if (active != isActive) { - if (active && !Entities.canAdjustLocks()) { - Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - } else { - isActive = active; - if (!isActive) { - entityListTool.setVisible(false); - // gridTool.setVisible(false); - grid.setEnabled(false); - propertiesTool.setVisible(false); - selectionManager.clearSelections(); - cameraManager.disable(); - } else { - hasShownPropertiesTool = false; - entityListTool.setVisible(true); - // gridTool.setVisible(true); - grid.setEnabled(true); - propertiesTool.setVisible(true); - Window.setFocus(); - } - that.showTools(isActive); - } - } - toolBar.selectTool(activeButton, isActive); - lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - }; - - // Sets visibility of tool buttons, excluding the power button - that.showTools = function(doShow) { - toolBar.showTool(newModelButton, doShow); - toolBar.showTool(newCubeButton, doShow); - toolBar.showTool(newSphereButton, doShow); - toolBar.showTool(newLightButton, doShow); - toolBar.showTool(newTextButton, doShow); - toolBar.showTool(newWebButton, doShow); - toolBar.showTool(newZoneButton, doShow); - toolBar.showTool(newPolyVoxButton, doShow); - }; - - var RESIZE_INTERVAL = 50; - var RESIZE_TIMEOUT = 120000; // 2 minutes - var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; - - function addModel(url) { - var entityID = createNewEntity({ - type: "Model", - modelURL: url - }, false); - - if (entityID) { - print("Model added: " + url); - selectionManager.setSelections([entityID]); - } - } - - function createNewEntity(properties, dragOnCreate) { - // Default to true if not passed in - dragOnCreate = dragOnCreate == undefined ? true : dragOnCreate; - - var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS; - var position = getPositionToCreateEntity(); - var entityID = null; - if (position != null) { - position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions), - properties.position = position; - - entityID = Entities.addEntity(properties); - if (dragOnCreate) { - placingEntityID = entityID; - } - } else { - Window.alert("Can't create " + properties.type + ": " + properties.type + " would be out of bounds."); - } - - return entityID; - } - - var newModelButtonDown = false; - that.mousePressEvent = function(event) { - var clickedOverlay, - url, - file; - - if (!event.isLeftButton) { - // if another mouse button than left is pressed ignore it - return false; - } - - clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - - if (activeButton === toolBar.clicked(clickedOverlay)) { - that.setActive(!isActive); - return true; - } - - // Handle these two buttons in the mouseRelease event handler so that we don't suppress a mouseRelease event from - // occurring when showing a modal dialog. - if (newModelButton === toolBar.clicked(clickedOverlay)) { - newModelButtonDown = true; - return true; - } - - - if (newCubeButton === toolBar.clicked(clickedOverlay)) { - createNewEntity({ - type: "Box", - dimensions: DEFAULT_DIMENSIONS, - color: { - red: 255, - green: 0, - blue: 0 - } - }); - - return true; - } - - if (newSphereButton === toolBar.clicked(clickedOverlay)) { - createNewEntity({ - type: "Sphere", - dimensions: DEFAULT_DIMENSIONS, - color: { - red: 255, - green: 0, - blue: 0 - } - }); - - return true; - } - - if (newLightButton === toolBar.clicked(clickedOverlay)) { - createNewEntity({ - type: "Light", - dimensions: DEFAULT_LIGHT_DIMENSIONS, - isSpotlight: false, - color: { - red: 150, - green: 150, - blue: 150 - }, - - constantAttenuation: 1, - linearAttenuation: 0, - quadraticAttenuation: 0, - exponent: 0, - cutoff: 180, // in degrees - }); - - return true; - } - - if (newTextButton === toolBar.clicked(clickedOverlay)) { - createNewEntity({ - type: "Text", - dimensions: { - x: 0.65, - y: 0.3, - z: 0.01 - }, - backgroundColor: { - red: 64, - green: 64, - blue: 64 - }, - textColor: { - red: 255, - green: 255, - blue: 255 - }, - text: "some text", - lineHeight: 0.06 - }); - - return true; - } - - if (newWebButton === toolBar.clicked(clickedOverlay)) { - createNewEntity({ - type: "Web", - dimensions: { - x: 1.6, - y: 0.9, - z: 0.01 - }, - sourceUrl: "https://highfidelity.com/", - }); - - return true; - } - - if (newZoneButton === toolBar.clicked(clickedOverlay)) { - createNewEntity({ - type: "Zone", - dimensions: { - x: 10, - y: 10, - z: 10 - }, - }); - - return true; - } - - if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) { - var polyVoxId = createNewEntity({ - type: "PolyVox", - dimensions: { - x: 10, - y: 10, - z: 10 - }, - voxelVolumeSize: { - x: 16, - y: 16, - z: 16 - }, - voxelSurfaceStyle: 2 - }); - for (var x = 1; x <= 14; x++) { - Entities.setVoxel(polyVoxId, { - x: x, - y: 1, - z: 1 - }, 255); - Entities.setVoxel(polyVoxId, { - x: x, - y: 14, - z: 1 - }, 255); - Entities.setVoxel(polyVoxId, { - x: x, - y: 1, - z: 14 - }, 255); - Entities.setVoxel(polyVoxId, { - x: x, - y: 14, - z: 14 - }, 255); - } - for (var y = 2; y <= 13; y++) { - Entities.setVoxel(polyVoxId, { - x: 1, - y: y, - z: 1 - }, 255); - Entities.setVoxel(polyVoxId, { - x: 14, - y: y, - z: 1 - }, 255); - Entities.setVoxel(polyVoxId, { - x: 1, - y: y, - z: 14 - }, 255); - Entities.setVoxel(polyVoxId, { - x: 14, - y: y, - z: 14 - }, 255); - } - for (var z = 2; z <= 13; z++) { - Entities.setVoxel(polyVoxId, { - x: 1, - y: 1, - z: z - }, 255); - Entities.setVoxel(polyVoxId, { - x: 14, - y: 1, - z: z - }, 255); - Entities.setVoxel(polyVoxId, { - x: 1, - y: 14, - z: z - }, 255); - Entities.setVoxel(polyVoxId, { - x: 14, - y: 14, - z: z - }, 255); - } - - - return true; - } - - return false; - }; - - that.mouseReleaseEvent = function(event) { - var handled = false; - if (newModelButtonDown) { - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (newModelButton === toolBar.clicked(clickedOverlay)) { - url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]); - if (url !== null && url !== "") { - addModel(url); - } - handled = true; - } - } - - newModelButtonDown = false; - - - return handled; - } - - Window.domainChanged.connect(function() { - that.setActive(false); - that.clearEntityList(); - }); - - Entities.canAdjustLocksChanged.connect(function(canAdjustLocks) { - if (isActive && !canAdjustLocks) { - that.setActive(false); - } - }); - - that.cleanup = function() { - toolBar.cleanup(); - }; - - initialize(); - return that; -}()); - - -function isLocked(properties) { - // special case to lock the ground plane model in hq. - if (location.hostname == "hq.highfidelity.io" && - properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { - return true; - } - return false; -} - - -var selectedEntityID; -var orientation; -var intersection; - - -var SCALE_FACTOR = 200.0; - -function rayPlaneIntersection(pickRay, point, normal) { - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / Vec3.dot(pickRay.direction, normal); - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function findClickedEntity(event) { - var pickZones = event.isControl; - - if (pickZones) { - Entities.setZonesArePickable(true); - } - - var pickRay = Camera.computePickRay(event.x, event.y); - - var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking - var lightResult = lightOverlayManager.findRayIntersection(pickRay); - lightResult.accurate = true; - - if (pickZones) { - Entities.setZonesArePickable(false); - } - - var result; - - if (!entityResult.intersects && !lightResult.intersects) { - return null; - } else if (entityResult.intersects && !lightResult.intersects) { - result = entityResult; - } else if (!entityResult.intersects && lightResult.intersects) { - result = lightResult; - } else { - if (entityResult.distance < lightResult.distance) { - result = entityResult; - } else { - result = lightResult; - } - } - - if (!result.accurate) { - return null; - } - - var foundEntity = result.entityID; - return { - pickRay: pickRay, - entityID: foundEntity - }; -} - -var mouseHasMovedSincePress = false; -var mousePressStartTime = 0; -var mousePressStartPosition = { - x: 0, - y: 0 -}; -var mouseDown = false; - -function mousePressEvent(event) { - mouseDown = true; - mousePressStartPosition = { - x: event.x, - y: event.y - }; - mousePressStartTime = Date.now(); - mouseHasMovedSincePress = false; - mouseCapturedByTool = false; - - if (propertyMenu.mousePressEvent(event) || toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - mouseCapturedByTool = true; - return; - } - if (isActive) { - if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } - } -} - -var highlightedEntityID = null; -var mouseCapturedByTool = false; -var lastMousePosition = null; -var idleMouseTimerId = null; -var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms -var CLICK_MOVE_DISTANCE_THRESHOLD = 8; -var IDLE_MOUSE_TIMEOUT = 200; -var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0; - -var lastMouseMoveEvent = null; - -function mouseMoveEventBuffered(event) { - lastMouseMoveEvent = event; -} - - - -function mouseMove(event) { - if (mouseDown && !mouseHasMovedSincePress) { - var timeSincePressMicro = Date.now() - mousePressStartTime; - - var dX = mousePressStartPosition.x - event.x; - var dY = mousePressStartPosition.y - event.y; - var sqDist = (dX * dX) + (dY * dY); - - // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved - // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move - // yet. The goal is to provide mouse clicks that are more lenient to small movements. - if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) { - return; - } - mouseHasMovedSincePress = true; - } - - if (placingEntityID) { - var pickRay = Camera.computePickRay(event.x, event.y); - var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE; - var offset = Vec3.multiply(distance, pickRay.direction); - var position = Vec3.sum(Camera.position, offset); - Entities.editEntity(placingEntityID, { - position: position, - }); - return; - } - if (!isActive) { - return; - } - if (idleMouseTimerId) { - Script.clearTimeout(idleMouseTimerId); - } - - // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing - if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { - return; - } - - lastMousePosition = { - x: event.x, - y: event.y - }; - - idleMouseTimerId = Script.setTimeout(handleIdleMouse, IDLE_MOUSE_TIMEOUT); - - - // brad's hack to move an overlay to the mouse - //Overlays.editOverlay(pointerOverlay, { position: lookAt3D }); - /* - var pickRay = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(pickRay); - print(JSON.stringify(result)); - if (result.intersects) { - Overlays.editOverlay(pointerOverlay, { position: result.intersection }); - Reticle.setVisible(false); - print("intersects..."); - } else { - var lookAt3D = HMD.getHUDLookAtPosition3D(); - Overlays.editOverlay(pointerOverlay, { position: { x: 0, y: 0, z: 0 } }); - Reticle.setVisible(true); - print("NO INTERSECTION..."); - } - */ -} - -function handleIdleMouse() { - idleMouseTimerId = null; -} - -function highlightEntityUnderCursor(position, accurateRay) { - var pickRay = Camera.computePickRay(position.x, position.y); - var entityIntersection = Entities.findRayIntersection(pickRay, accurateRay); - if (entityIntersection.accurate) { - if (highlightedEntityID && highlightedEntityID != entityIntersection.entityID) { - selectionDisplay.unhighlightSelectable(highlightedEntityID); - highlightedEntityID = { - id: -1 - }; - } - - var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), - entityIntersection.properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (entityIntersection.entityID && sizeOK) { - if (wantEntityGlow) { - Entities.editEntity(entityIntersection.entityID, { - glowLevel: 0.25 - }); - } - highlightedEntityID = entityIntersection.entityID; - selectionDisplay.highlightSelectable(entityIntersection.entityID); - } - - } -} - - -function mouseReleaseEvent(event) { - mouseDown = false; - - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } - if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) { - - return true; - } - if (placingEntityID) { - - if (isActive) { - - selectionManager.setSelections([placingEntityID]); - } - placingEntityID = null; - } - if (isActive && selectionManager.hasSelection()) { - - tooltip.show(false); - } - if (mouseCapturedByTool) { - - return; - } - - cameraManager.mouseReleaseEvent(event); - - if (!mouseHasMovedSincePress) { - mouseClickEvent(event); - } -} - -function mouseClickEvent(event) { - if (isActive && event.isLeftButton) { - var result = findClickedEntity(event); - if (result === null) { - if (!event.isShifted) { - selectionManager.clearSelections(); - } - return; - } - toolBar.setActive(true); - var pickRay = result.pickRay; - var foundEntity = result.entityID; - - var properties = Entities.getEntityProperties(foundEntity); - if (isLocked(properties)) { - print("Model locked " + properties.id); - } else { - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal); - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - entitySelected = true; - selectedEntityID = foundEntity; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); - - - if (!event.isShifted) { - selectionManager.setSelections([foundEntity]); - } else { - selectionManager.addEntity(foundEntity, true); - } - - print("Model selected: " + foundEntity); - selectionDisplay.select(selectedEntityID, event); - - if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { - cameraManager.enable(); - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } - } - } else if (event.isRightButton) { - var result = findClickedEntity(event); - if (result) { - var properties = Entities.getEntityProperties(result.entityID); - if (properties.marketplaceID) { - propertyMenu.marketplaceID = properties.marketplaceID; - propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); - } else { - propertyMenu.marketplaceID = null; - propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info"); - } - propertyMenu.setPosition(event.x, event.y); - propertyMenu.show(); - } else { - propertyMenu.hide(); - } - } -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var modelMenuAddedDelete = false; -var originalLightsArePickable = Entities.getLightsArePickable(); - -function setupModelMenus() { - print("setupModelMenus()"); - // adj our menuitems - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entities", - isSeparator: true, - grouping: "Advanced" - }); - if (!Menu.menuItemExists("Edit", "Delete")) { - print("no delete... adding ours"); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Delete", - shortcutKeyEvent: { - text: "backspace" - }, - afterItem: "Entities", - grouping: "Advanced" - }); - modelMenuAddedDelete = true; - } else { - print("delete exists... don't add ours"); - } - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entity List...", - shortcutKey: "CTRL+META+L", - afterItem: "Entities", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Allow Selecting of Large Models", - shortcutKey: "CTRL+META+L", - afterItem: "Entity List...", - isCheckable: true, - isChecked: true, - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Allow Selecting of Small Models", - shortcutKey: "CTRL+META+S", - afterItem: "Allow Selecting of Large Models", - isCheckable: true, - isChecked: true, - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Allow Selecting of Lights", - shortcutKey: "CTRL+SHIFT+META+L", - afterItem: "Allow Selecting of Small Models", - isCheckable: true, - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities In Box", - shortcutKey: "CTRL+SHIFT+META+A", - afterItem: "Allow Selecting of Lights", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities Touching Box", - shortcutKey: "CTRL+SHIFT+META+T", - afterItem: "Select All Entities In Box", - grouping: "Advanced" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Export Entities", - shortcutKey: "CTRL+META+E", - afterItem: "Entities", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities", - shortcutKey: "CTRL+META+I", - afterItem: "Export Entities", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities from URL", - shortcutKey: "CTRL+META+U", - afterItem: "Import Entities", - grouping: "Advanced" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_EASE_ON_FOCUS, - afterItem: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, - afterItem: MENU_EASE_ON_FOCUS, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true", - grouping: "Advanced" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, - afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true", - grouping: "Advanced" - }); - - Entities.setLightsArePickable(false); -} - -setupModelMenus(); // do this when first running our script. - -function cleanupModelMenus() { - Menu.removeSeparator("Edit", "Entities"); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Entity List..."); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - Menu.removeMenuItem("Edit", "Select All Entities In Box"); - Menu.removeMenuItem("Edit", "Select All Entities Touching Box"); - - Menu.removeMenuItem("Edit", "Export Entities"); - Menu.removeMenuItem("Edit", "Import Entities"); - Menu.removeMenuItem("Edit", "Import Entities from URL"); - - Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); - Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); - Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); -} - -Script.scriptEnding.connect(function() { - Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); - Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - Settings.setValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); - Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - - progressDialog.cleanup(); - toolBar.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - selectionDisplay.cleanup(); - Entities.setLightsArePickable(originalLightsArePickable); - - Overlays.deleteOverlay(importingSVOImageOverlay); - Overlays.deleteOverlay(importingSVOTextOverlay); -}); - -var intersectionBeaconPosition = { x: 0, y: 0, z: 0 }; -var intersectionBeaconSize = 0.03; -var intersectionBeacon = Overlays.addOverlay("sphere", { - position: intersectionBeaconPosition, - size: intersectionBeaconSize, - color: { red: 255, green: 0, blue: 0}, - alpha: 1, - solid: true, - ignoreRayIntersection: true, // this never ray intersects - }); - -Script.scriptEnding.connect(function(){ - Overlays.deleteOverlay(intersectionBeacon); -}); - - -var lastOrientation = null; -var lastPosition = null; -var lastDepthCheckTime = 0; - -// Do some stuff regularly, like check for placement of various overlays -Script.update.connect(function(deltaTime) { - progressDialog.move(); - selectionDisplay.checkMove(); - var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); - var dPosition = Vec3.distance(Camera.position, lastPosition); - if (dOrientation > 0.001 || dPosition > 0.001) { - propertyMenu.hide(); - lastOrientation = Camera.orientation; - lastPosition = Camera.position; - } - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - var TIME_BETWEEN_DEPTH_CHECKS = 100; - var timeSinceLastDepthCheck = Date.now() - lastDepthCheckTime; - if (timeSinceLastDepthCheck > TIME_BETWEEN_DEPTH_CHECKS) { - var pickRay = Camera.computePickRay(lastMouseMoveEvent.x, lastMouseMoveEvent.y); - var result = Overlays.findRayIntersection(pickRay); - - if (!result.intersects) { - result = Entities.findRayIntersection(pickRay, true); - } - if (result.intersects) { - // + JSON.stringify(result) - print("something hovered!! result.distance:" +result.distance); - Vec3.print("something hovered!! result.intersection:", result.intersection); - Reticle.setDepth(result.distance); - Overlays.editOverlay(intersectionBeacon, { position: result.intersection, visible: false }); - - } else { - Reticle.setDepth(100.0); - print("NO INTERSECTION..."); - var pointAt2D = Reticle.position; - var pointAt3D = HMD.worldPointFromOverlay(pointAt2D); - Overlays.editOverlay(intersectionBeacon, { position: pointAt3D, visible: false }); - } - - } - lastMouseMoveEvent = null; - } -}); - -function insideBox(center, dimensions, point) { - return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); -} - -function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { - if (selectionManager.hasSelection()) { - // Get all entities touching the bounding box of the current selection - var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition, - Vec3.multiply(selectionManager.worldDimensions, 0.5)); - var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions); - - if (!keepIfTouching) { - var isValid; - if (selectionManager.localPosition === null) { - isValid = function(position) { - return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); - } - } else { - isValid = function(position) { - var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), - Vec3.subtract(position, - selectionManager.localPosition)); - return insideBox({ - x: 0, - y: 0, - z: 0 - }, selectionManager.localDimensions, localPosition); - } - } - for (var i = 0; i < entities.length; ++i) { - var properties = Entities.getEntityProperties(entities[i]); - if (!isValid(properties.position)) { - entities.splice(i, 1); - --i; - } - } - } - selectionManager.setSelections(entities); - } -} - -function deleteSelectedEntities() { - if (SelectionManager.hasSelection()) { - print(" Delete Entities"); - SelectionManager.saveProperties(); - var savedProperties = []; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - SelectionManager.savedProperties[entityID]; - savedProperties.push({ - entityID: entityID, - properties: initialProperties - }); - Entities.deleteEntity(entityID); - } - SelectionManager.clearSelections(); - pushCommandForSelections([], savedProperties); - } else { - print(" Delete Entity.... not holding..."); - } -} - -function handeMenuEvent(menuItem) { - if (menuItem == "Allow Selecting of Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); - } else if (menuItem == "Allow Selecting of Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); - } else if (menuItem == "Allow Selecting of Lights") { - Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); - } else if (menuItem == "Delete") { - deleteSelectedEntities(); - } else if (menuItem == "Export Entities") { - if (!selectionManager.hasSelection()) { - Window.alert("No entities have been selected."); - } else { - var filename = "entities__" + Window.location.hostname + ".svo.json"; - filename = Window.save("Select where to save", filename, "*.json") - if (filename) { - var success = Clipboard.exportEntities(filename, selectionManager.selections); - if (!success) { - Window.alert("Export failed."); - } - } - } - } else if (menuItem == "Import Entities" || menuItem == "Import Entities from URL") { - - var importURL = null; - if (menuItem == "Import Entities") { - var fullPath = Window.browse("Select models to import", "", "*.json"); - if (fullPath) { - importURL = "file:///" + fullPath; - } - } else { - importURL = Window.prompt("URL of SVO to import", ""); - } - - if (importURL) { - importSVO(importURL); - } - } else if (menuItem == "Entity List...") { - entityListTool.toggleVisible(); - } else if (menuItem == "Select All Entities In Box") { - selectAllEtitiesInCurrentSelectionBox(false); - } else if (menuItem == "Select All Entities Touching Box") { - selectAllEtitiesInCurrentSelectionBox(true); - } else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) { - lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); - } else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) { - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - } - tooltip.show(false); -} - -// This function tries to find a reasonable position to place a new entity based on the camera -// position. If a reasonable position within the world bounds can't be found, `null` will -// be returned. The returned position will also take into account grid snapping settings. -function getPositionToCreateEntity() { - var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE; - var direction = Quat.getFront(Camera.orientation); - var offset = Vec3.multiply(distance, direction); - var placementPosition = Vec3.sum(Camera.position, offset); - - var cameraPosition = Camera.position; - - var HALF_TREE_SCALE = 16384; - - var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE; - var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE; - - if (cameraOutOfBounds && placementOutOfBounds) { - return null; - } - - placementPosition.x = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.x)); - placementPosition.y = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.y)); - placementPosition.z = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.z)); - - return placementPosition; -} - -function importSVO(importURL) { - print("Import URL requested: " + importURL) - if (!Entities.canAdjustLocks()) { - Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); - return; - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: true - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: true - }); - - var success = Clipboard.importEntities(importURL); - - if (success) { - var VERY_LARGE = 10000; - var position = { - x: 0, - y: 0, - z: 0 - }; - if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { - position = getPositionToCreateEntity(); - } - if (position != null) { - var pastedEntityIDs = Clipboard.pasteEntities(position); - - if (isActive) { - selectionManager.setSelections(pastedEntityIDs); - } - - Window.raiseMainWindow(); - } else { - Window.alert("Can't import objects: objects would be out of bounds."); - } - } else { - Window.alert("There was an error importing the entity file."); - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: false - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: false - }); -} -Window.svoImportRequested.connect(importSVO); - -Menu.menuItemEvent.connect(handeMenuEvent); - -Controller.keyPressEvent.connect(function(event) { - if (isActive) { - cameraManager.keyPressEvent(event); - } -}); - -Controller.keyReleaseEvent.connect(function(event) { - if (isActive) { - cameraManager.keyReleaseEvent(event); - } - // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items - if (event.text == "BACKSPACE" || event.text == "DELETE") { - deleteSelectedEntities(); - } else if (event.text == "ESC") { - selectionManager.clearSelections(); - } else if (event.text == "TAB") { - selectionDisplay.toggleSpaceMode(); - } else if (event.text == "f") { - if (isActive) { - if (selectionManager.hasSelection()) { - cameraManager.enable(); - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } - } else if (event.text == '[') { - if (isActive) { - cameraManager.enable(); - } - } else if (event.text == 'g') { - if (isActive && selectionManager.hasSelection()) { - var newPosition = selectionManager.worldPosition; - newPosition = Vec3.subtract(newPosition, { - x: 0, - y: selectionManager.worldDimensions.y * 0.5, - z: 0 - }); - grid.setPosition(newPosition); - } - } -}); - -// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently -// possible to create an entity with a specific id, earlier undo commands to the deleted entity -// will fail if there isn't a way to find the new entity id. -DELETED_ENTITY_MAP = {} - -function applyEntityProperties(data) { - var properties = data.setProperties; - var selectedEntityIDs = []; - for (var i = 0; i < properties.length; i++) { - var entityID = properties[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - Entities.editEntity(entityID, properties[i].properties); - selectedEntityIDs.push(entityID); - } - for (var i = 0; i < data.createEntities.length; i++) { - var entityID = data.createEntities[i].entityID; - var properties = data.createEntities[i].properties; - var newEntityID = Entities.addEntity(properties); - DELETED_ENTITY_MAP[entityID] = newEntityID; - if (data.selectCreated) { - selectedEntityIDs.push(newEntityID); - } - } - for (var i = 0; i < data.deleteEntities.length; i++) { - var entityID = data.deleteEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - Entities.deleteEntity(entityID); - } - - selectionManager.setSelections(selectedEntityIDs); -}; - -// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the -// redo command, and the saved properties for the undo command. Also, include create and delete entity data. -function pushCommandForSelections(createdEntityData, deletedEntityData) { - var undoData = { - setProperties: [], - createEntities: deletedEntityData || [], - deleteEntities: createdEntityData || [], - selectCreated: true, - }; - var redoData = { - setProperties: [], - createEntities: createdEntityData || [], - deleteEntities: deletedEntityData || [], - selectCreated: false, - }; - for (var i = 0; i < SelectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - var currentProperties = Entities.getEntityProperties(entityID); - undoData.setProperties.push({ - entityID: entityID, - properties: { - position: initialProperties.position, - rotation: initialProperties.rotation, - dimensions: initialProperties.dimensions, - }, - }); - redoData.setProperties.push({ - entityID: entityID, - properties: { - position: currentProperties.position, - rotation: currentProperties.rotation, - dimensions: currentProperties.dimensions, - }, - }); - } - UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); -} - -PropertiesTool = function(opts) { - var that = {}; - - var url = Script.resolvePath('html/entityProperties.html'); - var webView = new OverlayWebWindow({ - title: 'Entity Properties', - source: url, - toolWindow: true - }); - - var visible = false; - - webView.setVisible(visible); - - that.setVisible = function(newVisible) { - visible = newVisible; - webView.setVisible(visible); - }; - - selectionManager.addEventListener(function() { - data = { - type: 'update', - }; - var selections = []; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entity = {}; - entity.id = selectionManager.selections[i]; - entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); - if (entity.properties.rotation !== undefined) { - entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); - } - if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { - entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES, Vec3.toPolar(entity.properties.keyLight.direction)); - entity.properties.keyLight.direction.z = 0.0; - } - selections.push(entity); - } - data.selections = selections; - webView.eventBridge.emitScriptEvent(JSON.stringify(data)); - }); - - webView.eventBridge.webEventReceived.connect(function(data) { - data = JSON.parse(data); - if (data.type == "print") { - if (data.message) { - print(data.message); - } - } else if (data.type == "update") { - selectionManager.saveProperties(); - if (selectionManager.selections.length > 1) { - properties = { - locked: data.properties.locked, - visible: data.properties.visible, - }; - for (var i = 0; i < selectionManager.selections.length; i++) { - Entities.editEntity(selectionManager.selections[i], properties); - } - } else { - if (data.properties.dynamic === false) { - // this object is leaving dynamic, so we zero its velocities - data.properties["velocity"] = {x: 0, y: 0, z: 0}; - data.properties["angularVelocity"] = {x: 0, y: 0, z: 0}; - } - if (data.properties.rotation !== undefined) { - var rotation = data.properties.rotation; - data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); - } - if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) { - data.properties.keyLight.direction = Vec3.fromPolar( - data.properties.keyLight.direction.x * DEGREES_TO_RADIANS, data.properties.keyLight.direction.y * DEGREES_TO_RADIANS); - } - Entities.editEntity(selectionManager.selections[0], data.properties); - if (data.properties.name != undefined) { - entityListTool.sendUpdate(); - } - } - pushCommandForSelections(); - selectionManager._update(); - } else if (data.type == "showMarketplace") { - showMarketplace(); - } else if (data.type == "action") { - if (data.action == "moveSelectionToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); - var diff = { - x: 0, - y: dY, - z: 0 - }; - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition, - }); - } - pushCommandForSelections(); - selectionManager._update(); - } - } else if (data.action == "moveAllToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; - var dY = grid.getOrigin().y - bottomY; - var diff = { - x: 0, - y: dY, - z: 0 - }; - var newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition, - }); - } - pushCommandForSelections(); - selectionManager._update(); - } - } else if (data.action == "resetToNaturalDimensions") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var naturalDimensions = properties.naturalDimensions; - - // If any of the natural dimensions are not 0, resize - if (properties.type == "Model" && naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) { - Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded."); - } else { - Entities.editEntity(selectionManager.selections[i], { - dimensions: properties.naturalDimensions, - }); - } - } - pushCommandForSelections(); - selectionManager._update(); - } - } else if (data.action == "previewCamera") { - if (selectionManager.hasSelection()) { - Camera.mode = "entity"; - Camera.cameraEntity = selectionManager.selections[0]; - } - } else if (data.action == "rescaleDimensions") { - var multiplier = data.percentage / 100; - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; - Entities.editEntity(selectionManager.selections[i], { - dimensions: Vec3.multiply(multiplier, properties.dimensions), - }); - } - pushCommandForSelections(); - selectionManager._update(); - } - } else if (data.action == "reloadScript") { - if (selectionManager.hasSelection()) { - var timestamp = Date.now(); - for (var i = 0; i < selectionManager.selections.length; i++) { - Entities.editEntity(selectionManager.selections[i], { - scriptTimestamp: timestamp, - }); - } - } - } - } - }); - - return that; -}; - -PopupMenu = function() { - var self = this; - - var MENU_ITEM_HEIGHT = 21; - var MENU_ITEM_SPACING = 1; - var TEXT_MARGIN = 7; - - var overlays = []; - var overlayInfo = {}; - - var upColor = { - red: 0, - green: 0, - blue: 0 - }; - var downColor = { - red: 192, - green: 192, - blue: 192 - }; - var overColor = { - red: 128, - green: 128, - blue: 128 - }; - - self.onSelectMenuItem = function() {}; - - self.addMenuItem = function(name) { - var id = Overlays.addOverlay("text", { - text: name, - backgroundAlpha: 1.0, - backgroundColor: upColor, - topMargin: TEXT_MARGIN, - leftMargin: TEXT_MARGIN, - width: 210, - height: MENU_ITEM_HEIGHT, - font: { - size: 12 - }, - visible: false, - }); - overlays.push(id); - overlayInfo[id] = { - name: name - }; - return id; - }; - - self.updateMenuItemText = function(id, newText) { - Overlays.editOverlay(id, { - text: newText - }); - }; - - self.setPosition = function(x, y) { - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - x: x, - y: y, - }); - y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; - } - }; - - self.onSelected = function() {}; - - var pressingOverlay = null; - var hoveringOverlay = null; - - self.mousePressEvent = function(event) { - if (event.isLeftButton) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (overlay in overlayInfo) { - pressingOverlay = overlay; - Overlays.editOverlay(pressingOverlay, { - backgroundColor: downColor - }); - } else { - self.hide(); - } - return false; - } - }; - self.mouseMoveEvent = function(event) { - if (visible) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (!pressingOverlay) { - if (hoveringOverlay != null && overlay != hoveringOverlay) { - Overlays.editOverlay(hoveringOverlay, { - backgroundColor: upColor - }); - hoveringOverlay = null; - } - if (overlay != hoveringOverlay && overlay in overlayInfo) { - Overlays.editOverlay(overlay, { - backgroundColor: overColor - }); - hoveringOverlay = overlay; - } - } - } - return false; - }; - self.mouseReleaseEvent = function(event) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (pressingOverlay != null) { - if (overlay == pressingOverlay) { - self.onSelectMenuItem(overlayInfo[overlay].name); - } - Overlays.editOverlay(pressingOverlay, { - backgroundColor: upColor - }); - pressingOverlay = null; - self.hide(); - } - }; - - var visible = false; - - self.setVisible = function(newVisible) { - if (newVisible != visible) { - visible = newVisible; - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - visible: newVisible - }); - } - } - } - self.show = function() { - self.setVisible(true); - } - self.hide = function() { - self.setVisible(false); - } - - function cleanup() { - for (var i = 0; i < overlays.length; i++) { - Overlays.deleteOverlay(overlays[i]); - } - } - - Controller.mousePressEvent.connect(self.mousePressEvent); - Controller.mouseMoveEvent.connect(self.mouseMoveEvent); - Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent); - Script.scriptEnding.connect(cleanup); - - return this; -}; - -var propertyMenu = PopupMenu(); - -propertyMenu.onSelectMenuItem = function(name) { - if (propertyMenu.marketplaceID) { - showMarketplace(propertyMenu.marketplaceID); - } -}; - -var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); - -propertiesTool = PropertiesTool(); From 3f7a2eb10aa8cae9f3b8f9a815d15c3a640e1d76 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 22 Feb 2016 13:54:46 -0800 Subject: [PATCH 044/114] add support in depthReticle.js to set depth to overlay depth when you're over a 2D overlay --- examples/depthReticle.js | 35 +++++++++++++----------- interface/src/ui/ApplicationCompositor.h | 9 ++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/examples/depthReticle.js b/examples/depthReticle.js index 4d72836577..4c93f714aa 100644 --- a/examples/depthReticle.js +++ b/examples/depthReticle.js @@ -6,24 +6,27 @@ Script.update.connect(function(deltaTime) { var timeSinceLastDepthCheck = Date.now() - lastDepthCheckTime; if (timeSinceLastDepthCheck > TIME_BETWEEN_DEPTH_CHECKS) { var reticlePosition = Reticle.position; - var pickRay = Camera.computePickRay(reticlePosition.x, reticlePosition.y); - var result = Overlays.findRayIntersection(pickRay); - - if (!result.intersects) { - result = Entities.findRayIntersection(pickRay, true); - } - if (result.intersects) { - // + JSON.stringify(result) - print("something hovered!! result.distance:" +result.distance); - Vec3.print("something hovered!! result.intersection:", result.intersection); - Reticle.setDepth(result.distance); + // first check the 2D Overlays + if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(reticlePosition)) { + print("intersecting with 2D overlay..."); + Reticle.setDepth(1.0); } else { - Reticle.setDepth(100.0); - print("NO INTERSECTION..."); - var pointAt2D = Reticle.position; - var pointAt3D = HMD.worldPointFromOverlay(pointAt2D); - } + var pickRay = Camera.computePickRay(reticlePosition.x, reticlePosition.y); + var result = Overlays.findRayIntersection(pickRay); + if (!result.intersects) { + result = Entities.findRayIntersection(pickRay, true); + } + if (result.intersects) { + // + JSON.stringify(result) + print("something hovered!! result.distance:" +result.distance); + Vec3.print("something hovered!! result.intersection:", result.intersection); + Reticle.setDepth(result.distance); + } else { + Reticle.setDepth(100.0); + print("NO INTERSECTION..."); + } + } } }); diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 7337598d8f..3ee7c53f1b 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -105,6 +105,9 @@ public: bool shouldCaptureMouse() const; + /// if the reticle is pointing to a system overlay (a dialog box for example) then the function returns true otherwise false + bool isReticlePointingAtSystemOverlay() const { return _reticleOverQml; } + private: void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov); @@ -154,6 +157,8 @@ private: QPointF _lastKnownRealMouse; bool _ignoreMouseMove { false }; + bool _reticleOverQml { false }; + ReticleInterface* _reticleInterface; }; @@ -165,6 +170,7 @@ class ReticleInterface : public QObject { Q_PROPERTY(float depth READ getDepth WRITE setDepth) Q_PROPERTY(glm::vec2 maximumPosition READ getMaximumPosition) Q_PROPERTY(bool mouseCaptured READ isMouseCaptured) + Q_PROPERTY(bool pointingAtSystemOverlay READ isPointingAtSystemOverlay) public: ReticleInterface(ApplicationCompositor* outer) : QObject(outer), _compositor(outer) {} @@ -182,6 +188,9 @@ public: Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); } + Q_INVOKABLE bool isPointingAtSystemOverlay() { return _compositor->isReticlePointingAtSystemOverlay(); } + + private: ApplicationCompositor* _compositor; }; From 8a3b233659922c85e4a32a0f5201b7167d8e0f44 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 22 Feb 2016 13:58:07 -0800 Subject: [PATCH 045/114] don't crash if entity vanishes while doing touch test --- examples/controllers/handControllerGrab.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 3051f3faaf..dc43b3f117 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -564,7 +564,7 @@ function MyController(hand) { "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } - + this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject); }; @@ -1587,11 +1587,10 @@ function MyController(hand) { } ids.forEach(function(id) { - var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { return; - } else { + } else if (props.boundingBox) { var entityMinPoint = props.boundingBox.brn; var entityMaxPoint = props.boundingBox.tfl; var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); @@ -1616,7 +1615,6 @@ function MyController(hand) { } }); - }; this.startTouch = function(entityID) { From c4706490766f8fb5bf0531536db4f12c4e2328e1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 22 Feb 2016 14:00:01 -0800 Subject: [PATCH 046/114] don't crash if entity vanishes while doing touch test --- examples/controllers/handControllerGrab.js | 47 +++++++++++----------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index dc43b3f117..786ff33c82 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1589,31 +1589,32 @@ function MyController(hand) { ids.forEach(function(id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { - return; - } else if (props.boundingBox) { - var entityMinPoint = props.boundingBox.brn; - var entityMaxPoint = props.boundingBox.tfl; - var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); - var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); - - if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { - // we haven't been touched before, but either right or left is touching us now - _this.allTouchedIDs[id] = true; - _this.startTouch(id); - } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { - // we have been touched before and are still being touched - // continue touch - _this.continueTouch(id); - } else if (_this.allTouchedIDs[id]) { - delete _this.allTouchedIDs[id]; - _this.stopTouch(id); - - } else { - //we are in another state - return; - } + continue; } + if (!props || !props.boundingBox) { + continue; + } + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id]) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } }); }; From 4169e9be9d163977a303ef5042c8fcd5be1db9d9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 14:24:31 -0800 Subject: [PATCH 047/114] Don't deadlock objreader on shutdown --- libraries/fbx/src/OBJReader.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 11164afbbb..ff33246b3f 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -260,10 +260,22 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest netRequest(url); QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest); + if (!qApp) { + return netReply; + } QEventLoop loop; // Create an event loop that will quit when we get the finished signal QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); // Nothing is going to happen on this whole run thread until we get this - netReply->waitForReadyRead(-1); // so we might as well block this thread waiting for the response, rather than + + bool aboutToQuit { false }; + auto connection = QObject::connect(qApp, &QCoreApplication::aboutToQuit, [&] { + aboutToQuit = true; + }); + static const int WAIT_TIMEOUT_MS = 500; + while (qApp && !aboutToQuit && !netReply->isReadable()) { + netReply->waitForReadyRead(WAIT_TIMEOUT_MS); // so we might as well block this thread waiting for the response, rather than + } + QObject::disconnect(connection); return netReply; // trying to sync later on. } From b4a7dc113eac8dd6173ab8e8c640554b1e3be90d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 14:25:30 -0800 Subject: [PATCH 048/114] Safer shutdown behavior in QML surfaces --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 13 ++++++++----- libraries/gl/src/gl/OffscreenQmlSurface.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index e22feb694d..6ec162585b 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -315,6 +315,8 @@ OffscreenQmlSurface::OffscreenQmlSurface() { } OffscreenQmlSurface::~OffscreenQmlSurface() { + QObject::disconnect(&_updateTimer); + QObject::disconnect(qApp); _renderer->stop(); delete _rootItem; delete _renderer; @@ -322,6 +324,10 @@ OffscreenQmlSurface::~OffscreenQmlSurface() { delete _qmlEngine; } +void OffscreenQmlSurface::onAboutToQuit() { + QObject::disconnect(&_updateTimer); +} + void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { _renderer = new OffscreenQmlRenderer(this, shareContext); _renderer->_renderControl->_renderWindow = _proxyWindow; @@ -334,12 +340,9 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { // When Quick says there is a need to render, we will not render immediately. Instead, // a timer with a small interval is used to get better performance. _updateTimer.setInterval(MIN_TIMER_MS); - connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); - QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]{ - disconnect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); - }); + QObject::connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); + QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &OffscreenQmlSurface::onAboutToQuit); _updateTimer.start(); - _qmlComponent = new QQmlComponent(_qmlEngine); _qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 5641d16a30..9142e7f2ef 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -74,6 +74,7 @@ signals: public slots: void requestUpdate(); void requestRender(); + void onAboutToQuit(); private: QObject* finishQmlLoad(std::function f); From c07f3789e4e1d954225bd91f3e38ec33e43accc8 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 14:26:33 -0800 Subject: [PATCH 049/114] Don't crash on script destructor --- libraries/script-engine/src/ScriptEngine.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a65fe7417d..738e313f8f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -144,7 +144,12 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam ScriptEngine::~ScriptEngine() { qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename(); - DependencyManager::get()->removeScriptEngine(this); + auto scriptEngines = DependencyManager::get(); + if (scriptEngines) { + scriptEngines->removeScriptEngine(this); + } else { + qCWarning(scriptengine) << "Script destroyed after ScriptEngines!"; + } } void ScriptEngine::disconnectNonEssentialSignals() { From f6526272de23ddf57a6f62e544c646ff86d3f240 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Feb 2016 16:58:15 -0800 Subject: [PATCH 050/114] Add header descriptions --- libraries/networking/src/NLPacket.h | 11 +++++++++++ libraries/networking/src/udt/Packet.h | 27 +++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/NLPacket.h b/libraries/networking/src/NLPacket.h index 57ada84607..4527094322 100644 --- a/libraries/networking/src/NLPacket.h +++ b/libraries/networking/src/NLPacket.h @@ -21,6 +21,17 @@ class NLPacket : public udt::Packet { Q_OBJECT public: + + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Packet Type | Packet Version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Node UUID | Hash (only if verified) | Optional (only if sourced) + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + // NLPacket Header Format + // this is used by the Octree classes - must be known at compile time static const int MAX_PACKET_HEADER_SIZE = sizeof(udt::Packet::SequenceNumberAndBitField) + sizeof(udt::Packet::MessageNumberAndBitField) + diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 02d2c3d9bd..2beac65330 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -25,6 +25,25 @@ namespace udt { class Packet : public BasePacket { Q_OBJECT public: + // Packet Header Format + // + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |C|R|M| O | Sequence Number | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | P | Message Number | Optional (only if M = 1) + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Message Part Number | Optional (only if M = 1) + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + // C: Control bit + // R: Reliable bit + // M: Message bit + // O: Obfuscation level + // P: Position bits + + // NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field using SequenceNumberAndBitField = uint32_t; @@ -35,10 +54,10 @@ public: // Use same size as MessageNumberAndBitField so we can use the enum with bitwise operations enum PacketPosition : MessageNumberAndBitField { - ONLY = 0x0, - FIRST = 0x2, - MIDDLE = 0x3, - LAST = 0x1 + ONLY = 0x0, // 00 + FIRST = 0x2, // 10 + MIDDLE = 0x3, // 11 + LAST = 0x1 // 01 }; static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); From 6d9405d91de8dcf03a3737d18e1f66b910a3ec44 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Feb 2016 16:32:43 -0800 Subject: [PATCH 051/114] Add obfuscation level to packets --- libraries/networking/src/udt/Packet.cpp | 11 +++++++++-- libraries/networking/src/udt/Packet.h | 16 +++++++++++++--- libraries/networking/src/udt/SequenceNumber.h | 6 +++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index e068727e6f..53b6ef5b68 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -119,14 +119,16 @@ void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition posi writeHeader(); } -void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const { +void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level) const { + _obfuscationLevel = level; _sequenceNumber = sequenceNumber; writeHeader(); } static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 2); static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 3); -static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK; +static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0x03) << (SEQUENCE_NUMBER_BITS - 5); +static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; static const uint8_t PACKET_POSITION_OFFSET = 30; static const uint32_t PACKET_POSITION_MASK = uint32_t(0x03) << PACKET_POSITION_OFFSET; @@ -139,6 +141,7 @@ void Packet::readHeader() const { _isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit _isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit + _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> (SEQUENCE_NUMBER_BITS - 5)); _sequenceNumber = SequenceNumber{ *seqNumBitField & ~BIT_FIELD_MASK }; // Remove the bit field if (_isPartOfMessage) { @@ -163,6 +166,10 @@ void Packet::writeHeader() const { if (_isReliable) { *seqNumBitField |= RELIABILITY_BIT_MASK; } + + if (_obfuscationLevel != NoObfuscation) { + *seqNumBitField |= (_obfuscationLevel << (SEQUENCE_NUMBER_BITS - 5)); + } if (_isPartOfMessage) { *seqNumBitField |= MESSAGE_BIT_MASK; diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 2beac65330..3eefa83edc 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -59,7 +59,15 @@ public: MIDDLE = 0x3, // 11 LAST = 0x1 // 01 }; - + + // Use same size as SequenceNumberAndBitField so we can use the enum with bitwise operations + enum ObfuscationLevel : SequenceNumberAndBitField { + NoObfuscation = 0x0, // 00 + ObfuscationL1 = 0x1, // 01 + ObfuscationL2 = 0x2, // 10 + ObfuscationL3 = 0x3, // 01 + }; + static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); @@ -75,14 +83,15 @@ public: bool isPartOfMessage() const { return _isPartOfMessage; } bool isReliable() const { return _isReliable; } - + + ObfuscationLevel getObfuscationLevel() const { return _obfuscationLevel; } SequenceNumber getSequenceNumber() const { return _sequenceNumber; } MessageNumber getMessageNumber() const { return _messageNumber; } PacketPosition getPacketPosition() const { return _packetPosition; } MessagePartNumber getMessagePartNumber() const { return _messagePartNumber; } void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber); - void writeSequenceNumber(SequenceNumber sequenceNumber) const; + void writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level = NoObfuscation) const; protected: Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false); @@ -102,6 +111,7 @@ private: // Simple holders to prevent multiple reading and bitwise ops mutable bool _isReliable { false }; mutable bool _isPartOfMessage { false }; + mutable ObfuscationLevel _obfuscationLevel { NoObfuscation }; mutable SequenceNumber _sequenceNumber { 0 }; mutable MessageNumber _messageNumber { 0 }; mutable PacketPosition _packetPosition { PacketPosition::ONLY }; diff --git a/libraries/networking/src/udt/SequenceNumber.h b/libraries/networking/src/udt/SequenceNumber.h index a75f3478b8..3abc80bdd8 100644 --- a/libraries/networking/src/udt/SequenceNumber.h +++ b/libraries/networking/src/udt/SequenceNumber.h @@ -24,9 +24,9 @@ public: using Type = int32_t; using UType = uint32_t; - // Values are for 29 bit SequenceNumber - static const Type THRESHOLD = 0x0FFFFFFF; // threshold for comparing sequence numbers - static const Type MAX = 0x1FFFFFFF; // maximum sequence number used in UDT + // Values are for 27 bit SequenceNumber + static const Type THRESHOLD = 0x03FFFFFF; // threshold for comparing sequence numbers + static const Type MAX = 0x07FFFFFF; // maximum sequence number used in UDT SequenceNumber() = default; SequenceNumber(const SequenceNumber& other) : _value(other._value) {} From 3d7d812044f4dc8313cd1bea832d1475bbf2e287 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Feb 2016 16:33:50 -0800 Subject: [PATCH 052/114] Add resend mecanic with obfuscation --- libraries/networking/src/udt/SaltShaker.cpp | 54 +++++++++++++++++++++ libraries/networking/src/udt/SaltShaker.h | 27 +++++++++++ libraries/networking/src/udt/SendQueue.cpp | 50 ++++++++++++++++--- libraries/networking/src/udt/SendQueue.h | 3 +- libraries/networking/src/udt/Socket.h | 2 +- 5 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 libraries/networking/src/udt/SaltShaker.cpp create mode 100644 libraries/networking/src/udt/SaltShaker.h diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp new file mode 100644 index 0000000000..2ae1ab520c --- /dev/null +++ b/libraries/networking/src/udt/SaltShaker.cpp @@ -0,0 +1,54 @@ +// +// SaltShaker.cpp +// libraries/networking/src/udt +// +// Created by Clement on 2/18/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SaltShaker.h" + +#include + +using namespace udt; + +using Key = uint64_t; +static const std::array KEYS {{ + 0x0, + 0xd6ea42f07644016a, + 0x700f7e3414dc4d8c, + 0x54c92e8d2c871642 +}}; + +void saltingHelper(char* start, int size, Key key) {; + const auto end = start + size; + + auto p = start; + for (; p < end; p += sizeof(Key)) { + *reinterpret_cast(p) ^= key; + } + + p -= sizeof(Key); + + for (int i = 0; p < end; ++p || ++i) { + *p ^= *(reinterpret_cast(&key) + i); + } +} + +std::unique_ptr SaltShaker::salt(const Packet& packet, unsigned int saltiness) { + Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); + + auto copy = Packet::createCopy(packet); + saltingHelper(copy->getPayload(), copy->getPayloadSize(), KEYS[saltiness]); + copy->writeSequenceNumber(copy->getSequenceNumber(), (Packet::ObfuscationLevel)saltiness); + return copy; +} + +void unsalt(Packet& packet, unsigned int saltiness) { + Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); + + saltingHelper(packet.getPayload(), packet.getPayloadSize(), KEYS[saltiness]); +} \ No newline at end of file diff --git a/libraries/networking/src/udt/SaltShaker.h b/libraries/networking/src/udt/SaltShaker.h new file mode 100644 index 0000000000..4cdf5fdbe3 --- /dev/null +++ b/libraries/networking/src/udt/SaltShaker.h @@ -0,0 +1,27 @@ +// +// SaltShaker.h +// libraries/networking/src/udt +// +// Created by Clement on 2/18/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SaltShaker_h +#define hifi_SaltShaker_h + +#include "Packet.h" + +namespace udt { + +class SaltShaker { +public: + std::unique_ptr salt(const Packet& packet, unsigned int saltiness); + void unsalt(Packet& packet, unsigned int saltiness); +}; + +} + +#endif // hifi_SaltShaker_h \ No newline at end of file diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 4d6e431b45..e8cf121609 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -24,6 +24,7 @@ #include "ControlPacket.h" #include "Packet.h" #include "PacketList.h" +#include "SaltShaker.h" #include "Socket.h" using namespace udt; @@ -225,7 +226,9 @@ void SendQueue::sendNewPacketAndAddToSentList(std::unique_ptr newPacket, { // Insert the packet we have just sent in the sent list QWriteLocker locker(&_sentLock); - _sentPackets[newPacket->getSequenceNumber()].swap(newPacket); + auto& entry = _sentPackets[newPacket->getSequenceNumber()]; + entry.first = 0; // No resend + entry.second.swap(newPacket); } Q_ASSERT_X(!newPacket, "SendQueue::sendNewPacketAndAddToSentList()", "Overriden packet in sent list"); @@ -354,14 +357,45 @@ bool SendQueue::maybeResendPacket() { auto it = _sentPackets.find(resendNumber); if (it != _sentPackets.end()) { + auto& entry = it->second; // we found the packet - grab it - auto& resendPacket = *(it->second); - - // send it off - sendPacket(resendPacket); - - // unlock the sent packets - sentLocker.unlock(); + auto& resendPacket = *(entry.second); + ++entry.first; // Add 1 resend + + static const int OBFUSCATION_THRESHOLD = 3; + if (entry.first > OBFUSCATION_THRESHOLD) { + + if (entry.first % OBFUSCATION_THRESHOLD == 0) { + QString debugString = "Obfuscating packet %1 with level %2 for the first time."; + debugString = debugString.arg((uint32_t)resendPacket.getSequenceNumber(), + entry.first / OBFUSCATION_THRESHOLD); + + if (resendPacket.isPartOfMessage()) { + debugString += "\n"; + debugString += " Message Number: %1, Part Number: %2."; + debugString = debugString.arg(resendPacket.getMessageNumber(), + resendPacket.getMessagePartNumber()); + } + + qCritical() << qPrintable(debugString); + } + + + SaltShaker shaker; + auto packet = shaker.salt(resendPacket, glm::min(entry.first / OBFUSCATION_THRESHOLD, 3)); + + // unlock the sent packets + sentLocker.unlock(); + + // send it off + sendPacket(*packet); + } else { + // send it off + sendPacket(resendPacket); + + // unlock the sent packets + sentLocker.unlock(); + } emit packetRetransmitted(); diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 5428e7a26d..da8f5e6c3f 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -126,7 +126,8 @@ private: LossList _naks; // Sequence numbers of packets to resend mutable QReadWriteLock _sentLock; // Protects the sent packet list - std::unordered_map> _sentPackets; // Packets waiting for ACK. + using PacketResendPair = std::pair>; // Number of resend + packet ptr + std::unordered_map _sentPackets; // Packets waiting for ACK. std::mutex _handshakeMutex; // Protects the handshake ACK condition_variable std::atomic _hasReceivedHandshakeACK { false }; // flag for receipt of handshake ACK from client diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index 88db8e3d86..f31adfa4ab 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -25,7 +25,7 @@ #include "CongestionControl.h" #include "Connection.h" -//#define UDT_CONNECTION_DEBUG +#define UDT_CONNECTION_DEBUG class UDTTest; From 4605cf508771ea71da5430e849111e069e28d7ea Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 11:14:05 -0800 Subject: [PATCH 053/114] Move all udt header constants to Constant.h --- libraries/networking/src/udt/Constants.h | 61 ++++++++++++++++++-- libraries/networking/src/udt/Packet.cpp | 17 ++---- libraries/networking/src/udt/Packet.h | 2 +- libraries/networking/src/udt/PacketQueue.cpp | 2 +- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/libraries/networking/src/udt/Constants.h b/libraries/networking/src/udt/Constants.h index 9f5f1db883..a13997e9a3 100644 --- a/libraries/networking/src/udt/Constants.h +++ b/libraries/networking/src/udt/Constants.h @@ -26,10 +26,63 @@ namespace udt { static const int UDP_SEND_BUFFER_SIZE_BYTES = 1048576; static const int UDP_RECEIVE_BUFFER_SIZE_BYTES = 1048576; static const int DEFAULT_SYN_INTERVAL_USECS = 10 * 1000; - static const int SEQUENCE_NUMBER_BITS = sizeof(SequenceNumber) * 8; - static const int MESSAGE_LINE_NUMBER_BITS = 32; - static const int MESSAGE_NUMBER_BITS = 30; - static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 1); + + // Header constants + + // Bit sizes (in order) + static const int CONTROL_BIT_SIZE = 1; + static const int RELIABILITY_BIT_SIZE = 1; + static const int MESSAGE_BIT_SIZE = 1; + static const int OBFUSCATION_LEVEL_SIZE = 2; + static const int SEQUENCE_NUMBER_SIZE= 27; + + static const int PACKET_POSITION_SIZE = 2; + static const int MESSAGE_NUMBER_SIZE = 30; + + static const int MESSAGE_PART_NUMBER_SIZE = 32; + + // Offsets + static const int SEQUENCE_NUMBER_OFFSET = 0; + static const int OBFUSCATION_LEVEL_OFFSET = SEQUENCE_NUMBER_OFFSET + SEQUENCE_NUMBER_SIZE; + static const int MESSAGE_BIT_OFFSET = OBFUSCATION_LEVEL_OFFSET + OBFUSCATION_LEVEL_SIZE; + static const int RELIABILITY_BIT_OFFSET = MESSAGE_BIT_OFFSET + MESSAGE_BIT_SIZE; + static const int CONTROL_BIT_OFFSET = RELIABILITY_BIT_OFFSET + RELIABILITY_BIT_SIZE; + + static const int MESSAGE_NUMBER_OFFSET = 0; + static const int PACKET_POSITION_OFFSET = MESSAGE_NUMBER_OFFSET + MESSAGE_NUMBER_SIZE; + + static const int MESSAGE_PART_NUMBER_OFFSET = 0; + + // Masks + static const uint32_t CONTROL_BIT_MASK = uint32_t(0b1) << CONTROL_BIT_OFFSET; + static const uint32_t RELIABILITY_BIT_MASK = uint32_t(0b1) << RELIABILITY_BIT_OFFSET; + static const uint32_t MESSAGE_BIT_MASK = uint32_t(0b1) << MESSAGE_BIT_OFFSET; + static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0b11) << OBFUSCATION_LEVEL_OFFSET; + static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; + static const uint32_t SEQUENCE_NUMBER_MASK = ~BIT_FIELD_MASK; + + static const uint32_t PACKET_POSITION_MASK = uint32_t(0b11) << PACKET_POSITION_OFFSET; + static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK; + + static const uint32_t MESSAGE_PART_NUMBER_MASK = ~uint32_t(0); + + // Static checks + static_assert(CONTROL_BIT_SIZE + RELIABILITY_BIT_SIZE + MESSAGE_BIT_SIZE + + OBFUSCATION_LEVEL_SIZE + SEQUENCE_NUMBER_SIZE == 32, "Sequence number line size incorrect"); + static_assert(PACKET_POSITION_SIZE + MESSAGE_NUMBER_SIZE == 32, "Message number line size incorrect"); + static_assert(MESSAGE_PART_NUMBER_SIZE == 32, "Message part number line size incorrect"); + + static_assert(CONTROL_BIT_MASK == 0b10000000000000000000000000000000, "CONTROL_BIT_MASK incorrect"); + static_assert(RELIABILITY_BIT_MASK == 0b01000000000000000000000000000000, "RELIABILITY_BIT_MASK incorrect"); + static_assert(MESSAGE_BIT_MASK == 0b00100000000000000000000000000000, "MESSAGE_BIT_MASK incorrect"); + static_assert(OBFUSCATION_LEVEL_MASK == 0b00011000000000000000000000000000, "OBFUSCATION_LEVEL_MASK incorrect"); + static_assert(BIT_FIELD_MASK == 0b11111000000000000000000000000000, "BIT_FIELD_MASK incorrect"); + static_assert(SEQUENCE_NUMBER_MASK == 0b00000111111111111111111111111111, "SEQUENCE_NUMBER_MASK incorrect"); + + static_assert(PACKET_POSITION_MASK == 0b11000000000000000000000000000000, "PACKET_POSITION_MASK incorrect"); + static_assert(MESSAGE_NUMBER_MASK == 0b00111111111111111111111111111111, "MESSAGE_NUMBER_MASK incorrect"); + + static_assert(MESSAGE_PART_NUMBER_MASK == 0b11111111111111111111111111111111, "MESSAGE_PART_NUMBER_MASK incorrect"); } #endif // hifi_udt_Constants_h diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 53b6ef5b68..17d18bebea 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -120,20 +120,11 @@ void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition posi } void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level) const { - _obfuscationLevel = level; _sequenceNumber = sequenceNumber; + _obfuscationLevel = level; writeHeader(); } -static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 2); -static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 3); -static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0x03) << (SEQUENCE_NUMBER_BITS - 5); -static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; - -static const uint8_t PACKET_POSITION_OFFSET = 30; -static const uint32_t PACKET_POSITION_MASK = uint32_t(0x03) << PACKET_POSITION_OFFSET; -static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK; - void Packet::readHeader() const { SequenceNumberAndBitField* seqNumBitField = reinterpret_cast(_packet.get()); @@ -141,8 +132,8 @@ void Packet::readHeader() const { _isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit _isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit - _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> (SEQUENCE_NUMBER_BITS - 5)); - _sequenceNumber = SequenceNumber{ *seqNumBitField & ~BIT_FIELD_MASK }; // Remove the bit field + _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> OBFUSCATION_LEVEL_OFFSET); + _sequenceNumber = SequenceNumber{ *seqNumBitField & SEQUENCE_NUMBER_MASK }; // Remove the bit field if (_isPartOfMessage) { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; @@ -168,7 +159,7 @@ void Packet::writeHeader() const { } if (_obfuscationLevel != NoObfuscation) { - *seqNumBitField |= (_obfuscationLevel << (SEQUENCE_NUMBER_BITS - 5)); + *seqNumBitField |= (_obfuscationLevel << OBFUSCATION_LEVEL_OFFSET); } if (_isPartOfMessage) { diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 3eefa83edc..2fd38de51f 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -65,7 +65,7 @@ public: NoObfuscation = 0x0, // 00 ObfuscationL1 = 0x1, // 01 ObfuscationL2 = 0x2, // 10 - ObfuscationL3 = 0x3, // 01 + ObfuscationL3 = 0x3, // 11 }; static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); diff --git a/libraries/networking/src/udt/PacketQueue.cpp b/libraries/networking/src/udt/PacketQueue.cpp index bc3a1796e2..8ff2333a20 100644 --- a/libraries/networking/src/udt/PacketQueue.cpp +++ b/libraries/networking/src/udt/PacketQueue.cpp @@ -16,7 +16,7 @@ using namespace udt; MessageNumber PacketQueue::getNextMessageNumber() { - static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_BITS; + static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_SIZE; _currentMessageNumber = (_currentMessageNumber + 1) % MAX_MESSAGE_NUMBER; return _currentMessageNumber; } From bf5a65ca456a840314794c37a8efc81e0e6e8302 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 15:04:21 -0800 Subject: [PATCH 054/114] Add missing copies --- libraries/networking/src/udt/Constants.h | 1 + libraries/networking/src/udt/Packet.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/Constants.h b/libraries/networking/src/udt/Constants.h index a13997e9a3..0e63afe0a0 100644 --- a/libraries/networking/src/udt/Constants.h +++ b/libraries/networking/src/udt/Constants.h @@ -27,6 +27,7 @@ namespace udt { static const int UDP_RECEIVE_BUFFER_SIZE_BYTES = 1048576; static const int DEFAULT_SYN_INTERVAL_USECS = 10 * 1000; + // Header constants // Bit sizes (in order) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 17d18bebea..263c7ee6cf 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -76,15 +76,23 @@ Packet::Packet(const Packet& other) : { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; + _packetPosition = other._packetPosition; + _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; } Packet& Packet::operator=(const Packet& other) { BasePacket::operator=(other); - + _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; + _packetPosition = other._packetPosition; + _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; return *this; } @@ -94,19 +102,23 @@ Packet::Packet(Packet&& other) : { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; _packetPosition = other._packetPosition; _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; } Packet& Packet::operator=(Packet&& other) { BasePacket::operator=(std::move(other)); - + _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; _packetPosition = other._packetPosition; _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; return *this; } From c29ad093066871ee684d645f16c1179d1ce8436c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 15:12:31 -0800 Subject: [PATCH 055/114] Fix obfuscation --- libraries/networking/src/udt/Packet.cpp | 24 ++++++++++++++++ libraries/networking/src/udt/SaltShaker.cpp | 8 +++--- libraries/networking/src/udt/SendQueue.cpp | 31 +++++++++++---------- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 263c7ee6cf..84b4b24ec2 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -11,6 +11,10 @@ #include "Packet.h" +#include + +#include "SaltShaker.h" + using namespace udt; static int packetMetaTypeId = qRegisterMetaType("Packet*"); @@ -68,6 +72,26 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se { readHeader(); + if (getObfuscationLevel() != Packet::NoObfuscation) { + SaltShaker shaker; + shaker.unsalt(*this, getObfuscationLevel()); + readHeader(); // read packet header again as some of the data was obfuscated + + QString debugString = "Unobfuscating packet %1 with level %2"; + debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), + QString::number(getObfuscationLevel())); + + if (isPartOfMessage()) { + debugString += "\n"; + debugString += " Message Number: %1, Part Number: %2."; + debugString = debugString.arg(QString::number(getMessageNumber()), + QString::number(getMessagePartNumber())); + } + + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .{0,1000}"); + qDebug() << qPrintable(debugString); + } + adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); } diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp index 2ae1ab520c..73c59f7925 100644 --- a/libraries/networking/src/udt/SaltShaker.cpp +++ b/libraries/networking/src/udt/SaltShaker.cpp @@ -23,7 +23,7 @@ static const std::array KEYS {{ 0x54c92e8d2c871642 }}; -void saltingHelper(char* start, int size, Key key) {; +void saltingHelper(char* start, int size, Key key) { const auto end = start + size; auto p = start; @@ -42,13 +42,13 @@ std::unique_ptr SaltShaker::salt(const Packet& packet, unsigned int salt Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); auto copy = Packet::createCopy(packet); - saltingHelper(copy->getPayload(), copy->getPayloadSize(), KEYS[saltiness]); copy->writeSequenceNumber(copy->getSequenceNumber(), (Packet::ObfuscationLevel)saltiness); + saltingHelper(copy->getData() + 4, copy->getDataSize() - 4, KEYS[saltiness]); return copy; } -void unsalt(Packet& packet, unsigned int saltiness) { +void SaltShaker::unsalt(Packet& packet, unsigned int saltiness) { Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); - saltingHelper(packet.getPayload(), packet.getPayloadSize(), KEYS[saltiness]); + saltingHelper(packet.getData() + 4, packet.getDataSize() - 4, KEYS[saltiness]); } \ No newline at end of file diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index e8cf121609..da3727b214 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -338,6 +338,8 @@ bool SendQueue::maybeSendNewPacket() { return false; } +#include + bool SendQueue::maybeResendPacket() { // the following while makes sure that we find a packet to re-send, if there is one @@ -362,27 +364,26 @@ bool SendQueue::maybeResendPacket() { auto& resendPacket = *(entry.second); ++entry.first; // Add 1 resend - static const int OBFUSCATION_THRESHOLD = 3; - if (entry.first > OBFUSCATION_THRESHOLD) { + auto saltiness = entry.first < 2 ? 0 : (entry.first - 2) % 4; - if (entry.first % OBFUSCATION_THRESHOLD == 0) { - QString debugString = "Obfuscating packet %1 with level %2 for the first time."; - debugString = debugString.arg((uint32_t)resendPacket.getSequenceNumber(), - entry.first / OBFUSCATION_THRESHOLD); + if (saltiness != 0) { + QString debugString = "Obfuscating packet %1 with level %2"; + debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()), + QString::number(saltiness)); - if (resendPacket.isPartOfMessage()) { - debugString += "\n"; - debugString += " Message Number: %1, Part Number: %2."; - debugString = debugString.arg(resendPacket.getMessageNumber(), - resendPacket.getMessagePartNumber()); - } - - qCritical() << qPrintable(debugString); + if (resendPacket.isPartOfMessage()) { + debugString += "\n"; + debugString += " Message Number: %1, Part Number: %2."; + debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()), + QString::number(resendPacket.getMessagePartNumber())); } + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .{0,1000}"); + qCritical() << qPrintable(debugString); + SaltShaker shaker; - auto packet = shaker.salt(resendPacket, glm::min(entry.first / OBFUSCATION_THRESHOLD, 3)); + auto packet = shaker.salt(resendPacket, saltiness); // unlock the sent packets sentLocker.unlock(); From 3a11e84c94cf1842690c9eee3f1382e43d270436 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 15:30:12 -0800 Subject: [PATCH 056/114] Use hex for msvc compatibility --- libraries/networking/src/udt/Constants.h | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/libraries/networking/src/udt/Constants.h b/libraries/networking/src/udt/Constants.h index 0e63afe0a0..98569ead5a 100644 --- a/libraries/networking/src/udt/Constants.h +++ b/libraries/networking/src/udt/Constants.h @@ -55,35 +55,36 @@ namespace udt { static const int MESSAGE_PART_NUMBER_OFFSET = 0; // Masks - static const uint32_t CONTROL_BIT_MASK = uint32_t(0b1) << CONTROL_BIT_OFFSET; - static const uint32_t RELIABILITY_BIT_MASK = uint32_t(0b1) << RELIABILITY_BIT_OFFSET; - static const uint32_t MESSAGE_BIT_MASK = uint32_t(0b1) << MESSAGE_BIT_OFFSET; - static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0b11) << OBFUSCATION_LEVEL_OFFSET; + static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << CONTROL_BIT_OFFSET; + static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << RELIABILITY_BIT_OFFSET; + static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << MESSAGE_BIT_OFFSET; + static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(3) << OBFUSCATION_LEVEL_OFFSET; static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; static const uint32_t SEQUENCE_NUMBER_MASK = ~BIT_FIELD_MASK; - static const uint32_t PACKET_POSITION_MASK = uint32_t(0b11) << PACKET_POSITION_OFFSET; + static const uint32_t PACKET_POSITION_MASK = uint32_t(3) << PACKET_POSITION_OFFSET; static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK; static const uint32_t MESSAGE_PART_NUMBER_MASK = ~uint32_t(0); + // Static checks static_assert(CONTROL_BIT_SIZE + RELIABILITY_BIT_SIZE + MESSAGE_BIT_SIZE + OBFUSCATION_LEVEL_SIZE + SEQUENCE_NUMBER_SIZE == 32, "Sequence number line size incorrect"); static_assert(PACKET_POSITION_SIZE + MESSAGE_NUMBER_SIZE == 32, "Message number line size incorrect"); static_assert(MESSAGE_PART_NUMBER_SIZE == 32, "Message part number line size incorrect"); - static_assert(CONTROL_BIT_MASK == 0b10000000000000000000000000000000, "CONTROL_BIT_MASK incorrect"); - static_assert(RELIABILITY_BIT_MASK == 0b01000000000000000000000000000000, "RELIABILITY_BIT_MASK incorrect"); - static_assert(MESSAGE_BIT_MASK == 0b00100000000000000000000000000000, "MESSAGE_BIT_MASK incorrect"); - static_assert(OBFUSCATION_LEVEL_MASK == 0b00011000000000000000000000000000, "OBFUSCATION_LEVEL_MASK incorrect"); - static_assert(BIT_FIELD_MASK == 0b11111000000000000000000000000000, "BIT_FIELD_MASK incorrect"); - static_assert(SEQUENCE_NUMBER_MASK == 0b00000111111111111111111111111111, "SEQUENCE_NUMBER_MASK incorrect"); + static_assert(CONTROL_BIT_MASK == 0x80000000, "CONTROL_BIT_MASK incorrect"); + static_assert(RELIABILITY_BIT_MASK == 0x40000000, "RELIABILITY_BIT_MASK incorrect"); + static_assert(MESSAGE_BIT_MASK == 0x20000000, "MESSAGE_BIT_MASK incorrect"); + static_assert(OBFUSCATION_LEVEL_MASK == 0x18000000, "OBFUSCATION_LEVEL_MASK incorrect"); + static_assert(BIT_FIELD_MASK == 0xF8000000, "BIT_FIELD_MASK incorrect"); + static_assert(SEQUENCE_NUMBER_MASK == 0x07FFFFFF, "SEQUENCE_NUMBER_MASK incorrect"); - static_assert(PACKET_POSITION_MASK == 0b11000000000000000000000000000000, "PACKET_POSITION_MASK incorrect"); - static_assert(MESSAGE_NUMBER_MASK == 0b00111111111111111111111111111111, "MESSAGE_NUMBER_MASK incorrect"); + static_assert(PACKET_POSITION_MASK == 0xC0000000, "PACKET_POSITION_MASK incorrect"); + static_assert(MESSAGE_NUMBER_MASK == 0x3FFFFFFF, "MESSAGE_NUMBER_MASK incorrect"); - static_assert(MESSAGE_PART_NUMBER_MASK == 0b11111111111111111111111111111111, "MESSAGE_PART_NUMBER_MASK incorrect"); + static_assert(MESSAGE_PART_NUMBER_MASK == 0xFFFFFFFF, "MESSAGE_PART_NUMBER_MASK incorrect"); } #endif // hifi_udt_Constants_h From f06ac911c543e1cd5df04f8bc726cacff2c74955 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 16:05:57 -0800 Subject: [PATCH 057/114] Fix XORing algorithm --- libraries/networking/src/udt/SaltShaker.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp index 73c59f7925..4febaa789a 100644 --- a/libraries/networking/src/udt/SaltShaker.cpp +++ b/libraries/networking/src/udt/SaltShaker.cpp @@ -27,12 +27,10 @@ void saltingHelper(char* start, int size, Key key) { const auto end = start + size; auto p = start; - for (; p < end; p += sizeof(Key)) { + for (; p + sizeof(Key) < end; p += sizeof(Key)) { *reinterpret_cast(p) ^= key; } - p -= sizeof(Key); - for (int i = 0; p < end; ++p || ++i) { *p ^= *(reinterpret_cast(&key) + i); } From 17b4d6fcf9501579b8bf65315ae509cb2ad169ce Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 11:40:07 -0800 Subject: [PATCH 058/114] Factor members copy --- libraries/networking/src/udt/Packet.cpp | 50 ++++++++----------------- libraries/networking/src/udt/Packet.h | 2 + 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 84b4b24ec2..b06f7ba847 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -95,54 +95,26 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); } -Packet::Packet(const Packet& other) : - BasePacket(other) -{ - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; +Packet::Packet(const Packet& other) : BasePacket(other) { + copyMembers(other); } Packet& Packet::operator=(const Packet& other) { BasePacket::operator=(other); - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; + copyMembers(other); return *this; } -Packet::Packet(Packet&& other) : - BasePacket(std::move(other)) -{ - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; +Packet::Packet(Packet&& other) : BasePacket(std::move(other)) { + copyMembers(other); } Packet& Packet::operator=(Packet&& other) { BasePacket::operator=(std::move(other)); - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; + copyMembers(other); return *this; } @@ -161,6 +133,16 @@ void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel writeHeader(); } +void Packet::copyMembers(const Packet& other) { + _isReliable = other._isReliable; + _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; + _sequenceNumber = other._sequenceNumber; + _packetPosition = other._packetPosition; + _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; +} + void Packet::readHeader() const { SequenceNumberAndBitField* seqNumBitField = reinterpret_cast(_packet.get()); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 2fd38de51f..bfd1b9a3cd 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -104,6 +104,8 @@ protected: Packet& operator=(Packet&& other); private: + void copyMembers(const Packet& other); + // Header readers - these read data to member variables after pulling packet off wire void readHeader() const; void writeHeader() const; From cb4f400c7ee567b505daf320d80f0529ef78c037 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 15:15:15 -0800 Subject: [PATCH 059/114] Cleanup obfuscation code --- libraries/networking/src/udt/Packet.cpp | 53 ++++++++++++++++----- libraries/networking/src/udt/Packet.h | 5 +- libraries/networking/src/udt/SaltShaker.cpp | 52 -------------------- libraries/networking/src/udt/SaltShaker.h | 27 ----------- libraries/networking/src/udt/SendQueue.cpp | 19 ++++---- 5 files changed, 55 insertions(+), 101 deletions(-) delete mode 100644 libraries/networking/src/udt/SaltShaker.cpp delete mode 100644 libraries/networking/src/udt/SaltShaker.h diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index b06f7ba847..f6bff06173 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -11,14 +11,35 @@ #include "Packet.h" -#include +#include -#include "SaltShaker.h" +#include using namespace udt; static int packetMetaTypeId = qRegisterMetaType("Packet*"); +using Key = uint64_t; +static const std::array KEYS {{ + 0x0, + 0x6362726973736574, + 0x7362697261726461, + 0x72687566666d616e, +}}; + +void xorHelper(char* start, int size, Key key) { + const auto end = start + size; + + auto p = start; + for (; p + sizeof(Key) < end; p += sizeof(Key)) { + *reinterpret_cast(p) ^= key; + } + + for (int i = 0; p < end; ++p || ++i) { + *p ^= *(reinterpret_cast(&key) + i); + } +} + int Packet::localHeaderSize(bool isPartOfMessage) { return sizeof(Packet::SequenceNumberAndBitField) + (isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0); @@ -72,11 +93,9 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se { readHeader(); - if (getObfuscationLevel() != Packet::NoObfuscation) { - SaltShaker shaker; - shaker.unsalt(*this, getObfuscationLevel()); - readHeader(); // read packet header again as some of the data was obfuscated + adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); + if (getObfuscationLevel() != Packet::NoObfuscation) { QString debugString = "Unobfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), QString::number(getObfuscationLevel())); @@ -90,9 +109,9 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .{0,1000}"); qDebug() << qPrintable(debugString); - } - adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); + obfuscate(NoObfuscation); // Undo obfuscation + } } Packet::Packet(const Packet& other) : BasePacket(other) { @@ -119,7 +138,7 @@ Packet& Packet::operator=(Packet&& other) { return *this; } -void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) { +void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const { _isPartOfMessage = true; _messageNumber = messageNumber; _packetPosition = position; @@ -127,12 +146,23 @@ void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition posi writeHeader(); } -void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level) const { +void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const { _sequenceNumber = sequenceNumber; - _obfuscationLevel = level; writeHeader(); } +void Packet::obfuscate(ObfuscationLevel level) { + auto obfuscationKey = KEYS[getObfuscationLevel()] ^ KEYS[level]; // Undo old and apply new one. + if (obfuscationKey != 0) { + xorHelper(getData() + localHeaderSize(isPartOfMessage()), + getDataSize() - localHeaderSize(isPartOfMessage()), obfuscationKey); + + // Update members and header + _obfuscationLevel = level; + writeHeader(); + } +} + void Packet::copyMembers(const Packet& other) { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; @@ -155,6 +185,7 @@ void Packet::readHeader() const { if (_isPartOfMessage) { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; + _messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK; _packetPosition = static_cast(*messageNumberAndBitField >> PACKET_POSITION_OFFSET); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index bfd1b9a3cd..c0da3a0781 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -90,8 +90,9 @@ public: PacketPosition getPacketPosition() const { return _packetPosition; } MessagePartNumber getMessagePartNumber() const { return _messagePartNumber; } - void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber); - void writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level = NoObfuscation) const; + void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const; + void writeSequenceNumber(SequenceNumber sequenceNumber) const; + void obfuscate(ObfuscationLevel level); protected: Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false); diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp deleted file mode 100644 index 4febaa789a..0000000000 --- a/libraries/networking/src/udt/SaltShaker.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// SaltShaker.cpp -// libraries/networking/src/udt -// -// Created by Clement on 2/18/16. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "SaltShaker.h" - -#include - -using namespace udt; - -using Key = uint64_t; -static const std::array KEYS {{ - 0x0, - 0xd6ea42f07644016a, - 0x700f7e3414dc4d8c, - 0x54c92e8d2c871642 -}}; - -void saltingHelper(char* start, int size, Key key) { - const auto end = start + size; - - auto p = start; - for (; p + sizeof(Key) < end; p += sizeof(Key)) { - *reinterpret_cast(p) ^= key; - } - - for (int i = 0; p < end; ++p || ++i) { - *p ^= *(reinterpret_cast(&key) + i); - } -} - -std::unique_ptr SaltShaker::salt(const Packet& packet, unsigned int saltiness) { - Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); - - auto copy = Packet::createCopy(packet); - copy->writeSequenceNumber(copy->getSequenceNumber(), (Packet::ObfuscationLevel)saltiness); - saltingHelper(copy->getData() + 4, copy->getDataSize() - 4, KEYS[saltiness]); - return copy; -} - -void SaltShaker::unsalt(Packet& packet, unsigned int saltiness) { - Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); - - saltingHelper(packet.getData() + 4, packet.getDataSize() - 4, KEYS[saltiness]); -} \ No newline at end of file diff --git a/libraries/networking/src/udt/SaltShaker.h b/libraries/networking/src/udt/SaltShaker.h deleted file mode 100644 index 4cdf5fdbe3..0000000000 --- a/libraries/networking/src/udt/SaltShaker.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// SaltShaker.h -// libraries/networking/src/udt -// -// Created by Clement on 2/18/16. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_SaltShaker_h -#define hifi_SaltShaker_h - -#include "Packet.h" - -namespace udt { - -class SaltShaker { -public: - std::unique_ptr salt(const Packet& packet, unsigned int saltiness); - void unsalt(Packet& packet, unsigned int saltiness); -}; - -} - -#endif // hifi_SaltShaker_h \ No newline at end of file diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index da3727b214..d3051377d3 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -18,13 +18,13 @@ #include #include +#include #include #include "../NetworkLogging.h" #include "ControlPacket.h" #include "Packet.h" #include "PacketList.h" -#include "SaltShaker.h" #include "Socket.h" using namespace udt; @@ -338,8 +338,6 @@ bool SendQueue::maybeSendNewPacket() { return false; } -#include - bool SendQueue::maybeResendPacket() { // the following while makes sure that we find a packet to re-send, if there is one @@ -364,13 +362,12 @@ bool SendQueue::maybeResendPacket() { auto& resendPacket = *(entry.second); ++entry.first; // Add 1 resend - auto saltiness = entry.first < 2 ? 0 : (entry.first - 2) % 4; + Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4); - if (saltiness != 0) { + if (level != Packet::NoObfuscation) { QString debugString = "Obfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()), - QString::number(saltiness)); - + QString::number(level)); if (resendPacket.isPartOfMessage()) { debugString += "\n"; debugString += " Message Number: %1, Part Number: %2."; @@ -382,12 +379,16 @@ bool SendQueue::maybeResendPacket() { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .{0,1000}"); qCritical() << qPrintable(debugString); - SaltShaker shaker; - auto packet = shaker.salt(resendPacket, saltiness); + + // Create copy of the packet + auto packet = Packet::createCopy(resendPacket); // unlock the sent packets sentLocker.unlock(); + // Obfuscate packet + packet->obfuscate(level); + // send it off sendPacket(*packet); } else { From 97aebaf52a820610313243b6bdc3a8e71ca1453c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 15:33:53 -0800 Subject: [PATCH 060/114] Fix log regexes --- libraries/networking/src/udt/Packet.cpp | 2 +- libraries/networking/src/udt/SendQueue.cpp | 4 +--- libraries/networking/src/udt/Socket.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index f6bff06173..9b413c0517 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -107,7 +107,7 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se QString::number(getMessagePartNumber())); } - static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .{0,1000}"); + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*"); qDebug() << qPrintable(debugString); obfuscate(NoObfuscation); // Undo obfuscation diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index d3051377d3..3d7b585ed6 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -374,9 +374,7 @@ bool SendQueue::maybeResendPacket() { debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()), QString::number(resendPacket.getMessagePartNumber())); } - - - static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .{0,1000}"); + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*"); qCritical() << qPrintable(debugString); diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 8fb5db3853..1eb7c04331 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -277,7 +277,7 @@ void Socket::readPendingDatagrams() { if (packet->isReliable()) { // if this was a reliable packet then signal the matching connection with the sequence number auto& connection = findOrCreateConnection(senderSockAddr); - + if (!connection.processReceivedSequenceNumber(packet->getSequenceNumber(), packet->getDataSize(), packet->getPayloadSize())) { From 4c18a504733cac70e219cc002af71c1aca28a9a8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 15:38:09 -0800 Subject: [PATCH 061/114] Only debug if define set --- libraries/networking/src/udt/Packet.cpp | 4 +++- libraries/networking/src/udt/Packet.h | 2 +- libraries/networking/src/udt/SendQueue.cpp | 3 ++- libraries/networking/src/udt/Socket.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 9b413c0517..088de49981 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -96,6 +96,7 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); if (getObfuscationLevel() != Packet::NoObfuscation) { +#ifdef UDT_CONNECTION_DEBUG QString debugString = "Unobfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), QString::number(getObfuscationLevel())); @@ -109,6 +110,7 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*"); qDebug() << qPrintable(debugString); +#endif obfuscate(NoObfuscation); // Undo obfuscation } @@ -138,7 +140,7 @@ Packet& Packet::operator=(Packet&& other) { return *this; } -void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const { +void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) { _isPartOfMessage = true; _messageNumber = messageNumber; _packetPosition = position; diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index c0da3a0781..cad5cccb0e 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -90,7 +90,7 @@ public: PacketPosition getPacketPosition() const { return _packetPosition; } MessagePartNumber getMessagePartNumber() const { return _messagePartNumber; } - void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const; + void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber); void writeSequenceNumber(SequenceNumber sequenceNumber) const; void obfuscate(ObfuscationLevel level); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 3d7b585ed6..18269d1d43 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -365,6 +365,7 @@ bool SendQueue::maybeResendPacket() { Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4); if (level != Packet::NoObfuscation) { +#ifdef UDT_CONNECTION_DEBUG QString debugString = "Obfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()), QString::number(level)); @@ -376,7 +377,7 @@ bool SendQueue::maybeResendPacket() { } static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*"); qCritical() << qPrintable(debugString); - +#endif // Create copy of the packet auto packet = Packet::createCopy(resendPacket); diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index f31adfa4ab..88db8e3d86 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -25,7 +25,7 @@ #include "CongestionControl.h" #include "Connection.h" -#define UDT_CONNECTION_DEBUG +//#define UDT_CONNECTION_DEBUG class UDTTest; From f7654dce05568ee21ab7be61441060cea6a08eaa Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 13:10:02 +1300 Subject: [PATCH 062/114] Style modal dialog background and border --- .../qml/styles-uit/HifiConstants.qml | 2 ++ interface/resources/qml/windows-uit/Frame.qml | 1 - .../resources/qml/windows-uit/ModalFrame.qml | 24 ++++++++++++++++--- .../resources/qml/windows-uit/ModalWindow.qml | 2 +- .../resources/qml/windows-uit/Window.qml | 4 ++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index fda90d731a..b18a4498bf 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -77,6 +77,8 @@ Item { readonly property real textPadding: 8 readonly property real tablePadding: 12 readonly property real tableRowHeight: largeScreen ? 26 : 23 + readonly property real modalDialogMargin: 50 + readonly property real modalDialogTitleHeight: 40 // DJRTODO: Use } Item { diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 7f9e927d29..8dfd3a293f 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -18,7 +18,6 @@ Item { id: frame HifiConstants { id: hifi } - property alias window: frame.parent // Convenience accessor for the window default property var decoration readonly property int iconSize: 22 diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index 25f89a8baa..9c2e18d0f4 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -14,11 +14,29 @@ import "." import "../controls" Frame { - id: frame - Item { - anchors.fill: parent + id: modalFrame + anchors.fill: parent + anchors.margins: 0 + + readonly property bool hasTitle: window.title != "" + + Rectangle { + anchors { + topMargin: -hifi.dimensions.modalDialogMargin - (modalFrame.hasTitle ? hifi.dimensions.modalDialogTitleHeight : 0) + leftMargin: -hifi.dimensions.modalDialogMargin + rightMargin: -hifi.dimensions.modalDialogMargin + bottomMargin: -hifi.dimensions.modalDialogMargin + fill: parent + } + border { + width: hifi.dimensions.borderWidth + color: hifi.colors.lightGrayText80 + } + radius: hifi.dimensions.borderRadius + color: hifi.colors.faintGray + } Rectangle { id: background anchors.fill: parent diff --git a/interface/resources/qml/windows-uit/ModalWindow.qml b/interface/resources/qml/windows-uit/ModalWindow.qml index 47da73281d..af099eb275 100644 --- a/interface/resources/qml/windows-uit/ModalWindow.qml +++ b/interface/resources/qml/windows-uit/ModalWindow.qml @@ -13,7 +13,7 @@ import QtQuick 2.5 import "." Window { - id: root + id: window anchors.centerIn: parent modality: Qt.ApplicationModal destroyOnCloseButton: true diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index caf465fb58..8a1cd44c8b 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -133,12 +133,13 @@ Fadable { anchors.fill: parent anchors.rightMargin: parent.isScrolling ? 11 : 0 color: hifi.colors.baseGray + visible: modality != Qt.ApplicationModal } LinearGradient { // FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX. // Check again when have a later version of QtQuick. - visible: Qt.platform.os != "osx" + visible: modality != Qt.ApplicationModal && Qt.platform.os != "osx" anchors.top: contentBackground.bottom anchors.left: contentBackground.left width: contentBackground.width - 1 @@ -201,7 +202,6 @@ Fadable { } } } - children: [ swallower, frame, pane, activator ] Component.onCompleted: { raise(); setDefaultFocus(); } From e86b36b00f9b98e8b611a74b09fc44bb52843d70 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 13:12:29 +1300 Subject: [PATCH 063/114] Don't whitewash screen when modal dialog is displayed Focus shadow is used instead. --- interface/resources/qml/windows-uit/ModalFrame.qml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index 9c2e18d0f4..740f563ba3 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -37,14 +37,6 @@ Frame { radius: hifi.dimensions.borderRadius color: hifi.colors.faintGray } - Rectangle { - id: background - anchors.fill: parent - anchors.margins: -4096 - visible: window.visible - color: "#7f7f7f7f"; - radius: 3; - } Text { y: -implicitHeight - iconSize / 2 From f1921b4e38079219623642431f8cd8c96b1f5b29 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 13:14:38 +1300 Subject: [PATCH 064/114] Style modal dialog title --- .../resources/qml/windows-uit/ModalFrame.qml | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index 740f563ba3..fd6d13c235 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -11,7 +11,8 @@ import QtQuick 2.5 import "." -import "../controls" +import "../controls-uit" +import "../styles-uit" Frame { Item { @@ -38,14 +39,25 @@ Frame { color: hifi.colors.faintGray } - Text { - y: -implicitHeight - iconSize / 2 + RalewayRegular { text: window.title elide: Text.ElideRight - font.bold: true - color: window.focus ? "white" : "gray" - style: Text.Outline; - styleColor: "black" + color: hifi.colors.baseGrayHighlight + size: hifi.fontSizes.overlayTitle + y: -hifi.dimensions.modalDialogTitleHeight + anchors { + left: parent.left + right: parent.right + } + horizontalAlignment: Text.AlignHCenter + visible: modalFrame.hasTitle + } + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: hifi.colors.lightGray + visible: modalFrame.hasTitle } } } From 33cfe8f21fdb6a31bc5894595012b4063d470084 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 13:31:08 +1300 Subject: [PATCH 065/114] Style modal dialog icon and message --- .../resources/qml/dialogs/MessageDialog.qml | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index 3b7cc2c9a8..32db266f9d 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -1,10 +1,21 @@ +// +// Desktop.qml +// +// Created by Bradley Austin Davis on 25 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 -import QtQuick.Controls 1.2 +import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 as OriginalDialogs -import "../controls" -import "../styles" -import "../windows" +import "../controls-uit" +import "../styles-uit" +import "../windows-uit" + import "messageDialog" // FIXME respect default button functionality @@ -39,17 +50,16 @@ ModalWindow { property int clickedButton: OriginalDialogs.StandardButton.NoButton; focus: defaultButton === OriginalDialogs.StandardButton.NoButton - Rectangle { + Item { id: messageBox clip: true - anchors.fill: parent - radius: 4 - color: "white" + width: pane.width + height: pane.height QtObject { id: d - readonly property real spacing: hifi.layout.spacing - readonly property real outerSpacing: hifi.layout.spacing * 2 + readonly property real spacing: hifi.dimensions.contentSpacing.x + readonly property real outerSpacing: hifi.dimensions.contentSpacing.y readonly property int minWidth: 480 readonly property int maxWdith: 1280 readonly property int minHeight: 160 @@ -65,16 +75,16 @@ ModalWindow { FontAwesome { id: iconHolder - size: 48 + size: 30 anchors { left: parent.left top: parent.top margins: d.spacing * 2 } + color: hifi.colors.lightGrayText verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - style: Text.Outline; styleColor: "black" Component.onCompleted: updateIcon(); function updateIcon() { if (!root) { @@ -83,22 +93,18 @@ ModalWindow { switch (root.icon) { case OriginalDialogs.StandardIcon.Information: text = "\uF05A"; - color = "blue"; break; case OriginalDialogs.StandardIcon.Question: text = "\uF059" - color = "blue"; break; case OriginalDialogs.StandardIcon.Warning: text = "\uF071" - color = "yellow"; break; case OriginalDialogs.StandardIcon.Critical: text = "\uF057" - color = "red" break; default: @@ -108,12 +114,15 @@ ModalWindow { } } - Text { + RalewaySemibold { id: mainTextContainer onHeightChanged: d.resize(); onWidthChanged: d.resize(); wrapMode: Text.WordWrap - font { pointSize: 14; weight: Font.Bold } + size: hifi.fontSizes.menuItem + color: hifi.colors.baseGrayHighlight anchors { left: iconHolder.right; top: parent.top; margins: d.spacing * 2 } + lineHeight: 2 + lineHeightMode: Text.ProportionalHeight } Text { From 84e352a1de9333c4544a522ed595da92de2eae83 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 14:54:49 +1300 Subject: [PATCH 066/114] Move icon to be in title --- .../resources/qml/dialogs/MessageDialog.qml | 78 ++++++++----------- .../resources/qml/windows-uit/ModalFrame.qml | 34 +++++--- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index 32db266f9d..8524b5ce75 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -43,13 +43,36 @@ ModalWindow { property alias detailedText: detailedText.text property alias text: mainTextContainer.text property alias informativeText: informativeTextContainer.text - onIconChanged: iconHolder.updateIcon(); + onIconChanged: updateIcon(); property int buttons: OriginalDialogs.StandardButton.Ok property int icon: OriginalDialogs.StandardIcon.NoIcon + property string iconText: "" property int defaultButton: OriginalDialogs.StandardButton.NoButton; property int clickedButton: OriginalDialogs.StandardButton.NoButton; focus: defaultButton === OriginalDialogs.StandardButton.NoButton + function updateIcon() { + if (!root) { + return; + } + switch (root.icon) { + case OriginalDialogs.StandardIcon.Information: + iconText = "\uF05A"; + break; + case OriginalDialogs.StandardIcon.Question: + iconText = "\uF059" + break; + case OriginalDialogs.StandardIcon.Warning: + iconText = "\uF071" + break; + case OriginalDialogs.StandardIcon.Critical: + iconText = "\uF057" + break; + default: + iconText = "" + } + } + Item { id: messageBox clip: true @@ -66,61 +89,25 @@ ModalWindow { readonly property int maxHeight: 720 function resize() { - var targetWidth = iconHolder.width + mainTextContainer.width + d.spacing * 6 + var targetWidth = mainTextContainer.width var targetHeight = mainTextContainer.implicitHeight + informativeTextContainer.implicitHeight + d.spacing * 8 + buttons.height + details.height root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth) root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight) } } - FontAwesome { - id: iconHolder - size: 30 - anchors { - left: parent.left - top: parent.top - margins: d.spacing * 2 - } - color: hifi.colors.lightGrayText - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - Component.onCompleted: updateIcon(); - function updateIcon() { - if (!root) { - return; - } - switch (root.icon) { - case OriginalDialogs.StandardIcon.Information: - text = "\uF05A"; - break; - - case OriginalDialogs.StandardIcon.Question: - text = "\uF059" - break; - - case OriginalDialogs.StandardIcon.Warning: - text = "\uF071" - break; - - case OriginalDialogs.StandardIcon.Critical: - text = "\uF057" - break; - - default: - text = "" - } - visible = (text != ""); - } - } - RalewaySemibold { id: mainTextContainer onHeightChanged: d.resize(); onWidthChanged: d.resize(); wrapMode: Text.WordWrap size: hifi.fontSizes.menuItem color: hifi.colors.baseGrayHighlight - anchors { left: iconHolder.right; top: parent.top; margins: d.spacing * 2 } + anchors { + left: parent.left; + top: parent.top; + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } lineHeight: 2 lineHeightMode: Text.ProportionalHeight } @@ -130,7 +117,7 @@ ModalWindow { onHeightChanged: d.resize(); onWidthChanged: d.resize(); wrapMode: Text.WordWrap font.pointSize: 11 - anchors { top: mainTextContainer.bottom; right: parent.right; left: iconHolder.right; margins: d.spacing * 2 } + anchors { top: mainTextContainer.bottom; right: parent.right; left: parent.left; margins: d.spacing * 2 } } Flow { @@ -199,6 +186,7 @@ ModalWindow { } ] + Component.onCompleted: updateIcon(); onStateChanged: d.resize() } diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index fd6d13c235..7cf3af86ec 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -39,19 +39,31 @@ Frame { color: hifi.colors.faintGray } - RalewayRegular { - text: window.title - elide: Text.ElideRight - color: hifi.colors.baseGrayHighlight - size: hifi.fontSizes.overlayTitle - y: -hifi.dimensions.modalDialogTitleHeight - anchors { - left: parent.left - right: parent.right - } - horizontalAlignment: Text.AlignHCenter + Item { visible: modalFrame.hasTitle + width: title.width + (window.iconText !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0) + x: (parent.width - width) / 2 + + FontAwesome { + id: icon + text: window.iconText + size: 30 + color: hifi.colors.lightGrayText + visible: text != "" + y: -hifi.dimensions.modalDialogTitleHeight + anchors.left: parent.left + } + RalewayRegular { + id: title + text: window.title + elide: Text.ElideRight + color: hifi.colors.baseGrayHighlight + size: hifi.fontSizes.overlayTitle + y: -hifi.dimensions.modalDialogTitleHeight + anchors.right: parent.right + } } + Rectangle { anchors.left: parent.left anchors.right: parent.right From 23b204c0c6390fd2e5a9d95a20649da7c0e6f6d5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 22 Feb 2016 19:03:12 -0800 Subject: [PATCH 067/114] fix logic that checks getEntityProperties return value --- examples/controllers/handControllerGrab.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 1aaf78f68d..1fd6045fe0 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1588,11 +1588,10 @@ function MyController(hand) { ids.forEach(function(id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); - if (props.name === 'pointer') { - continue; - } - if (!props || !props.boundingBox) { - continue; + if (!props || + !props.boundingBox || + props.name === 'pointer') { + return; } var entityMinPoint = props.boundingBox.brn; var entityMaxPoint = props.boundingBox.tfl; From 3b87cd0ea895cbf40c33bb5a786f3cae981a20f7 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 22 Feb 2016 19:15:22 -0800 Subject: [PATCH 068/114] Improve hold action by using controller velocity The AvatarHoldAction now derives the body velocity by using data from the controller::Pose. Rather then trying to derive it based on previous positions. This results in more acurate motion of the held object when the hold is released. OpenVR input plugin: pass the velocity and angularVelocity directly from the controller pose to the controller::Pose. --- interface/src/Application.cpp | 9 ++++ interface/src/avatar/AvatarActionHold.cpp | 51 +++++++++++++++----- interface/src/avatar/AvatarActionHold.h | 6 ++- libraries/avatars/src/HandData.h | 1 + plugins/openvr/src/OpenVrDisplayPlugin.cpp | 5 ++ plugins/openvr/src/OpenVrHelpers.h | 6 ++- plugins/openvr/src/ViveControllerManager.cpp | 31 ++++++++---- plugins/openvr/src/ViveControllerManager.h | 9 ++-- 8 files changed, 89 insertions(+), 29 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64cd586e13..5c28e31d8c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5037,6 +5037,8 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de glm::vec3 position = pose.getTranslation(); glm::quat rotation = pose.getRotation(); + // AJT: REMOVE + /* // Compute current velocity from position change glm::vec3 rawVelocity; if (deltaTime > 0.0f) { @@ -5057,6 +5059,13 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de } else { palm.setRawAngularVelocity(glm::vec3(0.0f)); } + */ + + glm::vec3 rawVelocity = pose.getVelocity(); + glm::vec3 angularVelocity = pose.getAngularVelocity(); + + palm.setRawVelocity(rawVelocity); + palm.setRawAngularVelocity(angularVelocity); if (controller::InputDevice::getLowVelocityFilter()) { // Use a velocity sensitive filter to damp small motions and preserve large ones with diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 71bd1b1f82..0093c22377 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -93,7 +93,8 @@ void AvatarActionHold::prepareForPhysicsSimulation() { activateBody(true); } -std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) { +std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position, + glm::vec3& linearVelocity, glm::vec3& angularVelocity) { auto avatarManager = DependencyManager::get(); auto holdingAvatar = std::static_pointer_cast(avatarManager->getAvatarBySessionID(_holderID)); @@ -103,19 +104,22 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve withReadLock([&]{ bool isRightHand = (_hand == "right"); - glm::vec3 palmPosition { Vectors::ZERO }; - glm::quat palmRotation { Quaternions::IDENTITY }; + glm::vec3 palmPosition; + glm::quat palmRotation; + glm::vec3 palmLinearVelocity; + glm::vec3 palmAngularVelocity; + + PalmData palmData = holdingAvatar->getHand()->getCopyOfPalmData(isRightHand ? HandData::RightHand : HandData::LeftHand); + + // TODO: adjust according to _relativePosition and _relativeRotation? + linearVelocity = palmData.getVelocity(); + angularVelocity = palmData.getAngularVelocity(); if (_ignoreIK && holdingAvatar->isMyAvatar()) { // We cannot ignore other avatars IK and this is not the point of this option // This is meant to make the grabbing behavior more reactive. - if (isRightHand) { - palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getPosition(); - palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getRotation(); - } else { - palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition(); - palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); - } + palmPosition = palmData.getPosition(); + palmRotation = palmData.getRotation(); } else if (holdingAvatar->isMyAvatar()) { glm::vec3 avatarRigidBodyPosition; glm::quat avatarRigidBodyRotation; @@ -153,14 +157,19 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve rotation = palmRotation * _relativeRotation; position = palmPosition + rotation * _relativePosition; + + // update linearVelocity based on offset via _relativePosition; + linearVelocity = linearVelocity + glm::cross(angularVelocity, position - palmPosition); }); return holdingAvatar; } void AvatarActionHold::updateActionWorker(float deltaTimeStep) { - glm::quat rotation { Quaternions::IDENTITY }; - glm::vec3 position { Vectors::ZERO }; + glm::quat rotation; + glm::vec3 position; + glm::vec3 linearVelocity; + glm::vec3 angularVelocity; bool valid = false; int holdCount = 0; @@ -173,7 +182,8 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { std::shared_ptr holdAction = std::static_pointer_cast(action); glm::quat rotationForAction; glm::vec3 positionForAction; - std::shared_ptr holdingAvatar = holdAction->getTarget(rotationForAction, positionForAction); + glm::vec3 linearVelocityForAction, angularVelocityForAction; + std::shared_ptr holdingAvatar = holdAction->getTarget(rotationForAction, positionForAction, linearVelocityForAction, angularVelocityForAction); if (holdingAvatar) { holdCount ++; if (holdAction.get() == this) { @@ -183,15 +193,21 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { } position += positionForAction; + linearVelocity += linearVelocityForAction; + angularVelocity += angularVelocityForAction; } } if (valid && holdCount > 0) { position /= holdCount; + linearVelocity /= holdCount; + angularVelocity /= holdCount; withWriteLock([&]{ _positionalTarget = position; _rotationalTarget = rotation; + _linearVelocityTarget = linearVelocity; + _angularVelocityTarget = angularVelocity; _positionalTargetSet = true; _rotationalTargetSet = true; _active = true; @@ -225,15 +241,24 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { withWriteLock([&]{ if (_kinematicSetVelocity) { + rigidBody->setLinearVelocity(glmToBullet(_linearVelocityTarget)); + rigidBody->setAngularVelocity(glmToBullet(_angularVelocityTarget)); + /* if (_previousSet) { // smooth velocity over 2 frames glm::vec3 positionalDelta = _positionalTarget - _previousPositionalTarget; glm::vec3 positionalVelocity = (positionalDelta + _previousPositionalDelta) / (deltaTimeStep + _previousDeltaTimeStep); rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); + + if (_hand == "right") { + qDebug() << "AJT: rb vel = " << positionalVelocity.x << positionalVelocity.y << positionalVelocity.z; + } + _previousPositionalDelta = positionalDelta; _previousDeltaTimeStep = deltaTimeStep; } + */ } btTransform worldTrans = rigidBody->getWorldTransform(); diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 7646f87238..018c3fd076 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -36,7 +36,8 @@ public: virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); } bool getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); - std::shared_ptr getTarget(glm::quat& rotation, glm::vec3& position); + std::shared_ptr getTarget(glm::quat& rotation, glm::vec3& position, + glm::vec3& linearVelocity, glm::vec3& angularVelocity); virtual void prepareForPhysicsSimulation() override; @@ -50,6 +51,9 @@ private: QString _hand { "right" }; QUuid _holderID; + glm::vec3 _linearVelocityTarget; + glm::vec3 _angularVelocityTarget; + bool _kinematic { false }; bool _kinematicSetVelocity { false }; bool _previousSet { false }; diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 34ed610f80..63af43e399 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -93,6 +93,7 @@ public: PalmData(HandData* owningHandData = nullptr, HandData::Hand hand = HandData::UnknownHand); glm::vec3 getPosition() const { return _owningHandData->localToWorldPosition(_rawPosition); } glm::vec3 getVelocity() const { return _owningHandData->localToWorldDirection(_rawVelocity); } + glm::vec3 getAngularVelocity() const { return _owningHandData->localToWorldDirection(_rawAngularVelocity); } const glm::vec3& getRawPosition() const { return _rawPosition; } bool isActive() const { return _isActive; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index efd230bc28..559ea5bcfb 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "OpenVrHelpers.h" @@ -32,6 +33,8 @@ const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probab static vr::IVRCompositor* _compositor{ nullptr }; vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; +vec3 _trackedDeviceLinearVelocities[vr::k_unMaxTrackedDeviceCount]; +vec3 _trackedDeviceAngularVelocities[vr::k_unMaxTrackedDeviceCount]; static mat4 _sensorResetMat; static std::array VR_EYES { { vr::Eye_Left, vr::Eye_Right } }; @@ -119,6 +122,8 @@ glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { _trackedDevicePose[i] = predictedTrackedDevicePose[i]; _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking); + _trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity)); + _trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity)); } return _trackedDevicePoseMat4[0]; } diff --git a/plugins/openvr/src/OpenVrHelpers.h b/plugins/openvr/src/OpenVrHelpers.h index e4a34c53b7..26179fb757 100644 --- a/plugins/openvr/src/OpenVrHelpers.h +++ b/plugins/openvr/src/OpenVrHelpers.h @@ -13,7 +13,7 @@ #include vr::IVRSystem* acquireOpenVrSystem(); -void releaseOpenVrSystem(); +void releaseOpenVrSystem(); template void openvr_for_each_eye(F f) { @@ -25,6 +25,10 @@ inline mat4 toGlm(const vr::HmdMatrix44_t& m) { return glm::transpose(glm::make_mat4(&m.m[0][0])); } +inline vec3 toGlm(const vr::HmdVector3_t& v) { + return vec3(v.v[0], v.v[1], v.v[2]); +} + inline mat4 toGlm(const vr::HmdMatrix34_t& m) { mat4 result = mat4( m.m[0][0], m.m[1][0], m.m[2][0], 0.0, diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 720a6d48c6..071d5fd631 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -29,6 +29,8 @@ extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; +extern vec3 _trackedDeviceLinearVelocities[vr::k_unMaxTrackedDeviceCount]; +extern vec3 _trackedDeviceAngularVelocities[vr::k_unMaxTrackedDeviceCount]; vr::IVRSystem* acquireOpenVrSystem(); void releaseOpenVrSystem(); @@ -249,10 +251,11 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle numTrackedControllers++; bool left = numTrackedControllers == 2; - const mat4& mat = _trackedDevicePoseMat4[device]; - if (!jointsCaptured) { - handlePoseEvent(inputCalibrationData, mat, numTrackedControllers - 1); + const mat4& mat = _trackedDevicePoseMat4[device]; + const vec3 linearVelocity = _trackedDeviceLinearVelocities[device]; + const vec3 angularVelocity = _trackedDeviceAngularVelocities[device]; + handlePoseEvent(inputCalibrationData, mat, linearVelocity, angularVelocity, numTrackedControllers - 1); } // handle inputs @@ -314,7 +317,9 @@ void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool } } -void ViveControllerManager::InputDevice::handlePoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, bool left) { +void ViveControllerManager::InputDevice::handlePoseEvent(const controller::InputCalibrationData& inputCalibrationData, + const mat4& mat, const vec3& linearVelocity, + const vec3& angularVelocity, bool left) { // When the sensor-to-world rotation is identity the coordinate axes look like this: // // user @@ -379,16 +384,22 @@ void ViveControllerManager::InputDevice::handlePoseEvent(const controller::Input static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET; static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET; - glm::vec3 position = extractTranslation(mat); - glm::quat rotation = glm::quat_cast(mat); + auto translationOffset = (left ? leftTranslationOffset : rightTranslationOffset); + auto rotationOffset = (left ? leftRotationOffset : rightRotationOffset); - position += rotation * (left ? leftTranslationOffset : rightTranslationOffset); - rotation = rotation * (left ? leftRotationOffset : rightRotationOffset); + glm::vec3 position = extractTranslation(mat); + glm::quat rotation = glm::normalize(glm::quat_cast(mat)); + + position += rotation * translationOffset; + rotation = rotation * rotationOffset; // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; - auto avatarPose = controller::Pose(position, rotation).transform(controllerToAvatar); - _poseStateMap[left ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose; + auto avatarPose = controller::Pose(position, rotation); + // handle change in velocity due to translationOffset + avatarPose.velocity = linearVelocity + glm::cross(angularVelocity, position - extractTranslation(mat)); + avatarPose.angularVelocity = angularVelocity; + _poseStateMap[left ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose.transform(controllerToAvatar); } controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 282c8e41a5..51339cd465 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -46,7 +46,7 @@ public: void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges); void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } - + private: class InputDevice : public controller::InputDevice { public: @@ -60,7 +60,8 @@ private: void handleButtonEvent(uint32_t button, bool pressed, bool left); void handleAxisEvent(uint32_t axis, float x, float y, bool left); - void handlePoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, bool left); + void handlePoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, + const vec3& linearVelocity, const vec3& angularVelocity, bool left); int _trackedControllers { 0 }; vr::IVRSystem*& _hmd; @@ -68,8 +69,8 @@ private: }; void renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign); - - + + bool _registeredWithInputMapper { false }; bool _modelLoaded { false }; From 160a107bbd079af69a4b521afa550c68f4e07f05 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 19:36:00 -0800 Subject: [PATCH 069/114] Auto-unhide the desktop when showing or raising a window --- interface/resources/qml/desktop/Desktop.qml | 13 +++++++++++-- interface/src/Application.cpp | 9 ++++++++- interface/src/Application.h | 1 + libraries/ui/src/OffscreenUi.cpp | 5 +++++ libraries/ui/src/OffscreenUi.h | 3 +++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 0286c45ac3..e2aecdfd18 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -10,12 +10,19 @@ import "../js/Utils.js" as Utils // windows will be childed. FocusScope { id: desktop - anchors.fill: parent; objectName: "desktop" + // Allow the scale of the desktop to be changed without screwing up the size relative to the parent. + height: parent.height / scale + width: parent.width / scale + onHeightChanged: d.repositionAll(); onWidthChanged: d.repositionAll(); + // Controls and windows can trigger this signal to ensure the desktop becomes visible + // when they're opened. + signal showDesktop(); + // Allows QML/JS to find the desktop through the parent chain property bool desktopRoot: true @@ -217,6 +224,8 @@ FocusScope { } reposition(targetWindow); + + showDesktop(); } function reposition(item) { @@ -314,7 +323,7 @@ FocusScope { enabled: DebugQML onTriggered: focusDebugger.visible = !focusDebugger.visible } - + } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64cd586e13..704940433a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1198,7 +1198,8 @@ void Application::initializeUi() { // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // support the window management and scripting proxies for VR use offscreenUi->createDesktop(QString("hifi/Desktop.qml")); - + connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop); + // FIXME either expose so that dialogs can set this themselves or // do better detection in the offscreen UI of what has focus offscreenUi->setNavigationFocused(false); @@ -5128,3 +5129,9 @@ void Application::readArgumentsFromLocalSocket() { qApp->openUrl(QString::fromUtf8(message)); } } + +void Application::showDesktop() { + if (!_overlayConductor.getEnabled()) { + _overlayConductor.setEnabled(true); + } +} \ No newline at end of file diff --git a/interface/src/Application.h b/interface/src/Application.h index 96bafce23f..8cc2a33038 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -280,6 +280,7 @@ public slots: void runTests(); private slots: + void showDesktop(); void clearDomainOctreeDetails(); void idle(uint64_t now); void aboutToQuit(); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index fa40fedb9b..7e84836c86 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -112,6 +112,7 @@ void OffscreenUi::create(QOpenGLContext* context) { } void OffscreenUi::show(const QUrl& url, const QString& name, std::function f) { + emit showDesktop(); QQuickItem* item = getRootItem()->findChild(name); // First load? if (!item) { @@ -127,6 +128,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::functionfindChild(name); // Already loaded? if (item) { + emit showDesktop(); item->setVisible(!item->isVisible()); return; } @@ -134,6 +136,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::functionfindChild(name); if (item && !item->isVisible()) { + emit showDesktop(); item->setVisible(true); } } @@ -439,6 +442,8 @@ void OffscreenUi::createDesktop(const QUrl& url) { new VrMenu(this); new KeyboardFocusHack(); + + connect(_desktop, SIGNAL(showDesktop()), this, SLOT(showDesktop())); } QQuickItem* OffscreenUi::getDesktop() { diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index de479853f3..8b00180d43 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -106,6 +106,9 @@ public: // Compatibility with QInputDialog::getItem static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone); +signals: + void showDesktop(); + private: QString fileDialog(const QVariantMap& properties); From 0fd260076bbcae43f4d7bcf11b752f85476a9d7e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 22 Feb 2016 20:05:41 -0800 Subject: [PATCH 070/114] SixenseManager: fix velocity and angularVelocity computation Copied the delta based computation of velocity and angularVelocity that was in Application::setPalmData() and moved it into SixenseManager. This will guarantee that the velocity computation is the same as it was previously. The goal here is to NOT change the behavior of the hydra. The moving average style calculation of velocities has been removed. Removed dead code. --- interface/src/Application.cpp | 25 ------------- interface/src/avatar/Avatar.cpp | 29 --------------- interface/src/avatar/AvatarActionHold.cpp | 16 --------- plugins/hifiSixense/src/SixenseManager.cpp | 42 +++++++++------------- plugins/hifiSixense/src/SixenseManager.h | 7 ---- 5 files changed, 16 insertions(+), 103 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5c28e31d8c..ed7aef0dab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5036,31 +5036,6 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de // controller pose is in Avatar frame. glm::vec3 position = pose.getTranslation(); glm::quat rotation = pose.getRotation(); - - // AJT: REMOVE - /* - // Compute current velocity from position change - glm::vec3 rawVelocity; - if (deltaTime > 0.0f) { - rawVelocity = (position - palm.getRawPosition()) / deltaTime; - } else { - rawVelocity = glm::vec3(0.0f); - } - palm.setRawVelocity(rawVelocity); // meters/sec - - // Angular Velocity of Palm - glm::quat deltaRotation = rotation * glm::inverse(palm.getRawRotation()); - glm::vec3 angularVelocity(0.0f); - float rotationAngle = glm::angle(deltaRotation); - if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { - angularVelocity = glm::normalize(glm::axis(deltaRotation)); - angularVelocity *= (rotationAngle / deltaTime); - palm.setRawAngularVelocity(angularVelocity); - } else { - palm.setRawAngularVelocity(glm::vec3(0.0f)); - } - */ - glm::vec3 rawVelocity = pose.getVelocity(); glm::vec3 angularVelocity = pose.getAngularVelocity(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f62eb5a070..2b164a7bac 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -929,35 +929,6 @@ void Avatar::setAttachmentData(const QVector& attachmentData) { } _attachmentModels[i]->setURL(attachmentData[i].modelURL); } - - // AJT: TODO REMOVE - /* - // make sure we have as many models as attachments - while (_attachmentModels.size() < attachmentData.size()) { - Model* model = nullptr; - if (_unusedAttachments.size() > 0) { - model = _unusedAttachments.takeFirst(); - } else { - model = new Model(std::make_shared(), this); - } - model->init(); - _attachmentModels.append(model); - } - while (_attachmentModels.size() > attachmentData.size()) { - auto attachmentModel = _attachmentModels.back(); - _attachmentModels.pop_back(); - _attachmentsToRemove.push_back(attachmentModel); - } - */ - - /* - // update the urls - for (int i = 0; i < attachmentData.size(); i++) { - _attachmentModels[i]->setURL(attachmentData.at(i).modelURL); - _attachmentModels[i]->setSnapModelToCenter(true); - _attachmentModels[i]->setScaleToFit(true, getUniformScale() * _attachmentData.at(i).scale); - } - */ } diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 0093c22377..87990b941e 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -243,22 +243,6 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { if (_kinematicSetVelocity) { rigidBody->setLinearVelocity(glmToBullet(_linearVelocityTarget)); rigidBody->setAngularVelocity(glmToBullet(_angularVelocityTarget)); - /* - if (_previousSet) { - // smooth velocity over 2 frames - glm::vec3 positionalDelta = _positionalTarget - _previousPositionalTarget; - glm::vec3 positionalVelocity = - (positionalDelta + _previousPositionalDelta) / (deltaTimeStep + _previousDeltaTimeStep); - rigidBody->setLinearVelocity(glmToBullet(positionalVelocity)); - - if (_hand == "right") { - qDebug() << "AJT: rb vel = " << positionalVelocity.x << positionalVelocity.y << positionalVelocity.z; - } - - _previousPositionalDelta = positionalDelta; - _previousDeltaTimeStep = deltaTimeStep; - } - */ } btTransform worldTrans = rigidBody->getWorldTransform(); diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index aad61e4bea..9fdce3add4 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -113,7 +113,6 @@ void SixenseManager::deactivate() { _container->removeMenu(MENU_PATH); _inputDevice->_poseStateMap.clear(); - _inputDevice->_collectedSamples.clear(); if (_inputDevice->_deviceID != controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); @@ -158,7 +157,6 @@ void SixenseManager::InputDevice::update(float deltaTime, const controller::Inpu _axisStateMap.clear(); _buttonPressedMap.clear(); _poseStateMap.clear(); - _collectedSamples.clear(); } return; } @@ -209,13 +207,10 @@ void SixenseManager::InputDevice::update(float deltaTime, const controller::Inpu rawPoses[i] = controller::Pose(position, rotation, Vectors::ZERO, Vectors::ZERO); } else { _poseStateMap.clear(); - _collectedSamples.clear(); } } else { auto hand = left ? controller::StandardPoseChannel::LEFT_HAND : controller::StandardPoseChannel::RIGHT_HAND; _poseStateMap[hand] = controller::Pose(); - _collectedSamples[hand].first.clear(); - _collectedSamples[hand].second.clear(); } } @@ -481,29 +476,24 @@ void SixenseManager::InputDevice::handlePoseEvent(float deltaTime, const control glm::vec3 velocity(0.0f); glm::vec3 angularVelocity(0.0f); - if (prevPose.isValid() && deltaTime > std::numeric_limits::epsilon()) { - auto& samples = _collectedSamples[hand]; - - velocity = (pos - prevPose.getTranslation()) / deltaTime; - samples.first.addSample(velocity); - velocity = samples.first.average; - - auto deltaRot = glm::normalize(rot * glm::conjugate(prevPose.getRotation())); - auto axis = glm::axis(deltaRot); - auto speed = glm::angle(deltaRot) / deltaTime; - assert(!glm::isnan(speed)); - angularVelocity = speed * axis; - samples.second.addSample(angularVelocity); - angularVelocity = samples.second.average; - } else if (!prevPose.isValid()) { - _collectedSamples[hand].first.clear(); - _collectedSamples[hand].second.clear(); - } + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; // transform pose into avatar frame. - glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; - auto avatarPose = controller::Pose(pos, rot, velocity, angularVelocity).transform(controllerToAvatar); - _poseStateMap[hand] = avatarPose; + auto nextPose = controller::Pose(pos, rot, velocity, angularVelocity).transform(controllerToAvatar); + + if (prevPose.isValid() && (deltaTime > std::numeric_limits::epsilon())) { + nextPose.velocity = (nextPose.getTranslation() - prevPose.getTranslation()) / deltaTime; + + glm::quat deltaRotation = nextPose.getRotation() * glm::inverse(prevPose.getRotation()); + float rotationAngle = glm::angle(deltaRotation); + if (rotationAngle > EPSILON) { + nextPose.angularVelocity = glm::normalize(glm::axis(deltaRotation)); + nextPose.angularVelocity *= (rotationAngle / deltaTime); + } + + } + _poseStateMap[hand] = nextPose; + #endif // HAVE_SIXENSE } diff --git a/plugins/hifiSixense/src/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h index fc74b83532..5106c87836 100644 --- a/plugins/hifiSixense/src/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -52,11 +52,6 @@ private: static const glm::vec3 DEFAULT_AVATAR_POSITION; static const float CONTROLLER_THRESHOLD; - template - using SampleAverage = MovingAverage; - using Samples = std::pair, SampleAverage>; - using MovingAverageMap = std::map; - class InputDevice : public controller::InputDevice { public: InputDevice() : controller::InputDevice("Hydra") {} @@ -75,8 +70,6 @@ private: friend class SixenseManager; - MovingAverageMap _collectedSamples; - int _calibrationState { CALIBRATION_STATE_IDLE }; // these are calibration results glm::vec3 _avatarPosition { DEFAULT_AVATAR_POSITION }; // in hydra-frame From 86bb1b1ed8788222a83f629d41f2c19e86603862 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 17:44:11 +1300 Subject: [PATCH 071/114] Make copy of TextEdit control for restyling --- .../resources/qml/controls-uit/TextEdit.qml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 interface/resources/qml/controls-uit/TextEdit.qml diff --git a/interface/resources/qml/controls-uit/TextEdit.qml b/interface/resources/qml/controls-uit/TextEdit.qml new file mode 100644 index 0000000000..d6d0c60af3 --- /dev/null +++ b/interface/resources/qml/controls-uit/TextEdit.qml @@ -0,0 +1,18 @@ +// +// TextEdit.qml +// +// Created by Bradley Austin Davis on 24 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.3 as Original +import "../styles" + +Original.TextEdit { + HifiConstants { id: hifi } + font.family: hifi.fonts.fontFamily + font.pixelSize: hifi.fonts.pixelSize +} From aa32c1f1af21d003b263a079507202fffc7ab105 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 17:54:02 +1300 Subject: [PATCH 072/114] Restyle modal message dialog content --- .../resources/qml/controls-uit/TextEdit.qml | 19 ++++++--- .../resources/qml/dialogs/MessageDialog.qml | 40 ++++++++++++++----- .../messageDialog/MessageDialogButton.qml | 13 ++++++ .../qml/styles-uit/HifiConstants.qml | 1 + .../resources/qml/windows-uit/ModalFrame.qml | 2 +- 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/controls-uit/TextEdit.qml b/interface/resources/qml/controls-uit/TextEdit.qml index d6d0c60af3..5edc65a6e5 100644 --- a/interface/resources/qml/controls-uit/TextEdit.qml +++ b/interface/resources/qml/controls-uit/TextEdit.qml @@ -8,11 +8,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -import QtQuick 2.3 as Original -import "../styles" +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "../styles-uit" -Original.TextEdit { - HifiConstants { id: hifi } - font.family: hifi.fonts.fontFamily - font.pixelSize: hifi.fonts.pixelSize +TextEdit { + + property real size: 32 + + FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; } + font.family: ralewaySemibold.name + font.pointSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft } diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index 8524b5ce75..bac13c5403 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -18,7 +18,6 @@ import "../windows-uit" import "messageDialog" -// FIXME respect default button functionality ModalWindow { id: root HifiConstants { id: hifi } @@ -85,12 +84,15 @@ ModalWindow { readonly property real outerSpacing: hifi.dimensions.contentSpacing.y readonly property int minWidth: 480 readonly property int maxWdith: 1280 - readonly property int minHeight: 160 + readonly property int minHeight: 120 readonly property int maxHeight: 720 function resize() { var targetWidth = mainTextContainer.width - var targetHeight = mainTextContainer.implicitHeight + informativeTextContainer.implicitHeight + d.spacing * 8 + buttons.height + details.height + var targetHeight = mainTextContainer.height + 4 * hifi.dimensions.contentSpacing.y + + (informativeTextContainer.text != "" ? informativeTextContainer.contentHeight + hifi.dimensions.contentSpacing.y : 0) + + buttons.height + + (content.state === "expanded" ? details.implicitHeight + hifi.dimensions.contentSpacing.y : 0) root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth) root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight) } @@ -103,8 +105,8 @@ ModalWindow { size: hifi.fontSizes.menuItem color: hifi.colors.baseGrayHighlight anchors { - left: parent.left; top: parent.top; + left: parent.left; margins: 0 topMargin: hifi.dimensions.contentSpacing.y } @@ -112,12 +114,19 @@ ModalWindow { lineHeightMode: Text.ProportionalHeight } - Text { + RalewaySemibold { id: informativeTextContainer onHeightChanged: d.resize(); onWidthChanged: d.resize(); wrapMode: Text.WordWrap - font.pointSize: 11 - anchors { top: mainTextContainer.bottom; right: parent.right; left: parent.left; margins: d.spacing * 2 } + size: hifi.fontSizes.menuItem + color: hifi.colors.baseGrayHighlight + anchors { + top: mainTextContainer.bottom; + left: parent.left; + right: parent.right; + margins: 0 + topMargin: text != "" ? hifi.dimensions.contentSpacing.y : 0 + } } Flow { @@ -147,8 +156,8 @@ ModalWindow { Button { id: moreButton text: qsTr("Show Details...") - onClicked: { content.state = (content.state === "" ? "expanded" : "") - } + width: 160 + onClicked: { content.state = (content.state === "" ? "expanded" : "") } visible: detailedText && detailedText.length > 0 } MessageDialogButton { dialog: root; text: qsTr("Help"); button: OriginalDialogs.StandardButton.Help; } @@ -157,10 +166,16 @@ ModalWindow { Item { id: details width: parent.width - implicitHeight: detailedText.implicitHeight + root.spacing + implicitHeight: detailedText.implicitHeight height: 0 clip: true - anchors { bottom: parent.bottom; left: parent.left; right: parent.right; margins: d.spacing * 2 } + anchors { + top: buttons.bottom + left: parent.left; + right: parent.right; + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } Flickable { id: flickable contentHeight: detailedText.height @@ -169,10 +184,13 @@ ModalWindow { anchors.bottomMargin: root.outerSpacing TextEdit { id: detailedText + size: hifi.fontSizes.menuItem + color: hifi.colors.baseGrayHighlight width: details.width wrapMode: Text.WordWrap readOnly: true selectByMouse: true + anchors.margins: 0 } } } diff --git a/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml b/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml index 2bcb3d1f29..b7ff9354eb 100644 --- a/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml +++ b/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml @@ -1,11 +1,24 @@ +// +// MessageDialogButton.qml +// +// Created by Bradley Austin Davis on 29 Jan 2016 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 +import "../../controls-uit" + Button { property var dialog; property int button: StandardButton.NoButton; + color: dialog.defaultButton === button ? hifi.buttons.blue : hifi.buttons.white focus: dialog.defaultButton === button onClicked: dialog.click(button) visible: dialog.buttons & button diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index b18a4498bf..466feb88d5 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -42,6 +42,7 @@ Item { readonly property color baseGrayShadow60: "#99252525" readonly property color baseGrayHighlight40: "#66575757" readonly property color baseGrayHighlight15: "#26575757" + readonly property color lightGrayText80: "#ccafafaf" readonly property color faintGray50: "#80e3e3e3" // Other colors diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index 7cf3af86ec..b76996a873 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -50,7 +50,7 @@ Frame { size: 30 color: hifi.colors.lightGrayText visible: text != "" - y: -hifi.dimensions.modalDialogTitleHeight + y: -hifi.dimensions.modalDialogTitleHeight - 3 anchors.left: parent.left } RalewayRegular { From 49c229897f53a874b59ac63a997623c7190920e8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 17:55:36 +1300 Subject: [PATCH 073/114] Give the "change avatar?" confirmation dialog a default action --- interface/src/Application.cpp | 2 +- tests/ui/qml/main.qml | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7c1fd9279b..0268bc52a4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4315,7 +4315,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { case FSTReader::HEAD_AND_BODY_MODEL: ok = QMessageBox::Ok == OffscreenUi::question("Set Avatar", "Would you like to use '" + modelName + "' for your avatar?", - QMessageBox::Ok | QMessageBox::Cancel); + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); break; default: diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index d5ef2584f5..0bdfdb64b9 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -87,11 +87,13 @@ ApplicationWindow { var messageBox = desktop.messageBox({ title: "Set Avatar", text: "Would you like to use 'Albert' for your avatar?", - icon: OriginalDialogs.StandardIcon.Question, + icon: OriginalDialogs.StandardIcon.Question, // Test question icon //icon: OriginalDialogs.StandardIcon.Information, // Test informaton icon //icon: OriginalDialogs.StandardIcon.Warning, // Test warning icon //icon: OriginalDialogs.StandardIcon.Critical, // Test critical icon - buttons: OriginalDialogs.StandardButton.Ok + OriginalDialogs.StandardButton.Cancel + //icon: OriginalDialogs.StandardIcon.NoIcon, // Test no icon + buttons: OriginalDialogs.StandardButton.Ok + OriginalDialogs.StandardButton.Cancel, + defaultButton: OriginalDialogs.StandardButton.Ok }); messageBox.selected.connect(function(button) { console.log("You clicked " + button) From b09a20187abaa3c9a7a26adb31d4b1460f1604c6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 17:57:21 +1300 Subject: [PATCH 074/114] Reverse order buttons appear in to make more consistent with Windows --- .../resources/qml/dialogs/MessageDialog.qml | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index bac13c5403..f31b5cf41d 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -135,24 +135,30 @@ ModalWindow { spacing: d.spacing onHeightChanged: d.resize(); onWidthChanged: d.resize(); layoutDirection: Qt.RightToLeft - anchors { bottom: details.top; right: parent.right; margins: d.spacing * 2; bottomMargin: 0 } - MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; } - MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; } - MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; } - MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; } - MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; } - MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; } - MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; } - MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; } - MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; } - MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; } - MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; } - MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; } - MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; } - MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; } - MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; } - MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; } + anchors { + top: informativeTextContainer.bottom + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; } + MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; } + MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; } + MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; } + MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; } + MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; } + MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; } + MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; } + MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; } + MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; } + MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; } + MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; } + MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; } + MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; } + MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; } + MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; } + MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; } + Button { id: moreButton text: qsTr("Show Details...") From 0e3cbd2930ec226c32db92e8b7569eb7e61bdc30 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 18:05:49 +1300 Subject: [PATCH 075/114] Tidying --- interface/resources/qml/styles-uit/HifiConstants.qml | 2 +- interface/resources/qml/windows-uit/Window.qml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 466feb88d5..da904d5edb 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -79,7 +79,7 @@ Item { readonly property real tablePadding: 12 readonly property real tableRowHeight: largeScreen ? 26 : 23 readonly property real modalDialogMargin: 50 - readonly property real modalDialogTitleHeight: 40 // DJRTODO: Use + readonly property real modalDialogTitleHeight: 40 } Item { diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 8a1cd44c8b..2bc0175bf2 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -58,6 +58,8 @@ Fadable { // The content to place inside the window, determined by the client default property var content + function setDefaultFocus() {} // Default function; can be overridden by dialogs. + property var rectifier: Timer { property bool executing: false; interval: 100 From 6bf377aac84c46a10f81c9dd9b3ff1c0daba316f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 18:16:32 +1300 Subject: [PATCH 076/114] Move FontAwesome.qml to be with other font files --- .../resources/qml/{controls-uit => styles-uit}/FontAwesome.qml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename interface/resources/qml/{controls-uit => styles-uit}/FontAwesome.qml (100%) diff --git a/interface/resources/qml/controls-uit/FontAwesome.qml b/interface/resources/qml/styles-uit/FontAwesome.qml similarity index 100% rename from interface/resources/qml/controls-uit/FontAwesome.qml rename to interface/resources/qml/styles-uit/FontAwesome.qml From 9583b801f63cc22377a00c123b24c2dc5f5eadca Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 19:57:13 +1300 Subject: [PATCH 077/114] Increase size of resize handle --- interface/resources/qml/windows-uit/Frame.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 7f9e927d29..92ba2d4108 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -26,7 +26,7 @@ Item { readonly property int frameMarginLeft: frameMargin readonly property int frameMarginRight: frameMargin readonly property int frameMarginTop: 2 * frameMargin + iconSize - readonly property int frameMarginBottom: iconSize + 6 + readonly property int frameMarginBottom: iconSize + 11 // Frames always fill their parents, but their decorations may extend // beyond the window via negative margin sizes @@ -124,10 +124,10 @@ Item { } HiFiGlyphs { visible: sizeDrag.enabled - x: -5 // Move a little to visually align - y: -3 // "" + x: -11 // Move a little to visually align + y: -4 // "" text: "A" - size: iconSize + 4 + size: iconSize + 10 color: sizeDrag.containsMouse || sizeDrag.pressed ? hifi.colors.white : hifi.colors.white50 } } From 67b6cafc92abd1e75f1608a28039eac85c3e4893 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 20:05:16 +1300 Subject: [PATCH 078/114] Use placeholder text for Filter field instead of separate label Also fixes color of separate label if that is reinstated at some time. --- interface/resources/qml/controls-uit/TextField.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index 76858ad83d..6714cb94d5 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -24,6 +24,7 @@ TextField { font.family: firaSansSemiBold.name font.pointSize: hifi.fontSizes.textFieldInput height: implicitHeight + 4 // Make surrounding box higher so that highlight is vertically centered. + placeholderText: textField.label // Instead of separate label (see below). style: TextFieldStyle { textColor: textField.colorScheme == hifi.colorSchemes.light @@ -43,13 +44,16 @@ TextField { padding.right: hifi.dimensions.textPadding } + /* + // Separate label instead of placeholderText. RalewaySemibold { text: textField.label size: hifi.fontSizes.inputLabel - color: hifi.colors.lightGray + color: hifi.colors.lightGrayText anchors.left: parent.left anchors.bottom: parent.top anchors.bottomMargin: 4 visible: label != "" } + */ } From e30135a89d9c2f40cf132328c4abe21caffbf40a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Feb 2016 20:05:45 +1300 Subject: [PATCH 079/114] Increase height of dialog to avoid scrollbars --- interface/resources/qml/hifi/dialogs/RunningScripts.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 55b8946805..8ca410d90e 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -24,7 +24,7 @@ Window { resizable: true destroyOnInvisible: true x: 40; y: 40 - implicitWidth: 384; implicitHeight: 640 + implicitWidth: 384; implicitHeight: 650 minSize: Qt.vector2d(200, 300) HifiConstants { id: hifi } From 749f4478ab174711cdde95d32384c45cb2a203f1 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 23 Feb 2016 09:33:37 -0800 Subject: [PATCH 080/114] Fixed bug with parsing numbers for editjs --- examples/html/entityProperties.html | 2 +- examples/particle_explorer/particleExplorerTool.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 67ed261b5d..e3ad77870d 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -75,7 +75,7 @@ function createEmitNumberPropertyUpdateFunction(propertyName) { return function() { EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":' + Number(this.value.toFixed(4)) + '}}' + '{ "type":"update", "properties":{"' + propertyName + '":' + parseFloat(this.value).toFixed(4) + '}}' ); }; } diff --git a/examples/particle_explorer/particleExplorerTool.js b/examples/particle_explorer/particleExplorerTool.js index 20dfa6f1ba..007eb717ec 100644 --- a/examples/particle_explorer/particleExplorerTool.js +++ b/examples/particle_explorer/particleExplorerTool.js @@ -32,11 +32,9 @@ ParticleExplorerTool = function() { that.destroyWebView = function() { if (!that.webView) { - print("EBL CAN'ZT CLOSE WEB VIEW- IT DOESNT EXISTS!") return; } - print("EBL CLOSING WEB VIEW") that.webView.close(); that.webView = null; that.activeParticleEntity = 0; From 2db25690f1720b1e06286c04b2857aebd6544e53 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 23 Feb 2016 10:14:44 -0800 Subject: [PATCH 081/114] detect when mouse is over QML overlays or 2D JS Overlays --- interface/resources/qml/Stats.qml | 6 ++++++ interface/resources/qml/desktop/Desktop.qml | 1 + interface/resources/qml/desktop/FocusHack.qml | 1 + interface/resources/qml/hifi/Desktop.qml | 16 ++++++++++++++++ .../resources/qml/menus/MenuMouseHandler.qml | 2 ++ interface/src/Application.cpp | 2 ++ interface/src/ui/ApplicationCompositor.cpp | 2 +- interface/src/ui/ApplicationCompositor.h | 15 ++++++++------- 8 files changed, 37 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index d2f78191ea..660152ca0c 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -5,6 +5,8 @@ import QtQuick.Controls 1.2 Item { anchors.fill: parent anchors.leftMargin: 300 + objectName: "StatsItem" + Hifi.Stats { id: root objectName: "Stats" @@ -27,6 +29,7 @@ Item { MouseArea { anchors.fill: parent onClicked: { root.expanded = !root.expanded; } + hoverEnabled: true } Column { @@ -83,6 +86,7 @@ Item { MouseArea { anchors.fill: parent onClicked: { root.expanded = !root.expanded; } + hoverEnabled: true } Column { id: pingCol @@ -123,6 +127,7 @@ Item { MouseArea { anchors.fill: parent onClicked: { root.expanded = !root.expanded; } + hoverEnabled: true } Column { id: geoCol @@ -172,6 +177,7 @@ Item { MouseArea { anchors.fill: parent onClicked: { root.expanded = !root.expanded; } + hoverEnabled: true } Column { id: octreeCol diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 0286c45ac3..823b5cb923 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -304,6 +304,7 @@ FocusScope { Rectangle { id: focusDebugger; + objectName: "focusDebugger" z: 9999; visible: false; color: "red" ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 } } diff --git a/interface/resources/qml/desktop/FocusHack.qml b/interface/resources/qml/desktop/FocusHack.qml index 7514705983..14f2c62099 100644 --- a/interface/resources/qml/desktop/FocusHack.qml +++ b/interface/resources/qml/desktop/FocusHack.qml @@ -2,6 +2,7 @@ import QtQuick 2.5 FocusScope { id: root + objectName: "FocusHack" TextInput { id: textInput; diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 5227d3cb2e..dd9038e4b4 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -8,6 +8,22 @@ import ".." Desktop { id: desktop + MouseArea { + anchors.fill: parent + hoverEnabled: true + propagateComposedEvents: true + scrollGestureEnabled: false // we don't need/want these + onEntered: ApplicationCompositor.reticleOverDesktop = true + onExited: ApplicationCompositor.reticleOverDesktop = false + onClicked: mouse.accepted = false + onCanceled: mouse.accepted = false + onDoubleClicked: mouse.accepted = false + onPressed: mouse.accepted = false + onReleased: mouse.accepted = false + onWheel: mouse.accepted = false + onPositionChanged: mouse.accepted = false + } + Component.onCompleted: { WebEngine.settings.javascriptCanOpenWindows = true; WebEngine.settings.javascriptCanAccessClipboard = false; diff --git a/interface/resources/qml/menus/MenuMouseHandler.qml b/interface/resources/qml/menus/MenuMouseHandler.qml index bb2cc7d459..6f507dd445 100644 --- a/interface/resources/qml/menus/MenuMouseHandler.qml +++ b/interface/resources/qml/menus/MenuMouseHandler.qml @@ -6,9 +6,11 @@ import "." Item { id: root anchors.fill: parent + objectName: "MouseMenuHandlerItem" MouseArea { id: menuRoot; + objectName: "MouseMenuHandlerMouseArea" anchors.fill: parent enabled: d.topMenu !== null onClicked: { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64cd586e13..5c1f164fdb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1259,6 +1259,8 @@ void Application::initializeUi() { rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); rootContext->setContextProperty("Reticle", _compositor.getReticleInterface()); + rootContext->setContextProperty("ApplicationCompositor", &_compositor); + _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { QPointF result = pt; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4fd810e22f..5c6e4c9819 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -395,7 +395,7 @@ bool ApplicationCompositor::handleRealMouseMoveEvent(bool sendFakeEvent) { return false; // let the caller know to process the event } -glm::vec2 ApplicationCompositor::getReticlePosition() { +glm::vec2 ApplicationCompositor::getReticlePosition() const { if (qApp->isHMDMode()) { QMutexLocker locker(&_reticleLock); return _reticlePositionInHMD; diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 3ee7c53f1b..7bdb97727f 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -47,6 +47,7 @@ class ApplicationCompositor : public QObject { Q_OBJECT Q_PROPERTY(float alpha READ getAlpha WRITE setAlpha) + Q_PROPERTY(bool reticleOverDesktop READ getReticleOverDesktop WRITE setReticleOverDesktop) public: ApplicationCompositor(); ~ApplicationCompositor(); @@ -84,14 +85,14 @@ public: float getAlpha() const { return _alpha; } void setAlpha(float alpha) { _alpha = alpha; } - bool getReticleVisible() { return _reticleVisible; } + bool getReticleVisible() const { return _reticleVisible; } void setReticleVisible(bool visible) { _reticleVisible = visible; } - float getReticleDepth() { return _reticleDepth; } + float getReticleDepth() const { return _reticleDepth; } void setReticleDepth(float depth) { _reticleDepth = depth; } void resetReticleDepth() { _reticleDepth = DEFAULT_RETICLE_DEPTH; } - glm::vec2 getReticlePosition(); + glm::vec2 getReticlePosition() const; void setReticlePosition(glm::vec2 position, bool sendFakeEvent = true); glm::vec2 getReticleMaximumPosition() const; @@ -106,9 +107,11 @@ public: bool shouldCaptureMouse() const; /// if the reticle is pointing to a system overlay (a dialog box for example) then the function returns true otherwise false - bool isReticlePointingAtSystemOverlay() const { return _reticleOverQml; } + bool getReticleOverDesktop() const { return _isOverDesktop; } + void setReticleOverDesktop(bool value) { _isOverDesktop = value; } private: + bool _isOverDesktop { true }; void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov); void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); @@ -176,6 +179,7 @@ public: ReticleInterface(ApplicationCompositor* outer) : QObject(outer), _compositor(outer) {} Q_INVOKABLE bool isMouseCaptured() { return _compositor->shouldCaptureMouse(); } + Q_INVOKABLE bool isPointingAtSystemOverlay() { return !_compositor->getReticleOverDesktop(); } Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); } Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); } @@ -188,9 +192,6 @@ public: Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); } - Q_INVOKABLE bool isPointingAtSystemOverlay() { return _compositor->isReticlePointingAtSystemOverlay(); } - - private: ApplicationCompositor* _compositor; }; From 7c9022fb3e17d15b8976577c49ef0ef8edcfa3ad Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Feb 2016 10:40:47 -0800 Subject: [PATCH 082/114] Fix model overlay scaling --- interface/src/ui/overlays/ModelOverlay.cpp | 33 +++++++++------------- libraries/render-utils/src/Model.cpp | 10 ++++++- libraries/render-utils/src/Model.h | 2 +- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 3738f829f3..a06a9b0605 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -45,7 +45,7 @@ void ModelOverlay::update(float deltatime) { _updateModel = false; _model.setSnapModelToCenter(true); - _model.setScale(getScale()); + _model.setScale(getDimensions()); _model.setRotation(getRotation()); _model.setTranslation(getPosition()); _model.setURL(_url); @@ -82,22 +82,6 @@ void ModelOverlay::render(RenderArgs* args) { if (!_visible) { return; } - - /* - if (_model.isActive()) { - if (_model.isRenderable()) { - float glowLevel = getGlowLevel(); - Glower* glower = NULL; - if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); - } - _model.render(args, getAlpha()); - if (glower) { - delete glower; - } - } - } - */ } void ModelOverlay::setProperties(const QScriptValue &properties) { @@ -107,10 +91,19 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { Volume3DOverlay::setProperties(properties); - if (position != getPosition() || rotation != getRotation() || scale != getDimensions()) { - _model.setScaleToFit(true, getScale()); + if (position != getPosition() || rotation != getRotation()) { _updateModel = true; } + + if (scale != getDimensions()) { + auto newScale = getDimensions(); + if (newScale.x <= 0 || newScale.y <= 0 || newScale.z <= 0) { + setDimensions(scale); + } else { + _model.setScaleToFit(true, getDimensions()); + _updateModel = true; + } + } QScriptValue urlValue = properties.property("url"); if (urlValue.isValid() && urlValue.isString()) { @@ -140,7 +133,7 @@ QScriptValue ModelOverlay::getProperty(const QString& property) { if (property == "url") { return _url.toString(); } - if (property == "dimensions") { + if (property == "dimensions" || property == "scale" || property == "size") { return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions()); } if (property == "textures") { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3b741ac734..c29c37140e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -43,7 +43,7 @@ Model::Model(RigPointer rig, QObject* parent) : _rotation(), _scale(1.0f, 1.0f, 1.0f), _scaleToFit(false), - _scaleToFitDimensions(0.0f), + _scaleToFitDimensions(1.0f), _scaledToFit(false), _snapModelToRegistrationPoint(false), _snappedToRegistrationPoint(false), @@ -909,6 +909,14 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension, bool forceRes } } +glm::vec3 Model::getScaleToFitDimensions() const { + if (_scaleToFitDimensions.y == FAKE_DIMENSION_PLACEHOLDER && + _scaleToFitDimensions.z == FAKE_DIMENSION_PLACEHOLDER) { + return glm::vec3(_scaleToFitDimensions.x); + } + return _scaleToFitDimensions; +} + void Model::scaleToFit() { // If our _scaleToFitDimensions.y/z are FAKE_DIMENSION_PLACEHOLDER then it means our // user asked to scale us in a fixed aspect ratio to a single largest dimension, but diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 2c138fa7be..424eed1e66 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -197,7 +197,7 @@ public: /// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit - const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to + glm::vec3 getScaleToFitDimensions() const; /// the dimensions model is scaled to, including inferred y/z void setCauterizeBones(bool flag) { _cauterizeBones = flag; } bool getCauterizeBones() const { return _cauterizeBones; } From 1c53f9bc877f729c3d4783f3110160b0f42e73a7 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 23 Feb 2016 10:40:50 -0800 Subject: [PATCH 083/114] Fix the cleanup of the render::Item::ID in the EntityITem Rendereable wich were often not invalidated after beeing removed from the scene. THis caused a bug with particule system when beeing added /removed / updated quickly --- interface/src/avatar/Avatar.cpp | 3 ++- interface/src/ui/overlays/Overlay.cpp | 2 +- interface/src/ui/overlays/Overlays.cpp | 2 +- libraries/entities-renderer/src/RenderableEntityItem.h | 3 ++- .../entities-renderer/src/RenderableModelEntityItem.cpp | 1 + .../src/RenderableParticleEffectEntityItem.cpp | 6 ++++-- .../entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 1 + .../entities-renderer/src/RenderableZoneEntityItem.cpp | 3 ++- libraries/render/src/render/Item.h | 4 ++++ 9 files changed, 18 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f62eb5a070..efa6f6004b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -315,6 +315,7 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemID); + render::Item::clearID(_renderItemID); _skeletonModel.removeFromScene(scene, pendingChanges); getHead()->getFaceModel().removeFromScene(scene, pendingChanges); for (auto& attachmentModel : _attachmentModels) { @@ -323,7 +324,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr>(_renderItemID, [](render::Payload& p) {}); } } diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 1e3390e49f..64b5e2aedf 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -229,6 +229,6 @@ bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemID); - _renderItemID = render::Item::INVALID_ITEM_ID; + render::Item::clearID(_renderItemID); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index b53a5a0d05..c2b769d146 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -94,7 +94,7 @@ void Overlays::cleanupOverlaysToDelete() { Overlay::Pointer overlay = _overlaysToDelete.takeLast(); auto itemID = overlay->getRenderItemID(); - if (itemID != render::Item::INVALID_ITEM_ID) { + if (render::Item::isValidID(itemID)) { overlay->removeFromScene(overlay, scene, pendingChanges); } } while (!_overlaysToDelete.isEmpty()); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 7b3ea8edaa..30d3f9d83c 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -66,10 +66,11 @@ public: void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myItem); + render::Item::clearID(_myItem); } void notifyChanged() { - if (_myItem == render::Item::INVALID_ITEM_ID) { + if (!render::Item::isValidID(_myItem)) { return; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 89f819b0da..e3870705c9 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -251,6 +251,7 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myMetaItem); + render::Item::clearID(_myMetaItem); if (_model) { _model->removeFromScene(scene, pendingChanges); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e62dc82988..4d8eebf05b 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -179,6 +179,7 @@ void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemId); _scene = nullptr; + render::Item::clearID(_renderItemId); }; void RenderableParticleEffectEntityItem::update(const quint64& now) { @@ -199,7 +200,8 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { } void RenderableParticleEffectEntityItem::updateRenderItem() { - if (!_scene) { + // this 2 tests are synonyms for this class, but we would like to get rid of the _scene pointer ultimately + if (!_scene || !render::Item::isValidID(_renderItemId)) { return; } if (!getVisible()) { @@ -312,7 +314,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { } void RenderableParticleEffectEntityItem::notifyBoundChanged() { - if (_renderItemId == render::Item::INVALID_ITEM_ID) { + if (!render::Item::isValidID(_renderItemId)) { return; } render::PendingChanges pendingChanges; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 1029f3b3af..ef777df403 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -572,6 +572,7 @@ void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myItem); + render::Item::clearID(_myItem); } namespace render { diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 56771296db..44345ac0a2 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -230,6 +230,7 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myMetaItem); + render::Item::clearID(_myMetaItem); if (_model) { _model->removeFromScene(scene, pendingChanges); } @@ -237,7 +238,7 @@ void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shar void RenderableZoneEntityItem::notifyBoundChanged() { - if (_myMetaItem == render::Item::INVALID_ITEM_ID) { + if (!render::Item::isValidID(_myMetaItem)) { return; } render::PendingChanges pendingChanges; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 74c832a0c4..8aaaf07300 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -217,6 +217,10 @@ public: static const ID INVALID_ITEM_ID = 0; static const ItemCell INVALID_CELL = -1; + // Convenient function to clear an ID or check it s valid + static void clearID(ID& id) { id = INVALID_ITEM_ID; } + static bool isValidID(const ID id) { return id != INVALID_ITEM_ID; } + // Bound is the AABBox fully containing this item typedef AABox Bound; From 5d9ee84e6364a053c05275009fea50c98b69c7e2 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 23 Feb 2016 10:42:39 -0800 Subject: [PATCH 084/114] Extend the test for number of active injectors to apply to injector restarts. --- libraries/audio/src/AudioInjector.cpp | 8 ++++-- libraries/audio/src/AudioInjectorManager.cpp | 26 ++++++++++++++------ libraries/audio/src/AudioInjectorManager.h | 3 ++- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 157e973f5b..ad6b436d02 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -104,7 +104,9 @@ void AudioInjector::restart() { // reset state to start sending from beginning again _nextFrame = 0; - _frameTimer->invalidate(); + if (_frameTimer) { + _frameTimer->invalidate(); + } _hasSentFirstFrame = false; // check our state to decide if we need extra handling for the restart request @@ -122,7 +124,9 @@ void AudioInjector::restart() { injectLocally(); } else { // wake the AudioInjectorManager back up if it's stuck waiting - injectorManager->restartFinishedInjector(this); + if (!injectorManager->restartFinishedInjector(this)) { + _state = State::Finished; // we're not playing, so reset the state used by isPlaying. + } } } } diff --git a/libraries/audio/src/AudioInjectorManager.cpp b/libraries/audio/src/AudioInjectorManager.cpp index 032ad71145..0c060d30ad 100644 --- a/libraries/audio/src/AudioInjectorManager.cpp +++ b/libraries/audio/src/AudioInjectorManager.cpp @@ -129,6 +129,16 @@ void AudioInjectorManager::run() { static const int MAX_INJECTORS_PER_THREAD = 40; // calculated based on AudioInjector time to send frame, with sufficient padding +bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a lock. + if (_injectors.size() >= MAX_INJECTORS_PER_THREAD) { + qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of" + << MAX_INJECTORS_PER_THREAD << "current audio injectors."; + return true; + } + qDebug() << "current injectors:" << _injectors.size(); + return false; +} + bool AudioInjectorManager::threadInjector(AudioInjector* injector) { if (_shouldStop) { qDebug() << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down."; @@ -138,8 +148,9 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) { // guard the injectors vector with a mutex Lock lock(_injectorsMutex); - // check if we'll be able to thread this injector (do we have < max concurrent injectors) - if (_injectors.size() < MAX_INJECTORS_PER_THREAD) { + if (wouldExceedLimits()) { + return false; + } else { if (!_thread) { createThread(); } @@ -156,23 +167,22 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) { _injectorReady.notify_one(); return true; - } else { - // unable to thread this injector, at the max - qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of" - << MAX_INJECTORS_PER_THREAD << "current audio injectors."; - return false; } } -void AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) { +bool AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) { if (!_shouldStop) { // guard the injectors vector with a mutex Lock lock(_injectorsMutex); + if (wouldExceedLimits()) { + return false; + } // add the injector to the queue with a send timestamp of now _injectors.emplace(usecTimestampNow(), InjectorQPointer { injector }); // notify our wait condition so we can inject two frames for this injector immediately _injectorReady.notify_one(); } + return true; } diff --git a/libraries/audio/src/AudioInjectorManager.h b/libraries/audio/src/AudioInjectorManager.h index 91648fff39..de5537856e 100644 --- a/libraries/audio/src/AudioInjectorManager.h +++ b/libraries/audio/src/AudioInjectorManager.h @@ -50,8 +50,9 @@ private: using Lock = std::unique_lock; bool threadInjector(AudioInjector* injector); - void restartFinishedInjector(AudioInjector* injector); + bool restartFinishedInjector(AudioInjector* injector); void notifyInjectorReadyCondition() { _injectorReady.notify_one(); } + bool wouldExceedLimits(); AudioInjectorManager() {}; AudioInjectorManager(const AudioInjectorManager&) = delete; From 7e39cc7753a7cfc3d15a887ccc7350b60c0e399e Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 23 Feb 2016 10:53:33 -0800 Subject: [PATCH 085/114] clean up a bit the 2 globals RenderItem in APplication.cpp --- interface/src/Application.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 704940433a..89ec196fad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3773,8 +3773,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se // The pending changes collecting the changes here render::PendingChanges pendingChanges; + // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities // Background rendering decision - if (BackgroundRenderData::_item == 0) { + if (!render::Item::isValidID(BackgroundRenderData::_item)) { auto backgroundRenderData = make_shared(); auto backgroundRenderPayload = make_shared(backgroundRenderData); BackgroundRenderData::_item = _main3DScene->allocateID(); @@ -3799,8 +3800,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se } } + // FIXME: Move this out of here!, WorldBox should be driven by the entity content just like the other entities // Make sure the WorldBox is in the scene - if (WorldBoxRenderData::_item == 0) { + if (!render::Item::isValidID(WorldBoxRenderData::_item)) { auto worldBoxRenderData = make_shared(); auto worldBoxRenderPayload = make_shared(worldBoxRenderData); From 6a987391d2d0f46682e29c912b75256755b55695 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 23 Feb 2016 10:55:36 -0800 Subject: [PATCH 086/114] Remove debugging code. --- libraries/audio/src/AudioInjectorManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/audio/src/AudioInjectorManager.cpp b/libraries/audio/src/AudioInjectorManager.cpp index 0c060d30ad..b39da1c148 100644 --- a/libraries/audio/src/AudioInjectorManager.cpp +++ b/libraries/audio/src/AudioInjectorManager.cpp @@ -135,7 +135,6 @@ bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a << MAX_INJECTORS_PER_THREAD << "current audio injectors."; return true; } - qDebug() << "current injectors:" << _injectors.size(); return false; } From d3cdc5117f27be74ef52999b18adb672a3630e4b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 23 Feb 2016 11:01:57 -0800 Subject: [PATCH 087/114] clean up one more render::Item::isValid(ID) --- interface/src/ui/overlays/Overlays.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c2b769d146..2bc1286419 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -241,7 +241,7 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { render::ItemKey itemKey = render::payloadGetKey(thisOverlay); if (itemKey != oldItemKey) { auto itemID = thisOverlay->getRenderItemID(); - if (itemID != render::Item::INVALID_ITEM_ID) { + if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); render::PendingChanges pendingChanges; pendingChanges.resortItem(itemID, oldItemKey, itemKey); From 71262c3e646b462d11ea060fd886d04fdfaacbe5 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 23 Feb 2016 11:14:16 -0800 Subject: [PATCH 088/114] cleaner QML rejection of mouse messages --- interface/resources/qml/hifi/Desktop.qml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index dd9038e4b4..409c468878 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -15,13 +15,7 @@ Desktop { scrollGestureEnabled: false // we don't need/want these onEntered: ApplicationCompositor.reticleOverDesktop = true onExited: ApplicationCompositor.reticleOverDesktop = false - onClicked: mouse.accepted = false - onCanceled: mouse.accepted = false - onDoubleClicked: mouse.accepted = false - onPressed: mouse.accepted = false - onReleased: mouse.accepted = false - onWheel: mouse.accepted = false - onPositionChanged: mouse.accepted = false + acceptedButtons: Qt.NoButton } Component.onCompleted: { From a71a78b2d344a97cf53b43c166c69b5cea39b0cd Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 23 Feb 2016 11:22:24 -0800 Subject: [PATCH 089/114] add comments and license header to reticleDepth.js --- examples/depthReticle.js | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/examples/depthReticle.js b/examples/depthReticle.js index 4c93f714aa..a60e61d07c 100644 --- a/examples/depthReticle.js +++ b/examples/depthReticle.js @@ -1,6 +1,19 @@ +// depthReticle.js +// examples +// +// Created by Brad Hefta-Gaub on 2/23/16. +// Copyright 2016 High Fidelity, Inc. +// +// When used in HMD, this script will make the reticle depth track to any clickable item in view. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var APPARENT_2D_OVERLAY_DEPTH = 1.0; +var APPARENT_MAXIMUM_DEPTH = 100.0; // this is a depth at which things all seem sufficiently distant var lastDepthCheckTime = 0; -// Do some stuff regularly, like check for placement of various overlays Script.update.connect(function(deltaTime) { var TIME_BETWEEN_DEPTH_CHECKS = 100; var timeSinceLastDepthCheck = Date.now() - lastDepthCheckTime; @@ -9,23 +22,25 @@ Script.update.connect(function(deltaTime) { // first check the 2D Overlays if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(reticlePosition)) { - print("intersecting with 2D overlay..."); - Reticle.setDepth(1.0); + Reticle.setDepth(APPARENT_2D_OVERLAY_DEPTH); } else { var pickRay = Camera.computePickRay(reticlePosition.x, reticlePosition.y); + + // Then check the 3D overlays var result = Overlays.findRayIntersection(pickRay); if (!result.intersects) { + // finally check the entities result = Entities.findRayIntersection(pickRay, true); } + + // If either the overlays or entities intersect, then set the reticle depth to + // the distance of intersection if (result.intersects) { - // + JSON.stringify(result) - print("something hovered!! result.distance:" +result.distance); - Vec3.print("something hovered!! result.intersection:", result.intersection); Reticle.setDepth(result.distance); } else { - Reticle.setDepth(100.0); - print("NO INTERSECTION..."); + // if nothing intersects... set the depth to some sufficiently large depth + Reticle.setDepth(APPARENT_MAXIMUM_DEPTH); } } } From e544275500a10cce28427b8d088fb0df0a19fad6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 23 Feb 2016 12:07:14 -0800 Subject: [PATCH 090/114] Physics: extrapolate kinematic objects as well as dynamic ones. --- libraries/physics/src/EntityMotionState.cpp | 2 +- .../physics/src/ThreadSafeDynamicsWorld.cpp | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 8c0dab98db..ff7d550175 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,7 +191,7 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { } // This callback is invoked by the physics simulation at the end of each simulation step... -// iff the corresponding RigidBody is DYNAMIC and has moved. +// iff the corresponding RigidBody is active. void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { if (!_entity) { return; diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index b6f3487f1a..17b2b08d4d 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -96,19 +96,26 @@ void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { ///@todo: add 'dirty' flag //if (body->getActivationState() != ISLAND_SLEEPING) { + btTransform bodyTransform; + btVector3 bodyLinearVelocity, bodyAngularVelocity; if (body->isKinematicObject()) { ObjectMotionState* objectMotionState = static_cast(body->getMotionState()); if (objectMotionState->hasInternalKinematicChanges()) { objectMotionState->clearInternalKinematicChanges(); - body->getMotionState()->setWorldTransform(body->getWorldTransform()); } - return; + bodyTransform = body->getWorldTransform(); + bodyLinearVelocity = body->getLinearVelocity(); + bodyAngularVelocity = body->getAngularVelocity(); + } else { + bodyTransform = body->getInterpolationWorldTransform(); + bodyLinearVelocity = body->getInterpolationLinearVelocity(); + bodyAngularVelocity = body->getInterpolationAngularVelocity(); } + + // integrate the object foward to cover the time in-between fixed time steps. + btScalar dt = (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime * body->getHitFraction(); btTransform interpolatedTransform; - btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(), - (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(), - interpolatedTransform); + btTransformUtil::integrateTransform(bodyTransform, bodyLinearVelocity, bodyAngularVelocity, dt, interpolatedTransform); body->getMotionState()->setWorldTransform(interpolatedTransform); } } From 7804ee22d416b2080201f9c786800a4d76ff2af0 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Feb 2016 12:14:00 -0800 Subject: [PATCH 091/114] Consolidate stats for opaque/transparent/other --- interface/resources/qml/Stats.qml | 29 +++++------------ interface/src/ui/Stats.cpp | 20 ++++-------- interface/src/ui/Stats.h | 32 +++++-------------- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render/src/render/CullTask.h | 2 +- libraries/shared/src/RenderArgs.h | 23 ++++++------- 7 files changed, 34 insertions(+), 76 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index d2f78191ea..78b0411f67 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -186,42 +186,29 @@ Item { color: root.fontColor; font.pixelSize: root.fontSize visible: root.expanded; - text: "\tItems Rendered Opaque: " + root.opaqueRendered + - " / Translucent: " + root.translucentRendered + - " / Shadow: " + root.shadowRendered + - " / Other: " + root.otherRendered; + text: "Items rendered / considered: " + + root.itemRendered + " / " + root.itemConsidered; } Text { color: root.fontColor; font.pixelSize: root.fontSize visible: root.expanded; - text: "\tOpaque considered: " + root.opaqueConsidered + - " / Out of view: " + root.opaqueOutOfView + - " / Too small: " + root.opaqueTooSmall; + text: " out of view: " + root.itemOutOfView + + " too small: " + root.itemTooSmall; } Text { color: root.fontColor; font.pixelSize: root.fontSize visible: root.expanded; - text: "\tShadow considered: " + root.shadowConsidered + - " / Out of view: " + root.shadowOutOfView + - " / Too small: " + root.shadowTooSmall; + text: "Shadows rendered / considered: " + + root.shadowRendered + " / " + root.shadowConsidered; } Text { color: root.fontColor; font.pixelSize: root.fontSize visible: root.expanded; - text: "\tTranslucent considered: " + root.translucentConsidered + - " / Out of view: " + root.translucentOutOfView + - " / Too small: " + root.translucentTooSmall; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded; - text: "\tOther considered: " + root.otherConsidered + - " / Out of view: " + root.otherOutOfView + - " / Too small: " + root.otherTooSmall; + text: " out of view: " + root.shadowOutOfView + + " too small: " + root.shadowTooSmall; } Text { color: root.fontColor; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index c9c4c68dc9..e566f513ac 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -342,22 +342,14 @@ void Stats::setRenderDetails(const RenderDetails& details) { STAT_UPDATE(triangles, details._trianglesRendered); STAT_UPDATE(materialSwitches, details._materialSwitches); if (_expanded) { - STAT_UPDATE(opaqueConsidered, (int)details._opaque._considered); - STAT_UPDATE(opaqueOutOfView, details._opaque._outOfView); - STAT_UPDATE(opaqueTooSmall, details._opaque._tooSmall); - STAT_UPDATE(opaqueRendered, (int)details._opaque._rendered); - STAT_UPDATE(shadowConsidered, (int)details._shadow._considered); + STAT_UPDATE(itemConsidered, details._item._considered); + STAT_UPDATE(itemOutOfView, details._item._outOfView); + STAT_UPDATE(itemTooSmall, details._item._tooSmall); + STAT_UPDATE(itemRendered, details._item._rendered); + STAT_UPDATE(shadowConsidered, details._shadow._considered); STAT_UPDATE(shadowOutOfView, details._shadow._outOfView); STAT_UPDATE(shadowTooSmall, details._shadow._tooSmall); - STAT_UPDATE(shadowRendered, (int)details._shadow._rendered); - STAT_UPDATE(translucentConsidered, (int)details._translucent._considered); - STAT_UPDATE(translucentOutOfView, details._translucent._outOfView); - STAT_UPDATE(translucentTooSmall, details._translucent._tooSmall); - STAT_UPDATE(translucentRendered, (int)details._translucent._rendered); - STAT_UPDATE(otherConsidered, (int)details._other._considered); - STAT_UPDATE(otherOutOfView, details._other._outOfView); - STAT_UPDATE(otherTooSmall, details._other._tooSmall); - STAT_UPDATE(otherRendered, (int)details._other._rendered); + STAT_UPDATE(shadowRendered, details._shadow._rendered); } } diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index ba3c8f2391..3476087852 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -59,22 +59,14 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, triangles, 0) STATS_PROPERTY(int, quads, 0) STATS_PROPERTY(int, materialSwitches, 0) - STATS_PROPERTY(int, opaqueConsidered, 0) - STATS_PROPERTY(int, opaqueOutOfView, 0) - STATS_PROPERTY(int, opaqueTooSmall, 0) - STATS_PROPERTY(int, opaqueRendered, 0) + STATS_PROPERTY(int, itemConsidered, 0) + STATS_PROPERTY(int, itemOutOfView, 0) + STATS_PROPERTY(int, itemTooSmall, 0) + STATS_PROPERTY(int, itemRendered, 0) STATS_PROPERTY(int, shadowConsidered, 0) STATS_PROPERTY(int, shadowOutOfView, 0) STATS_PROPERTY(int, shadowTooSmall, 0) STATS_PROPERTY(int, shadowRendered, 0) - STATS_PROPERTY(int, translucentConsidered, 0) - STATS_PROPERTY(int, translucentOutOfView, 0) - STATS_PROPERTY(int, translucentTooSmall, 0) - STATS_PROPERTY(int, translucentRendered, 0) - STATS_PROPERTY(int, otherConsidered, 0) - STATS_PROPERTY(int, otherOutOfView, 0) - STATS_PROPERTY(int, otherTooSmall, 0) - STATS_PROPERTY(int, otherRendered, 0) STATS_PROPERTY(QString, sendingMode, QString()) STATS_PROPERTY(QString, packetStats, QString()) STATS_PROPERTY(QString, lodStatus, QString()) @@ -145,22 +137,14 @@ signals: void trianglesChanged(); void quadsChanged(); void materialSwitchesChanged(); - void opaqueConsideredChanged(); - void opaqueOutOfViewChanged(); - void opaqueTooSmallChanged(); - void opaqueRenderedChanged(); + void itemConsideredChanged(); + void itemOutOfViewChanged(); + void itemTooSmallChanged(); + void itemRenderedChanged(); void shadowConsideredChanged(); void shadowOutOfViewChanged(); void shadowTooSmallChanged(); void shadowRenderedChanged(); - void translucentConsideredChanged(); - void translucentOutOfViewChanged(); - void translucentTooSmallChanged(); - void translucentRenderedChanged(); - void otherConsideredChanged(); - void otherOutOfViewChanged(); - void otherTooSmallChanged(); - void otherRenderedChanged(); void sendingModeChanged(); void packetStatsChanged(); void lodStatusChanged(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 13a24fc16d..31f40f5285 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -56,7 +56,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // Fetch and cull the items from the scene auto sceneFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); const auto sceneSelection = addJob("FetchSceneSelection", sceneFilter); - const auto culledSceneSelection = addJob("CullSceneSelection", sceneSelection, cullFunctor, RenderDetails::OPAQUE_ITEM, sceneFilter); + const auto culledSceneSelection = addJob("CullSceneSelection", sceneSelection, cullFunctor, RenderDetails::ITEM, sceneFilter); // Multi filter visible items into different buckets const int NUM_FILTERS = 3; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 32188e4cc9..f8057c164b 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -108,7 +108,7 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha const auto fetchedItems = addJob("FetchShadowMap"); // CPU: Cull against KeyLight frustum (nearby viewing camera) - const auto culledItems = addJob>("CullShadowMap", fetchedItems, cullFunctor); + const auto culledItems = addJob>("CullShadowMap", fetchedItems, cullFunctor); // CPU: Sort by pipeline const auto sortedShapes = addJob("PipelineSortShadowSort", culledItems); diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 9a52bb06ff..734d683ad7 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -138,7 +138,7 @@ namespace render { _cullFunctor{ cullFunctor } {} CullFunctor _cullFunctor; - RenderDetails::Type _detailType{ RenderDetails::OPAQUE_ITEM }; + RenderDetails::Type _detailType{ RenderDetails::OTHER }; ItemFilter _filter{ ItemFilter::Builder::opaqueShape().withoutLayered() }; void configure(const Config& config); diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index f9fc6eb66b..341553b743 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -35,36 +35,31 @@ class ShapePipeline; class RenderDetails { public: enum Type { - OPAQUE_ITEM, - SHADOW_ITEM, - TRANSLUCENT_ITEM, - OTHER_ITEM + ITEM, + SHADOW, + OTHER }; struct Item { - size_t _considered = 0; - size_t _rendered = 0; + int _considered = 0; int _outOfView = 0; int _tooSmall = 0; + int _rendered = 0; }; int _materialSwitches = 0; int _trianglesRendered = 0; - Item _opaque; + Item _item; Item _shadow; - Item _translucent; Item _other; Item& edit(Type type) { switch (type) { - case OPAQUE_ITEM: - return _opaque; - case SHADOW_ITEM: + case SHADOW: return _shadow; - case TRANSLUCENT_ITEM: - return _translucent; - case OTHER_ITEM: + case ITEM: + return _item; default: return _other; } From 2258a9cad95a553ef7b4d162bbbefaffd456d22c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 23 Feb 2016 11:52:02 -0800 Subject: [PATCH 092/114] Allow avatar positioning from QML --- interface/src/avatar/MyAvatar.cpp | 42 ++++++++- interface/src/avatar/MyAvatar.h | 1 + libraries/shared/src/RegisteredMetaTypes.cpp | 92 +++++++++++++++++++- libraries/shared/src/RegisteredMetaTypes.h | 6 ++ 4 files changed, 135 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 56584df44e..ae3c969d2f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -123,8 +123,11 @@ MyAvatar::MyAvatar(RigPointer rig) : } // connect to AddressManager signal for location jumps - connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, - this, &MyAvatar::goToLocation); + connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, + [=](const glm::vec3& newPosition, bool hasOrientation, const glm::quat& newOrientation, bool shouldFaceLocation){ + goToLocation(newPosition, hasOrientation, newOrientation, shouldFaceLocation); + }); + _characterController.setEnabled(true); _bodySensorMatrix = deriveBodyFromHMDSensor(); @@ -1666,6 +1669,41 @@ void MyAvatar::resetSize() { qCDebug(interfaceapp, "Reset scale to %f", (double)_targetScale); } + +void MyAvatar::goToLocation(const QVariant& propertiesVar) { + qCDebug(interfaceapp, "MyAvatar QML goToLocation"); + auto properties = propertiesVar.toMap(); + if (!properties.contains("position")) { + qCWarning(interfaceapp, "goToLocation called without a position variable"); + return; + } + + bool validPosition; + glm::vec3 v = vec3FromVariant(properties["position"], validPosition); + if (!validPosition) { + qCWarning(interfaceapp, "goToLocation called with invalid position variable"); + return; + } + bool validOrientation; + glm::quat q; + if (properties.contains("orientation")) { + q = quatFromVariant(properties["orientation"], validOrientation); + if (!validOrientation) { + glm::vec3 eulerOrientation = vec3FromVariant(properties["orientation"], validOrientation); + q = glm::quat(eulerOrientation); + if (!validOrientation) { + qCWarning(interfaceapp, "goToLocation called with invalid orientation variable"); + } + } + } + + if (validOrientation) { + goToLocation(v, true, q); + } else { + goToLocation(v); + } +} + void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::quat& newOrientation, bool shouldFaceLocation) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8c84299e08..637baa3c22 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -253,6 +253,7 @@ public slots: void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false); + void goToLocation(const QVariant& properties); // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index c2c35df957..a1aae35063 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -9,10 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include "RegisteredMetaTypes.h" @@ -91,6 +94,51 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector()) { + v = glm::vec3(object.toFloat()); + valid = true; + } else if (object.canConvert()) { + auto qvec3 = qvariant_cast(object); + v.x = qvec3.x(); + v.y = qvec3.y(); + v.z = qvec3.z(); + valid = true; + } else { + auto map = object.toMap(); + auto x = map["x"]; + auto y = map["y"]; + auto z = map["z"]; + if (!x.isValid()) { + x = map["width"]; + } + if (!y.isValid()) { + y = map["height"]; + } + if (!y.isValid()) { + z = map["depth"]; + } + + if (x.canConvert() && y.canConvert() && z.canConvert()) { + v.x = x.toFloat(); + v.y = y.toFloat(); + v.z = z.toFloat(); + valid = true; + } + } + return v; +} + +glm::vec3 vec3FromVariant(const QVariant &object) { + bool valid = false; + return vec3FromVariant(object, valid); +} + + QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) { QScriptValue obj = engine->newObject(); if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) { @@ -111,6 +159,42 @@ void quatFromScriptValue(const QScriptValue &object, glm::quat &quat) { quat.w = object.property("w").toVariant().toFloat(); } +glm::quat quatFromVariant(const QVariant &object, bool& isValid) { + glm::quat q; + if (object.canConvert()) { + auto qvec3 = qvariant_cast(object); + q.x = qvec3.x(); + q.y = qvec3.y(); + q.z = qvec3.z(); + q.w = qvec3.scalar(); + isValid = true; + } else { + auto map = object.toMap(); + q.x = map["x"].toFloat(&isValid); + if (!isValid) { + return glm::quat(); + } + q.y = map["y"].toFloat(&isValid); + if (!isValid) { + return glm::quat(); + } + q.z = map["z"].toFloat(&isValid); + if (!isValid) { + return glm::quat(); + } + q.w = map["w"].toFloat(&isValid); + if (!isValid) { + return glm::quat(); + } + } + return q; +} + +glm::quat quatFromVariant(const QVariant &object) { + bool valid = false; + return quatFromVariant(object, valid); +} + QScriptValue qVectorQuatToScriptValue(QScriptEngine* engine, const QVector& vector) { QScriptValue array = engine->newArray(); for (int i = 0; i < vector.size(); i++) { diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 81314cef69..2bec5b025e 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -41,12 +41,18 @@ void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4); QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3); void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3); +glm::vec3 vec3FromVariant(const QVariant &object, bool& valid); +glm::vec3 vec3FromVariant(const QVariant &object); + QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2); void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2); QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat& quat); void quatFromScriptValue(const QScriptValue &object, glm::quat& quat); +glm::quat quatFromVariant(const QVariant &object, bool& isValid); +glm::quat quatFromVariant(const QVariant &object); + QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect); void qRectFromScriptValue(const QScriptValue& object, QRect& rect); From eb53f44a06a7145da1e1c2e549c553802ea69b33 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Feb 2016 12:44:38 -0800 Subject: [PATCH 093/114] Convert size_t details to int --- libraries/render/src/render/CullTask.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index cf4e825ea3..3fc6bffbd3 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -28,7 +28,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc RenderArgs* args = renderContext->args; ViewFrustum* frustum = args->_viewFrustum; - details._considered += inItems.size(); + details._considered += (int)inItems.size(); // Culling / LOD for (auto item : inItems) { @@ -59,7 +59,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc details._outOfView++; } } - details._rendered += outItems.size(); + details._rendered += (int)outItems.size(); } struct ItemBoundSort { @@ -202,7 +202,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re auto& scene = sceneContext->_scene; auto& details = args->_details.edit(_detailType); - details._considered += inSelection.numItems(); + details._considered += (int)inSelection.numItems(); // Eventually use a frozen frustum auto argFrustum = args->_viewFrustum; @@ -325,7 +325,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re } } - details._rendered += outItems.size(); + details._rendered += (int)outItems.size(); // Restore frustum if using the frozen one: From 38b29f47091b0f22ef41bd2718e66d3851ed0edd Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 23 Feb 2016 13:26:15 -0800 Subject: [PATCH 094/114] Revert "Physics: extrapolate kinematic objects as well as dynamic ones." This reverts commit e544275500a10cce28427b8d088fb0df0a19fad6. --- libraries/physics/src/EntityMotionState.cpp | 2 +- .../physics/src/ThreadSafeDynamicsWorld.cpp | 19 ++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index ff7d550175..8c0dab98db 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,7 +191,7 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { } // This callback is invoked by the physics simulation at the end of each simulation step... -// iff the corresponding RigidBody is active. +// iff the corresponding RigidBody is DYNAMIC and has moved. void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { if (!_entity) { return; diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index 17b2b08d4d..b6f3487f1a 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -96,26 +96,19 @@ void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { ///@todo: add 'dirty' flag //if (body->getActivationState() != ISLAND_SLEEPING) { - btTransform bodyTransform; - btVector3 bodyLinearVelocity, bodyAngularVelocity; if (body->isKinematicObject()) { ObjectMotionState* objectMotionState = static_cast(body->getMotionState()); if (objectMotionState->hasInternalKinematicChanges()) { objectMotionState->clearInternalKinematicChanges(); + body->getMotionState()->setWorldTransform(body->getWorldTransform()); } - bodyTransform = body->getWorldTransform(); - bodyLinearVelocity = body->getLinearVelocity(); - bodyAngularVelocity = body->getAngularVelocity(); - } else { - bodyTransform = body->getInterpolationWorldTransform(); - bodyLinearVelocity = body->getInterpolationLinearVelocity(); - bodyAngularVelocity = body->getInterpolationAngularVelocity(); + return; } - - // integrate the object foward to cover the time in-between fixed time steps. - btScalar dt = (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime * body->getHitFraction(); btTransform interpolatedTransform; - btTransformUtil::integrateTransform(bodyTransform, bodyLinearVelocity, bodyAngularVelocity, dt, interpolatedTransform); + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(), + (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(), + interpolatedTransform); body->getMotionState()->setWorldTransform(interpolatedTransform); } } From 9dd1bfad2d0b0319eccf21303e2fa2a458783e1d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 24 Feb 2016 10:54:36 +1300 Subject: [PATCH 095/114] Fix tree view branch indicator colors Using interim HiFi glyphs until branch triangles are added to the font. --- interface/resources/qml/controls-uit/Tree.qml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 18eab55563..8377812acc 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -54,6 +54,18 @@ TreeView { backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd + branchDelegate: HiFiGlyphs { + text: styleData.isExpanded ? "Z" : "B" + size: hifi.fontSizes.tableText * 2.5 // tableText is in points; proportionately scale to pixels + color: colorScheme == hifi.colorSchemes.light + ? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight) + : (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText) + anchors { + left: parent.left + leftMargin: hifi.dimensions.tablePadding / 2 + } + } + handle: Item { id: scrollbarHandle implicitWidth: 6 From 8f27424de7bef2ee80be3e0b2554b67b53e17acc Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 23 Feb 2016 14:30:51 -0800 Subject: [PATCH 096/114] MyAvatar: bug fix for avatar leaning --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 56584df44e..2909366ab8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1873,7 +1873,7 @@ bool MyAvatar::FollowHelper::shouldActivate(const MyAvatar& myAvatar, const glm: const float CYLINDER_RADIUS = 0.15f; glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix); - glm::vec3 radialOffset(offset.x, 0.0f, offset.y); + glm::vec3 radialOffset(offset.x, 0.0f, offset.z); float radialDistance = glm::length(radialOffset); return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM) || (radialDistance > CYLINDER_RADIUS); From 128583660b38c5ed93ab6d576212019b03913cef Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 24 Feb 2016 12:10:19 +1300 Subject: [PATCH 097/114] Specify font sizes in pixels instead of points Makes the dialog layout and look consistent across different devices. --- .../resources/qml/controls-uit/TextField.qml | 2 +- .../qml/styles-uit/AnonymousProRegular.qml | 2 +- .../qml/styles-uit/FiraSansSemiBold.qml | 2 +- .../resources/qml/styles-uit/HiFiGlyphs.qml | 2 +- .../qml/styles-uit/HifiConstants.qml | 32 +++++++++---------- .../resources/qml/styles-uit/RalewayBold.qml | 2 +- .../resources/qml/styles-uit/RalewayLight.qml | 2 +- .../qml/styles-uit/RalewayRegular.qml | 2 +- .../qml/styles-uit/RalewaySemibold.qml | 2 +- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index 6714cb94d5..fa1f7c97ad 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -22,7 +22,7 @@ TextField { FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } font.family: firaSansSemiBold.name - font.pointSize: hifi.fontSizes.textFieldInput + font.pixelSize: hifi.fontSizes.textFieldInput height: implicitHeight + 4 // Make surrounding box higher so that highlight is vertically centered. placeholderText: textField.label // Instead of separate label (see below). diff --git a/interface/resources/qml/styles-uit/AnonymousProRegular.qml b/interface/resources/qml/styles-uit/AnonymousProRegular.qml index 5e226bea99..789689973b 100644 --- a/interface/resources/qml/styles-uit/AnonymousProRegular.qml +++ b/interface/resources/qml/styles-uit/AnonymousProRegular.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: anonymousProRegular; source: "../../fonts/AnonymousPro-Regular.ttf"; } property real size: 32 - font.pointSize: size + font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: anonymousProRegular.name diff --git a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml index 085ce0537c..ddbeff7d90 100644 --- a/interface/resources/qml/styles-uit/FiraSansSemiBold.qml +++ b/interface/resources/qml/styles-uit/FiraSansSemiBold.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } property real size: 32 - font.pointSize: size + font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: firaSansSemiBold.name diff --git a/interface/resources/qml/styles-uit/HiFiGlyphs.qml b/interface/resources/qml/styles-uit/HiFiGlyphs.qml index 854e893441..d0dae746be 100644 --- a/interface/resources/qml/styles-uit/HiFiGlyphs.qml +++ b/interface/resources/qml/styles-uit/HiFiGlyphs.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: hiFiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; } property int size: 32 - font.pixelSize: size // Size this font in pixels because it's UI widgets. + font.pixelSize: size width: size height: size verticalAlignment: Text.AlignVCenter diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index fda90d731a..2dca4dd795 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -80,22 +80,22 @@ Item { } Item { - id: fontSizes - readonly property real overlayTitle: dimensions.largeScreen? 16 : 12 - readonly property real tabName: dimensions.largeScreen? 11 : 9 - readonly property real sectionName: dimensions.largeScreen? 11 : 9 - readonly property real inputLabel: dimensions.largeScreen? 13.5 : 9 - readonly property real textFieldInput: dimensions.largeScreen? 13.5 : 11 - readonly property real tableText: dimensions.largeScreen? 13.5 : 11 - readonly property real buttonLabel: dimensions.largeScreen? 12 : 8 - readonly property real iconButton: dimensions.largeScreen? 12: 8 - readonly property real listItem: dimensions.largeScreen? 13.5 : 9 - readonly property real tabularData: dimensions.largeScreen? 11 : 9 - readonly property real logs: dimensions.largeScreen? 15 : 10 - readonly property real code: dimensions.largeScreen? 15 : 10 - readonly property real rootMenu: dimensions.largeScreen? 13.5 : 9 - readonly property real menuItem: dimensions.largeScreen? 13.5 : 9 - readonly property real shortcutText: dimensions.largeScreen? 12 : 8 + id: fontSizes // In pixels + readonly property real overlayTitle: dimensions.largeScreen? 18 : 14 + readonly property real tabName: dimensions.largeScreen? 12 : 10 + readonly property real sectionName: dimensions.largeScreen? 12 : 10 + readonly property real inputLabel: dimensions.largeScreen? 14 : 10 + readonly property real textFieldInput: dimensions.largeScreen? 15 : 12 + readonly property real tableText: dimensions.largeScreen? 15 : 12 + readonly property real buttonLabel: dimensions.largeScreen? 13 : 9 + readonly property real iconButton: dimensions.largeScreen? 13 : 9 + readonly property real listItem: dimensions.largeScreen? 15 : 11 + readonly property real tabularData: dimensions.largeScreen? 15 : 11 + readonly property real logs: dimensions.largeScreen? 16 : 12 + readonly property real code: dimensions.largeScreen? 16 : 12 + readonly property real rootMenu: dimensions.largeScreen? 15 : 11 + readonly property real menuItem: dimensions.largeScreen? 15 : 11 + readonly property real shortcutText: dimensions.largeScreen? 13 : 9 } Item { diff --git a/interface/resources/qml/styles-uit/RalewayBold.qml b/interface/resources/qml/styles-uit/RalewayBold.qml index 359f0feda8..97a6a4c208 100644 --- a/interface/resources/qml/styles-uit/RalewayBold.qml +++ b/interface/resources/qml/styles-uit/RalewayBold.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: ralewayBold; source: "../../fonts/Raleway-Bold.ttf"; } property real size: 32 - font.pointSize: size + font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: ralewayBold.name diff --git a/interface/resources/qml/styles-uit/RalewayLight.qml b/interface/resources/qml/styles-uit/RalewayLight.qml index 8e24d74a46..913918afd7 100644 --- a/interface/resources/qml/styles-uit/RalewayLight.qml +++ b/interface/resources/qml/styles-uit/RalewayLight.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: ralewayLight; source: "../../fonts/Raleway-Light.ttf"; } property real size: 32 - font.pointSize: size + font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: ralewayLight.name diff --git a/interface/resources/qml/styles-uit/RalewayRegular.qml b/interface/resources/qml/styles-uit/RalewayRegular.qml index c04db54e9d..1ed5f122dc 100644 --- a/interface/resources/qml/styles-uit/RalewayRegular.qml +++ b/interface/resources/qml/styles-uit/RalewayRegular.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: ralewayRegular; source: "../../fonts/Raleway-Regular.ttf"; } property real size: 32 - font.pointSize: size + font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: ralewayRegular.name diff --git a/interface/resources/qml/styles-uit/RalewaySemibold.qml b/interface/resources/qml/styles-uit/RalewaySemibold.qml index 374696f902..3648e6bab9 100644 --- a/interface/resources/qml/styles-uit/RalewaySemibold.qml +++ b/interface/resources/qml/styles-uit/RalewaySemibold.qml @@ -16,7 +16,7 @@ Text { id: root FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; } property real size: 32 - font.pointSize: size + font.pixelSize: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.family: ralewaySemibold.name From bac703b29ea9d9b3821845e5c9706ad622881b2d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 24 Feb 2016 12:36:46 +1300 Subject: [PATCH 098/114] Adjust height of Running Scripts now that fonts are consistently sized --- interface/resources/qml/hifi/dialogs/RunningScripts.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 8ca410d90e..55b8946805 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -24,7 +24,7 @@ Window { resizable: true destroyOnInvisible: true x: 40; y: 40 - implicitWidth: 384; implicitHeight: 650 + implicitWidth: 384; implicitHeight: 640 minSize: Qt.vector2d(200, 300) HifiConstants { id: hifi } From ad4d697f387c0715e71364f6b9b6819a65e22377 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 24 Feb 2016 12:37:23 +1300 Subject: [PATCH 099/114] Use names for HiFi glyph characters --- interface/resources/qml/controls-uit/Table.qml | 4 ++-- interface/resources/qml/controls-uit/Tree.qml | 2 +- .../resources/qml/styles-uit/HifiConstants.qml | 14 ++++++++++++++ .../resources/qml/windows-uit/DefaultFrame.qml | 4 ++-- interface/resources/qml/windows-uit/Frame.qml | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index 5fa916f0cc..fc6c310612 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -132,7 +132,7 @@ TableView { // FIXME: Put reload item in tableModel passed in from RunningScripts. HiFiGlyphs { id: reloadButton - text: "a" + text: hifi.glyphs.reloadSmall color: parent.color anchors { top: parent.top @@ -148,7 +148,7 @@ TableView { // FIXME: Put stop item in tableModel passed in from RunningScripts. HiFiGlyphs { id: stopButton - text: "C" + text: hifi.glyphs.closeSmall color: parent.color anchors { top: parent.top diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 8377812acc..25003c2c2d 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -55,7 +55,7 @@ TreeView { alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd branchDelegate: HiFiGlyphs { - text: styleData.isExpanded ? "Z" : "B" + text: styleData.isExpanded ? hifi.glyphs.disclosureCollapse : hifi.glyphs.disclosureExpand size: hifi.fontSizes.tableText * 2.5 // tableText is in points; proportionately scale to pixels color: colorScheme == hifi.colorSchemes.light ? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight) diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 2dca4dd795..d068395bc9 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -16,6 +16,7 @@ Item { readonly property alias colorSchemes: colorSchemes readonly property alias dimensions: dimensions readonly property alias fontSizes: fontSizes + readonly property alias glyphs: glyphs readonly property alias buttons: buttons readonly property alias effects: effects @@ -98,6 +99,19 @@ Item { readonly property real shortcutText: dimensions.largeScreen? 13 : 9 } + Item { + id: glyphs + readonly property string close: "w" + readonly property string closeInverted: "x" + readonly property string closeSmall: "C" + readonly property string disclosureCollapse: "Z" + readonly property string disclosureExpand: "B" + readonly property string pin: "y" + readonly property string pinInverted: "z" + readonly property string reloadSmall: "a" + readonly property string resizeHandle: "A" + } + Item { id: buttons readonly property int white: 0 diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml index 4bc7fc7aec..4e4c2df8f2 100644 --- a/interface/resources/qml/windows-uit/DefaultFrame.qml +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -53,7 +53,7 @@ Frame { HiFiGlyphs { // "Pin" button visible: false - text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? "z" : "y" + text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? hifi.glyphs.pinInverted : hifi.glyphs.pin color: pinClickArea.containsMouse && !pinClickArea.pressed ? hifi.colors.redHighlight : hifi.colors.white size: iconSize MouseArea { @@ -68,7 +68,7 @@ Frame { HiFiGlyphs { // "Close" button visible: window ? window.closable : false - text: closeClickArea.containsPress ? "x" : "w" + text: closeClickArea.containsPress ? hifi.glyphs.closeInverted : hifi.glyphs.close color: closeClickArea.containsMouse ? hifi.colors.redHighlight : hifi.colors.white size: iconSize MouseArea { diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml index 92ba2d4108..00811e8ee3 100644 --- a/interface/resources/qml/windows-uit/Frame.qml +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -126,7 +126,7 @@ Item { visible: sizeDrag.enabled x: -11 // Move a little to visually align y: -4 // "" - text: "A" + text: hifi.glyphs.resizeHandle size: iconSize + 10 color: sizeDrag.containsMouse || sizeDrag.pressed ? hifi.colors.white : hifi.colors.white50 } From beef3f59eb0b011518bc5e17f6924179c94e1835 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 24 Feb 2016 12:59:21 +1300 Subject: [PATCH 100/114] Fix QML warning --- interface/resources/qml/controls-uit/Tree.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 25003c2c2d..d100cdcd44 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -61,7 +61,7 @@ TreeView { ? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight) : (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText) anchors { - left: parent.left + left: parent ? parent.left : undefined leftMargin: hifi.dimensions.tablePadding / 2 } } From 1f9324c78fa982c75ed7733936606a62722e9d66 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Feb 2016 16:14:41 -0800 Subject: [PATCH 101/114] Move Graphics... to Developer menu --- interface/src/Menu.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 48afdb4622..97eb67116c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -312,12 +312,6 @@ Menu::Menu() { DependencyManager::get()->toggle(QString("hifi/dialogs/AudioPreferencesDialog.qml"), "AudioPreferencesDialog"); }); - // Settings > Graphics... - action = addActionToQMenuAndActionHash(settingsMenu, "Graphics..."); - connect(action, &QAction::triggered, [] { - DependencyManager::get()->toggle(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), "GraphicsPreferencesDialog"); - }); - // Settings > LOD...-- FIXME: needs implementation action = addActionToQMenuAndActionHash(settingsMenu, "LOD..."); connect(action, &QAction::triggered, [] { @@ -345,6 +339,12 @@ Menu::Menu() { // Developer menu ---------------------------------- MenuWrapper* developerMenu = addMenu("Developer", "Developer"); + // Developer > Graphics... + action = addActionToQMenuAndActionHash(developerMenu, "Graphics..."); + connect(action, &QAction::triggered, [] { + DependencyManager::get()->toggle(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), "GraphicsPreferencesDialog"); + }); + // Developer > Render >>> MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); From 7ae97522723766e51a5aae200ec670380d8a048b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Feb 2016 16:15:27 -0800 Subject: [PATCH 102/114] Remove Render > Ambient Light menu --- interface/src/Application.cpp | 32 ++------------------------------ interface/src/Application.h | 1 - interface/src/Menu.cpp | 16 ---------------- interface/src/Menu.h | 12 ------------ 4 files changed, 2 insertions(+), 59 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 89ec196fad..1ff448f35f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3817,9 +3817,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se } // Setup the current Zone Entity lighting and skybox - // Fixme: We need a better soution through an actual render item !!! { - DependencyManager::get()->setAmbientLightMode(getRenderAmbientLight()); + // FIXME: Use a zone setting to determine the ambient light mode + DependencyManager::get()->setAmbientLightMode(-1); auto skyStage = DependencyManager::get()->getSkyStage(); DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity()); @@ -4630,34 +4630,6 @@ float Application::getRenderResolutionScale() const { } } -int Application::getRenderAmbientLight() const { - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLightGlobal)) { - return -1; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight0)) { - return 0; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight1)) { - return 1; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight2)) { - return 2; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight3)) { - return 3; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight4)) { - return 4; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight5)) { - return 5; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight6)) { - return 6; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight7)) { - return 7; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight8)) { - return 8; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderAmbientLight9)) { - return 9; - } else { - return -1; - } -} - void Application::notifyPacketVersionMismatch() { if (!_notifiedPacketVersionMismatchThisDomain) { _notifiedPacketVersionMismatchThisDomain = true; diff --git a/interface/src/Application.h b/interface/src/Application.h index 8cc2a33038..51b90bcb99 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -352,7 +352,6 @@ private: void checkSkeleton(); void initializeAcceptedFiles(); - int getRenderAmbientLight() const; void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 97eb67116c..9c7788851c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -350,22 +350,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, 0, true); - // Developer > Render > Ambient Light - MenuWrapper* ambientLightMenu = renderOptionsMenu->addMenu(MenuOption::RenderAmbientLight); - QActionGroup* ambientLightGroup = new QActionGroup(ambientLightMenu); - ambientLightGroup->setExclusive(true); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLightGlobal, 0, true)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight0, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight1, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight2, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight3, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight4, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight5, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight6, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight7, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight8, 0, false)); - ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight9, 0, false)); - // Developer > Render > Throttle FPS If Not Focus addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 51a1542490..44a24ee895 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -266,18 +266,6 @@ namespace MenuOption { const QString RenderResolutionHalf = "1/2"; const QString RenderResolutionThird = "1/3"; const QString RenderResolutionQuarter = "1/4"; - const QString RenderAmbientLight = "Ambient Light"; - const QString RenderAmbientLightGlobal = "Global"; - const QString RenderAmbientLight0 = "OLD_TOWN_SQUARE"; - const QString RenderAmbientLight1 = "GRACE_CATHEDRAL"; - const QString RenderAmbientLight2 = "EUCALYPTUS_GROVE"; - const QString RenderAmbientLight3 = "ST_PETERS_BASILICA"; - const QString RenderAmbientLight4 = "UFFIZI_GALLERY"; - const QString RenderAmbientLight5 = "GALILEOS_TOMB"; - const QString RenderAmbientLight6 = "VINE_STREET_KITCHEN"; - const QString RenderAmbientLight7 = "BREEZEWAY"; - const QString RenderAmbientLight8 = "CAMPUS_SUNSET"; - const QString RenderAmbientLight9 = "FUNSTON_BEACH_SUNSET"; const QString ResetAvatarSize = "Reset Avatar Size"; const QString ResetSensors = "Reset Sensors"; const QString RunningScripts = "Running Scripts..."; From ea8edb3744c2931f69d52970779216ad20d86879 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Feb 2016 16:18:27 -0800 Subject: [PATCH 103/114] Remove antialiasing from menus, default to on --- interface/resources/config/render.json | 5 ----- interface/src/ui/PreferencesDialog.cpp | 9 --------- libraries/render-utils/src/AntialiasingEffect.h | 4 ++-- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/interface/resources/config/render.json b/interface/resources/config/render.json index 092530d864..414d94e11e 100644 --- a/interface/resources/config/render.json +++ b/interface/resources/config/render.json @@ -9,11 +9,6 @@ "Enabled": { "enabled": true } - }, - "Antialiasing": { - "Enabled": { - "enabled": true - } } } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 93bacdd402..78c2405ade 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -330,15 +330,6 @@ void setupPreferences() { preferences->addPreference(preference); } - auto antialiasingConfig = renderConfig->getConfig(); - { - auto getter = [antialiasingConfig]()->QString { return antialiasingConfig->getPreset(); }; - auto setter = [antialiasingConfig](QString preset) { antialiasingConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Antialiasing", getter, setter); - preference->setItems(antialiasingConfig->getPresetList()); - preferences->addPreference(preference); - } - auto shadowConfig = renderConfig->getConfig(); { auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 6185ed07dc..6386622675 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -16,11 +16,11 @@ #include "render/DrawTask.h" -class AntiAliasingConfig : public render::Job::Config::Persistent { +class AntiAliasingConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(bool enabled MEMBER enabled) public: - AntiAliasingConfig() : render::Job::Config::Persistent("Antialiasing", false) {} + AntiAliasingConfig() : render::Job::Config(true) {} }; class Antialiasing { From a816d835d3129350eaa7488e52b39c606cfae350 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 24 Feb 2016 13:59:43 +1300 Subject: [PATCH 104/114] Finesse modal message box dialog layout --- interface/resources/qml/dialogs/MessageDialog.qml | 14 +++++++------- .../resources/qml/styles-uit/HifiConstants.qml | 2 +- interface/resources/qml/windows-uit/ModalFrame.qml | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index f31b5cf41d..21d17c4e54 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -89,8 +89,8 @@ ModalWindow { function resize() { var targetWidth = mainTextContainer.width - var targetHeight = mainTextContainer.height + 4 * hifi.dimensions.contentSpacing.y - + (informativeTextContainer.text != "" ? informativeTextContainer.contentHeight + hifi.dimensions.contentSpacing.y : 0) + var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + + (informativeTextContainer.text != "" ? informativeTextContainer.contentHeight + 3 * hifi.dimensions.contentSpacing.y : 0) + buttons.height + (content.state === "expanded" ? details.implicitHeight + hifi.dimensions.contentSpacing.y : 0) root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth) @@ -121,9 +121,9 @@ ModalWindow { size: hifi.fontSizes.menuItem color: hifi.colors.baseGrayHighlight anchors { - top: mainTextContainer.bottom; - left: parent.left; - right: parent.right; + top: mainTextContainer.bottom + left: parent.left + right: parent.right margins: 0 topMargin: text != "" ? hifi.dimensions.contentSpacing.y : 0 } @@ -136,10 +136,10 @@ ModalWindow { onHeightChanged: d.resize(); onWidthChanged: d.resize(); layoutDirection: Qt.RightToLeft anchors { - top: informativeTextContainer.bottom + top: informativeTextContainer.text == "" ? mainTextContainer.bottom : informativeTextContainer.bottom horizontalCenter: parent.horizontalCenter margins: 0 - topMargin: hifi.dimensions.contentSpacing.y + topMargin: 2 * hifi.dimensions.contentSpacing.y } MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; } MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; } diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index e18380f492..77e74163c3 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -79,7 +79,7 @@ Item { readonly property real textPadding: 8 readonly property real tablePadding: 12 readonly property real tableRowHeight: largeScreen ? 26 : 23 - readonly property real modalDialogMargin: 50 + readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30) readonly property real modalDialogTitleHeight: 40 } diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index b76996a873..17b60061e8 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -25,10 +25,10 @@ Frame { Rectangle { anchors { - topMargin: -hifi.dimensions.modalDialogMargin - (modalFrame.hasTitle ? hifi.dimensions.modalDialogTitleHeight : 0) - leftMargin: -hifi.dimensions.modalDialogMargin - rightMargin: -hifi.dimensions.modalDialogMargin - bottomMargin: -hifi.dimensions.modalDialogMargin + topMargin: -hifi.dimensions.modalDialogMargin.y - (modalFrame.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0) + leftMargin: -hifi.dimensions.modalDialogMargin.x + rightMargin: -hifi.dimensions.modalDialogMargin.x + bottomMargin: -hifi.dimensions.modalDialogMargin.y fill: parent } border { @@ -50,7 +50,7 @@ Frame { size: 30 color: hifi.colors.lightGrayText visible: text != "" - y: -hifi.dimensions.modalDialogTitleHeight - 3 + y: -hifi.dimensions.modalDialogTitleHeight - 5 anchors.left: parent.left } RalewayRegular { From 864f00ee6156c554fc4bfc6a5658558f5f252bfb Mon Sep 17 00:00:00 2001 From: Nex Pro Date: Wed, 24 Feb 2016 01:02:17 +0000 Subject: [PATCH 105/114] Fixed inverted particle rendering. --- libraries/entities-renderer/src/textured_particle.slv | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 4d819d389f..bbd7a1daa7 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -44,11 +44,12 @@ out vec4 varColor; out vec2 varTexcoord; const int NUM_VERTICES_PER_PARTICLE = 4; +// This ordering ensures that un-rotated particles render upright in the wiewer. const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( - vec4(-1.0, -1.0, 0.0, 0.0), - vec4(1.0, -1.0, 0.0, 0.0), vec4(-1.0, 1.0, 0.0, 0.0), - vec4(1.0, 1.0, 0.0, 0.0) + vec4(-1.0, -1.0, 0.0, 0.0), + vec4(1.0, 1.0, 0.0, 0.0), + vec4(1.0, -1.0, 0.0, 0.0) ); float bezierInterpolate(float y1, float y2, float y3, float u) { @@ -115,7 +116,8 @@ void main(void) { float seed = inColor.y; // Pass the texcoord and the z texcoord is representing the texture icon - varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); + // Offset for corrected vertex ordering. + varTexcoord = vec2((UNIT_QUAD[twoTriID].xy -1.0) * vec2(0.5, -0.5)); varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); // anchor point in eye space From 6403bb60a5ea751c6bd2a41c2f35925fdf2e969b Mon Sep 17 00:00:00 2001 From: Nex Pro Date: Wed, 24 Feb 2016 01:20:49 +0000 Subject: [PATCH 106/114] added particleOrientationTest.js for testing. --- examples/tests/particleOrientationTest.js | 101 ++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 examples/tests/particleOrientationTest.js diff --git a/examples/tests/particleOrientationTest.js b/examples/tests/particleOrientationTest.js new file mode 100644 index 0000000000..7fe670f4b7 --- /dev/null +++ b/examples/tests/particleOrientationTest.js @@ -0,0 +1,101 @@ +// +// particleOrientationTest.js +// examples/tests +// +// Created by Piper.Peppercorn. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var emitterBone = 'Head' +var particleEntities = []; + +function emitter(jointName) { + var jointID = MyAvatar.jointNames.indexOf(jointName); + var newEmitter = Entities.addEntity({ + name: 'particleEmitter ' + jointName, + type: 'ParticleEffect', + emitterShouldTrail: true, + textures: 'https://dl.dropboxusercontent.com/u/96759331/ParticleTest.png', + position: Vec3.sum(MyAvatar.getAbsoluteJointRotationInObjectFrame(jointID), MyAvatar.position), + parentJointIndex: jointID, + position: MyAvatar.getJointPosition(jointName), + color: { + red: 255, + green: 255, + blue: 255 + }, + isEmitting: 1, + maxParticles: 1, + lifespan: 2.0 + , + emitRate: 1, + emitSpeed: 0.0, + speedSpread: 0.0, + /* + emitOrientation: { + x: -0.7035577893257141, + y: -0.000015259007341228426, + z: -0.000015259007341228426, + w: 1.7106381058692932 + }, + */ + emitOrientation: { + x:0, + y: 0, + z: 0, + w: Math.PI + }, + emitRadiusStart: 0, + polarStart: 0, + polarFinish: 0, + azimuthFinish: 3.1415927410125732, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: 0, + y: 0, + z: 0 + }, + particleRadius: 2.0, + radiusSpread: 1.0, + radiusStart: 2.0, + radiusFinish: 2.0, + colorSpread: { + red: 0, + green: 0, + blue: 0 + }, + colorStart: { + red: 255, + green: 255, + blue: 255 + }, + colorFinish: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + alphaSpread: 0, + alphaStart: 1, + alphaFinish: 1 + }); + return newEmitter; +} + + +Script.scriptEnding.connect(function() { + for (var i = 0; i < particleEntities.length; i++) { + // Fixes a crash on shutdown: + Entities.editEntity(particleEntities[i], { parentID: '' }); + Entities.deleteEntity(particleEntities[i]); + } +}); + +particleEntities.push(emitter(emitterBone)); From b63e4b9d1fe66157d51993c01be04fd3ebe87a6b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 23 Feb 2016 18:15:29 -0800 Subject: [PATCH 107/114] Address shutdown crash --- libraries/ui/src/VrMenu.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index d1ef660532..6609b376b1 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -124,18 +124,25 @@ void VrMenu::addMenu(QMenu* menu) { new MenuUserData(menu, result); auto menuAction = menu->menuAction(); updateQmlItemFromAction(result, menuAction); - QObject::connect(menuAction, &QAction::changed, [=] { + auto connection = QObject::connect(menuAction, &QAction::changed, [=] { updateQmlItemFromAction(result, menuAction); }); + QObject::connect(qApp, &QCoreApplication::aboutToQuit, [=] { + QObject::disconnect(connection); + }); } void bindActionToQmlAction(QObject* qmlAction, QAction* action) { new MenuUserData(action, qmlAction); updateQmlItemFromAction(qmlAction, action); - QObject::connect(action, &QAction::changed, [=] { + auto connection = QObject::connect(action, &QAction::changed, [=] { updateQmlItemFromAction(qmlAction, action); }); + QObject::connect(qApp, &QCoreApplication::aboutToQuit, [=] { + QObject::disconnect(connection); + }); + QObject::connect(action, &QAction::toggled, [=](bool checked) { qmlAction->setProperty("checked", checked); }); From 4074ba172d8b3aeaaa418757c3ea610597c220da Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 23 Feb 2016 20:37:25 -0800 Subject: [PATCH 108/114] Fix window confirmation dialog --- libraries/ui/src/OffscreenUi.cpp | 6 +++--- libraries/ui/src/OffscreenUi.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 7e84836c86..1c41827795 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -254,15 +254,15 @@ QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QS } QMessageBox::StandardButton OffscreenUi::information(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return DependencyManager::get()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton); + return DependencyManager::get()->messageBox(QMessageBox::Icon::Information, title, text, buttons, defaultButton); } QMessageBox::StandardButton OffscreenUi::question(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return DependencyManager::get()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton); + return DependencyManager::get()->messageBox(QMessageBox::Icon::Question, title, text, buttons, defaultButton); } QMessageBox::StandardButton OffscreenUi::warning(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return DependencyManager::get()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton); + return DependencyManager::get()->messageBox(QMessageBox::Icon::Warning, title, text, buttons, defaultButton); } diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 8b00180d43..32f7a31d17 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -63,7 +63,7 @@ public: } /// Same design as QMessageBox::question(), will block, returns result static QMessageBox::StandardButton question(void* ignored, const QString& title, const QString& text, - QMessageBox::StandardButtons buttons = QMessageBox::Ok, + QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton) { return question(title, text, buttons, defaultButton); } From fa23e2023efdfb29cccbb3933c1bdaf78a03862d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 23 Feb 2016 20:37:46 -0800 Subject: [PATCH 109/114] Fix bad tool window placement --- interface/resources/qml/ToolWindow.qml | 6 ++++-- interface/resources/qml/desktop/Desktop.qml | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index a7d45b9984..404d1c1e78 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -20,8 +20,10 @@ Windows.Window { property string newTabSource property alias tabView: tabView onParentChanged: { - x = 120; - y = 120; + if (parent) { + x = 120; + y = 120; + } } Settings { diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 604d57d3da..fcc0f9967b 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -11,10 +11,7 @@ import "../js/Utils.js" as Utils FocusScope { id: desktop objectName: "desktop" - - // Allow the scale of the desktop to be changed without screwing up the size relative to the parent. - height: parent.height / scale - width: parent.width / scale + anchors.fill: parent onHeightChanged: d.repositionAll(); onWidthChanged: d.repositionAll(); From 51b41da4885ab401ab757fffe83182b7da4d6e1f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 25 Feb 2016 09:15:07 +1300 Subject: [PATCH 110/114] Horizontally center short messages in the dialog --- interface/resources/qml/dialogs/MessageDialog.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index 21d17c4e54..26ed406b02 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -105,8 +105,8 @@ ModalWindow { size: hifi.fontSizes.menuItem color: hifi.colors.baseGrayHighlight anchors { - top: parent.top; - left: parent.left; + top: parent.top + horizontalCenter: parent.horizontalCenter margins: 0 topMargin: hifi.dimensions.contentSpacing.y } From e78905a6d1906fb911b37dbb018535e9dab1146f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 24 Feb 2016 13:15:49 -0800 Subject: [PATCH 111/114] Rm previousDeltaTimeStep unused field from AvatarActionHold --- interface/src/avatar/AvatarActionHold.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 018c3fd076..1c3a4386bc 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -61,7 +61,6 @@ private: glm::vec3 _previousPositionalTarget; glm::quat _previousRotationalTarget; - float _previousDeltaTimeStep = 0.0f; glm::vec3 _previousPositionalDelta; glm::vec3 _palmOffsetFromRigidBody; From 3c4ab077bea8ac410598536f50166ef46e08f41d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 24 Feb 2016 13:16:45 -0800 Subject: [PATCH 112/114] Init validOrientation for myAvatar calc --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b080c0e283..6318a9bb1e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1684,7 +1684,7 @@ void MyAvatar::goToLocation(const QVariant& propertiesVar) { qCWarning(interfaceapp, "goToLocation called with invalid position variable"); return; } - bool validOrientation; + bool validOrientation = false; glm::quat q; if (properties.contains("orientation")) { q = quatFromVariant(properties["orientation"], validOrientation); From 124c84c8b90ecb1bfe7baebb088e62614d5691f6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 24 Feb 2016 12:54:03 -0800 Subject: [PATCH 113/114] Fix fxaa shader to use texture --- libraries/render-utils/src/fxaa.slf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/fxaa.slf b/libraries/render-utils/src/fxaa.slf index d1c50b2c58..7b241a3ebf 100644 --- a/libraries/render-utils/src/fxaa.slf +++ b/libraries/render-utils/src/fxaa.slf @@ -44,11 +44,11 @@ void main() { // fetch raw RGB values for nearby locations // sampling pattern is "five on a die" (each diagonal direction and the center) // computing the coordinates for these texture reads could be moved to the vertex shader for speed if needed - vec3 rgbNW = texture2D(colorTexture, varTexcoord + (vec2(-1.0, -1.0) * texcoordOffset)).xyz; - vec3 rgbNE = texture2D(colorTexture, varTexcoord + (vec2(+1.0, -1.0) * texcoordOffset)).xyz; - vec3 rgbSW = texture2D(colorTexture, varTexcoord + (vec2(-1.0, +1.0) * texcoordOffset)).xyz; - vec3 rgbSE = texture2D(colorTexture, varTexcoord + (vec2(+1.0, +1.0) * texcoordOffset)).xyz; - vec3 rgbM = texture2D(colorTexture, varTexcoord).xyz; + vec3 rgbNW = texture(colorTexture, varTexcoord + (vec2(-1.0, -1.0) * texcoordOffset)).xyz; + vec3 rgbNE = texture(colorTexture, varTexcoord + (vec2(+1.0, -1.0) * texcoordOffset)).xyz; + vec3 rgbSW = texture(colorTexture, varTexcoord + (vec2(-1.0, +1.0) * texcoordOffset)).xyz; + vec3 rgbSE = texture(colorTexture, varTexcoord + (vec2(+1.0, +1.0) * texcoordOffset)).xyz; + vec3 rgbM = texture(colorTexture, varTexcoord).xyz; // convert RGB values to luminance vec3 luma = vec3(0.299, 0.587, 0.114); @@ -76,11 +76,11 @@ void main() { // perform additional texture sampling perpendicular to gradient vec3 rgbA = (1.0 / 2.0) * ( - texture2D(colorTexture, varTexcoord + dir * (1.0 / 3.0 - 0.5)).xyz + - texture2D(colorTexture, varTexcoord + dir * (2.0 / 3.0 - 0.5)).xyz); + texture(colorTexture, varTexcoord + dir * (1.0 / 3.0 - 0.5)).xyz + + texture(colorTexture, varTexcoord + dir * (2.0 / 3.0 - 0.5)).xyz); vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * ( - texture2D(colorTexture, varTexcoord + dir * (0.0 / 3.0 - 0.5)).xyz + - texture2D(colorTexture, varTexcoord + dir * (3.0 / 3.0 - 0.5)).xyz); + texture(colorTexture, varTexcoord + dir * (0.0 / 3.0 - 0.5)).xyz + + texture(colorTexture, varTexcoord + dir * (3.0 / 3.0 - 0.5)).xyz); float lumaB = dot(rgbB, luma); // compare luma of new samples to the luma range of the original neighborhood From b9a1c2051b5934246d80f04a87298ac7d92353f8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 25 Feb 2016 10:52:16 +1300 Subject: [PATCH 114/114] Fix modal dialog not being opaque to mouse clicks --- .../resources/qml/windows-uit/ModalFrame.qml | 92 ++++++++++--------- .../resources/qml/windows-uit/Window.qml | 4 +- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/interface/resources/qml/windows-uit/ModalFrame.qml b/interface/resources/qml/windows-uit/ModalFrame.qml index 17b60061e8..d6c05c8f91 100644 --- a/interface/resources/qml/windows-uit/ModalFrame.qml +++ b/interface/resources/qml/windows-uit/ModalFrame.qml @@ -15,61 +15,67 @@ import "../controls-uit" import "../styles-uit" Frame { - Item { - id: modalFrame + HifiConstants { id: hifi } - anchors.fill: parent - anchors.margins: 0 + Rectangle { + id: modalFrame readonly property bool hasTitle: window.title != "" - Rectangle { - anchors { - topMargin: -hifi.dimensions.modalDialogMargin.y - (modalFrame.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0) - leftMargin: -hifi.dimensions.modalDialogMargin.x - rightMargin: -hifi.dimensions.modalDialogMargin.x - bottomMargin: -hifi.dimensions.modalDialogMargin.y - fill: parent - } - border { - width: hifi.dimensions.borderWidth - color: hifi.colors.lightGrayText80 - } - radius: hifi.dimensions.borderRadius - color: hifi.colors.faintGray + anchors { + fill: parent + topMargin: -hifi.dimensions.modalDialogMargin.y - (modalFrame.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0) + leftMargin: -hifi.dimensions.modalDialogMargin.x + rightMargin: -hifi.dimensions.modalDialogMargin.x + bottomMargin: -hifi.dimensions.modalDialogMargin.y } + border { + width: hifi.dimensions.borderWidth + color: hifi.colors.lightGrayText80 + } + radius: hifi.dimensions.borderRadius + color: hifi.colors.faintGray + Item { visible: modalFrame.hasTitle - width: title.width + (window.iconText !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0) - x: (parent.width - width) / 2 + anchors.fill: parent + anchors { + topMargin: -parent.anchors.topMargin + leftMargin: -parent.anchors.leftMargin + rightMargin: -parent.anchors.rightMargin + } - FontAwesome { - id: icon - text: window.iconText - size: 30 - color: hifi.colors.lightGrayText - visible: text != "" - y: -hifi.dimensions.modalDialogTitleHeight - 5 + Item { + width: title.width + (window.iconText !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0) + x: (parent.width - width) / 2 + + FontAwesome { + id: icon + text: window.iconText + size: 30 + color: hifi.colors.lightGrayText + visible: text != "" + y: -hifi.dimensions.modalDialogTitleHeight - 5 + anchors.left: parent.left + } + RalewayRegular { + id: title + text: window.title + elide: Text.ElideRight + color: hifi.colors.baseGrayHighlight + size: hifi.fontSizes.overlayTitle + y: -hifi.dimensions.modalDialogTitleHeight + anchors.right: parent.right + } + } + + Rectangle { anchors.left: parent.left - } - RalewayRegular { - id: title - text: window.title - elide: Text.ElideRight - color: hifi.colors.baseGrayHighlight - size: hifi.fontSizes.overlayTitle - y: -hifi.dimensions.modalDialogTitleHeight anchors.right: parent.right + height: 1 + color: hifi.colors.lightGray } } - - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: 1 - color: hifi.colors.lightGray - visible: modalFrame.hasTitle - } } } diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 2bc0175bf2..ae73a53d65 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -88,7 +88,7 @@ Fadable { property var activator: MouseArea { width: frame.decoration.width height: frame.decoration.height - x: frame.decoration.anchors.margins + x: frame.decoration.anchors.leftMargin y: frame.decoration.anchors.topMargin propagateComposedEvents: true acceptedButtons: Qt.AllButtons @@ -106,7 +106,7 @@ Fadable { property var swallower: MouseArea { width: frame.decoration.width height: frame.decoration.height - x: frame.decoration.anchors.margins + x: frame.decoration.anchors.leftMargin y: frame.decoration.anchors.topMargin hoverEnabled: true acceptedButtons: Qt.AllButtons