first pass at entity interface to actions

This commit is contained in:
Seth Alves 2015-06-02 16:06:27 -07:00
parent 100248c4e8
commit d6549948d0
12 changed files with 189 additions and 53 deletions

View file

@ -0,0 +1,25 @@
//
// EntityItem.h
// libraries/entities/src
//
// Created by Seth Alves on 2015-6-2
// 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_EntityActionInterface_h
#define hifi_EntityActionInterface_h
class EntityActionInterface {
public:
virtual ~EntityActionInterface();
virtual const QUuid& getID() const = 0;
virtual const EntityItemPointer& getOwnerEntity() const = 0;
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) = 0;
virtual QByteArray serialize() = 0;
static EntityActionInterface* deserialize(EntityItemPointer ownerEntity, QByteArray data);
};
#endif // hifi_EntityActionInterface_h

View file

@ -25,6 +25,7 @@
#include "EntityItem.h"
#include "EntitiesLogging.h"
#include "EntityTree.h"
#include "EntitySimulation.h"
bool EntityItem::_sendPhysicsUpdates = true;
@ -84,6 +85,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
EntityItem::~EntityItem() {
// these pointers MUST be NULL at delete, else we probably have a dangling backpointer
// to this EntityItem in the corresponding data structure.
clearActions();
assert(!_simulated);
assert(!_element);
assert(!_physicsInfo);
@ -1325,3 +1327,45 @@ void EntityItem::updateSimulatorID(const QUuid& value) {
_dirtyFlags |= EntityItem::DIRTY_SIMULATOR_ID;
}
}
void EntityItem::addAction(EntityActionInterface* action) {
assert(action);
const QUuid& actionID = action->getID();
assert(!_objectActions.contains(actionID) || _objectActions[actionID] == action);
_objectActions[actionID] = action;
assert (action->getOwnerEntity() == nullptr);
action->setOwnerEntity(EntityItemPointer(this));
const EntityTree* tree = _element->getTree();
if (tree) {
EntitySimulation* simulation = tree->getSimulation();
if (simulation) {
simulation->addAction(action);
}
}
}
void EntityItem::removeAction(const QUuid actionID) {
if (_objectActions.contains(actionID)) {
const EntityActionInterface* action = _objectActions[actionID];
_objectActions.remove(actionID);
const EntityTree* tree = _element->getTree();
if (tree) {
EntitySimulation* simulation = tree->getSimulation();
if (simulation) {
simulation->removeAction(action->getID());
}
}
delete action;
}
}
void EntityItem::clearActions() {
QHash<QUuid, const EntityActionInterface*>::iterator i;
for (i = _objectActions.begin(); i != _objectActions.end(); ++i) {
removeAction(i.key());
}
}

View file

