diff --git a/BUILD.md b/BUILD.md index bd264a74ad..c9bb48d4b7 100644 --- a/BUILD.md +++ b/BUILD.md @@ -106,3 +106,4 @@ The following build options can be used when running CMake #### Devices You can support external input/output devices such as Leap Motion, MIDI, and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. + \ No newline at end of file diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 2d5c68c0e8..e3cd492edb 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -13,15 +13,14 @@ import QtQuick 2.4 import controlsUit 1.0 as HifiControlsUit import stylesUit 1.0 as HifiStylesUit -import "LoginDialog" - FocusScope { id: root - HifiStylesUit.HifiConstants { id: hifi } objectName: "LoginDialog" property bool shown: true visible: shown + HifiStylesUit.HifiConstants { id: hifi } + anchors.fill: parent readonly property bool isTablet: false @@ -33,12 +32,17 @@ FocusScope { property bool keyboardRaised: false property bool punctuationMode: false property bool isPassword: false - property string title: "" - property string text: "" - property int titleWidth: 0 + property alias bannerWidth: banner.width property alias bannerHeight: banner.height + property string title: "" + property string text: "" + + property int titleWidth: 0 + + property bool isHMD: HMD.active + function tryDestroy() { root.destroy() } diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 8d6444bc0e..b01bb5b761 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -23,43 +23,36 @@ FocusScope { objectName: "LoginDialog" visible: true + HifiStylesUit.HifiConstants { id: hifi } + anchors.fill: parent - width: parent.width - height: parent.height - property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system"); - - property bool isHMD: HMD.active - property bool gotoPreviousApp: false; + readonly property bool isTablet: true + readonly property bool isOverlay: false + property string iconText: hifi.glyphs.avatar + property int iconSize: 35 property bool keyboardEnabled: false property bool keyboardRaised: false property bool punctuationMode: false property bool isPassword: false - readonly property bool isTablet: true - readonly property bool isOverlay: false - property alias text: loginKeyboard.mirroredText - - property int titleWidth: 0 property alias bannerWidth: banner.width property alias bannerHeight: banner.height - property string iconText: hifi.glyphs.avatar - property int iconSize: 35 - property var pane: QtObject { - property real width: root.width - property real height: root.height - } + property int titleWidth: 0 - function tryDestroy() { - tabletProxy.gotoHomeScreen(); - } + property bool isHMD: HMD.active - MouseArea { - width: root.width - height: root.height - } + // TABLET SPECIFIC PROPERTIES START // + property alias text: loginKeyboard.mirroredText + + width: parent.width + height: parent.height + + property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system") + + property bool gotoPreviousApp: false property bool keyboardOverride: true @@ -70,7 +63,20 @@ FocusScope { property alias loginDialog: loginDialog property alias hifi: hifi - HifiStylesUit.HifiConstants { id: hifi } + property var pane: QtObject { + property real width: root.width + property real height: root.height + } + + MouseArea { + width: root.width + height: root.height + } + // TABLET SPECIFIC PROPERTIES END // + + function tryDestroy() { + tabletProxy.gotoHomeScreen(); + } Timer { id: keyboardTimer @@ -102,6 +108,15 @@ FocusScope { anchors.fill: parent } + Rectangle { + z: -6 + id: opaqueRect + height: parent.height + width: parent.width + opacity: 0.65 + color: "black" + } + Item { z: -5 id: bannerContainer @@ -119,15 +134,6 @@ FocusScope { } } - Rectangle { - z: -6 - id: opaqueRect - height: parent.height - width: parent.width - opacity: 0.65 - color: "black" - } - HifiControlsUit.Keyboard { id: loginKeyboard raised: root.keyboardEnabled && root.keyboardRaised diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml index 957df6d584..ef9a3cbe24 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml @@ -122,7 +122,7 @@ Rectangle { Tablet.playSound(TabletEnums.ButtonClick); // Can't use `Window.location` in QML, so just use what setting `Window.location` actually calls under the hood: // AddressManager.handleLookupString(). - AddressManager.handleLookupString(LocationBookmarks.getHomeLocationAddress()); + AddressManager.handleLookupString(LocationBookmarks.getAddress("hqhome")); } } } diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 85b3cf149f..42d53d3f79 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -47,6 +47,12 @@ Rectangle { onSkeletonModelURLChanged: { root.updatePreviewUrl(); + + if ((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; + } } } @@ -95,7 +101,8 @@ Rectangle { inventoryFullyReceived = true; // If we have an avatar in our inventory AND we haven't already auto-selected an avatar... - if (!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) && topBarInventoryModel.count > 0) { + 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; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2f9a151c2f..f9470782bf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2708,6 +2708,7 @@ void Application::cleanupBeforeQuit() { } getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + getEntities()->clear(); // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) QThreadPool::globalInstance()->clear(); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index bb8b7ba7f4..efe3d59d90 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -490,7 +490,7 @@ void AvatarManager::buildPhysicsTransaction(PhysicsEngine::Transaction& transact _myAvatar->getCharacterController()->buildPhysicsTransaction(transaction); for (auto avatar : _otherAvatarsToChangeInPhysics) { bool isInPhysics = avatar->isInPhysicsSimulation(); - if (isInPhysics != avatar->shouldBeInPhysicsSimulation()) { + if (isInPhysics != avatar->shouldBeInPhysicsSimulation() || avatar->_needsReinsertion) { if (isInPhysics) { transaction.objectsToRemove.push_back(avatar->_motionState); avatar->_motionState = nullptr; diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 02ec62e6a5..b87e3a3dbc 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -262,7 +262,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, processing, 0) STATS_PROPERTY(int, processingPending, 0) STATS_PROPERTY(int, triangles, 0) - STATS_PROPERTY(uint32_t, drawcalls, 0) + STATS_PROPERTY(quint32 , drawcalls, 0) STATS_PROPERTY(int, materialSwitches, 0) STATS_PROPERTY(int, itemConsidered, 0) STATS_PROPERTY(int, itemOutOfView, 0) diff --git a/launchers/darwin/images/interface.icns b/launchers/darwin/images/interface.icns index 4aeb8301ce..8dadfd5037 100644 Binary files a/launchers/darwin/images/interface.icns and b/launchers/darwin/images/interface.icns differ diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index f586269864..d60c4080a2 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -46,6 +46,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; } -(void)awakeFromNib { + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(didTerminateApp:) name:NSWorkspaceDidTerminateApplicationNotification @@ -114,6 +115,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; userInfo:nil repeats:NO]; } + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; } - (void) setDownloadContextFilename:(NSString *)aFilename @@ -277,6 +279,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; -(void)onSplashScreenTimerFinished:(NSTimer *)timer { + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; [self showLoginScreen]; } @@ -336,6 +339,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUI/"]; NSString* domainUrl = [[Settings sharedSettings] getDomainUrl]; NSString* userToken = [[Launcher sharedLauncher] getTokenString]; + NSString* homeBookmark = [[NSString stringWithFormat:@"hqhome="] stringByAppendingString:domainUrl]; NSArray* arguments; if (userToken != nil) { arguments = [NSArray arrayWithObjects: @@ -344,6 +348,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; @"--cache", contentPath, @"--displayName", displayName, @"--scripts", scriptsPath, + @"--setBookmark", homeBookmark, @"--no-updater", @"--no-launcher", nil]; } else { @@ -351,6 +356,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; @"--url" , domainUrl, @"--cache", contentPath, @"--scripts", scriptsPath, + @"--setBookmark", homeBookmark, @"--no-updater", @"--no-launcher", nil]; } diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 35903a0887..fc79287457 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -234,9 +234,10 @@ HWND LauncherManager::launchApplication() { CString parsedTokens = _tokensJSON; parsedTokens.Replace(_T("\""), _T("\\\"")); tokensParam = _T("--tokens \""); - tokensParam += parsedTokens + _T("\""); + tokensParam += parsedTokens + _T("\" "); } - CString params = urlParam + scriptsParam + cacheParam + nameParam + tokensParam + EXTRA_PARAMETERS; + CString bookmarkParam = _T("--setBookmark hqhome=\"") + _domainURL + ("\" "); + CString params = urlParam + scriptsParam + cacheParam + nameParam + tokensParam + bookmarkParam + EXTRA_PARAMETERS; _shouldLaunch = FALSE; return LauncherUtils::executeOnForeground(interfaceExe, params); } diff --git a/launchers/win32/res/interface.ico b/launchers/win32/res/interface.ico index cdd4792f56..09a97956a7 100644 Binary files a/launchers/win32/res/interface.ico and b/launchers/win32/res/interface.ico differ diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 0748790df9..b40de7e42a 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -343,4 +343,4 @@ PulsePropertyGroup WebEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; }); -} \ No newline at end of file +} diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 86b33bbe20..be63956191 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -306,7 +306,8 @@ void NodeList::sendDomainServerCheckIn() { // may be called by multiple threads. if (!_sendDomainServerCheckInEnabled) { - qCDebug(networking_ice) << "Refusing to send a domain-server check in while it is disabled."; + static const QString DISABLED_CHECKIN_DEBUG{ "Refusing to send a domain-server check in while it is disabled." }; + HIFI_FCDEBUG(networking_ice(), DISABLED_CHECKIN_DEBUG); return; } @@ -450,13 +451,17 @@ void NodeList::sendDomainServerCheckIn() { // Send duplicate check-ins in the exponentially increasing sequence 1, 1, 2, 4, ... static const int MAX_CHECKINS_TOGETHER = 20; - static const int REBIND_CHECKIN_COUNT = 2; int outstandingCheckins = _domainHandler.getCheckInPacketsSinceLastReply(); + /* + static const int WARNING_CHECKIN_COUNT = 2; + if (outstandingCheckins > WARNING_CHECKIN_COUNT) { + // We may be headed for a disconnect, as we've written two DomainListRequests without getting anything back. + // In some cases, we've found that nothing is going out on the wire despite not getting any errors from + // sendPacket => writeDatagram, below. In at least some such cases, we've found that the DomainDisconnectRequest + // does go through, so let's at least try to mix it up with a different safe packet. + // TODO: send ICEPing, and later on tell the other nodes to shut up for a moment. - if (outstandingCheckins > REBIND_CHECKIN_COUNT) { - _nodeSocket.rebind(); - } - + }*/ int checkinCount = outstandingCheckins > 1 ? std::pow(2, outstandingCheckins - 2) : 1; checkinCount = std::min(checkinCount, MAX_CHECKINS_TOGETHER); for (int i = 1; i < checkinCount; ++i) { diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index fc6d2cbe2a..3a7a056c77 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -230,7 +230,7 @@ qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& soc // _udpSocket.writeDatagram will return an error anyway, but there are // potential crashes in Qt when that happens. if (_udpSocket.state() != QAbstractSocket::BoundState) { - qCDebug(networking) << "Attempt to writeDatagram when in unbound state"; + qCDebug(networking) << "Attempt to writeDatagram when in unbound state to" << sockAddr; return -1; } qint64 bytesWritten = _udpSocket.writeDatagram(datagram, sockAddr.getAddress(), sockAddr.getPort()); @@ -240,11 +240,11 @@ qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& soc #ifdef WIN32 wsaError = WSAGetLastError(); #endif - qCDebug(networking) << "udt::writeDatagram (" << _udpSocket.state() << ") error - " << wsaError << _udpSocket.error() << "(" << _udpSocket.errorString() << ")" + qCDebug(networking) << "udt::writeDatagram (" << _udpSocket.state() << sockAddr << ") error - " << wsaError << _udpSocket.error() << "(" << _udpSocket.errorString() << ")" << (pending ? "pending bytes:" : "pending:") << pending; #ifdef DEBUG_EVENT_QUEUE int nodeListQueueSize = ::hifi::qt::getEventQueueSize(thread()); - qCDebug(networking) << "Networking queue size - " << nodeListQueueSize; + qCDebug(networking) << "Networking queue size - " << nodeListQueueSize << "writing datagram to" << sockAddr; #endif // DEBUG_EVENT_QUEUE } diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index ec0fad5ff0..34cac90a05 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -686,43 +686,52 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n return; } -#if !defined(Q_OS_ANDROID) - // if HMD is being worn, allow keyboard to open. allow it to close, HMD or not. - if (!raised || qApp->property(hifi::properties::HMD).toBool()) { - QQuickItem* item = dynamic_cast(object); - if (!item) { - return; - } + bool android = false; +#if defined(Q_OS_ANDROID) + android = true; +#endif - // for future probably makes sense to consider one of the following: - // 1. make keyboard a singleton, which will be dynamically re-parented before showing - // 2. track currently visible keyboard somewhere, allow to subscribe for this signal - // any of above should also eliminate need in duplicated properties and code below + bool hmd = qApp->property(hifi::properties::HMD).toBool(); - while (item) { - // Numeric value may be set in parameter from HTML UI; for QML UI, detect numeric fields here. - numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox"; - - if (item->property("keyboardRaised").isValid()) { - // FIXME - HMD only: Possibly set value of "keyboardEnabled" per isHMDMode() for use in WebView.qml. - if (item->property("punctuationMode").isValid()) { - item->setProperty("punctuationMode", QVariant(numeric)); - } - if (item->property("passwordField").isValid()) { - item->setProperty("passwordField", QVariant(passwordField)); - } - - if (raised) { - item->setProperty("keyboardRaised", QVariant(!raised)); - } - - item->setProperty("keyboardRaised", QVariant(raised)); + if (!android || hmd) { + // if HMD is being worn, allow keyboard to open. allow it to close, HMD or not. + if (!raised || hmd) { + QQuickItem* item = dynamic_cast(object); + if (!item) { return; } - item = dynamic_cast(item->parentItem()); + + // for future probably makes sense to consider one of the following: + // 1. make keyboard a singleton, which will be dynamically re-parented before showing + // 2. track currently visible keyboard somewhere, allow to subscribe for this signal + // any of above should also eliminate need in duplicated properties and code below + + while (item) { + // Numeric value may be set in parameter from HTML UI; for QML UI, detect numeric fields here. + numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox"; + + if (item->property("keyboardRaised").isValid()) { + + if (item->property("punctuationMode").isValid()) { + item->setProperty("punctuationMode", QVariant(numeric)); + } + if (item->property("passwordField").isValid()) { + item->setProperty("passwordField", QVariant(passwordField)); + } + + if (hmd && item->property("keyboardEnabled").isValid()) { + item->setProperty("keyboardEnabled", true); + } + + item->setProperty("keyboardRaised", QVariant(raised)); + + return; + } + item = dynamic_cast(item->parentItem()); + } } } -#endif + } void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) { diff --git a/scripts/simplifiedUI/system/progress.js b/scripts/simplifiedUI/system/progress.js index b373612790..a641dd4556 100644 --- a/scripts/simplifiedUI/system/progress.js +++ b/scripts/simplifiedUI/system/progress.js @@ -83,9 +83,7 @@ // The initial delay cooldown keeps us from tracking progress before the allotted time // has passed. INITIAL_DELAY_COOLDOWN_TIME = 1000, - initialDelayCooldown = 0, - - isInInterstitialMode = false; + initialDelayCooldown = 0; function fade() { @@ -267,7 +265,7 @@ // Update state if (!visible) { // Not visible because no recent downloads - if ((displayProgress < 100 || gpuTextures > 0) && !isInInterstitialMode && !isInterstitialOverlaysVisible) { // Have started downloading so fade in + if (displayProgress < 100 || gpuTextures > 0) { // Have started downloading so fade in visible = true; alphaDelta = ALPHA_DELTA_IN; fadeTimer = Script.setInterval(fade, FADE_INTERVAL); @@ -307,9 +305,6 @@ } else { x = x * BAR_HMD_REPEAT; } - if (isInInterstitialMode || isInterstitialOverlaysVisible) { - visible = false; - } // Update progress bar Overlays.editOverlay(barDesktop.overlay, { @@ -349,10 +344,6 @@ } } - function interstitialModeChanged(inMode) { - isInInterstitialMode = inMode; - } - function setUp() { var is4k = Window.innerWidth > 3000; @@ -378,7 +369,6 @@ } setUp(); - Window.interstitialModeChanged.connect(interstitialModeChanged); GlobalServices.downloadInfoChanged.connect(onDownloadInfoChanged); GlobalServices.updateDownloadInfo(); Script.setInterval(update, 1000 / 60); diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index 16f081fb6b..70679b09bd 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -415,7 +415,7 @@ function getInputDeviceMutedOverlayTopY() { var inputDeviceMutedOverlay = false; var INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_X_PX = 353; var INPUT_DEVICE_MUTED_OVERLAY_DEFAULT_Y_PX = 95; -var INPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX = 20; +var INPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX = 20 + TOP_BAR_HEIGHT_PX; function updateInputDeviceMutedOverlay(isMuted) { if (isMuted) { var props = {