diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 353e7b3daa..10775a483f 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -80,6 +80,18 @@ var ACTION_TTL_REFRESH = 5; var PICKS_PER_SECOND_PER_HAND = 5; var MSECS_PER_SEC = 1000.0; + +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js + +var DEFAULT_GRABBABLE_DATA = { + grabbable: true, + invertSolidWhileHeld: false +}; + +var disabledHand ='none'; + + // states for the state machine var STATE_OFF = 0; var STATE_SEARCHING = 1; @@ -93,15 +105,35 @@ var STATE_FAR_GRABBING_NON_COLLIDING = 8; var STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING = 9; var STATE_RELEASE = 10; -var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js -var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js -var DEFAULT_GRABBABLE_DATA = { - grabbable: true, - invertSolidWhileHeld: false -}; +function stateToName(state) { + switch (state) { + case STATE_OFF: + return "off"; + case STATE_SEARCHING: + return "searching"; + case STATE_DISTANCE_HOLDING: + return "distance_holding"; + case STATE_CONTINUE_DISTANCE_HOLDING: + return "continue_distance_holding"; + case STATE_NEAR_GRABBING: + return "near_grabbing"; + case STATE_CONTINUE_NEAR_GRABBING: + return "continue_near_grabbing"; + case STATE_NEAR_GRABBING_NON_COLLIDING: + return "near_grabbing_non_colliding"; + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + return "continue_near_grabbing_non_colliding"; + case STATE_FAR_GRABBING_NON_COLLIDING: + return "far_grabbing_non_colliding"; + case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING: + return "continue_far_grabbing_non_colliding"; + case STATE_RELEASE: + return "release"; + } -var disabledHand ='none'; + return "unknown"; +} function getTag() { return "grab-" + MyAvatar.sessionUUID; @@ -196,7 +228,7 @@ function MyController(hand, triggerAction) { this.setState = function(newState) { if (WANT_DEBUG) { - print("STATE: " + this.state + " --> " + newState); + print("STATE: " + stateToName(this.state) + " --> " + newState + ", hand: " + this.hand); } this.state = newState; } @@ -348,10 +380,11 @@ function MyController(hand, triggerAction) { } if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) { // the hand is very close to the intersected object. go into close-grabbing mode. - if (intersection.properties.collisionsWillMove === 1) { - this.setState(STATE_NEAR_GRABBING); - } else { + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + if (grabbableData.wantsTrigger) { this.setState(STATE_NEAR_GRABBING_NON_COLLIDING); + } else { + this.setState(STATE_NEAR_GRABBING); } } else { // don't allow two people to distance grab the same object @@ -392,11 +425,11 @@ function MyController(hand, triggerAction) { } if (this.grabbedEntity === null) { return; - } else if (props.locked === 0 && props.collisionsWillMove === 1) { - this.setState(STATE_NEAR_GRABBING); - } else if (props.collisionsWillMove === 0 && grabbableData.wantsTrigger) { - // We have grabbed a non-physical object, so we want to trigger a non-colliding event as opposed to a grab event + } + if (grabbableData.wantsTrigger) { this.setState(STATE_NEAR_GRABBING_NON_COLLIDING); + } else if (props.locked === 0) { + this.setState(STATE_NEAR_GRABBING); } } }; @@ -816,6 +849,7 @@ function MyController(hand, triggerAction) { // the action will tend to quickly bring an object's velocity to zero. now that // the action is gone, set the objects velocity to something the holder might expect. + print("release velocity is " + vec3toStr(this.grabbedVelocity)); Entities.editEntity(this.grabbedEntity, { velocity: this.grabbedVelocity }); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 6832b8daff..42aaea33c2 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -146,7 +146,7 @@ MotionType EntityMotionState::computeObjectMotionType() const { if (_entity->getCollisionsWillMove()) { return MOTION_TYPE_DYNAMIC; } - return _entity->isMoving() ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; + return (_entity->isMoving() || _entity->hasActions()) ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; } bool EntityMotionState::isMoving() const { @@ -184,6 +184,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { if (!_entity) { return; } + assert(entityTreeIsLocked()); measureBodyAcceleration(); _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index c7dddb95c4..f725315330 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -102,6 +102,8 @@ void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { return; } else { objectMotionState->clearInternalKinematicChanges(); + body->getMotionState()->setWorldTransform(body->getWorldTransform()); + return; } } btTransform interpolatedTransform;