mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
keep a heart-beat timestamp in userData of grabbed entities. if grabbing something with an out-of-date heartbeat, reset it before grabbing
This commit is contained in:
parent
f82e5e2cd6
commit
0e028fbac8
1 changed files with 41 additions and 6 deletions
|
@ -73,9 +73,7 @@ var PICK_MAX_DISTANCE = 500; // max length of pick-ray
|
||||||
|
|
||||||
var GRAB_RADIUS = 0.06; // if the ray misses but an object is this close, it will still be selected
|
var GRAB_RADIUS = 0.06; // if the ray misses but an object is this close, it will still be selected
|
||||||
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
||||||
var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable.
|
|
||||||
var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected
|
var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected
|
||||||
var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things
|
|
||||||
var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object
|
var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object
|
||||||
var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed
|
var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed
|
||||||
var SHOW_GRAB_SPHERE = false; // draw a green sphere to show the grab search position and size
|
var SHOW_GRAB_SPHERE = false; // draw a green sphere to show the grab search position and size
|
||||||
|
@ -173,6 +171,10 @@ var STATE_WAITING_FOR_BUMPER_RELEASE = 15;
|
||||||
var COLLIDES_WITH_WHILE_GRABBED = "dynamic,otherAvatar";
|
var COLLIDES_WITH_WHILE_GRABBED = "dynamic,otherAvatar";
|
||||||
var COLLIDES_WITH_WHILE_MULTI_GRABBED = "dynamic";
|
var COLLIDES_WITH_WHILE_MULTI_GRABBED = "dynamic";
|
||||||
|
|
||||||
|
var HEART_BEAT_INTERVAL = 5; // seconds
|
||||||
|
var HEART_BEAT_TIMEOUT = 15;
|
||||||
|
|
||||||
|
|
||||||
function stateToName(state) {
|
function stateToName(state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_OFF:
|
case STATE_OFF:
|
||||||
|
@ -1103,6 +1105,8 @@ function MyController(hand) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.heartBeat(this.grabbedEntity);
|
||||||
|
|
||||||
var handPosition = this.getHandPosition();
|
var handPosition = this.getHandPosition();
|
||||||
var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition;
|
var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition;
|
||||||
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||||
|
@ -1438,6 +1442,8 @@ function MyController(hand) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.heartBeat(this.grabbedEntity);
|
||||||
|
|
||||||
var props = Entities.getEntityProperties(this.grabbedEntity, ["localPosition", "parentID", "position"]);
|
var props = Entities.getEntityProperties(this.grabbedEntity, ["localPosition", "parentID", "position"]);
|
||||||
if (props.parentID == MyAvatar.sessionUUID &&
|
if (props.parentID == MyAvatar.sessionUUID &&
|
||||||
Vec3.length(props.localPosition) > NEAR_PICK_MAX_DISTANCE * 2.0) {
|
Vec3.length(props.localPosition) > NEAR_PICK_MAX_DISTANCE * 2.0) {
|
||||||
|
@ -1670,19 +1676,40 @@ function MyController(hand) {
|
||||||
Entities.deleteEntity(this.pointLight);
|
Entities.deleteEntity(this.pointLight);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.heartBeat = function(entityID) {
|
||||||
|
var now = Date.now();
|
||||||
|
if (now - this.lastHeartBeat > HEART_BEAT_INTERVAL) {
|
||||||
|
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
|
||||||
|
data["heartBeat"] = now;
|
||||||
|
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
|
||||||
|
this.lastHeartBeat = now;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.resetAbandonedGrab = function(entityID) {
|
||||||
|
print("cleaning up abandoned grab on " + entityID);
|
||||||
|
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
|
||||||
|
data["refCount"] = 1;
|
||||||
|
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
|
||||||
|
this.deactivateEntity(entityID, false);
|
||||||
|
};
|
||||||
|
|
||||||
this.activateEntity = function(entityID, grabbedProperties, wasLoaded) {
|
this.activateEntity = function(entityID, grabbedProperties, wasLoaded) {
|
||||||
|
print("activating: " + entityID + " " + (this.hand === RIGHT_HAND ? "right" : "left"));
|
||||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA);
|
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA);
|
||||||
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
|
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
|
||||||
data["activated"] = true;
|
var now = Date.now();
|
||||||
data["avatarId"] = MyAvatar.sessionUUID;
|
|
||||||
if (wasLoaded) {
|
if (wasLoaded) {
|
||||||
data["refCount"] = 1;
|
data["refCount"] = 1;
|
||||||
data["avatarId"] = MyAvatar.sessionUUID;
|
|
||||||
} else {
|
} else {
|
||||||
data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1;
|
data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1;
|
||||||
|
|
||||||
// zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done
|
// zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done
|
||||||
if (data["refCount"] == 1) {
|
if (data["refCount"] == 1) {
|
||||||
|
data["heartBeat"] = now;
|
||||||
|
this.lastHeartBeat = now;
|
||||||
|
|
||||||
this.isInitialGrab = true;
|
this.isInitialGrab = true;
|
||||||
data["gravity"] = grabbedProperties.gravity;
|
data["gravity"] = grabbedProperties.gravity;
|
||||||
data["collidesWith"] = grabbedProperties.collidesWith;
|
data["collidesWith"] = grabbedProperties.collidesWith;
|
||||||
|
@ -1698,12 +1725,20 @@ function MyController(hand) {
|
||||||
z: 0
|
z: 0
|
||||||
},
|
},
|
||||||
// bummer, it isn't easy to do bitwise collisionMask operations like this:
|
// bummer, it isn't easy to do bitwise collisionMask operations like this:
|
||||||
//"collisionMask": COLLISION_MASK_WHILE_GRABBED | grabbedProperties.collisionMask
|
// "collisionMask": COLLISION_MASK_WHILE_GRABBED | grabbedProperties.collisionMask
|
||||||
// when using string values
|
// when using string values
|
||||||
"collidesWith": COLLIDES_WITH_WHILE_GRABBED
|
"collidesWith": COLLIDES_WITH_WHILE_GRABBED
|
||||||
};
|
};
|
||||||
Entities.editEntity(entityID, whileHeldProperties);
|
Entities.editEntity(entityID, whileHeldProperties);
|
||||||
} else if (data["refCount"] > 1) {
|
} else if (data["refCount"] > 1) {
|
||||||
|
if (now - data["heartBeat"] > HEART_BEAT_TIMEOUT) {
|
||||||
|
// this entity has userData suggesting it is grabbed, but nobody is updating the hearbeat.
|
||||||
|
// deactivate it before grabbing.
|
||||||
|
this.resetAbandonedGrab(entityID);
|
||||||
|
grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||||
|
return this.activateEntity(entityID, grabbedProperties, wasLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
this.isInitialGrab = false;
|
this.isInitialGrab = false;
|
||||||
// if an object is being grabbed by more than one person (or the same person twice, but nevermind), switch
|
// if an object is being grabbed by more than one person (or the same person twice, but nevermind), switch
|
||||||
// the collision groups so that it wont collide with "other" avatars. This avoids a situation where two
|
// the collision groups so that it wont collide with "other" avatars. This avoids a situation where two
|
||||||
|
|
Loading…
Reference in a new issue