Merge pull request #10468 from AndrewMeadows/cleanup-actions

cleanup Actions and Constraints part-1
This commit is contained in:
Seth Alves 2017-05-17 11:33:53 -07:00 committed by GitHub
commit 8a88b30da7
14 changed files with 49 additions and 585 deletions

View file

@ -53,31 +53,3 @@ QVariantMap AssignmentDynamic::getArguments() {
qDebug() << "UNEXPECTED -- AssignmentDynamic::getArguments called in assignment-client.";
return QVariantMap();
}
glm::vec3 AssignmentDynamic::getPosition() {
qDebug() << "UNEXPECTED -- AssignmentDynamic::getPosition called in assignment-client.";
return glm::vec3(0.0f);
}
glm::quat AssignmentDynamic::getRotation() {
qDebug() << "UNEXPECTED -- AssignmentDynamic::getRotation called in assignment-client.";
return glm::quat();
}
glm::vec3 AssignmentDynamic::getLinearVelocity() {
qDebug() << "UNEXPECTED -- AssignmentDynamic::getLinearVelocity called in assignment-client.";
return glm::vec3(0.0f);
}
void AssignmentDynamic::setLinearVelocity(glm::vec3 linearVelocity) {
qDebug() << "UNEXPECTED -- AssignmentDynamic::setLinearVelocity called in assignment-client.";
}
glm::vec3 AssignmentDynamic::getAngularVelocity() {
qDebug() << "UNEXPECTED -- AssignmentDynamic::getAngularVelocity called in assignment-client.";
return glm::vec3(0.0f);
}
void AssignmentDynamic::setAngularVelocity(glm::vec3 angularVelocity) {
qDebug() << "UNEXPECTED -- AssignmentDynamic::setAngularVelocity called in assignment-client.";
}

View file

@ -39,13 +39,6 @@ private:
QByteArray _data;
protected:
virtual glm::vec3 getPosition() override;
virtual glm::quat getRotation() override;
virtual glm::vec3 getLinearVelocity() override;
virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
virtual glm::vec3 getAngularVelocity() override;
virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
bool _active;
EntityItemWeakPointer _ownerEntity;
};

View file

@ -14,7 +14,6 @@
#include <avatar/AvatarActionHold.h>
#include <avatar/AvatarActionFarGrab.h>
#include <ObjectActionOffset.h>
#include <ObjectActionSpring.h>
#include <ObjectActionTractor.h>
#include <ObjectActionTravelOriented.h>
#include <ObjectConstraintHinge.h>
@ -33,7 +32,7 @@ EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid
case DYNAMIC_TYPE_OFFSET:
return std::make_shared<ObjectActionOffset>(id, ownerEntity);
case DYNAMIC_TYPE_SPRING:
return std::make_shared<ObjectActionSpring>(id, ownerEntity);
qDebug() << "The 'spring' Action is deprecated. Replacing with 'tractor' Action.";
case DYNAMIC_TYPE_TRACTOR:
return std::make_shared<ObjectActionTractor>(id, ownerEntity);
case DYNAMIC_TYPE_HOLD:

View file

