diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index c21214484b..f595f148a8 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -73,9 +73,9 @@ public: Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue()); - Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, - const QVector& avatarsToInclude, - const QVector& avatarsToDiscard); + /* Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, */ + /* const QVector& avatarsToInclude, */ + /* const QVector& avatarsToDiscard); */ // TODO: remove this HACK once we settle on optimal default sort coefficients Q_INVOKABLE float getAvatarSortCoefficient(const QString& name); diff --git a/scripts/system/controllers/controllerDispatcherUtils.js b/scripts/system/controllers/controllerDispatcherUtils.js index a1bf2726da..808623fc79 100644 --- a/scripts/system/controllers/controllerDispatcherUtils.js +++ b/scripts/system/controllers/controllerDispatcherUtils.js @@ -290,6 +290,7 @@ ensureDynamic = function (entityID) { findGroupParent = function (controllerData, targetProps) { while (targetProps.parentID && targetProps.parentID != NULL_UUID) { + // XXX use controllerData.nearbyEntityPropertiesByID ? var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES); if (!parentProps) { break; diff --git a/scripts/system/controllers/controllerModules/cloneEntity.js b/scripts/system/controllers/controllerModules/cloneEntity.js new file mode 100644 index 0000000000..0539ee983a --- /dev/null +++ b/scripts/system/controllers/controllerModules/cloneEntity.js @@ -0,0 +1,160 @@ +"use strict"; + +// cloneEntity.js +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + + +/* global Script, Entities, RIGHT_HAND, LEFT_HAND, + enableDispatcherModule, disableDispatcherModule, getGrabbableData, Vec3, + TRIGGER_ON_VALUE, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS +*/ + +Script.include("/~/system/controllers/controllerDispatcherUtils.js"); + +// Object assign polyfill +if (typeof Object.assign != 'function') { + Object.assign = function(target, varArgs) { + if (target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + var to = Object(target); + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + if (nextSource !== null) { + for (var nextKey in nextSource) { + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }; +} + +(function() { + + function entityIsCloneable(props) { + var grabbableData = getGrabbableData(props); + return grabbableData.cloneable; + } + + function CloneEntity(hand) { + this.hand = hand; + this.grabbing = false; + this.previousParentID = {}; + this.previousParentJointIndex = {}; + this.previouslyUnhooked = {}; + + this.parameters = makeDispatcherModuleParameters( + 150, + this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], + [], + 100); + + this.getTargetProps = function (controllerData) { + // nearbyEntityProperties is already sorted by length from controller + var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; + for (var i = 0; i < nearbyEntityProperties.length; i++) { + var props = nearbyEntityProperties[i]; + var handPosition = controllerData.controllerLocations[this.hand].position; + var distance = Vec3.distance(props.position, handPosition); + if (distance > NEAR_GRAB_RADIUS) { + break; + } + if (entityIsCloneable(props)) { + return props; + } + } + return null; + }; + + this.isReady = function (controllerData) { + if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { + this.waiting = false; + return makeRunningValues(false, [], []); + } + + if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { + if (this.waiting) { + return makeRunningValues(false, [], []); + } + this.waiting = true; + } + + var cloneableProps = this.getTargetProps(controllerData); + if (!cloneableProps) { + return makeRunningValues(false, [], []); + } + + // we need all the properties, for this + cloneableProps = Entities.getEntityProperties(cloneableProps.id); + + var worldEntityProps = controllerData.nearbyEntityProperties[this.hand]; + var count = 0; + worldEntityProps.forEach(function(itemWE) { + if (itemWE.name.indexOf('-clone-' + cloneableProps.id) !== -1) { + count++; + } + }); + + var grabInfo = getGrabbableData(cloneableProps); + + var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 0; + if (count >= limit && limit !== 0) { + return makeRunningValues(false, [], []); + } + + cloneableProps.name = cloneableProps.name + '-clone-' + cloneableProps.id; + var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; + var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false; + var cUserData = Object.assign({}, cloneableProps.userData); + var cProperties = Object.assign({}, cloneableProps); + + try { + delete cUserData.grabbableKey.cloneLifetime; + delete cUserData.grabbableKey.cloneable; + delete cUserData.grabbableKey.cloneDynamic; + delete cUserData.grabbableKey.cloneLimit; + delete cProperties.id; + } catch(e) { + } + + cProperties.dynamic = dynamic; + cProperties.locked = false; + if (!cUserData.grabbableKey) { + cUserData.grabbableKey = {}; + } + cUserData.grabbableKey.triggerable = true; + cUserData.grabbableKey.grabbable = true; + cProperties.lifetime = lifetime; + cProperties.userData = JSON.stringify(cUserData); + // var cloneID = + Entities.addEntity(cProperties); + + return makeRunningValues(false, [], []); + }; + + this.run = function (controllerData) { + }; + + this.cleanup = function () { + }; + } + + var leftNearParentingGrabEntity = new CloneEntity(LEFT_HAND); + var rightNearParentingGrabEntity = new CloneEntity(RIGHT_HAND); + + enableDispatcherModule("LeftNearParentingGrabEntity", leftNearParentingGrabEntity); + enableDispatcherModule("RightNearParentingGrabEntity", rightNearParentingGrabEntity); + + this.cleanup = function () { + leftNearParentingGrabEntity.cleanup(); + rightNearParentingGrabEntity.cleanup(); + disableDispatcherModule("LeftNearParentingGrabEntity"); + disableDispatcherModule("RightNearParentingGrabEntity"); + }; + Script.scriptEnding.connect(this.cleanup); +}()); diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 823247ea29..2197fdca28 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -321,7 +321,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa if (props.parentID === NULL_UUID) { hasParent = false; } - if (hasParent || entityHasActions(hotspot.entityID)) { + if (hasParent || props.locked || entityHasActions(hotspot.entityID)) { return false; } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 7d5d1163bf..2332fdd32c 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -82,8 +82,8 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); var reparentProps = { parentID: AVATAR_SELF_ID, parentJointIndex: handJointIndex, - velocity: {x: 0, y: 0, z: 0}, - angularVelocity: {x: 0, y: 0, z: 0} + localVelocity: {x: 0, y: 0, z: 0}, + localAngularVelocity: {x: 0, y: 0, z: 0} }; if (this.thisHandIsParent(targetProps)) { @@ -114,8 +114,8 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Entities.editEntity(this.targetEntityID, { parentID: this.previousParentID[this.targetEntityID], parentJointIndex: this.previousParentJointIndex[this.targetEntityID], - velocity: {x: 0, y: 0, z: 0}, - angularVelocity: {x: 0, y: 0, z: 0} + localVelocity: {x: 0, y: 0, z: 0}, + localAngularVelocity: {x: 0, y: 0, z: 0} }); } diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index d41dec6de1..01b0d2ef11 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -25,7 +25,8 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/farActionGrabEntity.js", "controllerModules/tabletStylusInput.js", "controllerModules/equipEntity.js", - "controllerModules/nearTrigger.js" + "controllerModules/nearTrigger.js", + "controllerModules/cloneEntity.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js";