Merge branch 'master' of github.com:highfidelity/hifi into wall

This commit is contained in:
Sam Gateau 2019-06-19 13:06:20 -07:00
commit 7ad0975528
60 changed files with 904 additions and 365 deletions

View file

@ -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.

View file

@ -33,7 +33,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
Download and install the latest version of CMake 3.9.
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.9 Version page](https://cmake.org/files/v3.9/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
### Step 3. Create VCPKG environment variable
In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.

View file

@ -739,6 +739,10 @@ void DomainServer::setupNodeListAndAssignments() {
connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded);
connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, this,
[this](const HifiSockAddr& localSockAddr) {
DependencyManager::get<LimitedNodeList>()->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, localSockAddr.getPort());
});
// register as the packet receiver for the types we want
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
@ -1735,7 +1739,12 @@ void DomainServer::nodePingMonitor() {
nodeList->eachNode([now](const SharedNodePointer& node) {
quint64 lastHeard = now - node->getLastHeardMicrostamp();
if (lastHeard > 2 * USECS_PER_SECOND) {
qCDebug(domain_server) << "Haven't heard from " << node->getPublicSocket() << " in " << lastHeard / USECS_PER_MSEC << " msec";
QString username;
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
if (nodeData) {
username = nodeData->getUsername();
}
qCDebug(domain_server) << "Haven't heard from " << node->getPublicSocket() << username << " in " << lastHeard / USECS_PER_MSEC << " msec";
}
});
}

View file

