mirror of
https://github.com/lubosz/overte.git
synced 2025-04-18 04:18:17 +02:00
reflect changes in grabbed wearable position/rotation in UI
This commit is contained in:
parent
c7570dbf83
commit
dbf1aa779a
3 changed files with 168 additions and 49 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue