entity server has its own version of actions which simply remember the encoded arguments. Entities with actions don't experience simulateKinematicMotion

This commit is contained in:
Seth Alves 2015-06-19 16:20:07 -07:00
parent 6deedd19a3
commit 5381e6e9bb
20 changed files with 317 additions and 61 deletions

View file

@ -0,0 +1,38 @@
//
// AssignmentAction.cpp
// assignment-client/src/
//
// Created by Seth Alves 2015-6-19
// 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 "EntitySimulation.h"
#include "AssignmentAction.h"
AssignmentAction::AssignmentAction(EntityActionType type, QUuid id, EntityItemPointer ownerEntity) :
_id(id),
_type(type),
_data(QByteArray()),
_active(false),
_ownerEntity(ownerEntity) {
}
AssignmentAction::~AssignmentAction() {
}
void AssignmentAction::removeFromSimulation(EntitySimulation* simulation) const {
simulation->removeAction(_id);
}
QByteArray AssignmentAction::serialize() {
return _data;
}
void AssignmentAction::deserialize(QByteArray serializedArguments) {
qDebug() << "setting data to" << serializedArguments.size() << "bytes";
_data = serializedArguments;
}

View file

@ -0,0 +1,64 @@
//
// AssignmentAction.h
// assignment-client/src/
//
// Created by Seth Alves 2015-6-19
// 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
//
// http://bulletphysics.org/Bullet/BulletFull/classbtActionInterface.html
#ifndef hifi_AssignmentAction_h
#define hifi_AssignmentAction_h
#include <QUuid>
#include <EntityItem.h>
#include "EntityActionInterface.h"
class AssignmentAction : public EntityActionInterface {
public:
AssignmentAction(EntityActionType type, QUuid id, EntityItemPointer ownerEntity);
virtual ~AssignmentAction();
const QUuid& getID() const { return _id; }
virtual EntityActionType getType() { return _type; }
virtual void removeFromSimulation(EntitySimulation* simulation) const;
virtual const EntityItemPointer& getOwnerEntity() const { return _ownerEntity; }
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; }
virtual bool updateArguments(QVariantMap arguments) { assert(false); return false; }
virtual QByteArray serialize();
virtual void deserialize(QByteArray serializedArguments);
private:
QUuid _id;
EntityActionType _type;
// QReadWriteLock _lock;
QByteArray _data;
protected:
// bool tryLockForRead() { return _lock.tryLockForRead(); }
// void lockForWrite() { _lock.lockForWrite(); }
// bool tryLockForWrite() { return _lock.tryLockForWrite(); }
// void unlock() { _lock.unlock(); }
virtual glm::vec3 getPosition() { assert(false); return glm::vec3(0.0f); }
virtual void setPosition(glm::vec3 position) { assert(false); }
virtual glm::quat getRotation() { assert(false); return glm::quat(); }
virtual void setRotation(glm::quat rotation) { assert(false); }
virtual glm::vec3 getLinearVelocity() { assert(false); return glm::vec3(0.0f); }
virtual void setLinearVelocity(glm::vec3 linearVelocity) { assert(false); }
virtual glm::vec3 getAngularVelocity() { assert(false); return glm::vec3(0.0f); }
virtual void setAngularVelocity(glm::vec3 angularVelocity) { assert(false); }
bool _active;
EntityItemPointer _ownerEntity;
};
#endif // hifi_AssignmentAction_h

View file

@ -0,0 +1,52 @@
//
// AssignmentActionFactory.cpp
// assignment-client/src/
//
// Created by Seth Alves on 2015-6-19
// 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 "AssignmentActionFactory.h"
EntityActionPointer assignmentActionFactory(EntityActionType type, QUuid id, EntityItemPointer ownerEntity) {
return (EntityActionPointer) new AssignmentAction(type, id, ownerEntity);
}
EntityActionPointer AssignmentActionFactory::factory(EntitySimulation* simulation,
EntityActionType type,
QUuid id,
EntityItemPointer ownerEntity,
QVariantMap arguments) {
EntityActionPointer action = assignmentActionFactory(type, id, ownerEntity);
if (action) {
bool ok = action->updateArguments(arguments);
if (ok) {
ownerEntity->addAction(simulation, action);
return action;
}
}
return action;
}
EntityActionPointer AssignmentActionFactory::factoryBA(EntitySimulation* simulation,
EntityItemPointer ownerEntity,
QByteArray data) {
QDataStream ds(data);
EntityActionType type;
QUuid id;
ds >> type;
ds >> id;
EntityActionPointer action = assignmentActionFactory(type, id, ownerEntity);
action->deserialize(data);
ownerEntity->addAction(simulation, action);
return action;
}