@ -14,6 +14,8 @@
#include <stdint.h>
#include <QSet>
#include <glm/glm.hpp>
#include <AnimationCache.h> // for Animation, AnimationCache, and AnimationPointer classes
@ -23,9 +25,10 @@
#include <OctreePacketData.h>
#include <ShapeInfo.h>
#include "EntityItemID.h"
#include "EntityItemProperties.h"
#include "EntityItemPropertiesDefaults.h"
#include "EntityItemID.h"
#include "EntityItemProperties.h"
#include "EntityItemPropertiesDefaults.h"
#include "EntityActionInterface.h"
#include "EntityTypes.h"
class EntitySimulation;
@ -88,7 +91,7 @@ public:
};
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
EntityItem(const EntityItemID& entityItemID);
EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
virtual ~EntityItem();
@ -100,7 +103,7 @@ public:
// methods for getting/setting all properties of an entity
virtual EntityItemProperties getProperties() const;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties);
@ -114,7 +117,7 @@ public:
/// Last edited time of this entity universal usecs
quint64 getLastEdited() const { return _lastEdited; }
void setLastEdited(quint64 lastEdited)
void setLastEdited(quint64 lastEdited)
{ _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
@ -128,26 +131,26 @@ public:
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
int& propertyCount,
OctreeElement::AppendState& appendState) const { /* do nothing*/ };
static EntityItemID readEntityItemIDFromBuffer(const unsigned char* data, int bytesLeftToRead,
static EntityItemID readEntityItemIDFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args);
virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
{ return 0; }
virtual void render(RenderArgs* args) { } // by default entity items don't know how to render
@ -159,7 +162,7 @@ public:
// perform update
virtual void update(const quint64& now) { _lastUpdated = now; }
quint64 getLastUpdated() const { return _lastUpdated; }
// perform linear extrapolation for SimpleEntitySimulation
void simulate(const quint64& now);
void simulateKinematicMotion(float timeElapsed, bool setFlags=true);
@ -167,18 +170,18 @@ public:
virtual bool needsToCallUpdate() const { return false; }
virtual void debugDump() const;
virtual bool supportsDetailedRayIntersection() const { return false; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return true; }
// attributes applicable to all entity types
EntityTypes::EntityType getType() const { return _type; }
const glm::vec3& getPosition() const { return _position; } /// get position in meters
void setPosition(const glm::vec3& value) {
_position = value;
void setPosition(const glm::vec3& value) {
_position = value;
}
glm::vec3 getCenter() const;
@ -214,7 +217,7 @@ public:
const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second
void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second
bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; }
float getDamping() const { return _damping; }
void setDamping(float value) { _damping = value; }
@ -233,7 +236,7 @@ public:
/// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires
bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; }
/// age of this entity in seconds
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
bool lifetimeHasExpired() const;
@ -252,7 +255,7 @@ public:
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity
/// registration point as ratio of entity
void setRegistrationPoint(const glm::vec3& value)
void setRegistrationPoint(const glm::vec3& value)
{ _registrationPoint = glm::clamp(value, 0.0f, 1.0f); }
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
@ -280,7 +283,7 @@ public:
bool getLocked() const { return _locked; }
void setLocked(bool value) { _locked = value; }
const QString& getUserData() const { return _userData; }
void setUserData(const QString& value) { _userData = value; }
@ -288,13 +291,13 @@ public:
void setSimulatorID(const QUuid& value);
void updateSimulatorID(const QUuid& value);
quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; }
const QString& getMarketplaceID() const { return _marketplaceID; }
void setMarketplaceID(const QString& value) { _marketplaceID = value; }
// TODO: get rid of users of getRadius()...
// TODO: get rid of users of getRadius()...
float getRadius() const;
virtual bool contains(const glm::vec3& point) const;
virtual bool isReadyToComputeShape() { return true; }
@ -329,11 +332,11 @@ public:
uint32_t getDirtyFlags() const { return _dirtyFlags; }
void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; }
bool isMoving() const;
void* getPhysicsInfo() const { return _physicsInfo; }
void setPhysicsInfo(void* data) { _physicsInfo = data; }
EntityTreeElement* getElement() const { return _element; }
@ -349,12 +352,18 @@ public:
void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
void addAction(EntityActionInterface* actionID);
void removeAction(const QUuid actionID);
void clearActions();
const QList<QUuid> getActionIDs() const { return _objectActions.keys(); }
protected:
static bool _sendPhysicsUpdates;
EntityTypes::EntityType _type;
QUuid _id;
quint64 _lastSimulated; // last time this entity called simulate(), this includes velocity, angular velocity, and physics changes
quint64 _lastSimulated; // last time this entity called simulate(), this includes velocity, angular velocity,
// and physics changes
quint64 _lastUpdated; // last time this entity called update(), this includes animations and non-physics changes
quint64 _lastEdited; // last official local or remote edit time
quint64 _lastBroadcast; // the last time we sent an edit packet about this entity
@ -405,12 +414,12 @@ protected:
//
// damping = 1 - exp(-1 / timescale)
//
// NOTE: Radius support is obsolete, but these private helper functions are available for this class to
// NOTE: Radius support is obsolete, but these private helper functions are available for this class to
// parse old data streams
/// set radius in domain scale units (0.0 - 1.0) this will also reset dimensions to be equal for each axis
void setRadius(float value);
void setRadius(float value);
// DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about.
uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation
@ -419,6 +428,8 @@ protected:
EntityTreeElement* _element = nullptr; // set by EntityTreeElement
void* _physicsInfo = nullptr; // set by EntitySimulation
bool _simulated; // set by EntitySimulation
QHash<QUuid, const EntityActionInterface*> _objectActions;
};
#endif // hifi_EntityItem_h

View file

@ -56,6 +56,10 @@ public:
friend class EntityTree;
virtual void addAction(EntityActionInterface* action) {}
virtual void removeAction(const QUuid actionID) {}
virtual void removeActions(QList<QUuid> actionIDsToRemove) {}
protected: // these only called by the EntityTree?
/// \param entity pointer to EntityItem to be added
/// \sideeffect sets relevant backpointers in entity, but maybe later when appropriate data structures are locked

View file

@ -158,7 +158,8 @@ public:
void emitEntityScriptChanging(const EntityItemID& entityItemID);
void setSimulation(EntitySimulation* simulation);
EntitySimulation* getSimulation() const { return _simulation; }
bool wantEditLogging() const { return _wantEditLogging; }
void setWantEditLogging(bool value) { _wantEditLogging = value; }

View file

@ -152,6 +152,7 @@ public:
bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; }
void setTree(EntityTree* tree) { _myTree = tree; }
const EntityTree* getTree() const { return _myTree; }
bool updateEntity(const EntityItem& entity);
void addEntityItem(EntityItemPointer entity);

View file

