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

This commit is contained in:
Sam Gateau 2019-06-18 11:24:04 -07:00
commit f30eb919c7
29 changed files with 345 additions and 110 deletions

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

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

View file

@ -75,21 +75,31 @@ ListModel {
// 1: equivalent to paging when reaching end (and not before). // 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. // 0: don't getNextPage on scroll at all here. The application code will do it.
property real pageAhead: 2.0; property real pageAhead: 2.0;
function needsEarlyYFetch() { function onContentXChanged() {
return flickable if (flickable &&
&& !flickable.atYBeginning !flickable.atXBeginning &&
&& (flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height)); (flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width))) {
getNextPage();
}
} }
function needsEarlyXFetch() { function onContentYChanged() {
return flickable if (flickable &&
&& !flickable.atXBeginning !flickable.atYBeginning &&
&& (flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width)); (flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height))) {
getNextPage();
}
} }
function getNextPageIfHorizontalScroll() { function onWidthChanged() {
if (needsEarlyXFetch()) { getNextPage(); } if (flickable &&
(flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width))) {
getNextPage();
}
} }
function getNextPageIfVerticalScroll() { function onHeightChanged() {
if (needsEarlyYFetch()) { getNextPage(); } if (flickable &&
(flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height))) {
getNextPage();
}
} }
function needsMoreHorizontalResults() { function needsMoreHorizontalResults() {
return flickable return flickable
@ -118,8 +128,10 @@ ListModel {
initialized = true; initialized = true;
if (flickable && pageAhead > 0.0) { if (flickable && pageAhead > 0.0) {
// Pun: Scrollers are usually one direction or another, such that only one of the following will actually fire. // Pun: Scrollers are usually one direction or another, such that only one of the following will actually fire.
flickable.contentXChanged.connect(getNextPageIfHorizontalScroll); flickable.contentXChanged.connect(onContentXChanged);
flickable.contentYChanged.connect(getNextPageIfVerticalScroll); flickable.contentYChanged.connect(onContentYChanged);
flickable.widthChanged.connect(onWidthChanged);
flickable.heightChanged.connect(onHeightChanged);
flickable.contentWidthChanged.connect(getNextPageIfNotEnoughHorizontalResults); flickable.contentWidthChanged.connect(getNextPageIfNotEnoughHorizontalResults);
flickable.contentHeightChanged.connect(getNextPageIfNotEnoughVerticalResults); 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 QtQuick 2.10
import "../simplifiedConstants" as SimplifiedConstants import "../simplifiedConstants" as SimplifiedConstants
import "../simplifiedControls" as SimplifiedControls
import "./components" as AvatarAppComponents import "./components" as AvatarAppComponents
import stylesUit 1.0 as HifiStylesUit import stylesUit 1.0 as HifiStylesUit
import TabletScriptingInterface 1.0 import TabletScriptingInterface 1.0
@ -245,6 +246,10 @@ Rectangle {
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
SimplifiedControls.VerticalScrollBar {
parent: inventoryContentsList
}
} }

View file

@ -9,7 +9,9 @@
// //
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Controls 2.3
import "../simplifiedConstants" as SimplifiedConstants import "../simplifiedConstants" as SimplifiedConstants
import "../simplifiedControls" as SimplifiedControls
import stylesUit 1.0 as HifiStylesUit import stylesUit 1.0 as HifiStylesUit
import "./audio" as AudioSettings import "./audio" as AudioSettings
import "./general" as GeneralSettings import "./general" as GeneralSettings
@ -129,9 +131,7 @@ Rectangle {
id: tabViewContainers id: tabViewContainers
anchors.top: tabContainer.bottom anchors.top: tabContainer.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 26
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -162,24 +162,20 @@ Rectangle {
visible: activeTabView === "devTabView" visible: activeTabView === "devTabView"
anchors.fill: parent anchors.fill: parent
} }
}
Image { SimplifiedControls.VerticalScrollBar {
source: { parent: {
if (root.activeTabView === "generalTabView") { if (activeTabView === "generalTabView") {
"images/accent1.svg" generalTabViewContainer
} else if (root.activeTabView === "audioTabView") { } else if (activeTabView === "audioTabView") {
"images/accent2.svg" audioTabViewContainer
} else if (root.activeTabView === "vrTabView") { } else if (activeTabView === "vrTabView") {
"images/accent3.svg" vrTabViewContainer
} else { } else if (activeTabView === "devTabView") {
"images/accent3.svg" devTabViewContainer
}
} }
} }
anchors.right: parent.right
anchors.top: tabContainer.bottom
width: 106
height: 200
} }

View file

@ -19,8 +19,6 @@ Flickable {
id: root id: root
contentWidth: parent.width contentWidth: parent.width
contentHeight: audioColumnLayout.height contentHeight: audioColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true clip: true
function changePeakValuesEnabled(enabled) { function changePeakValuesEnabled(enabled) {
@ -33,7 +31,7 @@ Flickable {
AudioScriptingInterface.devices.input.peakValuesEnabled = visible; AudioScriptingInterface.devices.input.peakValuesEnabled = visible;
if (visible) { if (visible) {
root.contentX = 0; root.contentX = 0;
root.contentY = -root.topMargin; root.contentY = 0;
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(changePeakValuesEnabled); AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(changePeakValuesEnabled);
} else { } else {
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.disconnect(changePeakValuesEnabled); AudioScriptingInterface.devices.input.peakValuesEnabledChanged.disconnect(changePeakValuesEnabled);
@ -45,16 +43,35 @@ Flickable {
id: simplifiedUI 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 { ColumnLayout {
id: audioColumnLayout id: audioColumnLayout
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout { ColumnLayout {
id: volumeControlsContainer id: volumeControlsContainer
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.topMargin: 24
spacing: 0 spacing: 0
HifiStylesUit.GraphikSemiBold { HifiStylesUit.GraphikSemiBold {
@ -289,6 +306,7 @@ Flickable {
ColumnLayout { ColumnLayout {
id: outputDeviceContainer id: outputDeviceContainer
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.bottomMargin: 24
spacing: 0 spacing: 0
HifiStylesUit.GraphikSemiBold { HifiStylesUit.GraphikSemiBold {

View file

@ -19,14 +19,12 @@ Flickable {
id: root id: root
contentWidth: parent.width contentWidth: parent.width
contentHeight: devColumnLayout.height contentHeight: devColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true clip: true
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
root.contentX = 0; root.contentX = 0;
root.contentY = -root.topMargin; root.contentY = 0;
} }
} }
@ -35,16 +33,36 @@ Flickable {
id: simplifiedUI 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 { ColumnLayout {
id: devColumnLayout id: devColumnLayout
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout { ColumnLayout {
id: uiControlsContainer id: uiControlsContainer
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.topMargin: 24
Layout.bottomMargin: 24
spacing: 0 spacing: 0
HifiStylesUit.GraphikSemiBold { HifiStylesUit.GraphikSemiBold {

View file

@ -9,6 +9,7 @@
// //
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Controls 2.3
import "../../simplifiedConstants" as SimplifiedConstants import "../../simplifiedConstants" as SimplifiedConstants
import "../../simplifiedControls" as SimplifiedControls import "../../simplifiedControls" as SimplifiedControls
import stylesUit 1.0 as HifiStylesUit import stylesUit 1.0 as HifiStylesUit
@ -20,8 +21,6 @@ Flickable {
id: root id: root
contentWidth: parent.width contentWidth: parent.width
contentHeight: generalColumnLayout.height contentHeight: generalColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true clip: true
onAvatarNametagModeChanged: { onAvatarNametagModeChanged: {
@ -31,7 +30,7 @@ Flickable {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
root.contentX = 0; root.contentX = 0;
root.contentY = -root.topMargin; root.contentY = 0;
} }
} }
@ -39,16 +38,35 @@ Flickable {
id: simplifiedUI 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 { ColumnLayout {
id: generalColumnLayout id: generalColumnLayout
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout { ColumnLayout {
id: avatarNameTagsContainer id: avatarNameTagsContainer
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.topMargin: 24
spacing: 0 spacing: 0
HifiStylesUit.GraphikSemiBold { HifiStylesUit.GraphikSemiBold {
@ -193,29 +211,36 @@ Flickable {
} }
} }
HifiStylesUit.GraphikRegular { ColumnLayout {
id: logoutText id: logoutContainer
text: (AccountServices.username === "Unknown user" ? "Log In" : "Logout " + AccountServices.username) Layout.preferredWidth: parent.width
wrapMode: Text.Wrap Layout.bottomMargin: 24
width: paintedWidth spacing: 0
height: paintedHeight
size: 14
color: simplifiedUI.colors.text.lightBlue
MouseArea { HifiStylesUit.GraphikRegular {
anchors.fill: parent id: logoutText
hoverEnabled: true text: (AccountServices.username === "Unknown user" ? "Log In" : "Logout " + AccountServices.username)
onEntered: { wrapMode: Text.Wrap
parent.color = simplifiedUI.colors.text.lightBlueHover; width: paintedWidth
} height: paintedHeight
onExited: { size: 14
parent.color = simplifiedUI.colors.text.lightBlue; color: simplifiedUI.colors.text.lightBlue
}
onClicked: { MouseArea {
if (Account.loggedIn) { anchors.fill: parent
AccountServices.logOut(); hoverEnabled: true
} else { onEntered: {
DialogsManager.showLoginDialog(); 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 id: root
contentWidth: parent.width contentWidth: parent.width
contentHeight: vrColumnLayout.height contentHeight: vrColumnLayout.height
topMargin: 24
bottomMargin: 24
clip: true clip: true
function changePeakValuesEnabled(enabled) { function changePeakValuesEnabled(enabled) {
@ -33,7 +31,7 @@ Flickable {
AudioScriptingInterface.devices.input.peakValuesEnabled = visible; AudioScriptingInterface.devices.input.peakValuesEnabled = visible;
if (visible) { if (visible) {
root.contentX = 0; root.contentX = 0;
root.contentY = -root.topMargin; root.contentY = 0;
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(changePeakValuesEnabled); AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(changePeakValuesEnabled);
} else { } else {
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.disconnect(changePeakValuesEnabled); AudioScriptingInterface.devices.input.peakValuesEnabledChanged.disconnect(changePeakValuesEnabled);
@ -45,16 +43,35 @@ Flickable {
id: simplifiedUI 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 { ColumnLayout {
id: vrColumnLayout id: vrColumnLayout
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top anchors.top: parent.top
spacing: simplifiedUI.margins.settings.spacingBetweenSettings spacing: simplifiedUI.margins.settings.spacingBetweenSettings
ColumnLayout { ColumnLayout {
id: controlsContainer id: controlsContainer
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.topMargin: 24
spacing: 0 spacing: 0
HifiStylesUit.GraphikSemiBold { HifiStylesUit.GraphikSemiBold {
@ -278,6 +295,7 @@ Flickable {
ColumnLayout { ColumnLayout {
id: outputDeviceContainer id: outputDeviceContainer
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.bottomMargin: 24
spacing: 0 spacing: 0
HifiStylesUit.GraphikSemiBold { HifiStylesUit.GraphikSemiBold {

View file

@ -144,6 +144,10 @@ QtObject {
readonly property color hover: "#FFFFFF" readonly property color hover: "#FFFFFF"
readonly property color focus: "#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" readonly property color darkSeparator: "#595959"
@ -219,6 +223,10 @@ QtObject {
readonly property QtObject textField: QtObject { readonly property QtObject textField: QtObject {
readonly property int editPencilPadding: 6 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

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

View file

@ -274,7 +274,9 @@ public slots:
protected: protected:
AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override; AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override;
DetailedMotionState* createDetailedMotionState(OtherAvatarPointer avatar, int32_t jointIndex); 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: private:
explicit AvatarManager(QObject* parent = 0); 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) { void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
if (isEnabled) { if (isEnabled) {
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f); 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) { if (_enableDebugDrawAnimPose && animSkeleton) {
// build absolute AnimPoseVec from rig
AnimPoseVec absPoses; AnimPoseVec absPoses;
const Rig& rig = _skeletonModel->getRig(); const Rig& rig = _skeletonModel->getRig();
absPoses.reserve(rig.getJointStateCount()); const glm::vec4 CYAN(0.1f, 0.6f, 0.6f, 1.0f);
for (int i = 0; i < rig.getJointStateCount(); i++) {
absPoses.push_back(AnimPose(rig.getJointTransform(i))); 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); void setEnableDebugDrawDefaultPose(bool isEnabled);
/**jsdoc /**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 * @function MyAvatar.setEnableDebugDrawAnimPose
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide. * @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
*/ */
void setEnableDebugDrawAnimPose(bool isEnabled); 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 /**jsdoc
* Displays position debug graphics. * Displays position debug graphics.
* @function MyAvatar.setEnableDebugDrawPosition * @function MyAvatar.setEnableDebugDrawPosition
@ -2666,6 +2674,8 @@ private:
bool _enableDebugDrawIKChains { false }; bool _enableDebugDrawIKChains { false };
bool _enableDebugDrawDetailedCollision { false }; bool _enableDebugDrawDetailedCollision { false };
ThreadSafeValueCache<QString> _debugDrawAnimPoseName;
mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state? mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state?
AudioListenerMode _audioListenerMode; AudioListenerMode _audioListenerMode;

View file

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

View file

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

View file

@ -177,7 +177,7 @@ const btCollisionShape* OtherAvatar::createCollisionShape(int32_t jointIndex, bo
return ObjectMotionState::getShapeManager()->getShape(shapeInfo); return ObjectMotionState::getShapeManager()->getShape(shapeInfo);
} }
void OtherAvatar::resetDetailedMotionStates() { void OtherAvatar::forgetDetailedMotionStates() {
// NOTE: the DetailedMotionStates are deleted after being added to PhysicsEngine::Transaction::_objectsToRemove // NOTE: the DetailedMotionStates are deleted after being added to PhysicsEngine::Transaction::_objectsToRemove
// See AvatarManager::handleProcessedPhysicsTransaction() // See AvatarManager::handleProcessedPhysicsTransaction()
_detailedMotionStates.clear(); _detailedMotionStates.clear();
@ -209,7 +209,7 @@ void OtherAvatar::computeShapeLOD() {
if (newLOD != _bodyLOD) { if (newLOD != _bodyLOD) {
_bodyLOD = newLOD; _bodyLOD = newLOD;
if (isInPhysicsSimulation()) { if (isInPhysicsSimulation()) {
_needsReinsertion = true; _needsDetailedRebuild = true;
} }
} }
} }
@ -224,14 +224,14 @@ bool OtherAvatar::shouldBeInPhysicsSimulation() const {
bool OtherAvatar::needsPhysicsUpdate() const { bool OtherAvatar::needsPhysicsUpdate() const {
constexpr uint32_t FLAGS_OF_INTEREST = Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS | Simulation::DIRTY_POSITION | Simulation::DIRTY_COLLISION_GROUP; 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() { void OtherAvatar::rebuildCollisionShape() {
if (_motionState) { if (_motionState) {
// do not actually rebuild here, instead flag for later // do not actually rebuild here, instead flag for later
_motionState->addDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); _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); const btCollisionShape* createCollisionShape(int32_t jointIndex, bool& isBound, std::vector<int32_t>& boundJoints);
std::vector<DetailedMotionState*>& getDetailedMotionStates() { return _detailedMotionStates; } std::vector<DetailedMotionState*>& getDetailedMotionStates() { return _detailedMotionStates; }
void resetDetailedMotionStates(); void forgetDetailedMotionStates();
BodyLOD getBodyLOD() { return _bodyLOD; } BodyLOD getBodyLOD() { return _bodyLOD; }
void computeShapeLOD(); void computeShapeLOD();
@ -90,7 +90,7 @@ protected:
int32_t _spaceIndex { -1 }; int32_t _spaceIndex { -1 };
uint8_t _workloadRegion { workload::Region::INVALID }; uint8_t _workloadRegion { workload::Region::INVALID };
BodyLOD _bodyLOD { BodyLOD::Sphere }; BodyLOD _bodyLOD { BodyLOD::Sphere };
bool _needsReinsertion { false }; bool _needsDetailedRebuild { false };
}; };
using OtherAvatarPointer = std::shared_ptr<OtherAvatar>; using OtherAvatarPointer = std::shared_ptr<OtherAvatar>;

View file

@ -64,7 +64,8 @@ function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
endfunction() endfunction()
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files}) 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 "") set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "")
if (LAUNCHER_HMAC_SECRET STREQUAL "") if (LAUNCHER_HMAC_SECRET STREQUAL "")
message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set") message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set")

View file

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

View file

@ -25,7 +25,7 @@
break; break;
case CHECKING_UPDATE: case CHECKING_UPDATE:
[self.boldStatus setStringValue:@"Getting updates..."]; [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; break;
case RUNNING_INTERFACE_AFTER_UPDATE: case RUNNING_INTERFACE_AFTER_UPDATE:
[self.boldStatus setStringValue:@"You're good to go!"]; [self.boldStatus setStringValue:@"You're good to go!"];

View file

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

View file

@ -98,6 +98,8 @@ public:
return result; return result;
} }
const AnimPoseVec& getPoses() const { return getPosesInternal(); }
protected: protected:
virtual void setCurrentFrameInternal(float frame) {} 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 { bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
if (_animSkeleton && _rootJointIndex >= 0) { if (_animSkeleton && _rootJointIndex >= 0) {
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans(); 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"); DETAILED_PERFORMANCE_TIMER("buildAbsolute");
if (!_animSkeleton) { if (!_animSkeleton) {
return; return;

View file

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

View file

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

View file

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