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

This commit is contained in:
Olivier Prat 2018-01-23 09:51:17 +01:00
commit 8985514a31
36 changed files with 1147 additions and 852 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1398BB;}
</style>
<path class="st0" d="M256.8,42C138.5,42,42.2,138.3,42.2,256.6s96.3,214.6,214.6,214.6c118.3,0,214.6-96.3,214.6-214.6
S375.1,42,256.8,42z M256.8,444.4C153.2,444.4,69,360.1,69,256.6C69,153,153.2,68.7,256.8,68.7c103.6,0,187.8,84.3,187.8,187.8
C444.6,360.1,360.4,444.4,256.8,444.4z"/>
<circle class="st0" cx="260.6" cy="189.4" r="60.6"/>
<path class="st0" d="M306.4,282.6h-87.6c-36.5,0-66.4,30.2-66.4,66.7v33.9c29.3,22.6,65.4,36.1,105,36.1c44.4,0,84.7-17,115.2-44.7
v-25.3C372.7,312.7,342.9,282.6,306.4,282.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1398BB;}
</style>
<path class="st0" d="M144.3,155c-8.7-8.8-16.7-17.1-25.2-25.7c-22.4,25.4-36.6,53.9-43.6,86.2c-26.9,125.7,81.2,241.5,208.6,223.4
C385.9,424.4,458,329.2,443.5,228.2c-4.4-30.6-15.4-58.9-34.1-83.9c-1.6-2.2-3.3-4.3-4.7-6.6c-4.4-7.4-3.1-14.9,3-19.5
c6-4.5,14.2-3.6,19.2,3.5c8.2,11.7,16.6,23.4,22.9,36.1c41.9,84.9,25.7,181.7-41,248.7c-67,67.4-175.1,81.3-257.1,33.3
c-35.3-20.7-63.1-48.6-82.7-84.5c-41-75-31.5-172.5,23.4-237.9c2.2-2.7,4.4-5.4,7.1-8.7c-8.1-8.5-16.1-16.9-24-25.3
c-7.2-7.7-7.9-16.1-1.9-22.1c5.9-5.9,15-5.1,22.1,2.4c56.8,59.5,113.6,119,170.4,178.6c7.2,7.6,7.8,15.4,1.9,21.4
c-6.1,6.2-14.7,5.5-22-2c-10.2-10.4-20.2-21-30.3-31.5c-17.4,24.7-3.3,62,27.2,72.5c23,7.9,48.8-2,60.7-23.1
c1.2-2.1,2.3-4.3,3.7-6.3c4.5-6.6,11.7-8.6,18.3-5c6.6,3.5,8.9,10.5,5.9,18.1c-12.4,31.6-47.9,52.2-82.3,47.7
c-36.1-4.8-64.3-32.6-68.4-67.7c-2.4-20.7,2.4-39.7,14.9-57.5c-10.4-10.9-20.8-21.6-31.7-33c-9.7,10.8-16.2,22.7-20.9,35.7
c-31.3,86.4,38.9,175.1,130.1,164.3c74-8.7,122.3-80.9,103.3-154.3c-3.4-13.1-1-20.2,7.8-22.7c9.5-2.8,15.2,1.8,19.2,15.4
c20.1,67.4-16,144.8-79.8,175.3c-67.5,32.2-147.5,9.7-188.8-49c-37.8-53.8-36.1-127.7,4.7-179.1C141.2,159.4,142.5,157.4,144.3,155z
"/>
<path class="st0" d="M236.2,262.2c-4.2-13.6,3.4-28.2,16.8-32.4c13.5-4.2,28.1,3.3,32.5,16.8c4.5,13.9-3.1,28.4-17.2,32.7
C254.6,283.5,240.4,275.9,236.2,262.2z"/>
<path class="st0" d="M319.6,101.9c-3.7-11,1.8-22.3,12.7-26c11.3-3.9,22.8,1.9,26.4,13.2c3.5,11-2.3,22.2-13.2,25.8
C334.5,118.5,323.3,112.9,319.6,101.9z"/>
<path class="st0" d="M214.9,66.2c3.2,10.2-2.2,20.5-12.5,23.6c-9.8,3-20-2.3-23.3-12c-3.3-9.9,2.2-20.8,12-24
C201.1,50.5,211.8,56.2,214.9,66.2z"/>
<path class="st0" d="M230.8,164.6c-3.7-11,1.8-22.3,12.7-26c11.3-3.9,22.8,1.9,26.4,13.2c3.5,11-2.3,22.2-13.2,25.8
C245.7,181.2,234.5,175.6,230.8,164.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 143.1 414.2" style="enable-background:new 0 0 143.1 414.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#B9B9B9;}
.st1{fill:#EE982D;}
.st2{fill:#FF630A;}
</style>
<path class="st0" d="M78.8,7.1c3.9,4.3,7.7,8.7,11.8,12.9c3.7,3.8,5.1,7.9,4.4,12.9c-1,7.1-1.8,14-7.1,20.1
c-4.2,4.7-1.3,12,4.6,14.5c5.6,2.3,11.1,4.6,16.7,7c8.1,3.5,12.3,9.6,13.2,17.4c0.8,6.3,0.8,12.6,1.2,18.9c0.1,2.2,0.3,4.3,0.7,6.4
c0.3,2.2,1.9,4.4-1.3,6.1c-0.6,0.3-0.6,2.2-0.3,3.3c5.4,25.1-0.3,49.7-4.9,74.3c-1.2,6.3-3.1,12-5.5,17.9
c-2.3,5.5-0.9,12.4-0.4,18.7c0.6,7.8,2,15.5,3.2,23.7c-2.5,0.5-4.5,1.4-6.3,1.2c-6.1-0.5-6.8,2.6-6.4,6.7c0.7,6.6,1.1,13.3,2.4,19.8
c0.6,3.3,3.5,6.1,4.5,9.4c5,15.6,1.1,30.9-1.3,46.5c-1.7,10.6-0.6,21.5-1.5,32.2c-0.5,6.5-1.5,13.3-4,19.4c-2.2,5.4-9,3.9-14.1,4
c-2.8,0.1-5.6-0.3-8.2-1.1c-1.2-0.3-2.6-2.2-2.5-3.3c0.1-1.9,0.7-4.1,1.9-5.7c11.5-16,9.1-33.7,8.2-51.2c-0.5-9.8-1.6-19.6-2.9-29.3
c-1.2-8.8-3.1-17.5-5-26.2c-1.2-5.5-3.4-10.9-4.4-16.5c-0.8-3.9-2.4-5.3-7.4-3.8c-0.5,8.5-3.1,17.7-0.9,25.9
c2.7,10.1,4.5,20,3.3,30.2c-1,8.8-2.9,17.5-3.9,26.2c-0.7,6.6-1.1,13,1.7,19.8c2.4,5.9,0.6,13.1,0.3,19.7c0,0.9-2.1,2.3-3.4,2.5
c-4.8,0.7-9.8,0.8-14.5,1.6c-5.1,0.9-9.9,3-15,3.6c-5.7,0.6-11.5,0.1-17.3,0.1c-2.4-4,0-6.2,3.2-8.4c6.9-4.5,13.7-9,20.5-13.6
c6.4-4.4,7.5-10.2,6.6-17.1c-2.1-17.2-6.4-34.1-5.2-51.6c0.8-11.3-0.7-22.5-4.2-33.5c-1.7-5.2-3.4-9.1-10.4-7.8
c-0.4-0.8-0.9-1.2-0.9-1.7c-0.4-17.6-1.7-35.3-0.9-52.9c0.6-12.6,3.9-25,6-37.5c0.1-0.6,0.9-1.5,0.7-1.8c-5-8,2.9-15.7,0.6-23.9
c-2.2-8-3.5-16.4-3.7-24.6c-0.2-6.9,2.3-13.8,2.8-20.7c0.8-12.2,8.8-18.8,20.6-23c7.3-2.6,9.1-5.2,8.2-11.3c-0.1-1.1-0.6-2.7-1.4-3
c-10-4.1-8.9-12.3-9.9-19.9c-0.9-7.2-2.7-14.2-3.6-21.4c-0.3-2.9,0.2-5.9,3.6-8.1c6.4-4,13.1-5.3,20.7-3.4
C73.7,8.3,76.3,7.4,78.8,7.1z M107.1,130.2c-1,0-2,0.1-3.1,0.1c0,3.1-0.2,6.1,0,9.2c0.7,9.3,5.9,19-2.4,27.7
c-0.2,0.2-0.2,0.6-0.1,0.9c1.9,7.2,3.8,14.5,5.6,21.7c0.7-0.1,1.4-0.1,2.1-0.2C108.5,169.9,107.8,150,107.1,130.2z"/>
<circle class="st1" cx="70.9" cy="109.9" r="26"/>
<circle class="st2" cx="70.9" cy="109.9" r="19"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 143.1 414.2" style="enable-background:new 0 0 143.1 414.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#B9B9B9;}
.st1{fill:#009175;}
.st2{fill:#1FC6A6;}
.st3{fill:#FFFFFF;}
</style>
<path class="st0" d="M78.8,7.1c3.9,4.3,7.7,8.7,11.8,12.9c3.7,3.8,5.1,7.9,4.4,12.9c-1,7.1-1.8,14-7.1,20.1
c-4.2,4.7-1.3,12,4.6,14.5c5.6,2.3,11.1,4.6,16.7,7c8.1,3.5,12.3,9.6,13.2,17.4c0.8,6.3,0.8,12.6,1.2,18.9c0.1,2.2,0.3,4.3,0.7,6.4
c0.3,2.2,1.9,4.4-1.3,6.1c-0.6,0.3-0.6,2.2-0.3,3.3c5.4,25.1-0.3,49.7-4.9,74.3c-1.2,6.3-3.1,12-5.5,17.9
c-2.3,5.5-0.9,12.4-0.4,18.7c0.6,7.8,2,15.5,3.2,23.7c-2.5,0.5-4.5,1.4-6.3,1.2c-6.1-0.5-6.8,2.6-6.4,6.7c0.7,6.6,1.1,13.3,2.4,19.8
c0.6,3.3,3.5,6.1,4.5,9.4c5,15.6,1.1,30.9-1.3,46.5c-1.7,10.6-0.6,21.5-1.5,32.2c-0.5,6.5-1.5,13.3-4,19.4c-2.2,5.4-9,3.9-14.1,4
c-2.8,0.1-5.6-0.3-8.2-1.1c-1.2-0.3-2.6-2.2-2.5-3.3c0.1-1.9,0.7-4.1,1.9-5.7c11.5-16,9.1-33.7,8.2-51.2c-0.5-9.8-1.6-19.6-2.9-29.3
c-1.2-8.8-3.1-17.5-5-26.2c-1.2-5.5-3.4-10.9-4.4-16.5c-0.8-3.9-2.4-5.3-7.4-3.8c-0.5,8.5-3.1,17.7-0.9,25.9
c2.7,10.1,4.5,20,3.3,30.2c-1,8.8-2.9,17.5-3.9,26.2c-0.7,6.6-1.1,13,1.7,19.8c2.4,5.9,0.6,13.1,0.3,19.7c0,0.9-2.1,2.3-3.4,2.5
c-4.8,0.7-9.8,0.8-14.5,1.6c-5.1,0.9-9.9,3-15,3.6c-5.7,0.6-11.5,0.1-17.3,0.1c-2.4-4,0-6.2,3.2-8.4c6.9-4.5,13.7-9,20.5-13.6
c6.4-4.4,7.5-10.2,6.6-17.1c-2.1-17.2-6.4-34.1-5.2-51.6c0.8-11.3-0.7-22.5-4.2-33.5c-1.7-5.2-3.4-9.1-10.4-7.8
c-0.4-0.8-0.9-1.2-0.9-1.7c-0.4-17.6-1.7-35.3-0.9-52.9c0.6-12.6,3.9-25,6-37.5c0.1-0.6,0.9-1.5,0.7-1.8c-5-8,2.9-15.7,0.6-23.9
c-2.2-8-3.5-16.4-3.7-24.6c-0.2-6.9,2.3-13.8,2.8-20.7c0.8-12.2,8.8-18.8,20.6-23c7.3-2.6,9.1-5.2,8.2-11.3c-0.1-1.1-0.6-2.7-1.4-3
c-10-4.1-8.9-12.3-9.9-19.9c-0.9-7.2-2.7-14.2-3.6-21.4c-0.3-2.9,0.2-5.9,3.6-8.1c6.4-4,13.1-5.3,20.7-3.4
C73.7,8.3,76.3,7.4,78.8,7.1z M107.1,130.2c-1,0-2,0.1-3.1,0.1c0,3.1-0.2,6.1,0,9.2c0.7,9.3,5.9,19-2.4,27.7
c-0.2,0.2-0.2,0.6-0.1,0.9c1.9,7.2,3.8,14.5,5.6,21.7c0.7-0.1,1.4-0.1,2.1-0.2C108.5,169.9,107.8,150,107.1,130.2z"/>
<circle class="st1" cx="70.9" cy="109.9" r="26"/>
<circle class="st2" cx="70.9" cy="109.9" r="23"/>
<path class="st3" d="M70.9,127.8c-9.9,0-17.9-8-17.9-17.9s8-17.9,17.9-17.9s17.9,8,17.9,17.9S80.7,127.8,70.9,127.8z M70.9,94.8
c-8.3,0-15.1,6.8-15.1,15.1s6.8,15.1,15.1,15.1S86,118.3,86,109.9S79.2,94.8,70.9,94.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

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

View file

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

View file

@ -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<PointerManager>()->setDoesHover(uid, hover);
}
}

View file

@ -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<PointerManager>()->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 <code>true</code> 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

View file

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

View file

@ -1705,16 +1705,16 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& 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<JointData>& 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<JointData>& 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();
}
}
}