@ -2,7 +2,7 @@
// ObjectAction.cpp
// libraries/physcis/src
//
// Created by Seth Alves 2015.6.2
// Created by Seth Alves 2015-6-2
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
@ -11,11 +11,26 @@
#include "ObjectAction.h"
ObjectAction::ObjectAction(EntityItemPointer ownerEntity) :
ObjectAction::ObjectAction(QUuid id, EntityItemPointer ownerEntity) :
btActionInterface(),
_id(QUuid::createUuid()),
_id(id),
_ownerEntity(ownerEntity) {
}
ObjectAction::ObjectAction(EntityItemPointer ownerEntity) :
ObjectAction(QUuid::createUuid(), ownerEntity) {
}
ObjectAction::~ObjectAction() {
}
void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
qDebug() << "updateAction called";
}
EntityActionInterface* ObjectAction::deserialize(EntityItemPointer ownerEntity, QByteArray data) {
return new ObjectAction(ownerEntity);
}
void ObjectAction::debugDraw(btIDebugDraw* debugDrawer) {
}

View file

@ -2,12 +2,13 @@
// ObjectAction.h
// libraries/physcis/src
//
// Created by Seth Alves 2015.6.2
// Created by Seth Alves 2015-6-2
// 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_ObjectAction_h
#define hifi_ObjectAction_h
@ -18,16 +19,22 @@
#include <EntityItem.h>
// http://bulletphysics.org/Bullet/BulletFull/classbtActionInterface.html
class ObjectAction : public btActionInterface {
class ObjectAction : public btActionInterface, public EntityActionInterface {
public:
ObjectAction(QUuid id, EntityItemPointer ownerEntity);
ObjectAction(EntityItemPointer ownerEntity);
virtual ~ObjectAction();
const QUuid& getID() const { return _id; }
virtual const EntityItemPointer& getOwnerEntity() const { return _ownerEntity; }
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; }
// virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) = 0
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
virtual QByteArray serialize() { return QByteArray(); }
static EntityActionInterface* deserialize(EntityItemPointer ownerEntity, QByteArray data);
virtual void debugDraw(btIDebugDraw* debugDrawer);
private:
QUuid _id;

View file

@ -232,3 +232,20 @@ void PhysicalEntitySimulation::handleCollisionEvents(CollisionEvents& collisionE
}
}
void PhysicalEntitySimulation::addAction(EntityActionInterface* action) {
if (_physicsEngine) {
_physicsEngine->addAction(action);
}
}
void PhysicalEntitySimulation::removeAction(const QUuid actionID) {
if (_physicsEngine) {
_physicsEngine->removeAction(actionID);
}
}
void PhysicalEntitySimulation::removeActions(QList<QUuid> actionIDsToRemove) {
if (_physicsEngine) {
_physicsEngine->removeActions(actionIDsToRemove);
}
}

View file

@ -32,6 +32,10 @@ public:
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender);
virtual void addAction(EntityActionInterface* action);
virtual void removeAction(const QUuid actionID);
virtual void removeActions(QList<QUuid> actionIDsToRemove);
protected: // only called by EntitySimulation
// overrides for EntitySimulation
virtual void updateEntitiesInternal(const quint64& now);

View file

@ -449,22 +449,28 @@ bool PhysicsEngine::getBodyLocation(void* physicsInfo, glm::vec3& positionReturn
return true;
}
QUuid PhysicsEngine::addAction(ObjectAction* action) {
void PhysicsEngine::addAction(EntityActionInterface* action) {
assert(action);
const QUuid& actionID = action->getID();
if (_objectActions.contains(actionID)) {
assert(_objectActions[actionID] == action);
return actionID;
return;
}
_objectActions[actionID] = action;
// XXX add to bullet
return actionID;
ObjectAction* objectAction = static_cast<ObjectAction*>(action);
_objectActions[actionID] = objectAction;
_dynamicsWorld->addAction(objectAction);
}
void PhysicsEngine::deleteAction(const QUuid actionID) {
void PhysicsEngine::removeAction(const QUuid actionID) {
if (_objectActions.contains(actionID)) {
// XXX remove from bullet
ObjectAction* action = _objectActions[actionID];
_dynamicsWorld->removeAction(action);
_objectActions.remove(actionID);
}
}
void PhysicsEngine::removeActions(QList<QUuid> actionIDsToRemove) {
foreach(QUuid actionID, actionIDsToRemove) {
removeAction(actionID);
}
}

View file

@ -95,8 +95,9 @@ public:
static bool physicsInfoIsActive(void* physicsInfo);
static bool getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn);
QUuid addAction(ObjectAction* action); // PhysicsEngine takes ownership of the pointer
void deleteAction(QUuid actionID);
void addAction(EntityActionInterface* action);
void removeAction(const QUuid actionID);
void removeActions(QList<QUuid> actionIDsToRemove);
private:
void removeContacts(ObjectMotionState* motionState);