reflect changes in grabbed wearable position/rotation in UI

This commit is contained in:
Alexander Ivash 2018-05-25 22:15:14 +03:00
parent c7570dbf83
commit dbf1aa779a
3 changed files with 168 additions and 49 deletions

View file

@ -114,7 +114,7 @@ Rectangle {
jointNames = message.data.jointNames;
emitSendToScript({'method' : getAvatarsMethod});
} else if(message.method === 'wearableUpdated') {
adjustWearables.refreshWearable(message.entityID, message.wearableIndex, message.properties);
adjustWearables.refreshWearable(message.entityID, message.wearableIndex, message.properties, message.updateUI);
} else if(message.method === 'wearablesUpdated') {
var wearablesModel = currentAvatar.wearables;
wearablesModel.clear();

View file

@ -67,24 +67,40 @@ Rectangle {
wearablesCombobox.currentIndex = 0;
}
function refreshWearable(wearableID, wearableIndex, properties) {
var wearable = wearablesCombobox.model.get(wearableIndex);
for(var prop in properties) {
wearable[prop] = properties[prop];
// 2do: consider removing 'properties' and manipulating localPosition/localRotation directly
var wearablesModelProps = wearablesModel.get(wearableIndex).properties;
wearablesModelProps[prop] = properties[prop];
wearablesModel.setProperty(wearableIndex, 'properties', wearablesModelProps);
console.debug('updated wearable', prop,
'old = ', JSON.stringify(wearable[prop], 0, 4),
'new = ', JSON.stringify(properties[prop], 0, 4),
'model = ', JSON.stringify(wearablesCombobox.model.get(wearableIndex)[prop]),
'wearablesModel = ', JSON.stringify(wearablesModel.get(wearableIndex).properties[prop], 0, 4)
);
function refreshWearable(wearableID, wearableIndex, properties, updateUI) {
if(wearableIndex === -1) {
wearableIndex = wearablesCombobox.model.findIndexById(wearableID);
}
var wearable = wearablesCombobox.model.get(wearableIndex);
console.debug('refreshWearable: ', wearableID, JSON.stringify(wearable, 0, 4));
if(!wearable) {
return;
}
var wearableModelItem = wearablesModel.get(wearableIndex);
for(var prop in properties) {
console.debug('updated wearable', prop,
'old = ', JSON.stringify(wearable[prop], 0, 4),
'new = ', JSON.stringify(properties[prop], 0, 4));
wearable[prop] = properties[prop];
wearableModelItem.properties[prop] = wearable[prop];
if(updateUI) {
if(prop === 'localPosition') {
position.set(wearable[prop]);
} else if(prop === 'localRotationAngles') {
rotation.set(wearable[prop]);
} else if(prop === 'dimensions') {
scalespinner.set(wearable[prop].x / wearable.naturalDimensions.x);
}
}
}
wearablesModel.setProperty(wearableIndex, 'properties', wearableModelItem.properties);
console.debug('wearablesModel.get(wearableIndex).properties: ', JSON.stringify(wearablesModel.get(wearableIndex).properties, 0, 4))
}
@ -133,6 +149,17 @@ Rectangle {
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: {
@ -141,24 +168,9 @@ Rectangle {
var currentWearable = getCurrentWearable();
if(currentWearable) {
position.notify = false;
position.xvalue = currentWearable.localPosition.x
position.yvalue = currentWearable.localPosition.y
position.zvalue = currentWearable.localPosition.z
console.debug('currentWearable.localPosition = ', JSON.stringify(currentWearable.localPosition, 0, 4))
position.notify = true;
rotation.notify = false;
rotation.xvalue = currentWearable.localRotationAngles.x
rotation.yvalue = currentWearable.localRotationAngles.y
rotation.zvalue = currentWearable.localRotationAngles.z
console.debug('currentWearable.localRotationAngles = ', JSON.stringify(currentWearable.localRotationAngles, 0, 4))
rotation.notify = true;
scalespinner.notify = false;
scalespinner.realValue = currentWearable.dimensions.x / currentWearable.naturalDimensions.x
console.debug('currentWearable.scale = ', scalespinner.realValue)
scalespinner.notify = true;
position.set(currentWearable.localPosition);
rotation.set(currentWearable.localRotationAngles);
scalespinner.set(currentWearable.dimensions.x / currentWearable.naturalDimensions.x)
wearableSelected(currentWearable.id);
}
@ -187,6 +199,16 @@ Rectangle {
id: position
backgroundColor: "lightgray"
function set(localPosition) {
notify = false;
xvalue = localPosition.x
yvalue = localPosition.y
zvalue = localPosition.z
notify = true;
console.debug('position.set: localPosition = ', JSON.stringify(localPosition, 0, 4))
}
function notifyPositionChanged() {
modified = true;
var properties = {
@ -231,6 +253,16 @@ Rectangle {
id: rotation
backgroundColor: "lightgray"
function set(localRotationAngles) {
notify = false;
xvalue = localRotationAngles.x
yvalue = localRotationAngles.y
zvalue = localRotationAngles.z
notify = true;
console.debug('localRotationAngles = ', JSON.stringify(localRotationAngles, 0, 4))
}
function notifyRotationChanged() {
modified = true;
var properties = {
@ -279,6 +311,14 @@ Rectangle {
property bool notify: false;
onValueChanged: if(notify) notifyScaleChanged();
function set(value) {
notify = false;
realValue = value
notify = true;
console.debug('scale = ', realValue)
}
function notifyScaleChanged() {
modified = true;
var currentWearable = getCurrentWearable();

View file

@ -152,7 +152,8 @@ function onAnimGraphUrlChanged(url) {
}
var selectedAvatarEntityGrabbable = false;
var selectedAvatarEntity = null;
var selectedAvatarEntityID = null;
var grabbedAvatarEntityChangeNotifier = null;
var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/purchases/Purchases.qml";
var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace";
@ -195,14 +196,17 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
}
console.debug('Entities.editEntity(message.entityID, message.properties)'.replace('message.entityID', message.entityID).replace('message.properties', JSON.stringify(message.properties)));
Entities.editEntity(message.entityID, message.properties);
sendToQml({'method' : 'wearableUpdated', 'wearable' : message.entityID, wearableIndex : message.wearableIndex, properties : message.properties})
sendToQml({'method' : 'wearableUpdated', 'entityID' : message.entityID, wearableIndex : message.wearableIndex, properties : message.properties, updateUI : false})
break;
case 'adjustWearablesOpened':
console.debug('avatarapp.js: adjustWearablesOpened');
currentAvatarWearablesBackup = getMyAvatarWearables();
adjustWearables.setOpened(true);
Entities.mousePressOnEntity.connect(onSelectedEntity);
Messages.subscribe('Hifi-Object-Manipulation');
Messages.messageReceived.connect(handleWearableMessages);
break;
case 'adjustWearablesClosed':
console.debug('avatarapp.js: adjustWearablesClosed');
@ -222,6 +226,8 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
adjustWearables.setOpened(false);
ensureWearableSelected(null);
Entities.mousePressOnEntity.disconnect(onSelectedEntity);
Messages.messageReceived.disconnect(handleWearableMessages);
Messages.unsubscribe('Hifi-Object-Manipulation');
break;
case 'selectWearable':
ensureWearableSelected(message.entityID);
@ -334,17 +340,23 @@ function setGrabbable(entityID, grabbable) {
}
function ensureWearableSelected(entityID) {
if(selectedAvatarEntity !== entityID) {
if(selectedAvatarEntity !== null) {
setGrabbable(selectedAvatarEntity, selectedAvatarEntityGrabbable);
if(selectedAvatarEntityID !== entityID) {
if(grabbedAvatarEntityChangeNotifier !== null) {
Script.clearInterval(grabbedAvatarEntityChangeNotifier);
grabbedAvatarEntityChangeNotifier = null;
}
selectedAvatarEntity = entityID;
if(selectedAvatarEntityID !== null) {
setGrabbable(selectedAvatarEntityID, selectedAvatarEntityGrabbable);
}
selectedAvatarEntityID = entityID;
console.debug('ensureWearableSelected: selectedAvatarEntity = ', selectedAvatarEntityID);
selectedAvatarEntityGrabbable = isGrabbable(entityID);
if(selectedAvatarEntity !== null) {
setGrabbable(selectedAvatarEntity, true);
if(selectedAvatarEntityID !== null) {
setGrabbable(selectedAvatarEntityID, true);
}
return true;
@ -358,11 +370,69 @@ function isEntityBeingWorn(entityID) {
};
function onSelectedEntity(entityID, pointerEvent) {
if (isEntityBeingWorn(entityID)) {
console.debug('onSelectedEntity: clicked on wearable', entityID);
console.debug('onSelectedEntity: clicked on wearable', entityID);
if(selectedAvatarEntityID !== entityID && isEntityBeingWorn(entityID))
{
console.debug('onSelectedEntity: clicked on worn wearable', entityID);
if(ensureWearableSelected(entityID)) {
sendToQml({'method' : 'selectAvatarEntity', 'entityID' : selectedAvatarEntity});
sendToQml({'method' : 'selectAvatarEntity', 'entityID' : selectedAvatarEntityID});
}
}
}
function handleWearableMessages(channel, message, sender) {
if (channel !== 'Hifi-Object-Manipulation') {
return;
}
var parsedMessage = null;
try {
parsedMessage = JSON.parse(message);
console.debug('handleWearableMessages: ', JSON.stringify(parsedMessage, null, 4));
} catch (e) {
print('error parsing wearable message');
return;
}
var entityID = parsedMessage.grabbedEntity;
console.debug('item worn: ', isEntityBeingWorn(entityID))
if(parsedMessage.action === 'grab') {
console.debug('handleWearableMessages: grab: ', JSON.stringify(parsedMessage, null, 4));
if(selectedAvatarEntityID !== entityID) {
ensureWearableSelected(entityID);
sendToQml({'method' : 'selectAvatarEntity', 'entityID' : selectedAvatarEntityID});
}
console.debug('creating grabbedAvatarEntityChangeNotifier: ', grabbedAvatarEntityChangeNotifier);
grabbedAvatarEntityChangeNotifier = Script.setInterval(function() {
console.debug('grabbedAvatarEntityChangeNotifier callback')
// for some reasons Entities.getEntityProperties returns more than was asked..
var propertyNames = ['localPosition', 'localRotation', 'dimensions', 'naturalDimensions'];
var entityProperties = Entities.getEntityProperties(selectedAvatarEntityID, propertyNames);
var properties = {}
propertyNames.forEach(function(propertyName) {
properties[propertyName] = entityProperties[propertyName];
})
properties.localRotationAngles = Quat.safeEulerAngles(properties.localRotation);
sendToQml({'method' : 'wearableUpdated', 'entityID' : selectedAvatarEntityID, 'wearableIndex' : -1, 'properties' : properties, updateUI : true})
}, 1000);
} else if(parsedMessage.action === 'release') {
console.debug('handleWearableMessages: release: ', JSON.stringify(parsedMessage, null, 4));
if(grabbedAvatarEntityChangeNotifier !== null) {
console.debug('clearing grabbedAvatarEntityChangeNotifier: ', grabbedAvatarEntityChangeNotifier);
Script.clearInterval(grabbedAvatarEntityChangeNotifier);
grabbedAvatarEntityChangeNotifier = null;
}
}
}
@ -415,9 +485,9 @@ startup();
var isWired = false;
function off() {
console.debug('entering avatarapp.js: off');
if (isWired) { // It is not ok to disconnect these twice, hence guard.
//Controller.mousePressEvent.disconnect(handleMouseEvent);
//Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent);
tablet.tabletShownChanged.disconnect(tabletVisibilityChanged);
isWired = false;
}
@ -426,6 +496,9 @@ function off() {
adjustWearables.setOpened(false);
ensureWearableSelected(null);
Entities.mousePressOnEntity.disconnect(onSelectedEntity);
Messages.messageReceived.disconnect(handleWearableMessages);
Messages.unsubscribe('Hifi-Object-Manipulation');
}
AvatarBookmarks.bookmarkLoaded.disconnect(onBookmarkLoaded);
@ -437,9 +510,13 @@ function off() {
MyAvatar.newCollisionSoundURL.disconnect(onNewCollisionSoundUrl);
MyAvatar.animGraphUrlChanged.disconnect(onAnimGraphUrlChanged);
MyAvatar.targetScaleChanged.disconnect(onTargetScaleChanged);
console.debug('exiting avatarapp.js: off');
}
function on() {
console.debug('entering avatarapp.js: on');
AvatarBookmarks.bookmarkLoaded.connect(onBookmarkLoaded);
AvatarBookmarks.bookmarkDeleted.connect(onBookmarkDeleted);
AvatarBookmarks.bookmarkAdded.connect(onBookmarkAdded);
@ -449,6 +526,8 @@ function on() {
MyAvatar.newCollisionSoundURL.connect(onNewCollisionSoundUrl);
MyAvatar.animGraphUrlChanged.connect(onAnimGraphUrlChanged);
MyAvatar.targetScaleChanged.connect(onTargetScaleChanged);
console.debug('exiting avatarapp.js: on');
}
function tabletVisibilityChanged() {