Merge pull request #7077 from sethalves/clean-up-grab-signaling

Clean up grab signaling + various fixes
This commit is contained in:
Chris Collins 2016-02-11 10:20:56 -08:00
commit a4afa03fe5
18 changed files with 165 additions and 230 deletions

View file

@ -120,10 +120,7 @@ function AttachedEntitiesManager() {
parsedMessage.action === 'loaded') { parsedMessage.action === 'loaded') {
// ignore // ignore
} else if (parsedMessage.action === 'release') { } else if (parsedMessage.action === 'release') {
manager.checkIfWearable(parsedMessage.grabbedEntity, parsedMessage.joint) manager.handleEntityRelease(parsedMessage.grabbedEntity, parsedMessage.joint)
// manager.saveAttachedEntities();
} else if (parsedMessage.action === 'shared-release') {
manager.updateRelativeOffsets(parsedMessage.grabbedEntity);
// manager.saveAttachedEntities(); // manager.saveAttachedEntities();
} else if (parsedMessage.action === 'equip') { } else if (parsedMessage.action === 'equip') {
// manager.saveAttachedEntities(); // manager.saveAttachedEntities();
@ -145,7 +142,14 @@ function AttachedEntitiesManager() {
return false; return false;
} }
this.checkIfWearable = function(grabbedEntity, releasedFromJoint) { this.handleEntityRelease = function(grabbedEntity, releasedFromJoint) {
// if this is still equipped, just rewrite the position information.
var grabData = getEntityCustomData('grabKey', entityID, {});
if ("refCount" in grabData && grabData.refCount > 0) {
manager.updateRelativeOffsets(parsedMessage.grabbedEntity);
return;
}
var allowedJoints = getEntityCustomData('wearable', grabbedEntity, DEFAULT_WEARABLE_DATA).joints; var allowedJoints = getEntityCustomData('wearable', grabbedEntity, DEFAULT_WEARABLE_DATA).joints;
var props = Entities.getEntityProperties(grabbedEntity, ["position", "parentID", "parentJointIndex"]); var props = Entities.getEntityProperties(grabbedEntity, ["position", "parentID", "parentJointIndex"]);

View file

@ -333,13 +333,9 @@ function MyController(hand) {
} }
}; };
this.callEntityMethodOnGrabbed = function(entityMethodName, args) { this.callEntityMethodOnGrabbed = function(entityMethodName) {
// print("Entity Method: " + entityMethodName + ", hand: " + this.hand); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
if (args.length > 0) { Entities.callEntityMethod(this.grabbedEntity, entityMethodName, args);
Entities.callEntityMethod(this.grabbedEntity, entityMethodName, args);
} else {
Entities.callEntityMethod(this.grabbedEntity, entityMethodName);
}
} }
this.setState = function(newState) { this.setState = function(newState) {
@ -1080,7 +1076,7 @@ function MyController(hand) {
if (this.actionID !== null) { if (this.actionID !== null) {
this.setState(STATE_CONTINUE_DISTANCE_HOLDING); this.setState(STATE_CONTINUE_DISTANCE_HOLDING);
this.activateEntity(this.grabbedEntity, grabbedProperties, false); this.activateEntity(this.grabbedEntity, grabbedProperties, false);
this.callSetupEntityMethods("startDistanceGrab"); this.callEntityMethodOnGrabbed("startDistanceGrab");
} }
this.currentAvatarPosition = MyAvatar.position; this.currentAvatarPosition = MyAvatar.position;
@ -1092,9 +1088,7 @@ function MyController(hand) {
this.continueDistanceHolding = function() { this.continueDistanceHolding = function() {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
if (this.isInitialGrab) { this.callEntityMethodOnGrabbed("releaseGrab");
this.callEntityMethodOnGrabbed("releaseGrab", []);
}
return; return;
} }
@ -1176,7 +1170,7 @@ function MyController(hand) {
this.handPreviousRotation = handRotation; this.handPreviousRotation = handRotation;
this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation);
this.callEntityMethodOnGrabbed("continueDistantGrab", []); this.callEntityMethodOnGrabbed("continueDistantGrab");
var defaultMoveWithHeadData = { var defaultMoveWithHeadData = {
disableMoveWithHead: false disableMoveWithHead: false
@ -1292,18 +1286,6 @@ function MyController(hand) {
return projection return projection
}; };
this.callSetupEntityMethods = function(entityMethodName) {
if (this.isInitialGrab) {
if (this.hand === RIGHT_HAND) {
this.callEntityMethodOnGrabbed("setRightHand", []);
} else {
this.callEntityMethodOnGrabbed("setLeftHand", []);
}
this.callEntityMethodOnGrabbed("setHand", [this.hand]);
this.callEntityMethodOnGrabbed(entityMethodName, [JSON.stringify(this.hand)]);
}
}
this.hasPresetOffsets = function() { this.hasPresetOffsets = function() {
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}}); var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
if ("joints" in wearableData) { if ("joints" in wearableData) {
@ -1340,9 +1322,7 @@ function MyController(hand) {
if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) { if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
if (this.isInitialGrab) { this.callEntityMethodOnGrabbed("releaseGrab");
this.callEntityMethodOnGrabbed("releaseGrab", []);
}
return; return;
} }
@ -1410,7 +1390,7 @@ function MyController(hand) {
})); }));
} }
this.callSetupEntityMethods(this.state == STATE_NEAR_GRABBING ? "startNearGrab" : "startEquip"); this.callEntityMethodOnGrabbed(this.state == STATE_NEAR_GRABBING ? "startNearGrab" : "startEquip");
if (this.state == STATE_NEAR_GRABBING) { if (this.state == STATE_NEAR_GRABBING) {
// near grabbing // near grabbing
@ -1428,9 +1408,7 @@ function MyController(hand) {
this.continueNearGrabbing = function() { this.continueNearGrabbing = function() {
if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) { if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
if (this.isInitialGrab) { this.callEntityMethodOnGrabbed("releaseGrab");
this.callEntityMethodOnGrabbed("releaseGrab", []);
}
return; return;
} }
if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) { if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) {
@ -1439,15 +1417,13 @@ function MyController(hand) {
} }
if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) { if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) {
this.setState(STATE_WAITING_FOR_BUMPER_RELEASE); this.setState(STATE_WAITING_FOR_BUMPER_RELEASE);
this.callEntityMethodOnGrabbed("releaseEquip", [JSON.stringify(this.hand)]); this.callEntityMethodOnGrabbed("releaseEquip");
return; return;
} }
if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.bumperSqueezed()) { if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.bumperSqueezed()) {
this.setState(STATE_CONTINUE_EQUIP_BD); this.setState(STATE_CONTINUE_EQUIP_BD);
if (this.isInitialGrab) { this.callEntityMethodOnGrabbed("releaseGrab");
this.callEntityMethodOnGrabbed("releaseGrab", [JSON.stringify(this.hand)]); this.callEntityMethodOnGrabbed("startEquip");
this.callEntityMethodOnGrabbed("startEquip", [JSON.stringify(this.hand)]);
}
return; return;
} }
@ -1458,8 +1434,7 @@ function MyController(hand) {
print("handControllerGrab -- autoreleasing held or equipped item because it is far from hand." + print("handControllerGrab -- autoreleasing held or equipped item because it is far from hand." +
props.parentID + " " + vec3toStr(props.position)); props.parentID + " " + vec3toStr(props.position));
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed(this.state == STATE_NEAR_GRABBING ? "releaseGrab" : "releaseEquip", this.callEntityMethodOnGrabbed(this.state == STATE_NEAR_GRABBING ? "releaseGrab" : "releaseEquip");
[JSON.stringify(this.hand)]);
return; return;
} }
@ -1480,15 +1455,11 @@ function MyController(hand) {
this.currentObjectTime = now; this.currentObjectTime = now;
var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, {}); var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, {});
if (this.isInitialGrab) { if (this.state === STATE_CONTINUE_EQUIP) {
if (this.state === STATE_CONTINUE_EQUIP) { this.callEntityMethodOnGrabbed("continueEquip");
// this.callEntityMethodOnGrabbed("continueEquip", []); }
Entities.callEntityMethod(this.grabbedEntity, "continueEquip"); if (this.state == STATE_CONTINUE_NEAR_GRABBING) {
} this.callEntityMethodOnGrabbed("continueNearGrab");
if (this.state == STATE_CONTINUE_NEAR_GRABBING) {
// this.callEntityMethodOnGrabbed("continueNearGrab", []);
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
}
} }
if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) { if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) {
@ -1516,48 +1487,42 @@ function MyController(hand) {
this.waitingForBumperRelease = function() { this.waitingForBumperRelease = function() {
if (this.bumperReleased()) { if (this.bumperReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, {});
if (this.isInitialGrab) {
// TODO -- only one of these should be sent
this.callEntityMethodOnGrabbed("releaseGrab", []);
this.callEntityMethodOnGrabbed("unequip", []);
}
} }
}; };
this.nearTrigger = function() { this.nearTrigger = function() {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed("stopNearTrigger", []); this.callEntityMethodOnGrabbed("stopNearTrigger");
return; return;
} }
this.callSetupEntityMethods("startNearTrigger"); this.callEntityMethodOnGrabbed("startNearTrigger");
this.setState(STATE_CONTINUE_NEAR_TRIGGER); this.setState(STATE_CONTINUE_NEAR_TRIGGER);
}; };
this.farTrigger = function() { this.farTrigger = function() {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed("stopFarTrigger", []); this.callEntityMethodOnGrabbed("stopFarTrigger");
return; return;
} }
this.callSetupEntityMethods("startFarTrigger"); this.callEntityMethodOnGrabbed("startFarTrigger");
this.setState(STATE_CONTINUE_FAR_TRIGGER); this.setState(STATE_CONTINUE_FAR_TRIGGER);
}; };
this.continueNearTrigger = function() { this.continueNearTrigger = function() {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed("stopNearTrigger", []); this.callEntityMethodOnGrabbed("stopNearTrigger");
return; return;
} }
this.callEntityMethodOnGrabbed("continueNearTrigger", []); this.callEntityMethodOnGrabbed("continueNearTrigger");
}; };
this.continueFarTrigger = function() { this.continueFarTrigger = function() {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed("stopFarTrigger", []); this.callEntityMethodOnGrabbed("stopFarTrigger");
return; return;
} }
@ -1573,7 +1538,7 @@ function MyController(hand) {
this.lastPickTime = now; this.lastPickTime = now;
if (intersection.entityID != this.grabbedEntity) { if (intersection.entityID != this.grabbedEntity) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed("stopFarTrigger", []); this.callEntityMethodOnGrabbed("stopFarTrigger");
return; return;
} }
} }
@ -1581,7 +1546,7 @@ function MyController(hand) {
if (USE_ENTITY_LINES_FOR_MOVING === true) { if (USE_ENTITY_LINES_FOR_MOVING === true) {
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
} }
this.callEntityMethodOnGrabbed("continueFarTrigger", []); this.callEntityMethodOnGrabbed("continueFarTrigger");
}; };
_this.allTouchedIDs = {}; _this.allTouchedIDs = {};
@ -1641,16 +1606,15 @@ function MyController(hand) {
}; };
this.startTouch = function(entityID) { this.startTouch = function(entityID) {
this.callEntityMethodOnGrabbed("startTouch", []); this.callEntityMethodOnGrabbed("startTouch");
}; };
this.continueTouch = function(entityID) { this.continueTouch = function(entityID) {
// this.callEntityMethodOnGrabbed("continueTouch", []); this.callEntityMethodOnGrabbed("continueTouch");
Entities.callEntityMethod(this.grabbedEntity, "continueTouch");
}; };
this.stopTouch = function(entityID) { this.stopTouch = function(entityID) {
this.callEntityMethodOnGrabbed("stopTouch", []); this.callEntityMethodOnGrabbed("stopTouch");
}; };
this.release = function() { this.release = function() {
@ -1679,19 +1643,11 @@ function MyController(hand) {
this.actionID = null; this.actionID = null;
this.setState(STATE_OFF); this.setState(STATE_OFF);
if (this.isInitialGrab) { Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'release',
action: 'release', grabbedEntity: this.grabbedEntity,
grabbedEntity: this.grabbedEntity, joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" }));
}));
} else {
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
action: 'shared-release',
grabbedEntity: this.grabbedEntity,
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
}));
}
this.grabbedEntity = null; this.grabbedEntity = null;
}; };
@ -1819,7 +1775,7 @@ function MyController(hand) {
this.grabbedEntity = loadedEntityID; this.grabbedEntity = loadedEntityID;
this.activateEntity(this.grabbedEntity, loadedProps, true); this.activateEntity(this.grabbedEntity, loadedProps, true);
this.isInitialGrab = true; this.isInitialGrab = true;
this.callSetupEntityMethods("startEquip"); this.callEntityMethodOnGrabbed("startEquip");
this.setState(STATE_CONTINUE_EQUIP); this.setState(STATE_CONTINUE_EQUIP);
} }
} }