View file

@ -0,0 +1,32 @@
//
// AssignmentActionFactory.cpp
// assignment-client/src/
//
// Created by Seth Alves on 2015-6-19
// 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_AssignmentActionFactory_h
#define hifi_AssignmentActionFactory_h
#include "EntityActionFactoryInterface.h"
#include "AssignmentAction.h"
class AssignmentActionFactory : public EntityActionFactoryInterface {
public:
AssignmentActionFactory() : EntityActionFactoryInterface() { }
virtual ~AssignmentActionFactory() { }
virtual EntityActionPointer factory(EntitySimulation* simulation,
EntityActionType type,
QUuid id,
EntityItemPointer ownerEntity,
QVariantMap arguments);
virtual EntityActionPointer factoryBA(EntitySimulation* simulation,
EntityItemPointer ownerEntity,
QByteArray data);
};
#endif // hifi_AssignmentActionFactory_h

View file

@ -32,6 +32,7 @@
#include <SoundCache.h>
#include "AssignmentFactory.h"
#include "AssignmentActionFactory.h"
#include "AssignmentClient.h"
@ -58,6 +59,9 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
auto entityScriptingInterface = DependencyManager::set<EntityScriptingInterface>();
DependencyManager::registerInheritance<EntityActionFactoryInterface, AssignmentActionFactory>();
auto actionFactory = DependencyManager::set<AssignmentActionFactory>();
// make up a uuid for this child so the parent can tell us apart. This id will be changed
// when the domain server hands over an assignment.
QUuid nodeUUID = QUuid::createUuid();

View file

@ -23,11 +23,11 @@ EntityActionPointer interfaceActionFactory(EntityActionType type, QUuid id, Enti
case ACTION_TYPE_NONE:
return nullptr;
case ACTION_TYPE_OFFSET:
return (EntityActionPointer) new ObjectActionOffset(id, ownerEntity);
return (EntityActionPointer) new ObjectActionOffset(type, id, ownerEntity);
case ACTION_TYPE_SPRING:
return (EntityActionPointer) new ObjectActionSpring(id, ownerEntity);
return (EntityActionPointer) new ObjectActionSpring(type, id, ownerEntity);
case ACTION_TYPE_HOLD:
return (EntityActionPointer) new AvatarActionHold(id, ownerEntity);
return (EntityActionPointer) new AvatarActionHold(type, id, ownerEntity);
}
assert(false);
@ -64,7 +64,7 @@ EntityActionPointer InterfaceActionFactory::factoryBA(EntitySimulation* simulati
EntityActionPointer action = interfaceActionFactory(type, id, ownerEntity);
action->deserializeFromDataStream(ds);
action->deserialize(data);
ownerEntity->addAction(simulation, action);
return action;
}

View file