@ -43,14 +43,14 @@
| |
+--------------------+ +-----------------------+
| | | |
| ObjectActionSpring | | ObjectConstraintHinge |
| ObjectActionTractor| | ObjectConstraintHinge |
| (physics) | | (physics) |
+--------------------+ +-----------------------+
A dynamic is a callback which is registered with bullet. A dynamic is called-back every physics
simulation step and can do whatever it wants with the various datastructures it has available. An
simulation step and can do whatever it wants with the various datastructures it has available. A
dynamic, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that
point by a spring.
@ -60,7 +60,7 @@ script or when receiving information via an EntityTree data-stream (either over
svo file).
In the interface, if an EntityItem has dynamics, this EntityItem will have pointers to ObjectDynamic
subclass (like ObjectDynamicSpring) instantiations. Code in the entities library affects a dynamic-object
subclass (like ObjectDynamicTractor) instantiations. Code in the entities library affects a dynamic-object
via the EntityDynamicInterface (which knows nothing about bullet). When the ObjectDynamic subclass
instance is created, it is registered as a dynamic with bullet. Bullet will call into code in this
instance with the btDynamicInterface every physics-simulation step.
@ -75,11 +75,11 @@ right now the AssignmentDynamic class is a place-holder.
The dynamic-objects are instantiated by singleton (dependecy) subclasses of EntityDynamicFactoryInterface.
In the interface, the subclass is an InterfaceDynamicFactory and it will produce things like
ObjectDynamicSpring. In an entity-server the subclass is an AssignmentDynamicFactory and it always
ObjectDynamicTractor. In an entity-server the subclass is an AssignmentDynamicFactory and it always
produces AssignmentDynamics.
Depending on the dynamic's type, it will have various arguments. When a script changes an argument of an
dynamic, the argument-holding member-variables of ObjectDynamicSpring (in this example) are updated and
dynamic, the argument-holding member-variables of ObjectDynamicTractor (in this example) are updated and
also serialized into _dynamicData in the EntityItem. Each subclass of ObjectDynamic knows how to serialize
and deserialize its own arguments. _dynamicData is what gets sent over the wire or saved in an svo file.
When a packet-reader receives data for _dynamicData, it will save it in the EntityItem; this causes the
@ -103,7 +103,7 @@ EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicT
return DYNAMIC_TYPE_OFFSET;
}
if (normalizedDynamicTypeString == "spring") {
return DYNAMIC_TYPE_SPRING;
return DYNAMIC_TYPE_TRACTOR;
}
if (normalizedDynamicTypeString == "tractor") {
return DYNAMIC_TYPE_TRACTOR;
@ -142,7 +142,6 @@ QString EntityDynamicInterface::dynamicTypeToString(EntityDynamicType dynamicTyp
case DYNAMIC_TYPE_OFFSET:
return "offset";
case DYNAMIC_TYPE_SPRING:
return "spring";
case DYNAMIC_TYPE_TRACTOR:
return "tractor";
case DYNAMIC_TYPE_HOLD:

View file

@ -94,15 +94,6 @@ public:
QString argumentName, bool& ok, bool required = true);
protected:
virtual glm::vec3 getPosition() = 0;
// virtual void setPosition(glm::vec3 position) = 0;
virtual glm::quat getRotation() = 0;
// virtual void setRotation(glm::quat rotation) = 0;
virtual glm::vec3 getLinearVelocity() = 0;
virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0;
virtual glm::vec3 getAngularVelocity() = 0;
virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0;
QUuid _id;
EntityDynamicType _type;
bool _active { false };

View file

@ -1,378 +0,0 @@
//
// ObjectActionSpring.cpp
// libraries/physics/src
//
// Created by Seth Alves 2015-6-5
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "QVariantGLM.h"
#include "ObjectActionSpring.h"
#include "PhysicsLogging.h"
const float SPRING_MAX_SPEED = 10.0f;
const float MAX_SPRING_TIMESCALE = 600.0f; // 10 min is a long time
const uint16_t ObjectActionSpring::springVersion = 1;
ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) :
ObjectAction(DYNAMIC_TYPE_SPRING, id, ownerEntity),
_positionalTarget(glm::vec3(0.0f)),
_desiredPositionalTarget(glm::vec3(0.0f)),
_linearTimeScale(FLT_MAX),
_positionalTargetSet(true),
_rotationalTarget(glm::quat()),
_desiredRotationalTarget(glm::quat()),
_angularTimeScale(FLT_MAX),
_rotationalTargetSet(true) {
#if WANT_DEBUG
qCDebug(physics) << "ObjectActionSpring::ObjectActionSpring";
#endif
}
ObjectActionSpring::~ObjectActionSpring() {
#if WANT_DEBUG
qCDebug(physics) << "ObjectActionSpring::~ObjectActionSpring";
#endif
}
bool ObjectActionSpring::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
float& linearTimeScale, float& angularTimeScale) {
SpatiallyNestablePointer other = getOther();
withReadLock([&]{
linearTimeScale = _linearTimeScale;
angularTimeScale = _angularTimeScale;
if (!_otherID.isNull()) {
if (other) {
rotation = _desiredRotationalTarget * other->getRotation();
position = other->getRotation() * _desiredPositionalTarget + other->getPosition();
} else {
// we should have an "other" but can't find it, so disable the spring.
linearTimeScale = FLT_MAX;
angularTimeScale = FLT_MAX;
}
} else {
rotation = _desiredRotationalTarget;
position = _desiredPositionalTarget;
}
linearVelocity = glm::vec3();
angularVelocity = glm::vec3();
});
return true;
}
bool ObjectActionSpring::prepareForSpringUpdate(btScalar deltaTimeStep) {
auto ownerEntity = _ownerEntity.lock();
if (!ownerEntity) {
return false;
}
glm::quat rotation;
glm::vec3 position;
glm::vec3 linearVelocity;
glm::vec3 angularVelocity;
bool linearValid = false;
int linearSpringCount = 0;
bool angularValid = false;
int angularSpringCount = 0;
QList<EntityDynamicPointer> springDerivedActions;
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_SPRING));
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_FAR_GRAB));
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_HOLD));
foreach (EntityDynamicPointer action, springDerivedActions) {
std::shared_ptr<ObjectActionSpring> springAction = std::static_pointer_cast<ObjectActionSpring>(action);
glm::quat rotationForAction;
glm::vec3 positionForAction;
glm::vec3 linearVelocityForAction;
glm::vec3 angularVelocityForAction;
float linearTimeScale;
float angularTimeScale;
bool success = springAction->getTarget(deltaTimeStep,
rotationForAction, positionForAction,
linearVelocityForAction, angularVelocityForAction,
linearTimeScale, angularTimeScale);
if (success) {
if (angularTimeScale < MAX_SPRING_TIMESCALE) {
angularValid = true;
angularSpringCount++;
angularVelocity += angularVelocityForAction;
if (springAction.get() == this) {
// only use the rotation for this action
rotation = rotationForAction;
}
}
if (linearTimeScale < MAX_SPRING_TIMESCALE) {
linearValid = true;
linearSpringCount++;
position += positionForAction;
linearVelocity += linearVelocityForAction;
}
}
}
if ((angularValid && angularSpringCount > 0) || (linearValid && linearSpringCount > 0)) {
withWriteLock([&]{
if (linearValid && linearSpringCount > 0) {
position /= linearSpringCount;
linearVelocity /= linearSpringCount;
_positionalTarget = position;
_linearVelocityTarget = linearVelocity;
_positionalTargetSet = true;
_active = true;
}
if (angularValid && angularSpringCount > 0) {
angularVelocity /= angularSpringCount;
_rotationalTarget = rotation;
_angularVelocityTarget = angularVelocity;
_rotationalTargetSet = true;
_active = true;
}
});
}
return linearValid || angularValid;
}
void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
if (!prepareForSpringUpdate(deltaTimeStep)) {
return;
}
withReadLock([&]{
auto ownerEntity = _ownerEntity.lock();
if (!ownerEntity) {
return;
}
void* physicsInfo = ownerEntity->getPhysicsInfo();
if (!physicsInfo) {
return;
}
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
btRigidBody* rigidBody = motionState->getRigidBody();
if (!rigidBody) {
qCDebug(physics) << "ObjectActionSpring::updateActionWorker no rigidBody";
return;
}
if (_linearTimeScale < MAX_SPRING_TIMESCALE) {
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
float offsetLength = offset.length();
if (offsetLength > FLT_EPSILON) {
float speed = glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED);
targetVelocity = (-speed / offsetLength) * offset;
if (speed > rigidBody->getLinearSleepingThreshold()) {
forceBodyNonStatic();
rigidBody->activate();
}
}
// this action is aggresively critically damped and defeats the current velocity
rigidBody->setLinearVelocity(targetVelocity);
}
if (_angularTimeScale < MAX_SPRING_TIMESCALE) {
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
btQuaternion bodyRotation = rigidBody->getOrientation();
auto alignmentDot = bodyRotation.dot(glmToBullet(_rotationalTarget));
const float ALMOST_ONE = 0.99999f;
if (glm::abs(alignmentDot) < ALMOST_ONE) {
btQuaternion target = glmToBullet(_rotationalTarget);
if (alignmentDot < 0.0f) {
target = -target;
}
// if dQ is the incremental rotation that gets an object from Q0 to Q1 then:
//
// Q1 = dQ * Q0
//
// solving for dQ gives:
//
// dQ = Q1 * Q0^
btQuaternion deltaQ = target * bodyRotation.inverse();
float speed = deltaQ.getAngle() / _angularTimeScale;
targetVelocity = speed * deltaQ.getAxis();
if (speed > rigidBody->getAngularSleepingThreshold()) {
rigidBody->activate();
}
}
// this action is aggresively critically damped and defeats the current velocity
rigidBody->setAngularVelocity(targetVelocity);
}
});
}
const float MIN_TIMESCALE = 0.1f;
bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
glm::vec3 positionalTarget;
float linearTimeScale;
glm::quat rotationalTarget;
float angularTimeScale;
QUuid otherID;
bool needUpdate = false;
bool somethingChanged = ObjectDynamic::updateArguments(arguments);
withReadLock([&]{
// targets are required, spring-constants are optional
bool ok = true;
positionalTarget = EntityDynamicInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false);
if (!ok) {
positionalTarget = _desiredPositionalTarget;
}
ok = true;
linearTimeScale = EntityDynamicInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false);
if (!ok || linearTimeScale <= 0.0f) {
linearTimeScale = _linearTimeScale;
}
ok = true;
rotationalTarget = EntityDynamicInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false);
if (!ok) {
rotationalTarget = _desiredRotationalTarget;
}
ok = true;
angularTimeScale =
EntityDynamicInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false);
if (!ok) {
angularTimeScale = _angularTimeScale;
}
ok = true;
otherID = QUuid(EntityDynamicInterface::extractStringArgument("spring action",
arguments, "otherID", ok, false));
if (!ok) {
otherID = _otherID;
}
if (somethingChanged ||
positionalTarget != _desiredPositionalTarget ||
linearTimeScale != _linearTimeScale ||
rotationalTarget != _desiredRotationalTarget ||
angularTimeScale != _angularTimeScale ||
otherID != _otherID) {
// something changed
needUpdate = true;
}
});
if (needUpdate) {
withWriteLock([&] {
_desiredPositionalTarget = positionalTarget;
_linearTimeScale = glm::max(MIN_TIMESCALE, glm::abs(linearTimeScale));
_desiredRotationalTarget = rotationalTarget;
_angularTimeScale = glm::max(MIN_TIMESCALE, glm::abs(angularTimeScale));
_otherID = otherID;
_active = true;
auto ownerEntity = _ownerEntity.lock();
if (ownerEntity) {
ownerEntity->setDynamicDataDirty(true);
ownerEntity->setDynamicDataNeedsTransmit(true);
}
});
activateBody();
}
return true;
}
QVariantMap ObjectActionSpring::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {
arguments["linearTimeScale"] = _linearTimeScale;
arguments["targetPosition"] = glmToQMap(_desiredPositionalTarget);
arguments["targetRotation"] = glmToQMap(_desiredRotationalTarget);
arguments["angularTimeScale"] = _angularTimeScale;
arguments["otherID"] = _otherID;
});
return arguments;
}
void ObjectActionSpring::serializeParameters(QDataStream& dataStream) const {
withReadLock([&] {
dataStream << _desiredPositionalTarget;
dataStream << _linearTimeScale;
dataStream << _positionalTargetSet;
dataStream << _desiredRotationalTarget;
dataStream << _angularTimeScale;
dataStream << _rotationalTargetSet;
dataStream << localTimeToServerTime(_expires);
dataStream << _tag;
dataStream << _otherID;
});
}
QByteArray ObjectActionSpring::serialize() const {
QByteArray serializedActionArguments;
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
dataStream << DYNAMIC_TYPE_SPRING;
dataStream << getID();
dataStream << ObjectActionSpring::springVersion;
serializeParameters(dataStream);
return serializedActionArguments;
}
void ObjectActionSpring::deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream) {
withWriteLock([&] {
dataStream >> _desiredPositionalTarget;
dataStream >> _linearTimeScale;
dataStream >> _positionalTargetSet;
dataStream >> _desiredRotationalTarget;
dataStream >> _angularTimeScale;
dataStream >> _rotationalTargetSet;
quint64 serverExpires;
dataStream >> serverExpires;
_expires = serverTimeToLocalTime(serverExpires);
dataStream >> _tag;
dataStream >> _otherID;
_active = true;
});
}
void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
QDataStream dataStream(serializedArguments);
EntityDynamicType type;
dataStream >> type;
assert(type == getType());
QUuid id;
dataStream >> id;
assert(id == getID());
uint16_t serializationVersion;
dataStream >> serializationVersion;
if (serializationVersion != ObjectActionSpring::springVersion) {
assert(false);
return;
}
deserializeParameters(serializedArguments, dataStream);
}