@ -58,6 +58,7 @@ Windows.Window {
}
QmlSurface.load(source, contentHolder, function(newObject) {
dynamicContent = newObject;
updateInteractiveWindowSizeForMode();
if (dynamicContent && dynamicContent.anchors) {
dynamicContent.anchors.fill = contentHolder;
}
@ -81,10 +82,12 @@ Windows.Window {
}
function updateInteractiveWindowSizeForMode() {
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
width = interactiveWindowSize.width;
height = interactiveWindowSize.height;
} else if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
root.width = interactiveWindowSize.width;
root.height = interactiveWindowSize.height;
contentHolder.width = interactiveWindowSize.width;
contentHolder.height = interactiveWindowSize.height;
if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
nativeWindow.width = interactiveWindowSize.width;
nativeWindow.height = interactiveWindowSize.height;
}
@ -134,6 +137,9 @@ Windows.Window {
Window {
id: root;
width: interactiveWindowSize.width
height: interactiveWindowSize.height
Rectangle {
color: hifi.colors.baseGray
anchors.fill: parent

View file

@ -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()
}

View file

@ -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

View file

@ -75,21 +75,31 @@ ListModel {
// 1: equivalent to paging when reaching end (and not before).
// 0: don't getNextPage on scroll at all here. The application code will do it.
property real pageAhead: 2.0;
function needsEarlyYFetch() {
return flickable
&& !flickable.atYBeginning
&& (flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height));
function onContentXChanged() {
if (flickable &&
!flickable.atXBeginning &&
(flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width))) {
getNextPage();
}
}
function needsEarlyXFetch() {
return flickable
&& !flickable.atXBeginning
&& (flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width));
function onContentYChanged() {
if (flickable &&
!flickable.atYBeginning &&
(flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height))) {
getNextPage();
}
}
function getNextPageIfHorizontalScroll() {
if (needsEarlyXFetch()) { getNextPage(); }
function onWidthChanged() {
if (flickable &&
(flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width))) {
getNextPage();
}
}
function getNextPageIfVerticalScroll() {
if (needsEarlyYFetch()) { getNextPage(); }
function onHeightChanged() {
if (flickable &&
(flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height))) {
getNextPage();
}
}
function needsMoreHorizontalResults() {
return flickable
@ -118,8 +128,10 @@ ListModel {
initialized = true;
if (flickable && pageAhead > 0.0) {
// Pun: Scrollers are usually one direction or another, such that only one of the following will actually fire.
flickable.contentXChanged.connect(getNextPageIfHorizontalScroll);
flickable.contentYChanged.connect(getNextPageIfVerticalScroll);
flickable.contentXChanged.connect(onContentXChanged);
flickable.contentYChanged.connect(onContentYChanged);
flickable.widthChanged.connect(onWidthChanged);
flickable.heightChanged.connect(onHeightChanged);
flickable.contentWidthChanged.connect(getNextPageIfNotEnoughHorizontalResults);
flickable.contentHeightChanged.connect(getNextPageIfNotEnoughVerticalResults);
}

View file

@ -0,0 +1,3 @@
module hifiModels
PSFListModel 1.0 PSFListModel.qml
S3Model 1.0 S3Model.qml

View file

@ -10,6 +10,7 @@
import QtQuick 2.10
import "../simplifiedConstants" as SimplifiedConstants
import "../simplifiedControls" as SimplifiedControls
import "./components" as AvatarAppComponents
import stylesUit 1.0 as HifiStylesUit
import TabletScriptingInterface 1.0
@ -245,6 +246,10 @@ Rectangle {
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
SimplifiedControls.VerticalScrollBar {
parent: inventoryContentsList
}
}

View file

@ -94,6 +94,7 @@ Item {
text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName
maximumLength: 256
clip: true
selectByMouse: true
anchors.fill: parent
onEditingFinished: {
if (MyAvatar.displayName !== text) {

View file

@ -9,12 +9,15 @@
//
import QtQuick 2.10
import QtQuick.Controls 2.3
import "../simplifiedConstants" as SimplifiedConstants
import "../simplifiedControls" as SimplifiedControls
import stylesUit 1.0 as HifiStylesUit
import "./audio" as AudioSettings
import "./general" as GeneralSettings
import "./vr" as VrSettings
import "./dev" as DevSettings
import "./about" as AboutSettings
Rectangle {
property string activeTabView: "generalTabView"
@ -74,6 +77,10 @@ Rectangle {
tabTitle: "VR"
tabViewName: "vrTabView"
}
ListElement {
tabTitle: "About"
tabViewName: "aboutTabView"
}
ListElement {
tabTitle: "Dev"
tabViewName: "devTabView"
@ -101,7 +108,7 @@ Rectangle {
delegate: Item {
visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled)
width: tabTitleText.paintedWidth + 64
width: tabTitleText.paintedWidth + 32
height: parent.height
HifiStylesUit.GraphikRegular {
@ -129,9 +136,7 @@ Rectangle {
id: tabViewContainers
anchors.top: tabContainer.bottom
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.bottom: parent.bottom
@ -162,24 +167,28 @@ Rectangle {
visible: activeTabView === "devTabView"
anchors.fill: parent
}
}
Image {
source: {
if (root.activeTabView === "generalTabView") {
"images/accent1.svg"
} else if (root.activeTabView === "audioTabView") {
"images/accent2.svg"
} else if (root.activeTabView === "vrTabView") {
"images/accent3.svg"
} else {
"images/accent3.svg"
AboutSettings.About {
id: aboutTabViewContainer
visible: activeTabView === "aboutTabView"
anchors.fill: parent
}
SimplifiedControls.VerticalScrollBar {
parent: {
if (activeTabView === "generalTabView") {
generalTabViewContainer
} else if (activeTabView === "audioTabView") {
audioTabViewContainer
} else if (activeTabView === "vrTabView") {
vrTabViewContainer
} else if (activeTabView === "devTabView") {
devTabViewContainer
} else if (activeTabView === "aboutTabView") {
aboutTabViewContainer
}
}
}
anchors.right: parent.right
anchors.top: tabContainer.bottom
width: 106
height: 200
}

View file

@ -0,0 +1,218 @@
//
// About.qml
//
// Created by Zach Fox on 2019-06-18
// 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 "../../simplifiedConstants" as SimplifiedConstants
import "../../simplifiedControls" as SimplifiedControls
import stylesUit 1.0 as HifiStylesUit
import QtQuick.Layouts 1.3
Flickable {
id: root
contentWidth: parent.width
contentHeight: aboutColumnLayout.height
clip: true
onVisibleChanged: {
if (visible) {
root.contentX = 0;
root.contentY = 0;
}
}
SimplifiedConstants.SimplifiedConstants {
id: simplifiedUI
}
ColumnLayout {
id: aboutColumnLayout
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top
spacing: 0
Image {
source: "images/logo.png"
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 16
Layout.preferredWidth: 200
Layout.preferredHeight: 150
fillMode: Image.PreserveAspectFit
mipmap: true
}
ColumnLayout {
id: platformInfoContainer
Layout.preferredWidth: parent.width
Layout.bottomMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {
text: "Version " + Window.checkVersion()
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikSemiBold {
text: "Platform Info"
Layout.maximumWidth: parent.width
Layout.topMargin: 8
Layout.bottomMargin: 8
height: paintedHeight
size: 22
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b>Computer Vendor/Model:</b>"
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
Component.onCompleted: {
var computer = JSON.parse(PlatformInfo.getComputer());
var computerVendor = computer.vendor;
if (computerVendor.length === 0) {
computerVendor = "Unknown";
}
var computerModel = computer.model;
if (computerModel.length === 0) {
computerModel = "Unknown";
}
text = "<b>Computer Vendor/Model:</b> " + computerVendor + "/" + computerModel;
}
}
HifiStylesUit.GraphikRegular {
text: "<b>Profiled Platform Tier:</b> " + PlatformInfo.getTierProfiled()
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b>OS Type:</b> " + PlatformInfo.getOperatingSystemType()
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b>CPU:</b> " + PlatformInfo.getCPUBrand()
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b># CPUs:</b> " + PlatformInfo.getNumCPUs()
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b># CPU Cores:</b> " + PlatformInfo.getNumLogicalCores()
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b>RAM:</b> " + PlatformInfo.getTotalSystemMemoryMB() + " MB"
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b>GPU:</b> " + PlatformInfo.getGraphicsCardType()
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "<b>VR Hand Controllers:</b> " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"))
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
}
SimplifiedControls.Button {
Layout.topMargin: 8
width: 200
height: 32
text: "Copy to Clipboard"
onClicked: {
Window.copyToClipboard(root.buildPlatformInfoTextToCopy());
}
}
}
}
function buildPlatformInfoTextToCopy() {
var textToCopy = "**About Interface**\n";
textToCopy += "Interface Version: " + Window.checkVersion() + "\n";
textToCopy += "\n**Platform Info**\n";
var computer = JSON.parse(PlatformInfo.getComputer());
var computerVendor = computer.vendor;
if (computerVendor.length === 0) {
computerVendor = "Unknown";
}
var computerModel = computer.model;
if (computerModel.length === 0) {
computerModel = "Unknown";
}
textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n";
textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n";
textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n";
textToCopy += "CPU: " + PlatformInfo.getCPUBrand() + "\n";
textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n";
textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n";
textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n";
textToCopy += "GPU: " + PlatformInfo.getGraphicsCardType() + "\n";
textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"));
return textToCopy;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -19,8 +19,6 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: audioColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true
function changePeakValuesEnabled(enabled) {
@ -33,7 +31,7 @@ Flickable {
AudioScriptingInterface.devices.input.peakValuesEnabled = visible;
if (visible) {
root.contentX = 0;
root.contentY = -root.topMargin;
root.contentY = 0;
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(changePeakValuesEnabled);
} else {
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.disconnect(changePeakValuesEnabled);
@ -45,16 +43,35 @@ Flickable {
id: simplifiedUI
}
Image {
id: accent
source: "../images/accent2.svg"
anchors.left: parent.left
anchors.top: parent.top
width: 83
height: 156
transform: Scale {
xScale: -1
origin.x: accent.width / 2
origin.y: accent.height / 2
}
}
ColumnLayout {
id: audioColumnLayout
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout {
id: volumeControlsContainer
Layout.preferredWidth: parent.width
Layout.topMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {
@ -289,6 +306,7 @@ Flickable {
ColumnLayout {
id: outputDeviceContainer
Layout.preferredWidth: parent.width
Layout.bottomMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {

View file

@ -19,14 +19,12 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: devColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true
onVisibleChanged: {
if (visible) {
root.contentX = 0;
root.contentY = -root.topMargin;
root.contentY = 0;
}
}
@ -35,16 +33,36 @@ Flickable {
id: simplifiedUI
}
Image {
id: accent
source: "../images/accent3.svg"
anchors.left: parent.left
anchors.top: parent.top
width: 83
height: 156
transform: Scale {
xScale: -1
origin.x: accent.width / 2
origin.y: accent.height / 2
}
}
ColumnLayout {
id: devColumnLayout
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout {
id: uiControlsContainer
Layout.preferredWidth: parent.width
Layout.topMargin: 24
Layout.bottomMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {

View file

@ -9,6 +9,7 @@
//
import QtQuick 2.10
import QtQuick.Controls 2.3
import "../../simplifiedConstants" as SimplifiedConstants
import "../../simplifiedControls" as SimplifiedControls
import stylesUit 1.0 as HifiStylesUit
@ -20,8 +21,6 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: generalColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true
onAvatarNametagModeChanged: {
@ -31,7 +30,7 @@ Flickable {
onVisibleChanged: {
if (visible) {
root.contentX = 0;
root.contentY = -root.topMargin;
root.contentY = 0;
}
}
@ -39,16 +38,35 @@ Flickable {
id: simplifiedUI
}
Image {
id: accent
source: "../images/accent1.svg"
anchors.left: parent.left
anchors.top: parent.top
width: 83
height: 156
transform: Scale {
xScale: -1
origin.x: accent.width / 2
origin.y: accent.height / 2
}
}
ColumnLayout {
id: generalColumnLayout
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout {
id: avatarNameTagsContainer
Layout.preferredWidth: parent.width
Layout.topMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {
@ -193,29 +211,36 @@ Flickable {
}
}
HifiStylesUit.GraphikRegular {
id: logoutText
text: (AccountServices.username === "Unknown user" ? "Log In" : "Logout " + AccountServices.username)
wrapMode: Text.Wrap
width: paintedWidth
height: paintedHeight
size: 14
color: simplifiedUI.colors.text.lightBlue
ColumnLayout {
id: logoutContainer
Layout.preferredWidth: parent.width
Layout.bottomMargin: 24
spacing: 0
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
parent.color = simplifiedUI.colors.text.lightBlueHover;
}
onExited: {
parent.color = simplifiedUI.colors.text.lightBlue;
}
onClicked: {
if (Account.loggedIn) {
AccountServices.logOut();
} else {
DialogsManager.showLoginDialog();
HifiStylesUit.GraphikRegular {
id: logoutText
text: (AccountServices.username === "Unknown user" ? "Log In" : "Logout " + AccountServices.username)
wrapMode: Text.Wrap
width: paintedWidth
height: paintedHeight
size: 14
color: simplifiedUI.colors.text.lightBlue
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
parent.color = simplifiedUI.colors.text.lightBlueHover;
}
onExited: {
parent.color = simplifiedUI.colors.text.lightBlue;
}
onClicked: {
if (Account.loggedIn) {
AccountServices.logOut();
} else {
DialogsManager.showLoginDialog();
}
}
}
}

View file

@ -19,8 +19,6 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: vrColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true
function changePeakValuesEnabled(enabled) {
@ -33,7 +31,7 @@ Flickable {
AudioScriptingInterface.devices.input.peakValuesEnabled = visible;
if (visible) {
root.contentX = 0;
root.contentY = -root.topMargin;
root.contentY = 0;
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(changePeakValuesEnabled);
} else {
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.disconnect(changePeakValuesEnabled);
@ -45,16 +43,35 @@ Flickable {
id: simplifiedUI
}
Image {
id: accent
source: "../images/accent3.svg"
anchors.left: parent.left
anchors.top: parent.top
width: 83
height: 156
transform: Scale {
xScale: -1
origin.x: accent.width / 2
origin.y: accent.height / 2
}
}
ColumnLayout {
id: vrColumnLayout
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout {
id: controlsContainer
Layout.preferredWidth: parent.width
Layout.topMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {
@ -278,6 +295,7 @@ Flickable {
ColumnLayout {
id: outputDeviceContainer
Layout.preferredWidth: parent.width
Layout.bottomMargin: 24
spacing: 0
HifiStylesUit.GraphikSemiBold {

View file

@ -144,6 +144,10 @@ QtObject {
readonly property color hover: "#FFFFFF"
readonly property color focus: "#FFFFFF"
}
readonly property QtObject scrollBar: QtObject {
readonly property color background: "#474747"
readonly property color contentItem: "#0198CB"
}
}
readonly property color darkSeparator: "#595959"
@ -219,6 +223,10 @@ QtObject {
readonly property QtObject textField: QtObject {
readonly property int editPencilPadding: 6
}
readonly property QtObject scrollBar: QtObject {
readonly property int backgroundWidth: 9
readonly property int contentItemWidth: 7
}
}
}

View file

@ -0,0 +1,51 @@
//
// VerticalScrollBar.qml
//
// Created by Zach Fox on 2019-06-17
// 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 "../simplifiedConstants" as SimplifiedConstants
ScrollBar {
SimplifiedConstants.SimplifiedConstants {
id: simplifiedUI
}
orientation: Qt.Vertical
policy: ScrollBar.AlwaysOn
anchors.top: parent.top
anchors.topMargin: 4
anchors.right: parent.right
anchors.rightMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
width: simplifiedUI.sizes.controls.scrollBar.backgroundWidth
visible: parent.contentHeight > parent.parent.height
position: parent.contentY / parent.contentHeight
size: parent.parent.height / parent.contentHeight
minimumSize: 0.1
background: Rectangle {
color: simplifiedUI.colors.controls.scrollBar.background
anchors.fill: parent
}
contentItem: Rectangle {
width: simplifiedUI.sizes.controls.scrollBar.contentItemWidth
color: simplifiedUI.colors.controls.scrollBar.contentItem
anchors {
horizontalCenter: parent.horizontalCenter
topMargin: 1
bottomMargin: 1
}
}
onPositionChanged: {
if (pressed) {
parent.contentY = position * parent.contentHeight;
}
}
}

View file

@ -48,7 +48,8 @@ Rectangle {
onSkeletonModelURLChanged: {
root.updatePreviewUrl();
if (MyAvatar.skeletonModelURL.indexOf("defaultAvatar" > -1) && topBarInventoryModel.count > 0) {
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;
}
@ -100,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;
}

View file

@ -435,7 +435,7 @@ DetailedMotionState* AvatarManager::createDetailedMotionState(OtherAvatarPointer
return nullptr;
}
void AvatarManager::rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction, OtherAvatarPointer avatar) {
void AvatarManager::rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar) {
if (!avatar->_motionState) {
avatar->_motionState = new AvatarMotionState(avatar, nullptr);
}
@ -452,20 +452,24 @@ void AvatarManager::rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction
transaction.objectsToAdd.push_back(motionState);
}
motionState->clearIncomingDirtyFlags();
}
// Rather than reconcile numbers of joints after change to model or LOD
// we blow away old detailedMotionStates and create anew all around.
void AvatarManager::removeDetailedAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar) {
// delete old detailedMotionStates
auto& detailedMotionStates = avatar->getDetailedMotionStates();
if (detailedMotionStates.size() != 0) {
for (auto& detailedMotionState : detailedMotionStates) {
transaction.objectsToRemove.push_back(detailedMotionState);
}
avatar->resetDetailedMotionStates();
avatar->forgetDetailedMotionStates();
}
}
// build new detailedMotionStates
void AvatarManager::rebuildDetailedAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar) {
// Rather than reconcile numbers of joints after change to model or LOD
// we blow away old detailedMotionStates and create anew all around.
removeDetailedAvatarPhysics(transaction, avatar);
auto& detailedMotionStates = avatar->getDetailedMotionStates();
OtherAvatar::BodyLOD lod = avatar->getBodyLOD();
if (lod == OtherAvatar::BodyLOD::Sphere) {
auto dMotionState = createDetailedMotionState(avatar, -1);
@ -483,24 +487,21 @@ void AvatarManager::rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction
}
}
}
avatar->_needsReinsertion = false;
avatar->_needsDetailedRebuild = false;
}
void AvatarManager::buildPhysicsTransaction(PhysicsEngine::Transaction& transaction) {
_myAvatar->getCharacterController()->buildPhysicsTransaction(transaction);
for (auto avatar : _otherAvatarsToChangeInPhysics) {
bool isInPhysics = avatar->isInPhysicsSimulation();
if (isInPhysics != avatar->shouldBeInPhysicsSimulation() || avatar->_needsReinsertion) {
if (isInPhysics != avatar->shouldBeInPhysicsSimulation()) {
if (isInPhysics) {
transaction.objectsToRemove.push_back(avatar->_motionState);
avatar->_motionState = nullptr;
auto& detailedMotionStates = avatar->getDetailedMotionStates();
for (auto& motionState : detailedMotionStates) {
transaction.objectsToRemove.push_back(motionState);
}
avatar->resetDetailedMotionStates();
removeDetailedAvatarPhysics(transaction, avatar);
} else {
rebuildAvatarPhysics(transaction, avatar);
rebuildDetailedAvatarPhysics(transaction, avatar);
}
} else if (isInPhysics) {
AvatarMotionState* motionState = avatar->_motionState;
@ -519,6 +520,10 @@ void AvatarManager::buildPhysicsTransaction(PhysicsEngine::Transaction& transact
}
motionState->clearIncomingDirtyFlags();
}
if (avatar->_needsDetailedRebuild) {
rebuildDetailedAvatarPhysics(transaction, avatar);
}
}
}
_otherAvatarsToChangeInPhysics.clear();

View file

@ -274,7 +274,9 @@ public slots:
protected:
AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override;
DetailedMotionState* createDetailedMotionState(OtherAvatarPointer avatar, int32_t jointIndex);
void rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction, OtherAvatarPointer avatar);
void rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar);
void removeDetailedAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar);
void rebuildDetailedAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar);
private:
explicit AvatarManager(QObject* parent = 0);

View file

@ -1416,6 +1416,10 @@ void MyAvatar::setEnableDebugDrawAnimPose(bool isEnabled) {
}
}
void MyAvatar::setDebugDrawAnimPoseName(QString poseName) {
_debugDrawAnimPoseName.set(poseName);
}
void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
if (isEnabled) {
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
@ -3086,15 +3090,26 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
}
if (_enableDebugDrawAnimPose && animSkeleton) {
// build absolute AnimPoseVec from rig
AnimPoseVec absPoses;
const Rig& rig = _skeletonModel->getRig();
absPoses.reserve(rig.getJointStateCount());
for (int i = 0; i < rig.getJointStateCount(); i++) {
absPoses.push_back(AnimPose(rig.getJointTransform(i)));
const glm::vec4 CYAN(0.1f, 0.6f, 0.6f, 1.0f);
QString name = _debugDrawAnimPoseName.get();
if (name.isEmpty()) {
// build absolute AnimPoseVec from rig transforms. i.e. the same that are used for rendering.
absPoses.reserve(rig.getJointStateCount());
for (int i = 0; i < rig.getJointStateCount(); i++) {
absPoses.push_back(AnimPose(rig.getJointTransform(i)));
}
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN);
} else {
AnimNode::ConstPointer node = rig.findAnimNodeByName(name);
if (node) {
rig.buildAbsoluteRigPoses(node->getPoses(), absPoses);
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN);
}
}
glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f);
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, cyan);
}
}

View file

@ -2018,12 +2018,20 @@ public slots:
void setEnableDebugDrawDefaultPose(bool isEnabled);
/**jsdoc
* Displays animation debug graphics.
* Displays animation debug graphics. By default it shows the animation poses used for rendering.
* However, the property MyAvatar.setDebugDrawAnimPoseName can be used to draw a specific animation node.
* @function MyAvatar.setEnableDebugDrawAnimPose
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
*/
void setEnableDebugDrawAnimPose(bool isEnabled);
/**jsdoc
* If set it determines which animation debug graphics to draw, when MyAvatar.setEnableDebugDrawAnimPose is set to true.
* @function MyAvatar.setDebugDrawAnimPoseName
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
*/
void setDebugDrawAnimPoseName(QString poseName);
/**jsdoc
* Displays position debug graphics.
* @function MyAvatar.setEnableDebugDrawPosition
@ -2666,6 +2674,8 @@ private:
bool _enableDebugDrawIKChains { false };
bool _enableDebugDrawDetailedCollision { false };
ThreadSafeValueCache<QString> _debugDrawAnimPoseName;
mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state?
AudioListenerMode _audioListenerMode;

View file

@ -398,15 +398,13 @@ DetailedMotionState* MyCharacterController::createDetailedMotionStateForJoint(in
}
void MyCharacterController::clearDetailedMotionStates() {
// we don't actually clear the MotionStates here
// instead we twiddle some flags as a signal of what to do later
_pendingFlags |= PENDING_FLAG_REMOVE_DETAILED_FROM_SIMULATION;
// We make sure we don't add them again
_pendingFlags &= ~PENDING_FLAG_ADD_DETAILED_TO_SIMULATION;
}
void MyCharacterController::resetDetailedMotionStates() {
_detailedMotionStates.clear();
}
void MyCharacterController::buildPhysicsTransaction(PhysicsEngine::Transaction& transaction) {
for (size_t i = 0; i < _detailedMotionStates.size(); i++) {
_detailedMotionStates[i]->forceActive();
@ -416,6 +414,8 @@ void MyCharacterController::buildPhysicsTransaction(PhysicsEngine::Transaction&
for (size_t i = 0; i < _detailedMotionStates.size(); i++) {
transaction.objectsToRemove.push_back(_detailedMotionStates[i]);
}
// NOTE: the DetailedMotionStates are deleted after being added to PhysicsEngine::Transaction::_objectsToRemove
// See AvatarManager::handleProcessedPhysicsTransaction()
_detailedMotionStates.clear();
}
if (_pendingFlags & PENDING_FLAG_ADD_DETAILED_TO_SIMULATION) {

View file

@ -48,7 +48,6 @@ public:
DetailedMotionState* createDetailedMotionStateForJoint(int32_t jointIndex);
std::vector<DetailedMotionState*>& getDetailedMotionStates() { return _detailedMotionStates; }
void clearDetailedMotionStates();
void resetDetailedMotionStates();
void buildPhysicsTransaction(PhysicsEngine::Transaction& transaction);

View file

@ -177,7 +177,7 @@ const btCollisionShape* OtherAvatar::createCollisionShape(int32_t jointIndex, bo
return ObjectMotionState::getShapeManager()->getShape(shapeInfo);
}
void OtherAvatar::resetDetailedMotionStates() {
void OtherAvatar::forgetDetailedMotionStates() {
// NOTE: the DetailedMotionStates are deleted after being added to PhysicsEngine::Transaction::_objectsToRemove
// See AvatarManager::handleProcessedPhysicsTransaction()
_detailedMotionStates.clear();
@ -209,7 +209,7 @@ void OtherAvatar::computeShapeLOD() {
if (newLOD != _bodyLOD) {
_bodyLOD = newLOD;
if (isInPhysicsSimulation()) {
_needsReinsertion = true;
_needsDetailedRebuild = true;
}
}
}
@ -224,14 +224,14 @@ bool OtherAvatar::shouldBeInPhysicsSimulation() const {
bool OtherAvatar::needsPhysicsUpdate() const {
constexpr uint32_t FLAGS_OF_INTEREST = Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS | Simulation::DIRTY_POSITION | Simulation::DIRTY_COLLISION_GROUP;
return (_needsReinsertion || (_motionState && (bool)(_motionState->getIncomingDirtyFlags() & FLAGS_OF_INTEREST)));
return (_needsDetailedRebuild || (_motionState && (bool)(_motionState->getIncomingDirtyFlags() & FLAGS_OF_INTEREST)));
}
void OtherAvatar::rebuildCollisionShape() {
if (_motionState) {
// do not actually rebuild here, instead flag for later
_motionState->addDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
_needsReinsertion = true;
_needsDetailedRebuild = true;
}
}

View file

@ -54,7 +54,7 @@ public:
const btCollisionShape* createCollisionShape(int32_t jointIndex, bool& isBound, std::vector<int32_t>& boundJoints);
std::vector<DetailedMotionState*>& getDetailedMotionStates() { return _detailedMotionStates; }
void resetDetailedMotionStates();
void forgetDetailedMotionStates();
BodyLOD getBodyLOD() { return _bodyLOD; }
void computeShapeLOD();
@ -90,7 +90,7 @@ protected:
int32_t _spaceIndex { -1 };
uint8_t _workloadRegion { workload::Region::INVALID };
BodyLOD _bodyLOD { BodyLOD::Sphere };
bool _needsReinsertion { false };
bool _needsDetailedRebuild { false };
};
using OtherAvatarPointer = std::shared_ptr<OtherAvatar>;

View file

@ -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)

View file

@ -64,7 +64,8 @@ function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
endfunction()
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME}
MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME})
set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "")
if (LAUNCHER_HMAC_SECRET STREQUAL "")
message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set")

View file

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<string>${APP_NAME}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
@ -29,7 +29,9 @@
<string>Window</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleDisplayName</key>
<string>HQ Launcher</string>
<string>CFBundleName</string>
</dict>
</plist>

View file

@ -25,7 +25,7 @@
break;
case CHECKING_UPDATE:
[self.boldStatus setStringValue:@"Getting updates..."];
[self.smallStatus setStringValue:@"We're getting the lastest and greatest for you, one sec."];
[self.smallStatus setStringValue:@"We're getting the latest and greatest for you, one sec."];
break;
case RUNNING_INTERFACE_AFTER_UPDATE:
[self.boldStatus setStringValue:@"You're good to go!"];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -10,10 +10,13 @@
#include "AnimClip.h"
#include <assert.h>
#include "GLMHelpers.h"
#include "AnimationLogging.h"
#include "AnimUtil.h"
AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) :
AnimNode(AnimNode::Type::Clip, id),
_startFrame(startFrame),
@ -107,6 +110,19 @@ static std::vector<int> buildJointIndexMap(const AnimSkeleton& dstSkeleton, cons
return jointIndexMap;
}
#ifdef USE_CUSTOM_ASSERT
#undef ASSERT
#define ASSERT(x) \
do { \
if (!(x)) { \
int* bad_ptr = 0; \
*bad_ptr = 0x0badf00d; \
} \
} while (0)
#else
#define ASSERT assert
#endif
void AnimClip::copyFromNetworkAnim() {
assert(_networkAnim && _networkAnim->isLoaded() && _skeleton);
_anim.clear();
@ -165,11 +181,14 @@ void AnimClip::copyFromNetworkAnim() {
for (int frame = 0; frame < animFrameCount; frame++) {
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
ASSERT(frame >= 0 && frame < (int)animModel.animationFrames.size());
// extract the full rotations from the animFrame (including pre and post rotations from the animModel).
std::vector<glm::quat> animRotations;
animRotations.reserve(animJointCount);
for (int i = 0; i < animJointCount; i++) {
ASSERT(i >= 0 && i < (int)animModel.joints.size());
ASSERT(i >= 0 && i < (int)animFrame.rotations.size());
animRotations.push_back(animModel.joints[i].preRotation * animFrame.rotations[i] * animModel.joints[i].postRotation);
}
@ -180,10 +199,12 @@ void AnimClip::copyFromNetworkAnim() {
std::vector<glm::quat> avatarRotations;
avatarRotations.reserve(avatarJointCount);
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size());
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
if (animJointIndex >= 0) {
// This joint is in both animation and avatar.
// Set the absolute rotation directly
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animRotations.size());
avatarRotations.push_back(animRotations[animJointIndex]);
} else {
// This joint is NOT in the animation at all.
@ -192,6 +213,7 @@ void AnimClip::copyFromNetworkAnim() {
glm::quat avatarParentAbsoluteRot;
int avatarParentJointIndex = avatarSkeleton->getParentIndex(avatarJointIndex);
if (avatarParentJointIndex >= 0) {
ASSERT(avatarParentJointIndex >= 0 && avatarParentJointIndex < (int)avatarRotations.size());
avatarParentAbsoluteRot = avatarRotations[avatarParentJointIndex];
}
avatarRotations.push_back(avatarParentAbsoluteRot * avatarRelativeDefaultRot);
@ -201,6 +223,7 @@ void AnimClip::copyFromNetworkAnim() {
// convert avatar rotations into relative frame
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
ASSERT(frame >= 0 && frame < (int)_anim.size());
_anim[frame].reserve(avatarJointCount);
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
@ -209,12 +232,15 @@ void AnimClip::copyFromNetworkAnim() {
glm::vec3 relativeScale = avatarDefaultPose.scale();
glm::vec3 relativeTranslation;
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size());
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
if (animJointIndex >= 0) {
// This joint is in both animation and avatar.
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animFrame.translations.size());
const glm::vec3& animTrans = animFrame.translations[animJointIndex];
// retarget translation from animation to avatar
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animModel.animationFrames[0].translations.size());
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
} else {
@ -224,6 +250,7 @@ void AnimClip::copyFromNetworkAnim() {
}
// build the final pose
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarRotations.size());
_anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation));
}
}

View file

@ -98,6 +98,8 @@ public:
return result;
}
const AnimPoseVec& getPoses() const { return getPosesInternal(); }
protected:
virtual void setCurrentFrameInternal(float frame) {}

View file

@ -2232,6 +2232,14 @@ void Rig::initAnimGraph(const QUrl& url) {
}
}
AnimNode::ConstPointer Rig::findAnimNodeByName(const QString& name) const {
if (_animNode) {
return _animNode->findByName(name);
} else {
return nullptr;
}
}
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
if (_animSkeleton && _rootJointIndex >= 0) {
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans();
@ -2258,7 +2266,7 @@ void Rig::applyOverridePoses() {
}
}
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const {
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
if (!_animSkeleton) {
return;

View file

@ -196,6 +196,7 @@ public:
void initAnimGraph(const QUrl& url);
AnimNode::ConstPointer getAnimNode() const { return _animNode; }
AnimNode::ConstPointer findAnimNodeByName(const QString& name) const;
AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList);
void removeAnimationStateHandler(QScriptValue handler);
@ -243,7 +244,7 @@ public:
Flow& getFlow() { return _internalFlow; }
float getUnscaledEyeHeight() const;
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const;
signals:
void onLoadComplete();
@ -252,7 +253,6 @@ protected:
bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); }
void updateAnimationStateHandlers();
void applyOverridePoses();
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut);
void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,

View file

@ -35,16 +35,6 @@ static const double SQRT2 = 1.41421356237309504880;
static const double FIXQ31 = 2147483648.0;
static const double FIXQ32 = 4294967296.0;
// Round an integer to the next power-of-two, at compile time.
// VS2013 does not support constexpr so macros are used instead.
#define SETBITS0(x) (x)
#define SETBITS1(x) (SETBITS0(x) | (SETBITS0(x) >> 1))
#define SETBITS2(x) (SETBITS1(x) | (SETBITS1(x) >> 2))
#define SETBITS3(x) (SETBITS2(x) | (SETBITS2(x) >> 4))
#define SETBITS4(x) (SETBITS3(x) | (SETBITS3(x) >> 8))
#define SETBITS5(x) (SETBITS4(x) | (SETBITS4(x) >> 16))
#define NEXTPOW2(x) (SETBITS5((x) - 1) + 1)
//
// Allpass delay modulation
//
@ -111,6 +101,18 @@ static const int M_AP19 = 113;
static const int M_AP20 = 107;
static const int M_AP21 = 127;
// Round an integer to the next power-of-two, at compile time
constexpr uint32_t NEXTPOW2(uint32_t n) {
n -= 1;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
n += 1;
return n;
}
//
// Filter design tools using analog-matched response.
// All filter types approximate the s-plane response, including cutoff > Nyquist.
@ -1796,6 +1798,18 @@ void AudioReverb::render(float** inputs, float** outputs, int numFrames) {
#include <emmintrin.h>
// unaligned load/store without undefined behavior
static inline __m128i mm_loadu_si32(void const* mem_addr) {
int32_t temp;
memcpy(&temp, mem_addr, sizeof(int32_t));
return _mm_cvtsi32_si128(temp);
}
static inline void mm_storeu_si32(void* mem_addr, __m128i a) {
int32_t temp = _mm_cvtsi128_si32(a);
memcpy(mem_addr, &temp, sizeof(int32_t));
}
// convert int16_t to float, deinterleave stereo
void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) {
__m128 scale = _mm_set1_ps(1/32768.0f);
@ -1816,7 +1830,7 @@ void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFra
_mm_storeu_ps(&outputs[1][i], f1);
}
for (; i < numFrames; i++) {
__m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]);
__m128i a0 = mm_loadu_si32((__m128i*)&input[2*i]);
__m128i a1 = a0;
// deinterleave and sign-extend
@ -1887,7 +1901,7 @@ void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames)
// interleave
a0 = _mm_unpacklo_epi16(a0, a1);
*(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0);
mm_storeu_si32((__m128i*)&output[2*i], a0);
}
}

View file

@ -793,6 +793,18 @@ int AudioSRC::multirateFilter4(const float* input0, const float* input1, const f
#include <emmintrin.h> // SSE2
// unaligned load/store without undefined behavior
static inline __m128i mm_loadu_si32(void const* mem_addr) {
int32_t temp;
memcpy(&temp, mem_addr, sizeof(int32_t));
return _mm_cvtsi32_si128(temp);
}
static inline void mm_storeu_si32(void* mem_addr, __m128i a) {
int32_t temp = _mm_cvtsi128_si32(a);
memcpy(mem_addr, &temp, sizeof(int32_t));
}
// convert int16_t to float, deinterleave stereo
void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) {
__m128 scale = _mm_set1_ps(1/32768.0f);
@ -839,7 +851,7 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames
_mm_storeu_ps(&outputs[1][i], f1);
}
for (; i < numFrames; i++) {
__m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]);
__m128i a0 = mm_loadu_si32((__m128i*)&input[2*i]);
__m128i a1 = a0;
// deinterleave and sign-extend
@ -878,9 +890,9 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames
_mm_storeu_ps(&outputs[3][i], _mm_shuffle_ps(f1, f3, _MM_SHUFFLE(3,1,3,1)));
}
for (; i < numFrames; i++) {
__m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+0]);
__m128i a0 = mm_loadu_si32((__m128i*)&input[4*i+0]);
__m128i a1 = a0;
__m128i a2 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+2]);
__m128i a2 = mm_loadu_si32((__m128i*)&input[4*i+2]);
__m128i a3 = a2;
// deinterleave and sign-extend
@ -986,7 +998,7 @@ void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) {
// interleave
a0 = _mm_unpacklo_epi16(a0, a1);
*(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0);
mm_storeu_si32((__m128i*)&output[2*i], a0);
}
} else if (_numChannels == 4) {

View file

@ -256,28 +256,18 @@ void EntityTreeRenderer::clear() {
}
// reset the engine
if (_wantScripts && !_shuttingDown) {
resetEntitiesScriptEngine();
}
// remove all entities from the scene
auto scene = _viewState->getMain3DScene();
if (_shuttingDown) {
if (scene) {
render::Transaction transaction;
for (const auto& entry : _entitiesInScene) {
const auto& renderer = entry.second;
renderer->removeFromScene(scene, transaction);
}
scene->enqueueTransaction(transaction);
if (scene) {
for (const auto& entry : _entitiesInScene) {
const auto& renderer = entry.second;
fadeOutRenderable(renderer);
}
} else {
if (_wantScripts) {
resetEntitiesScriptEngine();
}
if (scene) {
for (const auto& entry : _entitiesInScene) {
const auto& renderer = entry.second;
fadeOutRenderable(renderer);
}
} else {
qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene";
}
qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown";
}
_entitiesInScene.clear();
_renderablesToUpdate.clear();

View file

@ -368,6 +368,10 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
}
if (type == SHAPE_TYPE_COMPOUND) {
if (!_compoundShapeResource || !_compoundShapeResource->isLoaded()) {
return;
}
updateModelBounds();
// should never fall in here when collision model not fully loaded

View file

@ -7,7 +7,6 @@
//
#include "RenderableWebEntityItem.h"
#include <atomic>
#include <QtCore/QTimer>
#include <QtGui/QOpenGLContext>
@ -47,7 +46,7 @@ static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND;
static uint8_t YOUTUBE_MAX_FPS = 30;
// Don't allow more than 20 concurrent web views
static std::atomic<uint32_t> _currentWebCount(0);
static uint32_t _currentWebCount { 0 };
static const uint32_t MAX_CONCURRENT_WEB_VIEWS = 20;
static QTouchDevice _touchDevice;
@ -357,15 +356,16 @@ void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const Q
void WebEntityRenderer::destroyWebSurface() {
QSharedPointer<OffscreenQmlSurface> webSurface;
ContentType contentType = ContentType::NoContent;
withWriteLock([&] {
webSurface.swap(_webSurface);
_contentType = ContentType::NoContent;
if (webSurface) {
--_currentWebCount;
WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections);
}
_contentType = contentType;
});
if (webSurface) {
--_currentWebCount;
WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections);
}
}
glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) const {
@ -469,12 +469,6 @@ void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) {
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
}
void WebEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
// HACK: destroyWebSurface() here to avoid a crash on shutdown.
// TODO: fix the real problem: EntityRenderer<>::dtor never called on shutdown for smart-pointer resource leak.
destroyWebSurface();
}
void WebEntityRenderer::setProxyWindow(QWindow* proxyWindow) {
withReadLock([&] {
if (_webSurface) {

View file

@ -64,7 +64,6 @@ protected:
void handlePointerEventAsTouch(const PointerEvent& event);
void handlePointerEventAsMouse(const PointerEvent& event);
void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
private:
void onTimeout();
void buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL);

View file

@ -559,6 +559,8 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer<Rec
}
}
static const int SILENT_DOMAIN_TRAFFIC_DROP_MIN = 2;
bool DomainHandler::checkInPacketTimeout() {
++_checkInPacketsSinceLastReply;
@ -566,9 +568,14 @@ bool DomainHandler::checkInPacketTimeout() {
qCDebug(networking_ice) << "Silent domain checkins:" << _checkInPacketsSinceLastReply;
}
if (_checkInPacketsSinceLastReply > MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
auto nodeList = DependencyManager::get<NodeList>();
auto nodeList = DependencyManager::get<NodeList>();
if (_checkInPacketsSinceLastReply > SILENT_DOMAIN_TRAFFIC_DROP_MIN) {
qCDebug(networking_ice) << _checkInPacketsSinceLastReply << "seconds since last domain list request, squelching traffic";
nodeList->setDropOutgoingNodeTraffic(true);
}
if (_checkInPacketsSinceLastReply > MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
// so emit our signal that says that

View file

@ -409,6 +409,16 @@ qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const HifiS
Q_ASSERT_X(!packet.isReliable(), "LimitedNodeList::sendUnreliablePacket",
"Trying to send a reliable packet unreliably.");
if (_dropOutgoingNodeTraffic) {
auto destinationNode = findNodeWithAddr(sockAddr);
// findNodeWithAddr returns null for the address of the domain server
if (!destinationNode.isNull()) {
// This only suppresses individual unreliable packets, not unreliable packet lists
return ERROR_SENDING_PACKET_BYTES;
}
}
fillPacketHeader(packet, hmacAuth);
return _nodeSocket.writePacket(packet, sockAddr);
@ -440,13 +450,16 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const HifiS
auto size = sendUnreliablePacket(*packet, sockAddr, hmacAuth);
if (size < 0) {
auto now = usecTimestampNow();
eachNode([now](const SharedNodePointer & node) {
qCDebug(networking) << "Stats for " << node->getPublicSocket() << "\n"
<< " Last Heard Microstamp: " << node->getLastHeardMicrostamp() << " (" << (now - node->getLastHeardMicrostamp()) << "usec ago)\n"
<< " Outbound Kbps: " << node->getOutboundKbps() << "\n"
<< " Inbound Kbps: " << node->getInboundKbps() << "\n"
<< " Ping: " << node->getPingMs();
});
if (now - _sendErrorStatsTime > ERROR_STATS_PERIOD_US) {
_sendErrorStatsTime = now;
eachNode([now](const SharedNodePointer& node) {
qCDebug(networking) << "Stats for " << node->getPublicSocket() << "\n"
<< " Last Heard Microstamp: " << node->getLastHeardMicrostamp() << " (" << (now - node->getLastHeardMicrostamp()) << "usec ago)\n"
<< " Outbound Kbps: " << node->getOutboundKbps() << "\n"
<< " Inbound Kbps: " << node->getInboundKbps() << "\n"
<< " Ping: " << node->getPingMs();
});
}
}
return size;
}
@ -986,7 +999,7 @@ void LimitedNodeList::sendSTUNRequest() {
const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10;
if (!_hasCompletedInitialSTUN) {
qCDebug(networking) << "Sending intial stun request to" << STUN_SERVER_HOSTNAME;
qCDebug(networking) << "Sending initial stun request to" << STUN_SERVER_HOSTNAME;
if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) {
// we're still trying to do our initial STUN we're over the fail threshold
@ -1175,7 +1188,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
// We now setup a timer here to fire every so often to check that our IP address has not changed.
// Or, if we failed - if will check if we can eventually get a public socket
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 10 * 1000;
QTimer* stunOccasionalTimer = new QTimer { this };
connect(stunOccasionalTimer, &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
@ -1233,15 +1246,22 @@ void LimitedNodeList::errorTestingLocalSocket() {
}
void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
if (sockAddr != _localSockAddr) {
if (sockAddr.getAddress() != _localSockAddr.getAddress()) {
if (_localSockAddr.isNull()) {
qCInfo(networking) << "Local socket is" << sockAddr;
_localSockAddr = sockAddr;
} else {
qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
_localSockAddr = sockAddr;
if (_hasTCPCheckedLocalSocket) { // Force a port change for NAT:
reset();
_nodeSocket.rebind(0);
_localSockAddr.setPort(_nodeSocket.localPort());
qCInfo(networking) << "Local port changed to" << _localSockAddr.getPort();
}
}
_localSockAddr = sockAddr;
emit localSockAddrChanged(_localSockAddr);
}
}

View file

@ -335,6 +335,8 @@ public:
float getInboundKbps() const { return _inboundKbps; }
float getOutboundKbps() const { return _outboundKbps; }
void setDropOutgoingNodeTraffic(bool squelchOutgoingNodeTraffic) { _dropOutgoingNodeTraffic = squelchOutgoingNodeTraffic; }
const std::set<NodeType_t> SOLO_NODE_TYPES = {
NodeType::AvatarMixer,
NodeType::AudioMixer,
@ -493,6 +495,11 @@ private:
int _outboundPPS { 0 };
float _inboundKbps { 0.0f };
float _outboundKbps { 0.0f };
bool _dropOutgoingNodeTraffic { false };
quint64 _sendErrorStatsTime { (quint64)0 };
static const quint64 ERROR_STATS_PERIOD_US { 1 * USECS_PER_SECOND };
};
#endif // hifi_LimitedNodeList_h

View file

@ -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,8 @@ 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();
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) {
@ -710,6 +706,7 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
// this is a packet from the domain server, reset the count of un-replied check-ins
_domainHandler.clearPendingCheckins();
setDropOutgoingNodeTraffic(false);
// emit our signal so listeners know we just heard from the DS
emit receivedDomainServerList();

View file

@ -33,6 +33,7 @@ using namespace udt;
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
QObject(parent),
_udpSocket(parent),
_readyReadBackupTimer(new QTimer(this)),
_shouldChangeSocketOptions(shouldChangeSocketOptions)
{
@ -50,6 +51,7 @@ Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
}
void Socket::bind(const QHostAddress& address, quint16 port) {
_udpSocket.bind(address, port);
if (_shouldChangeSocketOptions) {
@ -75,7 +77,7 @@ void Socket::rebind() {
}
void Socket::rebind(quint16 localPort) {
_udpSocket.close();
_udpSocket.abort();
bind(QHostAddress::AnyIPv4, localPort);
}
@ -230,7 +232,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 +242,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
}

View file

@ -149,6 +149,11 @@ bool Profiler::isRenderMethodDeferredCapable() {
if ((computerModel.find("MacBookPro11,1") != std::string::npos) && (gpuModel.find("Intel Iris") != std::string::npos)) {
return false;
}
// TO avoid issues for the next few days, we are excluding all of intel chipset...
if ((gpuModel.find("Intel ") != std::string::npos)) {
return false;
}
return true;
#elif defined(Q_OS_ANDROID)

View file

@ -37,7 +37,6 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness
_fragColor0 = vec4(albedo, mix(packShadedMetallic(metallic), packScatteringMetallic(metallic), check));
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
_fragColor2 = vec4(mix(emissive, vec3(scattering), check), occlusion);
_fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);
}
@ -49,7 +48,6 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r
_fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
_fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);
_fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);
}
@ -59,7 +57,7 @@ void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {
}
_fragColor0 = vec4(color, packUnlit());
_fragColor1 = vec4(packNormal(normal), 1.0);
// _fragColor2 = vec4(vec3(0.0), 1.0);
_fragColor2 = vec4(vec3(0.0), 1.0);
_fragColor3 = vec4(color, 1.0);
}
@ -69,7 +67,8 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, floa
}
_fragColor0 = vec4(albedo.rgb, alpha);
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
_fragColor2 = vec4(vec3(0.0), 1.0);
_fragColor3 = vec4(0.0);
}
<@endif@>

View file

@ -41,33 +41,17 @@ namespace gr {
using namespace render;
struct LightLocations {
bool shadowTransform{ false };
void initialize(const gpu::ShaderPointer& program) {
shadowTransform = program->getReflection().validUniformBuffer(ru::Buffer::ShadowParams);
}
};
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& program);
void DeferredLightingEffect::init() {
_directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightLocations = std::make_shared<LightLocations>();
loadLightProgram(shader::render_utils::program::directional_ambient_light, false, _directionalAmbientSphereLight);
loadLightProgram(shader::render_utils::program::directional_skybox_light, false, _directionalSkyboxLight);
_directionalAmbientSphereLightShadowLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>();
loadLightProgram(shader::render_utils::program::directional_ambient_light_shadow, false, _directionalAmbientSphereLightShadow);
loadLightProgram(shader::render_utils::program::directional_skybox_light_shadow, false, _directionalSkyboxLightShadow);
_localLightLocations = std::make_shared<LightLocations>();
_localLightOutlineLocations = std::make_shared<LightLocations>();
loadLightProgram(shader::render_utils::program::directional_ambient_light, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);
loadLightProgram(shader::render_utils::program::directional_skybox_light, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
loadLightProgram(shader::render_utils::program::directional_ambient_light_shadow, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations);
loadLightProgram(shader::render_utils::program::directional_skybox_light_shadow, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
loadLightProgram(shader::render_utils::program::local_lights_shading, true, _localLight, _localLightLocations);
loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline, _localLightOutlineLocations);
loadLightProgram(shader::render_utils::program::local_lights_shading, true, _localLight);
loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline);
}
// FIXME: figure out how to move lightFrame into a varying in GeometryCache and RenderPipelines
@ -123,15 +107,9 @@ void DeferredLightingEffect::unsetLocalLightsBatch(gpu::Batch& batch) {
batch.setUniformBuffer(ru::Buffer::LightClusterFrustumGrid, nullptr);
}
static gpu::ShaderPointer makeLightProgram(int programId, LightLocationsPtr& locations) {
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& pipeline) {
gpu::ShaderPointer program = gpu::Shader::createProgram(programId);
locations->initialize(program);
return program;
}
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
gpu::ShaderPointer program = makeLightProgram(programId, locations);
auto state = std::make_shared<gpu::State>();
state->setColorWriteMask(true, true, true, false);
@ -456,7 +434,6 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
// Setup the global directional pass pipeline
auto program = deferredLightingEffect->_directionalSkyboxLight;
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
{
if (keyLightCastShadows) {
@ -464,20 +441,16 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
// otherwise use the ambient sphere version
if (hasAmbientMap) {
program = deferredLightingEffect->_directionalSkyboxLightShadow;
locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations;
} else {
program = deferredLightingEffect->_directionalAmbientSphereLightShadow;
locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations;
}
} else {
// If the keylight has an ambient Map then use the Skybox version of the pass
// otherwise use the ambient sphere version
if (hasAmbientMap) {
program = deferredLightingEffect->_directionalSkyboxLight;
locations = deferredLightingEffect->_directionalSkyboxLightLocations;
} else {
program = deferredLightingEffect->_directionalAmbientSphereLight;
locations = deferredLightingEffect->_directionalAmbientSphereLightLocations;
}
}

View file

@ -37,10 +37,6 @@
#include "SubsurfaceScattering.h"
#include "AmbientOcclusionEffect.h"
struct LightLocations;
using LightLocationsPtr = std::shared_ptr<LightLocations>;
// THis is where we currently accumulate the local lights, let s change that sooner than later
class DeferredLightingEffect : public Dependency {
SINGLETON_DEPENDENCY
@ -72,15 +68,6 @@ private:
gpu::PipelinePointer _localLight;
gpu::PipelinePointer _localLightOutline;
LightLocationsPtr _directionalSkyboxLightLocations;
LightLocationsPtr _directionalAmbientSphereLightLocations;
LightLocationsPtr _directionalSkyboxLightShadowLocations;
LightLocationsPtr _directionalAmbientSphereLightShadowLocations;
LightLocationsPtr _localLightLocations;
LightLocationsPtr _localLightOutlineLocations;
friend class LightClusteringPass;
friend class RenderDeferredSetup;
friend class RenderDeferredLocals;

View file

@ -18,7 +18,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
void main(void) {
const float depth = 1.0;
const vec4 UNIT_QUAD[4] = vec4[4](
const mat4 UNIT_QUAD = mat4(
vec4(-1.0, -1.0, depth, 1.0),
vec4(1.0, -1.0, depth, 1.0),
vec4(-1.0, 1.0, depth, 1.0),
@ -26,7 +26,7 @@ void main(void) {
);
vec4 pos = UNIT_QUAD[gl_VertexID];
_texCoord01.xy = (pos.xy + 1.0) * 0.5;
_texCoord01 = vec4((pos.xy + 1.0) * 0.5, 0.0, 0.0);
gl_Position = pos;
}

View file

@ -115,48 +115,39 @@ protected:
const Lambda _triggerHandler;
};
template <typename T>
class TypedPreference : public Preference {
public:
using Getter = std::function<T()>;
using Setter = std::function<void(const T&)>;
TypedPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: Preference(category, name), _getter(getter), _setter(setter) { }
T getValue() const { return _value; }
void setValue(const T& value) { if (_value != value) { _value = value; emitValueChanged(); } }
void load() override { _value = _getter(); }
void save() const override {
T oldValue = _getter();
if (_value != oldValue) {
_setter(_value);
}
}
protected:
T _value;
const Getter _getter;
const Setter _setter;
};
class BoolPreference : public TypedPreference<bool> {
class BoolPreference : public Preference {
Q_OBJECT
Q_PROPERTY(bool value READ getValue WRITE setValue NOTIFY valueChanged)
public:
using Getter = std::function<bool()>;
using Setter = std::function<void(const bool&)>;
BoolPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: TypedPreference(category, name, getter, setter) { }
: Preference(category, name), _getter(getter), _setter(setter) { }
bool getValue() const { return _value; }
void setValue(const bool& value) { if (_value != value) { _value = value; emitValueChanged(); } }
void load() override { _value = _getter(); }
void save() const override {
bool oldValue = _getter();
if (_value != oldValue) {
_setter(_value);
}
}
signals:
void valueChanged();
protected:
bool _value;
const Getter _getter;
const Setter _setter;
void emitValueChanged() override { emit valueChanged(); }
};
class FloatPreference : public TypedPreference<float> {
class FloatPreference : public Preference {
Q_OBJECT
Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(float min READ getMin CONSTANT)
@ -165,8 +156,21 @@ class FloatPreference : public TypedPreference<float> {
Q_PROPERTY(float decimals READ getDecimals CONSTANT)
public:
using Getter = std::function<float()>;
using Setter = std::function<void(const float&)>;
FloatPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: TypedPreference(category, name, getter, setter) { }
: Preference(category, name), _getter(getter), _setter(setter) { }
float getValue() const { return _value; }
void setValue(const float& value) { if (_value != value) { _value = value; emitValueChanged(); } }
void load() override { _value = _getter(); }
void save() const override {
float oldValue = _getter();
if (_value != oldValue) {
_setter(_value);
}
}
float getMin() const { return _min; }
void setMin(float min) { _min = min; };
@ -186,14 +190,17 @@ signals:
protected:
void emitValueChanged() override { emit valueChanged(); }
float _value;
const Getter _getter;
const Setter _setter;
float _decimals { 0 };
float _min { 0 };
float _max { 1 };
float _step { 0.1f };
};
class IntPreference : public TypedPreference<int> {
class IntPreference : public Preference {
Q_OBJECT
Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(float min READ getMin CONSTANT)
@ -202,8 +209,21 @@ class IntPreference : public TypedPreference<int> {
Q_PROPERTY(int decimals READ getDecimals CONSTANT)
public:
using Getter = std::function<int()>;
using Setter = std::function<void(const int&)>;
IntPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: TypedPreference(category, name, getter, setter) { }
: Preference(category, name), _getter(getter), _setter(setter) { }
int getValue() const { return _value; }
void setValue(const int& value) { if (_value != value) { _value = value; emitValueChanged(); } }
void load() override { _value = _getter(); }
void save() const override {
int oldValue = _getter();
if (_value != oldValue) {
_setter(_value);
}
}
float getMin() const { return _min; }
void setMin(float min) { _min = min; };
@ -221,6 +241,10 @@ signals:
void valueChanged();
protected:
int _value;
const Getter _getter;
const Setter _setter;
void emitValueChanged() override { emit valueChanged(); }
int _min { std::numeric_limits<int>::min() };
@ -229,19 +253,37 @@ protected:
int _decimals { 0 };
};
class StringPreference : public TypedPreference<QString> {
class StringPreference : public Preference {
Q_OBJECT
Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged)
public:
using Getter = std::function<QString()>;
using Setter = std::function<void(const QString&)>;
StringPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: TypedPreference(category, name, getter, setter) { }
: Preference(category, name), _getter(getter), _setter(setter) { }
QString getValue() const { return _value; }
void setValue(const QString& value) { if (_value != value) { _value = value; emitValueChanged(); } }
void load() override { _value = _getter(); }
void save() const override {
QString oldValue = _getter();
if (_value != oldValue) {
_setter(_value);
}
}
signals:
void valueChanged();
protected:
void emitValueChanged() override { emit valueChanged(); }
QString _value;
const Getter _getter;
const Setter _setter;
};
class SliderPreference : public FloatPreference {
@ -303,7 +345,7 @@ public:
ComboBoxPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: EditPreference(category, name, getter, setter) { }
Type getType() override { return ComboBox; }
const QStringList& getItems() { return _items; }
void setItems(const QStringList& items) { _items = items; }
@ -342,6 +384,9 @@ class CheckPreference : public BoolPreference {
Q_OBJECT
Q_PROPERTY(bool indented READ getIndented CONSTANT)
public:
using Getter = std::function<bool()>;
using Setter = std::function<void(const bool&)>;
CheckPreference(const QString& category, const QString& name, Getter getter, Setter setter)
: BoolPreference(category, name, getter, setter) { }
Type getType() override { return Checkbox; }

View file

@ -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<QQuickItem*>(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<QQuickItem*>(object);
if (!item) {
return;
}
item = dynamic_cast<QQuickItem*>(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<QQuickItem*>(item->parentItem());
}
}
}
#endif
}
void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) {

View file

@ -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);

View file

@ -152,7 +152,7 @@ function simplifiedStatusIndicator(properties) {
// When avatar goes away, set status to busy
var previousStatus;
var previousStatus = "available";
function onWentAway() {
previousStatus = currentStatus;
if (currentStatus !== "busy") {

View file

@ -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 = {

View file

@ -265,8 +265,8 @@ void TestRunnerDesktop::runInstaller() {
folderName += QString(" - ") + getPRNumberFromURL(_url->text());
}
script.write((QString("cp -rf \"$VOLUME/") + folderName + "/interface.app\" \"" + _workingFolder + "/High_Fidelity/\"\n").toStdString().c_str());
script.write((QString("cp -rf \"$VOLUME/") + folderName + "/Sandbox.app\" \"" + _workingFolder + "/High_Fidelity/\"\n").toStdString().c_str());
script.write((QString("cp -Rf \"$VOLUME/") + folderName + "/interface.app\" \"" + _workingFolder + "/High_Fidelity/\"\n").toStdString().c_str());
script.write((QString("cp -Rf \"$VOLUME/") + folderName + "/Sandbox.app\" \"" + _workingFolder + "/High_Fidelity/\"\n").toStdString().c_str());
script.write("hdiutil detach \"$VOLUME\"\n");
script.write("killall yes\n");