diff --git a/interface/resources/qml/controls-uit/ComboBox.qml b/interface/resources/qml/controls-uit/ComboBox.qml
index be8c9f6740..245b565a62 100644
--- a/interface/resources/qml/controls-uit/ComboBox.qml
+++ b/interface/resources/qml/controls-uit/ComboBox.qml
@@ -103,7 +103,7 @@ FocusScope {
verticalCenter: parent.verticalCenter
}
size: hifi.fontSizes.textFieldInput
- text: comboBox.currentText
+ text: comboBox.displayText ? comboBox.displayText : comboBox.currentText
elide: Text.ElideRight
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
}
diff --git a/interface/resources/qml/controls-uit/SpinBox.qml b/interface/resources/qml/controls-uit/SpinBox.qml
index f3ae3c5d6e..3d3ea7a75e 100644
--- a/interface/resources/qml/controls-uit/SpinBox.qml
+++ b/interface/resources/qml/controls-uit/SpinBox.qml
@@ -21,6 +21,7 @@ SpinBox {
id: hifi
}
+ inputMethodHints: Qt.ImhFormattedNumbersOnly
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
property string label: ""
@@ -91,7 +92,6 @@ SpinBox {
}
valueFromText: function(text, locale) {
- spinBox.value = 0; // Force valueChanged signal to be emitted so that validator fires.
return Number.fromLocaleString(locale, text)*factor;
}
@@ -104,6 +104,8 @@ SpinBox {
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
text: spinBox.textFromValue(spinBox.value, spinBox.locale) + suffix
+ inputMethodHints: spinBox.inputMethodHints
+ validator: spinBox.validator
verticalAlignment: Qt.AlignVCenter
leftPadding: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
//rightPadding: hifi.dimensions.spinnerSize
diff --git a/interface/resources/qml/hifi/AvatarApp.qml b/interface/resources/qml/hifi/AvatarApp.qml
index b7e1adda70..d8eae311d8 100644
--- a/interface/resources/qml/hifi/AvatarApp.qml
+++ b/interface/resources/qml/hifi/AvatarApp.qml
@@ -57,7 +57,7 @@ Rectangle {
try {
var marketResponse = JSON.parse(xmlhttp.responseText.trim())
- if(marketResponse.status === 'success') {
+ if (marketResponse.status === 'success') {
avatar.modelName = marketResponse.data.title;
}
}
@@ -72,14 +72,14 @@ Rectangle {
function getAvatarModelName() {
- if(currentAvatar === null) {
+ if (currentAvatar === null) {
return '';
}
- if(currentAvatar.modelName !== undefined) {
+ if (currentAvatar.modelName !== undefined) {
return currentAvatar.modelName;
} else {
var marketId = allAvatars.extractMarketId(currentAvatar.avatarUrl);
- if(marketId !== '') {
+ if (marketId !== '') {
fetchAvatarModelName(marketId, currentAvatar);
}
}
@@ -103,51 +103,51 @@ Rectangle {
property url externalAvatarThumbnailUrl: '../../images/avatarapp/guy-in-circle.svg'
function fromScript(message) {
- if(message.method === 'initialize') {
+ if (message.method === 'initialize') {
jointNames = message.data.jointNames;
emitSendToScript({'method' : getAvatarsMethod});
- } else if(message.method === 'wearableUpdated') {
+ } else if (message.method === 'wearableUpdated') {
adjustWearables.refreshWearable(message.entityID, message.wearableIndex, message.properties, message.updateUI);
- } else if(message.method === 'wearablesUpdated') {
+ } else if (message.method === 'wearablesUpdated') {
var wearablesModel = currentAvatar.wearables;
wearablesModel.clear();
message.wearables.forEach(function(wearable) {
wearablesModel.append(wearable);
});
adjustWearables.refresh(currentAvatar);
- } else if(message.method === 'scaleChanged') {
+ } else if (message.method === 'scaleChanged') {
currentAvatar.avatarScale = message.value;
updateCurrentAvatarInBookmarks(currentAvatar);
- } else if(message.method === 'externalAvatarApplied') {
+ } else if (message.method === 'externalAvatarApplied') {
currentAvatar.avatarUrl = message.avatarURL;
currentAvatar.thumbnailUrl = allAvatars.makeThumbnailUrl(message.avatarURL);
currentAvatar.entry.avatarUrl = currentAvatar.avatarUrl;
currentAvatar.modelName = undefined;
updateCurrentAvatarInBookmarks(currentAvatar);
- } else if(message.method === 'settingChanged') {
+ } else if (message.method === 'settingChanged') {
currentAvatarSettings[message.name] = message.value;
- } else if(message.method === 'changeSettings') {
+ } else if (message.method === 'changeSettings') {
currentAvatarSettings = message.settings;
- } else if(message.method === 'bookmarkLoaded') {
+ } else if (message.method === 'bookmarkLoaded') {
setCurrentAvatar(message.data.currentAvatar, message.data.name);
var avatarIndex = allAvatars.findAvatarIndex(currentAvatar.name);
allAvatars.move(avatarIndex, 0, 1);
view.setPage(0);
- } else if(message.method === 'bookmarkAdded') {
+ } else if (message.method === 'bookmarkAdded') {
var avatar = allAvatars.findAvatar(message.bookmarkName);
- if(avatar !== undefined) {
+ if (avatar !== undefined) {
var avatarObject = allAvatars.makeAvatarObject(message.bookmark, message.bookmarkName);
for(var prop in avatarObject) {
avatar[prop] = avatarObject[prop];
}
- if(currentAvatar.name === message.bookmarkName) {
+ if (currentAvatar.name === message.bookmarkName) {
currentAvatar = currentAvatarModel.makeAvatarEntry(avatarObject);
}
} else {
allAvatars.addAvatarEntry(message.bookmark, message.bookmarkName);
}
updateCurrentAvatarInBookmarks(currentAvatar);
- } else if(message.method === 'bookmarkDeleted') {
+ } else if (message.method === 'bookmarkDeleted') {
pageOfAvatars.isUpdating = true;
var index = pageOfAvatars.findAvatarIndex(message.name);
@@ -159,15 +159,16 @@ Rectangle {
var itemsOnPage = pageOfAvatars.count;
var newItemIndex = view.currentPage * view.itemsPerPage + itemsOnPage;
- if(newItemIndex <= (allAvatars.count - 1)) {
+ if (newItemIndex <= (allAvatars.count - 1)) {
pageOfAvatars.append(allAvatars.get(newItemIndex));
} else {
- if(!pageOfAvatars.hasGetAvatars())
+ if (!pageOfAvatars.hasGetAvatars()) {
pageOfAvatars.appendGetAvatars();
+ }
}
pageOfAvatars.isUpdating = false;
- } else if(message.method === getAvatarsMethod) {
+ } else if (message.method === getAvatarsMethod) {
var getAvatarsData = message.data;
allAvatars.populate(getAvatarsData.bookmarks);
setCurrentAvatar(getAvatarsData.currentAvatar, '');
@@ -175,16 +176,16 @@ Rectangle {
currentAvatarSettings = getAvatarsData.currentAvatarSettings;
updateCurrentAvatarInBookmarks(currentAvatar);
- } else if(message.method === 'updateAvatarInBookmarks') {
+ } else if (message.method === 'updateAvatarInBookmarks') {
updateCurrentAvatarInBookmarks(currentAvatar);
- } else if(message.method === 'selectAvatarEntity') {
+ } else if (message.method === 'selectAvatarEntity') {
adjustWearables.selectWearableByID(message.entityID);
}
}
function updateCurrentAvatarInBookmarks(avatar) {
var bookmarkAvatarIndex = allAvatars.findAvatarIndexByValue(avatar);
- if(bookmarkAvatarIndex === -1) {
+ if (bookmarkAvatarIndex === -1) {
avatar.name = '';
view.setPage(0);
} else {
@@ -285,6 +286,9 @@ Rectangle {
onWearableSelected: {
emitSendToScript({'method' : 'selectWearable', 'entityID' : id});
}
+ onAddWearable: {
+ emitSendToScript({'method' : 'addWearable', 'avatarName' : avatarName, 'url' : url});
+ }
z: 3
}
@@ -491,33 +495,10 @@ Rectangle {
anchors.verticalCenter: wearablesLabel.verticalCenter
glyphText: "\ue02e"
- visible: avatarWearablesCount !== 0
onClicked: {
adjustWearables.open(currentAvatar);
}
}
-
- // TextStyle3
- RalewayRegular {
- size: 22;
- anchors.right: parent.right
- anchors.verticalCenter: wearablesLabel.verticalCenter
- font.underline: true
- text: "Add"
- color: 'black'
- visible: avatarWearablesCount === 0
-
- MouseArea {
- anchors.fill: parent
- onClicked: {
- popup.showGetWearables(function() {
- emitSendToScript({'method' : 'navigate', 'url' : 'hifi://AvatarIsland/11.5848,-8.10862,-2.80195'})
- }, function(link) {
- emitSendToScript({'method' : 'navigate', 'url' : link})
- });
- }
- }
- }
}
Rectangle {
@@ -617,8 +598,9 @@ Rectangle {
pageOfAvatars.append(avatarItem);
}
- if(pageOfAvatars.count !== itemsPerPage)
+ if (pageOfAvatars.count !== itemsPerPage) {
pageOfAvatars.appendGetAvatars();
+ }
currentPage = pageIndex;
pageOfAvatars.isUpdating = false;
@@ -639,7 +621,7 @@ Rectangle {
}
function removeGetAvatars() {
- if(hasGetAvatars()) {
+ if (hasGetAvatars()) {
remove(count - 1)
}
}
@@ -707,13 +689,13 @@ Rectangle {
hoverEnabled: enabled
onClicked: {
- if(isInManageState) {
+ if (isInManageState) {
var currentItem = delegateRoot.GridView.view.model.get(index);
popup.showDeleteFavorite(currentItem.name, function() {
view.deleteAvatar(currentItem);
});
} else {
- if(delegateRoot.GridView.view.currentIndex !== index) {
+ if (delegateRoot.GridView.view.currentIndex !== index) {
var currentItem = delegateRoot.GridView.view.model.get(index);
popup.showLoadFavorite(currentItem.name, function() {
view.selectAvatar(currentItem);
diff --git a/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml b/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml
index 39344b04bc..e80dab60c2 100644
--- a/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml
+++ b/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml
@@ -1,5 +1,6 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
+import QtQuick.Layouts 1.3
import "../../styles-uit"
import "../../controls-uit" as HifiControlsUit
import "../../controls" as HifiControls
@@ -17,6 +18,7 @@ Rectangle {
signal adjustWearablesOpened(var avatarName);
signal adjustWearablesClosed(bool status, var avatarName);
+ signal addWearable(string avatarName, string url);
property bool modified: false;
Component.onCompleted: {
@@ -30,6 +32,7 @@ Rectangle {
function open(avatar) {
adjustWearablesOpened(avatar.name);
+ modified = false;
visible = true;
avatarName = avatar.name;
wearablesModel = avatar.wearables;
@@ -38,43 +41,47 @@ Rectangle {
function refresh(avatar) {
wearablesCombobox.model.clear();
- for(var i = 0; i < avatar.wearables.count; ++i) {
+ wearablesCombobox.currentIndex = -1;
+
+ for (var i = 0; i < avatar.wearables.count; ++i) {
var wearable = avatar.wearables.get(i).properties;
- for(var j = (wearable.modelURL.length - 1); j >= 0; --j) {
- if(wearable.modelURL[j] === '/') {
- wearable.text = wearable.modelURL.substring(j + 1) + ' [%jointIndex%]'.replace('%jointIndex%', jointNames[wearable.parentJointIndex]);
+ for (var j = (wearable.modelURL.length - 1); j >= 0; --j) {
+ if (wearable.modelURL[j] === '/') {
+ wearable.text = wearable.modelURL.substring(j + 1);
break;
}
}
wearablesCombobox.model.append(wearable);
}
- wearablesCombobox.currentIndex = 0;
+ if (wearablesCombobox.model.count !== 0) {
+ wearablesCombobox.currentIndex = 0;
+ }
}
function refreshWearable(wearableID, wearableIndex, properties, updateUI) {
- if(wearableIndex === -1) {
+ if (wearableIndex === -1) {
wearableIndex = wearablesCombobox.model.findIndexById(wearableID);
}
var wearable = wearablesCombobox.model.get(wearableIndex);
- if(!wearable) {
+ if (!wearable) {
return;
}
var wearableModelItemProperties = wearablesModel.get(wearableIndex).properties;
- for(var prop in properties) {
+ for (var prop in properties) {
wearable[prop] = properties[prop];
wearableModelItemProperties[prop] = wearable[prop];
- if(updateUI) {
- if(prop === 'localPosition') {
- position.set(wearable[prop]);
- } else if(prop === 'localRotationAngles') {
- rotation.set(wearable[prop]);
- } else if(prop === 'dimensions') {
+ if (updateUI) {
+ if (prop === 'localPosition') {
+ positionVector.set(wearable[prop]);
+ } else if (prop === 'localRotationAngles') {
+ rotationVector.set(wearable[prop]);
+ } else if (prop === 'dimensions') {
scalespinner.set(wearable[prop].x / wearable.naturalDimensions.x);
}
}
@@ -84,13 +91,13 @@ Rectangle {
}
function getCurrentWearable() {
- return wearablesCombobox.model.get(wearablesCombobox.currentIndex)
+ return wearablesCombobox.currentIndex !== -1 ? wearablesCombobox.model.get(wearablesCombobox.currentIndex) : null;
}
function selectWearableByID(entityID) {
- for(var i = 0; i < wearablesCombobox.model.count; ++i) {
+ for (var i = 0; i < wearablesCombobox.model.count; ++i) {
var wearable = wearablesCombobox.model.get(i);
- if(wearable.id === entityID) {
+ if (wearable.id === entityID) {
wearablesCombobox.currentIndex = i;
break;
}
@@ -115,72 +122,216 @@ Rectangle {
Column {
anchors.top: parent.top
- anchors.topMargin: 15
+ anchors.topMargin: 12
anchors.horizontalCenter: parent.horizontalCenter
spacing: 20
- width: parent.width - 30 * 2
+ width: parent.width - 22 * 2
- HifiControlsUit.ComboBox {
- id: wearablesCombobox
- anchors.left: parent.left
- anchors.right: parent.right
- comboBox.textRole: "text"
+ Column {
+ width: parent.width
- model: ListModel {
- function findIndexById(id) {
+ Rectangle {
+ color: hifi.colors.orangeHighlight
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 70
+ visible: HMD.active
- for(var i = 0; i < count; ++i) {
- var wearable = get(i);
- if(wearable.id === id) {
- return i;
- }
- }
-
- return -1;
+ RalewayRegular {
+ anchors.fill: parent
+ anchors.leftMargin: 18
+ anchors.rightMargin: 18
+ size: 20;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 23;
+ text: "Tip: You can use hand controllers to grab and adjust your wearables"
+ wrapMode: Text.WordWrap
}
}
- comboBox.onCurrentIndexChanged: {
- var currentWearable = getCurrentWearable();
+ Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 12 // spacing
+ visible: HMD.active
+ }
- if(currentWearable) {
- position.set(currentWearable.localPosition);
- rotation.set(currentWearable.localRotationAngles);
- scalespinner.set(currentWearable.dimensions.x / currentWearable.naturalDimensions.x)
+ RowLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
- wearableSelected(currentWearable.id);
+ RalewayBold {
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
+ text: "Wearable"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ spacing: 10
+
+ RalewayBold {
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
+ text: "Get more"
+ linkColor: hifi.colors.blueHighlight
+ anchors.verticalCenter: parent.verticalCenter
+ onLinkActivated: {
+ popup.showGetWearables(function() {
+ emitSendToScript({'method' : 'navigate', 'url' : 'hifi://AvatarIsland/11.5848,-8.10862,-2.80195'})
+ }, function(link) {
+ emitSendToScript({'method' : 'navigate', 'url' : link})
+ });
+ }
+ }
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ RalewayBold {
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
+ text: "Add custom"
+ linkColor: hifi.colors.blueHighlight
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ onLinkActivated: {
+ popup.showSpecifyWearableUrl(function(url) {
+ console.debug('popup.showSpecifyWearableUrl: ', url);
+ addWearable(root.avatarName, url);
+ modified = true;
+ });
+ }
+ }
+ }
+ }
+
+ HifiControlsUit.ComboBox {
+ id: wearablesCombobox
+ anchors.left: parent.left
+ anchors.right: parent.right
+ enabled: getCurrentWearable() !== null
+ comboBox.textRole: "text"
+
+ model: ListModel {
+ function findIndexById(id) {
+
+ for (var i = 0; i < count; ++i) {
+ var wearable = get(i);
+ if (wearable.id === id) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+ }
+
+ comboBox.onCurrentIndexChanged: {
+ var currentWearable = getCurrentWearable();
+ var position = currentWearable ? currentWearable.localPosition : { x : 0, y : 0, z : 0 };
+ var rotation = currentWearable ? currentWearable.localRotationAngles : { x : 0, y : 0, z : 0 };
+ var scale = currentWearable ? currentWearable.dimensions.x / currentWearable.naturalDimensions.x : 1.0;
+ var joint = currentWearable ? currentWearable.parentJointIndex : -1;
+ var soft = currentWearable ? currentWearable.relayParentJoints : false;
+
+ positionVector.set(position);
+ rotationVector.set(rotation);
+ scalespinner.set(scale);
+ jointsCombobox.set(joint);
+ isSoft.set(soft);
+
+ if (currentWearable) {
+ wearableSelected(currentWearable.id);
+ }
+ }
+ }
+ }
+
+ Column {
+ width: parent.width
+
+ RalewayBold {
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
+ text: "Joint"
+ }
+
+ HifiControlsUit.ComboBox {
+ id: jointsCombobox
+ anchors.left: parent.left
+ anchors.right: parent.right
+ enabled: getCurrentWearable() !== null && !isSoft.checked
+ comboBox.displayText: isSoft.checked ? 'Hips' : comboBox.currentText
+
+ model: jointNames
+ property bool notify: false
+
+ function set(jointIndex) {
+ notify = false;
+ currentIndex = jointIndex;
+ notify = true;
+ }
+
+ function notifyJointChanged() {
+ modified = true;
+ var properties = {
+ parentJointIndex: currentIndex,
+ localPosition: {
+ x: positionVector.xvalue,
+ y: positionVector.yvalue,
+ z: positionVector.zvalue
+ },
+ localRotationAngles: {
+ x: rotationVector.xvalue,
+ y: rotationVector.yvalue,
+ z: rotationVector.zvalue,
+ }
+ };
+
+ wearableUpdated(getCurrentWearable().id, wearablesCombobox.currentIndex, properties);
+ }
+
+ onCurrentIndexChanged: {
+ if (notify) notifyJointChanged();
}
}
}
Column {
width: parent.width
- spacing: 5
Row {
spacing: 20
// TextStyle5
- FiraSansSemiBold {
+ RalewayBold {
id: positionLabel
- size: 22;
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
text: "Position"
}
// TextStyle7
- FiraSansRegular {
- size: 18;
+ RalewayBold {
+ size: 15;
lineHeightMode: Text.FixedHeight
- lineHeight: 16.9;
+ lineHeight: 18;
text: "m"
anchors.verticalCenter: positionLabel.verticalCenter
}
}
Vector3 {
- id: position
+ id: positionVector
backgroundColor: "lightgray"
+ enabled: getCurrentWearable() !== null
function set(localPosition) {
notify = false;
@@ -201,9 +352,9 @@ Rectangle {
property bool notify: false;
- onXvalueChanged: if(notify) notifyPositionChanged();
- onYvalueChanged: if(notify) notifyPositionChanged();
- onZvalueChanged: if(notify) notifyPositionChanged();
+ onXvalueChanged: if (notify) notifyPositionChanged();
+ onYvalueChanged: if (notify) notifyPositionChanged();
+ onZvalueChanged: if (notify) notifyPositionChanged();
decimals: 2
realFrom: -10
@@ -214,31 +365,33 @@ Rectangle {
Column {
width: parent.width
- spacing: 5
Row {
spacing: 20
// TextStyle5
- FiraSansSemiBold {
+ RalewayBold {
id: rotationLabel
- size: 22;
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
text: "Rotation"
}
// TextStyle7
- FiraSansRegular {
- size: 18;
+ RalewayBold {
+ size: 15;
lineHeightMode: Text.FixedHeight
- lineHeight: 16.9;
+ lineHeight: 18;
text: "deg"
anchors.verticalCenter: rotationLabel.verticalCenter
}
}
Vector3 {
- id: rotation
+ id: rotationVector
backgroundColor: "lightgray"
+ enabled: getCurrentWearable() !== null
function set(localRotationAngles) {
notify = false;
@@ -259,9 +412,9 @@ Rectangle {
property bool notify: false;
- onXvalueChanged: if(notify) notifyRotationChanged();
- onYvalueChanged: if(notify) notifyRotationChanged();
- onZvalueChanged: if(notify) notifyRotationChanged();
+ onXvalueChanged: if (notify) notifyRotationChanged();
+ onYvalueChanged: if (notify) notifyRotationChanged();
+ onZvalueChanged: if (notify) notifyRotationChanged();
decimals: 0
realFrom: -180
@@ -270,33 +423,66 @@ Rectangle {
}
}
- Column {
+ Item {
width: parent.width
- spacing: 5
+ height: childrenRect.height
- // TextStyle5
- FiraSansSemiBold {
- size: 22;
- text: "Scale"
+ HifiControlsUit.CheckBox {
+ id: isSoft
+ enabled: getCurrentWearable() !== null
+ text: "Is soft"
+ labelFontSize: 15
+ labelFontWeight: Font.Bold
+ color: Qt.black
+ y: scalespinner.y
+
+ function set(value) {
+ notify = false;
+ checked = value
+ notify = true;
+ }
+
+ function notifyIsSoftChanged() {
+ modified = true;
+ var properties = {
+ relayParentJoints: checked
+ };
+
+ wearableUpdated(getCurrentWearable().id, wearablesCombobox.currentIndex, properties);
+ }
+
+ property bool notify: false;
+
+ onCheckedChanged: if (notify) notifyIsSoftChanged();
}
- Item {
- width: parent.width
- height: childrenRect.height
+ Column {
+ id: scalesColumn
+ anchors.right: parent.right
+
+ // TextStyle5
+ RalewayBold {
+ id: scaleLabel
+ size: 15;
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18;
+ text: "Scale"
+ }
HifiControlsUit.SpinBox {
id: scalespinner
+ enabled: getCurrentWearable() !== null
decimals: 2
realStepSize: 0.1
realFrom: 0.1
realTo: 3.0
realValue: 1.0
backgroundColor: "lightgray"
- width: position.spinboxWidth
+ width: positionVector.spinboxWidth
colorScheme: hifi.colorSchemes.light
property bool notify: false;
- onValueChanged: if(notify) notifyScaleChanged();
+ onRealValueChanged: if (notify) notifyScaleChanged();
function set(value) {
notify = false;
@@ -320,26 +506,34 @@ Rectangle {
wearableUpdated(currentWearable.id, wearablesCombobox.currentIndex, properties);
}
}
-
- HifiControlsUit.Button {
- fontSize: 18
- height: 40
- anchors.right: parent.right
- color: hifi.buttons.red;
- colorScheme: hifi.colorSchemes.light;
- text: "TAKE IT OFF"
- onClicked: wearableDeleted(root.avatarName, getCurrentWearable().id);
- enabled: wearablesCombobox.model.count !== 0
- anchors.verticalCenter: scalespinner.verticalCenter
- }
}
+ }
+ Column {
+ width: parent.width
+
+ HifiControlsUit.Button {
+ fontSize: 18
+ height: 40
+ width: scalespinner.width
+ anchors.right: parent.right
+ color: hifi.buttons.red;
+ colorScheme: hifi.colorSchemes.light;
+ text: "TAKE IT OFF"
+ onClicked: {
+ modified = true;
+ wearableDeleted(root.avatarName, getCurrentWearable().id);
+ }
+ enabled: wearablesCombobox.model.count !== 0
+ }
}
}
DialogButtons {
+ yesButton.enabled: modified
+
anchors.bottom: parent.bottom
- anchors.bottomMargin: 30
+ anchors.bottomMargin: 57
anchors.left: parent.left
anchors.leftMargin: 30
anchors.right: parent.right
diff --git a/interface/resources/qml/hifi/avatarapp/AvatarsModel.qml b/interface/resources/qml/hifi/avatarapp/AvatarsModel.qml
index 931a041747..bfd66f1a30 100644
--- a/interface/resources/qml/hifi/avatarapp/AvatarsModel.qml
+++ b/interface/resources/qml/hifi/avatarapp/AvatarsModel.qml
@@ -24,8 +24,9 @@ ListModel {
function makeThumbnailUrl(avatarUrl) {
var marketId = extractMarketId(avatarUrl);
- if(marketId === '')
+ if (marketId === '') {
return '';
+ }
var avatarThumbnailUrl = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/%marketId%/large/hifi-mp-%marketId%.jpg"
.split('%marketId%').join(marketId);
@@ -42,7 +43,6 @@ ListModel {
'thumbnailUrl' : avatarThumbnailUrl,
'avatarUrl' : avatar.avatarUrl,
'wearables' : avatar.avatarEntites ? avatar.avatarEntites : [],
- 'attachments' : avatar.attachments ? avatar.attachments : [],
'entry' : avatar,
'getMoreAvatars' : false
};
@@ -58,7 +58,7 @@ ListModel {
function populate(bookmarks) {
clear();
- for(var avatarName in bookmarks) {
+ for (var avatarName in bookmarks) {
var avatar = bookmarks[avatarName];
var avatarEntry = makeAvatarObject(avatar, avatarName);
@@ -67,19 +67,19 @@ ListModel {
}
function arraysAreEqual(a1, a2, comparer) {
- if(Array.isArray(a1) && Array.isArray(a2)) {
- if(a1.length !== a2.length) {
+ if (Array.isArray(a1) && Array.isArray(a2)) {
+ if (a1.length !== a2.length) {
return false;
}
- for(var i = 0; i < a1.length; ++i) {
- if(!comparer(a1[i], a2[i])) {
+ for (var i = 0; i < a1.length; ++i) {
+ if (!comparer(a1[i], a2[i])) {
return false;
}
}
- } else if(Array.isArray(a1)) {
+ } else if (Array.isArray(a1)) {
return a1.length === 0;
- } else if(Array.isArray(a2)) {
+ } else if (Array.isArray(a2)) {
return a2.length === 0;
}
@@ -87,26 +87,26 @@ ListModel {
}
function modelsAreEqual(m1, m2, comparer) {
- if(m1.count !== m2.count) {
+ if (m1.count !== m2.count) {
return false;
}
- for(var i = 0; i < m1.count; ++i) {
+ for (var i = 0; i < m1.count; ++i) {
var e1 = m1.get(i);
var allDifferent = true;
// it turns out order of wearables can randomly change so make position-independent comparison here
- for(var j = 0; j < m2.count; ++j) {
+ for (var j = 0; j < m2.count; ++j) {
var e2 = m2.get(j);
- if(comparer(e1, e2)) {
+ if (comparer(e1, e2)) {
allDifferent = false;
break;
}
}
- if(allDifferent) {
+ if (allDifferent) {
return false;
}
}
@@ -115,18 +115,20 @@ ListModel {
}
function compareNumericObjects(o1, o2) {
- if(o1 === undefined && o2 !== undefined)
+ if (o1 === undefined && o2 !== undefined) {
return false;
- if(o1 !== undefined && o2 === undefined)
+ }
+ if (o1 !== undefined && o2 === undefined) {
return false;
+ }
- for(var prop in o1) {
- if(o1.hasOwnProperty(prop) && o2.hasOwnProperty(prop)) {
+ for (var prop in o1) {
+ if (o1.hasOwnProperty(prop) && o2.hasOwnProperty(prop)) {
var v1 = o1[prop];
var v2 = o2[prop];
- if(v1 !== v2 && Math.round(v1 * 500) != Math.round(v2 * 500)) {
+ if (v1 !== v2 && Math.round(v1 * 500) != Math.round(v2 * 500)) {
return false;
}
}
@@ -136,7 +138,7 @@ ListModel {
}
function compareObjects(o1, o2, props, arrayProp) {
- for(var i = 0; i < props.length; ++i) {
+ for (var i = 0; i < props.length; ++i) {
var prop = props[i];
var propertyName = prop.propertyName;
var comparer = prop.comparer;
@@ -144,12 +146,12 @@ ListModel {
var o1Value = arrayProp ? o1[arrayProp][propertyName] : o1[propertyName];
var o2Value = arrayProp ? o2[arrayProp][propertyName] : o2[propertyName];
- if(comparer) {
- if(comparer(o1Value, o2Value) === false) {
+ if (comparer) {
+ if (comparer(o1Value, o2Value) === false) {
return false;
}
} else {
- if(JSON.stringify(o1Value) !== JSON.stringify(o2Value)) {
+ if (JSON.stringify(o1Value) !== JSON.stringify(o2Value)) {
return false;
}
}
@@ -164,42 +166,34 @@ ListModel {
{'propertyName' : 'marketplaceID'},
{'propertyName' : 'itemName'},
{'propertyName' : 'script'},
+ {'propertyName' : 'relayParentJoints'},
{'propertyName' : 'localPosition', 'comparer' : compareNumericObjects},
{'propertyName' : 'localRotationAngles', 'comparer' : compareNumericObjects},
{'propertyName' : 'dimensions', 'comparer' : compareNumericObjects}], 'properties')
}
- function compareAttachments(a1, a2) {
- return compareObjects(a1, a2, [{'propertyName' : 'position', 'comparer' : compareNumericObjects},
- {'propertyName' : 'orientation'},
- {'propertyName' : 'parentJointIndex'},
- {'propertyName' : 'modelurl'}])
- }
-
function findAvatarIndexByValue(avatar) {
var index = -1;
// 2DO: find better way of determining selected avatar in bookmarks
- for(var i = 0; i < allAvatars.count; ++i) {
+ for (var i = 0; i < allAvatars.count; ++i) {
var thesame = true;
var bookmarkedAvatar = allAvatars.get(i);
- if(bookmarkedAvatar.avatarUrl !== avatar.avatarUrl)
- continue;
-
- if(bookmarkedAvatar.avatarScale !== avatar.avatarScale)
- continue;
-
- if(!modelsAreEqual(bookmarkedAvatar.attachments, avatar.attachments, compareAttachments)) {
+ if (bookmarkedAvatar.avatarUrl !== avatar.avatarUrl) {
continue;
}
- if(!modelsAreEqual(bookmarkedAvatar.wearables, avatar.wearables, compareWearables)) {
+ if (bookmarkedAvatar.avatarScale !== avatar.avatarScale) {
continue;
}
- if(thesame) {
+ if (!modelsAreEqual(bookmarkedAvatar.wearables, avatar.wearables, compareWearables)) {
+ continue;
+ }
+
+ if (thesame) {
index = i;
break;
}
@@ -209,8 +203,8 @@ ListModel {
}
function findAvatarIndex(avatarName) {
- for(var i = 0; i < count; ++i) {
- if(get(i).name === avatarName) {
+ for (var i = 0; i < count; ++i) {
+ if (get(i).name === avatarName) {
return i;
}
}
@@ -219,8 +213,9 @@ ListModel {
function findAvatar(avatarName) {
var avatarIndex = findAvatarIndex(avatarName);
- if(avatarIndex === -1)
+ if (avatarIndex === -1) {
return undefined;
+ }
return get(avatarIndex);
}
diff --git a/interface/resources/qml/hifi/avatarapp/CreateFavoriteDialog.qml b/interface/resources/qml/hifi/avatarapp/CreateFavoriteDialog.qml
index ab995e79e8..1387c0791a 100644
--- a/interface/resources/qml/hifi/avatarapp/CreateFavoriteDialog.qml
+++ b/interface/resources/qml/hifi/avatarapp/CreateFavoriteDialog.qml
@@ -125,9 +125,9 @@ Rectangle {
size: 15
color: 'red'
visible: {
- for(var i = 0; i < avatars.count; ++i) {
+ for (var i = 0; i < avatars.count; ++i) {
var avatarName = avatars.get(i).name;
- if(avatarName === favoriteName.text) {
+ if (avatarName === favoriteName.text) {
return true;
}
}
@@ -165,7 +165,7 @@ Rectangle {
}
onYesClicked: function() {
- if(onSaveClicked) {
+ if (onSaveClicked) {
onSaveClicked();
} else {
root.close();
@@ -173,7 +173,7 @@ Rectangle {
}
onNoClicked: function() {
- if(onCancelClicked) {
+ if (onCancelClicked) {
onCancelClicked();
} else {
root.close();
diff --git a/interface/resources/qml/hifi/avatarapp/DialogButtons.qml b/interface/resources/qml/hifi/avatarapp/DialogButtons.qml
index 46c17bb4dc..d6eb0139ed 100644
--- a/interface/resources/qml/hifi/avatarapp/DialogButtons.qml
+++ b/interface/resources/qml/hifi/avatarapp/DialogButtons.qml
@@ -33,7 +33,7 @@ Row {
onClicked: {
console.debug('whitebutton.clicked', onNoClicked);
- if(onNoClicked) {
+ if (onNoClicked) {
onNoClicked();
}
}
diff --git a/interface/resources/qml/hifi/avatarapp/MessageBox.qml b/interface/resources/qml/hifi/avatarapp/MessageBox.qml
index e4aa0847c5..f111303214 100644
--- a/interface/resources/qml/hifi/avatarapp/MessageBox.qml
+++ b/interface/resources/qml/hifi/avatarapp/MessageBox.qml
@@ -128,7 +128,7 @@ Rectangle {
wrapMode: Text.WordWrap;
onLinkActivated: {
- if(onLinkClicked)
+ if (onLinkClicked)
onLinkClicked(link);
}
}
@@ -166,7 +166,7 @@ Rectangle {
noText: root.button1text
onYesClicked: function() {
- if(onButton2Clicked) {
+ if (onButton2Clicked) {
onButton2Clicked();
} else {
root.close();
@@ -174,7 +174,7 @@ Rectangle {
}
onNoClicked: function() {
- if(onButton1Clicked) {
+ if (onButton1Clicked) {
onButton1Clicked();
} else {
root.close();
diff --git a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml
index bdb0462f42..b7782c697d 100644
--- a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml
+++ b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml
@@ -18,15 +18,38 @@ MessageBox {
popup.button2text = 'CONFIRM';
popup.onButton2Clicked = function() {
- if(callback)
+ if (callback) {
callback();
+ }
popup.close();
}
popup.onLinkClicked = function(link) {
- if(linkCallback)
+ if (linkCallback) {
linkCallback(link);
+ }
+ }
+
+ popup.open();
+ popup.inputText.forceActiveFocus();
+ }
+
+ function showSpecifyWearableUrl(callback) {
+ popup.button2text = 'CONFIRM'
+ popup.button1text = 'CANCEL'
+ popup.titleText = 'Specify Wearable URL'
+ popup.bodyText = 'If you want to add a custom wearable, you can specify the URL of the wearable file here.'
+
+ popup.inputText.visible = true;
+ popup.inputText.placeholderText = 'Enter Wearable URL';
+
+ popup.onButton2Clicked = function() {
+ if (callback) {
+ callback(popup.inputText.text);
+ }
+
+ popup.close();
}
popup.open();
@@ -41,22 +64,24 @@ MessageBox {
popup.button1text = 'CANCEL'
popup.titleText = 'Get Wearables'
popup.bodyText = 'Buy wearables from Marketplace.' + '
' +
- 'Use wearables in My Purchases.' + '
' + '
' +
- 'Visit “AvatarIsland” to get wearables.'
+ 'Wear wearable from My Purchases.' + '
' + '
' +
+ 'Visit “AvatarIsland” to get wearables'
popup.imageSource = getWearablesUrl;
popup.onButton2Clicked = function() {
popup.close();
- if(callback)
+ if (callback) {
callback();
+ }
}
popup.onLinkClicked = function(link) {
popup.close();
- if(linkCallback)
+ if (linkCallback) {
linkCallback(link);
+ }
}
popup.open();
@@ -72,8 +97,9 @@ MessageBox {
popup.onButton2Clicked = function() {
popup.close();
- if(callback)
+ if (callback) {
callback();
+ }
}
popup.open();
}
@@ -87,8 +113,9 @@ MessageBox {
popup.onButton2Clicked = function() {
popup.close();
- if(callback)
+ if (callback) {
callback();
+ }
}
popup.open();
}
@@ -109,15 +136,17 @@ MessageBox {
popup.onButton2Clicked = function() {
popup.close();
- if(callback)
+ if (callback) {
callback();
+ }
}
popup.onLinkClicked = function(link) {
popup.close();
- if(linkCallback)
+ if (linkCallback) {
linkCallback(link);
+ }
}
popup.open();
diff --git a/interface/resources/qml/hifi/avatarapp/Settings.qml b/interface/resources/qml/hifi/avatarapp/Settings.qml
index e1b55866c2..71bfbb084d 100644
--- a/interface/resources/qml/hifi/avatarapp/Settings.qml
+++ b/interface/resources/qml/hifi/avatarapp/Settings.qml
@@ -33,13 +33,13 @@ Rectangle {
scaleSlider.value = Math.round(avatarScale * 10);
scaleSlider.notify = true;;
- if(settings.dominantHand === 'left') {
+ if (settings.dominantHand === 'left') {
leftHandRadioButton.checked = true;
} else {
rightHandRadioButton.checked = true;
}
- if(settings.collisionsEnabled) {
+ if (settings.collisionsEnabled) {
collisionsEnabledRadiobutton.checked = true;
} else {
collisionsDisabledRadioButton.checked = true;
@@ -113,7 +113,7 @@ Rectangle {
onValueChanged: {
console.debug('value changed: ', value);
- if(notify) {
+ if (notify) {
console.debug('notifying.. ');
root.scaleChanged(value / 10);
}
diff --git a/interface/resources/qml/hifi/avatarapp/TransparencyMask.qml b/interface/resources/qml/hifi/avatarapp/TransparencyMask.qml
index 4884d1e1ad..6c50a6093a 100644
--- a/interface/resources/qml/hifi/avatarapp/TransparencyMask.qml
+++ b/interface/resources/qml/hifi/avatarapp/TransparencyMask.qml
@@ -32,7 +32,7 @@ Item {
highp vec4 maskColor = texture2D(mask, vec2(qt_TexCoord0.x, qt_TexCoord0.y));
highp vec4 sourceColor = texture2D(source, vec2(qt_TexCoord0.x, qt_TexCoord0.y));
- if(maskColor.a > 0.0)
+ if (maskColor.a > 0.0)
gl_FragColor = sourceColor;
else
gl_FragColor = maskColor;
diff --git a/interface/resources/qml/hifi/avatarapp/Vector3.qml b/interface/resources/qml/hifi/avatarapp/Vector3.qml
index 33e82fe0ee..d77665f992 100644
--- a/interface/resources/qml/hifi/avatarapp/Vector3.qml
+++ b/interface/resources/qml/hifi/avatarapp/Vector3.qml
@@ -20,6 +20,7 @@ Row {
spacing: spinboxSpace
+ property bool enabled: false;
property alias xvalue: xspinner.realValue
property alias yvalue: yspinner.realValue
property alias zvalue: zspinner.realValue
@@ -35,6 +36,7 @@ Row {
realFrom: root.realFrom
realTo: root.realTo
realStepSize: root.realStepSize
+ enabled: root.enabled
}
HifiControlsUit.SpinBox {
@@ -48,6 +50,7 @@ Row {
realFrom: root.realFrom
realTo: root.realTo
realStepSize: root.realStepSize
+ enabled: root.enabled
}
HifiControlsUit.SpinBox {
@@ -61,5 +64,6 @@ Row {
realFrom: root.realFrom
realTo: root.realTo
realStepSize: root.realStepSize
+ enabled: root.enabled
}
}
diff --git a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml
deleted file mode 100644
index 006a4b7158..0000000000
--- a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// AttachmentsDialog.qml
-//
-// Created by David Rowe on 9 Mar 2017.
-// Copyright 2017 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import QtQuick 2.5
-import Qt.labs.settings 1.0
-
-import "../../styles-uit"
-import "../../windows"
-import "content"
-
-ScrollingWindow {
- id: root
- title: "Attachments"
- objectName: "AttachmentsDialog"
- width: 600
- height: 600
- resizable: true
- destroyOnHidden: true
- minSize: Qt.vector2d(400, 500)
-
- HifiConstants { id: hifi }
-
- // This is for JS/QML communication, which is unused in the AttachmentsDialog,
- // but not having this here results in spurious warnings about a
- // missing signal
- signal sendToScript(var message);
-
- property var settings: Settings {
- category: "AttachmentsDialog"
- property alias x: root.x
- property alias y: root.y
- property alias width: root.width
- property alias height: root.height
- }
-
- function closeDialog() {
- root.destroy();
- }
-
- AttachmentsContent { }
-}
diff --git a/interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml
deleted file mode 100644
index b4357a0077..0000000000
--- a/interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml
+++ /dev/null
@@ -1,130 +0,0 @@
-import QtQuick 2.7
-import QtQuick.Controls 1.5
-import QtQuick.XmlListModel 2.0
-import QtQuick.Controls.Styles 1.4
-
-import "../../windows"
-import "../../js/Utils.js" as Utils
-import "../models"
-
-ModalWindow {
- id: root
- resizable: true
- width: 640
- height: 480
-
- property var result;
-
- signal selected(var modelUrl);
- signal canceled();
-
- Rectangle {
- anchors.fill: parent
- color: "white"
-
- Item {
- anchors { fill: parent; margins: 8 }
-
- TextField {
- id: filterEdit
- anchors { left: parent.left; right: parent.right; top: parent.top }
- style: TextFieldStyle { renderType: Text.QtRendering }
- placeholderText: "filter"
- onTextChanged: tableView.model.filter = text
- }
-
- TableView {
- id: tableView
- anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; topMargin: 8; bottom: buttonRow.top; bottomMargin: 8 }
- model: S3Model{}
- onCurrentRowChanged: {
- if (currentRow == -1) {
- root.result = null;
- return;
- }
- result = model.baseUrl + "/" + model.get(tableView.currentRow).key;
- }
- itemDelegate: Component {
- Item {
- clip: true
- Text {
- x: 3
- anchors.verticalCenter: parent.verticalCenter
- color: tableView.activeFocus && styleData.row === tableView.currentRow ? "yellow" : styleData.textColor
- elide: styleData.elideMode
- text: getText()
-
- function getText() {
- switch(styleData.column) {
- case 1:
- return Utils.formatSize(styleData.value)
- default:
- return styleData.value;
- }
- }
-
- }
- }
- }
- TableViewColumn {
- role: "name"
- title: "Name"
- width: 200
- }
- TableViewColumn {
- role: "size"
- title: "Size"
- width: 100
- }
- TableViewColumn {
- role: "modified"
- title: "Last Modified"
- width: 200
- }
- Rectangle {
- anchors.fill: parent
- visible: tableView.model.status !== XmlListModel.Ready
- color: "#7fffffff"
- BusyIndicator {
- anchors.centerIn: parent
- width: 48; height: 48
- running: true
- }
- }
- }
-
- Row {
- id: buttonRow
- anchors { right: parent.right; bottom: parent.bottom }
- Button { action: acceptAction }
- Button { action: cancelAction }
- }
-
- Action {
- id: acceptAction
- text: qsTr("OK")
- enabled: root.result ? true : false
- shortcut: "Return"
- onTriggered: {
- root.selected(root.result);
- root.destroy();
- }
- }
-
- Action {
- id: cancelAction
- text: qsTr("Cancel")
- shortcut: "Esc"
- onTriggered: {
- root.canceled();
- root.destroy();
- }
- }
- }
-
- }
-}
-
-
-
-
diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml
deleted file mode 100644
index 54270c2d06..0000000000
--- a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml
+++ /dev/null
@@ -1,230 +0,0 @@
-import QtQuick 2.5
-
-import "."
-import ".."
-import "../../tablet"
-import "../../../styles-uit"
-import "../../../controls-uit" as HifiControls
-import "../../../windows"
-
-Item {
- height: column.height + 2 * 8
-
- property var attachment;
-
- HifiConstants { id: hifi }
-
- signal selectAttachment();
- signal deleteAttachment(var attachment);
- signal updateAttachment();
- property bool completed: false;
-
- function doSelectAttachment(control, focus) {
- if (focus) {
- selectAttachment();
-
- // Refocus control after possibly changing focus to attachment.
- if (control.setControlFocus !== undefined) {
- control.setControlFocus();
- } else {
- control.focus = true;
- }
- }
- }
-
- Rectangle { color: hifi.colors.baseGray; anchors.fill: parent; radius: 4 }
-
- Component.onCompleted: {
- jointChooser.model = MyAvatar.jointNames;
- completed = true;
- }
-
- Column {
- y: 8
- id: column
- anchors { left: parent.left; right: parent.right; margins: 20 }
- spacing: 8
-
- Item {
- height: modelChooserButton.height + urlLabel.height + 4
- anchors { left: parent.left; right: parent.right;}
- HifiControls.Label { id: urlLabel; color: hifi.colors.lightGrayText; text: "Model URL"; anchors.top: parent.top;}
- HifiControls.TextField {
- id: modelUrl;
- height: jointChooser.height;
- colorScheme: hifi.colorSchemes.dark
- anchors { bottom: parent.bottom; left: parent.left; rightMargin: 8; right: modelChooserButton.left }
- text: attachment ? attachment.modelUrl : ""
- onTextChanged: {
- if (completed && attachment && attachment.modelUrl !== text) {
- attachment.modelUrl = text;
- updateAttachment();
- }
- }
- onFocusChanged: doSelectAttachment(this, focus);
- }
- HifiControls.Button {
- id: modelChooserButton;
- text: "Choose";
- color: hifi.buttons.black
- colorScheme: hifi.colorSchemes.dark
- anchors { right: parent.right; verticalCenter: modelUrl.verticalCenter }
- Component {
- id: modelBrowserBuilder;
- ModelBrowserDialog {}
- }
- Component {
- id: tabletModelBrowserBuilder;
- TabletModelBrowserDialog {}
- }
-
- onClicked: {
- var browser;
- if (typeof desktop !== "undefined") {
- browser = modelBrowserBuilder.createObject(desktop);
- browser.selected.connect(function(newModelUrl){
- modelUrl.text = newModelUrl;
- });
- } else {
- browser = tabletModelBrowserBuilder.createObject(tabletRoot);
- browser.selected.connect(function(newModelUrl){
- modelUrl.text = newModelUrl;
- tabletRoot.openModal = null;
- });
- browser.canceled.connect(function() {
- tabletRoot.openModal = null;
- });
-
- // Make dialog modal.
- tabletRoot.openModal = browser;
- }
- }
- }
- }
-
- Item {
- z: 1000
- height: jointChooser.height + jointLabel.height + 4
- anchors { left: parent.left; right: parent.right; }
- HifiControls.Label {
- id: jointLabel;
- text: "Joint";
- color: hifi.colors.lightGrayText;
- anchors.top: parent.top
- }
- HifiControls.ComboBox {
- id: jointChooser;
- dropdownHeight: (typeof desktop !== "undefined") ? 480 : 206
- anchors { bottom: parent.bottom; left: parent.left; right: parent.right }
- colorScheme: hifi.colorSchemes.dark
- currentIndex: attachment ? model.indexOf(attachment.jointName) : -1
- onCurrentIndexChanged: {
- if (completed && attachment && currentIndex != -1 && attachment.jointName !== model[currentIndex]) {
- attachment.jointName = model[currentIndex];
- updateAttachment();
- }
- }
- onFocusChanged: doSelectAttachment(this, focus);
- }
- }
-
- Item {
- height: translation.height + translationLabel.height + 4
- anchors { left: parent.left; right: parent.right; }
- HifiControls.Label { id: translationLabel; color: hifi.colors.lightGrayText; text: "Translation"; anchors.top: parent.top; }
- Translation {
- id: translation;
- anchors { left: parent.left; right: parent.right; bottom: parent.bottom}
- vector: attachment ? attachment.translation : {x: 0, y: 0, z: 0};
- onValueChanged: {
- if (completed && attachment) {
- attachment.translation = vector;
- updateAttachment();
- }
- }
- onControlFocusChanged: doSelectAttachment(this, controlFocus);
- }
- }
-
- Item {
- height: rotation.height + rotationLabel.height + 4
- anchors { left: parent.left; right: parent.right; }
- HifiControls.Label { id: rotationLabel; color: hifi.colors.lightGrayText; text: "Rotation"; anchors.top: parent.top; }
- Rotation {
- id: rotation;
- anchors { left: parent.left; right: parent.right; bottom: parent.bottom; }
- vector: attachment ? attachment.rotation : {x: 0, y: 0, z: 0};
- onValueChanged: {
- if (completed && attachment) {
- attachment.rotation = vector;
- updateAttachment();
- }
- }
- onControlFocusChanged: doSelectAttachment(this, controlFocus);
- }
- }
-
- Item {
- height: scaleItem.height
- anchors { left: parent.left; right: parent.right; }
-
- Item {
- id: scaleItem
- height: scaleSpinner.height + scaleLabel.height + 4
- width: parent.width / 3 - 8
- anchors { right: parent.right; }
- HifiControls.Label { id: scaleLabel; color: hifi.colors.lightGrayText; text: "Scale"; anchors.top: parent.top; }
- HifiControls.SpinBox {
- id: scaleSpinner;
- anchors { left: parent.left; right: parent.right; bottom: parent.bottom; }
- decimals: 2;
- minimumValue: 0.01
- maximumValue: 10
- realStepSize: 0.05;
- realValue: attachment ? attachment.scale : 1.0
- colorScheme: hifi.colorSchemes.dark
- onRealValueChanged: {
- if (completed && attachment && attachment.scale !== realValue) {
- attachment.scale = realValue;
- updateAttachment();
- }
- }
- onFocusChanged: doSelectAttachment(this, focus);
- }
- }
-
- Item {
- id: isSoftItem
- height: scaleSpinner.height
- anchors {
- left: parent.left
- bottom: parent.bottom
- }
- HifiControls.CheckBox {
- id: soft
- text: "Is soft"
- anchors {
- left: parent.left
- verticalCenter: parent.verticalCenter
- }
- checked: attachment ? attachment.soft : false
- colorScheme: hifi.colorSchemes.dark
- onCheckedChanged: {
- if (completed && attachment && attachment.soft !== checked) {
- attachment.soft = checked;
- updateAttachment();
- }
- }
- onFocusChanged: doSelectAttachment(this, focus);
- }
- }
- }
- HifiControls.Button {
- color: hifi.buttons.black
- colorScheme: hifi.colorSchemes.dark
- anchors { left: parent.left; right: parent.right; }
- text: "Delete"
- onClicked: deleteAttachment(root.attachment);
- }
- }
-}
diff --git a/interface/resources/qml/hifi/dialogs/attachments/Rotation.qml b/interface/resources/qml/hifi/dialogs/attachments/Rotation.qml
deleted file mode 100644
index 6061efc4c8..0000000000
--- a/interface/resources/qml/hifi/dialogs/attachments/Rotation.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import "."
-
-Vector3 {
- decimals: 1;
- stepSize: 1;
- maximumValue: 180
- minimumValue: -180
-}
-
diff --git a/interface/resources/qml/hifi/dialogs/attachments/Translation.qml b/interface/resources/qml/hifi/dialogs/attachments/Translation.qml
deleted file mode 100644
index 39ac6da55a..0000000000
--- a/interface/resources/qml/hifi/dialogs/attachments/Translation.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import "."
-
-Vector3 {
- decimals: 3;
- stepSize: 0.01;
- maximumValue: 10
- minimumValue: -10
-}
-
diff --git a/interface/resources/qml/hifi/dialogs/attachments/Vector3.qml b/interface/resources/qml/hifi/dialogs/attachments/Vector3.qml
deleted file mode 100644
index 311492858b..0000000000
--- a/interface/resources/qml/hifi/dialogs/attachments/Vector3.qml
+++ /dev/null
@@ -1,112 +0,0 @@
-import QtQuick 2.5
-
-import "../../../styles-uit"
-import "../../../controls-uit" as HifiControls
-import "../../../windows"
-
-Item {
- id: root
- implicitHeight: xspinner.height
- readonly property real spacing: 8
- property real spinboxWidth: (width / 3) - spacing
- property var vector;
- property real decimals: 0
- property real stepSize: 1
- property real maximumValue: 99
- property real minimumValue: 0
- property bool controlFocus: false; // True if one of the ordinate controls has focus.
- property var controlFocusControl: undefined
-
- signal valueChanged();
-
- function setControlFocus() {
- if (controlFocusControl) {
- controlFocusControl.focus = true;
- // The controlFocus value is updated via onFocusChanged.
- }
- }
-
- function setFocus(control, focus) {
- if (focus) {
- controlFocusControl = control;
- setControlFocusTrue.start(); // After any subsequent false from previous control.
- } else {
- controlFocus = false;
- }
- }
-
- Timer {
- id: setControlFocusTrue
- interval: 50
- repeat: false
- running: false
- onTriggered: {
- controlFocus = true;
- }
- }
-
- HifiConstants { id: hifi }
-
- HifiControls.SpinBox {
- id: xspinner
- width: root.spinboxWidth
- anchors { left: parent.left }
- realValue: root.vector.x
- labelInside: "X:"
- colorScheme: hifi.colorSchemes.dark
- colorLabelInside: hifi.colors.redHighlight
- decimals: root.decimals
- realStepSize: root.stepSize
- maximumValue: root.maximumValue
- minimumValue: root.minimumValue
- onRealValueChanged: {
- if (realValue !== vector.x) {
- vector.x = realValue
- root.valueChanged();
- }
- }
- onFocusChanged: setFocus(this, focus);
- }
-
- HifiControls.SpinBox {
- id: yspinner
- width: root.spinboxWidth
- anchors { horizontalCenter: parent.horizontalCenter }
- realValue: root.vector.y
- labelInside: "Y:"
- colorLabelInside: hifi.colors.greenHighlight
- colorScheme: hifi.colorSchemes.dark
- decimals: root.decimals
- realStepSize: root.stepSize
- maximumValue: root.maximumValue
- minimumValue: root.minimumValue
- onRealValueChanged: {
- if (realValue !== vector.y) {
- vector.y = realValue
- root.valueChanged();
- }
- }
- onFocusChanged: setFocus(this, focus);
- }
-
- HifiControls.SpinBox {
- id: zspinner
- width: root.spinboxWidth
- anchors { right: parent.right; }
- realValue: root.vector.z
- labelInside: "Z:"
- colorLabelInside: hifi.colors.primaryHighlight
- colorScheme: hifi.colorSchemes.dark
- decimals: root.decimals
- realStepSize: root.stepSize
- maximumValue: root.maximumValue
- minimumValue: root.minimumValue
- onRealValueChanged: {
- if (realValue !== vector.z) {
- vector.z = realValue
- root.valueChanged();
- }
- }
- onFocusChanged: setFocus(this, focus);
- }
-}
diff --git a/interface/resources/qml/hifi/dialogs/content/AttachmentsContent.qml b/interface/resources/qml/hifi/dialogs/content/AttachmentsContent.qml
deleted file mode 100644
index fa71116574..0000000000
--- a/interface/resources/qml/hifi/dialogs/content/AttachmentsContent.qml
+++ /dev/null
@@ -1,282 +0,0 @@
-import QtQuick 2.7
-import QtQuick.Controls 2.3
-import QtQuick.Dialogs 1.2 as OriginalDialogs
-
-import "../../../styles-uit"
-import "../../../controls-uit" as HifiControls
-import "../../../windows"
-import "../attachments"
-
-Item {
- id: content
-
- readonly property var originalAttachments: MyAvatar.getAttachmentsVariant();
- property var attachments: [];
-
- function reload(){
- content.attachments = [];
- var currentAttachments = MyAvatar.getAttachmentsVariant();
- listView.model.clear();
- for (var i = 0; i < currentAttachments.length; ++i) {
- var attachment = currentAttachments[i];
- content.attachments.push(attachment);
- listView.model.append({});
- }
- }
-
- Connections {
- id: onAttachmentsChangedConnection
- target: MyAvatar
- onAttachmentsChanged: reload()
- }
-
- Component.onCompleted: {
- reload()
- }
-
- function setAttachmentsVariant(attachments) {
- onAttachmentsChangedConnection.enabled = false;
- MyAvatar.setAttachmentsVariant(attachments);
- onAttachmentsChangedConnection.enabled = true;
- }
-
- Column {
- width: pane.width
-
- Rectangle {
- width: parent.width
- height: root.height - (keyboardEnabled && keyboardRaised ? 200 : 0)
- color: hifi.colors.baseGray
-
- Rectangle {
- id: attachmentsBackground
- anchors {
- left: parent.left; right: parent.right; top: parent.top; bottom: newAttachmentButton.top;
- margins: hifi.dimensions.contentMargin.x
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- color: hifi.colors.baseGrayShadow
- radius: 4
-
- ListView {
- id: listView
- anchors {
- top: parent.top
- left: parent.left
- right: scrollBar.left
- bottom: parent.bottom
- margins: 4
- }
- clip: true
- cacheBuffer: 4000
-
- model: ListModel {}
- delegate: Item {
- id: attachmentDelegate
- implicitHeight: attachmentView.height + 8;
- implicitWidth: attachmentView.width
-
- MouseArea {
- // User can click on whitespace to select item.
- anchors.fill: parent
- propagateComposedEvents: true
- onClicked: {
- listView.currentIndex = index;
- attachmentsBackground.forceActiveFocus(); // Unfocus from any control.
- mouse.accepted = false;
- }
- }
-
- Attachment {
- id: attachmentView
- width: listView.width
- attachment: content.attachments[index]
- onSelectAttachment: {
- listView.currentIndex = index;
- }
- onDeleteAttachment: {
- attachments.splice(index, 1);
- listView.model.remove(index, 1);
- }
- onUpdateAttachment: {
- setAttachmentsVariant(attachments);
- }
- }
- }
-
- onCountChanged: {
- setAttachmentsVariant(attachments);
- }
-
- /*
- // DEBUG
- highlight: Rectangle { color: "#40ffff00" }
- highlightFollowsCurrentItem: true
- */
-
- onHeightChanged: {
- // Keyboard has been raised / lowered.
- positionViewAtIndex(listView.currentIndex, ListView.SnapPosition);
- }
-
- onCurrentIndexChanged: {
- if (!yScrollTimer.running) {
- scrollSlider.y = currentIndex * (scrollBar.height - scrollSlider.height) / (listView.count - 1);
- }
- }
-
- onContentYChanged: {
- // User may have dragged content up/down.
- yScrollTimer.restart();
- }
-
- Timer {
- id: yScrollTimer
- interval: 200
- repeat: false
- running: false
- onTriggered: {
- var index = (listView.count - 1) * listView.contentY / (listView.contentHeight - scrollBar.height);
- index = Math.round(index);
- listView.currentIndex = index;
- scrollSlider.y = index * (scrollBar.height - scrollSlider.height) / (listView.count - 1);
- }
- }
- }
-
- Rectangle {
- id: scrollBar
-
- property bool scrolling: listView.contentHeight > listView.height
-
- anchors {
- top: parent.top
- right: parent.right
- bottom: parent.bottom
- topMargin: 4
- bottomMargin: 4
- }
- width: scrolling ? 18 : 0
- radius: attachmentsBackground.radius
- color: hifi.colors.baseGrayShadow
-
- MouseArea {
- anchors.fill: parent
-
- onClicked: {
- var index = listView.currentIndex;
- index = index + (mouse.y <= scrollSlider.y ? -1 : 1);
- if (index < 0) {
- index = 0;
- }
- if (index > listView.count - 1) {
- index = listView.count - 1;
- }
- listView.currentIndex = index;
- }
- }
-
- Rectangle {
- id: scrollSlider
- anchors {
- right: parent.right
- rightMargin: 3
- }
- width: 16
- height: (listView.height / listView.contentHeight) * listView.height
- radius: width / 2
- color: hifi.colors.lightGray
-
- visible: scrollBar.scrolling;
-
- onYChanged: {
- var index = y * (listView.count - 1) / (scrollBar.height - scrollSlider.height);
- index = Math.round(index);
- listView.currentIndex = index;
- }
-
- MouseArea {
- anchors.fill: parent
- drag.target: scrollSlider
- drag.axis: Drag.YAxis
- drag.minimumY: 0
- drag.maximumY: scrollBar.height - scrollSlider.height
- }
- }
- }
- }
-
- HifiControls.Button {
- id: newAttachmentButton
- anchors {
- left: parent.left
- right: parent.right
- bottom: buttonRow.top
- margins: hifi.dimensions.contentMargin.x;
- topMargin: hifi.dimensions.contentSpacing.y
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- text: "New Attachment"
- color: hifi.buttons.black
- colorScheme: hifi.colorSchemes.dark
- onClicked: {
- var template = {
- modelUrl: "",
- translation: { x: 0, y: 0, z: 0 },
- rotation: { x: 0, y: 0, z: 0 },
- scale: 1,
- jointName: MyAvatar.jointNames[0],
- soft: false
- };
- attachments.push(template);
- listView.model.append({});
- setAttachmentsVariant(attachments);
- }
- }
-
- Row {
- id: buttonRow
- spacing: 8
- anchors {
- right: parent.right
- bottom: parent.bottom
- margins: hifi.dimensions.contentMargin.x
- topMargin: hifi.dimensions.contentSpacing.y
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- HifiControls.Button {
- action: okAction
- color: hifi.buttons.black
- colorScheme: hifi.colorSchemes.dark
- }
- HifiControls.Button {
- action: cancelAction
- color: hifi.buttons.black
- colorScheme: hifi.colorSchemes.dark
- }
- }
-
- Action {
- id: cancelAction
- text: "Cancel"
- onTriggered: {
- setAttachmentsVariant(originalAttachments);
- closeDialog();
- }
- }
-
- Action {
- id: okAction
- text: "OK"
- onTriggered: {
- for (var i = 0; i < attachments.length; ++i) {
- console.log("Attachment " + i + ": " + attachments[i]);
- }
-
- setAttachmentsVariant(attachments);
- closeDialog();
- }
- }
- }
- }
-}
diff --git a/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml b/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml
deleted file mode 100644
index 7e1cdea0db..0000000000
--- a/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// TabletAttachmentsDialog.qml
-//
-// Created by David Rowe on 9 Mar 2017.
-// Copyright 2017 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import QtQuick 2.5
-
-import "../../controls-uit" as HifiControls
-import "../../styles-uit"
-import "../dialogs/content"
-
-Item {
- id: root
- objectName: "AttachmentsDialog"
-
- property string title: "Avatar Attachments"
-
- property bool keyboardEnabled: false
- property bool keyboardRaised: false
- property bool punctuationMode: false
-
- signal sendToScript(var message);
-
- anchors.fill: parent
-
- HifiConstants { id: hifi }
-
- Rectangle {
- id: pane // Surrogate for ScrollingWindow's pane.
- anchors.fill: parent
- }
-
- function closeDialog() {
- Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen();
- }
-
- anchors.topMargin: hifi.dimensions.tabletMenuHeader // Space for header.
-
- HifiControls.TabletHeader {
- id: header
- title: root.title
-
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.top
- }
- }
-
- AttachmentsContent {
- id: attachments
-
- anchors {
- top: header.bottom
- left: parent.left
- right: parent.right
- bottom: keyboard.top
- }
-
- MouseArea {
- // Defocuses any current control so that the keyboard gets hidden.
- id: defocuser
- anchors.fill: parent
- propagateComposedEvents: true
- acceptedButtons: Qt.AllButtons
- onPressed: {
- parent.forceActiveFocus();
- mouse.accepted = false;
- }
- }
- }
-
- HifiControls.Keyboard {
- id: keyboard
- raised: parent.keyboardEnabled && parent.keyboardRaised
- numeric: parent.punctuationMode
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- }
-
- MouseArea {
- id: activator
- anchors.fill: parent
- propagateComposedEvents: true
- enabled: true
- acceptedButtons: Qt.AllButtons
- onPressed: {
- mouse.accepted = false;
- }
- }
-
- Component.onCompleted: {
- keyboardEnabled = HMD.active;
- }
-}
diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp
index 6afab71c90..4119b843e1 100644
--- a/interface/src/AvatarBookmarks.cpp
+++ b/interface/src/AvatarBookmarks.cpp
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -35,7 +36,7 @@
#include "QVariantGLM.h"
#include
-
+#include
void addAvatarEntities(const QVariantList& avatarEntities) {
auto nodeList = DependencyManager::get();
@@ -145,8 +146,8 @@ void AvatarBookmarks::removeBookmark(const QString& bookmarkName) {
}
bool isWearableEntity(const EntityItemPointer& entity) {
- return entity->isVisible() && entity->getParentJointIndex() != INVALID_JOINT_INDEX &&
- (entity->getParentID() == DependencyManager::get()->getSessionUUID() || entity->getParentID() == DependencyManager::get()->getMyAvatar()->getSelfID());
+ return entity->isVisible() && (entity->getParentJointIndex() != INVALID_JOINT_INDEX || (entity->getType() == EntityTypes::Model && (std::static_pointer_cast(entity))->getRelayParentJoints()))
+ && (entity->getParentID() == DependencyManager::get()->getSessionUUID() || entity->getParentID() == DependencyManager::get()->getMyAvatar()->getSelfID());
}
void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
@@ -254,7 +255,6 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
- bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
QScriptEngine scriptEngine;
QVariantList wearableEntities;
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 2c364154f7..fe7083ea30 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -277,13 +277,6 @@ Menu::Menu() {
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
});
- // Settings > Attachments...
- action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Attachments);
- connect(action, &QAction::triggered, [] {
- qApp->showDialog(QString("hifi/dialogs/AttachmentsDialog.qml"),
- QString("hifi/tablet/TabletAttachmentsDialog.qml"), "AttachmentsDialog");
- });
-
// Settings > Developer Menu
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index a4fc283d54..c489a3f0b0 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -36,7 +36,6 @@ namespace MenuOption {
const QString AskToResetSettings = "Ask To Reset Settings on Start";
const QString AssetMigration = "ATP Asset Migration";
const QString AssetServer = "Asset Browser";
- const QString Attachments = "Attachments...";
const QString AudioScope = "Show Scope";
const QString AudioScopeFiftyFrames = "Fifty";
const QString AudioScopeFiveFrames = "Five";
diff --git a/scripts/system/avatarapp.js b/scripts/system/avatarapp.js
index 03b7b3969d..10ccb66d96 100644
--- a/scripts/system/avatarapp.js
+++ b/scripts/system/avatarapp.js
@@ -20,7 +20,6 @@ Script.include("/~/system/libraries/controllers.js");
// constants from AvatarBookmarks.h
var ENTRY_AVATAR_URL = "avatarUrl";
-var ENTRY_AVATAR_ATTACHMENTS = "attachments";
var ENTRY_AVATAR_ENTITIES = "avatarEntites";
var ENTRY_AVATAR_SCALE = "avatarScale";
var ENTRY_VERSION = "version";
@@ -31,7 +30,7 @@ function executeLater(callback) {
var INVALID_JOINT_INDEX = -1
function isWearable(avatarEntity) {
- return avatarEntity.properties.visible === true && avatarEntity.properties.parentJointIndex !== INVALID_JOINT_INDEX &&
+ return avatarEntity.properties.visible === true && (avatarEntity.properties.parentJointIndex !== INVALID_JOINT_INDEX || avatarEntity.properties.relayParentJoints === true) &&
(avatarEntity.properties.parentID === MyAvatar.sessionUUID || avatarEntity.properties.parentID === MyAvatar.SELF_ID);
}
@@ -57,7 +56,6 @@ function getMyAvatar() {
var avatar = {}
avatar[ENTRY_AVATAR_URL] = MyAvatar.skeletonModelURL;
avatar[ENTRY_AVATAR_SCALE] = MyAvatar.getAvatarScale();
- avatar[ENTRY_AVATAR_ATTACHMENTS] = MyAvatar.getAttachmentsVariant();
avatar[ENTRY_AVATAR_ENTITIES] = getMyAvatarWearables();
return avatar;
}
@@ -72,12 +70,15 @@ function getMyAvatarSettings() {
}
}
-function updateAvatarWearables(avatar, bookmarkAvatarName) {
+function updateAvatarWearables(avatar, bookmarkAvatarName, callback) {
executeLater(function() {
var wearables = getMyAvatarWearables();
avatar[ENTRY_AVATAR_ENTITIES] = wearables;
sendToQml({'method' : 'wearablesUpdated', 'wearables' : wearables, 'avatarName' : bookmarkAvatarName})
+
+ if(callback)
+ callback();
});
}
@@ -235,6 +236,32 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
Messages.messageReceived.disconnect(handleWearableMessages);
Messages.unsubscribe('Hifi-Object-Manipulation');
break;
+ case 'addWearable':
+
+ var joints = MyAvatar.getJointNames();
+ var hipsIndex = -1;
+
+ for(var i = 0; i < joints.length; ++i) {
+ if(joints[i] === 'Hips') {
+ hipsIndex = i;
+ break;
+ }
+ }
+
+ var properties = {
+ name: "Custom wearable",
+ type: "Model",
+ modelURL: message.url,
+ parentID: MyAvatar.sessionUUID,
+ relayParentJoints: false,
+ parentJointIndex: hipsIndex
+ };
+
+ var entityID = Entities.addEntity(properties, true);
+ updateAvatarWearables(currentAvatar, message.avatarName, function() {
+ onSelectedEntity(entityID);
+ });
+ break;
case 'selectWearable':
ensureWearableSelected(message.entityID);
break;