View file

@ -33,7 +33,8 @@
}; };
var ARROW_MODEL_URL = "http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/newarrow_textured.fbx"; var ARROW_MODEL_URL = "http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/newarrow_textured.fbx";
var ARROW_COLLISION_HULL_URL = "http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/newarrow_collision_hull.obj"; var ARROW_COLLISION_HULL_URL =
"http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/newarrow_collision_hull.obj";
var ARROW_DIMENSIONS = { var ARROW_DIMENSIONS = {
x: 0.02, x: 0.02,
@ -94,7 +95,6 @@
} }
Bow.prototype = { Bow.prototype = {
isGrabbed: false,
stringDrawn: false, stringDrawn: false,
aiming: false, aiming: false,
arrowTipPosition: null, arrowTipPosition: null,
@ -125,33 +125,13 @@
Entities.deleteEntity(this.arrow); Entities.deleteEntity(this.arrow);
}, },
setLeftHand: function() { startEquip: function(entityID, args) {
if (this.isGrabbed === true) { this.hand = args[0];
return false; avatarID = args[1];
}
this.hand = 'left';
},
setRightHand: function() {
if (this.isGrabbed === true) {
return false;
}
this.hand = 'right';
},
startEquip: function() {
print('START BOW GRAB')
if (this.isGrabbed === true) {
return false;
}
this.isGrabbed = true;
this.initialHand = this.hand;
//disable the opposite hand in handControllerGrab.js by message //disable the opposite hand in handControllerGrab.js by message
var handToDisable = this.initialHand === 'right' ? 'left' : 'right'; var handToDisable = this.hand === 'right' ? 'left' : 'right';
print("disabling hand: " + handToDisable);
Messages.sendMessage('Hifi-Hand-Disabler', handToDisable); Messages.sendMessage('Hifi-Hand-Disabler', handToDisable);
var data = getEntityCustomData('grabbableKey', this.entityID, {}); var data = getEntityCustomData('grabbableKey', this.entityID, {});
@ -159,7 +139,7 @@
setEntityCustomData('grabbableKey', this.entityID, data); setEntityCustomData('grabbableKey', this.entityID, data);
}, },
continueEquip: function() { continueEquip: function(entityID, args) {
this.deltaTime = checkInterval(); this.deltaTime = checkInterval();
//debounce during debugging -- maybe we're updating too fast? //debounce during debugging -- maybe we're updating too fast?
@ -188,25 +168,19 @@
this.checkStringHand(); this.checkStringHand();
}, },
releaseEquip: function(entityID, args) {
releaseGrab: function() {
// print('RELEASE GRAB EVENT') // print('RELEASE GRAB EVENT')
if (this.isGrabbed === true && this.hand === this.initialHand) { Messages.sendMessage('Hifi-Hand-Disabler', "none")
Messages.sendMessage('Hifi-Hand-Disabler', "none") this.stringDrawn = false;
this.deleteStrings();
this.isGrabbed = false; var data = getEntityCustomData('grabbableKey', this.entityID, {});
this.stringDrawn = false; data.grabbable = true;
this.deleteStrings(); setEntityCustomData('grabbableKey', this.entityID, data);
Entities.deleteEntity(this.arrow);
var data = getEntityCustomData('grabbableKey', this.entityID, {}); this.aiming = false;
data.grabbable = true; this.hasArrowNotched = false;
setEntityCustomData('grabbableKey', this.entityID, data);
Entities.deleteEntity(this.arrow);
this.aiming = false;
this.hasArrowNotched = false;
}
}, },
createArrow: function() { createArrow: function() {
@ -367,10 +341,10 @@
checkStringHand: function() { checkStringHand: function() {
//invert the hands because our string will be held with the opposite hand of the first one we pick up the bow with //invert the hands because our string will be held with the opposite hand of the first one we pick up the bow with
var triggerLookup; var triggerLookup;
if (this.initialHand === 'left') { if (this.hand === 'left') {
triggerLookup = 1; triggerLookup = 1;
this.getStringHandPosition = MyAvatar.getRightPalmPosition; this.getStringHandPosition = MyAvatar.getRightPalmPosition;
} else if (this.initialHand === 'right') { } else if (this.hand === 'right') {
this.getStringHandPosition = MyAvatar.getLeftPalmPosition; this.getStringHandPosition = MyAvatar.getLeftPalmPosition;
triggerLookup = 0; triggerLookup = 0;
} }

View file

@ -119,7 +119,8 @@
//wait to make the bubbles collidable, so that they dont hit each other and the wand //wait to make the bubbles collidable, so that they dont hit each other and the wand
Script.setTimeout(this.addCollisionsToBubbleAfterCreation(this.currentBubble), lifetime / 2); Script.setTimeout(this.addCollisionsToBubbleAfterCreation(this.currentBubble), lifetime / 2);
//release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble //release the bubble -- when we create a new bubble, it will carry on and this update loop will
// affect the new bubble
this.createBubbleAtTipOfWand(); this.createBubbleAtTipOfWand();
return; return;
} else { } else {

View file

@ -24,15 +24,11 @@
Doll.prototype = { Doll.prototype = {
audioInjector: null, audioInjector: null,
isGrabbed: false, isGrabbed: false,
setLeftHand: function() {
this.hand = 'left';
},
setRightHand: function() { startNearGrab: function(entityID, args) {
this.hand = 'right'; this.hand = args[0];
}, avatarID = args[1];
startNearGrab: function() {
Entities.editEntity(this.entityID, { Entities.editEntity(this.entityID, {
animation: { animation: {
url: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx", url: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx",
@ -53,18 +49,18 @@
this.startNearGrab(id, params); this.startNearGrab(id, params);
}, },
continueNearGrab: function() { continueNearGrab: function(entityID, args) {
var props = Entities.getEntityProperties(this.entityID, ["position"]); var props = Entities.getEntityProperties(this.entityID, ["position"]);
var audioOptions = { var audioOptions = {
position: props.position position: props.position
}; };
this.audioInjector.options = audioOptions; this.audioInjector.options = audioOptions;
}, },
continueEquip: function() { continueEquip: function(entityID, args) {
this.continueNearGrab(); this.continueNearGrab(entityID, args);
}, },
releaseGrab: function() { releaseGrab: function(entityID, args) {
if (this.isGrabbed === true && this.hand === this.initialHand) { if (this.isGrabbed === true && this.hand === this.initialHand) {
this.audioInjector.stop(); this.audioInjector.stop();
Entities.editEntity(this.entityID, { Entities.editEntity(this.entityID, {
@ -79,8 +75,8 @@
this.isGrabbed = false; this.isGrabbed = false;
} }
}, },
releaseEquip: function() { releaseEquip: function(entityID, args) {
this.releaseGrab(); this.releaseGrab(entityID, args);
}, },
preload: function(entityID) { preload: function(entityID) {

View file

@ -77,15 +77,10 @@
whichHand: null, whichHand: null,
hasSpotlight: false, hasSpotlight: false,
spotlight: null, spotlight: null,
setRightHand: function() {
this.hand = 'RIGHT';
},
setLeftHand: function() { startNearGrab: function(entityID, args) {
this.hand = 'LEFT'; this.hand = args[0];
},
startNearGrab: function(entityID) {
print("FLASHLIGHT startNearGrab"); print("FLASHLIGHT startNearGrab");
if (!this.hasSpotlight) { if (!this.hasSpotlight) {
@ -161,11 +156,11 @@
this.changeLightWithTriggerPressure(this.whichHand); this.changeLightWithTriggerPressure(this.whichHand);
} }
}, },
continueEquip: function() { continueEquip: function(entityID, args) {
this.continueNearGrab(); this.continueNearGrab(entityID, args);
}, },
releaseGrab: function() { releaseGrab: function(entityID, args) {
//delete the lights and reset state //delete the lights and reset state
if (this.hasSpotlight) { if (this.hasSpotlight) {
Entities.deleteEntity(this.spotlight); Entities.deleteEntity(this.spotlight);
@ -177,8 +172,8 @@
this.lightOn = false; this.lightOn = false;
} }
}, },
releaseEquip: function() { releaseEquip: function(entityID, args) {
this.releaseGrab(); this.releaseGrab(entityID, args);
}, },
changeLightWithTriggerPressure: function(flashLightHand) { changeLightWithTriggerPressure: function(flashLightHand) {

View file

@ -54,47 +54,26 @@
PingPongGun.prototype = { PingPongGun.prototype = {
hand: null, hand: null,
whichHand: null,
gunTipPosition: null, gunTipPosition: null,
canShoot: false, canShoot: false,
canShootTimeout: null, canShootTimeout: null,
setRightHand: function() {
this.hand = 1; startEquip: function(entityID, args) {
this.hand = args[0] == "left" ? 0 : 1;
}, },
setLeftHand: function() { continueEquip: function(entityID, args) {
this.hand = 0; if (this.canShootTimeout !== null) {
}, Script.clearTimeout(this.canShootTimeout);
startEquip: function() {
this.setWhichHand();
},
setWhichHand: function() {
this.whichHand = this.hand;
},
continueEquip: function() {
if (this.whichHand === null) {
//only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten
this.setWhichHand();
} else {
if (this.canShootTimeout !== null) {
Script.clearTimeout(this.canShootTimeout);
}
this.checkTriggerPressure(this.whichHand);
} }
this.checkTriggerPressure(this.hand);
}, },
releaseEquip: function() { releaseEquip: function(entityID, args) {
var _this = this; var _this = this;
this.canShootTimeout = Script.setTimeout(function() {
if (this.whichHand === this.hand) { _this.canShoot = false;
this.whichHand = null; }, 250);
this.canShootTimeout = Script.setTimeout(function() {
_this.canShoot = false;
}, 250);
}
}, },
checkTriggerPressure: function(gunHand) { checkTriggerPressure: function(gunHand) {
@ -102,7 +81,7 @@
if (this.triggerValue < RELOAD_THRESHOLD) { if (this.triggerValue < RELOAD_THRESHOLD) {
// print('RELOAD'); // print('RELOAD');
this.canShoot = true; this.canShoot = true;
} else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true && this.hand === this.whichHand) { } else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true) {
var gunProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); var gunProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]);
this.shootBall(gunProperties); this.shootBall(gunProperties);
this.canShoot = false; this.canShoot = false;

View file

@ -49,10 +49,10 @@
startEquip: function(id, params) { startEquip: function(id, params) {
this.equipped = true; this.equipped = true;
this.hand = JSON.parse(params[0]); this.hand = params[0] == "left" ? 0 : 1;
}, },
continueEquip: function() { continueEquip: function(id, params) {
if (!this.equipped) { if (!this.equipped) {
return; return;
} }
@ -111,7 +111,7 @@
}); });
}, },
unequip: function() { releaseEquip: function(id, params) {
this.hand = null; this.hand = null;
this.equipped = false; this.equipped = false;
Overlays.editOverlay(this.laser, { Overlays.editOverlay(this.laser, {

View file

@ -38,20 +38,12 @@
Controller.Standard.RT, Controller.Standard.RT,
]; ];
this.setRightHand = function () { this.startNearGrab = function (entityID, args) {
this.hand = 1; this.hand = args[0] == "left" ? 0 : 1;
}
this.setLeftHand = function () {
this.hand = 0;
}
this.startNearGrab = function () {
this.whichHand = this.hand;
} }
this.toggleWithTriggerPressure = function () { this.toggleWithTriggerPressure = function () {
this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.whichHand]); this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]);
if (this.triggerValue < DISABLE_SPRAY_THRESHOLD && this.spraying === true) { if (this.triggerValue < DISABLE_SPRAY_THRESHOLD && this.spraying === true) {
this.spraying = false; this.spraying = false;
this.disableStream(); this.disableStream();

View file

@ -412,7 +412,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
} }
}); });
bool movingOrAnimating = isMoving() || isAnimatingSomething(); bool movingOrAnimating = isMovingRelativeToParent() || isAnimatingSomething();
if ((movingOrAnimating || if ((movingOrAnimating ||
_needsInitialSimulation || _needsInitialSimulation ||
_model->getTranslation() != getPosition() || _model->getTranslation() != getPosition() ||

View file

@ -76,8 +76,8 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
_physicsInfo(nullptr), _physicsInfo(nullptr),
_simulated(false) _simulated(false)
{ {
setVelocity(ENTITY_ITEM_DEFAULT_VELOCITY); setLocalVelocity(ENTITY_ITEM_DEFAULT_VELOCITY);
setAngularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); setLocalAngularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY);
// explicitly set transform parts to set dirty flags used by batch rendering // explicitly set transform parts to set dirty flags used by batch rendering
setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS); setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
quint64 now = usecTimestampNow(); quint64 now = usecTimestampNow();
@ -244,8 +244,8 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, _simulationOwner.toByteArray()); APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, _simulationOwner.toByteArray());
APPEND_ENTITY_PROPERTY(PROP_POSITION, getLocalPosition()); APPEND_ENTITY_PROPERTY(PROP_POSITION, getLocalPosition());
APPEND_ENTITY_PROPERTY(PROP_ROTATION, getLocalOrientation()); APPEND_ENTITY_PROPERTY(PROP_ROTATION, getLocalOrientation());
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, getVelocity()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY, getLocalVelocity());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getLocalAngularVelocity());
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration()); APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration());
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); // NOTE: PROP_RADIUS obsolete
@ -1054,7 +1054,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete
COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getLocalOrientation); COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getLocalOrientation);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getVelocity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getLocalVelocity);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravity);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(acceleration, getAcceleration); COPY_ENTITY_PROPERTY_TO_PROPERTIES(acceleration, getAcceleration);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(damping, getDamping); COPY_ENTITY_PROPERTY_TO_PROPERTIES(damping, getDamping);
@ -1066,7 +1066,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp); COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint); COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getAngularVelocity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getLocalAngularVelocity);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping); COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel); COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha); COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha);
@ -1562,7 +1562,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask
} else { } else {
if (_dynamic) { if (_dynamic) {
group = BULLET_COLLISION_GROUP_DYNAMIC; group = BULLET_COLLISION_GROUP_DYNAMIC;
} else if (isMoving() || hasActions()) { } else if (isMovingRelativeToParent() || hasActions()) {
group = BULLET_COLLISION_GROUP_KINEMATIC; group = BULLET_COLLISION_GROUP_KINEMATIC;
} else { } else {
group = BULLET_COLLISION_GROUP_STATIC; group = BULLET_COLLISION_GROUP_STATIC;

View file

@ -81,6 +81,8 @@ EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties
entitySideProperties.getParentID(), entitySideProperties.getParentID(),
entitySideProperties.getParentJointIndex(), entitySideProperties.getParentJointIndex(),
success); success);
// TODO -- handle velocity and angularVelocity
scriptSideProperties.setPosition(worldPosition); scriptSideProperties.setPosition(worldPosition);
scriptSideProperties.setRotation(worldRotation); scriptSideProperties.setRotation(worldRotation);
@ -94,6 +96,8 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti
EntityItemProperties entitySideProperties = scriptSideProperties; EntityItemProperties entitySideProperties = scriptSideProperties;
bool success; bool success;
// TODO -- handle velocity and angularVelocity
if (scriptSideProperties.localPositionChanged()) { if (scriptSideProperties.localPositionChanged()) {
entitySideProperties.setPosition(scriptSideProperties.getLocalPosition()); entitySideProperties.setPosition(scriptSideProperties.getLocalPosition());
} else if (scriptSideProperties.positionChanged()) { } else if (scriptSideProperties.positionChanged()) {
@ -128,14 +132,14 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
auto newVelocity = propertiesWithSimID.getVelocity().length(); auto newVelocity = propertiesWithSimID.getVelocity().length();
float cost = calculateCost(density * volume, 0, newVelocity); float cost = calculateCost(density * volume, 0, newVelocity);
cost *= costMultiplier; cost *= costMultiplier;
if(cost > _currentAvatarEnergy) { if(cost > _currentAvatarEnergy) {
return QUuid(); return QUuid();
} else { } else {
//debit the avatar energy and continue //debit the avatar energy and continue
emit debitEnergySource(cost); emit debitEnergySource(cost);
} }
EntityItemID id = EntityItemID(QUuid::createUuid()); EntityItemID id = EntityItemID(QUuid::createUuid());
// If we have a local entity tree set, then also update it. // If we have a local entity tree set, then also update it.

View file

@ -70,7 +70,7 @@ void EntitySimulation::prepareEntityForDelete(EntityItemPointer entity) {
} }
void EntitySimulation::addEntityInternal(EntityItemPointer entity) { void EntitySimulation::addEntityInternal(EntityItemPointer entity) {
if (entity->isMoving() && !entity->getPhysicsInfo()) { if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) {
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
} }
@ -78,7 +78,7 @@ void EntitySimulation::addEntityInternal(EntityItemPointer entity) {
void EntitySimulation::changeEntityInternal(EntityItemPointer entity) { void EntitySimulation::changeEntityInternal(EntityItemPointer entity) {
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
if (entity->isMoving() && !entity->getPhysicsInfo()) { if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
} else { } else {
_simpleKinematicEntities.remove(entity); _simpleKinematicEntities.remove(entity);

View file

@ -313,7 +313,11 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// pops to the next higher cell. So we want to check to see that the entity is large enough to be seen // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
// before we consider including it. // before we consider including it.
if (includeThisEntity) { if (includeThisEntity) {
AABox entityBounds = entity->getAABox(success); success = true;
// we can't cull a parent-entity by its dimensions because the child may be larger. we need to
// avoid sending details about a child but not the parent. the parent's queryAACube should have
// been adjusted to encompass the queryAACube of the child.
AABox entityBounds = entity->hasChildren() ? AABox(entityCube) : entity->getAABox(success);
if (!success) { if (!success) {
// if this entity is a child of an avatar, the entity-server wont be able to determine its // if this entity is a child of an avatar, the entity-server wont be able to determine its
// AABox. If this happens, fall back to the queryAACube. // AABox. If this happens, fall back to the queryAACube.

View file

@ -158,12 +158,12 @@ PhysicsMotionType EntityMotionState::computePhysicsMotionType() const {
} }
return MOTION_TYPE_DYNAMIC; return MOTION_TYPE_DYNAMIC;
} }
return (_entity->isMoving() || _entity->hasActions()) ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; return (_entity->isMovingRelativeToParent() || _entity->hasActions()) ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC;
} }
bool EntityMotionState::isMoving() const { bool EntityMotionState::isMoving() const {
assert(entityTreeIsLocked()); assert(entityTreeIsLocked());
return _entity && _entity->isMoving(); return _entity && _entity->isMovingRelativeToParent();
} }
// This callback is invoked by the physics simulation in two cases: // This callback is invoked by the physics simulation in two cases:
@ -555,7 +555,7 @@ uint32_t EntityMotionState::getIncomingDirtyFlags() {
} }
// we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings // we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings
int bodyFlags = _body->getCollisionFlags(); int bodyFlags = _body->getCollisionFlags();
bool isMoving = _entity->isMoving(); bool isMoving = _entity->isMovingRelativeToParent();
if (((bodyFlags & btCollisionObject::CF_STATIC_OBJECT) && isMoving) || if (((bodyFlags & btCollisionObject::CF_STATIC_OBJECT) && isMoving) ||
(bodyFlags & btCollisionObject::CF_KINEMATIC_OBJECT && !isMoving)) { (bodyFlags & btCollisionObject::CF_KINEMATIC_OBJECT && !isMoving)) {
dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; dirtyFlags |= Simulation::DIRTY_MOTION_TYPE;

View file

@ -51,7 +51,7 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
if (!motionState) { if (!motionState) {
_entitiesToAddToPhysics.insert(entity); _entitiesToAddToPhysics.insert(entity);
} }
} else if (entity->isMoving()) { } else if (entity->isMovingRelativeToParent()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
} }
} }
@ -98,7 +98,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
_physicalObjects.remove(motionState); _physicalObjects.remove(motionState);
_outgoingChanges.remove(motionState); _outgoingChanges.remove(motionState);
_entitiesToRemoveFromPhysics.insert(entity); _entitiesToRemoveFromPhysics.insert(entity);
if (entity->isMoving()) { if (entity->isMovingRelativeToParent()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
} }
} else { } else {
@ -109,7 +109,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
// Perhaps it's shape has changed and it can now be added? // Perhaps it's shape has changed and it can now be added?
_entitiesToAddToPhysics.insert(entity); _entitiesToAddToPhysics.insert(entity);
_simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic
} else if (entity->isMoving()) { } else if (entity->isMovingRelativeToParent()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
} else { } else {
_simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic
@ -209,7 +209,7 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re
} else if (!entity->shouldBePhysical()) { } else if (!entity->shouldBePhysical()) {
// this entity should no longer be on the internal _entitiesToAddToPhysics // this entity should no longer be on the internal _entitiesToAddToPhysics
entityItr = _entitiesToAddToPhysics.erase(entityItr); entityItr = _entitiesToAddToPhysics.erase(entityItr);
if (entity->isMoving()) { if (entity->isMovingRelativeToParent()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
} }
} else if (entity->isReadyToComputeShape()) { } else if (entity->isReadyToComputeShape()) {

View file

@ -392,9 +392,15 @@ void SpatiallyNestable::setOrientation(const glm::quat& orientation) {
} }
glm::vec3 SpatiallyNestable::getVelocity(bool& success) const { glm::vec3 SpatiallyNestable::getVelocity(bool& success) const {
glm::vec3 parentVelocity = getParentVelocity(success);
Transform parentTransform = getParentTransform(success);
glm::vec3 result; glm::vec3 result;
glm::vec3 parentVelocity = getParentVelocity(success);
if (!success) {
return result;
}
Transform parentTransform = getParentTransform(success);
if (!success) {
return result;
}
_velocityLock.withReadLock([&] { _velocityLock.withReadLock([&] {
// TODO: take parent angularVelocity into account. // TODO: take parent angularVelocity into account.
result = parentVelocity + parentTransform.getRotation() * _velocity; result = parentVelocity + parentTransform.getRotation() * _velocity;
@ -431,16 +437,25 @@ void SpatiallyNestable::setVelocity(const glm::vec3& velocity) {
glm::vec3 SpatiallyNestable::getParentVelocity(bool& success) const { glm::vec3 SpatiallyNestable::getParentVelocity(bool& success) const {
glm::vec3 result; glm::vec3 result;
SpatiallyNestablePointer parent = getParentPointer(success); SpatiallyNestablePointer parent = getParentPointer(success);
if (success && parent) { if (!success) {
return result;
}
if (parent) {
result = parent->getVelocity(success); result = parent->getVelocity(success);
} }
return result; return result;
} }
glm::vec3 SpatiallyNestable::getAngularVelocity(bool& success) const { glm::vec3 SpatiallyNestable::getAngularVelocity(bool& success) const {
glm::vec3 parentAngularVelocity = getParentAngularVelocity(success);
Transform parentTransform = getParentTransform(success);
glm::vec3 result; glm::vec3 result;
glm::vec3 parentAngularVelocity = getParentAngularVelocity(success);
if (!success) {
return result;
}
Transform parentTransform = getParentTransform(success);
if (!success) {
return result;
}
_angularVelocityLock.withReadLock([&] { _angularVelocityLock.withReadLock([&] {
result = parentAngularVelocity + parentTransform.getRotation() * _angularVelocity; result = parentAngularVelocity + parentTransform.getRotation() * _angularVelocity;
}); });
@ -475,7 +490,10 @@ void SpatiallyNestable::setAngularVelocity(const glm::vec3& angularVelocity) {
glm::vec3 SpatiallyNestable::getParentAngularVelocity(bool& success) const { glm::vec3 SpatiallyNestable::getParentAngularVelocity(bool& success) const {
glm::vec3 result; glm::vec3 result;
SpatiallyNestablePointer parent = getParentPointer(success); SpatiallyNestablePointer parent = getParentPointer(success);
if (success && parent) { if (!success) {
return result;
}
if (parent) {
result = parent->getAngularVelocity(success); result = parent->getAngularVelocity(success);
} }
return result; return result;
@ -672,6 +690,16 @@ QList<SpatiallyNestablePointer> SpatiallyNestable::getChildren() const {
return children; return children;
} }
bool SpatiallyNestable::hasChildren() const {
bool result = false;
_childrenLock.withReadLock([&] {
if (_children.size() > 0) {
result = true;
}
});
return result;
}
const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jointIndex) const { const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jointIndex) const {
Transform jointTransformInObjectFrame; Transform jointTransformInObjectFrame;
glm::vec3 position = getAbsoluteJointTranslationInObjectFrame(jointIndex); glm::vec3 position = getAbsoluteJointTranslationInObjectFrame(jointIndex);

View file

@ -116,6 +116,8 @@ public:
virtual void setLocalScale(const glm::vec3& scale); virtual void setLocalScale(const glm::vec3& scale);
QList<SpatiallyNestablePointer> getChildren() const; QList<SpatiallyNestablePointer> getChildren() const;
bool hasChildren() const;
NestableType getNestableType() const { return _nestableType; } NestableType getNestableType() const { return _nestableType; }
// this object's frame // this object's frame