156 lines
6.7 KiB
JavaScript
156 lines
6.7 KiB
JavaScript
(function() {
|
|
var _this = null;
|
|
|
|
// direct copy from source code: faux joint indexes (-1 means invalid)
|
|
const SENSOR_TO_WORLD_MATRIX_INDEX = 65534; // -2
|
|
const CONTROLLER_RIGHTHAND_INDEX = 65533; // -3
|
|
const CONTROLLER_LEFTHAND_INDEX = 65532; // -4
|
|
|
|
const ZERO_UUID = '{00000000-0000-0000-0000-000000000000}';
|
|
|
|
const SANETIZE_PROPERTIES = ['childEntities', 'parentID', 'id'];
|
|
|
|
function entityListToTree(entitiesList) {
|
|
function entityListToTreeRecursive(properties) {
|
|
properties.childEntities = [];
|
|
entitiesList.forEach(function(entityProperties) {
|
|
if (properties.id !== undefined && properties.id === entityProperties.parentID) {
|
|
properties.childEntities.push(entityListToTreeRecursive(entityProperties));
|
|
}
|
|
});
|
|
return properties;
|
|
}
|
|
var entityTree = [];
|
|
entitiesList.forEach(function(entityProperties) {
|
|
if (entityProperties.parentID === undefined || entityProperties.parentID === ZERO_UUID) {
|
|
entityTree.push(entityListToTreeRecursive(entityProperties));
|
|
}
|
|
});
|
|
return entityTree;
|
|
}
|
|
|
|
// TODO: ATP support (currently the JS API for ATP does not support file links, only hashes)
|
|
function importEntitiesJSON(importLink, parentProperties) {
|
|
if (parentProperties === undefined) {
|
|
parentProperties = {};
|
|
}
|
|
var request = new XMLHttpRequest();
|
|
request.open('GET', importLink, false);
|
|
request.send();
|
|
try {
|
|
var response = JSON.parse(request.responseText);
|
|
parentProperties.childEntities = entityListToTree(response.Entities);
|
|
return parentProperties;
|
|
} catch (e) {
|
|
print('Failed importing entities JSON because: ' + JSON.stringify(e));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
//Creates an entity and returns a mixed object of the creation properties and the assigned entityID
|
|
var createEntity = function(entityProperties, parent, clientOnly) {
|
|
if (parent.rotation !== undefined) {
|
|
if (entityProperties.rotation !== undefined) {
|
|
entityProperties.rotation = Quat.multiply(parent.rotation, entityProperties.rotation);
|
|
} else {
|
|
entityProperties.rotation = parent.rotation;
|
|
}
|
|
}
|
|
if (parent.position !== undefined) {
|
|
var localPosition = (parent.rotation !== undefined) ? Vec3.multiplyQbyV(parent.rotation, entityProperties.position) : entityProperties.position;
|
|
entityProperties.position = Vec3.sum(localPosition, parent.position)
|
|
}
|
|
if (parent.id !== undefined) {
|
|
entityProperties.parentID = parent.id;
|
|
}
|
|
entityProperties.id = Entities.addEntity(entityProperties, clientOnly);
|
|
return entityProperties;
|
|
};
|
|
|
|
var createEntitiesFromTree = function(entityTree, parent, clientOnly) {
|
|
if (parent === undefined) {
|
|
parent = {};
|
|
}
|
|
var createdTree = [];
|
|
entityTree.forEach(function(entityProperties) {
|
|
var sanetizedProperties = {};
|
|
Object.keys(entityProperties).forEach(function(propertyKey) {
|
|
if (!entityProperties.hasOwnProperty(propertyKey) || SANETIZE_PROPERTIES.indexOf(propertyKey) !== -1) {
|
|
return true;
|
|
}
|
|
sanetizedProperties[propertyKey] = entityProperties[propertyKey];
|
|
});
|
|
|
|
|
|
// Allow for non-entity parent objects, this allows us to offset groups of entities to a specific position/rotation
|
|
var parentProperties = sanetizedProperties;
|
|
if (entityProperties.type !== undefined) {
|
|
parentProperties = createEntity(sanetizedProperties, parent, clientOnly);
|
|
}
|
|
if (entityProperties.childEntities !== undefined) {
|
|
parentProperties.childEntities =
|
|
createEntitiesFromTree(entityProperties.childEntities, parentProperties, clientOnly);
|
|
}
|
|
createdTree.push(parentProperties);
|
|
});
|
|
return createdTree;
|
|
};
|
|
|
|
function HandyAttacher() {
|
|
_this = this;
|
|
};
|
|
|
|
HandyAttacher.prototype = {
|
|
attachEntity: function(entityID, attachHand) {
|
|
var userData;
|
|
try {
|
|
userData = JSON.parse(Entities.getEntityProperties(entityID, ['userData']).userData);
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
if (userData.attachmentEntityJSON === undefined) {
|
|
return;
|
|
}
|
|
if (attachHand === 'preset') {
|
|
if (userData.attachHand === undefined) {
|
|
return;
|
|
}
|
|
attachHand = userData.attachHand;
|
|
}
|
|
|
|
//if (userData.deleteOtherHandAttachment) {
|
|
// MyAvatar.jointNames.indexOf(attachHand === 'left' ? 'RightHand' : 'LeftHand')
|
|
// print('I am here. Yes delete it');
|
|
//}
|
|
// !! makes sure that clientOnly would contain a boolean representation of the value set in the userdata
|
|
var clientOnly = userData.clientOnly ? !!userData.clientOnly : false;
|
|
var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation,
|
|
MyAvatar.getAbsoluteJointTranslationInObjectFrame(attachHand === 'left' ? CONTROLLER_LEFTHAND_INDEX : CONTROLLER_RIGHTHAND_INDEX)), MyAvatar.position);
|
|
|
|
var attachmentJSON = importEntitiesJSON(userData.attachmentEntityJSON, {
|
|
//position: controllerPosition
|
|
position: MyAvatar.getJointPosition(MyAvatar.jointNames.indexOf(attachHand === 'left' ? 'LeftHand' : 'RightHand'))
|
|
});
|
|
print(attachmentJSON);
|
|
if (attachmentJSON === null) {
|
|
return;
|
|
}
|
|
|
|
// print(JSON.stringify(attachmentJSON));
|
|
var createdEntities = createEntitiesFromTree([attachmentJSON], {}, clientOnly);
|
|
print("Created = " + JSON.stringify(createdEntities[0]));
|
|
var probableGolfClubID = createdEntities[0].childEntities[0].id;
|
|
Messages.sendLocalMessage('Hifi-Hand-Grab', JSON.stringify({hand: attachHand, entityID: probableGolfClubID}));
|
|
},
|
|
// enterEntity: function(entityID) {
|
|
// print (' on enter!!');
|
|
// _this.attachEntity(entityID, 'preset');
|
|
// },
|
|
startNearTrigger: function(entityID, args) {
|
|
print (' on startNearTrigger!!');
|
|
_this.attachEntity(entityID, args[0]);
|
|
}
|
|
};
|
|
|
|
return new HandyAttacher();
|
|
})
|