Merge pull request #16294 from RebeccaStankus/friction
First Time User Experience Project
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Layouts 1.3
|
||||
import "../simplifiedConstants" as SimplifiedConstants
|
||||
import "../simplifiedControls" as SimplifiedControls
|
||||
import "./components" as AvatarAppComponents
|
||||
|
@ -79,7 +80,11 @@ Rectangle {
|
|||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nInventory status: " + result.status + "\nMessage: " + result.message;
|
||||
} else if (result.data && result.data.assets && result.data.assets.length === 0 && avatarAppInventoryModel.count === 0) {
|
||||
errorText.text = "You have not created any avatars yet! Create an avatar with the Avatar Creator, then close and re-open the Avatar App."
|
||||
emptyInventoryContainer.visible = true;
|
||||
}
|
||||
|
||||
if (Settings.getValue("simplifiedUI/debugFTUE", 0) === 4) {
|
||||
emptyInventoryContainer.visible = true;
|
||||
}
|
||||
|
||||
avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result);
|
||||
|
@ -140,8 +145,95 @@ Rectangle {
|
|||
anchors.rightMargin: 24
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: emptyInventoryContainer
|
||||
visible: false
|
||||
anchors.top: displayNameHeader.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
Flickable {
|
||||
id: emptyInventoryFlickable
|
||||
anchors.fill: parent
|
||||
contentWidth: parent.width
|
||||
contentHeight: emptyInventoryLayout.height
|
||||
clip: true
|
||||
|
||||
ColumnLayout {
|
||||
id: emptyInventoryLayout
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 26
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 26
|
||||
spacing: 0
|
||||
|
||||
HifiStylesUit.GraphikSemiBold {
|
||||
text: "Stand out from the crowd!"
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: paintedHeight
|
||||
Layout.topMargin: 16
|
||||
size: 28
|
||||
color: simplifiedUI.colors.text.white
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
text: "Create your custom avatar."
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: paintedHeight
|
||||
Layout.topMargin: 2
|
||||
size: 18
|
||||
wrapMode: Text.Wrap
|
||||
color: simplifiedUI.colors.text.white
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Image {
|
||||
id: avatarImage;
|
||||
source: "images/avatarProfilePic.png"
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 450
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
mipmap: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
Image {
|
||||
source: "images/qrCode.jpg"
|
||||
Layout.preferredWidth: 190
|
||||
Layout.preferredHeight: 190
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: -160
|
||||
mipmap: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
HifiStylesUit.GraphikSemiBold {
|
||||
text: "Scan for Mobile App"
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: paintedHeight
|
||||
Layout.topMargin: 12
|
||||
size: 28
|
||||
color: simplifiedUI.colors.text.white
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimplifiedControls.VerticalScrollBar {
|
||||
parent: emptyInventoryFlickable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: avatarInfoTextContainer
|
||||
visible: !emptyInventoryContainer.visible
|
||||
width: parent.implicitWidth
|
||||
height: childrenRect.height
|
||||
anchors.top: displayNameHeader.bottom
|
||||
|
@ -164,7 +256,7 @@ Rectangle {
|
|||
id: yourAvatarsSubtitle
|
||||
text: "These are the avatars that you've created and uploaded via the Avatar Creator."
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
wrapMode: Text.Wrap
|
||||
anchors.top: yourAvatarsTitle.bottom
|
||||
anchors.topMargin: 6
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
|
@ -208,9 +300,10 @@ Rectangle {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
visible: !emptyInventoryContainer.visible
|
||||
|
||||
AnimatedImage {
|
||||
visible: !inventoryContentsList.visible && !errorText.visible
|
||||
visible: !(inventoryContentsList.visible || errorText.visible)
|
||||
anchors.centerIn: parent
|
||||
width: 72
|
||||
height: width
|
||||
|
@ -271,6 +364,8 @@ Rectangle {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
root.avatarPreviewUrl = "../../images/defaultAvatar.svg";
|
||||
}
|
||||
|
||||
function fromScript(message) {
|
||||
|
|
After Width: | Height: | Size: 319 KiB |
After Width: | Height: | Size: 159 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 145 KiB |
After Width: | Height: | Size: 151 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 148 KiB |
|
@ -54,8 +54,8 @@ Rectangle {
|
|||
|
||||
if ((MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) &&
|
||||
topBarInventoryModel.count > 0) {
|
||||
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true);
|
||||
MyAvatar.useFullAvatarURL = topBarInventoryModel.get(0).download_url;
|
||||
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", true);
|
||||
MyAvatar.useFullAvatarURL(topBarInventoryModel.get(0).download_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ Rectangle {
|
|||
if (isLoggedIn) {
|
||||
Commerce.getWalletStatus();
|
||||
} else {
|
||||
// Show some error to the user
|
||||
// Show some error to the user in the UI?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,12 +113,68 @@ Rectangle {
|
|||
topBarInventoryModel.getNextPage();
|
||||
} else {
|
||||
inventoryFullyReceived = true;
|
||||
var scriptExecutionCount = Settings.getValue("simplifiedUI/SUIScriptExecutionCount");
|
||||
var currentAvatarURL = MyAvatar.skeletonModelURL;
|
||||
var currentAvatarURLContainsDefaultAvatar = currentAvatarURL.indexOf("defaultAvatar") > -1;
|
||||
var currentAvatarURLContainsFST = currentAvatarURL.indexOf("fst") > -1;
|
||||
var currentAvatarURLContainsSimplifiedAvatar = currentAvatarURL.indexOf("simplifiedAvatar") > -1;
|
||||
var alreadyAutoSelectedAvatarFromInventory = Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", false);
|
||||
var userHasValidAvatarInInventory = topBarInventoryModel.count > 0 &&
|
||||
topBarInventoryModel.get(0).download_url.indexOf(".fst") > -1;
|
||||
var simplifiedAvatarPrefix = "https://content.highfidelity.com/Experiences/Releases/simplifiedUI/simplifiedFTUE/avatars/simplifiedAvatar_";
|
||||
var simplifiedAvatarColors = ["Blue", "Cyan", "Green", "Magenta", "Red"];
|
||||
var simplifiedAvatarSuffix = "/avatar.fst";
|
||||
|
||||
// If we have an avatar in our inventory AND we haven't already auto-selected an avatar...
|
||||
if ((!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) ||
|
||||
MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && topBarInventoryModel.count > 0) {
|
||||
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true);
|
||||
MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url;
|
||||
// Use `Settings.setValue("simplifiedUI/debugFTUE", 0);` to turn off FTUE Debug Mode.
|
||||
// Use `Settings.setValue("simplifiedUI/debugFTUE", 1);` to debug FTUE Screen 1.
|
||||
// Use `Settings.setValue("simplifiedUI/debugFTUE", 2);` to debug FTUE Screen 2.
|
||||
// Use `Settings.setValue("simplifiedUI/debugFTUE", 3);` to debug FTUE Screen 3.
|
||||
// Use `Settings.setValue("simplifiedUI/debugFTUE", 4);` to force the UI to show what would happen if the user had an empty Inventory.
|
||||
|
||||
var debugFTUE = Settings.getValue("simplifiedUI/debugFTUE", 0);
|
||||
if (debugFTUE === 1 || debugFTUE === 2) {
|
||||
scriptExecutionCount = 1;
|
||||
currentAvatarURLContainsDefaultAvatar = true;
|
||||
if (debugFTUE === 1) {
|
||||
userHasValidAvatarInInventory = false;
|
||||
currentAvatarURLContainsSimplifiedAvatar = false;
|
||||
}
|
||||
} else if (debugFTUE === 3) {
|
||||
scriptExecutionCount = 2;
|
||||
currentAvatarURLContainsDefaultAvatar = false;
|
||||
currentAvatarURLContainsSimplifiedAvatar = true;
|
||||
}
|
||||
|
||||
// If we have never auto-selected and the user is still using a default avatar or if the current avatar is not valid (fst), or if
|
||||
// the current avatar is the old default (Woody), use top avatar from inventory or one of the new defaults.
|
||||
|
||||
// If the current avatar URL is invalid, OR the user is using the "default avatar" (Woody)...
|
||||
if (!currentAvatarURLContainsFST || currentAvatarURLContainsDefaultAvatar) {
|
||||
// If the user has a valid avatar in their inventory...
|
||||
if (userHasValidAvatarInInventory) {
|
||||
// ...use the first avatar in the user's inventory.
|
||||
MyAvatar.useFullAvatarURL(topBarInventoryModel.get(0).download_url);
|
||||
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", true);
|
||||
// Else if the user isn't wearing a "Simplified Avatar"
|
||||
} else if (!currentAvatarURLContainsSimplifiedAvatar) {
|
||||
// ...assign to the user a new "Simplified Avatar" (i.e. a simple avatar of random color)
|
||||
var avatarColor = simplifiedAvatarColors[Math.floor(Math.random() * simplifiedAvatarColors.length)];
|
||||
var simplifiedAvatarModelURL = simplifiedAvatarPrefix + avatarColor + simplifiedAvatarSuffix;
|
||||
MyAvatar.useFullAvatarURL(simplifiedAvatarModelURL);
|
||||
currentAvatarURLContainsSimplifiedAvatar = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptExecutionCount === 1) {
|
||||
sendToScript({
|
||||
"source": "SimplifiedTopBar.qml",
|
||||
"method": "displayInitialLaunchWindow"
|
||||
});
|
||||
} else if (scriptExecutionCount === 2 && currentAvatarURLContainsSimplifiedAvatar) {
|
||||
sendToScript({
|
||||
"source": "SimplifiedTopBar.qml",
|
||||
"method": "displaySecondLaunchWindow"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +612,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
|
||||
function updatePreviewUrl() {
|
||||
function updatePreviewUrl() {
|
||||
var previewUrl = "";
|
||||
var downloadUrl = "";
|
||||
for (var i = 0; i < topBarInventoryModel.count; ++i) {
|
||||
|
@ -570,6 +626,8 @@ Rectangle {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
avatarButtonImage.source = "../images/defaultAvatar.svg";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,6 +52,21 @@ static const QVariantMap DOCK_AREA {
|
|||
{ "RIGHT", DockArea::RIGHT }
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* The possible "relative position anchors" of an <code>InteractiveWindow</code>. Used when defining the `relativePosition` property of an `InteractiveWindow`.
|
||||
* @typedef {object} InteractiveWindow.RelativePositionAnchors
|
||||
* @property {InteractiveWindow.RelativePositionAnchor} TOP_LEFT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the top left of the Interface window.
|
||||
* @property {InteractiveWindow.RelativePositionAnchor} TOP_RIGHT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the top right of the Interface window.
|
||||
* @property {InteractiveWindow.RelativePositionAnchor} BOTTOM_RIGHT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the bottom right of the Interface window.
|
||||
* @property {InteractiveWindow.RelativePositionAnchor} BOTTOM_LEFT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the bottom left of the Interface window.
|
||||
*/
|
||||
static const QVariantMap RELATIVE_POSITION_ANCHOR {
|
||||
{ "TOP_LEFT", RelativePositionAnchor::TOP_LEFT },
|
||||
{ "TOP_RIGHT", RelativePositionAnchor::TOP_RIGHT },
|
||||
{ "BOTTOM_RIGHT", RelativePositionAnchor::BOTTOM_RIGHT },
|
||||
{ "BOTTOM_LEFT", RelativePositionAnchor::BOTTOM_LEFT }
|
||||
};
|
||||
|
||||
DesktopScriptingInterface::DesktopScriptingInterface(QObject* parent, bool restricted)
|
||||
: QObject(parent), _restricted(restricted) { }
|
||||
|
||||
|
@ -99,6 +114,10 @@ QVariantMap DesktopScriptingInterface::getDockArea() {
|
|||
return DOCK_AREA;
|
||||
}
|
||||
|
||||
QVariantMap DesktopScriptingInterface::getRelativePositionAnchor() {
|
||||
return RELATIVE_POSITION_ANCHOR;
|
||||
}
|
||||
|
||||
void DesktopScriptingInterface::setHUDAlpha(float alpha) {
|
||||
qApp->getApplicationCompositor().setAlpha(alpha);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
* @property {InteractiveWindow.DockAreas} DockArea - The possible docking locations of an {@link InteractiveWindow}: top,
|
||||
* bottom, left, or right of the Interface window.
|
||||
* <em>Read-only.</em>
|
||||
* @property {InteractiveWindow.RelativePositionAnchors} RelativePositionAnchor - The possible "relative position anchors" for an {@link InteractiveWindow}: top left,
|
||||
* top right, bottom right, or bottom left of the Interface window.
|
||||
* <em>Read-only.</em>
|
||||
*/
|
||||
class DesktopScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -50,6 +53,7 @@ class DesktopScriptingInterface : public QObject, public Dependency {
|
|||
|
||||
Q_PROPERTY(QVariantMap PresentationMode READ getPresentationMode CONSTANT FINAL)
|
||||
Q_PROPERTY(QVariantMap DockArea READ getDockArea CONSTANT FINAL)
|
||||
Q_PROPERTY(QVariantMap RelativePositionAnchor READ getRelativePositionAnchor CONSTANT FINAL)
|
||||
Q_PROPERTY(int ALWAYS_ON_TOP READ flagAlwaysOnTop CONSTANT FINAL)
|
||||
Q_PROPERTY(int CLOSE_BUTTON_HIDES READ flagCloseButtonHides CONSTANT FINAL)
|
||||
|
||||
|
@ -106,7 +110,7 @@ private:
|
|||
Q_INVOKABLE InteractiveWindowPointer createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread);
|
||||
|
||||
static QVariantMap getDockArea();
|
||||
|
||||
static QVariantMap getRelativePositionAnchor();
|
||||
Q_INVOKABLE static QVariantMap getPresentationMode();
|
||||
const bool _restricted;
|
||||
};
|
||||
|
|
|
@ -39,6 +39,9 @@ static const char* const ADDITIONAL_FLAGS_PROPERTY = "additionalFlags";
|
|||
static const char* const OVERRIDE_FLAGS_PROPERTY = "overrideFlags";
|
||||
static const char* const SOURCE_PROPERTY = "source";
|
||||
static const char* const TITLE_PROPERTY = "title";
|
||||
static const char* const RELATIVE_POSITION_ANCHOR_PROPERTY = "relativePositionAnchor";
|
||||
static const char* const RELATIVE_POSITION_PROPERTY = "relativePosition";
|
||||
static const char* const IS_FULL_SCREEN_WINDOW = "isFullScreenWindow";
|
||||
static const char* const POSITION_PROPERTY = "position";
|
||||
static const char* const INTERACTIVE_WINDOW_POSITION_PROPERTY = "interactiveWindowPosition";
|
||||
static const char* const SIZE_PROPERTY = "size";
|
||||
|
@ -112,6 +115,14 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) {
|
|||
QCoreApplication::postEvent(QCoreApplication::instance(), event);
|
||||
}
|
||||
|
||||
void InteractiveWindow::onMainWindowGeometryChanged(QRect geometry) {
|
||||
if (_isFullScreenWindow) {
|
||||
repositionAndResizeFullScreenWindow();
|
||||
} else {
|
||||
setPositionUsingRelativePositionAndAnchor(geometry);
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveWindow::emitMainWindowResizeEvent() {
|
||||
emit qApp->getWindow()->windowGeometryChanged(qApp->getWindow()->geometry());
|
||||
}
|
||||
|
@ -184,22 +195,32 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
*/
|
||||
if (nativeWindowInfo.contains(DOCK_AREA_PROPERTY)) {
|
||||
DockArea dockedArea = (DockArea) nativeWindowInfo[DOCK_AREA_PROPERTY].toInt();
|
||||
int tempWidth = 0;
|
||||
int tempHeight = 0;
|
||||
switch (dockedArea) {
|
||||
case DockArea::TOP:
|
||||
dockArea = Qt::TopDockWidgetArea;
|
||||
_dockWidget->setFixedHeight(windowSize.height());
|
||||
tempHeight = windowSize.height();
|
||||
_dockWidget->setFixedHeight(tempHeight);
|
||||
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(0, -tempHeight));
|
||||
break;
|
||||
case DockArea::BOTTOM:
|
||||
dockArea = Qt::BottomDockWidgetArea;
|
||||
_dockWidget->setFixedHeight(windowSize.height());
|
||||
tempHeight = windowSize.height();
|
||||
_dockWidget->setFixedHeight(tempHeight);
|
||||
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(0, tempHeight));
|
||||
break;
|
||||
case DockArea::LEFT:
|
||||
dockArea = Qt::LeftDockWidgetArea;
|
||||
_dockWidget->setFixedWidth(windowSize.width());
|
||||
tempWidth = windowSize.width();
|
||||
_dockWidget->setFixedWidth(tempWidth);
|
||||
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(-tempWidth, 0));
|
||||
break;
|
||||
case DockArea::RIGHT:
|
||||
dockArea = Qt::RightDockWidgetArea;
|
||||
_dockWidget->setFixedWidth(windowSize.width());
|
||||
tempWidth = windowSize.width();
|
||||
_dockWidget->setFixedWidth(tempWidth);
|
||||
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(tempWidth, 0));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -255,6 +276,9 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
if (properties.contains(TITLE_PROPERTY)) {
|
||||
object->setProperty(TITLE_PROPERTY, properties[TITLE_PROPERTY].toString());
|
||||
}
|
||||
if (properties.contains(VISIBLE_PROPERTY)) {
|
||||
object->setProperty(VISIBLE_PROPERTY, properties[INTERACTIVE_WINDOW_VISIBLE_PROPERTY].toBool());
|
||||
}
|
||||
if (properties.contains(SIZE_PROPERTY)) {
|
||||
const auto size = vec2FromVariant(properties[SIZE_PROPERTY]);
|
||||
object->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y));
|
||||
|
@ -263,8 +287,21 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
const auto position = vec2FromVariant(properties[POSITION_PROPERTY]);
|
||||
object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
|
||||
}
|
||||
if (properties.contains(VISIBLE_PROPERTY)) {
|
||||
object->setProperty(VISIBLE_PROPERTY, properties[INTERACTIVE_WINDOW_VISIBLE_PROPERTY].toBool());
|
||||
if (properties.contains(RELATIVE_POSITION_ANCHOR_PROPERTY)) {
|
||||
_relativePositionAnchor = static_cast<RelativePositionAnchor>(properties[RELATIVE_POSITION_ANCHOR_PROPERTY].toInt());
|
||||
}
|
||||
if (properties.contains(RELATIVE_POSITION_PROPERTY)) {
|
||||
_relativePosition = vec2FromVariant(properties[RELATIVE_POSITION_PROPERTY]);
|
||||
setPositionUsingRelativePositionAndAnchor(qApp->getWindow()->geometry());
|
||||
}
|
||||
if (properties.contains(IS_FULL_SCREEN_WINDOW)) {
|
||||
_isFullScreenWindow = properties[IS_FULL_SCREEN_WINDOW].toBool();
|
||||
}
|
||||
|
||||
if (_isFullScreenWindow) {
|
||||
QRect geo = qApp->getWindow()->geometry();
|
||||
object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(geo.x(), geo.y()));
|
||||
object->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(geo.width(), geo.height()));
|
||||
}
|
||||
|
||||
// The qmlToScript method handles the thread-safety of this call. Because the QVariant argument
|
||||
|
@ -288,6 +325,8 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
connect(object, SIGNAL(interactiveWindowVisibleChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection);
|
||||
connect(object, SIGNAL(presentationModeChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection);
|
||||
#endif
|
||||
|
||||
connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &InteractiveWindow::onMainWindowGeometryChanged, Qt::QueuedConnection);
|
||||
|
||||
QUrl sourceURL{ sourceUrl };
|
||||
// If the passed URL doesn't correspond to a known scheme, assume it's a local file path
|
||||
|
@ -414,6 +453,68 @@ void InteractiveWindow::setPosition(const glm::vec2& position) {
|
|||
}
|
||||
}
|
||||
|
||||
RelativePositionAnchor InteractiveWindow::getRelativePositionAnchor() const {
|
||||
return _relativePositionAnchor;
|
||||
}
|
||||
|
||||
void InteractiveWindow::setRelativePositionAnchor(const RelativePositionAnchor& relativePositionAnchor) {
|
||||
_relativePositionAnchor = relativePositionAnchor;
|
||||
setPositionUsingRelativePositionAndAnchor(qApp->getWindow()->geometry());
|
||||
}
|
||||
|
||||
glm::vec2 InteractiveWindow::getRelativePosition() const {
|
||||
return _relativePosition;
|
||||
}
|
||||
|
||||
void InteractiveWindow::setRelativePosition(const glm::vec2& relativePosition) {
|
||||
_relativePosition = relativePosition;
|
||||
setPositionUsingRelativePositionAndAnchor(qApp->getWindow()->geometry());
|
||||
}
|
||||
|
||||
void InteractiveWindow::setPositionUsingRelativePositionAndAnchor(const QRect& mainWindowGeometry) {
|
||||
RelativePositionAnchor relativePositionAnchor = getRelativePositionAnchor();
|
||||
glm::vec2 relativePosition = getRelativePosition();
|
||||
|
||||
glm::vec2 newPosition;
|
||||
|
||||
switch (relativePositionAnchor) {
|
||||
case RelativePositionAnchor::TOP_LEFT:
|
||||
newPosition.x = mainWindowGeometry.x() + relativePosition.x;
|
||||
newPosition.y = mainWindowGeometry.y() + relativePosition.y;
|
||||
break;
|
||||
case RelativePositionAnchor::TOP_RIGHT:
|
||||
newPosition.x = mainWindowGeometry.x() + mainWindowGeometry.width() - relativePosition.x;
|
||||
newPosition.y = mainWindowGeometry.y() + relativePosition.y;
|
||||
break;
|
||||
case RelativePositionAnchor::BOTTOM_RIGHT:
|
||||
newPosition.x = mainWindowGeometry.x() + mainWindowGeometry.width() - relativePosition.x;
|
||||
newPosition.y = mainWindowGeometry.y() + mainWindowGeometry.height() - relativePosition.y;
|
||||
break;
|
||||
case RelativePositionAnchor::BOTTOM_LEFT:
|
||||
newPosition.x = mainWindowGeometry.x() + relativePosition.x;
|
||||
newPosition.y = mainWindowGeometry.y() + mainWindowGeometry.height() - relativePosition.y;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we include the dimensions of the docked widget!
|
||||
QSize dockedWidgetRelativePositionOffset = qApp->getWindow()->getDockedWidgetRelativePositionOffset();
|
||||
newPosition.x = newPosition.x + dockedWidgetRelativePositionOffset.width();
|
||||
newPosition.y = newPosition.y + dockedWidgetRelativePositionOffset.height();
|
||||
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY),
|
||||
Q_ARG(QVariant, QPointF(newPosition.x, newPosition.y)));
|
||||
}
|
||||
setPosition(newPosition);
|
||||
}
|
||||
|
||||
void InteractiveWindow::repositionAndResizeFullScreenWindow() {
|
||||
QRect windowGeometry = qApp->getWindow()->geometry();
|
||||
|
||||
setPosition(glm::vec2(windowGeometry.x(), windowGeometry.y()));
|
||||
setSize(glm::vec2(windowGeometry.width(), windowGeometry.height()));
|
||||
}
|
||||
|
||||
glm::vec2 InteractiveWindow::getSize() const {
|
||||
if (!_qmlWindowProxy) {
|
||||
return {};
|
||||
|
|
|
@ -89,6 +89,14 @@ namespace InteractiveWindowEnums {
|
|||
RIGHT
|
||||
};
|
||||
Q_ENUM_NS(DockArea);
|
||||
|
||||
enum RelativePositionAnchor {
|
||||
TOP_LEFT,
|
||||
TOP_RIGHT,
|
||||
BOTTOM_RIGHT,
|
||||
BOTTOM_LEFT
|
||||
};
|
||||
Q_ENUM_NS(RelativePositionAnchor);
|
||||
}
|
||||
|
||||
using namespace InteractiveWindowEnums;
|
||||
|
@ -121,6 +129,8 @@ class InteractiveWindow : public QObject {
|
|||
|
||||
Q_PROPERTY(QString title READ getTitle WRITE setTitle)
|
||||
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition)
|
||||
Q_PROPERTY(RelativePositionAnchor relativePositionAnchor READ getRelativePositionAnchor WRITE setRelativePositionAnchor)
|
||||
Q_PROPERTY(glm::vec2 relativePosition READ getRelativePosition WRITE setRelativePosition)
|
||||
Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize)
|
||||
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
|
||||
Q_PROPERTY(int presentationMode READ getPresentationMode WRITE setPresentationMode)
|
||||
|
@ -136,6 +146,21 @@ private:
|
|||
|
||||
Q_INVOKABLE glm::vec2 getPosition() const;
|
||||
Q_INVOKABLE void setPosition(const glm::vec2& position);
|
||||
|
||||
RelativePositionAnchor _relativePositionAnchor{ RelativePositionAnchor::TOP_LEFT };
|
||||
Q_INVOKABLE RelativePositionAnchor getRelativePositionAnchor() const;
|
||||
Q_INVOKABLE void setRelativePositionAnchor(const RelativePositionAnchor& position);
|
||||
|
||||
// This "relative position" is relative to the "relative position anchor" and excludes the window frame.
|
||||
// This position will ALWAYS include the geometry of a docked widget, if one is present.
|
||||
glm::vec2 _relativePosition{ 0.0f, 0.0f };
|
||||
Q_INVOKABLE glm::vec2 getRelativePosition() const;
|
||||
Q_INVOKABLE void setRelativePosition(const glm::vec2& position);
|
||||
|
||||
Q_INVOKABLE void setPositionUsingRelativePositionAndAnchor(const QRect& mainWindowGeometry);
|
||||
|
||||
bool _isFullScreenWindow{ false };
|
||||
Q_INVOKABLE void repositionAndResizeFullScreenWindow();
|
||||
|
||||
Q_INVOKABLE glm::vec2 getSize() const;
|
||||
Q_INVOKABLE void setSize(const glm::vec2& size);
|
||||
|
@ -320,6 +345,7 @@ protected slots:
|
|||
void forwardKeyPressEvent(int key, int modifiers);
|
||||
void forwardKeyReleaseEvent(int key, int modifiers);
|
||||
void emitMainWindowResizeEvent();
|
||||
void onMainWindowGeometryChanged(QRect geometry);
|
||||
|
||||
private:
|
||||
std::shared_ptr<QmlWindowProxy> _qmlWindowProxy;
|
||||
|
|
|
@ -24,6 +24,10 @@ public:
|
|||
~MainWindow();
|
||||
|
||||
static QWindow* findMainWindow();
|
||||
|
||||
// This offset is used for positioning children window relative to the main window.
|
||||
void setDockedWidgetRelativePositionOffset(const QSize& newOffset) { _dockedWidgetRelativePositionOffset.setWidth(newOffset.width()); _dockedWidgetRelativePositionOffset.setHeight(newOffset.height()); }
|
||||
QSize getDockedWidgetRelativePositionOffset() { return _dockedWidgetRelativePositionOffset; }
|
||||
public slots:
|
||||
void restoreGeometry();
|
||||
void saveGeometry();
|
||||
|
@ -46,6 +50,7 @@ protected:
|
|||
private:
|
||||
Setting::Handle<QRect> _windowGeometry;
|
||||
Setting::Handle<int> _windowState;
|
||||
QSize _dockedWidgetRelativePositionOffset{ 0, 0 };
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__MainWindow__) */
|
||||
|
|
|
@ -444,17 +444,9 @@ function updateEmoteIndicatorIcon(iconURL) {
|
|||
}
|
||||
|
||||
|
||||
function onGeometryChanged(rect) {
|
||||
updateEmoteAppBarPosition();
|
||||
}
|
||||
|
||||
|
||||
function onWindowMinimizedChanged(isMinimized) {
|
||||
if (isMinimized) {
|
||||
handleEmoteIndicatorVisibleChanged(false);
|
||||
} else if (!HMD.active) {
|
||||
handleEmoteIndicatorVisibleChanged(true);
|
||||
}
|
||||
isWindowMinimized = isMinimized;
|
||||
maybeChangeEmoteIndicatorVisibility(!isMinimized);
|
||||
}
|
||||
|
||||
|
||||
|
@ -539,10 +531,11 @@ function showEmoteAppBar() {
|
|||
x: EMOTE_APP_BAR_WIDTH_PX,
|
||||
y: EMOTE_APP_BAR_HEIGHT_PX
|
||||
},
|
||||
position: {
|
||||
x: Window.x + EMOTE_APP_BAR_LEFT_MARGIN,
|
||||
y: Window.y + Window.innerHeight - EMOTE_APP_BAR_BOTTOM_MARGIN
|
||||
relativePosition: {
|
||||
x: EMOTE_APP_BAR_LEFT_MARGIN,
|
||||
y: EMOTE_APP_BAR_BOTTOM_MARGIN
|
||||
},
|
||||
relativePositionAnchor: Desktop.RelativePositionAnchor.BOTTOM_LEFT,
|
||||
overrideFlags: EMOTE_APP_BAR_WINDOW_FLAGS
|
||||
});
|
||||
|
||||
|
@ -550,10 +543,18 @@ function showEmoteAppBar() {
|
|||
}
|
||||
|
||||
|
||||
function handleEmoteIndicatorVisibleChanged(shouldBeVisible) {
|
||||
if (shouldBeVisible && !emoteAppBarWindow) {
|
||||
// There is currently no property in the Window Scripting Interface to determine
|
||||
// whether the Interface window is currently minimized. This feels like an oversight.
|
||||
// We should add that functionality to the Window Scripting Interface, and remove `isWindowMinimized` below.
|
||||
var isWindowMinimized = false;
|
||||
function maybeChangeEmoteIndicatorVisibility(desiredVisibility) {
|
||||
if (isWindowMinimized || HMD.active) {
|
||||
desiredVisibility = false;
|
||||
}
|
||||
|
||||
if (desiredVisibility && !emoteAppBarWindow) {
|
||||
showEmoteAppBar();
|
||||
} else if (emoteAppBarWindow) {
|
||||
} else if (!desiredVisibility && emoteAppBarWindow) {
|
||||
emoteAppBarWindow.fromQml.disconnect(onMessageFromEmoteAppBar);
|
||||
emoteAppBarWindow.close();
|
||||
emoteAppBarWindow = false;
|
||||
|
@ -561,23 +562,25 @@ function handleEmoteIndicatorVisibleChanged(shouldBeVisible) {
|
|||
}
|
||||
|
||||
|
||||
function handleFTUEScreensVisibilityChanged(ftueScreenVisible) {
|
||||
maybeChangeEmoteIndicatorVisibility(!ftueScreenVisible);
|
||||
}
|
||||
|
||||
|
||||
function onDisplayModeChanged(isHMDMode) {
|
||||
reactionsBegun.forEach(function(react) {
|
||||
endReactionWrapper(react);
|
||||
});
|
||||
|
||||
if (isHMDMode) {
|
||||
handleEmoteIndicatorVisibleChanged(false);
|
||||
} else {
|
||||
handleEmoteIndicatorVisibleChanged(true);
|
||||
}
|
||||
maybeChangeEmoteIndicatorVisibility(!isHMDMode);
|
||||
}
|
||||
|
||||
|
||||
var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js?" + Date.now());
|
||||
var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js");
|
||||
var keyPressSignalsConnected = false;
|
||||
var emojiCodeMap;
|
||||
var customEmojiCodeMap;
|
||||
var _this;
|
||||
function setup() {
|
||||
deleteOldReticles();
|
||||
|
||||
|
@ -605,16 +608,25 @@ function setup() {
|
|||
}, {});
|
||||
|
||||
Window.minimizedChanged.connect(onWindowMinimizedChanged);
|
||||
Window.geometryChanged.connect(onGeometryChanged);
|
||||
HMD.displayModeChanged.connect(onDisplayModeChanged);
|
||||
|
||||
getSounds();
|
||||
handleEmoteIndicatorVisibleChanged(true);
|
||||
maybeChangeEmoteIndicatorVisibility(true);
|
||||
|
||||
Controller.keyPressEvent.connect(keyPressHandler);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseHandler);
|
||||
keyPressSignalsConnected = true;
|
||||
Script.scriptEnding.connect(unload);
|
||||
|
||||
function Emote() {
|
||||
_this = this;
|
||||
}
|
||||
|
||||
Emote.prototype = {
|
||||
handleFTUEScreensVisibilityChanged: handleFTUEScreensVisibilityChanged
|
||||
};
|
||||
|
||||
return new Emote();
|
||||
}
|
||||
|
||||
|
||||
|
@ -638,7 +650,6 @@ function unload() {
|
|||
maybeDeleteRemoteIndicatorTimeout();
|
||||
|
||||
Window.minimizedChanged.disconnect(onWindowMinimizedChanged);
|
||||
Window.geometryChanged.disconnect(onGeometryChanged);
|
||||
HMD.displayModeChanged.disconnect(onDisplayModeChanged);
|
||||
|
||||
if (keyPressSignalsConnected) {
|
||||
|
@ -671,7 +682,6 @@ function unload() {
|
|||
// #region EMOJI_UTILITY
|
||||
|
||||
|
||||
var EMOJI_52_BASE_URL = "../../resources/images/emojis/52px/";
|
||||
function selectedEmoji(code) {
|
||||
emojiAPI.addEmoji(code);
|
||||
// this URL needs to be relative to SimplifiedEmoteIndicator.qml
|
||||
|
@ -786,4 +796,6 @@ function toggleEmojiApp() {
|
|||
// END EMOJI
|
||||
// *************************************
|
||||
|
||||
setup();
|
||||
var emote = setup();
|
||||
|
||||
module.exports = emote;
|
350
scripts/simplifiedUI/ui/simplifiedFTUE/InitialLaunchWindow.qml
Normal file
|
@ -0,0 +1,350 @@
|
|||
//
|
||||
// InitialLaunchWindow.qml
|
||||
//
|
||||
// Copyright 2019 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.10
|
||||
import QtQuick.Controls 2.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Layouts 1.3
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import TabletScriptingInterface 1.0
|
||||
import hifi.simplifiedUI.simplifiedConstants 1.0 as SimplifiedConstants
|
||||
import hifi.simplifiedUI.simplifiedControls 1.0 as SimplifiedControls
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: simplifiedUI.colors.white
|
||||
anchors.fill: parent
|
||||
property bool landscapeOrientation: root.width > root.height
|
||||
|
||||
SimplifiedConstants.SimplifiedConstants {
|
||||
id: simplifiedUI
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
var debugFTUE = Settings.getValue("simplifiedUI/debugFTUE", 0);
|
||||
|
||||
if ((debugFTUE !== 1 &&
|
||||
(Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", false) ||
|
||||
Settings.getValue("simplifiedUI/closedAvatarPageOfInitialLaunchWindow", false))) ||
|
||||
debugFTUE === 2) {
|
||||
tempAvatarPageContainer.visible = false;
|
||||
controlsContainer.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: tempAvatarPageContainer
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
id: contentContainer
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: firstPageBottomBarContainer.top
|
||||
|
||||
Image {
|
||||
id: avatarImage
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: Math.max(parent.height - 48, 350)
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/" +
|
||||
MyAvatar.skeletonModelURL.substring(MyAvatar.skeletonModelURL.indexOf("simplifiedAvatar"), MyAvatar.skeletonModelURL.lastIndexOf("/")) + ".png"
|
||||
mipmap: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: textContainer
|
||||
clip: true
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 128
|
||||
anchors.bottom: qrAndInstructionsContainer.top
|
||||
anchors.bottomMargin: 32
|
||||
anchors.left: avatarImage.right
|
||||
anchors.leftMargin: 48
|
||||
anchors.right: parent.right
|
||||
contentWidth: width
|
||||
contentHeight: contentItem.childrenRect.height
|
||||
interactive: contentHeight > height
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: headerText
|
||||
text: "We know this isn't you..."
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 48
|
||||
height: paintedHeight
|
||||
wrapMode: Text.Wrap
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: descriptionText
|
||||
anchors.top: headerText.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.left: parent.left
|
||||
width: Math.min(700, parent.width) - headerText.anchors.rightMargin
|
||||
height: paintedHeight
|
||||
text: "...but we've given you this <b>temporary avatar</b> to use " +
|
||||
"for today. If you see this avatar in-world, walk up and " +
|
||||
"say hello to other new users!<br><br>" +
|
||||
"<b>We want you to be you</b> so we've built " +
|
||||
'<a href="https://www.highfidelity.com/knowledge/virtual-you/">Virtual You</a>, an Avatar Creator ' +
|
||||
"App. Creating an avatar is as easy as taking a selfie and picking your " +
|
||||
"outfits! Available now on iOS and Android."
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 22
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: qrAndInstructionsContainer
|
||||
anchors.left: avatarImage.right
|
||||
anchors.leftMargin: 48
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.bottom: parent.bottom
|
||||
height: 130
|
||||
|
||||
Image {
|
||||
id: avatarAppQRCodeImage
|
||||
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/qrCode.jpg"
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: 130
|
||||
mipmap: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: instructionText
|
||||
anchors.top: avatarAppQRCodeImage.top
|
||||
anchors.bottom: avatarAppQRCodeImage.bottom
|
||||
anchors.left: avatarAppQRCodeImage.right
|
||||
anchors.leftMargin: 30
|
||||
anchors.right: parent.right
|
||||
text: "Use your mobile phone to scan this QR code."
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 22
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
SimplifiedControls.VerticalScrollBar {
|
||||
parent: textContainer
|
||||
visible: parent.contentHeight > parent.height
|
||||
size: parent.height / parent.contentHeight
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: firstPageBottomBarContainer
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 32
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 32
|
||||
anchors.bottom: parent.bottom
|
||||
height: continueLink.height + 48
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: continueLink
|
||||
anchors.centerIn: parent
|
||||
text: "Continue >"
|
||||
width: parent.width
|
||||
height: paintedHeight
|
||||
color: simplifiedUI.colors.text.lightBlue
|
||||
opacity: continueMouseArea.containsMouse ? 1.0 : 0.7
|
||||
size: 36
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
MouseArea {
|
||||
id: continueMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
tempAvatarPageContainer.visible = false;
|
||||
Settings.setValue("simplifiedUI/closedAvatarPageOfInitialLaunchWindow", true);
|
||||
controlsContainer.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: controlsContainer
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: controlsDescriptionText
|
||||
text: "Use these avatar controls to<br><b>interact with and move around in your new HQ.</b>"
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 48
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 32
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 32
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
height: paintedHeight
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 36
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.top: controlsDescriptionText.bottom
|
||||
anchors.topMargin: 16
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: bottomBarContainer.top
|
||||
|
||||
GridView {
|
||||
id: controlsGrid
|
||||
property int maxColumns: 2
|
||||
property int idealCellWidth: 361
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
cellWidth: width / Math.min(Math.floor(width / idealCellWidth), maxColumns)
|
||||
cellHeight: 225
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
imageHeight: 198
|
||||
imageSource: "images/walkingControls.png"
|
||||
}
|
||||
ListElement {
|
||||
imageHeight: 193
|
||||
imageSource: "images/mouseControls.png"
|
||||
}
|
||||
ListElement {
|
||||
imageHeight: 146
|
||||
imageSource: "images/runJumpControls.png"
|
||||
}
|
||||
ListElement {
|
||||
imageHeight: 96
|
||||
imageSource: "images/cameraControls.png"
|
||||
}
|
||||
}
|
||||
delegate: Rectangle {
|
||||
height: GridView.view.cellHeight
|
||||
width: GridView.view.cellWidth
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
width: parent.GridView.view.idealCellWidth
|
||||
height: model.imageHeight
|
||||
source: model.imageSource
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimplifiedControls.VerticalScrollBar {
|
||||
parent: controlsGrid
|
||||
anchors.topMargin: 96
|
||||
anchors.bottomMargin: anchors.topMargin
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: bottomBarContainer
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 32
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 32
|
||||
anchors.bottom: parent.bottom
|
||||
height: iHaveAGoodGrip.height + learnMoreLink.height + 48
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: iHaveAGoodGrip
|
||||
anchors.centerIn: parent
|
||||
text: "I've got a good grip on the controls."
|
||||
width: parent.width
|
||||
height: paintedHeight
|
||||
color: simplifiedUI.colors.text.lightBlue
|
||||
opacity: goodGripMouseArea.containsMouse ? 1.0 : 0.7
|
||||
size: 36
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
MouseArea {
|
||||
id: goodGripMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
sendToScript({
|
||||
"source": "InitialLaunchWindow.qml",
|
||||
"method": "closeInitialLaunchWindow"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: learnMoreLink
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.top: iHaveAGoodGrip.bottom
|
||||
anchors.topMargin: 8
|
||||
text: "Learn more about our controls."
|
||||
width: paintedWidth
|
||||
height: paintedHeight
|
||||
color: simplifiedUI.colors.text.lightBlue
|
||||
opacity: learnMoreAboutControlsMouseArea.containsMouse ? 1.0 : 0.7
|
||||
size: 14
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
MouseArea {
|
||||
id: learnMoreAboutControlsMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
Qt.openUrlExternally("https://www.highfidelity.com/knowledge/get-around");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: topLeftAccentImage
|
||||
width: 400
|
||||
height: 180
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
source: "images/defaultTopLeft.png"
|
||||
}
|
||||
|
||||
Image {
|
||||
id: bottomRightAccentImage
|
||||
width: 80
|
||||
height: 250
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
source: "images/defaultBottomRight.png"
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
}
|
186
scripts/simplifiedUI/ui/simplifiedFTUE/SecondLaunchWindow.qml
Normal file
|
@ -0,0 +1,186 @@
|
|||
//
|
||||
// SecondLaunchWindow.qml
|
||||
//
|
||||
// Copyright 2019 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.10
|
||||
import QtQuick.Controls 2.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Layouts 1.3
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import TabletScriptingInterface 1.0
|
||||
import hifi.simplifiedUI.simplifiedConstants 1.0 as SimplifiedConstants
|
||||
import hifi.simplifiedUI.simplifiedControls 1.0 as SimplifiedControls
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: simplifiedUI.colors.white
|
||||
anchors.fill: parent
|
||||
|
||||
SimplifiedConstants.SimplifiedConstants {
|
||||
id: simplifiedUI
|
||||
}
|
||||
|
||||
Item {
|
||||
id: contentContainer
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: continueLink.top
|
||||
|
||||
Image {
|
||||
id: avatarImage
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: Math.max(parent.height - 48, 350)
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/hero.png"
|
||||
mipmap: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 196
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 32
|
||||
anchors.left: avatarImage.right
|
||||
anchors.leftMargin: 48
|
||||
anchors.right: parent.right
|
||||
|
||||
Flickable {
|
||||
id: textContainer
|
||||
clip: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: Math.min(700, parent.width)
|
||||
contentWidth: width
|
||||
contentHeight: contentItem.childrenRect.height
|
||||
interactive: contentHeight > height
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: headerText
|
||||
text: "Stand out from the crowd!"
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 48
|
||||
height: paintedHeight
|
||||
wrapMode: Text.Wrap
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: descriptionText
|
||||
anchors.top: headerText.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.left: parent.left
|
||||
width: parent.width - headerText.anchors.rightMargin
|
||||
height: paintedHeight
|
||||
text: "You can create and upload custom avatars from our Avatar Creator App. " +
|
||||
"It's as easy as taking a selfie.<br>Available now on iOS and Android Platforms."
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 22
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Item {
|
||||
id: qrAndInstructionsContainer
|
||||
anchors.top: descriptionText.bottom
|
||||
anchors.topMargin: 24
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
height: avatarAppQRCodeImage.height
|
||||
|
||||
Image {
|
||||
id: avatarAppQRCodeImage
|
||||
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/qrCode.jpg"
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 130
|
||||
height: width
|
||||
mipmap: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: instructionText
|
||||
anchors.top: avatarAppQRCodeImage.top
|
||||
anchors.bottom: avatarAppQRCodeImage.bottom
|
||||
anchors.left: avatarAppQRCodeImage.right
|
||||
anchors.leftMargin: 30
|
||||
anchors.right: parent.right
|
||||
text: "Use your mobile phone to scan this QR code."
|
||||
color: simplifiedUI.colors.text.black
|
||||
size: 22
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimplifiedControls.VerticalScrollBar {
|
||||
parent: textContainer
|
||||
visible: parent.contentHeight > parent.height
|
||||
size: parent.height / parent.contentHeight
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HifiStylesUit.RalewayBold {
|
||||
id: continueLink
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
height: 96
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: "No thanks, I'll keep using my default avatar."
|
||||
color: simplifiedUI.colors.text.lightBlue
|
||||
opacity: continueMouseArea.containsMouse ? 1.0 : 0.7
|
||||
size: 24
|
||||
|
||||
MouseArea {
|
||||
id: continueMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
sendToScript({
|
||||
"source": "SecondLaunchWindow.qml",
|
||||
"method": "closeSecondLaunchWindow"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: topLeftAccentImage
|
||||
width: 130
|
||||
height: 320
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
source: "images/standOutTopLeft.png"
|
||||
}
|
||||
|
||||
Image {
|
||||
id: bottomRightAccentImage
|
||||
width: 250
|
||||
height: 80
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
source: "images/standOutBottomRight.png"
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
}
|
BIN
scripts/simplifiedUI/ui/simplifiedFTUE/images/cameraControls.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
BIN
scripts/simplifiedUI/ui/simplifiedFTUE/images/defaultTopLeft.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
scripts/simplifiedUI/ui/simplifiedFTUE/images/mouseControls.png
Normal file
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 9.7 KiB |
|
@ -14,7 +14,6 @@
|
|||
|
||||
|
||||
// START CONFIG OPTIONS
|
||||
var DOCKED_QML_SUPPORTED = true;
|
||||
var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system";
|
||||
var DEFAULT_SCRIPTS_PATH_PREFIX = ScriptDiscoveryService.defaultScriptsPath + "/";
|
||||
// END CONFIG OPTIONS
|
||||
|
@ -352,6 +351,124 @@ function setOutputMuted(outputMuted) {
|
|||
}
|
||||
}
|
||||
|
||||
var TOP_BAR_HEIGHT_PX = 48;
|
||||
var INITIAL_LAUNCH_QML_PATH = Script.resolvePath("./simplifiedFTUE/InitialLaunchWindow.qml");
|
||||
var INITIAL_LAUNCH_WINDOW_TITLE = "Initial Launch";
|
||||
var INITIAL_LAUNCH_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
|
||||
var INITIAL_WINDOW_FLAGS = 0x00000001 | // Qt::Window
|
||||
0x00000008 | // Qt::Popup
|
||||
0x00000002 | // Qt::Tool
|
||||
0x00000800 | // Qt::FramelessWindowHint
|
||||
0x40000000; // Qt::NoDropShadowWindowHint
|
||||
var initialLaunchWindow = false;
|
||||
function displayInitialLaunchWindow() {
|
||||
if (initialLaunchWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
simplifiedEmote.handleFTUEScreensVisibilityChanged(true);
|
||||
|
||||
initialLaunchWindow = Desktop.createWindow(INITIAL_LAUNCH_QML_PATH, {
|
||||
title: INITIAL_LAUNCH_WINDOW_TITLE,
|
||||
presentationMode: INITIAL_LAUNCH_PRESENTATION_MODE,
|
||||
isFullScreenWindow: true,
|
||||
overrideFlags: INITIAL_WINDOW_FLAGS
|
||||
});
|
||||
|
||||
initialLaunchWindow.fromQml.connect(onMessageFromInitialLaunchWindow);
|
||||
|
||||
Window.location = "file:///~/serverless/tutorial.json";
|
||||
}
|
||||
|
||||
var SECOND_LAUNCH_QML_PATH = Script.resolvePath("simplifiedFTUE/SecondLaunchWindow.qml");
|
||||
var SECOND_LAUNCH_WINDOW_TITLE = "Second Launch";
|
||||
var SECOND_LAUNCH_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
|
||||
var SECOND_WINDOW_FLAGS = 0x00000001 | // Qt::Window
|
||||
0x00000008 | // Qt::Popup
|
||||
0x00000002 | // Qt::Tool
|
||||
0x00000800 | // Qt::FramelessWindowHint
|
||||
0x40000000; // Qt::NoDropShadowWindowHint
|
||||
var secondLaunchWindow = false;
|
||||
function displaySecondLaunchWindow() {
|
||||
if (secondLaunchWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
simplifiedEmote.handleFTUEScreensVisibilityChanged(true);
|
||||
|
||||
secondLaunchWindow = Desktop.createWindow(SECOND_LAUNCH_QML_PATH, {
|
||||
title: SECOND_LAUNCH_WINDOW_TITLE,
|
||||
presentationMode: SECOND_LAUNCH_PRESENTATION_MODE,
|
||||
isFullScreenWindow: true,
|
||||
overrideFlags: SECOND_WINDOW_FLAGS
|
||||
});
|
||||
|
||||
secondLaunchWindow.fromQml.connect(onMessageFromSecondLaunchWindow);
|
||||
|
||||
Window.location = "file:///~/serverless/tutorial.json";
|
||||
}
|
||||
|
||||
function closeInitialLaunchWindow() {
|
||||
if (initialLaunchWindow) {
|
||||
initialLaunchWindow.fromQml.disconnect(onMessageFromInitialLaunchWindow);
|
||||
initialLaunchWindow.close();
|
||||
initialLaunchWindow = null;
|
||||
}
|
||||
|
||||
simplifiedEmote.handleFTUEScreensVisibilityChanged(false);
|
||||
}
|
||||
|
||||
function closeSecondLaunchWindow() {
|
||||
if (secondLaunchWindow) {
|
||||
secondLaunchWindow.fromQml.disconnect(onMessageFromSecondLaunchWindow);
|
||||
secondLaunchWindow.close();
|
||||
secondLaunchWindow = null;
|
||||
}
|
||||
|
||||
simplifiedEmote.handleFTUEScreensVisibilityChanged(false);
|
||||
}
|
||||
|
||||
var INITIAL_LAUNCH_WINDOW_MESSAGE_SOURCE = "InitialLaunchWindow.qml";
|
||||
function onMessageFromInitialLaunchWindow(message) {
|
||||
if (message.source !== INITIAL_LAUNCH_WINDOW_MESSAGE_SOURCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.method) {
|
||||
case "closeInitialLaunchWindow":
|
||||
closeInitialLaunchWindow();
|
||||
var homeLocation = LocationBookmarks.getAddress("hqhome");
|
||||
if (homeLocation) {
|
||||
Window.location = homeLocation;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("Unrecognized message from " + INITIAL_LAUNCH_WINDOW_MESSAGE_SOURCE + ": " + JSON.stringify(message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var SECOND_LAUNCH_WINDOW_MESSAGE_SOURCE = "SecondLaunchWindow.qml";
|
||||
function onMessageFromSecondLaunchWindow(message) {
|
||||
if (message.source !== SECOND_LAUNCH_WINDOW_MESSAGE_SOURCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.method) {
|
||||
case "closeSecondLaunchWindow":
|
||||
closeSecondLaunchWindow();
|
||||
var homeLocation = LocationBookmarks.getAddress("hqhome");
|
||||
if (homeLocation) {
|
||||
Window.location = homeLocation;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("Unrecognized message from " + SECOND_LAUNCH_WINDOW_MESSAGE_SOURCE + ": " + JSON.stringify(message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var WAIT_FOR_TOP_BAR_MS = 1000;
|
||||
function sendLocalStatusToQml() {
|
||||
|
@ -397,6 +514,14 @@ function onMessageFromTopBar(message) {
|
|||
si.toggleStatus();
|
||||
break;
|
||||
|
||||
case "displayInitialLaunchWindow":
|
||||
displayInitialLaunchWindow();
|
||||
break;
|
||||
|
||||
case "displaySecondLaunchWindow":
|
||||
displaySecondLaunchWindow();
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message));
|
||||
break;
|
||||
|
@ -425,7 +550,6 @@ var TOP_BAR_QML_PATH = Script.resourcesPath() + "qml/hifi/simplifiedUI/topBar/Si
|
|||
var TOP_BAR_WINDOW_TITLE = "Simplified Top Bar";
|
||||
var TOP_BAR_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
|
||||
var TOP_BAR_WIDTH_PX = Window.innerWidth;
|
||||
var TOP_BAR_HEIGHT_PX = 48;
|
||||
var topBarWindow = false;
|
||||
function loadSimplifiedTopBar() {
|
||||
var windowProps = {
|
||||
|
@ -436,16 +560,9 @@ function loadSimplifiedTopBar() {
|
|||
y: TOP_BAR_HEIGHT_PX
|
||||
}
|
||||
};
|
||||
if (DOCKED_QML_SUPPORTED) {
|
||||
windowProps.presentationWindowInfo = {
|
||||
dockArea: Desktop.DockArea.TOP
|
||||
};
|
||||
} else {
|
||||
windowProps.position = {
|
||||
x: Window.x,
|
||||
y: Window.y
|
||||
};
|
||||
}
|
||||
windowProps.presentationWindowInfo = {
|
||||
dockArea: Desktop.DockArea.TOP
|
||||
};
|
||||
topBarWindow = Desktop.createWindow(TOP_BAR_QML_PATH, windowProps);
|
||||
|
||||
topBarWindow.fromQml.connect(onMessageFromTopBar);
|
||||
|
@ -510,21 +627,38 @@ function onHMDInputDeviceMutedChanged(isMuted) {
|
|||
function onGeometryChanged(rect) {
|
||||
updateInputDeviceMutedOverlay(Audio.muted);
|
||||
updateOutputDeviceMutedOverlay(isOutputMuted());
|
||||
if (topBarWindow && !DOCKED_QML_SUPPORTED) {
|
||||
topBarWindow.size = {
|
||||
"x": rect.width,
|
||||
"y": TOP_BAR_HEIGHT_PX
|
||||
};
|
||||
topBarWindow.position = {
|
||||
"x": rect.x,
|
||||
"y": rect.y
|
||||
};
|
||||
}
|
||||
|
||||
var initialLaunchWindowIsMinimized = false;
|
||||
var secondLaunchWindowIsMinimized = false;
|
||||
function onWindowMinimizedChanged(isMinimized) {
|
||||
if (isMinimized) {
|
||||
handleInitialLaunchWindowVisibleChanged(false);
|
||||
handleSecondLaunchWindowVisibleChanged(false);
|
||||
} else if (!HMD.active) {
|
||||
handleInitialLaunchWindowVisibleChanged(true);
|
||||
handleSecondLaunchWindowVisibleChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
function onWindowMinimizedChanged() {
|
||||
// prerequisite placeholder for Reduce Friction of Customer Acquisition sub task: https://highfidelity.atlassian.net/browse/DEV-585
|
||||
print("WINDOW MINIMIZED CHANGED SIGNAL");
|
||||
function handleInitialLaunchWindowVisibleChanged(shouldBeVisible) {
|
||||
if (shouldBeVisible && !initialLaunchWindow && initialLaunchWindowIsMinimized) {
|
||||
displayInitialLaunchWindow();
|
||||
initialLaunchWindowIsMinimized = false;
|
||||
} else if (!shouldBeVisible && initialLaunchWindow) {
|
||||
closeInitialLaunchWindow();
|
||||
initialLaunchWindowIsMinimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
function handleSecondLaunchWindowVisibleChanged(shouldBeVisible) {
|
||||
if (shouldBeVisible && !secondLaunchWindow && secondLaunchWindowIsMinimized) {
|
||||
displaySecondLaunchWindow();
|
||||
secondLaunchWindowIsMinimized = false;
|
||||
} else if (!shouldBeVisible && secondLaunchWindow) {
|
||||
closeSecondLaunchWindow();
|
||||
secondLaunchWindowIsMinimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
function onDisplayModeChanged(isHMDMode) {
|
||||
|
@ -534,8 +668,12 @@ function onDisplayModeChanged(isHMDMode) {
|
|||
|
||||
if (isHMDMode) {
|
||||
onHMDInputDeviceMutedChanged(Audio.mutedHMD);
|
||||
handleInitialLaunchWindowVisibleChanged(false);
|
||||
handleSecondLaunchWindowVisibleChanged(false);
|
||||
} else {
|
||||
onDesktopInputDeviceMutedChanged(Audio.mutedDesktop);
|
||||
handleInitialLaunchWindowVisibleChanged(true);
|
||||
handleSecondLaunchWindowVisibleChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -578,9 +716,9 @@ function restoreLODSettings() {
|
|||
}
|
||||
|
||||
|
||||
var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now());
|
||||
var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now());
|
||||
var emote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now());
|
||||
var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js");
|
||||
var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js");
|
||||
var simplifiedEmote = Script.require("../simplifiedEmote/simplifiedEmote.js");
|
||||
var oldShowAudioTools;
|
||||
var oldShowBubbleTools;
|
||||
var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false);
|
||||
|
@ -647,6 +785,14 @@ function shutdown() {
|
|||
settingsAppWindow.close();
|
||||
}
|
||||
|
||||
if (initialLaunchWindow) {
|
||||
closeInitialLaunchWindow();
|
||||
}
|
||||
|
||||
if (secondLaunchWindow) {
|
||||
closeSecondLaunchWindow();
|
||||
}
|
||||
|
||||
maybeDeleteInputDeviceMutedOverlay();
|
||||
maybeDeleteOutputDeviceMutedOverlay();
|
||||
|
||||
|
|