View file

@ -39,6 +39,7 @@
#include <AudioHelpers.h>
#include <Profile.h>
#include <VariantMapToScriptValue.h>
#include <BitVectorHelpers.h>
#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<unsigned char*>(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<glm::quat>& 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<glm::vec3>& 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;
}

View file

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

View file

@ -1050,7 +1050,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
return;
}
QVector<JointData> jointsData;
QVector<EntityJointData> jointsData;
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size();

View file

@ -452,7 +452,7 @@ void ModelEntityItem::resizeJointArrays(int newSize) {
});
}
void ModelEntityItem::setAnimationJointsData(const QVector<JointData>& jointsData) {
void ModelEntityItem::setAnimationJointsData(const QVector<EntityJointData>& jointsData) {
resizeJointArrays(jointsData.size());
_jointDataLock.withWriteLock([&] {
for (auto index = 0; index < jointsData.size(); ++index) {

View file

@ -124,7 +124,7 @@ public:
virtual void setJointTranslations(const QVector<glm::vec3>& translations);
virtual void setJointTranslationsSet(const QVector<bool>& translationsSet);
virtual void setAnimationJointsData(const QVector<JointData>& jointsData);
virtual void setAnimationJointsData(const QVector<EntityJointData>& jointsData);
QVector<glm::quat> getJointRotations() const;
QVector<bool> 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 };
};

View file

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

View file

@ -38,7 +38,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::AvatarData:
case PacketType::BulkAvatarData:
case PacketType::KillAvatar:
return static_cast<PacketVersion>(AvatarMixerPacketVersion::UpdatedMannequinDefaultAvatar);
return static_cast<PacketVersion>(AvatarMixerPacketVersion::AvatarJointDefaultPoseFlags);
case PacketType::MessagesData:
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
case PacketType::ICEServerHeartbeat:

View file

@ -247,7 +247,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
AvatarIdentitySequenceFront,
IsReplicatedInAvatarIdentity,
AvatarIdentityLookAtSnapping,
UpdatedMannequinDefaultAvatar
UpdatedMannequinDefaultAvatar,
AvatarJointDefaultPoseFlags
};
enum class DomainConnectRequestVersion : PacketVersion {

View file

@ -64,12 +64,6 @@ bool Pointer::isMouse() const {
return DependencyManager::get<PickManager>()->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) {

View file

@ -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<std::string, PickedObject> _triggeredObjects;
PointerEvent::Button chooseButton(const std::string& button);
};
#endif // hifi_Pick_h

View file

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

View file

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

View file

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

View file

@ -5,14 +5,27 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
// 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

View file

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

View file

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

View file

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

View file

@ -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, [], []);
};
}