overte/interface/resources/qml/hifi/avatarapp/AvatarsModel.qml
Alexander Ivash 5381dce8d8 get rid of 'isExternal' due to changes requirements
show avatar thumbnail if url was specified & valid, show 'guy-in-circle' otherwise
2018-07-06 21:00:54 +03:00

246 lines
7.8 KiB
QML

import QtQuick 2.9
ListModel {
id: model
function extractMarketId(avatarUrl) {
var guidRegexp = '([A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12})';
var regexp = new RegExp(guidRegexp,["i"]);
var match = regexp.exec(avatarUrl);
if (match !== null)
{
console.debug('marketplaceId guid', match[1]);
return match[1];
}
return '';
}
function makeMarketItemUrl(avatarUrl) {
var marketItemUrl = "https://highfidelity.com/marketplace/items/%marketId%"
.split('%marketId%').join(extractMarketId(avatarUrl));
return marketItemUrl;
}
function makeThumbnailUrl(avatarUrl) {
var marketId = extractMarketId(avatarUrl);
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);
return avatarThumbnailUrl;
}
function makeAvatarObject(avatar, avatarName) {
console.debug('makeAvatarEntry: ', avatarName, JSON.stringify(avatar));
var avatarThumbnailUrl = makeThumbnailUrl(avatar.avatarUrl);
console.debug('avatarThumbnailUrl:', avatarThumbnailUrl);
return {
'name' : avatarName,
'avatarScale' : avatar.avatarScale,
'thumbnailUrl' : avatarThumbnailUrl,
'avatarUrl' : avatar.avatarUrl,
'wearables' : avatar.avatarEntites ? avatar.avatarEntites : [],
'attachments' : avatar.attachments ? avatar.attachments : [],
'entry' : avatar,
'getMoreAvatars' : false
};
}
function addAvatarEntry(avatar, avatarName) {
console.debug('addAvatarEntry: ', avatarName);
var avatarEntry = makeAvatarObject(avatar, avatarName);
append(avatarEntry);
return allAvatars.count - 1;
}
function populate(bookmarks) {
for(var avatarName in bookmarks) {
var avatar = bookmarks[avatarName];
var avatarEntry = makeAvatarObject(avatar, avatarName);
append(avatarEntry);
}
}
function arraysAreEqual(a1, a2, comparer) {
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])) {
return false;
}
}
} else if(Array.isArray(a1)) {
return a1.length === 0;
} else if(Array.isArray(a2)) {
return a2.length === 0;
}
return true;
}
function modelsAreEqual(m1, m2, comparer) {
if(m1.count !== m2.count) {
return false;
}
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) {
var e2 = m2.get(j);
if(comparer(e1, e2)) {
allDifferent = false;
break;
}
}
if(allDifferent) {
return false;
}
}
return true;
}
function compareNumericObjects(o1, o2) {
if(o1 === undefined && o2 !== undefined)
return false;
if(o1 !== undefined && o2 === undefined)
return false;
for(var prop in o1) {
var v1 = o1[prop];
var v2 = o2[prop];
if(v1 !== v2 && Math.round(v1 * 1000) != Math.round(v2 * 1000))
return false;
}
return true;
}
function compareObjects(o1, o2, props, arrayProp) {
console.debug('compare ojects: o1 = ', JSON.stringify(o1, null, 4), 'o2 = ', JSON.stringify(o2, null, 4));
for(var i = 0; i < props.length; ++i) {
var prop = props[i];
var propertyName = prop.propertyName;
var comparer = prop.comparer;
var o1Value = arrayProp ? o1[arrayProp][propertyName] : o1[propertyName];
var o2Value = arrayProp ? o2[arrayProp][propertyName] : o2[propertyName];
console.debug('compare values for key: ', propertyName, comparer ? 'using specified comparer' : 'using default comparer', ', o1 = ', JSON.stringify(o1Value, null, 4), 'o2 = ', JSON.stringify(o2Value, null, 4));
if(comparer) {
if(comparer(o1Value, o2Value) === false) {
console.debug('comparer: not equal');
return false;
} else {
console.debug('comparer: equal');
}
} else {
if(JSON.stringify(o1Value) !== JSON.stringify(o2Value)) {
console.debug('not equal');
return false;
} else {
console.debug('equal');
}
}
}
return true;
}
function compareWearables(w1, w2) {
return compareObjects(w1, w2, [{'propertyName' : 'modelURL'},
{'propertyName' : 'parentJointIndex'},
{'propertyName' : 'marketplaceID'},
{'propertyName' : 'itemName'},
{'propertyName' : 'script'},
{'propertyName' : 'rotation', 'comparer' : compareNumericObjects},
{'propertyName' : 'localPosition', 'comparer' : compareNumericObjects},
{'propertyName' : 'localRotation', '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;
console.debug('findAvatarIndexByValue: ', 'name = ', avatar.name);
// 2DO: find better way of determining selected avatar in bookmarks
console.debug('allAvatars.count: ', allAvatars.count);
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)) {
continue;
}
if(!modelsAreEqual(bookmarkedAvatar.wearables, avatar.wearables, compareWearables)) {
continue;
}
if(thesame) {
index = i;
break;
}
}
return index;
}
function findAvatarIndex(avatarName) {
for(var i = 0; i < count; ++i) {
if(get(i).name === avatarName) {
console.debug('avatar found by index: ', i)
return i;
}
}
return -1;
}
function findAvatar(avatarName) {
console.debug('AvatarsModel: find avatar by', avatarName);
var avatarIndex = findAvatarIndex(avatarName);
if(avatarIndex === -1)
return undefined;
return get(avatarIndex);
}
}