From f1d2017a9eb30b563b4e4087d04b0b8c78074f35 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 7 Aug 2014 12:50:02 -0700 Subject: [PATCH] getting animation working again --- examples/editModels.js | 2 + libraries/entities/src/BoxEntityItem.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 34 +---- libraries/entities/src/EntityItem.h | 19 ++- libraries/entities/src/EntityItemProperties.h | 6 +- libraries/entities/src/EntityTree.cpp | 138 +++++++++++++----- libraries/entities/src/EntityTree.h | 7 +- libraries/entities/src/EntityTreeElement.cpp | 7 +- libraries/entities/src/EntityTypes.cpp | 26 ++-- libraries/entities/src/EntityTypes.h | 18 +-- libraries/entities/src/ModelEntityItem.cpp | 47 +++++- libraries/entities/src/ModelEntityItem.h | 9 +- libraries/entities/src/todo.txt | 54 +------ 13 files changed, 221 insertions(+), 150 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 718d84ad2e..d0029ad2b5 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1608,6 +1608,7 @@ function handeMenuEvent(menuItem){ array.push({ label: "Model URL:", value: properties.modelURL }); array.push({ label: "Animation URL:", value: properties.animationURL }); array.push({ label: "Animation is playing:", value: properties.animationIsPlaying }); + array.push({ label: "Animation FPS:", value: properties.animationFPS }); } array.push({ label: "X:", value: properties.position.x.toFixed(decimals) }); array.push({ label: "Y:", value: properties.position.y.toFixed(decimals) }); @@ -1632,6 +1633,7 @@ function handeMenuEvent(menuItem){ properties.modelURL = array[index++].value; properties.animationURL = array[index++].value; properties.animationIsPlaying = array[index++].value; + properties.animationFPS = array[index++].value; } properties.position.x = array[index++].value; properties.position.y = array[index++].value; diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index 8cacb909ce..3ce8bad046 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -128,7 +128,7 @@ qDebug() << "BoxEntityItem::readEntityDataFromBuffer()... <<<<<<<<<<<<<<<< <<<< dataAt += encodedType.size(); bytesRead += encodedType.size(); quint32 type = typeCoder; - _type = (EntityTypes::EntityType_t)type; + _type = (EntityTypes::EntityType)type; // XXXBHG: is this a good place to handle the last edited time client vs server?? @@ -272,7 +272,7 @@ qDebug() << "BoxEntityItem::appendEntityData()... ****************************** // encode our type as a byte count coded byte stream - EntityTypes::EntityType_t type = getType(); + EntityTypes::EntityType type = getType(); qDebug() << "BoxEntityItem::appendEntityData()... type=" << type; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index fac4d6d73f..a40cf2a933 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -460,7 +460,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += encodedType.size(); bytesRead += encodedType.size(); quint32 type = typeCoder; - _type = (EntityTypes::EntityType_t)type; + _type = (EntityTypes::EntityType)type; // XXXBHG: is this a good place to handle the last edited time client vs server?? @@ -1086,35 +1086,11 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s } void EntityItem::update(const quint64& updateTime) { - _lastUpdated = updateTime; - setShouldBeDeleted(getShouldBeDeleted()); + // nothing to do here... but will add gravity, etc... +} - quint64 now = usecTimestampNow(); - - // only advance the frame index if we're playing -#if 0 //def HIDE_SUBCLASS_METHODS - if (getAnimationIsPlaying()) { - - float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; - - const bool wantDebugging = false; - if (wantDebugging) { - qDebug() << "EntityItem::update() now=" << now; - qDebug() << " updateTime=" << updateTime; - qDebug() << " _lastAnimated=" << _lastAnimated; - qDebug() << " deltaTime=" << deltaTime; - } - _lastAnimated = now; - _animationFrameIndex += deltaTime * _animationFPS; - - if (wantDebugging) { - qDebug() << " _animationFrameIndex=" << _animationFrameIndex; - } - - } else { - _lastAnimated = now; - } -#endif +EntityItem::SimuationState EntityItem::getSimulationState() const { + return EntityItem::Static; // change this once we support gravity, etc... } void EntityItem::copyChangedProperties(const EntityItem& other) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 1001610e66..c23648a597 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -23,7 +23,7 @@ #include "EntityItemID.h" #include "EntityItemProperties.h" -#include "EntityTypes.h" +#include "EntityTypes.h" class EntityTreeElementExtraEncodeData; @@ -70,7 +70,15 @@ public: unsigned char* bufferOut, int sizeIn, int& sizeOut); static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew); - void update(const quint64& now); + virtual void update(const quint64& now); + + typedef enum SimuationState_t { + Static, + Changing, + Moving + } SimuationState; + + virtual SimuationState getSimulationState() const ; void debugDump() const; // similar to assignment/copy, but it handles keeping lifetime accurate @@ -78,7 +86,7 @@ public: // attributes applicable to all entity types - EntityTypes::EntityType_t getType() const { return _type; } + EntityTypes::EntityType getType() const { return _type; } const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0) void setPosition(const glm::vec3& value) { _position = value; } /// set position in domain scale units (0.0 - 1.0) @@ -100,11 +108,14 @@ public: glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); } AACube getAACube() const { return AACube(getMinimumPoint(), getSize()); } /// AACube in domain scale units (0.0 - 1.0) + + + protected: virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init quint32 _id; - EntityTypes::EntityType_t _type; + EntityTypes::EntityType _type; uint32_t _creatorTokenID; bool _newlyCreated; quint64 _lastUpdated; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 1868da9e56..544dd4a9ce 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -119,7 +119,7 @@ public: void debugDump() const; // properties of all entities - EntityTypes::EntityType_t getType() const { return _type; } + EntityTypes::EntityType getType() const { return _type; } const glm::vec3& getPosition() const { return _position; } float getRadius() const { return _radius; } float getMaxDimension() const { return _radius * 2.0f; } @@ -127,7 +127,7 @@ public: const glm::quat& getRotation() const { return _rotation; } bool getShouldBeDeleted() const { return _shouldBeDeleted; } - void setType(EntityTypes::EntityType_t type) { _type = type; } + void setType(EntityTypes::EntityType type) { _type = type; } /// set position in meter units void setPosition(const glm::vec3& value) { _position = value; _positionChanged = true; } void setRadius(float value) { _radius = value; _radiusChanged = true; } @@ -170,7 +170,7 @@ private: bool _idSet; quint64 _lastEdited; - EntityTypes::EntityType_t _type; + EntityTypes::EntityType _type; glm::vec3 _position; float _radius; glm::quat _rotation; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index cf18ba17a1..33312037ae 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -176,6 +176,9 @@ void EntityTree::addEntityItem(EntityItem* entityItem) { //qDebug() << "AFTER... about to call recurseTreeWithOperator(AddEntityOperator)..."; //debugDumpMap(); + // check to see if we need to simulate this entity.. + changeEntityState(entityItem, EntityItem::Static, entityItem->getSimulationState()); + _isDirty = true; } @@ -363,7 +366,6 @@ OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* elemen bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) { - bool updated = false; // You should not call this on existing entities that are already part of the tree! Call updateEntity() EntityTreeElement* containingElement = getContainingElement(entityID); if (!containingElement) { @@ -376,10 +378,17 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp assert(existingEntity); // don't call updateEntity() on entity items that don't exist return false; } + + // check to see if we need to simulate this entity... + EntityItem::SimuationState oldState = existingEntity->getSimulationState(); + UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties); recurseTreeWithOperator(&theOperator); _isDirty = true; + EntityItem::SimuationState newState = existingEntity->getSimulationState(); + changeEntityState(existingEntity, oldState, newState); + containingElement = getContainingElement(entityID); if (!containingElement) { qDebug() << "after updateEntity() we no longer have a containing element???"; @@ -408,7 +417,7 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem } // construct the instance of the entity - EntityTypes::EntityType_t type = properties.getType(); + EntityTypes::EntityType type = properties.getType(); result = EntityTypes::constructEntityItem(type, entityID, properties); if (result) { @@ -1068,50 +1077,109 @@ if (childAt) { return true; } -void EntityTree::update() { - // XXXBHG: replace storeEntity with new API!! - //qDebug() << "EntityTree::update().... NOT YET IMPLEMENTED!!!"; - #if 0 ////////////////////////////////////////////////////// +void EntityTree::changeEntityState(EntityItem* const entity, EntityItem::SimuationState oldState, EntityItem::SimuationState newState) { + if (oldState != newState) { + switch (oldState) { + case EntityItem::Changing: + _changingEntities.removeAll(entity); + break; - lockForWrite(); - _isDirty = true; + case EntityItem::Moving: + _movingEntities.removeAll(entity); + break; + default: + break; + } - // TODO: could we manage this by iterating the known entities map/hash? Would that be faster? - EntityTreeUpdateArgs args; - recurseTreeWithOperation(updateOperation, &args); - // now add back any of the particles that moved elements.... - int movingEntities = args._movingEntities.size(); - - for (int i = 0; i < movingEntities; i++) { - - bool shouldDie = args._movingEntities[i]->getShouldBeDeleted(); + switch (newState) { + case EntityItem::Changing: + _changingEntities.push_back(entity); + break; - // if the particle is still inside our total bounds, then re-add it - AACube treeBounds = getRoot()->getAACube(); - - if (!shouldDie && treeBounds.contains(args._movingEntities[i]->getPosition())) { - storeEntity(*args._movingEntities[i]); - } else { - uint32_t entityItemID = args._movingEntities[i]->getID(); - quint64 deletedAt = usecTimestampNow(); - _recentlyDeletedEntitiesLock.lockForWrite(); - _recentlyDeletedEntityItemIDs.insert(deletedAt, entityItemID); - _recentlyDeletedEntitiesLock.unlock(); + case EntityItem::Moving: + _movingEntities.push_back(entity); + break; + default: + break; } } +} +void EntityTree::update() { - #endif // 0 ////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NEW CODE!!!! +// +// our new strategy should be to segregate entities into three classes: +// 1) stationary things that are not changing - most models +// 2) stationary things that are animating - they can be touched linearly and they don't change the tree +// 3) moving things - these need to scan the tree and update accordingly - - // prune the tree... - /* lockForWrite(); -qDebug() << "pruning tree"; - recurseTreeWithOperation(pruneOperation, NULL); + quint64 now = usecTimestampNow(); + + //_movingEntities; // entities that are moving as part of update + //_changingEntities; // entities that are changing (like animating), but not moving + + + for (int i = 0; i < _changingEntities.size(); i++) { + EntityItem* thisEntity = _changingEntities[i]; + thisEntity->update(now); + } + unlock(); - */ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// OLD CODE!!!! +// +// The old update code scanned the entire tree... this is very expensive, since not all entities are getting simulated +// +// // XXXBHG: replace storeEntity with new API!! +// //qDebug() << "EntityTree::update().... NOT YET IMPLEMENTED!!!"; +// #if 0 ////////////////////////////////////////////////////// +// +// lockForWrite(); +// _isDirty = true; +// +// // TODO: could we manage this by iterating the known entities map/hash? Would that be faster? +// EntityTreeUpdateArgs args; +// recurseTreeWithOperation(updateOperation, &args); +// +// // now add back any of the particles that moved elements.... +// int movingEntities = args._movingEntities.size(); +// +// for (int i = 0; i < movingEntities; i++) { +// +// bool shouldDie = args._movingEntities[i]->getShouldBeDeleted(); +// +// // if the particle is still inside our total bounds, then re-add it +// AACube treeBounds = getRoot()->getAACube(); +// +// if (!shouldDie && treeBounds.contains(args._movingEntities[i]->getPosition())) { +// storeEntity(*args._movingEntities[i]); +// } else { +// uint32_t entityItemID = args._movingEntities[i]->getID(); +// quint64 deletedAt = usecTimestampNow(); +// _recentlyDeletedEntitiesLock.lockForWrite(); +// _recentlyDeletedEntityItemIDs.insert(deletedAt, entityItemID); +// _recentlyDeletedEntitiesLock.unlock(); +// } +// } +// +// +// #endif // 0 ////////////////////////////////////////////////////// +// +// +// // prune the tree... +// /* +// lockForWrite(); +//qDebug() << "pruning tree"; +// recurseTreeWithOperation(pruneOperation, NULL); +// unlock(); +// */ } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 13d7e26a53..e09c0f05a3 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -112,9 +112,10 @@ public: void rememberDirtyCube(const AACube& cube); void rememberEntityToMove(const EntityItem* entity); - void sendEntities(EntityEditPacketSender* packetSender, float x, float y, float z); + void changeEntityState(EntityItem* const entity, EntityItem::SimuationState oldState, EntityItem::SimuationState newState); + private: static bool updateOperation(OctreeElement* element, void* extraData); @@ -139,6 +140,10 @@ private: EntityItemFBXService* _fbxService; QHash _entityToElementMap; + + + QList _movingEntities; // entities that are moving as part of update + QList _changingEntities; // entities that are changing (like animating), but not moving }; #endif // hifi_EntityTree_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 36f0504f67..d2d7aeee47 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -619,8 +619,11 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int //if (currentContainingElement != this) { // qDebug() << "EXISTING ENTITY CASE!!!!!!!!!!!!!! CONTAINING ELEMENT MISMATCH!!"; //} - + + EntityItem::SimuationState oldState = entityItem->getSimulationState(); bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + EntityItem::SimuationState newState = entityItem->getSimulationState(); + _myTree->changeEntityState(entityItem, oldState, newState); bool bestFitAfter = bestFitEntityBounds(entityItem); @@ -651,9 +654,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int if (entityItem) { bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); - //qDebug() << "NEW ENTITY CASE!!!!!!!!!!!!!! EntityTreeElement::readElementDataFromBuffer() BEFORE addEntityItem(entity); element=" << this << "entity=" << entityItem << "id=" << entityItem->getEntityItemID() << "bestFit=" << bestFitEntityBounds(entityItem); addEntityItem(entityItem); // add this new entity to this elements entities - //qDebug() << "NEW ENTITY CASE!!!!!!!!!!!!!! EntityTreeElement::readElementDataFromBuffer() AFTER addEntityItem(entity); element=" << this << "entity=" << entityItem << "id=" << entityItem->getEntityItemID() << "bestFit=" << bestFitEntityBounds(entityItem); _myTree->setContainingElement(entityItem->getEntityItemID(), this); newEntity = true; } diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 327bd56be5..10080a2973 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -21,8 +21,8 @@ #include "BoxEntityItem.h" #include "ModelEntityItem.h" -QMap EntityTypes::_typeToNameMap; -QMap EntityTypes::_nameToTypeMap; +QMap EntityTypes::_typeToNameMap; +QMap EntityTypes::_nameToTypeMap; EntityTypeFactory EntityTypes::_factories[EntityTypes::LAST]; bool EntityTypes::_factoriesInitialized = false; EntityTypeRenderer EntityTypes::_renderers[EntityTypes::LAST]; @@ -39,23 +39,23 @@ REGISTER_ENTITY_TYPE(Cylinder) REGISTER_ENTITY_TYPE(Pyramid) -const QString& EntityTypes::getEntityTypeName(EntityType_t entityType) { - QMap::iterator matchedTypeName = _typeToNameMap.find(entityType); +const QString& EntityTypes::getEntityTypeName(EntityType entityType) { + QMap::iterator matchedTypeName = _typeToNameMap.find(entityType); if (matchedTypeName != _typeToNameMap.end()) { return matchedTypeName.value(); } return ENTITY_TYPE_NAME_UNKNOWN; } -EntityTypes::EntityType_t EntityTypes::getEntityTypeFromName(const QString& name) { - QMap::iterator matchedTypeName = _nameToTypeMap.find(name); +EntityTypes::EntityType EntityTypes::getEntityTypeFromName(const QString& name) { + QMap::iterator matchedTypeName = _nameToTypeMap.find(name); if (matchedTypeName != _nameToTypeMap.end()) { return matchedTypeName.value(); } return Unknown; } -bool EntityTypes::registerEntityType(EntityType_t entityType, const char* name, EntityTypeFactory factoryMethod) { +bool EntityTypes::registerEntityType(EntityType entityType, const char* name, EntityTypeFactory factoryMethod) { qDebug() << "EntityTypes::registerEntityType()"; qDebug() << " entityType=" << entityType; qDebug() << " name=" << name; @@ -71,8 +71,8 @@ bool EntityTypes::registerEntityType(EntityType_t entityType, const char* name, return true; } -EntityItem* EntityTypes::constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties) { - qDebug() << "EntityTypes::constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties)"; +EntityItem* EntityTypes::constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties) { + qDebug() << "EntityTypes::constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties)"; qDebug() << " entityType=" << entityType; qDebug() << " entityID=" << entityID; @@ -125,7 +125,7 @@ qDebug() << "EntityTypes::constructEntityItem(data, bytesToRead).... NEW BITSTRE encodedType = typeCoder; // determine true length bytesRead += encodedType.size(); quint32 type = typeCoder; - EntityTypes::EntityType_t entityType = (EntityTypes::EntityType_t)type; + EntityTypes::EntityType entityType = (EntityTypes::EntityType)type; EntityItemID tempEntityID(actualID); EntityItemProperties tempProperties; @@ -224,7 +224,7 @@ qDebug() << "EntityItem::decodeEntityEditPacket() ... lastEdited=" << lastEdited QByteArray encodedType((const char*)dataAt, (bytesToRead - processedBytes)); ByteCountCoded typeCoder = encodedType; quint32 entityTypeCode = typeCoder; - properties.setType((EntityTypes::EntityType_t)entityTypeCode); + properties.setType((EntityTypes::EntityType)entityTypeCode); encodedType = typeCoder; // determine true bytesToRead dataAt += encodedType.size(); processedBytes += encodedType.size(); @@ -377,7 +377,7 @@ qDebug() << "EntityItem::decodeEntityEditPacket() ... lastEdited=" << lastEdited return valid; } -bool EntityTypes::registerEntityTypeRenderer(EntityType_t entityType, EntityTypeRenderer renderMethod) { +bool EntityTypes::registerEntityTypeRenderer(EntityType entityType, EntityTypeRenderer renderMethod) { qDebug() << "EntityTypes::registerEntityTypeRenderer()"; qDebug() << " entityType=" << entityType; qDebug() << " renderMethod=" << (void*)renderMethod; @@ -392,7 +392,7 @@ bool EntityTypes::registerEntityTypeRenderer(EntityType_t entityType, EntityType } void EntityTypes::renderEntityItem(EntityItem* entityItem, RenderArgs* args) { - EntityType_t entityType = entityItem->getType(); + EntityType entityType = entityItem->getType(); EntityTypeRenderer renderMethod = _renderers[entityType]; if (renderMethod) { renderMethod(entityItem, args); diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 08d8df2e67..60089d5a81 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -29,7 +29,7 @@ typedef void (*EntityTypeRenderer)(EntityItem* entity, RenderArgs* args); class EntityTypes { public: - typedef enum EntityType { + typedef enum EntityType_t { Unknown, Model, Box, @@ -38,22 +38,22 @@ public: Cylinder, Pyramid, LAST = Pyramid - } EntityType_t; + } EntityType; - static const QString& getEntityTypeName(EntityType_t entityType); - static EntityTypes::EntityType_t getEntityTypeFromName(const QString& name); - static bool registerEntityType(EntityType_t entityType, const char* name, EntityTypeFactory factoryMethod); - static EntityItem* constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties); + static const QString& getEntityTypeName(EntityType entityType); + static EntityTypes::EntityType getEntityTypeFromName(const QString& name); + static bool registerEntityType(EntityType entityType, const char* name, EntityTypeFactory factoryMethod); + static EntityItem* constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItem* constructEntityItem(const unsigned char* data, int bytesToRead, ReadBitstreamToTreeParams& args); static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes, EntityItemID& entityID, EntityItemProperties& properties); - static bool registerEntityTypeRenderer(EntityType_t entityType, EntityTypeRenderer renderMethod); + static bool registerEntityTypeRenderer(EntityType entityType, EntityTypeRenderer renderMethod); static void renderEntityItem(EntityItem* entityItem, RenderArgs* args); private: - static QMap _typeToNameMap; - static QMap _nameToTypeMap; + static QMap _typeToNameMap; + static QMap _nameToTypeMap; static EntityTypeFactory _factories[LAST]; static bool _factoriesInitialized; static EntityTypeRenderer _renderers[LAST]; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index c360900131..7cded0697c 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -33,7 +33,6 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI qDebug() << "ModelEntityItem::ModelEntityItem() calling setProperties()"; setProperties(properties); qDebug() << "ModelEntityItem::ModelEntityItem() getModelURL()=" << getModelURL(); - } EntityItemProperties ModelEntityItem::getProperties() const { @@ -165,7 +164,7 @@ qDebug() << "ModelEntityItem::readEntityDataFromBuffer()... <<<<<<<<<<<<<<<< << dataAt += encodedType.size(); bytesRead += encodedType.size(); quint32 type = typeCoder; - _type = (EntityTypes::EntityType_t)type; + _type = (EntityTypes::EntityType)type; // XXXBHG: is this a good place to handle the last edited time client vs server?? @@ -853,3 +852,47 @@ QVector ModelEntityItem::getAnimationFrame() { } return frameData; } + +bool ModelEntityItem::isAnimatingSomething() const { + return getAnimationIsPlaying() && + getAnimationFPS() != 0.0f && + !getAnimationURL().isEmpty(); +} + +EntityItem::SimuationState ModelEntityItem::getSimulationState() const { + if (isAnimatingSomething()) { + return EntityItem::Changing; + } + return EntityItem::Static; +} + +void ModelEntityItem::update(const quint64& updateTime) { + _lastUpdated = updateTime; + //setShouldBeDeleted(getShouldBeDeleted()); + + quint64 now = updateTime; //usecTimestampNow(); + + // only advance the frame index if we're playing + if (getAnimationIsPlaying()) { + + float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; + + const bool wantDebugging = false; + if (wantDebugging) { + qDebug() << "EntityItem::update() now=" << now; + qDebug() << " updateTime=" << updateTime; + qDebug() << " _lastAnimated=" << _lastAnimated; + qDebug() << " deltaTime=" << deltaTime; + } + _lastAnimated = now; + _animationFrameIndex += deltaTime * _animationFPS; + + if (wantDebugging) { + qDebug() << " _animationFrameIndex=" << _animationFrameIndex; + } + + } else { + _lastAnimated = now; + } +} + diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index a576ad764a..e7b3efbad8 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -32,8 +32,9 @@ public: virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); - /// For reading models from pre V3 bitstreams - int oldVersionReadEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); + virtual void update(const quint64& now); + virtual SimuationState getSimulationState() const; + // TODO: Move these to subclasses, or other appropriate abstraction // getters/setters applicable to models and particles @@ -73,6 +74,10 @@ public: protected: + /// For reading models from pre V3 bitstreams + int oldVersionReadEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); + bool isAnimatingSomething() const; + rgbColor _color; QString _modelURL; QVector _sittingPoints; diff --git a/libraries/entities/src/todo.txt b/libraries/entities/src/todo.txt index e24334c293..fa9cc3fa6f 100644 --- a/libraries/entities/src/todo.txt +++ b/libraries/entities/src/todo.txt @@ -4,15 +4,14 @@ Base properties... * size/radius/bounds?? maybe correct is x,y,z scales * rotation * script - -should these be included for all entities? Light, Models, planes, etc? * velocity * gravity * damping + * glow level + +should these be included for all entities? Light, Models, planes, etc? * rotational velocity? - wouldn't that be cool to be automatic with no edits * rotational damping?? - can you slow a quat rotation by simply multiplying it by a fraction? - * glow level??? - * color?? Primitive Object Properties: @@ -26,11 +25,7 @@ Model properties: void setAnimationFrameIndex(float value) void setAnimationIsPlaying(bool value) void setAnimationFPS(float value) - void setGlowLevel(float glowLevel) void setSittingPoints(QVector sittingPoints) ??? - should this just be a string property??? - - - @@ -56,6 +51,9 @@ Model properties: F) TODO: do we need to handle "killing" viewed entities as well??? void EntityTreeElement::updateEntityItemID(const EntityItemID& creatorTokenEntityID, const EntityItemID& knownIDEntityID)... + 13) support sitpoints + + K) verify shadows work // NICE TO DO: @@ -132,7 +130,7 @@ Model properties: // 12a) make sure server is deleting items?? // 12b) Use the delete message instead of shouldDelete property -// 13) add user properties (support sitpoints) +// 13b) add user properties // 14) implement "Light" entity, "Fire" entity? @@ -177,44 +175,6 @@ Model properties: // SOLVED - 9) problem here... looks like the client got confused and sent us an unknown edit packet with a creator token id we already had... // we probably can't keep the creator tokens in our server tree or else we'll collide between multiple editors!! // -- fixed this by only storing assigned IDs in the server's ID base -// -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] setContainingElement() entityItemID= [ id: 0 , creatorTokenID: 0 , isKnownID: true ] element= 0x7ff7b8702c50 -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] EntityTree::debugDumpMap() -------------------------- -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] [ id: 0 , creatorTokenID: 0 , isKnownID: true ] : 0x7ff7b8702c50 -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] ----------------------------------------------------- -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] AddEntityOperator calling setContainingElement... new entityID= [ id: 0 , creatorTokenID: 0 , isKnownID: true ] -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] EntityTree::debugDumpMap() -------------------------- -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] [ id: 0 , creatorTokenID: 0 , isKnownID: true ] : 0x7ff7b8702c50 -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] ----------------------------------------------------- -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] AFTER... about to call recurseTreeWithOperator(AddEntityOperator)... -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] EntityTree::debugDumpMap() -------------------------- -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] [ id: 0 , creatorTokenID: 0 , isKnownID: true ] : 0x7ff7b8702c50 -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] ----------------------------------------------------- -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] EntityServer::entityCreated() newEntity.getEntityItemID()= [ id: 0 , creatorTokenID: 0 , isKnownID: true ] -// [DEBUG] [2014-07-28 21:22:07 -0700] [41087:24258] [entity-server] EntityServer::entityCreated() writeDatagram() -// [DEBUG] [2014-07-28 21:22:10 -0700] [41087:24258] [entity-server] Killed "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:10 -0700] [41087:24258] [entity-server] Entity server killed node: "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:10 -0700] [41087:24258] [entity-server] Added "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:10 -0700] [41087:24258] [entity-server] Entity server added node: "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:10 -0700] [41087:24258] [entity-server] Entity server [ EntityServer(0x7ff7bc000000) ]: client disconnected - ending sending thread [ OctreeSendThread(0x7ff7b9006e00) ] -// [DEBUG] [2014-07-28 21:22:14 -0700] [41087:24258] [entity-server] Killed "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:14 -0700] [41087:24258] [entity-server] Entity server killed node: "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:14 -0700] [41087:24258] [entity-server] Entity server node missing linked data node: "Agent" (I) {79efcb8c-614c-42f4-abb9-72d096603c85} 50.132.90.94:51973 / 192.168.1.152:51973 -// [DEBUG] [2014-07-28 21:22:32 -0700] [41087:24258] [entity-server] saving Octrees to file "resources/models.svo" ... -// [DEBUG] [2014-07-28 21:22:32 -0700] [41087:24258] [entity-server] DONE saving Octrees to file... -// [DEBUG] [2014-07-28 21:23:59 -0700] [41087:24258] [entity-server] Packet of type 3 received from unknown node with UUID QUuid("{12a522ec-7476-4d68-8e31-da39eb4a18b2}") -// [DEBUG] [2014-07-28 21:24:00 -0700] [41087:24258] [entity-server] Added "Agent" (I) {12a522ec-7476-4d68-8e31-da39eb4a18b2} 50.132.90.94:65198 / 192.168.1.152:65198 -// [DEBUG] [2014-07-28 21:24:00 -0700] [41087:24258] [entity-server] Entity server added node: "Agent" (I) {12a522ec-7476-4d68-8e31-da39eb4a18b2} 50.132.90.94:65198 / 192.168.1.152:65198 -// [DEBUG] [2014-07-28 21:24:00 -0700] [41087:24258] [entity-server] Activating local socket for node "Agent" (I) {12a522ec-7476-4d68-8e31-da39eb4a18b2} 50.132.90.94:65198 / 192.168.1.152:65198 -// [DEBUG] [2014-07-28 21:24:02 -0700] [41087:24258] [entity-server] Entity server [ EntityServer(0x7ff7bc000000) ]: client connected - starting sending thread [ OctreeSendThread(0x7ff7bb000c00) ] -// [DEBUG] [2014-07-28 21:24:07 -0700] [41087:24258] [entity-server] EntityTree::processEditPacketData().... -// [DEBUG] [2014-07-28 21:24:07 -0700] [41087:24258] [entity-server] EntityTree::getContainingElement() entityItemID= [ id: 4294967295 , creatorTokenID: 0 , isKnownID: false ] -// [DEBUG] [2014-07-28 21:24:07 -0700] [41087:24258] [entity-server] EntityTree::debugDumpMap() -------------------------- -// [DEBUG] [2014-07-28 21:24:07 -0700] [41087:24258] [entity-server] [ id: 0 , creatorTokenID: 0 , isKnownID: true ] : 0x7ff7b8702c50 -// [DEBUG] [2014-07-28 21:24:07 -0700] [41087:24258] [entity-server] ----------------------------------------------------- -// Assertion failed: (!getContainingElement(entityItemID)), function assignEntityID, file /Users/zappoman/Development/HiFi/hifi/libraries/entities/src/EntityTree.cpp, line 958. -// -// // SOLVED - 15) fix all places where "Voxels" turns off some features of models/entities // SOLVED - 16) duplicate copies of entity references in the elements... this appears to be caused when "viewing" while editing... // SOLVED - 17) Handle the newer on client vs changed on server problem properly for entities