@ -14,8 +14,8 @@
#include "AvatarActionHold.h"
AvatarActionHold::AvatarActionHold(QUuid id, EntityItemPointer ownerEntity) :
ObjectActionSpring(id, ownerEntity) {
AvatarActionHold::AvatarActionHold(EntityActionType type, QUuid id, EntityItemPointer ownerEntity) :
ObjectActionSpring(type, id, ownerEntity) {
#if WANT_DEBUG
qDebug() << "AvatarActionHold::AvatarActionHold";
#endif
@ -116,15 +116,35 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
return true;
}
void AvatarActionHold::serializeToDataStream(QDataStream& dataStream) {
QByteArray AvatarActionHold::serialize() {
QByteArray ba;
QDataStream dataStream(&ba, QIODevice::WriteOnly);
dataStream << getType();
dataStream << getID();
dataStream << _relativePosition;
dataStream << _relativeRotation;
dataStream << _hand;
return ba;
}
void AvatarActionHold::deserializeFromDataStream(QDataStream& dataStream) {
void AvatarActionHold::deserialize(QByteArray serializedArguments) {
QDataStream dataStream(serializedArguments);
EntityActionType type;
QUuid id;
dataStream >> type;
dataStream >> id;
assert(type == getType());
assert(id == getID());
dataStream >> _relativePosition;
dataStream >> _relativeRotation;
dataStream >> _hand;
_parametersSet = true;
_active = true;
}

View file

@ -19,7 +19,7 @@
class AvatarActionHold : public ObjectActionSpring {
public:
AvatarActionHold(QUuid id, EntityItemPointer ownerEntity);
AvatarActionHold(EntityActionType type, QUuid id, EntityItemPointer ownerEntity);
virtual ~AvatarActionHold();
virtual EntityActionType getType() { return ACTION_TYPE_HOLD; }
@ -27,9 +27,12 @@ public:
virtual bool updateArguments(QVariantMap arguments);
virtual void updateActionWorker(float deltaTimeStep);
virtual QByteArray serialize();
virtual void deserialize(QByteArray serializedArguments);
protected:
void serializeToDataStream(QDataStream& dataStream);
void deserializeFromDataStream(QDataStream& dataStream);
// void serializeToDataStream(QDataStream& dataStream);
// void deserializeFromDataStream(QDataStream& dataStream);
private:
glm::vec3 _relativePosition;

View file

@ -175,25 +175,14 @@ QString EntityActionInterface::extractStringArgument(QString objectName, QVarian
return v;
}
QByteArray EntityActionInterface::serialize() {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << getType();
ds << getID();
serializeToDataStream(ds);
return ba;
}
QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType)
{
return stream << (quint8)entityActionType;
return stream << (quint16)entityActionType;
}
QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType)
{
quint8 v;
quint16 v;
stream >> v;
entityActionType = (EntityActionType)v;
return stream;

View file

@ -20,10 +20,10 @@ class EntitySimulation;
enum EntityActionType {
// keep these synchronized with actionTypeFromString and actionTypeToString
ACTION_TYPE_NONE,
ACTION_TYPE_OFFSET,
ACTION_TYPE_SPRING,
ACTION_TYPE_HOLD
ACTION_TYPE_NONE = 0,
ACTION_TYPE_OFFSET = 1000,
ACTION_TYPE_SPRING = 2000,
ACTION_TYPE_HOLD = 3000
};
@ -39,9 +39,8 @@ public:
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) = 0;
virtual bool updateArguments(QVariantMap arguments) = 0;
virtual QByteArray serialize();
virtual void serializeToDataStream(QDataStream& dataStream) = 0;
virtual void deserializeFromDataStream(QDataStream& dataStream) = 0;
virtual QByteArray serialize() = 0;
virtual void deserialize(QByteArray serializedArguments) = 0;
static EntityActionType actionTypeFromString(QString actionTypeString);
static QString actionTypeToString(EntityActionType actionType);

View file

@ -761,6 +761,10 @@ void EntityItem::simulate(const quint64& now) {
}
void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
if (hasActions()) {
return;
}
if (hasAngularVelocity()) {
// angular damping
if (_angularDamping > 0.0f) {
@ -772,7 +776,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
}
float angularSpeed = glm::length(_angularVelocity);
const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.0017453f; // 0.0017453 rad/sec = 0.1f degrees/sec
if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) {
if (setFlags && angularSpeed > 0.0f) {
@ -780,8 +784,8 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
}
_angularVelocity = ENTITY_ITEM_ZERO_VEC3;
} else {
// for improved agreement with the way Bullet integrates rotations we use an approximation
// and break the integration into bullet-sized substeps
// for improved agreement with the way Bullet integrates rotations we use an approximation
// and break the integration into bullet-sized substeps
glm::quat rotation = getRotation();
float dt = timeElapsed;
while (dt > PHYSICS_ENGINE_FIXED_SUBSTEP) {
@ -1367,7 +1371,7 @@ bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer act
assert(action->getOwnerEntity().get() == this);
simulation->addAction(action);
return false;
return true;
}
bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionID, const QVariantMap& arguments) {
@ -1404,12 +1408,11 @@ void EntityItem::setActionData(QByteArray actionData) {
if (actionData.size() == 0) {
return;
}
QVector<QByteArray> serializedActions;
QDataStream ds(actionData);
ds >> serializedActions;
qDebug() << "EntityItem::setActionData" << actionData.size() << "bytes";
foreach(QByteArray serializedAction, serializedActions) {
QDataStream dsForAction(serializedAction);
EntityActionType actionType;
@ -1420,7 +1423,7 @@ void EntityItem::setActionData(QByteArray actionData) {
if (_objectActions.contains(actionID)) {
EntityActionPointer action = _objectActions[actionID];
// XXX make sure types match?
action->deserializeFromDataStream(dsForAction);
action->deserialize(serializedAction);
} else {
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
@ -1439,6 +1442,10 @@ void EntityItem::setActionData(QByteArray actionData) {
const QByteArray EntityItem::getActionData() const {
if (_objectActions.size() == 0) {
return QByteArray();
}
QVector<QByteArray> serializedActions;
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
while (i != _objectActions.end()) {
@ -1452,5 +1459,6 @@ const QByteArray EntityItem::getActionData() const {
QByteArray result;
QDataStream ds(&result, QIODevice::WriteOnly);
ds << serializedActions;
return result;
}

View file

@ -381,6 +381,7 @@ public:
void clearActions(EntitySimulation* simulation);
void setActionData(QByteArray actionData);
const QByteArray getActionData() const;
bool hasActions() { return !_objectActions.empty(); }
protected:

View file

@ -181,7 +181,6 @@ QString EntityItemProperties::getAnimationSettings() const {
void EntityItemProperties::setCreated(QDateTime &v) {
_created = v.toMSecsSinceEpoch() * 1000; // usec per msec
qDebug() << "EntityItemProperties::setCreated QDateTime" << v << _created;
}
void EntityItemProperties::debugDump() const {

View file

@ -13,7 +13,7 @@
#include "ObjectAction.h"
ObjectAction::ObjectAction(QUuid id, EntityItemPointer ownerEntity) :
ObjectAction::ObjectAction(EntityActionType type, QUuid id, EntityItemPointer ownerEntity) :
btActionInterface(),
_id(id),
_active(false),
@ -124,3 +124,12 @@ void ObjectAction::setAngularVelocity(glm::vec3 angularVelocity) {
rigidBody->setAngularVelocity(glmToBullet(angularVelocity));
rigidBody->activate();
}
QByteArray ObjectAction::serialize() {
assert(false);
return QByteArray();
}
void ObjectAction::deserialize(QByteArray serializedArguments) {
assert(false);
}

View file

@ -26,7 +26,7 @@
class ObjectAction : public btActionInterface, public EntityActionInterface {
public:
ObjectAction(QUuid id, EntityItemPointer ownerEntity);
ObjectAction(EntityActionType type, QUuid id, EntityItemPointer ownerEntity);
virtual ~ObjectAction();
const QUuid& getID() const { return _id; }
@ -43,13 +43,14 @@ public:
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
virtual void debugDraw(btIDebugDraw* debugDrawer);
virtual QByteArray serialize();
virtual void deserialize(QByteArray serializedArguments);
private:
QUuid _id;
QReadWriteLock _lock;
protected:
virtual void serializeToDataStream(QDataStream& dataStream) = 0;
virtual void deserializeFromDataStream(QDataStream& dataStream) = 0;
virtual btRigidBody* getRigidBody();
virtual glm::vec3 getPosition();

View file

@ -11,8 +11,8 @@
#include "ObjectActionOffset.h"
ObjectActionOffset::ObjectActionOffset(QUuid id, EntityItemPointer ownerEntity) :
ObjectAction(id, ownerEntity) {
ObjectActionOffset::ObjectActionOffset(EntityActionType type, QUuid id, EntityItemPointer ownerEntity) :
ObjectAction(type, id, ownerEntity) {
#if WANT_DEBUG
qDebug() << "ObjectActionOffset::ObjectActionOffset";
#endif
@ -108,16 +108,35 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
return true;
}
void ObjectActionOffset::serializeToDataStream(QDataStream& dataStream) {
QByteArray ObjectActionOffset::serialize() {
QByteArray ba;
QDataStream dataStream(&ba, QIODevice::WriteOnly);
dataStream << getType();
dataStream << getID();
dataStream << _pointToOffsetFrom;
dataStream << _linearDistance;
dataStream << _linearTimeScale;
dataStream << _positionalTargetSet;
return ba;
}
void ObjectActionOffset::deserializeFromDataStream(QDataStream& dataStream) {
void ObjectActionOffset::deserialize(QByteArray serializedArguments) {
QDataStream dataStream(serializedArguments);
EntityActionType type;
QUuid id;
dataStream >> type;
dataStream >> id;
assert(type == getType());
assert(id == getID());
dataStream >> _pointToOffsetFrom;
dataStream >> _linearDistance;
dataStream >> _linearTimeScale;
dataStream >> _positionalTargetSet;
_active = true;
}

View file

@ -19,7 +19,7 @@
class ObjectActionOffset : public ObjectAction {
public:
ObjectActionOffset(QUuid id, EntityItemPointer ownerEntity);
ObjectActionOffset(EntityActionType type, QUuid id, EntityItemPointer ownerEntity);
virtual ~ObjectActionOffset();
virtual EntityActionType getType() { return ACTION_TYPE_OFFSET; }
@ -27,11 +27,10 @@ public:
virtual bool updateArguments(QVariantMap arguments);
virtual void updateActionWorker(float deltaTimeStep);
protected:
virtual void serializeToDataStream(QDataStream& dataStream);
virtual void deserializeFromDataStream(QDataStream& dataStream);
virtual QByteArray serialize();
virtual void deserialize(QByteArray serializedArguments);
private:
private:
glm::vec3 _pointToOffsetFrom;
float _linearDistance;
float _linearTimeScale;

View file

@ -11,8 +11,8 @@
#include "ObjectActionSpring.h"
ObjectActionSpring::ObjectActionSpring(QUuid id, EntityItemPointer ownerEntity) :
ObjectAction(id, ownerEntity) {
ObjectActionSpring::ObjectActionSpring(EntityActionType type, QUuid id, EntityItemPointer ownerEntity) :
ObjectAction(type, id, ownerEntity) {
#if WANT_DEBUG
qDebug() << "ObjectActionSpring::ObjectActionSpring";
#endif
@ -143,8 +143,13 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
return true;
}
QByteArray ObjectActionSpring::serialize() {
QByteArray ba;
QDataStream dataStream(&ba, QIODevice::WriteOnly);
dataStream << getType();
dataStream << getID();
void ObjectActionSpring::serializeToDataStream(QDataStream& dataStream) {
dataStream << _positionalTarget;
dataStream << _linearTimeScale;
dataStream << _positionalTargetSet;
@ -152,9 +157,21 @@ void ObjectActionSpring::serializeToDataStream(QDataStream& dataStream) {
dataStream << _rotationalTarget;
dataStream << _angularTimeScale;
dataStream << _rotationalTargetSet;
return ba;
}
void ObjectActionSpring::deserializeFromDataStream(QDataStream& dataStream) {
void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
QDataStream dataStream(serializedArguments);
EntityActionType type;
QUuid id;
dataStream >> type;
dataStream >> id;
assert(type == getType());
assert(id == getID());
dataStream >> _positionalTarget;
dataStream >> _linearTimeScale;
dataStream >> _positionalTargetSet;
@ -162,4 +179,6 @@ void ObjectActionSpring::deserializeFromDataStream(QDataStream& dataStream) {
dataStream >> _rotationalTarget;
dataStream >> _angularTimeScale;
dataStream >> _rotationalTargetSet;
_active = true;
}

View file

@ -19,7 +19,7 @@
class ObjectActionSpring : public ObjectAction {
public:
ObjectActionSpring(QUuid id, EntityItemPointer ownerEntity);
ObjectActionSpring(EntityActionType type, QUuid id, EntityItemPointer ownerEntity);
virtual ~ObjectActionSpring();
virtual EntityActionType getType() { return ACTION_TYPE_SPRING; }
@ -27,10 +27,10 @@ public:
virtual bool updateArguments(QVariantMap arguments);
virtual void updateActionWorker(float deltaTimeStep);
protected:
virtual void serializeToDataStream(QDataStream& dataStream);
virtual void deserializeFromDataStream(QDataStream& dataStream);
virtual QByteArray serialize();
virtual void deserialize(QByteArray serializedArguments);
protected:
glm::vec3 _positionalTarget;
float _linearTimeScale;
bool _positionalTargetSet;

View file

@ -1056,7 +1056,7 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int
// Triangle strip points
// 3 ------ 5
// / \
// / \
// 1 7
// | |
// 2 8