diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp
index c9ded2d6fb..1f3f770867 100644
--- a/assignment-client/src/avatars/ScriptableAvatar.cpp
+++ b/assignment-client/src/avatars/ScriptableAvatar.cpp
@@ -123,12 +123,12 @@ void ScriptableAvatar::update(float deltatime) {
AnimPose& absPose = absPoses[i];
if (data.rotation != absPose.rot()) {
data.rotation = absPose.rot();
- data.rotationSet = true;
+ data.rotationIsDefaultPose = false;
}
AnimPose& relPose = poses[i];
if (data.translation != relPose.trans()) {
data.translation = relPose.trans();
- data.translationSet = true;
+ data.translationIsDefaultPose = false;
}
}
diff --git a/interface/resources/qml/CurrentAPI.qml b/interface/resources/qml/CurrentAPI.qml
index 45cf09925a..37984965d9 100644
--- a/interface/resources/qml/CurrentAPI.qml
+++ b/interface/resources/qml/CurrentAPI.qml
@@ -16,10 +16,9 @@ import "controls-uit" as HifiControls
Item {
id: root
width: parent.width
- height: parent.height
+ height: parent.height
property var hideQtMethods: true
-
property var maxUpdateValues: 20
property var maxReloadValues: 200
property var apiMembers: []
@@ -30,7 +29,7 @@ Item {
property Component keyboard
Rectangle {
- color: "white"
+ color: hifi.colors.baseGray
width: parent.width
height: parent.height
}
@@ -51,32 +50,22 @@ Item {
Row {
id: topBar
anchors.left: parent.left
- anchors.leftMargin: 8
+ anchors.leftMargin: 30
+ anchors.top: parent.top
+ anchors.topMargin: 30
width: parent.width
- height: 50
- HifiControls.GlyphButton {
- id: search
- enabled: true
- glyph: hifi.glyphs.search
- color: hifi.colors.text
- size: 48
- width: 50
- height: 50
- onClicked: {
- addListElements(searchBar.text);
- focus = true;
- }
- }
+ height: 40
HifiControls.GlyphButton {
id: back;
enabled: true;
+ color: hifi.buttons.black
glyph: hifi.glyphs.backward
- color: hifi.colors.text
- size: 48
- width: 30
- height: 50
- anchors.margins: 2
+ size: 40
+ width: 40
+ height: 40
+ anchors.left: search.right
+ anchors.leftMargin: 12
onClicked: {
var text = searchBar.text;
var chain = text.split(".");
@@ -99,17 +88,20 @@ Item {
}
}
- TextField {
- id: searchBar
+ HifiControls.TextField {
+ id: searchBar
focus: true
- font.pixelSize: 16
- width: 2*(parent.width-back.width-search.width-reload.width-update.width-evaluate.width-addMember.width-16)/3
- height: parent.height
- font.family: ralewayRegular.name
+ isSearchField: true
+ width: parent.width - 112
+ height: 40
+ colorScheme: hifi.colorSchemes.dark
+ anchors.left: back.right
+ anchors.leftMargin: 10
+ font.family: firaSansSemiBold.name
placeholderText: "Search"
onAccepted: {
console.log("Enter Pressed");
- search.clicked();
+ addListElements(searchBar.text);
}
onActiveFocusChanged: {
if (activeFocus && HMD.mounted) {
@@ -119,15 +111,27 @@ Item {
}
}
- }
+ }
+ }
- HifiControls.Button {
+ Row {
+ id: topBar2
+ anchors.left: parent.left
+ anchors.leftMargin: 30
+ anchors.top: topBar.bottom
+ anchors.topMargin: 30
+ width: parent.width -60
+ height: 40
+
+ HifiControls.GlyphButton {
id: addMember;
enabled: true;
- text: "+"
- width: 50
- height: 50
- anchors.margins: 2
+ color: hifi.buttons.black
+ glyph: hifi.glyphs.maximize
+ width: 40
+ height: 40
+ anchors.top: parent.top
+ anchors.left: parent.left
onClicked: {
addNewMember();
updateList.start();
@@ -138,36 +142,48 @@ Item {
HifiControls.Button {
id: evaluate;
enabled: true;
+ color: hifi.buttons.black
text: "Eval"
- width: 50
- height: 50
- anchors.margins: 2
+ width: 40
+ height: 40
+ anchors.left: addMember.right
+ anchors.leftMargin: 12
onClicked: {
evaluateMember();
focus = true;
}
}
- TextField {
- id: valueBar
- focus: true
+
+ HifiControls.TextField {
+ id: valueBar
+ isSearchField: false
font.pixelSize: 16
- width: (parent.width-back.width-search.width-reload.width-update.width-evaluate.width-addMember.width-16)/3
- height: parent.height
- font.family: ralewayRegular.name
+ width: parent.width - 208
+ height: 40
+ colorScheme: hifi.colorSchemes.dark
+ font.family: firaSansSemiBold.name
placeholderText: "Value"
- textColor: "#4466DD"
- anchors.margins: 2
+ anchors.left: evaluate.right
+ anchors.leftMargin: 12
+ onActiveFocusChanged: {
+ if (activeFocus && HMD.mounted) {
+ keyboard.raised = true;
+ } else {
+ keyboard.raised = false;
+ }
+ }
}
HifiControls.GlyphButton {
id: reload;
enabled: false;
+ color: hifi.buttons.black
glyph: hifi.glyphs.reload
- color: hifi.colors.text
- size: 48
- width: 50
- height: 50
- anchors.margins: 2
+ size: 40
+ width: 40
+ height: 40
+ anchors.right: update.left
+ anchors.rightMargin: 12
onClicked: {
reloadListValues();
focus = true;
@@ -177,11 +193,12 @@ Item {
HifiControls.GlyphButton {
id: update;
enabled: false;
+ color: hifi.buttons.black
glyph: hifi.glyphs.playback_play
- size: 48
- width: 50
- height: 50
- anchors.margins: 2
+ size: 40
+ width: 40
+ height: 40
+ anchors.right: parent.right
onClicked: {
if (isReloading) {
update.glyph = hifi.glyphs.playback_play
@@ -196,71 +213,104 @@ Item {
}
}
}
-
- ListModel {
- id: memberModel
- }
- Component {
- id: memberDelegate
-
- Row {
- id: memberRow
- property var isMainKey: apiType === "class";
- spacing: 10
- Rectangle {
- width: isMainKey ? 20 : 40;
- height: parent.height
- }
-
- RalewayRegular {
- text: apiMember
- size: !isMainKey ? 16 : 22
- MouseArea {
- width: list.width
- height: parent.height
- onClicked: {
- searchBar.text = apiType=="function()" ? apiMember + "()" : apiMember;
- valueBar.text = !apiValue ? "" : apiValue;
- list.currentIndex = index;
- evaluatingIdx = index;
- }
- onDoubleClicked: {
- if (apiType === "class") {
- addListElements(apiMember+".");
- } else {
- isolateElement(evaluatingIdx);
- }
-
- }
- }
- }
-
-
- RalewayRegular {
- text: apiType
- size: 14
- color: hifi.colors.baseGrayHighlight
- }
-
- RalewayRegular {
- text: !apiValue ? "" : apiValue;
- size: 16
- color: "#4466DD"
- }
- }
- }
-
-
Rectangle {
id: membersBackground
anchors {
- left: parent.left; right: parent.right; top: topBar.bottom; bottom: parent.bottom;
- margins: hifi.dimensions.contentMargin.x
- bottomMargin: hifi.dimensions.contentSpacing.y + 40
+ left: parent.left; right: parent.right; top: topBar2.bottom; bottom: bottomBar.top;
+ margins: 30
+ }
+ color: hifi.colors.tableBackgroundDark
+ border.color: hifi.colors.lightGray
+ border.width: 2
+ radius: 5
+
+ ListModel {
+ id: memberModel
+ }
+
+ Component {
+ id: memberDelegate
+ Item {
+ id: item
+ width: parent.width
+ anchors.left: parent.left
+ height: 26
+ clip: true
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: index % 2 == 0 ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd
+ anchors.verticalCenter: parent.verticalCenter
+
+ Row {
+ id: memberRow
+ anchors.bottom: parent.bottom
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 10
+
+ FiraSansSemiBold {
+ property var isMainKey: apiType === "class";
+ text: apiMember
+ size: isMainKey ? 17 : 15
+ font.bold: true
+ anchors.verticalCenter: parent.verticalCenter
+ color: isMainKey ? hifi.colors.faintGray : hifi.colors.lightGrayText
+ MouseArea {
+ width: list.width
+ height: parent.height
+ onClicked: {
+ searchBar.text = apiType=="function()" ? apiMember + "()" : apiMember;
+ valueBar.text = !apiValue ? "" : apiValue;
+ list.currentIndex = index;
+ evaluatingIdx = index;
+ }
+ onDoubleClicked: {
+ if (apiType === "class") {
+ addListElements(apiMember+".");
+ } else {
+ isolateElement(evaluatingIdx);
+ }
+ }
+ }
+ }
+
+ FiraSansRegular {
+ text: apiType
+ anchors.left: apiMember.right
+ anchors.verticalCenter: parent.verticalCenter
+ size: 13
+ color: hifi.colors.lightGrayText
+ }
+
+ FiraSansRegular {
+ text: !apiValue ? "" : apiValue;
+ anchors.left: apiType.right
+ anchors.verticalCenter: parent.verticalCenter
+ size: 14
+ color: hifi.colors.primaryHighlight
+ }
+ }
+ }
+ }
+ }
+
+ Component {
+ id: highlight
+ Rectangle {
+ anchors {
+ left: list.left
+ right: scrollBar.left
+ leftMargin: 2
+ rightMargin: 2
+ }
+ color: hifi.colors.primaryHighlight
+ radius: 4
+ z: 10
+ opacity: 0.5
+ }
}
- color: "white"
- radius: 4
ListView {
id: list
@@ -269,23 +319,16 @@ Item {
left: parent.left
right: scrollBar.left
bottom: parent.bottom
- margins: 4
+ topMargin: 2
+ leftMargin: 2
+ bottomMargin: 2
}
clip: true
cacheBuffer: 4000
model: memberModel
delegate: memberDelegate
highlightMoveDuration: 0
-
- highlight: Rectangle {
- anchors {
- left: parent ? parent.left : undefined
- right: parent ? parent.right : undefined
- leftMargin: hifi.dimensions.borderWidth
- rightMargin: hifi.dimensions.borderWidth
- }
- color: "#BBDDFF"
- }
+ highlight: highlight
onMovementStarted: {
scrollSlider.manual = true;
}
@@ -310,12 +353,11 @@ Item {
top: parent.top
right: parent.right
bottom: parent.bottom
- topMargin: 4
- bottomMargin: 4
+ margins: 2
}
- width: scrolling ? 18 : 0
- radius: 4
- color: hifi.colors.baseGrayShadow
+ width: 22
+ height: parent.height - 4
+ color: hifi.colors.tableScrollBackgroundDark
MouseArea {
anchors.fill: parent
@@ -344,14 +386,12 @@ Item {
y = index*(scrollBar.height - scrollSlider.height)/(list.count - 1);
}
- anchors {
- right: parent.right
- rightMargin: 3
- }
- width: 12
- height: (list.height / list.contentHeight) * list.height
- radius: width / 4
- color: "white"
+ anchors.right: parent.right
+ anchors.margins: 2
+ width: 18
+ height: ((list.height / list.contentHeight) * list.height) < 15 ? 15 : (list.height / list.contentHeight) * list.height
+ radius: 5
+ color: hifi.colors.tableScrollHandleDark
visible: scrollBar.scrolling;
@@ -373,66 +413,75 @@ Item {
}
}
}
-
- HifiControls.GlyphButton {
- id: clipboard;
- enabled: true;
- glyph: hifi.glyphs.scriptNew
- size: 38
- width: 50
- height: 50
+
+ Row {
+ id: bottomBar
anchors.left: parent.left
+ anchors.leftMargin: 30
anchors.bottom: parent.bottom
- anchors.margins: 2
- anchors.leftMargin: 8
- onClicked: {
- var buffer = "";
- for (var i = 0; i < memberModel.count; i++) {
- var datarow = memberModel.get(i);
- buffer += "\n" + datarow.apiMember + " " + datarow.apiType + " " + datarow.apiValue;
- }
- Window.copyToClipboard(buffer);
- focus = true;
- }
- }
-
- HifiControls.Button {
- id: debug;
- enabled: true;
- text: "Debug Script"
- width: 120
- height: 50
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.margins: 2
- anchors.rightMargin: 8
- onClicked: {
- sendToScript({type: "selectScript"});
- }
- }
+ anchors.bottomMargin: 30
+ width: parent.width
+ height: 40
- HifiControls.CheckBox {
- id: hideQt
- boxSize: 25
- boxRadius: 3
- checked: true
- anchors.left: clipboard.right
- anchors.leftMargin: 8
- anchors.verticalCenter: clipboard.verticalCenter
- anchors.margins: 2
- onClicked: {
- hideQtMethods = checked;
- addListElements();
+ HifiControls.GlyphButton {
+ id: clipboard;
+ enabled: true;
+ color: hifi.buttons.black
+ glyph: hifi.glyphs.scriptNew
+ size: 25
+ width: 40
+ height: 40
+ anchors.left: parent.left
+ onClicked: {
+ var buffer = "";
+ for (var i = 0; i < memberModel.count; i++) {
+ var datarow = memberModel.get(i);
+ buffer += "\n" + datarow.apiMember + " " + datarow.apiType + " " + datarow.apiValue;
+ }
+ Window.copyToClipboard(buffer);
+ focus = true;
+ }
}
- }
- HifiControls.Label {
- id: hideLabel
- anchors.left: hideQt.right
- anchors.verticalCenter: clipboard.verticalCenter
- anchors.margins: 2
- font.pixelSize: 15
- text: "Hide Qt Methods"
+ HifiControls.CheckBox {
+ id: hideQt
+ colorScheme: hifi.checkbox.dark
+ boxSize: 25
+ boxRadius: 3
+ checked: true
+ anchors.left: clipboard.right
+ anchors.leftMargin: 10
+ anchors.verticalCenter: clipboard.verticalCenter
+ onClicked: {
+ hideQtMethods = checked;
+ addListElements();
+ }
+ }
+
+ HifiControls.Label {
+ id: hideLabel
+ anchors.left: hideQt.right
+ anchors.verticalCenter: clipboard.verticalCenter
+ anchors.margins: 2
+ font.pixelSize: 15
+ text: "Hide Qt Methods"
+ }
+
+ HifiControls.Button {
+ id: debug;
+ enabled: true;
+ color: hifi.buttons.black
+ text: "Debug Script"
+ width: 120
+ height: 40
+ anchors.right: parent.right
+ anchors.rightMargin: 60
+ anchors.bottom: parent.bottom
+
+ onClicked: {
+ sendToScript({type: "selectScript"});
+ }
+ }
}
HifiControls.Keyboard {
@@ -639,4 +688,4 @@ Item {
}
signal sendToScript(var message);
-}
\ No newline at end of file
+}
diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml
index b942c8b4ab..a21d1f8efd 100644
--- a/interface/resources/qml/controls-uit/TextField.qml
+++ b/interface/resources/qml/controls-uit/TextField.qml
@@ -24,10 +24,13 @@ TextField {
property bool isSearchField: false
property string label: ""
property real controlHeight: height + (textFieldLabel.visible ? textFieldLabel.height + 1 : 0)
+ property bool hasDefocusedBorder: true;
property bool hasRoundedBorder: false
+ property int roundedBorderRadius: 4
property bool error: false;
property bool hasClearButton: false;
- property string leftPlaceholderGlyph: "";
+ property string leftPermanentGlyph: "";
+ property string centerPlaceholderGlyph: "";
placeholderText: textField.placeholderText
@@ -101,12 +104,12 @@ TextField {
}
}
border.color: textField.error ? hifi.colors.redHighlight :
- (textField.activeFocus ? hifi.colors.primaryHighlight : (isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray))
+ (textField.activeFocus ? hifi.colors.primaryHighlight : (hasDefocusedBorder ? (isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray) : color))
border.width: textField.activeFocus || hasRoundedBorder || textField.error ? 1 : 0
- radius: isSearchField ? textField.height / 2 : (hasRoundedBorder ? 4 : 0)
+ radius: isSearchField ? textField.height / 2 : (hasRoundedBorder ? roundedBorderRadius : 0)
HiFiGlyphs {
- text: textField.leftPlaceholderGlyph;
+ text: textField.leftPermanentGlyph;
color: textColor;
size: hifi.fontSizes.textFieldSearchIcon;
anchors.left: parent.left;
@@ -115,6 +118,15 @@ TextField {
visible: text;
}
+ HiFiGlyphs {
+ text: textField.centerPlaceholderGlyph;
+ color: textColor;
+ size: parent.height;
+ anchors.horizontalCenter: parent.horizontalCenter;
+ anchors.verticalCenter: parent.verticalCenter;
+ visible: text && !textField.focus && textField.text === "";
+ }
+
HiFiGlyphs {
text: hifi.glyphs.search
color: textColor
@@ -145,7 +157,7 @@ TextField {
placeholderTextColor: isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
- padding.left: ((isSearchField || textField.leftPlaceholderGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
+ padding.left: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
index da67569bc3..ae42b8e3e1 100644
--- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
@@ -389,7 +389,7 @@ Rectangle {
//
Item {
id: tabButtonsContainer;
- visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange";
+ visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendMoneyStep";
property int numTabs: 5;
// Size
width: root.width;
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/ConnectionItem.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/ConnectionItem.qml
index c2d9ef3b19..33cd43bb05 100644
--- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/ConnectionItem.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/ConnectionItem.qml
@@ -29,13 +29,13 @@ Item {
property string userName;
property string profilePicUrl;
- height: 65;
+ height: 75;
width: parent.width;
Rectangle {
id: mainContainer;
// Style
- color: root.isSelected ? hifi.colors.faintGray : hifi.colors.white;
+ color: root.isSelected ? hifi.colors.faintGray80 : hifi.colors.white;
// Size
anchors.left: parent.left;
anchors.right: parent.right;
@@ -49,7 +49,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter;
anchors.left: parent.left;
anchors.leftMargin: 36;
- height: root.height - 15;
+ height: 50;
width: visible ? height : 0;
clip: true;
Image {
@@ -83,15 +83,15 @@ Item {
RalewaySemiBold {
id: userName;
anchors.left: avatarImage.right;
- anchors.leftMargin: 16;
+ anchors.leftMargin: 12;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: chooseButton.visible ? chooseButton.left : parent.right;
anchors.rightMargin: chooseButton.visible ? 10 : 0;
// Text size
- size: 20;
+ size: 18;
// Style
- color: hifi.colors.baseGray;
+ color: hifi.colors.blueAccent;
text: root.userName;
elide: Text.ElideRight;
// Alignment
@@ -107,9 +107,9 @@ Item {
colorScheme: hifi.colorSchemes.dark;
anchors.verticalCenter: parent.verticalCenter;
anchors.right: parent.right;
- anchors.rightMargin: 24;
- height: root.height - 20;
- width: 110;
+ anchors.rightMargin: 28;
+ height: 35;
+ width: 100;
text: "CHOOSE";
onClicked: {
var msg = { method: 'chooseConnection', userName: root.userName, profilePicUrl: root.profilePicUrl };
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/RecipientDisplay.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/RecipientDisplay.qml
index 267cf0ed51..43636d47ca 100644
--- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/RecipientDisplay.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/RecipientDisplay.qml
@@ -29,6 +29,7 @@ Item {
property string displayName;
property string userName;
property string profilePic;
+ property string textColor: hifi.colors.white;
Item {
visible: root.isDisplayingNearby;
@@ -46,7 +47,7 @@ Item {
// Text size
size: 18;
// Style
- color: hifi.colors.baseGray;
+ color: root.textColor;
verticalAlignment: Text.AlignBottom;
elide: Text.ElideRight;
}
@@ -63,7 +64,7 @@ Item {
// Text size
size: 16;
// Style
- color: hifi.colors.baseGray;
+ color: root.textColor;
verticalAlignment: Text.AlignTop;
elide: Text.ElideRight;
}
@@ -108,7 +109,7 @@ Item {
// Text size
size: 16;
// Style
- color: hifi.colors.baseGray;
+ color: root.textColor;
verticalAlignment: Text.AlignVCenter;
elide: Text.ElideRight;
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
index 9164ba7a8c..f66781c919 100644
--- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
@@ -29,8 +29,9 @@ Item {
property int parentAppNavBarHeight;
property string currentActiveView: "sendMoneyHome";
property string nextActiveView: "";
- property bool isCurrentlyFullScreen: chooseRecipientConnection.visible ||
- chooseRecipientNearby.visible || sendMoneyStep.visible || paymentSuccess.visible || paymentFailure.visible;
+ property bool shouldShowTopAndBottomOfWallet: chooseRecipientConnection.visible ||
+ chooseRecipientNearby.visible || paymentSuccess.visible || paymentFailure.visible;
+ property bool shouldShowTopOfWallet: sendMoneyStep.visible;
property bool isCurrentlySendingMoney: false;
// This object is always used in a popup or full-screen Wallet section.
@@ -38,9 +39,9 @@ Item {
// able to click on a button/mouseArea underneath the popup/section.
MouseArea {
x: 0;
- y: root.isCurrentlyFullScreen ? 0 : root.parentAppTitleBarHeight;
+ y: (root.shouldShowTopAndBottomOfWallet && !root.shouldShowTopOfWallet) ? 0 : root.parentAppTitleBarHeight;
width: parent.width;
- height: root.isCurrentlyFullScreen ? parent.height : parent.height - root.parentAppTitleBarHeight - root.parentAppNavBarHeight;
+ height: (root.shouldShowTopAndBottomOfWallet || root.shouldShowTopOfWallet) ? parent.height : parent.height - root.parentAppTitleBarHeight - root.parentAppNavBarHeight;
propagateComposedEvents: false;
}
@@ -105,7 +106,8 @@ Item {
// Send Money Home BEGIN
Item {
id: sendMoneyHome;
- visible: root.currentActiveView === "sendMoneyHome";
+ z: 996;
+ visible: root.currentActiveView === "sendMoneyHome" || root.currentActiveView === "chooseRecipientConnection" || root.currentActiveView === "chooseRecipientNearby";
anchors.fill: parent;
anchors.topMargin: root.parentAppTitleBarHeight;
anchors.bottomMargin: root.parentAppNavBarHeight;
@@ -194,6 +196,17 @@ Item {
anchors.right: parent.right;
anchors.bottom: parent.bottom;
height: 440;
+
+
+ LinearGradient {
+ anchors.fill: parent;
+ start: Qt.point(0, 0);
+ end: Qt.point(0, height);
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: hifi.colors.white }
+ GradientStop { position: 1.0; color: hifi.colors.faintGray }
+ }
+ }
RalewaySemiBold {
id: sendMoneyText;
@@ -223,12 +236,13 @@ Item {
Image {
anchors.top: parent.top;
- source: "../images/wallet-bg.jpg";
- height: 60;
+ source: "./images/connection.svg";
+ height: 70;
width: parent.width;
fillMode: Image.PreserveAspectFit;
horizontalAlignment: Image.AlignHCenter;
verticalAlignment: Image.AlignTop;
+ mipmap: true;
}
RalewaySemiBold {
@@ -248,6 +262,7 @@ Item {
anchors.fill: parent;
onClicked: {
root.nextActiveView = "chooseRecipientConnection";
+ filterBar.text = "";
}
}
}
@@ -264,12 +279,13 @@ Item {
Image {
anchors.top: parent.top;
- source: "../images/wallet-bg.jpg";
- height: 60;
+ source: "./images/nearby.svg";
+ height: 70;
width: parent.width;
fillMode: Image.PreserveAspectFit;
horizontalAlignment: Image.AlignHCenter;
verticalAlignment: Image.AlignTop;
+ mipmap: true;
}
RalewaySemiBold {
@@ -299,9 +315,18 @@ Item {
// Choose Recipient Connection BEGIN
Rectangle {
id: chooseRecipientConnection;
+ z: 997;
visible: root.currentActiveView === "chooseRecipientConnection";
anchors.fill: parent;
- color: "#AAAAAA";
+ color: "#80000000";
+
+ // This object is always used in a popup or full-screen Wallet section.
+ // This MouseArea is used to prevent a user from being
+ // able to click on a button/mouseArea underneath the popup/section.
+ MouseArea {
+ anchors.fill: parent;
+ propagateComposedEvents: false;
+ }
ListModel {
id: connectionsModel;
@@ -314,6 +339,8 @@ Item {
anchors.centerIn: parent;
width: parent.width - 30;
height: parent.height - 30;
+ color: "#FFFFFF";
+ radius: 8;
RalewaySemiBold {
id: chooseRecipientText_connections;
@@ -322,11 +349,11 @@ Item {
anchors.top: parent.top;
anchors.topMargin: 26;
anchors.left: parent.left;
- anchors.leftMargin: 20;
+ anchors.leftMargin: 36;
width: paintedWidth;
height: 30;
// Text size
- size: 22;
+ size: 18;
// Style
color: hifi.colors.baseGray;
}
@@ -334,6 +361,7 @@ Item {
HiFiGlyphs {
id: closeGlyphButton_connections;
text: hifi.glyphs.close;
+ color: hifi.colors.lightGrayText;
size: 26;
anchors.top: parent.top;
anchors.topMargin: 10;
@@ -363,7 +391,7 @@ Item {
height: 40;
// Anchors
anchors.left: parent.left;
- anchors.leftMargin: 16;
+ anchors.leftMargin: 36;
anchors.right: parent.right;
anchors.rightMargin: 16;
anchors.top: chooseRecipientText_connections.bottom;
@@ -374,8 +402,10 @@ Item {
colorScheme: hifi.colorSchemes.faintGray;
hasClearButton: true;
hasRoundedBorder: true;
+ hasDefocusedBorder: false;
+ roundedBorderRadius: filterBar.height/2;
anchors.fill: parent;
- placeholderText: "filter recipients";
+ centerPlaceholderGlyph: hifi.glyphs.search;
onTextChanged: {
buildFilteredConnectionsModel();
@@ -461,17 +491,28 @@ Item {
// Choose Recipient Nearby BEGIN
Rectangle {
id: chooseRecipientNearby;
+ z: 997;
+ color: "#80000000";
property string selectedRecipient;
visible: root.currentActiveView === "chooseRecipientNearby";
anchors.fill: parent;
- color: "#AAAAAA";
+
+ // This object is always used in a popup or full-screen Wallet section.
+ // This MouseArea is used to prevent a user from being
+ // able to click on a button/mouseArea underneath the popup/section.
+ MouseArea {
+ anchors.fill: parent;
+ propagateComposedEvents: false;
+ }
Rectangle {
anchors.centerIn: parent;
width: parent.width - 30;
height: parent.height - 30;
+ color: "#FFFFFF";
+ radius: 8;
RalewaySemiBold {
text: "Choose Recipient:";
@@ -483,7 +524,7 @@ Item {
width: paintedWidth;
height: 30;
// Text size
- size: 22;
+ size: 18;
// Style
color: hifi.colors.baseGray;
}
@@ -491,6 +532,7 @@ Item {
HiFiGlyphs {
id: closeGlyphButton_nearby;
text: hifi.glyphs.close;
+ color: hifi.colors.lightGrayText;
size: 26;
anchors.top: parent.top;
anchors.topMargin: 10;
@@ -512,163 +554,142 @@ Item {
}
}
- Item {
- id: selectionInstructionsContainer;
- visible: chooseRecipientNearby.selectedRecipient === "";
- anchors.fill: parent;
-
- RalewaySemiBold {
- id: selectionInstructions_deselected;
- text: "Click/trigger on an avatar nearby to select them...";
- // Anchors
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: 200;
- anchors.left: parent.left;
- anchors.leftMargin: 58;
- anchors.right: parent.right;
- anchors.rightMargin: anchors.leftMargin;
- height: paintedHeight;
- // Text size
- size: 20;
- // Style
- color: hifi.colors.baseGray;
- horizontalAlignment: Text.AlignHCenter;
- wrapMode: Text.Wrap;
- }
+ RalewaySemiBold {
+ id: selectionInstructions;
+ text: chooseRecipientNearby.selectedRecipient === "" ? "Trigger or click on\nsomeone nearby to select them" :
+ "Trigger or click on\nsomeone else to select again";
+ // Anchors
+ anchors.top: parent.top;
+ anchors.topMargin: 100;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.right: parent.right;
+ anchors.rightMargin: anchors.leftMargin;
+ height: paintedHeight;
+ // Text size
+ size: 20;
+ // Style
+ color: hifi.colors.baseGray;
+ horizontalAlignment: Text.AlignHCenter;
+ wrapMode: Text.Wrap;
}
- Item {
+ Image {
+ anchors.top: selectionInstructions.bottom;
+ anchors.topMargin: 20;
+ anchors.bottom: selectionMadeContainer.top;
+ anchors.bottomMargin: 30;
+ source: "./images/p2p-nearby-unselected.svg";
+ width: parent.width;
+ fillMode: Image.PreserveAspectFit;
+ horizontalAlignment: Image.AlignHCenter;
+ verticalAlignment: Image.AlignVCenter;
+ mipmap: true;
+ }
+
+ Rectangle {
id: selectionMadeContainer;
- visible: !selectionInstructionsContainer.visible;
- anchors.fill: parent;
+ visible: chooseRecipientNearby.selectedRecipient !== "";
+ anchors.bottom: parent.bottom;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ height: 190;
+ color: "#F3F3F3";
+ radius: 8;
+
+ // Used to square off the top left and top right edges of this container
+ Rectangle {
+ color: "#F3F3F3";
+ height: selectionMadeContainer.radius;
+ anchors.top: selectionMadeContainer.top;
+ anchors.left: selectionMadeContainer.left;
+ anchors.right: selectionMadeContainer.right;
+ }
RalewaySemiBold {
id: sendToText;
- text: "Send To:";
+ text: "Send to:";
// Anchors
anchors.top: parent.top;
- anchors.topMargin: 120;
+ anchors.topMargin: 36;
anchors.left: parent.left;
- anchors.leftMargin: 12;
+ anchors.leftMargin: 36;
width: paintedWidth;
height: paintedHeight;
// Text size
- size: 20;
+ size: 18;
// Style
color: hifi.colors.baseGray;
}
+ Image {
+ id: selectedImage;
+ anchors.top: parent.top;
+ anchors.topMargin: 24;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 32;
+ anchors.left: sendToText.right;
+ anchors.leftMargin: 4;
+ source: "./images/p2p-nearby-selected.svg";
+ width: 50;
+ fillMode: Image.PreserveAspectFit;
+ horizontalAlignment: Image.AlignHCenter;
+ verticalAlignment: Image.AlignVCenter;
+ mipmap: true;
+ }
+
RalewaySemiBold {
id: avatarDisplayName;
text: '"' + AvatarList.getAvatar(chooseRecipientNearby.selectedRecipient).sessionDisplayName + '"';
// Anchors
- anchors.top: sendToText.bottom;
- anchors.topMargin: 60;
- anchors.left: parent.left;
- anchors.leftMargin: 30;
+ anchors.top: parent.top;
+ anchors.topMargin: 34;
+ anchors.left: selectedImage.right;
+ anchors.leftMargin: 10;
anchors.right: parent.right;
- anchors.rightMargin: 30;
+ anchors.rightMargin: 10;
height: paintedHeight;
// Text size
- size: 22;
+ size: 20;
// Style
- horizontalAlignment: Text.AlignHCenter;
- color: hifi.colors.baseGray;
- }
-
- RalewaySemiBold {
- id: avatarNodeID;
- text: chooseRecipientNearby.selectedRecipient;
- // Anchors
- anchors.top: avatarDisplayName.bottom;
- anchors.topMargin: 6;
- anchors.left: parent.left;
- anchors.leftMargin: 30;
- anchors.right: parent.right;
- anchors.rightMargin: 30;
- height: paintedHeight;
- // Text size
- size: 14;
- // Style
- horizontalAlignment: Text.AlignHCenter;
- color: hifi.colors.lightGrayText;
+ color: hifi.colors.blueAccent;
}
RalewaySemiBold {
id: avatarUserName;
text: sendMoneyStep.selectedRecipientUserName;
// Anchors
- anchors.top: avatarNodeID.bottom;
- anchors.topMargin: 12;
- anchors.left: parent.left;
- anchors.leftMargin: 30;
+ anchors.top: avatarDisplayName.bottom;
+ anchors.topMargin: 16;
+ anchors.left: selectedImage.right;
+ anchors.leftMargin: 10;
anchors.right: parent.right;
- anchors.rightMargin: 30;
+ anchors.rightMargin: 10;
height: paintedHeight;
// Text size
- size: 22;
+ size: 18;
// Style
- horizontalAlignment: Text.AlignHCenter;
color: hifi.colors.baseGray;
}
- RalewaySemiBold {
- id: selectionInstructions_selected;
- text: "Click/trigger on another avatar nearby to select them...\n\nor press 'Next' to continue.";
- // Anchors
+ // "CHOOSE" button
+ HifiControlsUit.Button {
+ id: chooseButton;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.horizontalCenter: parent.horizontalCenter;
anchors.bottom: parent.bottom;
- anchors.bottomMargin: 200;
- anchors.left: parent.left;
- anchors.leftMargin: 58;
- anchors.right: parent.right;
- anchors.rightMargin: anchors.leftMargin;
- height: paintedHeight;
- // Text size
- size: 20;
- // Style
- color: hifi.colors.baseGray;
- horizontalAlignment: Text.AlignHCenter;
- wrapMode: Text.Wrap;
- }
- }
+ anchors.bottomMargin: 20;
+ height: 40;
+ width: 110;
+ text: "CHOOSE";
+ onClicked: {
+ sendMoneyStep.referrer = "nearby";
+ sendMoneyStep.selectedRecipientNodeID = chooseRecipientNearby.selectedRecipient;
+ chooseRecipientNearby.selectedRecipient = "";
- // "Cancel" button
- HifiControlsUit.Button {
- id: cancelButton;
- color: hifi.buttons.noneBorderless;
- colorScheme: hifi.colorSchemes.dark;
- anchors.left: parent.left;
- anchors.leftMargin: 60;
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: 80;
- height: 50;
- width: 120;
- text: "Cancel";
- onClicked: {
- root.nextActiveView = "sendMoneyHome";
- resetSendMoneyData();
- }
- }
-
- // "Next" button
- HifiControlsUit.Button {
- id: nextButton;
- enabled: chooseRecipientNearby.selectedRecipient !== "";
- color: hifi.buttons.blue;
- colorScheme: hifi.colorSchemes.dark;
- anchors.right: parent.right;
- anchors.rightMargin: 60;
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: 80;
- height: 50;
- width: 120;
- text: "Next";
- onClicked: {
- sendMoneyStep.referrer = "nearby";
- sendMoneyStep.selectedRecipientNodeID = chooseRecipientNearby.selectedRecipient;
- chooseRecipientNearby.selectedRecipient = "";
-
- root.nextActiveView = "sendMoneyStep";
+ root.nextActiveView = "sendMoneyStep";
+ }
}
}
}
@@ -676,9 +697,9 @@ Item {
// Choose Recipient Nearby END
// Send Money Screen BEGIN
- Rectangle {
+ Item {
id: sendMoneyStep;
- z: 997;
+ z: 996;
property string referrer; // either "connections" or "nearby"
property string selectedRecipientNodeID;
@@ -688,284 +709,333 @@ Item {
visible: root.currentActiveView === "sendMoneyStep";
anchors.fill: parent;
- color: "#AAAAAA";
+ anchors.topMargin: root.parentAppTitleBarHeight;
- Rectangle {
- anchors.centerIn: parent;
- width: parent.width - 30;
- height: parent.height - 30;
+ RalewaySemiBold {
+ id: sendMoneyText_sendMoneyStep;
+ text: "Send Money";
+ // Anchors
+ anchors.top: parent.top;
+ anchors.topMargin: 26;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ width: paintedWidth;
+ height: 30;
+ // Text size
+ size: 22;
+ // Style
+ color: hifi.colors.white;
+ }
+
+ Item {
+ id: sendToContainer;
+ anchors.top: sendMoneyText_sendMoneyStep.bottom;
+ anchors.topMargin: 20;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.right: parent.right;
+ anchors.rightMargin: 20;
+ height: 80;
RalewaySemiBold {
- id: sendMoneyText_sendMoneyStep;
- text: "Send Money To:";
+ id: sendToText_sendMoneyStep;
+ text: "Send to:";
// Anchors
anchors.top: parent.top;
- anchors.topMargin: 26;
anchors.left: parent.left;
- anchors.leftMargin: 20;
- width: paintedWidth;
- height: 30;
+ anchors.bottom: parent.bottom;
+ width: 90;
// Text size
- size: 22;
+ size: 18;
// Style
- color: hifi.colors.baseGray;
+ color: hifi.colors.white;
+ verticalAlignment: Text.AlignVCenter;
}
- Item {
- id: sendToContainer;
- anchors.top: sendMoneyText_sendMoneyStep.bottom;
- anchors.topMargin: 20;
- anchors.left: parent.left;
- anchors.leftMargin: 20;
+ RecipientDisplay {
+ anchors.top: parent.top;
+ anchors.left: sendToText_sendMoneyStep.right;
+ anchors.right: changeButton.left;
+ anchors.rightMargin: 12;
+ height: parent.height;
+
+ displayName: sendMoneyStep.selectedRecipientDisplayName;
+ userName: sendMoneyStep.selectedRecipientUserName;
+ profilePic: sendMoneyStep.selectedRecipientProfilePic !== "" ? ((0 === sendMoneyStep.selectedRecipientProfilePic.indexOf("http")) ?
+ sendMoneyStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendMoneyStep.selectedRecipientProfilePic)) : "";
+ isDisplayingNearby: sendMoneyStep.referrer === "nearby";
+ }
+
+ // "CHANGE" button
+ HifiControlsUit.Button {
+ id: changeButton;
+ color: hifi.buttons.none;
+ colorScheme: hifi.colorSchemes.dark;
anchors.right: parent.right;
- anchors.rightMargin: 20;
- height: 80;
-
- RalewaySemiBold {
- id: sendToText_sendMoneyStep;
- text: "Send To:";
- // Anchors
- anchors.top: parent.top;
- anchors.left: parent.left;
- anchors.bottom: parent.bottom;
- width: 90;
- // Text size
- size: 18;
- // Style
- color: hifi.colors.baseGray;
- verticalAlignment: Text.AlignVCenter;
- }
-
- RecipientDisplay {
- anchors.top: parent.top;
- anchors.left: sendToText_sendMoneyStep.right;
- anchors.right: changeButton.left;
- anchors.rightMargin: 12;
- height: parent.height;
-
- displayName: sendMoneyStep.selectedRecipientDisplayName;
- userName: sendMoneyStep.selectedRecipientUserName;
- profilePic: sendMoneyStep.selectedRecipientProfilePic !== "" ? ((0 === sendMoneyStep.selectedRecipientProfilePic.indexOf("http")) ?
- sendMoneyStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendMoneyStep.selectedRecipientProfilePic)) : "";
- isDisplayingNearby: sendMoneyStep.referrer === "nearby";
- }
-
- // "CHANGE" button
- HifiControlsUit.Button {
- id: changeButton;
- color: hifi.buttons.black;
- colorScheme: hifi.colorSchemes.dark;
- anchors.right: parent.right;
- anchors.verticalCenter: parent.verticalCenter;
- height: 35;
- width: 120;
- text: "CHANGE";
- onClicked: {
- if (sendMoneyStep.referrer === "connections") {
- root.nextActiveView = "chooseRecipientConnection";
- } else if (sendMoneyStep.referrer === "nearby") {
- root.nextActiveView = "chooseRecipientNearby";
- }
- resetSendMoneyData();
+ anchors.verticalCenter: parent.verticalCenter;
+ height: 35;
+ width: 100;
+ text: "CHANGE";
+ onClicked: {
+ if (sendMoneyStep.referrer === "connections") {
+ root.nextActiveView = "chooseRecipientConnection";
+ } else if (sendMoneyStep.referrer === "nearby") {
+ root.nextActiveView = "chooseRecipientNearby";
}
+ resetSendMoneyData();
+ }
+ }
+ }
+
+ Item {
+ id: amountContainer;
+ anchors.top: sendToContainer.bottom;
+ anchors.topMargin: 2;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.right: parent.right;
+ anchors.rightMargin: 20;
+ height: 80;
+
+ RalewaySemiBold {
+ id: amountText;
+ text: "Amount:";
+ // Anchors
+ anchors.top: parent.top;
+ anchors.left: parent.left;
+ anchors.bottom: parent.bottom;
+ width: 90;
+ // Text size
+ size: 18;
+ // Style
+ color: hifi.colors.white;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ HifiControlsUit.TextField {
+ id: amountTextField;
+ colorScheme: hifi.colorSchemes.dark;
+ inputMethodHints: Qt.ImhDigitsOnly;
+ // Anchors
+ anchors.verticalCenter: parent.verticalCenter;
+ anchors.left: amountText.right;
+ anchors.right: parent.right;
+ height: 50;
+ // Style
+ leftPermanentGlyph: hifi.glyphs.hfc;
+ activeFocusOnPress: true;
+ activeFocusOnTab: true;
+
+ validator: IntValidator { bottom: 0; }
+
+ onAccepted: {
+ optionalMessage.focus = true;
}
}
- Item {
- id: amountContainer;
- anchors.top: sendToContainer.bottom;
+ FiraSansSemiBold {
+ visible: amountTextFieldError.text === "";
+ text: "Balance: ";
+ // Anchors
+ anchors.top: amountTextField.bottom;
anchors.topMargin: 2;
- anchors.left: parent.left;
- anchors.leftMargin: 20;
- anchors.right: parent.right;
- anchors.rightMargin: 20;
- height: 80;
-
- RalewaySemiBold {
- id: amountText;
- text: "Amount:";
- // Anchors
- anchors.top: parent.top;
- anchors.left: parent.left;
- anchors.bottom: parent.bottom;
- width: 90;
- // Text size
- size: 18;
- // Style
- color: hifi.colors.baseGray;
- verticalAlignment: Text.AlignVCenter;
- }
-
- HifiControlsUit.TextField {
- id: amountTextField;
- colorScheme: hifi.colorSchemes.light;
- inputMethodHints: Qt.ImhDigitsOnly;
- // Anchors
- anchors.verticalCenter: parent.verticalCenter;
- anchors.left: amountText.right;
- anchors.right: parent.right;
- height: 50;
- // Style
- leftPlaceholderGlyph: hifi.glyphs.hfc;
- activeFocusOnPress: true;
- activeFocusOnTab: true;
-
- validator: IntValidator { bottom: 0; }
-
- onAccepted: {
- optionalMessage.focus = true;
- }
- }
-
- RalewaySemiBold {
- id: amountTextFieldError;
- // Anchors
- anchors.top: amountTextField.bottom;
- anchors.topMargin: 2;
- anchors.left: amountTextField.left;
- anchors.right: amountTextField.right;
- height: 40;
- // Text size
- size: 16;
- // Style
- color: hifi.colors.baseGray;
- verticalAlignment: Text.AlignTop;
- horizontalAlignment: Text.AlignRight;
- }
+ anchors.left: amountTextField.left;
+ anchors.right: sendMoneyBalanceText_HFC.left;
+ width: paintedWidth;
+ height: 40;
+ // Text size
+ size: 16;
+ // Style
+ color: hifi.colors.lightGrayText;
+ verticalAlignment: Text.AlignTop;
+ horizontalAlignment: Text.AlignRight;
+ }
+ HiFiGlyphs {
+ id: sendMoneyBalanceText_HFC;
+ visible: amountTextFieldError.text === "";
+ text: hifi.glyphs.hfc;
+ // Size
+ size: 16;
+ // Anchors
+ anchors.top: amountTextField.bottom;
+ anchors.topMargin: 2;
+ anchors.right: sendMoneyBalanceText.left;
+ width: paintedWidth;
+ height: 40;
+ // Style
+ color: hifi.colors.lightGrayText;
+ verticalAlignment: Text.AlignTop;
+ horizontalAlignment: Text.AlignRight;
+ }
+ FiraSansSemiBold {
+ id: sendMoneyBalanceText;
+ visible: amountTextFieldError.text === "";
+ text: balanceText.text;
+ // Anchors
+ anchors.top: amountTextField.bottom;
+ anchors.topMargin: 2;
+ anchors.right: amountTextField.right;
+ width: paintedWidth;
+ height: 40;
+ // Text size
+ size: 16;
+ // Style
+ color: hifi.colors.lightGrayText;
+ verticalAlignment: Text.AlignTop;
+ horizontalAlignment: Text.AlignRight;
}
- Item {
- id: messageContainer;
- anchors.top: amountContainer.bottom;
- anchors.topMargin: 16;
- anchors.left: parent.left;
- anchors.leftMargin: 20;
- anchors.right: parent.right;
- anchors.rightMargin: 20;
- height: 140;
+ RalewaySemiBold {
+ id: amountTextFieldError;
+ // Anchors
+ anchors.top: amountTextField.bottom;
+ anchors.topMargin: 2;
+ anchors.left: amountTextField.left;
+ anchors.right: amountTextField.right;
+ height: 40;
+ // Text size
+ size: 16;
+ // Style
+ color: hifi.colors.white;
+ verticalAlignment: Text.AlignTop;
+ horizontalAlignment: Text.AlignRight;
+ }
+ }
+
+ Item {
+ id: messageContainer;
+ anchors.top: amountContainer.bottom;
+ anchors.topMargin: 16;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.right: parent.right;
+ anchors.rightMargin: 20;
+ height: 140;
- FontLoader { id: firaSansSemiBold; source: "../../../../../fonts/FiraSans-SemiBold.ttf"; }
- TextArea {
- id: optionalMessage;
- property int maximumLength: 70;
- property string previousText: text;
- placeholderText: "Optional Message";
- font.family: firaSansSemiBold.name;
- font.pixelSize: 20;
- // Anchors
+ FontLoader { id: firaSansSemiBold; source: "../../../../../fonts/FiraSans-SemiBold.ttf"; }
+ TextArea {
+ id: optionalMessage;
+ property int maximumLength: 72;
+ property string previousText: text;
+ placeholderText: "Optional Message (" + maximumLength + " character limit)";
+ font.family: firaSansSemiBold.name;
+ font.pixelSize: 20;
+ // Anchors
+ anchors.fill: parent;
+ // Style
+ background: Rectangle {
anchors.fill: parent;
- // Style
- background: Rectangle {
- anchors.fill: parent;
- color: optionalMessage.activeFocus ? hifi.colors.white : hifi.colors.textFieldLightBackground;
- border.width: optionalMessage.activeFocus ? 1 : 0;
- border.color: optionalMessage.activeFocus ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground;
- }
- color: hifi.colors.black;
- textFormat: TextEdit.PlainText;
- wrapMode: TextEdit.Wrap;
- activeFocusOnPress: true;
- activeFocusOnTab: true;
- // Workaround for no max length on TextAreas
- onTextChanged: {
- if (text.length > maximumLength) {
- var cursor = cursorPosition;
- text = previousText;
- if (cursor > text.length) {
- cursorPosition = text.length;
- } else {
- cursorPosition = cursor-1;
- }
- }
- previousText = text;
- }
+ color: optionalMessage.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow;
+ border.width: optionalMessage.activeFocus ? 1 : 0;
+ border.color: optionalMessage.activeFocus ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground;
}
- RalewaySemiBold {
- id: optionalMessageCharacterCount;
- text: optionalMessage.text.length + "/" + optionalMessage.maximumLength;
- // Anchors
- anchors.top: optionalMessage.bottom;
- anchors.topMargin: 2;
- anchors.right: optionalMessage.right;
- height: paintedHeight;
- // Text size
- size: 16;
- // Style
- color: hifi.colors.baseGray;
- verticalAlignment: Text.AlignTop;
- horizontalAlignment: Text.AlignRight;
+ color: hifi.colors.white;
+ textFormat: TextEdit.PlainText;
+ wrapMode: TextEdit.Wrap;
+ activeFocusOnPress: true;
+ activeFocusOnTab: true;
+ // Workaround for no max length on TextAreas
+ onTextChanged: {
+ if (text.length > maximumLength) {
+ var cursor = cursorPosition;
+ text = previousText;
+ if (cursor > text.length) {
+ cursorPosition = text.length;
+ } else {
+ cursorPosition = cursor-1;
+ }
+ }
+ previousText = text;
+ }
+ }
+ FiraSansSemiBold {
+ id: optionalMessageCharacterCount;
+ text: optionalMessage.text.length + "/" + optionalMessage.maximumLength;
+ // Anchors
+ anchors.top: optionalMessage.bottom;
+ anchors.topMargin: 4;
+ anchors.right: optionalMessage.right;
+ height: paintedHeight;
+ // Text size
+ size: 16;
+ // Style
+ color: optionalMessage.text.length === optionalMessage.maximumLength ? "#ea89a5" : hifi.colors.lightGrayText;
+ verticalAlignment: Text.AlignTop;
+ horizontalAlignment: Text.AlignRight;
+ }
+ }
+
+ HifiControlsUit.CheckBox {
+ id: sendPubliclyCheckbox;
+ visible: false; // FIXME ONCE PARTICLE EFFECTS ARE IN
+ text: "Send Publicly"
+ // Anchors
+ anchors.top: messageContainer.bottom;
+ anchors.topMargin: 16;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.right: parent.right;
+ anchors.rightMargin: 16;
+ boxSize: 24;
+ }
+
+ Item {
+ id: bottomBarContainer;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.right: parent.right;
+ anchors.rightMargin: 20;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 20;
+ height: 60;
+
+ // "CANCEL" button
+ HifiControlsUit.Button {
+ id: cancelButton_sendMoneyStep;
+ color: hifi.buttons.noneBorderlessWhite;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.left: parent.left;
+ anchors.leftMargin: 24;
+ anchors.verticalCenter: parent.verticalCenter;
+ height: 40;
+ width: 150;
+ text: "CANCEL";
+ onClicked: {
+ resetSendMoneyData();
+ root.nextActiveView = "sendMoneyHome";
}
}
- Item {
- id: bottomBarContainer;
- anchors.top: messageContainer.bottom;
- anchors.topMargin: 30;
- anchors.left: parent.left;
- anchors.leftMargin: 20;
+ // "SEND" button
+ HifiControlsUit.Button {
+ id: sendButton;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
anchors.right: parent.right;
- anchors.rightMargin: 20;
- height: 80;
-
- HifiControlsUit.CheckBox {
- id: sendPubliclyCheckbox;
- visible: false; // FIXME ONCE PARTICLE EFFECTS ARE IN
- text: "Send Publicly"
- // Anchors
- anchors.verticalCenter: parent.verticalCenter;
- anchors.left: parent.left;
- anchors.right: cancelButton_sendMoneyStep.left;
- anchors.rightMargin: 16;
- boxSize: 24;
- }
-
- // "CANCEL" button
- HifiControlsUit.Button {
- id: cancelButton_sendMoneyStep;
- color: hifi.buttons.noneBorderless;
- colorScheme: hifi.colorSchemes.dark;
- anchors.right: sendButton.left;
- anchors.rightMargin: 16;
- anchors.verticalCenter: parent.verticalCenter;
- height: 35;
- width: 100;
- text: "CANCEL";
- onClicked: {
- resetSendMoneyData();
- root.nextActiveView = "sendMoneyHome";
- }
- }
-
- // "SEND" button
- HifiControlsUit.Button {
- id: sendButton;
- color: hifi.buttons.blue;
- colorScheme: hifi.colorSchemes.dark;
- anchors.right: parent.right;
- anchors.verticalCenter: parent.verticalCenter;
- height: 35;
- width: 100;
- text: "SEND";
- onClicked: {
- if (parseInt(amountTextField.text) > parseInt(balanceText.text)) {
- amountTextField.focus = true;
- amountTextField.error = true;
- amountTextFieldError.text = "amount exceeds available funds";
- } else if (amountTextField.text === "" || parseInt(amountTextField.text) < 1) {
- amountTextField.focus = true;
- amountTextField.error = true;
- amountTextFieldError.text = "invalid amount";
- } else {
- amountTextFieldError.text = "";
- amountTextField.error = false;
- root.isCurrentlySendingMoney = true;
- amountTextField.focus = false;
- optionalMessage.focus = false;
- if (sendMoneyStep.referrer === "connections") {
- Commerce.transferHfcToUsername(sendMoneyStep.selectedRecipientUserName, parseInt(amountTextField.text), optionalMessage.text);
- } else if (sendMoneyStep.referrer === "nearby") {
- Commerce.transferHfcToNode(sendMoneyStep.selectedRecipientNodeID, parseInt(amountTextField.text), optionalMessage.text);
- }
+ anchors.rightMargin: 24;
+ anchors.verticalCenter: parent.verticalCenter;
+ height: 40;
+ width: 150;
+ text: "SUBMIT";
+ onClicked: {
+ if (parseInt(amountTextField.text) > parseInt(balanceText.text)) {
+ amountTextField.focus = true;
+ amountTextField.error = true;
+ amountTextFieldError.text = "amount exceeds available funds";
+ } else if (amountTextField.text === "" || parseInt(amountTextField.text) < 1) {
+ amountTextField.focus = true;
+ amountTextField.error = true;
+ amountTextFieldError.text = "invalid amount";
+ } else {
+ amountTextFieldError.text = "";
+ amountTextField.error = false;
+ root.isCurrentlySendingMoney = true;
+ amountTextField.focus = false;
+ optionalMessage.focus = false;
+ if (sendMoneyStep.referrer === "connections") {
+ Commerce.transferHfcToUsername(sendMoneyStep.selectedRecipientUserName, parseInt(amountTextField.text), optionalMessage.text);
+ } else if (sendMoneyStep.referrer === "nearby") {
+ Commerce.transferHfcToNode(sendMoneyStep.selectedRecipientNodeID, parseInt(amountTextField.text), optionalMessage.text);
}
}
}
@@ -981,7 +1051,7 @@ Item {
visible: root.isCurrentlySendingMoney;
anchors.fill: parent;
- color: Qt.rgba(0.0, 0.0, 0.0, 0.5);
+ color: Qt.rgba(0.0, 0.0, 0.0, 0.8);
// This object is always used in a popup or full-screen Wallet section.
// This MouseArea is used to prevent a user from being
@@ -993,11 +1063,10 @@ Item {
AnimatedImage {
id: sendingMoneyImage;
- source: "../../../../../icons/profilePicLoading.gif"
- width: 160;
+ source: "./images/loader.gif"
+ width: 96;
height: width;
- anchors.top: parent.top;
- anchors.topMargin: 185;
+ anchors.verticalCenter: parent.verticalCenter;
anchors.horizontalCenter: parent.horizontalCenter;
}
@@ -1005,11 +1074,11 @@ Item {
text: "Sending";
// Anchors
anchors.top: sendingMoneyImage.bottom;
- anchors.topMargin: 22;
+ anchors.topMargin: 4;
anchors.horizontalCenter: parent.horizontalCenter;
width: paintedWidth;
// Text size
- size: 24;
+ size: 26;
// Style
color: hifi.colors.white;
verticalAlignment: Text.AlignVCenter;
@@ -1018,17 +1087,17 @@ Item {
// Sending Money Overlay END
// Payment Success BEGIN
- Rectangle {
+ Item {
id: paymentSuccess;
visible: root.currentActiveView === "paymentSuccess";
anchors.fill: parent;
- color: "#AAAAAA";
Rectangle {
anchors.centerIn: parent;
width: parent.width - 30;
height: parent.height - 30;
+ color: "#FFFFFF";
RalewaySemiBold {
id: paymentSentText;
@@ -1049,6 +1118,7 @@ Item {
HiFiGlyphs {
id: closeGlyphButton_paymentSuccess;
text: hifi.glyphs.close;
+ color: hifi.colors.lightGrayText;
size: 26;
anchors.top: parent.top;
anchors.topMargin: 10;
@@ -1100,6 +1170,7 @@ Item {
anchors.left: sendToText_paymentSuccess.right;
anchors.right: parent.right;
height: parent.height;
+ textColor: hifi.colors.blueAccent;
displayName: sendMoneyStep.selectedRecipientDisplayName;
userName: sendMoneyStep.selectedRecipientUserName;
@@ -1145,10 +1216,10 @@ Item {
anchors.verticalCenter: parent.verticalCenter;
height: 50;
// Style
- color: hifi.colors.baseGray;
+ color: hifi.colors.blueAccent;
}
- RalewaySemiBold {
+ FiraSansSemiBold {
id: amountSentText;
text: amountTextField.text;
// Anchors
@@ -1159,7 +1230,7 @@ Item {
height: 50;
// Style
size: 22;
- color: hifi.colors.baseGray;
+ color: hifi.colors.blueAccent;
}
}
@@ -1177,7 +1248,7 @@ Item {
// Text size
size: 22;
// Style
- color: hifi.colors.baseGray;
+ color: hifi.colors.blueAccent;
wrapMode: Text.Wrap;
verticalAlignment: Text.AlignTop;
}
@@ -1203,17 +1274,17 @@ Item {
// Payment Success END
// Payment Failure BEGIN
- Rectangle {
+ Item {
id: paymentFailure;
visible: root.currentActiveView === "paymentFailure";
anchors.fill: parent;
- color: "#AAAAAA";
Rectangle {
anchors.centerIn: parent;
width: parent.width - 30;
height: parent.height - 30;
+ color: "#FFFFFF";
RalewaySemiBold {
id: paymentFailureText;
@@ -1234,6 +1305,7 @@ Item {
HiFiGlyphs {
id: closeGlyphButton_paymentFailure;
text: hifi.glyphs.close;
+ color: hifi.colors.lightGrayText;
size: 26;
anchors.top: parent.top;
anchors.topMargin: 10;
@@ -1303,6 +1375,7 @@ Item {
anchors.left: sentToText_paymentFailure.right;
anchors.right: parent.right;
height: parent.height;
+ textColor: hifi.colors.baseGray;
displayName: sendMoneyStep.selectedRecipientDisplayName;
userName: sendMoneyStep.selectedRecipientUserName;
@@ -1351,7 +1424,7 @@ Item {
color: hifi.colors.baseGray;
}
- RalewaySemiBold {
+ FiraSansSemiBold {
id: amountSentText_paymentFailure;
text: amountTextField.text;
// Anchors
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/connection.svg b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/connection.svg
new file mode 100644
index 0000000000..7c5403fda3
--- /dev/null
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/connection.svg
@@ -0,0 +1,14 @@
+
+
+
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/loader.gif b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/loader.gif
new file mode 100644
index 0000000000..0536bd1884
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/loader.gif differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/nearby.svg b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/nearby.svg
new file mode 100644
index 0000000000..dec87e658d
--- /dev/null
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/nearby.svg
@@ -0,0 +1,27 @@
+
+
+
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/p2p-nearby-selected.svg b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/p2p-nearby-selected.svg
new file mode 100644
index 0000000000..59635a99b1
--- /dev/null
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/p2p-nearby-selected.svg
@@ -0,0 +1,27 @@
+
+
+
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/p2p-nearby-unselected.svg b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/p2p-nearby-unselected.svg
new file mode 100644
index 0000000000..bba07b9567
--- /dev/null
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/p2p-nearby-unselected.svg
@@ -0,0 +1,30 @@
+
+
+
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 8b1d70e9e2..ffe2f781db 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -504,7 +504,13 @@ public:
}
if (message->message == WM_DEVICECHANGE) {
- Midi::USBchanged(); // re-scan the MIDI bus
+ const float MIN_DELTA_SECONDS = 2.0f; // de-bounce signal
+ static float lastTriggerTime = 0.0f;
+ const float deltaSeconds = secTimestampNow() - lastTriggerTime;
+ lastTriggerTime = secTimestampNow();
+ if (deltaSeconds > MIN_DELTA_SECONDS) {
+ Midi::USBchanged(); // re-scan the MIDI bus
+ }
}
}
return false;
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index 11496f727e..e93b897013 100755
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -2019,8 +2019,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
_smoothOrientationTimer = 0.0f;
}
- getHead()->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime);
-
+ Head* head = getHead();
auto headPose = getControllerPoseInAvatarFrame(controller::Action::HEAD);
if (headPose.isValid()) {
glm::quat localOrientation = headPose.rotation * Quaternions::Y_180;
@@ -2032,6 +2031,10 @@ void MyAvatar::updateOrientation(float deltaTime) {
head->setBaseYaw(YAW(euler));
head->setBasePitch(PITCH(euler));
head->setBaseRoll(ROLL(euler));
+ } else {
+ head->setBaseYaw(0.0f);
+ head->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime);
+ head->setBaseRoll(0.0f);
}
}
diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp
index a334834979..ac5a467e76 100644
--- a/interface/src/raypick/PointerScriptingInterface.cpp
+++ b/interface/src/raypick/PointerScriptingInterface.cpp
@@ -175,8 +175,4 @@ QVariantMap PointerScriptingInterface::getPrevPickResult(unsigned int uid) const
result = pickResult->toVariantMap();
}
return result;
-}
-
-void PointerScriptingInterface::setDoesHover(unsigned int uid, bool hover) const {
- DependencyManager::get()->setDoesHover(uid, hover);
-}
+}
\ No newline at end of file
diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h
index 451c132769..1cc7b56503 100644
--- a/interface/src/raypick/PointerScriptingInterface.h
+++ b/interface/src/raypick/PointerScriptingInterface.h
@@ -202,14 +202,6 @@ public:
*/
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay, offsetMat); }
- /**jsdoc
- * Sets whether or not a pointer should generate hover events.
- * @function Pointers.setDoesHover
- * @param {boolean} uid - The ID of the Pointer, as returned by {@link Pointers.createPointer}.
- * @param {boolean} hover - If true
then the pointer generates hover events, otherwise it does not.
- */
- Q_INVOKABLE void setDoesHover(unsigned int uid, bool hove) const;
-
/**jsdoc
* Check if a Pointer is associated with the left hand.
* @function Pointers.isLeftHand
diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp
index d29ee93e62..4804a2db3d 100644
--- a/interface/src/ui/overlays/ModelOverlay.cpp
+++ b/interface/src/ui/overlays/ModelOverlay.cpp
@@ -564,9 +564,9 @@ void ModelOverlay::animate() {
rotationMat * fbxJoints[index].postTransform);
auto& jointData = jointsData[j];
jointData.translation = extractTranslation(finalMat);
- jointData.translationSet = true;
+ jointData.translationIsDefaultPose = false;
jointData.rotation = glmExtractRotation(finalMat);
- jointData.rotationSet = true;
+ jointData.rotationIsDefaultPose = false;
}
}
// Set the data in the model
diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp
index 1c9d9a3447..b1b41775a8 100644
--- a/libraries/animation/src/Rig.cpp
+++ b/libraries/animation/src/Rig.cpp
@@ -1705,16 +1705,16 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const {
// rotations are in absolute rig frame.
glm::quat defaultAbsRot = geometryToRigPose.rot() * _animSkeleton->getAbsoluteDefaultPose(i).rot();
data.rotation = _internalPoseSet._absolutePoses[i].rot();
- data.rotationSet = !isEqual(data.rotation, defaultAbsRot);
+ data.rotationIsDefaultPose = isEqual(data.rotation, defaultAbsRot);
// translations are in relative frame but scaled so that they are in meters,
// instead of geometry units.
glm::vec3 defaultRelTrans = _geometryOffset.scale() * _animSkeleton->getRelativeDefaultPose(i).trans();
data.translation = _geometryOffset.scale() * _internalPoseSet._relativePoses[i].trans();
- data.translationSet = !isEqual(data.translation, defaultRelTrans);
+ data.translationIsDefaultPose = isEqual(data.translation, defaultRelTrans);
} else {
- data.translationSet = false;
- data.rotationSet = false;
+ data.translationIsDefaultPose = true;
+ data.rotationIsDefaultPose = true;
}
}
}
@@ -1739,11 +1739,11 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) {
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
for (int i = 0; i < numJoints; i++) {
const JointData& data = jointDataVec.at(i);
- if (data.rotationSet) {
+ if (data.rotationIsDefaultPose) {
+ rotations.push_back(absoluteDefaultPoses[i].rot());
+ } else {
// JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame
rotations.push_back(rigToGeometryRot * data.rotation);
- } else {
- rotations.push_back(absoluteDefaultPoses[i].rot());
}
}
@@ -1759,11 +1759,11 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) {
const JointData& data = jointDataVec.at(i);
_internalPoseSet._relativePoses[i].scale() = Vectors::ONE;
_internalPoseSet._relativePoses[i].rot() = rotations[i];
- if (data.translationSet) {
+ if (data.translationIsDefaultPose) {
+ _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans();
+ } else {
// JointData translations are in scaled relative-frame so we scale back to regular relative-frame
_internalPoseSet._relativePoses[i].trans() = _invGeometryOffset.scale() * data.translation;
- } else {
- _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans();
}
}
}
diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp
index 94df5bf7f4..2a3c0452f3 100644
--- a/libraries/avatars/src/AvatarData.cpp
+++ b/libraries/avatars/src/AvatarData.cpp
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include "AvatarLogging.h"
@@ -77,6 +78,16 @@ size_t AvatarDataPacket::maxJointDataSize(size_t numJoints) {
return totalSize;
}
+size_t AvatarDataPacket::maxJointDefaultPoseFlagsSize(size_t numJoints) {
+ const size_t bitVectorSize = calcBitVectorSize((int)numJoints);
+ size_t totalSize = sizeof(uint8_t); // numJoints
+
+ // one set of bits for rotation and one for translation
+ const size_t NUM_BIT_VECTORS_IN_DEFAULT_POSE_FLAGS_SECTION = 2;
+ totalSize += NUM_BIT_VECTORS_IN_DEFAULT_POSE_FLAGS_SECTION * bitVectorSize;
+
+ return totalSize;
+}
AvatarData::AvatarData() :
SpatiallyNestable(NestableType::Avatar, QUuid()),
@@ -272,6 +283,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
bool hasFaceTrackerInfo = false;
bool hasJointData = false;
+ bool hasJointDefaultPoseFlags = false;
if (sendPALMinimum) {
hasAudioLoudness = true;
@@ -290,12 +302,14 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
hasFaceTrackerInfo = !dropFaceTracking && hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime));
hasJointData = sendAll || !sendMinimum;
+ hasJointDefaultPoseFlags = hasJointData;
}
const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE +
(hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) +
- (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0);
+ (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0) +
+ (hasJointDefaultPoseFlags ? AvatarDataPacket::maxJointDefaultPoseFlagsSize(_jointData.size()) : 0);
QByteArray avatarDataByteArray((int)byteArraySize, 0);
unsigned char* destinationBuffer = reinterpret_cast(avatarDataByteArray.data());
@@ -314,7 +328,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
| (hasParentInfo ? AvatarDataPacket::PACKET_HAS_PARENT_INFO : 0)
| (hasAvatarLocalPosition ? AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION : 0)
| (hasFaceTrackerInfo ? AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO : 0)
- | (hasJointData ? AvatarDataPacket::PACKET_HAS_JOINT_DATA : 0);
+ | (hasJointData ? AvatarDataPacket::PACKET_HAS_JOINT_DATA : 0)
+ | (hasJointDefaultPoseFlags ? AvatarDataPacket::PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS : 0);
memcpy(destinationBuffer, &packetStateFlags, sizeof(packetStateFlags));
destinationBuffer += sizeof(packetStateFlags);
@@ -541,14 +556,19 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
for (int i = 0; i < _jointData.size(); i++) {
const JointData& data = _jointData[i];
+ const JointData& last = lastSentJointData[i];
- // The dot product for smaller rotations is a smaller number.
- // So if the dot() is less than the value, then the rotation is a larger angle of rotation
- bool largeEnoughRotation = fabsf(glm::dot(data.rotation, lastSentJointData[i].rotation)) < minRotationDOT;
+ if (!data.rotationIsDefaultPose) {
+ if (sendAll || last.rotationIsDefaultPose || last.rotation != data.rotation) {
- if (sendAll || lastSentJointData[i].rotation != data.rotation) {
- if (sendAll || !cullSmallChanges || largeEnoughRotation) {
- if (data.rotationSet) {
+ bool largeEnoughRotation = true;
+ if (cullSmallChanges) {
+ // The dot product for smaller rotations is a smaller number.
+ // So if the dot() is less than the value, then the rotation is a larger angle of rotation
+ largeEnoughRotation = fabsf(glm::dot(last.rotation, data.rotation)) < minRotationDOT;
+ }
+
+ if (sendAll || !cullSmallChanges || largeEnoughRotation) {
validity |= (1 << validityBit);
#ifdef WANT_DEBUG
rotationSentCount++;
@@ -557,8 +577,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
if (sentJointDataOut) {
localSentJointDataOut[i].rotation = data.rotation;
+ localSentJointDataOut[i].rotationIsDefaultPose = false;
}
-
}
}
}
@@ -588,11 +608,10 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
float maxTranslationDimension = 0.0;
for (int i = 0; i < _jointData.size(); i++) {
const JointData& data = _jointData[i];
- if (sendAll || lastSentJointData[i].translation != data.translation) {
- if (sendAll ||
- !cullSmallChanges ||
- glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation) {
- if (data.translationSet) {
+
+ if (!data.translationIsDefaultPose) {
+ if (sendAll || lastSentJointData[i].translation != data.translation) {
+ if (sendAll || !cullSmallChanges || glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation) {
validity |= (1 << validityBit);
#ifdef WANT_DEBUG
translationSentCount++;
@@ -606,8 +625,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
if (sentJointDataOut) {
localSentJointDataOut[i].translation = data.translation;
+ localSentJointDataOut[i].translationIsDefaultPose = false;
}
-
}
}
}
@@ -655,6 +674,30 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
}
}
+ if (hasJointDefaultPoseFlags) {
+ auto startSection = destinationBuffer;
+ QReadLocker readLock(&_jointDataLock);
+
+ // write numJoints
+ int numJoints = _jointData.size();
+ *destinationBuffer++ = (uint8_t)numJoints;
+
+ // write rotationIsDefaultPose bits
+ destinationBuffer += writeBitVector(destinationBuffer, numJoints, [&](int i) {
+ return _jointData[i].rotationIsDefaultPose;
+ });
+
+ // write translationIsDefaultPose bits
+ destinationBuffer += writeBitVector(destinationBuffer, numJoints, [&](int i) {
+ return _jointData[i].translationIsDefaultPose;
+ });
+
+ if (outboundDataRateOut) {
+ size_t numBytes = destinationBuffer - startSection;
+ outboundDataRateOut->jointDefaultPoseFlagsRate.increment(numBytes);
+ }
+ }
+
int avatarDataSize = destinationBuffer - startPosition;
if (avatarDataSize > (int)byteArraySize) {
@@ -664,6 +707,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
return avatarDataByteArray.left(avatarDataSize);
}
+
// NOTE: This is never used in a "distanceAdjust" mode, so it's ok that it doesn't use a variable minimum rotation/translation
void AvatarData::doneEncoding(bool cullSmallChanges) {
// The server has finished sending this version of the joint-data to other nodes. Update _lastSentJointData.
@@ -674,7 +718,7 @@ void AvatarData::doneEncoding(bool cullSmallChanges) {
if (_lastSentJointData[i].rotation != data.rotation) {
if (!cullSmallChanges ||
fabsf(glm::dot(data.rotation, _lastSentJointData[i].rotation)) <= AVATAR_MIN_ROTATION_DOT) {
- if (data.rotationSet) {
+ if (!data.rotationIsDefaultPose) {
_lastSentJointData[i].rotation = data.rotation;
}
}
@@ -682,7 +726,7 @@ void AvatarData::doneEncoding(bool cullSmallChanges) {
if (_lastSentJointData[i].translation != data.translation) {
if (!cullSmallChanges ||
glm::distance(data.translation, _lastSentJointData[i].translation) > AVATAR_MIN_TRANSLATION) {
- if (data.translationSet) {
+ if (!data.translationIsDefaultPose) {
_lastSentJointData[i].translation = data.translation;
}
}
@@ -730,6 +774,7 @@ const unsigned char* unpackFauxJoint(const unsigned char* sourceBuffer, ThreadSa
// read data in packet starting at byte offset and return number of bytes parsed
int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
+
// lazily allocate memory for HeadData in case we're not an Avatar instance
lazyInitHeadData();
@@ -745,18 +790,19 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
#define HAS_FLAG(B,F) ((B & F) == F)
- bool hasAvatarGlobalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_GLOBAL_POSITION);
- bool hasAvatarBoundingBox = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_BOUNDING_BOX);
- bool hasAvatarOrientation = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_ORIENTATION);
- bool hasAvatarScale = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_SCALE);
- bool hasLookAtPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_LOOK_AT_POSITION);
- bool hasAudioLoudness = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AUDIO_LOUDNESS);
- bool hasSensorToWorldMatrix = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_SENSOR_TO_WORLD_MATRIX);
- bool hasAdditionalFlags = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_ADDITIONAL_FLAGS);
- bool hasParentInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_PARENT_INFO);
- bool hasAvatarLocalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION);
- bool hasFaceTrackerInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO);
- bool hasJointData = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_JOINT_DATA);
+ bool hasAvatarGlobalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_GLOBAL_POSITION);
+ bool hasAvatarBoundingBox = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_BOUNDING_BOX);
+ bool hasAvatarOrientation = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_ORIENTATION);
+ bool hasAvatarScale = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_SCALE);
+ bool hasLookAtPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_LOOK_AT_POSITION);
+ bool hasAudioLoudness = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AUDIO_LOUDNESS);
+ bool hasSensorToWorldMatrix = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_SENSOR_TO_WORLD_MATRIX);
+ bool hasAdditionalFlags = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_ADDITIONAL_FLAGS);
+ bool hasParentInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_PARENT_INFO);
+ bool hasAvatarLocalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION);
+ bool hasFaceTrackerInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO);
+ bool hasJointData = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_JOINT_DATA);
+ bool hasJointDefaultPoseFlags = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS);
quint64 now = usecTimestampNow();
@@ -1055,7 +1101,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
if (validRotations[i]) {
sourceBuffer += unpackOrientationQuatFromSixBytes(sourceBuffer, data.rotation);
_hasNewJointData = true;
- data.rotationSet = true;
+ data.rotationIsDefaultPose = false;
}
}
@@ -1090,7 +1136,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
if (validTranslations[i]) {
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
_hasNewJointData = true;
- data.translationSet = true;
+ data.translationIsDefaultPose = false;
}
}
@@ -1110,6 +1156,32 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
_jointDataUpdateRate.increment();
}
+ if (hasJointDefaultPoseFlags) {
+ auto startSection = sourceBuffer;
+
+ QWriteLocker writeLock(&_jointDataLock);
+
+ PACKET_READ_CHECK(JointDefaultPoseFlagsNumJoints, sizeof(uint8_t));
+ int numJoints = (int)*sourceBuffer++;
+
+ _jointData.resize(numJoints);
+
+ size_t bitVectorSize = calcBitVectorSize(numJoints);
+ PACKET_READ_CHECK(JointDefaultPoseFlagsRotationFlags, bitVectorSize);
+ sourceBuffer += readBitVector(sourceBuffer, numJoints, [&](int i, bool value) {
+ _jointData[i].rotationIsDefaultPose = value;
+ });
+
+ PACKET_READ_CHECK(JointDefaultPoseFlagsTranslationFlags, bitVectorSize);
+ sourceBuffer += readBitVector(sourceBuffer, numJoints, [&](int i, bool value) {
+ _jointData[i].translationIsDefaultPose = value;
+ });
+
+ int numBytesRead = sourceBuffer - startSection;
+ _jointDefaultPoseFlagsRate.increment(numBytesRead);
+ _jointDefaultPoseFlagsUpdateRate.increment();
+ }
+
int numBytesRead = sourceBuffer - startPosition;
_averageBytesReceived.updateAverage(numBytesRead);
@@ -1146,6 +1218,8 @@ float AvatarData::getDataRate(const QString& rateName) const {
return _faceTrackerRate.rate() / BYTES_PER_KILOBIT;
} else if (rateName == "jointData") {
return _jointDataRate.rate() / BYTES_PER_KILOBIT;
+ } else if (rateName == "jointDefaultPoseFlagsRate") {
+ return _jointDefaultPoseFlagsRate.rate() / BYTES_PER_KILOBIT;
} else if (rateName == "globalPositionOutbound") {
return _outboundDataRate.globalPositionRate.rate() / BYTES_PER_KILOBIT;
} else if (rateName == "localPositionOutbound") {
@@ -1170,6 +1244,8 @@ float AvatarData::getDataRate(const QString& rateName) const {
return _outboundDataRate.faceTrackerRate.rate() / BYTES_PER_KILOBIT;
} else if (rateName == "jointDataOutbound") {
return _outboundDataRate.jointDataRate.rate() / BYTES_PER_KILOBIT;
+ } else if (rateName == "jointDefaultPoseFlagsOutbound") {
+ return _outboundDataRate.jointDefaultPoseFlagsRate.rate() / BYTES_PER_KILOBIT;
}
return 0.0f;
}
@@ -1236,9 +1312,9 @@ void AvatarData::setJointData(int index, const glm::quat& rotation, const glm::v
}
JointData& data = _jointData[index];
data.rotation = rotation;
- data.rotationSet = true;
+ data.rotationIsDefaultPose = false;
data.translation = translation;
- data.translationSet = true;
+ data.translationIsDefaultPose = false;
}
void AvatarData::clearJointData(int index) {
@@ -1294,7 +1370,8 @@ void AvatarData::setJointData(const QString& name, const glm::quat& rotation, co
auto& jointData = _jointData[index];
jointData.rotation = rotation;
jointData.translation = translation;
- jointData.rotationSet = jointData.translationSet = true;
+ jointData.rotationIsDefaultPose = false;
+ jointData.translationIsDefaultPose = false;
});
}
@@ -1304,7 +1381,7 @@ void AvatarData::setJointRotation(const QString& name, const glm::quat& rotation
writeLockWithNamedJointIndex(name, [&](int index) {
auto& data = _jointData[index];
data.rotation = rotation;
- data.rotationSet = true;
+ data.rotationIsDefaultPose = false;
});
}
@@ -1314,7 +1391,7 @@ void AvatarData::setJointTranslation(const QString& name, const glm::vec3& trans
writeLockWithNamedJointIndex(name, [&](int index) {
auto& data = _jointData[index];
data.translation = translation;
- data.translationSet = true;
+ data.translationIsDefaultPose = false;
});
}
@@ -1328,7 +1405,7 @@ void AvatarData::setJointRotation(int index, const glm::quat& rotation) {
}
JointData& data = _jointData[index];
data.rotation = rotation;
- data.rotationSet = true;
+ data.rotationIsDefaultPose = false;
}
void AvatarData::setJointTranslation(int index, const glm::vec3& translation) {
@@ -1341,7 +1418,7 @@ void AvatarData::setJointTranslation(int index, const glm::vec3& translation) {
}
JointData& data = _jointData[index];
data.translation = translation;
- data.translationSet = true;
+ data.translationIsDefaultPose = false;
}
void AvatarData::clearJointData(const QString& name) {
@@ -1397,7 +1474,7 @@ void AvatarData::setJointRotations(const QVector& jointRotations) {
for (int i = 0; i < size; ++i) {
auto& data = _jointData[i];
data.rotation = jointRotations[i];
- data.rotationSet = true;
+ data.rotationIsDefaultPose = false;
}
}
@@ -1419,7 +1496,7 @@ void AvatarData::setJointTranslations(const QVector& jointTranslation
for (int i = 0; i < size; ++i) {
auto& data = _jointData[i];
data.translation = jointTranslations[i];
- data.translationSet = true;
+ data.translationIsDefaultPose = false;
}
}
@@ -1996,9 +2073,9 @@ JointData jointDataFromJsonValue(const QJsonValue& json) {
if (json.isArray()) {
QJsonArray array = json.toArray();
result.rotation = quatFromJsonValue(array[0]);
- result.rotationSet = true;
+ result.rotationIsDefaultPose = false;
result.translation = vec3FromJsonValue(array[1]);
- result.translationSet = true;
+ result.translationIsDefaultPose = false;
}
return result;
}
diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h
index 00cc760658..92c505f5c3 100644
--- a/libraries/avatars/src/AvatarData.h
+++ b/libraries/avatars/src/AvatarData.h
@@ -113,18 +113,19 @@ namespace AvatarDataPacket {
// Packet State Flags - we store the details about the existence of other records in this bitset:
// AvatarGlobalPosition, Avatar face tracker, eye tracking, and existence of
using HasFlags = uint16_t;
- const HasFlags PACKET_HAS_AVATAR_GLOBAL_POSITION = 1U << 0;
- const HasFlags PACKET_HAS_AVATAR_BOUNDING_BOX = 1U << 1;
- const HasFlags PACKET_HAS_AVATAR_ORIENTATION = 1U << 2;
- const HasFlags PACKET_HAS_AVATAR_SCALE = 1U << 3;
- const HasFlags PACKET_HAS_LOOK_AT_POSITION = 1U << 4;
- const HasFlags PACKET_HAS_AUDIO_LOUDNESS = 1U << 5;
- const HasFlags PACKET_HAS_SENSOR_TO_WORLD_MATRIX = 1U << 6;
- const HasFlags PACKET_HAS_ADDITIONAL_FLAGS = 1U << 7;
- const HasFlags PACKET_HAS_PARENT_INFO = 1U << 8;
- const HasFlags PACKET_HAS_AVATAR_LOCAL_POSITION = 1U << 9;
- const HasFlags PACKET_HAS_FACE_TRACKER_INFO = 1U << 10;
- const HasFlags PACKET_HAS_JOINT_DATA = 1U << 11;
+ const HasFlags PACKET_HAS_AVATAR_GLOBAL_POSITION = 1U << 0;
+ const HasFlags PACKET_HAS_AVATAR_BOUNDING_BOX = 1U << 1;
+ const HasFlags PACKET_HAS_AVATAR_ORIENTATION = 1U << 2;
+ const HasFlags PACKET_HAS_AVATAR_SCALE = 1U << 3;
+ const HasFlags PACKET_HAS_LOOK_AT_POSITION = 1U << 4;
+ const HasFlags PACKET_HAS_AUDIO_LOUDNESS = 1U << 5;
+ const HasFlags PACKET_HAS_SENSOR_TO_WORLD_MATRIX = 1U << 6;
+ const HasFlags PACKET_HAS_ADDITIONAL_FLAGS = 1U << 7;
+ const HasFlags PACKET_HAS_PARENT_INFO = 1U << 8;
+ const HasFlags PACKET_HAS_AVATAR_LOCAL_POSITION = 1U << 9;
+ const HasFlags PACKET_HAS_FACE_TRACKER_INFO = 1U << 10;
+ const HasFlags PACKET_HAS_JOINT_DATA = 1U << 11;
+ const HasFlags PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS = 1U << 12;
const size_t AVATAR_HAS_FLAGS_SIZE = 2;
using SixByteQuat = uint8_t[6];
@@ -256,6 +257,15 @@ namespace AvatarDataPacket {
};
*/
size_t maxJointDataSize(size_t numJoints);
+
+ /*
+ struct JointDefaultPoseFlags {
+ uint8_t numJoints;
+ uint8_t rotationIsDefaultPoseBits[ceil(numJoints / 8)];
+ uint8_t translationIsDefaultPoseBits[ceil(numJoints / 8)];
+ };
+ */
+ size_t maxJointDefaultPoseFlagsSize(size_t numJoints);
}
const float MAX_AUDIO_LOUDNESS = 1000.0f; // close enough for mouth animation
@@ -321,6 +331,7 @@ public:
RateCounter<> parentInfoRate;
RateCounter<> faceTrackerRate;
RateCounter<> jointDataRate;
+ RateCounter<> jointDefaultPoseFlagsRate;
};
class AvatarPriority {
@@ -810,6 +821,7 @@ protected:
RateCounter<> _parentInfoRate;
RateCounter<> _faceTrackerRate;
RateCounter<> _jointDataRate;
+ RateCounter<> _jointDefaultPoseFlagsRate;
// Some rate data for incoming data updates
RateCounter<> _parseBufferUpdateRate;
@@ -825,6 +837,7 @@ protected:
RateCounter<> _parentInfoUpdateRate;
RateCounter<> _faceTrackerUpdateRate;
RateCounter<> _jointDataUpdateRate;
+ RateCounter<> _jointDefaultPoseFlagsUpdateRate;
// Some rate data for outgoing data
AvatarDataRate _outboundDataRate;
diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index fc1688974c..2e39e2e498 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -1050,7 +1050,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
return;
}
- QVector jointsData;
+ QVector jointsData;
const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size();
diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp
index 8996665262..a615beefa9 100644
--- a/libraries/entities/src/ModelEntityItem.cpp
+++ b/libraries/entities/src/ModelEntityItem.cpp
@@ -452,7 +452,7 @@ void ModelEntityItem::resizeJointArrays(int newSize) {
});
}
-void ModelEntityItem::setAnimationJointsData(const QVector& jointsData) {
+void ModelEntityItem::setAnimationJointsData(const QVector& jointsData) {
resizeJointArrays(jointsData.size());
_jointDataLock.withWriteLock([&] {
for (auto index = 0; index < jointsData.size(); ++index) {
diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h
index 6169039f52..c2109ba51f 100644
--- a/libraries/entities/src/ModelEntityItem.h
+++ b/libraries/entities/src/ModelEntityItem.h
@@ -124,7 +124,7 @@ public:
virtual void setJointTranslations(const QVector& translations);
virtual void setJointTranslationsSet(const QVector& translationsSet);
- virtual void setAnimationJointsData(const QVector& jointsData);
+ virtual void setAnimationJointsData(const QVector& jointsData);
QVector getJointRotations() const;
QVector getJointRotationsSet() const;
@@ -150,7 +150,7 @@ protected:
bool _jointTranslationsExplicitlySet{ false }; // were the joints set as a property or just side effect of animations
struct ModelJointData {
- JointData joint;
+ EntityJointData joint;
bool rotationDirty { false };
bool translationDirty { false };
};
diff --git a/libraries/midi/src/Midi.cpp b/libraries/midi/src/Midi.cpp
index 69c35c4a20..1f190111f2 100644
--- a/libraries/midi/src/Midi.cpp
+++ b/libraries/midi/src/Midi.cpp
@@ -163,7 +163,7 @@ void Midi::sendRawMessage(int device, int raw) {
void Midi::sendMessage(int device, int channel, int type, int note, int velocity) {
int message = (channel - 1) | (type << MIDI_SHIFT_STATUS);
if (broadcastEnabled) {
- for (int i = 0; i < midihout.size(); i++) {
+ for (int i = 1; i < midihout.size(); i++) { // Skip 0 (Microsoft GS Wavetable Synth)
if (midihout[i] != NULL) {
midiOutShortMsg(midihout[i], message | (note << MIDI_SHIFT_NOTE) | (velocity << MIDI_SHIFT_VELOCITY));
}
@@ -174,9 +174,9 @@ void Midi::sendMessage(int device, int channel, int type, int note, int velocity
}
void Midi::sendNote(int status, int note, int velocity) {
- for (int i = 0; i < midihout.size(); i++) {
+ for (int i = 1; i < midihout.size(); i++) { // Skip 0 (Microsoft GS Wavetable Synth)
if (midihout[i] != NULL) {
- midiOutShortMsg(midihout[i], status + (note << MIDI_SHIFT_NOTE) + (velocity << MIDI_SHIFT_VELOCITY));
+ midiOutShortMsg(midihout[i], status | (note << MIDI_SHIFT_NOTE) | (velocity << MIDI_SHIFT_VELOCITY));
}
}
}
@@ -283,9 +283,6 @@ void Midi::midiHardwareChange() {
Midi::Midi() {
instance = this;
-#if defined Q_OS_WIN32
- midiOutExclude.push_back("Microsoft GS Wavetable Synth"); // we don't want to hear this thing (Lags)
-#endif
MidiSetup();
}
diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp
index 711aeb2cc2..c48c6bfc0b 100644
--- a/libraries/networking/src/udt/PacketHeaders.cpp
+++ b/libraries/networking/src/udt/PacketHeaders.cpp
@@ -38,7 +38,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::AvatarData:
case PacketType::BulkAvatarData:
case PacketType::KillAvatar:
- return static_cast(AvatarMixerPacketVersion::UpdatedMannequinDefaultAvatar);
+ return static_cast(AvatarMixerPacketVersion::AvatarJointDefaultPoseFlags);
case PacketType::MessagesData:
return static_cast(MessageDataVersion::TextOrBinaryData);
case PacketType::ICEServerHeartbeat:
diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h
index 458666571c..0f69691bd5 100644
--- a/libraries/networking/src/udt/PacketHeaders.h
+++ b/libraries/networking/src/udt/PacketHeaders.h
@@ -247,7 +247,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
AvatarIdentitySequenceFront,
IsReplicatedInAvatarIdentity,
AvatarIdentityLookAtSnapping,
- UpdatedMannequinDefaultAvatar
+ UpdatedMannequinDefaultAvatar,
+ AvatarJointDefaultPoseFlags
};
enum class DomainConnectRequestVersion : PacketVersion {
diff --git a/libraries/pointers/src/Pointer.cpp b/libraries/pointers/src/Pointer.cpp
index 287d5a3c97..5307e17355 100644
--- a/libraries/pointers/src/Pointer.cpp
+++ b/libraries/pointers/src/Pointer.cpp
@@ -64,12 +64,6 @@ bool Pointer::isMouse() const {
return DependencyManager::get()->isMouse(_pickUID);
}
-void Pointer::setDoesHover(bool doesHover) {
- withWriteLock([&] {
- _hover = doesHover;
- });
-}
-
void Pointer::update(unsigned int pointerID) {
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
withReadLock([&] {
@@ -101,8 +95,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
}
// Hover events
- bool doHover = _hover && shouldHover(pickResult);
-
+ bool doHover = shouldHover(pickResult);
Pointer::PickedObject hoveredObject = getHoveredObject(pickResult);
PointerEvent hoveredEvent = buildPointerEvent(hoveredObject, pickResult);
hoveredEvent.setType(PointerEvent::Move);
@@ -111,7 +104,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
hoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave);
// if shouldHover && !_prevDoHover, only send hoverBegin
- if (_enabled && doHover && !_prevDoHover) {
+ if (_enabled && _hover && doHover && !_prevDoHover) {
if (hoveredObject.type == ENTITY) {
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
} else if (hoveredObject.type == OVERLAY) {
@@ -119,7 +112,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
} else if (hoveredObject.type == HUD) {
emit pointerManager->hoverBeginHUD(hoveredEvent);
}
- } else if (_enabled && doHover) {
+ } else if (_enabled && _hover && doHover) {
if (hoveredObject.type == OVERLAY) {
if (_prevHoveredObject.type == OVERLAY) {
if (hoveredObject.objectID == _prevHoveredObject.objectID) {
@@ -236,7 +229,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
}
// if we disable the pointer or disable hovering, send hoverEnd events after triggerEnd
- if ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover)) {
+ if (_hover && ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover))) {
if (_prevHoveredObject.type == ENTITY) {
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
} else if (_prevHoveredObject.type == OVERLAY) {
diff --git a/libraries/pointers/src/Pointer.h b/libraries/pointers/src/Pointer.h
index 9fd434fb15..3197c80cad 100644
--- a/libraries/pointers/src/Pointer.h
+++ b/libraries/pointers/src/Pointer.h
@@ -62,8 +62,6 @@ public:
virtual void setLength(float length) {}
virtual void setLockEndUUID(const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) {}
- virtual void setDoesHover(bool hover);
-
void update(unsigned int pointerID);
virtual void updateVisuals(const PickResultPointer& pickResult) = 0;
void generatePointerEvents(unsigned int pointerID, const PickResultPointer& pickResult);
@@ -103,6 +101,7 @@ private:
std::unordered_map _triggeredObjects;
PointerEvent::Button chooseButton(const std::string& button);
+
};
#endif // hifi_Pick_h
diff --git a/libraries/pointers/src/PointerManager.cpp b/libraries/pointers/src/PointerManager.cpp
index 13b38457b6..be890da392 100644
--- a/libraries/pointers/src/PointerManager.cpp
+++ b/libraries/pointers/src/PointerManager.cpp
@@ -122,13 +122,6 @@ void PointerManager::setLockEndUUID(unsigned int uid, const QUuid& objectID, boo
}
}
-void PointerManager::setDoesHover(unsigned int uid, bool hover) const {
- auto pointer = find(uid);
- if (pointer) {
- pointer->setDoesHover(hover);
- }
-}
-
bool PointerManager::isLeftHand(unsigned int uid) {
auto pointer = find(uid);
if (pointer) {
diff --git a/libraries/pointers/src/PointerManager.h b/libraries/pointers/src/PointerManager.h
index 2c9a37e129..b98558622f 100644
--- a/libraries/pointers/src/PointerManager.h
+++ b/libraries/pointers/src/PointerManager.h
@@ -37,7 +37,6 @@ public:
void setLength(unsigned int uid, float length) const;
void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const;
- void setDoesHover(unsigned int uid, bool hover) const;
void update();
diff --git a/libraries/shared/src/BitVectorHelpers.h b/libraries/shared/src/BitVectorHelpers.h
new file mode 100644
index 0000000000..71826036eb
--- /dev/null
+++ b/libraries/shared/src/BitVectorHelpers.h
@@ -0,0 +1,58 @@
+//
+// BitVectorHelpers.h
+// libraries/shared/src
+//
+// Created by Anthony Thibault on 1/19/18.
+// Copyright 2018 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_BitVectorHelpers_h
+#define hifi_BitVectorHelpers_h
+
+size_t calcBitVectorSize(int numBits) {
+ return ((numBits - 1) >> 3) + 1;
+}
+
+// func should be of type bool func(int index)
+template
+size_t writeBitVector(uint8_t* destinationBuffer, int numBits, const F& func) {
+ size_t totalBytes = ((numBits - 1) >> 3) + 1;
+ uint8_t* cursor = destinationBuffer;
+ uint8_t byte = 0;
+ uint8_t bit = 0;
+
+ for (int i = 0; i < numBits; i++) {
+ if (func(i)) {
+ byte |= (1 << bit);
+ }
+ if (++bit == BITS_IN_BYTE) {
+ *cursor++ = byte;
+ byte = 0;
+ bit = 0;
+ }
+ }
+ return totalBytes;
+}
+
+// func should be of type 'void func(int index, bool value)'
+template
+size_t readBitVector(const uint8_t* sourceBuffer, int numBits, const F& func) {
+ size_t totalBytes = ((numBits - 1) >> 3) + 1;
+ const uint8_t* cursor = sourceBuffer;
+ uint8_t bit = 0;
+
+ for (int i = 0; i < numBits; i++) {
+ bool value = (bool)(*cursor & (1 << bit));
+ func(i, value);
+ if (++bit == BITS_IN_BYTE) {
+ cursor++;
+ bit = 0;
+ }
+ }
+ return totalBytes;
+}
+
+#endif
diff --git a/libraries/shared/src/JointData.h b/libraries/shared/src/JointData.h
index a05b5c649a..f4c8b89e7a 100644
--- a/libraries/shared/src/JointData.h
+++ b/libraries/shared/src/JointData.h
@@ -5,14 +5,27 @@
#include
#include
-// Used by the avatar mixer to describe a single joint
-// These are relative to their parent and translations are in meters
-class JointData {
+class EntityJointData {
public:
glm::quat rotation;
+ glm::vec3 translation;
bool rotationSet = false;
- glm::vec3 translation; // meters
bool translationSet = false;
};
+// Used by the avatar mixer to describe a single joint
+// Translations relative to their parent and are in meters.
+// Rotations are absolute (i.e. not relative to parent) and are in rig space.
+class JointData {
+public:
+ glm::quat rotation;
+ glm::vec3 translation;
+
+ // This indicates that the rotation or translation is the same as the defaultPose for the avatar.
+ // if true, it also means that the rotation or translation value in this structure is not valid and
+ // should be replaced by the avatar's actual default pose value.
+ bool rotationIsDefaultPose = true;
+ bool translationIsDefaultPose = true;
+};
+
#endif
diff --git a/scripts/developer/utilities/tools/currentAPI.js b/scripts/developer/utilities/tools/currentAPI.js
index 175b84b8d9..6cab6a5710 100644
--- a/scripts/developer/utilities/tools/currentAPI.js
+++ b/scripts/developer/utilities/tools/currentAPI.js
@@ -28,8 +28,8 @@
var window = new OverlayWindow({
title: 'API Debugger',
source: qml,
- width: 1200,
- height: 500
+ width: 500,
+ height: 700
});
window.closed.connect(function () {
diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js
index f93d6714f1..ad864622ed 100644
--- a/scripts/system/commerce/wallet.js
+++ b/scripts/system/commerce/wallet.js
@@ -593,10 +593,16 @@
getConnectionData(false);
break;
case 'enable_ChooseRecipientNearbyMode':
- Script.update.connect(updateOverlays);
+ if (!isUpdateOverlaysWired) {
+ Script.update.connect(updateOverlays);
+ isUpdateOverlaysWired = true;
+ }
break;
case 'disable_ChooseRecipientNearbyMode':
- Script.update.disconnect(updateOverlays);
+ if (isUpdateOverlaysWired) {
+ Script.update.disconnect(updateOverlays);
+ isUpdateOverlaysWired = false;
+ }
removeOverlays();
break;
default:
@@ -681,14 +687,18 @@
}
}
var isWired = false;
+ var isUpdateOverlaysWired = false;
function off() {
if (isWired) { // It is not ok to disconnect these twice, hence guard.
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
- Script.update.disconnect(updateOverlays);
Controller.mousePressEvent.disconnect(handleMouseEvent);
Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent);
isWired = false;
}
+ if (isUpdateOverlaysWired) {
+ Script.update.disconnect(updateOverlays);
+ isUpdateOverlaysWired = false;
+ }
triggerMapping.disable(); // It's ok if we disable twice.
triggerPressMapping.disable(); // see above
removeOverlays();
diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index a8658933e7..16f1d086b7 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -44,12 +44,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
this.highVarianceCount = 0;
this.veryhighVarianceCount = 0;
this.tabletID = null;
- this.TABLET_UI_UUIDS = [];
this.blacklist = [];
- this.leftPointerDoesHover = true;
- this.leftPointerDoesHoverChanged = false;
- this.rightPointerDoesHover = true;
- this.rightPointerDoesHoverChanged = false;
this.pointerManager = new PointerManager();
// a module can occupy one or more "activity" slots while it's running. If all the required slots for a module are
@@ -127,10 +122,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
return getControllerWorldLocation(Controller.Standard.RightHand, true);
};
- this.isTabletID = function (uuid) {
- return _this.TABLET_UI_UUIDS.indexOf(uuid) !== -1;
- };
-
this.updateTimings = function () {
_this.intervalCount++;
var thisInterval = Date.now();
@@ -157,35 +148,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
this.setIgnorePointerItems = function() {
if (HMD.tabletID !== this.tabletID) {
this.tabletID = HMD.tabletID;
- this.TABLET_UI_UUIDS = [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID];
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist);
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist);
}
};
- this.updateDoesHover = function(handLaser, doesHover) {
- if (handLaser.doesHover !== undefined) {
- if (handLaser.hand === LEFT_HAND && _this.leftPointerDoesHover !== doesHover) {
- _this.leftPointerDoesHover = doesHover;
- _this.leftPointerDoesHoverChanged = true;
- } else if (handLaser.hand === RIGHT_HAND && _this.rightPointerDoesHover !== doesHover) {
- _this.rightPointerDoesHover = doesHover;
- _this.rightPointerDoesHoverChanged = true;
- }
- }
- }
-
- this.updateHovering = function () {
- if (_this.leftPointerDoesHoverChanged) {
- Pointers.setDoesHover(_this.leftPointer, _this.leftPointerDoesHover);
- _this.leftPointerDoesHoverChanged = false;
- }
- if (_this.rightPointerDoesHoverChanged) {
- Pointers.setDoesHover(_this.rightPointer, _this.rightPointerDoesHover);
- _this.rightPointerDoesHoverChanged = false;
- }
- };
-
this.update = function () {
try {
_this.updateInternal();
@@ -357,8 +324,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
_this.runningPluginNames[orderedPluginName] = true;
_this.markSlots(candidatePlugin, orderedPluginName);
_this.pointerManager.makePointerVisible(candidatePlugin.parameters.handLaser);
- _this.updateDoesHover(candidatePlugin.parameters.handLaser,
- candidatePlugin.parameters.handLaser.doesHover);
if (DEBUG) {
print("controllerDispatcher running " + orderedPluginName);
}
@@ -389,15 +354,12 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
Script.beginProfileRange("dispatch.run." + runningPluginName);
}
var runningness = plugin.run(controllerData, deltaTime);
- if (runningness.active) {
- _this.updateDoesHover(plugin.parameters.handLaser, plugin.parameters.handLaser.doesHover);
- } else {
+ if (!runningness.active) {
// plugin is finished running, for now. remove it from the list
// of running plugins and mark its activity-slots as "not in use"
delete _this.runningPluginNames[runningPluginName];
_this.markSlots(plugin, false);
_this.pointerManager.makePointerInvisible(plugin.parameters.handLaser);
- _this.updateDoesHover(plugin.parameters.handLaser, true);
if (DEBUG) {
print("controllerDispatcher stopping " + runningPluginName);
}
@@ -410,8 +372,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
}
}
_this.pointerManager.updatePointersRenderState(controllerData.triggerClicks, controllerData.triggerValues);
- _this.updateHovering();
-
if (PROFILE) {
Script.endProfileRange("dispatch.run");
}
diff --git a/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js b/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js
index cc8378af84..3d9d7979d5 100644
--- a/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js
+++ b/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js
@@ -87,89 +87,41 @@ Script.include("/~/system/libraries/controllers.js");
return MyAvatar.getDominantHand() === "right" ? 1 : 0;
};
- this.letOtherHandRunFirst = function (controllerData, pointingAt) {
- // If both hands are ready to run, let the other hand run first if it is the dominant hand so that it gets the
- // highlight.
- var isOtherTriggerPressed = controllerData.triggerValues[this.otherHand] > TRIGGER_OFF_VALUE;
- var isLetOtherHandRunFirst = !this.getOtherModule().running
- && this.getDominantHand() === this.otherHand
- && (this.parameters.handLaser.allwaysOn || isOtherTriggerPressed);
- if (isLetOtherHandRunFirst) {
- var otherHandPointingAt = controllerData.rayPicks[this.otherHand].objectID;
- if (this.isTabletID(otherHandPointingAt)) {
- otherHandPointingAt = HMD.tabletID;
- }
- isLetOtherHandRunFirst = pointingAt === otherHandPointingAt;
- }
- return isLetOtherHandRunFirst;
- };
-
- this.hoverItem = null;
-
- this.isTabletID = function (uuid) {
- return [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID].indexOf(uuid) !== -1;
- };
+ this.dominantHandOverride = false;
this.isReady = function(controllerData) {
- if (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData)) {
+ var otherModuleRunning = this.getOtherModule().running;
+ otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand.
+ var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE
+ && controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE;
+ if ((!otherModuleRunning || isTriggerPressed)
+ && (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData))) {
this.updateAllwaysOn();
-
- var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE;
+ if (isTriggerPressed) {
+ this.dominantHandOverride = true; // Override dominant hand.
+ this.getOtherModule().dominantHandOverride = false;
+ }
if (this.parameters.handLaser.allwaysOn || isTriggerPressed) {
- var pointingAt = controllerData.rayPicks[this.hand].objectID;
- if (this.isTabletID(pointingAt)) {
- pointingAt = HMD.tabletID;
- }
-
- if (!this.letOtherHandRunFirst(controllerData, pointingAt)) {
-
- if (pointingAt !== this.getOtherModule().hoverItem) {
- this.parameters.handLaser.doesHover = true;
- this.hoverItem = pointingAt;
- } else {
- this.parameters.handLaser.doesHover = false;
- this.hoverItem = null;
- }
-
- return makeRunningValues(true, [], []);
- }
+ return makeRunningValues(true, [], []);
}
}
-
- this.parameters.handLaser.doesHover = false;
- this.hoverItem = null;
-
return makeRunningValues(false, [], []);
};
this.run = function(controllerData, deltaTime) {
+ var otherModuleRunning = this.getOtherModule().running;
+ otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand.
+ otherModuleRunning = otherModuleRunning || this.getOtherModule().dominantHandOverride; // Override dominant hand.
var grabModuleNeedsToRun = this.grabModuleWantsNearbyOverlay(controllerData);
- var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE;
- if (!grabModuleNeedsToRun && (isTriggerPressed || this.parameters.handLaser.allwaysOn
+ if (!otherModuleRunning && !grabModuleNeedsToRun && (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE
+ || this.parameters.handLaser.allwaysOn
&& (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData)))) {
this.running = true;
-
- var pointingAt = controllerData.rayPicks[this.hand].objectID;
- if (this.isTabletID(pointingAt)) {
- pointingAt = HMD.tabletID;
- }
-
- if (pointingAt !== this.getOtherModule().hoverItem || isTriggerPressed) {
- this.parameters.handLaser.doesHover = true;
- this.hoverItem = pointingAt;
- } else {
- this.parameters.handLaser.doesHover = false;
- this.hoverItem = null;
- }
-
return makeRunningValues(true, [], []);
}
this.deleteContextOverlay();
this.running = false;
-
- this.parameters.handLaser.doesHover = false;
- this.hoverItem = null;
-
+ this.dominantHandOverride = false;
return makeRunningValues(false, [], []);
};
}