View file

@ -1,56 +0,0 @@
//
// ObjectActionSpring.h
// libraries/physics/src
//
// Created by Seth Alves 2015-6-5
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_ObjectActionSpring_h
#define hifi_ObjectActionSpring_h
#include "ObjectAction.h"
class ObjectActionSpring : public ObjectAction {
public:
ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectActionSpring();
virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep) override;
virtual QByteArray serialize() const override;
virtual void deserialize(QByteArray serializedArguments) override;
virtual bool getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
float& linearTimeScale, float& angularTimeScale);
protected:
static const uint16_t springVersion;
glm::vec3 _positionalTarget;
glm::vec3 _desiredPositionalTarget;
float _linearTimeScale;
bool _positionalTargetSet;
glm::quat _rotationalTarget;
glm::quat _desiredRotationalTarget;
float _angularTimeScale;
bool _rotationalTargetSet;
glm::vec3 _linearVelocityTarget;
glm::vec3 _angularVelocityTarget;
virtual bool prepareForSpringUpdate(btScalar deltaTimeStep);
void serializeParameters(QDataStream& dataStream) const;
void deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream);
};
#endif // hifi_ObjectActionSpring_h

View file

@ -160,56 +160,6 @@ btRigidBody* ObjectDynamic::getRigidBody() {
return nullptr;
}
glm::vec3 ObjectDynamic::getPosition() {
auto rigidBody = getRigidBody();
if (!rigidBody) {
return glm::vec3(0.0f);
}
return bulletToGLM(rigidBody->getCenterOfMassPosition());
}
glm::quat ObjectDynamic::getRotation() {
auto rigidBody = getRigidBody();
if (!rigidBody) {
return glm::quat(0.0f, 0.0f, 0.0f, 1.0f);
}
return bulletToGLM(rigidBody->getOrientation());
}
glm::vec3 ObjectDynamic::getLinearVelocity() {
auto rigidBody = getRigidBody();
if (!rigidBody) {
return glm::vec3(0.0f);
}
return bulletToGLM(rigidBody->getLinearVelocity());
}
void ObjectDynamic::setLinearVelocity(glm::vec3 linearVelocity) {
auto rigidBody = getRigidBody();
if (!rigidBody) {
return;
}
rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f)));
rigidBody->activate();
}
glm::vec3 ObjectDynamic::getAngularVelocity() {
auto rigidBody = getRigidBody();
if (!rigidBody) {
return glm::vec3(0.0f);
}
return bulletToGLM(rigidBody->getAngularVelocity());
}
void ObjectDynamic::setAngularVelocity(glm::vec3 angularVelocity) {
auto rigidBody = getRigidBody();
if (!rigidBody) {
return;
}
rigidBody->setAngularVelocity(glmToBullet(angularVelocity));
rigidBody->activate();
}
void ObjectDynamic::activateBody(bool forceActivation) {
auto rigidBody = getRigidBody();
if (rigidBody) {

View file

@ -56,12 +56,6 @@ protected:
btRigidBody* getOtherRigidBody(EntityItemID otherEntityID);
EntityItemPointer getEntityByID(EntityItemID entityID) const;
virtual btRigidBody* getRigidBody();
virtual glm::vec3 getPosition() override;
virtual glm::quat getRotation() override;
virtual glm::vec3 getLinearVelocity() override;
virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
virtual glm::vec3 getAngularVelocity() override;
virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
virtual void activateBody(bool forceActivation = false);
virtual void forceBodyNonStatic();

View file

@ -1,6 +1,6 @@
// shopItemGrab.js
//
// Semplified and coarse version of handControllerGrab.js with the addition of the ownerID concept.
// Simplified and coarse version of handControllerGrab.js with the addition of the ownerID concept.
// This grab is the only one which should run in the vrShop. It allows only near grab and add the feature of checking the ownerID. (See shopGrapSwapperEntityScript.js)
//
@ -63,8 +63,8 @@ var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-g
// equip
//
var EQUIP_SPRING_SHUTOFF_DISTANCE = 0.05;
var EQUIP_SPRING_TIMEFRAME = 0.4; // how quickly objects move to their new position
var EQUIP_TRACTOR_SHUTOFF_DISTANCE = 0.05;
var EQUIP_TRACTOR_TIMEFRAME = 0.4; // how quickly objects move to their new position
//
// other constants
@ -121,7 +121,7 @@ var STATE_EQUIP_SEARCHING = 11;
var STATE_EQUIP = 12
var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down
var STATE_CONTINUE_EQUIP = 14;
var STATE_EQUIP_SPRING = 16;
var STATE_EQUIP_TRACTOR = 16;
function stateToName(state) {
@ -152,8 +152,8 @@ function stateToName(state) {
return "continue_equip_bd";
case STATE_CONTINUE_EQUIP:
return "continue_equip";
case STATE_EQUIP_SPRING:
return "state_equip_spring";
case STATE_EQUIP_TRACTOR:
return "state_equip_tractor";
}
return "unknown";
@ -216,7 +216,7 @@ function MyController(hand) {
case STATE_EQUIP:
this.nearGrabbing();
break;
case STATE_EQUIP_SPRING:
case STATE_EQUIP_TRACTOR:
this.pullTowardEquipPosition()
break;
case STATE_CONTINUE_NEAR_GRABBING:
@ -404,14 +404,14 @@ function MyController(hand) {
return;
} else if (!properties.locked) {
var ownerObj = getEntityCustomData('ownerKey', intersection.entityID, null);
if (ownerObj == null || ownerObj.ownerID === MyAvatar.sessionUUID) { //I can only grab new or already mine items
this.grabbedEntity = intersection.entityID;
if (this.state == STATE_SEARCHING) {
this.setState(STATE_NEAR_GRABBING);
} else { // equipping
if (typeof grabbableData.spatialKey !== 'undefined') {
this.setState(STATE_EQUIP_SPRING);
this.setState(STATE_EQUIP_TRACTOR);
} else {
this.setState(STATE_EQUIP);
}
@ -558,7 +558,7 @@ function MyController(hand) {
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
// use a spring to pull the object to where it will be when equipped
// use a tractor to pull the object to where it will be when equipped
var relativeRotation = {
x: 0.0,
y: 0.0,
@ -582,34 +582,34 @@ function MyController(hand) {
var offset = Vec3.multiplyQbyV(targetRotation, relativePosition);
var targetPosition = Vec3.sum(handPosition, offset);
if (typeof this.equipSpringID === 'undefined' ||
this.equipSpringID === null ||
this.equipSpringID === NULL_ACTION_ID) {
this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, {
if (typeof this.equipTractorID === 'undefined' ||
this.equipTractorID === null ||
this.equipTractorID === NULL_ACTION_ID) {
this.equipTractorID = Entities.addAction("tractor", this.grabbedEntity, {
targetPosition: targetPosition,
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
linearTimeScale: EQUIP_TRACTOR_TIMEFRAME,
targetRotation: targetRotation,
angularTimeScale: EQUIP_SPRING_TIMEFRAME,
angularTimeScale: EQUIP_TRACTOR_TIMEFRAME,
ttl: ACTION_TTL
});
if (this.equipSpringID === NULL_ACTION_ID) {
this.equipSpringID = null;
if (this.equipTractorID === NULL_ACTION_ID) {
this.equipTractorID = null;
this.setState(STATE_OFF);
return;
}
} else {
Entities.updateAction(this.grabbedEntity, this.equipSpringID, {
Entities.updateAction(this.grabbedEntity, this.equipTractorID, {
targetPosition: targetPosition,
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
linearTimeScale: EQUIP_TRACTOR_TIMEFRAME,
targetRotation: targetRotation,
angularTimeScale: EQUIP_SPRING_TIMEFRAME,
angularTimeScale: EQUIP_TRACTOR_TIMEFRAME,
ttl: ACTION_TTL
});
}
if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_SPRING_SHUTOFF_DISTANCE) {
Entities.deleteAction(this.grabbedEntity, this.equipSpringID);
this.equipSpringID = null;
if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_TRACTOR_SHUTOFF_DISTANCE) {
Entities.deleteAction(this.grabbedEntity, this.equipTractorID);
this.equipTractorID = null;
this.setState(STATE_EQUIP);
}
};
@ -862,4 +862,4 @@ function cleanup() {
}
Script.scriptEnding.connect(cleanup);
Script.update.connect(update);
Script.update.connect(update);

View file

@ -28,7 +28,7 @@
function coneTwistAndSpringLeverTest(params) {
function coneTwistAndTractorLeverTest(params) {
var pos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, {x: 0, y: -0.5, z: -2}));
var lifetime = params.lifetime;
@ -84,10 +84,10 @@
tag: "cone-twist test"
});
Entities.addAction("spring", leverID, {
Entities.addAction("tractor", leverID, {
targetRotation: { x: 0, y: 0, z: 0, w: 1 },
angularTimeScale: 0.2,
tag: "cone-twist test spring"
tag: "cone-twist test tractor"
});
@ -349,11 +349,11 @@
userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }"
});
Entities.addAction("spring", headID, {
Entities.addAction("tractor", headID, {
targetRotation: { x: 0, y: 0, z: 0, w: 1 },
angularTimeScale: 2.0,
otherID: bodyID,
tag: "cone-twist test spring"
tag: "cone-twist test tractor"
});
@ -705,7 +705,7 @@
if (event["dynamics-tests-command"]) {
var commandToFunctionMap = {
"cone-twist-and-spring-lever-test": coneTwistAndSpringLeverTest,
"cone-twist-and-tractor-lever-test": coneTwistAndTractorLeverTest,
"door-vs-world-test": doorVSWorldTest,
"hinge-chain-test": hingeChainTest,
"slider-vs-world-test": sliderVSWorldTest,

View file

@ -113,4 +113,4 @@
};
return new SpringHold();
});
});

View file

@ -2,7 +2,7 @@
// touch.js
//
// Sample file using spring action, haptic vibration, and color change to demonstrate two spheres
// Sample file using tractor action, haptic vibration, and color change to demonstrate two spheres
// That can give a sense of touch to the holders.
// Create two standard spheres, make them grabbable, and attach this entity script. Grab them and touch them together.
//
@ -53,7 +53,7 @@
_this = this;
}
function updateSpringAction(timescale) {
function updateTractorAction(timescale) {
var targetProps = Entities.getEntityProperties(_this.entityID);
//
// Look for nearby entities to touch
@ -113,7 +113,7 @@
var success = Entities.updateAction(_this.copy, _this.actionID, props);
}
function createSpringAction(timescale) {
function createTractorAction(timescale) {
var targetProps = Entities.getEntityProperties(_this.entityID);
var props = {
@ -123,7 +123,7 @@
angularTimeScale: timescale,
ttl: ACTION_TTL
};
_this.actionID = Entities.addAction("spring", _this.copy, props);
_this.actionID = Entities.addAction("tractor", _this.copy, props);
return;
}
@ -170,7 +170,7 @@
});
}
function deleteSpringAction() {
function deleteTractorAction() {
Entities.deleteAction(_this.copy, _this.actionID);
}
@ -188,19 +188,19 @@
},
startNearGrab: function(entityID, data) {
createCopy();
createSpringAction(TIMESCALE);
createTractorAction(TIMESCALE);
makeOriginalInvisible();
setHand(Entities.getEntityProperties(_this.entityID).position);
},
continueNearGrab: function() {
updateSpringAction(TIMESCALE);
updateTractorAction(TIMESCALE);
},
releaseGrab: function() {
deleteSpringAction();
deleteTractorAction();
deleteCopy();
makeOriginalVisible();
}
};
return new TouchExample();
});
});

View file

@ -89,7 +89,7 @@ LookAtTarget = function(sourceEntityID) {
}
});
if (!actionFound) {
Entities.addAction('spring', _sourceEntityID, getNewActionProperties());
Entities.addAction('tractor', _sourceEntityID, getNewActionProperties());
}
}
};