mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 07:37:20 +02:00
Merge pull request #13782 from ElderOrb/FB17184
Add Support for Managing Avatar Entities to the Avatar App
This commit is contained in:
commit
32562511e8
24 changed files with 442 additions and 1140 deletions
|
@ -103,7 +103,7 @@ FocusScope {
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
size: hifi.fontSizes.textFieldInput
|
size: hifi.fontSizes.textFieldInput
|
||||||
text: comboBox.currentText
|
text: comboBox.displayText ? comboBox.displayText : comboBox.currentText
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
|
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ SpinBox {
|
||||||
id: hifi
|
id: hifi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||||
property int colorScheme: hifi.colorSchemes.light
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
|
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
|
||||||
property string label: ""
|
property string label: ""
|
||||||
|
@ -91,7 +92,6 @@ SpinBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
valueFromText: function(text, locale) {
|
valueFromText: function(text, locale) {
|
||||||
spinBox.value = 0; // Force valueChanged signal to be emitted so that validator fires.
|
|
||||||
return Number.fromLocaleString(locale, text)*factor;
|
return Number.fromLocaleString(locale, text)*factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ SpinBox {
|
||||||
selectedTextColor: hifi.colors.black
|
selectedTextColor: hifi.colors.black
|
||||||
selectionColor: hifi.colors.primaryHighlight
|
selectionColor: hifi.colors.primaryHighlight
|
||||||
text: spinBox.textFromValue(spinBox.value, spinBox.locale) + suffix
|
text: spinBox.textFromValue(spinBox.value, spinBox.locale) + suffix
|
||||||
|
inputMethodHints: spinBox.inputMethodHints
|
||||||
|
validator: spinBox.validator
|
||||||
verticalAlignment: Qt.AlignVCenter
|
verticalAlignment: Qt.AlignVCenter
|
||||||
leftPadding: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
|
leftPadding: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
|
||||||
//rightPadding: hifi.dimensions.spinnerSize
|
//rightPadding: hifi.dimensions.spinnerSize
|
||||||
|
|
|
@ -57,7 +57,7 @@ Rectangle {
|
||||||
try {
|
try {
|
||||||
var marketResponse = JSON.parse(xmlhttp.responseText.trim())
|
var marketResponse = JSON.parse(xmlhttp.responseText.trim())
|
||||||
|
|
||||||
if(marketResponse.status === 'success') {
|
if (marketResponse.status === 'success') {
|
||||||
avatar.modelName = marketResponse.data.title;
|
avatar.modelName = marketResponse.data.title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,14 +72,14 @@ Rectangle {
|
||||||
|
|
||||||
function getAvatarModelName() {
|
function getAvatarModelName() {
|
||||||
|
|
||||||
if(currentAvatar === null) {
|
if (currentAvatar === null) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if(currentAvatar.modelName !== undefined) {
|
if (currentAvatar.modelName !== undefined) {
|
||||||
return currentAvatar.modelName;
|
return currentAvatar.modelName;
|
||||||
} else {
|
} else {
|
||||||
var marketId = allAvatars.extractMarketId(currentAvatar.avatarUrl);
|
var marketId = allAvatars.extractMarketId(currentAvatar.avatarUrl);
|
||||||
if(marketId !== '') {
|
if (marketId !== '') {
|
||||||
fetchAvatarModelName(marketId, currentAvatar);
|
fetchAvatarModelName(marketId, currentAvatar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,51 +103,51 @@ Rectangle {
|
||||||
property url externalAvatarThumbnailUrl: '../../images/avatarapp/guy-in-circle.svg'
|
property url externalAvatarThumbnailUrl: '../../images/avatarapp/guy-in-circle.svg'
|
||||||
|
|
||||||
function fromScript(message) {
|
function fromScript(message) {
|
||||||
if(message.method === 'initialize') {
|
if (message.method === 'initialize') {
|
||||||
jointNames = message.data.jointNames;
|
jointNames = message.data.jointNames;
|
||||||
emitSendToScript({'method' : getAvatarsMethod});
|
emitSendToScript({'method' : getAvatarsMethod});
|
||||||
} else if(message.method === 'wearableUpdated') {
|
} else if (message.method === 'wearableUpdated') {
|
||||||
adjustWearables.refreshWearable(message.entityID, message.wearableIndex, message.properties, message.updateUI);
|
adjustWearables.refreshWearable(message.entityID, message.wearableIndex, message.properties, message.updateUI);
|
||||||
} else if(message.method === 'wearablesUpdated') {
|
} else if (message.method === 'wearablesUpdated') {
|
||||||
var wearablesModel = currentAvatar.wearables;
|
var wearablesModel = currentAvatar.wearables;
|
||||||
wearablesModel.clear();
|
wearablesModel.clear();
|
||||||
message.wearables.forEach(function(wearable) {
|
message.wearables.forEach(function(wearable) {
|
||||||
wearablesModel.append(wearable);
|
wearablesModel.append(wearable);
|
||||||
});
|
});
|
||||||
adjustWearables.refresh(currentAvatar);
|
adjustWearables.refresh(currentAvatar);
|
||||||
} else if(message.method === 'scaleChanged') {
|
} else if (message.method === 'scaleChanged') {
|
||||||
currentAvatar.avatarScale = message.value;
|
currentAvatar.avatarScale = message.value;
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
updateCurrentAvatarInBookmarks(currentAvatar);
|
||||||
} else if(message.method === 'externalAvatarApplied') {
|
} else if (message.method === 'externalAvatarApplied') {
|
||||||
currentAvatar.avatarUrl = message.avatarURL;
|
currentAvatar.avatarUrl = message.avatarURL;
|
||||||
currentAvatar.thumbnailUrl = allAvatars.makeThumbnailUrl(message.avatarURL);
|
currentAvatar.thumbnailUrl = allAvatars.makeThumbnailUrl(message.avatarURL);
|
||||||
currentAvatar.entry.avatarUrl = currentAvatar.avatarUrl;
|
currentAvatar.entry.avatarUrl = currentAvatar.avatarUrl;
|
||||||
currentAvatar.modelName = undefined;
|
currentAvatar.modelName = undefined;
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
updateCurrentAvatarInBookmarks(currentAvatar);
|
||||||
} else if(message.method === 'settingChanged') {
|
} else if (message.method === 'settingChanged') {
|
||||||
currentAvatarSettings[message.name] = message.value;
|
currentAvatarSettings[message.name] = message.value;
|
||||||
} else if(message.method === 'changeSettings') {
|
} else if (message.method === 'changeSettings') {
|
||||||
currentAvatarSettings = message.settings;
|
currentAvatarSettings = message.settings;
|
||||||
} else if(message.method === 'bookmarkLoaded') {
|
} else if (message.method === 'bookmarkLoaded') {
|
||||||
setCurrentAvatar(message.data.currentAvatar, message.data.name);
|
setCurrentAvatar(message.data.currentAvatar, message.data.name);
|
||||||
var avatarIndex = allAvatars.findAvatarIndex(currentAvatar.name);
|
var avatarIndex = allAvatars.findAvatarIndex(currentAvatar.name);
|
||||||
allAvatars.move(avatarIndex, 0, 1);
|
allAvatars.move(avatarIndex, 0, 1);
|
||||||
view.setPage(0);
|
view.setPage(0);
|
||||||
} else if(message.method === 'bookmarkAdded') {
|
} else if (message.method === 'bookmarkAdded') {
|
||||||
var avatar = allAvatars.findAvatar(message.bookmarkName);
|
var avatar = allAvatars.findAvatar(message.bookmarkName);
|
||||||
if(avatar !== undefined) {
|
if (avatar !== undefined) {
|
||||||
var avatarObject = allAvatars.makeAvatarObject(message.bookmark, message.bookmarkName);
|
var avatarObject = allAvatars.makeAvatarObject(message.bookmark, message.bookmarkName);
|
||||||
for(var prop in avatarObject) {
|
for(var prop in avatarObject) {
|
||||||
avatar[prop] = avatarObject[prop];
|
avatar[prop] = avatarObject[prop];
|
||||||
}
|
}
|
||||||
if(currentAvatar.name === message.bookmarkName) {
|
if (currentAvatar.name === message.bookmarkName) {
|
||||||
currentAvatar = currentAvatarModel.makeAvatarEntry(avatarObject);
|
currentAvatar = currentAvatarModel.makeAvatarEntry(avatarObject);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allAvatars.addAvatarEntry(message.bookmark, message.bookmarkName);
|
allAvatars.addAvatarEntry(message.bookmark, message.bookmarkName);
|
||||||
}
|
}
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
updateCurrentAvatarInBookmarks(currentAvatar);
|
||||||
} else if(message.method === 'bookmarkDeleted') {
|
} else if (message.method === 'bookmarkDeleted') {
|
||||||
pageOfAvatars.isUpdating = true;
|
pageOfAvatars.isUpdating = true;
|
||||||
|
|
||||||
var index = pageOfAvatars.findAvatarIndex(message.name);
|
var index = pageOfAvatars.findAvatarIndex(message.name);
|
||||||
|
@ -159,15 +159,16 @@ Rectangle {
|
||||||
var itemsOnPage = pageOfAvatars.count;
|
var itemsOnPage = pageOfAvatars.count;
|
||||||
var newItemIndex = view.currentPage * view.itemsPerPage + itemsOnPage;
|
var newItemIndex = view.currentPage * view.itemsPerPage + itemsOnPage;
|
||||||
|
|
||||||
if(newItemIndex <= (allAvatars.count - 1)) {
|
if (newItemIndex <= (allAvatars.count - 1)) {
|
||||||
pageOfAvatars.append(allAvatars.get(newItemIndex));
|
pageOfAvatars.append(allAvatars.get(newItemIndex));
|
||||||
} else {
|
} else {
|
||||||
if(!pageOfAvatars.hasGetAvatars())
|
if (!pageOfAvatars.hasGetAvatars()) {
|
||||||
pageOfAvatars.appendGetAvatars();
|
pageOfAvatars.appendGetAvatars();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pageOfAvatars.isUpdating = false;
|
pageOfAvatars.isUpdating = false;
|
||||||
} else if(message.method === getAvatarsMethod) {
|
} else if (message.method === getAvatarsMethod) {
|
||||||
var getAvatarsData = message.data;
|
var getAvatarsData = message.data;
|
||||||
allAvatars.populate(getAvatarsData.bookmarks);
|
allAvatars.populate(getAvatarsData.bookmarks);
|
||||||
setCurrentAvatar(getAvatarsData.currentAvatar, '');
|
setCurrentAvatar(getAvatarsData.currentAvatar, '');
|
||||||
|
@ -175,16 +176,16 @@ Rectangle {
|
||||||
currentAvatarSettings = getAvatarsData.currentAvatarSettings;
|
currentAvatarSettings = getAvatarsData.currentAvatarSettings;
|
||||||
|
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
updateCurrentAvatarInBookmarks(currentAvatar);
|
||||||
} else if(message.method === 'updateAvatarInBookmarks') {
|
} else if (message.method === 'updateAvatarInBookmarks') {
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
updateCurrentAvatarInBookmarks(currentAvatar);
|
||||||
} else if(message.method === 'selectAvatarEntity') {
|
} else if (message.method === 'selectAvatarEntity') {
|
||||||
adjustWearables.selectWearableByID(message.entityID);
|
adjustWearables.selectWearableByID(message.entityID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCurrentAvatarInBookmarks(avatar) {
|
function updateCurrentAvatarInBookmarks(avatar) {
|
||||||
var bookmarkAvatarIndex = allAvatars.findAvatarIndexByValue(avatar);
|
var bookmarkAvatarIndex = allAvatars.findAvatarIndexByValue(avatar);
|
||||||
if(bookmarkAvatarIndex === -1) {
|
if (bookmarkAvatarIndex === -1) {
|
||||||
avatar.name = '';
|
avatar.name = '';
|
||||||
view.setPage(0);
|
view.setPage(0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -285,6 +286,9 @@ Rectangle {
|
||||||
onWearableSelected: {
|
onWearableSelected: {
|
||||||
emitSendToScript({'method' : 'selectWearable', 'entityID' : id});
|
emitSendToScript({'method' : 'selectWearable', 'entityID' : id});
|
||||||
}
|
}
|
||||||
|
onAddWearable: {
|
||||||
|
emitSendToScript({'method' : 'addWearable', 'avatarName' : avatarName, 'url' : url});
|
||||||
|
}
|
||||||
|
|
||||||
z: 3
|
z: 3
|
||||||
}
|
}
|
||||||
|
@ -491,33 +495,10 @@ Rectangle {
|
||||||
anchors.verticalCenter: wearablesLabel.verticalCenter
|
anchors.verticalCenter: wearablesLabel.verticalCenter
|
||||||
glyphText: "\ue02e"
|
glyphText: "\ue02e"
|
||||||
|
|
||||||
visible: avatarWearablesCount !== 0
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
adjustWearables.open(currentAvatar);
|
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 {
|
Rectangle {
|
||||||
|
@ -617,8 +598,9 @@ Rectangle {
|
||||||
pageOfAvatars.append(avatarItem);
|
pageOfAvatars.append(avatarItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pageOfAvatars.count !== itemsPerPage)
|
if (pageOfAvatars.count !== itemsPerPage) {
|
||||||
pageOfAvatars.appendGetAvatars();
|
pageOfAvatars.appendGetAvatars();
|
||||||
|
}
|
||||||
|
|
||||||
currentPage = pageIndex;
|
currentPage = pageIndex;
|
||||||
pageOfAvatars.isUpdating = false;
|
pageOfAvatars.isUpdating = false;
|
||||||
|
@ -639,7 +621,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeGetAvatars() {
|
function removeGetAvatars() {
|
||||||
if(hasGetAvatars()) {
|
if (hasGetAvatars()) {
|
||||||
remove(count - 1)
|
remove(count - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,13 +689,13 @@ Rectangle {
|
||||||
hoverEnabled: enabled
|
hoverEnabled: enabled
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if(isInManageState) {
|
if (isInManageState) {
|
||||||
var currentItem = delegateRoot.GridView.view.model.get(index);
|
var currentItem = delegateRoot.GridView.view.model.get(index);
|
||||||
popup.showDeleteFavorite(currentItem.name, function() {
|
popup.showDeleteFavorite(currentItem.name, function() {
|
||||||
view.deleteAvatar(currentItem);
|
view.deleteAvatar(currentItem);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if(delegateRoot.GridView.view.currentIndex !== index) {
|
if (delegateRoot.GridView.view.currentIndex !== index) {
|
||||||
var currentItem = delegateRoot.GridView.view.model.get(index);
|
var currentItem = delegateRoot.GridView.view.model.get(index);
|
||||||
popup.showLoadFavorite(currentItem.name, function() {
|
popup.showLoadFavorite(currentItem.name, function() {
|
||||||
view.selectAvatar(currentItem);
|
view.selectAvatar(currentItem);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Hifi 1.0 as Hifi
|
import Hifi 1.0 as Hifi
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
import "../../styles-uit"
|
import "../../styles-uit"
|
||||||
import "../../controls-uit" as HifiControlsUit
|
import "../../controls-uit" as HifiControlsUit
|
||||||
import "../../controls" as HifiControls
|
import "../../controls" as HifiControls
|
||||||
|
@ -17,6 +18,7 @@ Rectangle {
|
||||||
|
|
||||||
signal adjustWearablesOpened(var avatarName);
|
signal adjustWearablesOpened(var avatarName);
|
||||||
signal adjustWearablesClosed(bool status, var avatarName);
|
signal adjustWearablesClosed(bool status, var avatarName);
|
||||||
|
signal addWearable(string avatarName, string url);
|
||||||
|
|
||||||
property bool modified: false;
|
property bool modified: false;
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
@ -30,6 +32,7 @@ Rectangle {
|
||||||
function open(avatar) {
|
function open(avatar) {
|
||||||
adjustWearablesOpened(avatar.name);
|
adjustWearablesOpened(avatar.name);
|
||||||
|
|
||||||
|
modified = false;
|
||||||
visible = true;
|
visible = true;
|
||||||
avatarName = avatar.name;
|
avatarName = avatar.name;
|
||||||
wearablesModel = avatar.wearables;
|
wearablesModel = avatar.wearables;
|
||||||
|
@ -38,43 +41,47 @@ Rectangle {
|
||||||
|
|
||||||
function refresh(avatar) {
|
function refresh(avatar) {
|
||||||
wearablesCombobox.model.clear();
|
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;
|
var wearable = avatar.wearables.get(i).properties;
|
||||||
for(var j = (wearable.modelURL.length - 1); j >= 0; --j) {
|
for (var j = (wearable.modelURL.length - 1); j >= 0; --j) {
|
||||||
if(wearable.modelURL[j] === '/') {
|
if (wearable.modelURL[j] === '/') {
|
||||||
wearable.text = wearable.modelURL.substring(j + 1) + ' [%jointIndex%]'.replace('%jointIndex%', jointNames[wearable.parentJointIndex]);
|
wearable.text = wearable.modelURL.substring(j + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wearablesCombobox.model.append(wearable);
|
wearablesCombobox.model.append(wearable);
|
||||||
}
|
}
|
||||||
|
|
||||||
wearablesCombobox.currentIndex = 0;
|
if (wearablesCombobox.model.count !== 0) {
|
||||||
|
wearablesCombobox.currentIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshWearable(wearableID, wearableIndex, properties, updateUI) {
|
function refreshWearable(wearableID, wearableIndex, properties, updateUI) {
|
||||||
if(wearableIndex === -1) {
|
if (wearableIndex === -1) {
|
||||||
wearableIndex = wearablesCombobox.model.findIndexById(wearableID);
|
wearableIndex = wearablesCombobox.model.findIndexById(wearableID);
|
||||||
}
|
}
|
||||||
|
|
||||||
var wearable = wearablesCombobox.model.get(wearableIndex);
|
var wearable = wearablesCombobox.model.get(wearableIndex);
|
||||||
|
|
||||||
if(!wearable) {
|
if (!wearable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var wearableModelItemProperties = wearablesModel.get(wearableIndex).properties;
|
var wearableModelItemProperties = wearablesModel.get(wearableIndex).properties;
|
||||||
|
|
||||||
for(var prop in properties) {
|
for (var prop in properties) {
|
||||||
wearable[prop] = properties[prop];
|
wearable[prop] = properties[prop];
|
||||||
wearableModelItemProperties[prop] = wearable[prop];
|
wearableModelItemProperties[prop] = wearable[prop];
|
||||||
|
|
||||||
if(updateUI) {
|
if (updateUI) {
|
||||||
if(prop === 'localPosition') {
|
if (prop === 'localPosition') {
|
||||||
position.set(wearable[prop]);
|
positionVector.set(wearable[prop]);
|
||||||
} else if(prop === 'localRotationAngles') {
|
} else if (prop === 'localRotationAngles') {
|
||||||
rotation.set(wearable[prop]);
|
rotationVector.set(wearable[prop]);
|
||||||
} else if(prop === 'dimensions') {
|
} else if (prop === 'dimensions') {
|
||||||
scalespinner.set(wearable[prop].x / wearable.naturalDimensions.x);
|
scalespinner.set(wearable[prop].x / wearable.naturalDimensions.x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,13 +91,13 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentWearable() {
|
function getCurrentWearable() {
|
||||||
return wearablesCombobox.model.get(wearablesCombobox.currentIndex)
|
return wearablesCombobox.currentIndex !== -1 ? wearablesCombobox.model.get(wearablesCombobox.currentIndex) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectWearableByID(entityID) {
|
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);
|
var wearable = wearablesCombobox.model.get(i);
|
||||||
if(wearable.id === entityID) {
|
if (wearable.id === entityID) {
|
||||||
wearablesCombobox.currentIndex = i;
|
wearablesCombobox.currentIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -115,72 +122,216 @@ Rectangle {
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 15
|
anchors.topMargin: 12
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
spacing: 20
|
spacing: 20
|
||||||
width: parent.width - 30 * 2
|
width: parent.width - 22 * 2
|
||||||
|
|
||||||
HifiControlsUit.ComboBox {
|
Column {
|
||||||
id: wearablesCombobox
|
width: parent.width
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
comboBox.textRole: "text"
|
|
||||||
|
|
||||||
model: ListModel {
|
Rectangle {
|
||||||
function findIndexById(id) {
|
color: hifi.colors.orangeHighlight
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: 70
|
||||||
|
visible: HMD.active
|
||||||
|
|
||||||
for(var i = 0; i < count; ++i) {
|
RalewayRegular {
|
||||||
var wearable = get(i);
|
anchors.fill: parent
|
||||||
if(wearable.id === id) {
|
anchors.leftMargin: 18
|
||||||
return i;
|
anchors.rightMargin: 18
|
||||||
}
|
size: 20;
|
||||||
}
|
lineHeightMode: Text.FixedHeight
|
||||||
|
lineHeight: 23;
|
||||||
return -1;
|
text: "Tip: You can use hand controllers to grab and adjust your wearables"
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comboBox.onCurrentIndexChanged: {
|
Rectangle {
|
||||||
var currentWearable = getCurrentWearable();
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: 12 // spacing
|
||||||
|
visible: HMD.active
|
||||||
|
}
|
||||||
|
|
||||||
if(currentWearable) {
|
RowLayout {
|
||||||
position.set(currentWearable.localPosition);
|
anchors.left: parent.left
|
||||||
rotation.set(currentWearable.localRotationAngles);
|
anchors.right: parent.right
|
||||||
scalespinner.set(currentWearable.dimensions.x / currentWearable.naturalDimensions.x)
|
|
||||||
|
|
||||||
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: "<a href='#'>Get more</a>"
|
||||||
|
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: "<a href='#'>Add custom</a>"
|
||||||
|
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 {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 5
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: 20
|
spacing: 20
|
||||||
|
|
||||||
// TextStyle5
|
// TextStyle5
|
||||||
FiraSansSemiBold {
|
RalewayBold {
|
||||||
id: positionLabel
|
id: positionLabel
|
||||||
size: 22;
|
size: 15;
|
||||||
|
lineHeightMode: Text.FixedHeight
|
||||||
|
lineHeight: 18;
|
||||||
text: "Position"
|
text: "Position"
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextStyle7
|
// TextStyle7
|
||||||
FiraSansRegular {
|
RalewayBold {
|
||||||
size: 18;
|
size: 15;
|
||||||
lineHeightMode: Text.FixedHeight
|
lineHeightMode: Text.FixedHeight
|
||||||
lineHeight: 16.9;
|
lineHeight: 18;
|
||||||
text: "m"
|
text: "m"
|
||||||
anchors.verticalCenter: positionLabel.verticalCenter
|
anchors.verticalCenter: positionLabel.verticalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 {
|
Vector3 {
|
||||||
id: position
|
id: positionVector
|
||||||
backgroundColor: "lightgray"
|
backgroundColor: "lightgray"
|
||||||
|
enabled: getCurrentWearable() !== null
|
||||||
|
|
||||||
function set(localPosition) {
|
function set(localPosition) {
|
||||||
notify = false;
|
notify = false;
|
||||||
|
@ -201,9 +352,9 @@ Rectangle {
|
||||||
|
|
||||||
property bool notify: false;
|
property bool notify: false;
|
||||||
|
|
||||||
onXvalueChanged: if(notify) notifyPositionChanged();
|
onXvalueChanged: if (notify) notifyPositionChanged();
|
||||||
onYvalueChanged: if(notify) notifyPositionChanged();
|
onYvalueChanged: if (notify) notifyPositionChanged();
|
||||||
onZvalueChanged: if(notify) notifyPositionChanged();
|
onZvalueChanged: if (notify) notifyPositionChanged();
|
||||||
|
|
||||||
decimals: 2
|
decimals: 2
|
||||||
realFrom: -10
|
realFrom: -10
|
||||||
|
@ -214,31 +365,33 @@ Rectangle {
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 5
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: 20
|
spacing: 20
|
||||||
|
|
||||||
// TextStyle5
|
// TextStyle5
|
||||||
FiraSansSemiBold {
|
RalewayBold {
|
||||||
id: rotationLabel
|
id: rotationLabel
|
||||||
size: 22;
|
size: 15;
|
||||||
|
lineHeightMode: Text.FixedHeight
|
||||||
|
lineHeight: 18;
|
||||||
text: "Rotation"
|
text: "Rotation"
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextStyle7
|
// TextStyle7
|
||||||
FiraSansRegular {
|
RalewayBold {
|
||||||
size: 18;
|
size: 15;
|
||||||
lineHeightMode: Text.FixedHeight
|
lineHeightMode: Text.FixedHeight
|
||||||
lineHeight: 16.9;
|
lineHeight: 18;
|
||||||
text: "deg"
|
text: "deg"
|
||||||
anchors.verticalCenter: rotationLabel.verticalCenter
|
anchors.verticalCenter: rotationLabel.verticalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 {
|
Vector3 {
|
||||||
id: rotation
|
id: rotationVector
|
||||||
backgroundColor: "lightgray"
|
backgroundColor: "lightgray"
|
||||||
|
enabled: getCurrentWearable() !== null
|
||||||
|
|
||||||
function set(localRotationAngles) {
|
function set(localRotationAngles) {
|
||||||
notify = false;
|
notify = false;
|
||||||
|
@ -259,9 +412,9 @@ Rectangle {
|
||||||
|
|
||||||
property bool notify: false;
|
property bool notify: false;
|
||||||
|
|
||||||
onXvalueChanged: if(notify) notifyRotationChanged();
|
onXvalueChanged: if (notify) notifyRotationChanged();
|
||||||
onYvalueChanged: if(notify) notifyRotationChanged();
|
onYvalueChanged: if (notify) notifyRotationChanged();
|
||||||
onZvalueChanged: if(notify) notifyRotationChanged();
|
onZvalueChanged: if (notify) notifyRotationChanged();
|
||||||
|
|
||||||
decimals: 0
|
decimals: 0
|
||||||
realFrom: -180
|
realFrom: -180
|
||||||
|
@ -270,33 +423,66 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 5
|
height: childrenRect.height
|
||||||
|
|
||||||
// TextStyle5
|
HifiControlsUit.CheckBox {
|
||||||
FiraSansSemiBold {
|
id: isSoft
|
||||||
size: 22;
|
enabled: getCurrentWearable() !== null
|
||||||
text: "Scale"
|
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 {
|
Column {
|
||||||
width: parent.width
|
id: scalesColumn
|
||||||
height: childrenRect.height
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
// TextStyle5
|
||||||
|
RalewayBold {
|
||||||
|
id: scaleLabel
|
||||||
|
size: 15;
|
||||||
|
lineHeightMode: Text.FixedHeight
|
||||||
|
lineHeight: 18;
|
||||||
|
text: "Scale"
|
||||||
|
}
|
||||||
|
|
||||||
HifiControlsUit.SpinBox {
|
HifiControlsUit.SpinBox {
|
||||||
id: scalespinner
|
id: scalespinner
|
||||||
|
enabled: getCurrentWearable() !== null
|
||||||
decimals: 2
|
decimals: 2
|
||||||
realStepSize: 0.1
|
realStepSize: 0.1
|
||||||
realFrom: 0.1
|
realFrom: 0.1
|
||||||
realTo: 3.0
|
realTo: 3.0
|
||||||
realValue: 1.0
|
realValue: 1.0
|
||||||
backgroundColor: "lightgray"
|
backgroundColor: "lightgray"
|
||||||
width: position.spinboxWidth
|
width: positionVector.spinboxWidth
|
||||||
colorScheme: hifi.colorSchemes.light
|
colorScheme: hifi.colorSchemes.light
|
||||||
|
|
||||||
property bool notify: false;
|
property bool notify: false;
|
||||||
onValueChanged: if(notify) notifyScaleChanged();
|
onRealValueChanged: if (notify) notifyScaleChanged();
|
||||||
|
|
||||||
function set(value) {
|
function set(value) {
|
||||||
notify = false;
|
notify = false;
|
||||||
|
@ -320,26 +506,34 @@ Rectangle {
|
||||||
wearableUpdated(currentWearable.id, wearablesCombobox.currentIndex, properties);
|
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 {
|
DialogButtons {
|
||||||
|
yesButton.enabled: modified
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 30
|
anchors.bottomMargin: 57
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 30
|
anchors.leftMargin: 30
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
|
@ -24,8 +24,9 @@ ListModel {
|
||||||
|
|
||||||
function makeThumbnailUrl(avatarUrl) {
|
function makeThumbnailUrl(avatarUrl) {
|
||||||
var marketId = extractMarketId(avatarUrl);
|
var marketId = extractMarketId(avatarUrl);
|
||||||
if(marketId === '')
|
if (marketId === '') {
|
||||||
return '';
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
var avatarThumbnailUrl = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/%marketId%/large/hifi-mp-%marketId%.jpg"
|
var avatarThumbnailUrl = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/%marketId%/large/hifi-mp-%marketId%.jpg"
|
||||||
.split('%marketId%').join(marketId);
|
.split('%marketId%').join(marketId);
|
||||||
|
@ -42,7 +43,6 @@ ListModel {
|
||||||
'thumbnailUrl' : avatarThumbnailUrl,
|
'thumbnailUrl' : avatarThumbnailUrl,
|
||||||
'avatarUrl' : avatar.avatarUrl,
|
'avatarUrl' : avatar.avatarUrl,
|
||||||
'wearables' : avatar.avatarEntites ? avatar.avatarEntites : [],
|
'wearables' : avatar.avatarEntites ? avatar.avatarEntites : [],
|
||||||
'attachments' : avatar.attachments ? avatar.attachments : [],
|
|
||||||
'entry' : avatar,
|
'entry' : avatar,
|
||||||
'getMoreAvatars' : false
|
'getMoreAvatars' : false
|
||||||
};
|
};
|
||||||
|
@ -58,7 +58,7 @@ ListModel {
|
||||||
|
|
||||||
function populate(bookmarks) {
|
function populate(bookmarks) {
|
||||||
clear();
|
clear();
|
||||||
for(var avatarName in bookmarks) {
|
for (var avatarName in bookmarks) {
|
||||||
var avatar = bookmarks[avatarName];
|
var avatar = bookmarks[avatarName];
|
||||||
var avatarEntry = makeAvatarObject(avatar, avatarName);
|
var avatarEntry = makeAvatarObject(avatar, avatarName);
|
||||||
|
|
||||||
|
@ -67,19 +67,19 @@ ListModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
function arraysAreEqual(a1, a2, comparer) {
|
function arraysAreEqual(a1, a2, comparer) {
|
||||||
if(Array.isArray(a1) && Array.isArray(a2)) {
|
if (Array.isArray(a1) && Array.isArray(a2)) {
|
||||||
if(a1.length !== a2.length) {
|
if (a1.length !== a2.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < a1.length; ++i) {
|
for (var i = 0; i < a1.length; ++i) {
|
||||||
if(!comparer(a1[i], a2[i])) {
|
if (!comparer(a1[i], a2[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(Array.isArray(a1)) {
|
} else if (Array.isArray(a1)) {
|
||||||
return a1.length === 0;
|
return a1.length === 0;
|
||||||
} else if(Array.isArray(a2)) {
|
} else if (Array.isArray(a2)) {
|
||||||
return a2.length === 0;
|
return a2.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,26 +87,26 @@ ListModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
function modelsAreEqual(m1, m2, comparer) {
|
function modelsAreEqual(m1, m2, comparer) {
|
||||||
if(m1.count !== m2.count) {
|
if (m1.count !== m2.count) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < m1.count; ++i) {
|
for (var i = 0; i < m1.count; ++i) {
|
||||||
var e1 = m1.get(i);
|
var e1 = m1.get(i);
|
||||||
|
|
||||||
var allDifferent = true;
|
var allDifferent = true;
|
||||||
|
|
||||||
// it turns out order of wearables can randomly change so make position-independent comparison here
|
// 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);
|
var e2 = m2.get(j);
|
||||||
|
|
||||||
if(comparer(e1, e2)) {
|
if (comparer(e1, e2)) {
|
||||||
allDifferent = false;
|
allDifferent = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allDifferent) {
|
if (allDifferent) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,18 +115,20 @@ ListModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareNumericObjects(o1, o2) {
|
function compareNumericObjects(o1, o2) {
|
||||||
if(o1 === undefined && o2 !== undefined)
|
if (o1 === undefined && o2 !== undefined) {
|
||||||
return false;
|
return false;
|
||||||
if(o1 !== undefined && o2 === undefined)
|
}
|
||||||
|
if (o1 !== undefined && o2 === undefined) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for(var prop in o1) {
|
for (var prop in o1) {
|
||||||
if(o1.hasOwnProperty(prop) && o2.hasOwnProperty(prop)) {
|
if (o1.hasOwnProperty(prop) && o2.hasOwnProperty(prop)) {
|
||||||
var v1 = o1[prop];
|
var v1 = o1[prop];
|
||||||
var v2 = o2[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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +138,7 @@ ListModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareObjects(o1, o2, props, arrayProp) {
|
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 prop = props[i];
|
||||||
var propertyName = prop.propertyName;
|
var propertyName = prop.propertyName;
|
||||||
var comparer = prop.comparer;
|
var comparer = prop.comparer;
|
||||||
|
@ -144,12 +146,12 @@ ListModel {
|
||||||
var o1Value = arrayProp ? o1[arrayProp][propertyName] : o1[propertyName];
|
var o1Value = arrayProp ? o1[arrayProp][propertyName] : o1[propertyName];
|
||||||
var o2Value = arrayProp ? o2[arrayProp][propertyName] : o2[propertyName];
|
var o2Value = arrayProp ? o2[arrayProp][propertyName] : o2[propertyName];
|
||||||
|
|
||||||
if(comparer) {
|
if (comparer) {
|
||||||
if(comparer(o1Value, o2Value) === false) {
|
if (comparer(o1Value, o2Value) === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(JSON.stringify(o1Value) !== JSON.stringify(o2Value)) {
|
if (JSON.stringify(o1Value) !== JSON.stringify(o2Value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,42 +166,34 @@ ListModel {
|
||||||
{'propertyName' : 'marketplaceID'},
|
{'propertyName' : 'marketplaceID'},
|
||||||
{'propertyName' : 'itemName'},
|
{'propertyName' : 'itemName'},
|
||||||
{'propertyName' : 'script'},
|
{'propertyName' : 'script'},
|
||||||
|
{'propertyName' : 'relayParentJoints'},
|
||||||
{'propertyName' : 'localPosition', 'comparer' : compareNumericObjects},
|
{'propertyName' : 'localPosition', 'comparer' : compareNumericObjects},
|
||||||
{'propertyName' : 'localRotationAngles', 'comparer' : compareNumericObjects},
|
{'propertyName' : 'localRotationAngles', 'comparer' : compareNumericObjects},
|
||||||
{'propertyName' : 'dimensions', 'comparer' : compareNumericObjects}], 'properties')
|
{'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) {
|
function findAvatarIndexByValue(avatar) {
|
||||||
|
|
||||||
var index = -1;
|
var index = -1;
|
||||||
|
|
||||||
// 2DO: find better way of determining selected avatar in bookmarks
|
// 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 thesame = true;
|
||||||
var bookmarkedAvatar = allAvatars.get(i);
|
var bookmarkedAvatar = allAvatars.get(i);
|
||||||
|
|
||||||
if(bookmarkedAvatar.avatarUrl !== avatar.avatarUrl)
|
if (bookmarkedAvatar.avatarUrl !== avatar.avatarUrl) {
|
||||||
continue;
|
|
||||||
|
|
||||||
if(bookmarkedAvatar.avatarScale !== avatar.avatarScale)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(!modelsAreEqual(bookmarkedAvatar.attachments, avatar.attachments, compareAttachments)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!modelsAreEqual(bookmarkedAvatar.wearables, avatar.wearables, compareWearables)) {
|
if (bookmarkedAvatar.avatarScale !== avatar.avatarScale) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(thesame) {
|
if (!modelsAreEqual(bookmarkedAvatar.wearables, avatar.wearables, compareWearables)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thesame) {
|
||||||
index = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -209,8 +203,8 @@ ListModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
function findAvatarIndex(avatarName) {
|
function findAvatarIndex(avatarName) {
|
||||||
for(var i = 0; i < count; ++i) {
|
for (var i = 0; i < count; ++i) {
|
||||||
if(get(i).name === avatarName) {
|
if (get(i).name === avatarName) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,8 +213,9 @@ ListModel {
|
||||||
|
|
||||||
function findAvatar(avatarName) {
|
function findAvatar(avatarName) {
|
||||||
var avatarIndex = findAvatarIndex(avatarName);
|
var avatarIndex = findAvatarIndex(avatarName);
|
||||||
if(avatarIndex === -1)
|
if (avatarIndex === -1) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return get(avatarIndex);
|
return get(avatarIndex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,9 +125,9 @@ Rectangle {
|
||||||
size: 15
|
size: 15
|
||||||
color: 'red'
|
color: 'red'
|
||||||
visible: {
|
visible: {
|
||||||
for(var i = 0; i < avatars.count; ++i) {
|
for (var i = 0; i < avatars.count; ++i) {
|
||||||
var avatarName = avatars.get(i).name;
|
var avatarName = avatars.get(i).name;
|
||||||
if(avatarName === favoriteName.text) {
|
if (avatarName === favoriteName.text) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onYesClicked: function() {
|
onYesClicked: function() {
|
||||||
if(onSaveClicked) {
|
if (onSaveClicked) {
|
||||||
onSaveClicked();
|
onSaveClicked();
|
||||||
} else {
|
} else {
|
||||||
root.close();
|
root.close();
|
||||||
|
@ -173,7 +173,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onNoClicked: function() {
|
onNoClicked: function() {
|
||||||
if(onCancelClicked) {
|
if (onCancelClicked) {
|
||||||
onCancelClicked();
|
onCancelClicked();
|
||||||
} else {
|
} else {
|
||||||
root.close();
|
root.close();
|
||||||
|
|
|
@ -33,7 +33,7 @@ Row {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.debug('whitebutton.clicked', onNoClicked);
|
console.debug('whitebutton.clicked', onNoClicked);
|
||||||
|
|
||||||
if(onNoClicked) {
|
if (onNoClicked) {
|
||||||
onNoClicked();
|
onNoClicked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ Rectangle {
|
||||||
wrapMode: Text.WordWrap;
|
wrapMode: Text.WordWrap;
|
||||||
|
|
||||||
onLinkActivated: {
|
onLinkActivated: {
|
||||||
if(onLinkClicked)
|
if (onLinkClicked)
|
||||||
onLinkClicked(link);
|
onLinkClicked(link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ Rectangle {
|
||||||
noText: root.button1text
|
noText: root.button1text
|
||||||
|
|
||||||
onYesClicked: function() {
|
onYesClicked: function() {
|
||||||
if(onButton2Clicked) {
|
if (onButton2Clicked) {
|
||||||
onButton2Clicked();
|
onButton2Clicked();
|
||||||
} else {
|
} else {
|
||||||
root.close();
|
root.close();
|
||||||
|
@ -174,7 +174,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onNoClicked: function() {
|
onNoClicked: function() {
|
||||||
if(onButton1Clicked) {
|
if (onButton1Clicked) {
|
||||||
onButton1Clicked();
|
onButton1Clicked();
|
||||||
} else {
|
} else {
|
||||||
root.close();
|
root.close();
|
||||||
|
|
|
@ -18,15 +18,38 @@ MessageBox {
|
||||||
popup.button2text = 'CONFIRM';
|
popup.button2text = 'CONFIRM';
|
||||||
|
|
||||||
popup.onButton2Clicked = function() {
|
popup.onButton2Clicked = function() {
|
||||||
if(callback)
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.onLinkClicked = function(link) {
|
popup.onLinkClicked = function(link) {
|
||||||
if(linkCallback)
|
if (linkCallback) {
|
||||||
linkCallback(link);
|
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();
|
popup.open();
|
||||||
|
@ -41,22 +64,24 @@ MessageBox {
|
||||||
popup.button1text = 'CANCEL'
|
popup.button1text = 'CANCEL'
|
||||||
popup.titleText = 'Get Wearables'
|
popup.titleText = 'Get Wearables'
|
||||||
popup.bodyText = 'Buy wearables from <b><a href="app://marketplace">Marketplace.</a></b>' + '<br/>' +
|
popup.bodyText = 'Buy wearables from <b><a href="app://marketplace">Marketplace.</a></b>' + '<br/>' +
|
||||||
'Use wearables in <b><a href="app://purchases">My Purchases.</a></b>' + '<br/>' + '<br/>' +
|
'Wear wearable from <b><a href="app://purchases">My Purchases.</a></b>' + '<br/>' + '<br/>' +
|
||||||
'Visit “AvatarIsland” to get wearables.'
|
'Visit “AvatarIsland” to get wearables'
|
||||||
|
|
||||||
popup.imageSource = getWearablesUrl;
|
popup.imageSource = getWearablesUrl;
|
||||||
popup.onButton2Clicked = function() {
|
popup.onButton2Clicked = function() {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
if(callback)
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.onLinkClicked = function(link) {
|
popup.onLinkClicked = function(link) {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
if(linkCallback)
|
if (linkCallback) {
|
||||||
linkCallback(link);
|
linkCallback(link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.open();
|
popup.open();
|
||||||
|
@ -72,8 +97,9 @@ MessageBox {
|
||||||
popup.onButton2Clicked = function() {
|
popup.onButton2Clicked = function() {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
if(callback)
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
|
@ -87,8 +113,9 @@ MessageBox {
|
||||||
popup.onButton2Clicked = function() {
|
popup.onButton2Clicked = function() {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
if(callback)
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
|
@ -109,15 +136,17 @@ MessageBox {
|
||||||
popup.onButton2Clicked = function() {
|
popup.onButton2Clicked = function() {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
if(callback)
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.onLinkClicked = function(link) {
|
popup.onLinkClicked = function(link) {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
if(linkCallback)
|
if (linkCallback) {
|
||||||
linkCallback(link);
|
linkCallback(link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.open();
|
popup.open();
|
||||||
|
|
|
@ -33,13 +33,13 @@ Rectangle {
|
||||||
scaleSlider.value = Math.round(avatarScale * 10);
|
scaleSlider.value = Math.round(avatarScale * 10);
|
||||||
scaleSlider.notify = true;;
|
scaleSlider.notify = true;;
|
||||||
|
|
||||||
if(settings.dominantHand === 'left') {
|
if (settings.dominantHand === 'left') {
|
||||||
leftHandRadioButton.checked = true;
|
leftHandRadioButton.checked = true;
|
||||||
} else {
|
} else {
|
||||||
rightHandRadioButton.checked = true;
|
rightHandRadioButton.checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(settings.collisionsEnabled) {
|
if (settings.collisionsEnabled) {
|
||||||
collisionsEnabledRadiobutton.checked = true;
|
collisionsEnabledRadiobutton.checked = true;
|
||||||
} else {
|
} else {
|
||||||
collisionsDisabledRadioButton.checked = true;
|
collisionsDisabledRadioButton.checked = true;
|
||||||
|
@ -113,7 +113,7 @@ Rectangle {
|
||||||
|
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
console.debug('value changed: ', value);
|
console.debug('value changed: ', value);
|
||||||
if(notify) {
|
if (notify) {
|
||||||
console.debug('notifying.. ');
|
console.debug('notifying.. ');
|
||||||
root.scaleChanged(value / 10);
|
root.scaleChanged(value / 10);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ Item {
|
||||||
highp vec4 maskColor = texture2D(mask, vec2(qt_TexCoord0.x, qt_TexCoord0.y));
|
highp vec4 maskColor = texture2D(mask, vec2(qt_TexCoord0.x, qt_TexCoord0.y));
|
||||||
highp vec4 sourceColor = texture2D(source, 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;
|
gl_FragColor = sourceColor;
|
||||||
else
|
else
|
||||||
gl_FragColor = maskColor;
|
gl_FragColor = maskColor;
|
||||||
|
|
|
@ -20,6 +20,7 @@ Row {
|
||||||
|
|
||||||
spacing: spinboxSpace
|
spacing: spinboxSpace
|
||||||
|
|
||||||
|
property bool enabled: false;
|
||||||
property alias xvalue: xspinner.realValue
|
property alias xvalue: xspinner.realValue
|
||||||
property alias yvalue: yspinner.realValue
|
property alias yvalue: yspinner.realValue
|
||||||
property alias zvalue: zspinner.realValue
|
property alias zvalue: zspinner.realValue
|
||||||
|
@ -35,6 +36,7 @@ Row {
|
||||||
realFrom: root.realFrom
|
realFrom: root.realFrom
|
||||||
realTo: root.realTo
|
realTo: root.realTo
|
||||||
realStepSize: root.realStepSize
|
realStepSize: root.realStepSize
|
||||||
|
enabled: root.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControlsUit.SpinBox {
|
HifiControlsUit.SpinBox {
|
||||||
|
@ -48,6 +50,7 @@ Row {
|
||||||
realFrom: root.realFrom
|
realFrom: root.realFrom
|
||||||
realTo: root.realTo
|
realTo: root.realTo
|
||||||
realStepSize: root.realStepSize
|
realStepSize: root.realStepSize
|
||||||
|
enabled: root.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControlsUit.SpinBox {
|
HifiControlsUit.SpinBox {
|
||||||
|
@ -61,5 +64,6 @@ Row {
|
||||||
realFrom: root.realFrom
|
realFrom: root.realFrom
|
||||||
realTo: root.realTo
|
realTo: root.realTo
|
||||||
realStepSize: root.realStepSize
|
realStepSize: root.realStepSize
|
||||||
|
enabled: root.enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { }
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import "."
|
|
||||||
|
|
||||||
Vector3 {
|
|
||||||
decimals: 1;
|
|
||||||
stepSize: 1;
|
|
||||||
maximumValue: 180
|
|
||||||
minimumValue: -180
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import "."
|
|
||||||
|
|
||||||
Vector3 {
|
|
||||||
decimals: 3;
|
|
||||||
stepSize: 0.01;
|
|
||||||
maximumValue: 10
|
|
||||||
minimumValue: -10
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <avatar/AvatarManager.h>
|
#include <avatar/AvatarManager.h>
|
||||||
#include <EntityItemID.h>
|
#include <EntityItemID.h>
|
||||||
#include <EntityTree.h>
|
#include <EntityTree.h>
|
||||||
|
#include <ModelEntityItem.h>
|
||||||
#include <PhysicalEntitySimulation.h>
|
#include <PhysicalEntitySimulation.h>
|
||||||
#include <EntityEditPacketSender.h>
|
#include <EntityEditPacketSender.h>
|
||||||
#include <VariantMapToScriptValue.h>
|
#include <VariantMapToScriptValue.h>
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
#include "QVariantGLM.h"
|
#include "QVariantGLM.h"
|
||||||
|
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
void addAvatarEntities(const QVariantList& avatarEntities) {
|
void addAvatarEntities(const QVariantList& avatarEntities) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
@ -145,8 +146,8 @@ void AvatarBookmarks::removeBookmark(const QString& bookmarkName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWearableEntity(const EntityItemPointer& entity) {
|
bool isWearableEntity(const EntityItemPointer& entity) {
|
||||||
return entity->isVisible() && entity->getParentJointIndex() != INVALID_JOINT_INDEX &&
|
return entity->isVisible() && (entity->getParentJointIndex() != INVALID_JOINT_INDEX || (entity->getType() == EntityTypes::Model && (std::static_pointer_cast<ModelEntityItem>(entity))->getRelayParentJoints()))
|
||||||
(entity->getParentID() == DependencyManager::get<NodeList>()->getSessionUUID() || entity->getParentID() == DependencyManager::get<AvatarManager>()->getMyAvatar()->getSelfID());
|
&& (entity->getParentID() == DependencyManager::get<NodeList>()->getSessionUUID() || entity->getParentID() == DependencyManager::get<AvatarManager>()->getMyAvatar()->getSelfID());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
||||||
|
@ -254,7 +255,6 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
|
||||||
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
||||||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||||
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
||||||
bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
|
|
||||||
|
|
||||||
QScriptEngine scriptEngine;
|
QScriptEngine scriptEngine;
|
||||||
QVariantList wearableEntities;
|
QVariantList wearableEntities;
|
||||||
|
|
|
@ -277,13 +277,6 @@ Menu::Menu() {
|
||||||
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
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
|
// Settings > Developer Menu
|
||||||
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace MenuOption {
|
||||||
const QString AskToResetSettings = "Ask To Reset Settings on Start";
|
const QString AskToResetSettings = "Ask To Reset Settings on Start";
|
||||||
const QString AssetMigration = "ATP Asset Migration";
|
const QString AssetMigration = "ATP Asset Migration";
|
||||||
const QString AssetServer = "Asset Browser";
|
const QString AssetServer = "Asset Browser";
|
||||||
const QString Attachments = "Attachments...";
|
|
||||||
const QString AudioScope = "Show Scope";
|
const QString AudioScope = "Show Scope";
|
||||||
const QString AudioScopeFiftyFrames = "Fifty";
|
const QString AudioScopeFiftyFrames = "Fifty";
|
||||||
const QString AudioScopeFiveFrames = "Five";
|
const QString AudioScopeFiveFrames = "Five";
|
||||||
|
|
|
@ -20,7 +20,6 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
|
|
||||||
// constants from AvatarBookmarks.h
|
// constants from AvatarBookmarks.h
|
||||||
var ENTRY_AVATAR_URL = "avatarUrl";
|
var ENTRY_AVATAR_URL = "avatarUrl";
|
||||||
var ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
|
||||||
var ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
var ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
||||||
var ENTRY_AVATAR_SCALE = "avatarScale";
|
var ENTRY_AVATAR_SCALE = "avatarScale";
|
||||||
var ENTRY_VERSION = "version";
|
var ENTRY_VERSION = "version";
|
||||||
|
@ -31,7 +30,7 @@ function executeLater(callback) {
|
||||||
|
|
||||||
var INVALID_JOINT_INDEX = -1
|
var INVALID_JOINT_INDEX = -1
|
||||||
function isWearable(avatarEntity) {
|
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);
|
(avatarEntity.properties.parentID === MyAvatar.sessionUUID || avatarEntity.properties.parentID === MyAvatar.SELF_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +56,6 @@ function getMyAvatar() {
|
||||||
var avatar = {}
|
var avatar = {}
|
||||||
avatar[ENTRY_AVATAR_URL] = MyAvatar.skeletonModelURL;
|
avatar[ENTRY_AVATAR_URL] = MyAvatar.skeletonModelURL;
|
||||||
avatar[ENTRY_AVATAR_SCALE] = MyAvatar.getAvatarScale();
|
avatar[ENTRY_AVATAR_SCALE] = MyAvatar.getAvatarScale();
|
||||||
avatar[ENTRY_AVATAR_ATTACHMENTS] = MyAvatar.getAttachmentsVariant();
|
|
||||||
avatar[ENTRY_AVATAR_ENTITIES] = getMyAvatarWearables();
|
avatar[ENTRY_AVATAR_ENTITIES] = getMyAvatarWearables();
|
||||||
return avatar;
|
return avatar;
|
||||||
}
|
}
|
||||||
|
@ -72,12 +70,15 @@ function getMyAvatarSettings() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAvatarWearables(avatar, bookmarkAvatarName) {
|
function updateAvatarWearables(avatar, bookmarkAvatarName, callback) {
|
||||||
executeLater(function() {
|
executeLater(function() {
|
||||||
var wearables = getMyAvatarWearables();
|
var wearables = getMyAvatarWearables();
|
||||||
avatar[ENTRY_AVATAR_ENTITIES] = wearables;
|
avatar[ENTRY_AVATAR_ENTITIES] = wearables;
|
||||||
|
|
||||||
sendToQml({'method' : 'wearablesUpdated', 'wearables' : wearables, 'avatarName' : bookmarkAvatarName})
|
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.messageReceived.disconnect(handleWearableMessages);
|
||||||
Messages.unsubscribe('Hifi-Object-Manipulation');
|
Messages.unsubscribe('Hifi-Object-Manipulation');
|
||||||
break;
|
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':
|
case 'selectWearable':
|
||||||
ensureWearableSelected(message.entityID);
|
ensureWearableSelected(message.entityID);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue