From e13a74213c0f51f75c89caaaffc6655bd515a02c Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 6 Nov 2017 17:29:19 -0800 Subject: [PATCH 01/48] this is holder spot to put avatar entity animation code --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 7db19704b4..3959bf0bf0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -979,6 +979,8 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } + //this a spot to work on the avatar npc in my branch + QVector jointsData; const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy From af0304fd6b48122f97373f70c5d751f5c6e5c9e6 Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 9 Nov 2017 10:04:12 -0800 Subject: [PATCH 02/48] preliminary changes for the property fixes --- .../src/RenderableModelEntityItem.cpp | 38 +++++++++++++++++-- .../src/RenderableModelEntityItem.h | 2 + libraries/entities/src/ModelEntityItem.cpp | 7 ++++ libraries/entities/src/ModelEntityItem.h | 1 + 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3959bf0bf0..40e5066e2d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -979,6 +979,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } + //added by angus //this a spot to work on the avatar npc in my branch QVector jointsData; @@ -989,6 +990,19 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } + //get entity model anim props + bool isLooping = entity->getAnimationLoop(); + int firstFrame = entity->getAnimationFirstFrame(); + int lastFrame = entity->getAnimationLastFrame(); + bool isHolding = entity->getAnimationHold(); + int updatedFrameCount = frameCount; + + if ((firstFrame >= 0) && (firstFrame < lastFrame) && (lastFrame <= frameCount)) { + //length of animation in now determined by first and last frame + updatedFrameCount = lastFrame - firstFrame; + } + + if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; @@ -997,11 +1011,25 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { auto now = usecTimestampNow(); auto interval = now - _lastAnimated; _lastAnimated = now; - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + //we handle the hold animation property here + //if hold don't advance the current frame. + if (!isHolding) { + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + } { - int animationCurrentFrame = (int)(glm::floor(_currentFrame)) % frameCount; + //where are we in the currently defined animation segment? + int animationCurrentFrame = (int)(glm::floor(_currentFrame)) % updatedFrameCount; + //this starts us at the offset first frame. + animationCurrentFrame += firstFrame; + + //here we implement the looping animation property + //if we have played through the animation once then we hold on the last frame + if (!isLooping && (_currentFrame > (updatedFrameCount - 1))) { + animationCurrentFrame = updatedFrameCount + firstFrame; + } + if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { animationCurrentFrame = 0; } @@ -1314,7 +1342,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (newAnimationProperties != _renderAnimationProperties) { withWriteLock([&] { _renderAnimationProperties = newAnimationProperties; - _currentFrame = _renderAnimationProperties.getCurrentFrame(); + //if (entity->getAnimationHold()) { + // _currentFrame = _renderAnimationProperties.getCurrentFrame(); + //} }); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 0272bed575..d33976e356 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -185,6 +185,8 @@ private: bool _animating { false }; uint64_t _lastAnimated { 0 }; float _currentFrame { 0 }; + //bool _previousHold{ false }; + float _currentFramePropertyValue{ 0 }; }; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 26f063f7cc..ae73fa684a 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -538,6 +538,13 @@ void ModelEntityItem::setAnimationLoop(bool loop) { }); } +bool ModelEntityItem::getAnimationLoop() const { + return resultWithReadLock([&] { + return _animationProperties.getLoop(); + }); +} + + void ModelEntityItem::setAnimationHold(bool hold) { withWriteLock([&] { _animationProperties.setHold(hold); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 2c3ef3aa2d..698197b1a6 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -90,6 +90,7 @@ public: bool getAnimationAllowTranslation() const { return _animationProperties.getAllowTranslation(); }; void setAnimationLoop(bool loop); + bool getAnimationLoop() const; void setAnimationHold(bool hold); bool getAnimationHold() const; From 1a06c6ef118257a97674844425ea445b968ae204 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 10 Nov 2017 15:23:17 -0800 Subject: [PATCH 03/48] all entity animation fixes done except play animation --- .../src/RenderableModelEntityItem.cpp | 50 +++++++++++++------ .../src/RenderableModelEntityItem.h | 4 ++ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 4ebdfb7b8b..989f019980 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1012,24 +1012,33 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { auto now = usecTimestampNow(); auto interval = now - _lastAnimated; _lastAnimated = now; - //we handle the hold animation property here - //if hold don't advance the current frame. - if (!isHolding) { - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + + + //here we implement the looping animation property + //if we have played through the animation once then we hold on the last frame + // if (!isLooping && (_currentFrame > _endAnim)) { + //don't advance current frame!!! + + //}else{ + if( isLooping || ( _currentFrame < _endAnim ) ){ + //else advance the current frame. + //if hold or not playing don't advance the current frame. + if (!isHolding && entity->getAnimationIsPlaying()) { + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + } } { //where are we in the currently defined animation segment? - int animationCurrentFrame = (int)(glm::floor(_currentFrame)) % updatedFrameCount; - //this starts us at the offset first frame. - animationCurrentFrame += firstFrame; + int animationCurrentFrame = (int)(glm::floor(_currentFrame - _renderAnimationProperties.getFirstFrame())) % updatedFrameCount; + //this gives us the absolute frame value to use by adding the first frame value. + animationCurrentFrame += _renderAnimationProperties.getFirstFrame(); + - //here we implement the looping animation property - //if we have played through the animation once then we hold on the last frame - if (!isLooping && (_currentFrame > (updatedFrameCount - 1))) { - animationCurrentFrame = updatedFrameCount + firstFrame; - } + + + if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { animationCurrentFrame = 0; @@ -1352,10 +1361,19 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { withWriteLock([&] { + if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { + _currentFrame = newAnimationProperties.getCurrentFrame(); + _endAnim = (_currentFrame - 1) + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())); + //qCDebug(entitiesrenderer) << "reset current frame" << _endAnim; + } + if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { + //set the end of animation relative to the current frame + //qCDebug(entitiesrenderer) << "turned off looping"; + float startOffset = newAnimationProperties.getCurrentFrame() - newAnimationProperties.getFirstFrame(); + float posRelativeToStart = (_currentFrame - newAnimationProperties.getFirstFrame()) - startOffset; + _endAnim = (_currentFrame - 1) + (((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - ((int)(glm::floor(posRelativeToStart)) % ((int)newAnimationProperties.getLastFrame() - (int)newAnimationProperties.getFirstFrame()))); + } _renderAnimationProperties = newAnimationProperties; - //if (entity->getAnimationHold()) { - // _currentFrame = _renderAnimationProperties.getCurrentFrame(); - //} }); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index d33976e356..65b915465c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -187,6 +187,10 @@ private: float _currentFrame { 0 }; //bool _previousHold{ false }; float _currentFramePropertyValue{ 0 }; + float _firstFramePropertyValue{ 0 }; + float _lastFramePropertyValue{ 0 }; + bool _stopLoop{ false }; + float _endAnim{ 0 }; }; From 3f7a9e97039eb5e5e58d051c0af7384aded17e26 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 10 Nov 2017 15:36:57 -0800 Subject: [PATCH 04/48] all entity animation fixes including the animation play reset --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 989f019980..3ed0bdfc43 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1364,6 +1364,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { _currentFrame = newAnimationProperties.getCurrentFrame(); _endAnim = (_currentFrame - 1) + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())); + _lastAnimated = 0; //qCDebug(entitiesrenderer) << "reset current frame" << _endAnim; } if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { From 842cddde88603469e5791ded31682d244010ba9a Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 13 Nov 2017 11:58:49 -0800 Subject: [PATCH 05/48] Deleted new members of RenderableModelEntity.h that were not necessary to implement the loop,hold,play properties for an entity animationq --- libraries/entities-renderer/src/RenderableModelEntityItem.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 65b915465c..16892ce3e0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -185,11 +185,6 @@ private: bool _animating { false }; uint64_t _lastAnimated { 0 }; float _currentFrame { 0 }; - //bool _previousHold{ false }; - float _currentFramePropertyValue{ 0 }; - float _firstFramePropertyValue{ 0 }; - float _lastFramePropertyValue{ 0 }; - bool _stopLoop{ false }; float _endAnim{ 0 }; }; From cc43d8115c3fff02e5aa0d878f0eeabf427bb248 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 15 Nov 2017 17:41:33 -0800 Subject: [PATCH 06/48] In response to bug in the original PR, in RenderModelEntityItem.cpp I made a change in the handling of the boundary cases for the first and last frame properties. Also deleted some extraneous comments. --- .../src/RenderableModelEntityItem.cpp | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3ed0bdfc43..aedc649470 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -980,8 +980,6 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } - //added by angus - //this a spot to work on the avatar npc in my branch QVector jointsData; @@ -1000,7 +998,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { if ((firstFrame >= 0) && (firstFrame < lastFrame) && (lastFrame <= frameCount)) { //length of animation in now determined by first and last frame - updatedFrameCount = lastFrame - firstFrame; + updatedFrameCount = (lastFrame - firstFrame + 1); } @@ -1016,14 +1014,12 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { //here we implement the looping animation property //if we have played through the animation once then we hold on the last frame - // if (!isLooping && (_currentFrame > _endAnim)) { - //don't advance current frame!!! - - //}else{ + if( isLooping || ( _currentFrame < _endAnim ) ){ //else advance the current frame. //if hold or not playing don't advance the current frame. - if (!isHolding && entity->getAnimationIsPlaying()) { + //also if the animFrame is outside of first or last frame then don't advance the motion. + if (!isHolding && entity->getAnimationIsPlaying() && !( _renderAnimationProperties.getCurrentFrame() > _renderAnimationProperties.getLastFrame() ) && !( _renderAnimationProperties.getCurrentFrame() < _renderAnimationProperties.getFirstFrame() ) ) { float deltaTime = (float)interval / (float)USECS_PER_SECOND; _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); } @@ -1362,17 +1358,14 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (newAnimationProperties != _renderAnimationProperties) { withWriteLock([&] { if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { - _currentFrame = newAnimationProperties.getCurrentFrame(); - _endAnim = (_currentFrame - 1) + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())); - _lastAnimated = 0; - //qCDebug(entitiesrenderer) << "reset current frame" << _endAnim; - } - if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { - //set the end of animation relative to the current frame - //qCDebug(entitiesrenderer) << "turned off looping"; - float startOffset = newAnimationProperties.getCurrentFrame() - newAnimationProperties.getFirstFrame(); - float posRelativeToStart = (_currentFrame - newAnimationProperties.getFirstFrame()) - startOffset; - _endAnim = (_currentFrame - 1) + (((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - ((int)(glm::floor(posRelativeToStart)) % ((int)newAnimationProperties.getLastFrame() - (int)newAnimationProperties.getFirstFrame()))); + if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { + _currentFrame = newAnimationProperties.getCurrentFrame(); + _endAnim = _currentFrame + ( newAnimationProperties.getLastFrame() - newAnimationProperties.getFirstFrame() ); + _lastAnimated = 0; + } + }else if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { + int currentframe_mod_length = (int)(_currentFrame - (int)(glm::floor(newAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(newAnimationProperties.getLastFrame())) - (int)(glm::floor(newAnimationProperties.getFirstFrame())) + 1); + _endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; } _renderAnimationProperties = newAnimationProperties; }); From 881b22ab159d637561971b63596d7e176cf5552e Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 16 Nov 2017 12:41:56 -0800 Subject: [PATCH 07/48] added update function to modelEntityItem.cpp --- .../src/RenderableModelEntityItem.cpp | 1 + libraries/entities/src/ModelEntityItem.cpp | 23 +++++++++++++++++++ libraries/entities/src/ModelEntityItem.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index aedc649470..e78e609699 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1356,6 +1356,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // make a copy of the animation properites auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { + qCDebug(entitiesrenderer) << "this is where the change is currently handled in the rendering code"; withWriteLock([&] { if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index ae73fa684a..515d76a9b3 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -186,6 +186,29 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit } +//angus +/* +void ModelEntityItem::update(const quint64& now) { + + //put something here + qCDebug(entities) << "model entity item update"; + + +} + +bool ModelEntityItem::needsToCallUpdate() const { + + + //put something here + qCDebug(entities) << "needs to call update"; + return true; +} +*/ +//angus + + + + void ModelEntityItem::debugDump() const { qCDebug(entities) << "ModelEntityItem id:" << getEntityItemID(); qCDebug(entities) << " edited ago:" << getEditedAgo(); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 698197b1a6..4f13fbdf6a 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -46,8 +46,10 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + //angus //virtual void update(const quint64& now) override; //virtual bool needsToCallUpdate() const override; + //angus virtual void debugDump() const override; void setShapeType(ShapeType type) override; From 20fd893b47dfd3b2214c830fd56646c81393e8a6 Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 16 Nov 2017 18:38:28 -0800 Subject: [PATCH 08/48] Starting to implement the update function to ModelEntityItem_cpp Also put access to the currently playing frame in RenderableModelEntityItem_cpp --- .../src/RenderableModelEntityItem.cpp | 4 +- .../entities/src/AnimationPropertyGroup.cpp | 12 ++++++ .../entities/src/AnimationPropertyGroup.h | 1 + libraries/entities/src/ModelEntityItem.cpp | 42 +++++++++++++++---- libraries/entities/src/ModelEntityItem.h | 10 ++++- 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e78e609699..2ba8a7a45f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -971,9 +971,6 @@ void ModelEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entit entity->setModel({}); } -bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b) { - return !(a == b); -} void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { if (!_animation || !_animation->isLoaded()) { @@ -1357,6 +1354,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { qCDebug(entitiesrenderer) << "this is where the change is currently handled in the rendering code"; + qCDebug(entitiesrenderer) << "getting the currently playing frame from the modelentityitem update" << entity->getCurrentlyPlayingFrame(); withWriteLock([&] { if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index d6a2937553..c871849064 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -31,6 +31,18 @@ bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b (a._hold == b._hold); } +bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b) { + return + (a._url != b._url) || + (a._currentFrame != b._currentFrame) || + (a._running != b._running) || + (a._loop != b._loop) || + (a._firstFrame != b._firstFrame) || + (a._lastFrame != b._lastFrame) || + (a._hold != b._hold); +} + + void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index affa960d66..54d4ced92f 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -89,6 +89,7 @@ public: protected: friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b); + friend bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b); void setFromOldAnimationSettings(const QString& value); }; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 515d76a9b3..c24efa8eec 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -187,12 +187,33 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit //angus -/* + void ModelEntityItem::update(const quint64& now) { //put something here - qCDebug(entities) << "model entity item update"; + //qCDebug(entities) << "model entity item update" << getName() << " " << getEntityItemID(); + { + auto currentAnimationProperties = this->getAnimationProperties(); + + if (_previousAnimationProperties != currentAnimationProperties) { + qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code"; + withWriteLock([&] { + //if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { + // if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { + // _currentFrame = newAnimationProperties.getCurrentFrame(); + // _endAnim = _currentFrame + ( newAnimationProperties.getLastFrame() - newAnimationProperties.getFirstFrame() ); + //_lastAnimated = 0; + // } + //}else if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { + // int currentframe_mod_length = (int)(_currentFrame - (int)(glm::floor(newAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(newAnimationProperties.getLastFrame())) - (int)(glm::floor(newAnimationProperties.getFirstFrame())) + 1); + // _endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; + // } + _previousAnimationProperties = currentAnimationProperties; + }); + } + + } } @@ -200,10 +221,10 @@ bool ModelEntityItem::needsToCallUpdate() const { //put something here - qCDebug(entities) << "needs to call update"; + //qCDebug(entities) << "needs to call update"; return true; } -*/ + //angus @@ -603,8 +624,9 @@ float ModelEntityItem::getAnimationLastFrame() const { return _animationProperties.getLastFrame(); }); } +//angus change bool ModelEntityItem::getAnimationIsPlaying() const { - return resultWithReadLock([&] { + return resultWithReadLock([&] { return _animationProperties.getRunning(); }); } @@ -614,11 +636,17 @@ float ModelEntityItem::getAnimationCurrentFrame() const { return _animationProperties.getCurrentFrame(); }); } - +//angus change bool ModelEntityItem::isAnimatingSomething() const { - return resultWithReadLock([&] { + return resultWithReadLock([&] { return !_animationProperties.getURL().isEmpty() && _animationProperties.getRunning() && (_animationProperties.getFPS() != 0.0f); }); } + +float ModelEntityItem::getCurrentlyPlayingFrame() const { + return resultWithReadLock([&] { + return _currentlyPlayingFrame; + }); +} diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 4f13fbdf6a..c9c33e10c9 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -47,8 +47,8 @@ public: bool& somethingChanged) override; //angus - //virtual void update(const quint64& now) override; - //virtual bool needsToCallUpdate() const override; + virtual void update(const quint64& now) override; + virtual bool needsToCallUpdate() const override; //angus virtual void debugDump() const override; @@ -107,6 +107,8 @@ public: float getAnimationCurrentFrame() const; bool isAnimatingSomething() const; + float getCurrentlyPlayingFrame() const; + static const QString DEFAULT_TEXTURES; const QString getTextures() const; void setTextures(const QString& textures); @@ -163,6 +165,10 @@ protected: QString _textures; ShapeType _shapeType = SHAPE_TYPE_NONE; + +private: + float _currentlyPlayingFrame{ 0 }; + AnimationPropertyGroup _previousAnimationProperties; }; #endif // hifi_ModelEntityItem_h From 013d16cee9e0d30c05458e76685ae8675549efba Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 17 Nov 2017 18:37:54 -0800 Subject: [PATCH 09/48] this is the change to add a property for the currentframeplaying --- .../src/RenderableModelEntityItem.cpp | 27 +++++++-- .../src/RenderableModelEntityItem.h | 4 +- .../entities/src/AnimationPropertyGroup.cpp | 16 +++++ .../entities/src/AnimationPropertyGroup.h | 1 + .../entities/src/EntityItemProperties.cpp | 1 + libraries/entities/src/EntityPropertyFlags.h | 2 + libraries/entities/src/ModelEntityItem.cpp | 60 +++++++++++++++---- libraries/entities/src/ModelEntityItem.h | 11 +++- 8 files changed, 102 insertions(+), 20 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 2ba8a7a45f..3176010536 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -993,12 +993,19 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { bool isHolding = entity->getAnimationHold(); int updatedFrameCount = frameCount; + //get the updated frame from the ModelEntity + auto modelAnimProperties = entity->getAnimationProperties(); + withWriteLock([&] { + _currentFrame = modelAnimProperties.getCurrentlyPlayingFrame(); + }); + qCDebug(entitiesrenderer) << "the client frame count is the following " << _currentFrame; + if ((firstFrame >= 0) && (firstFrame < lastFrame) && (lastFrame <= frameCount)) { //length of animation in now determined by first and last frame updatedFrameCount = (lastFrame - firstFrame + 1); } - + /* if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; @@ -1008,7 +1015,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { auto interval = now - _lastAnimated; _lastAnimated = now; - + //here we implement the looping animation property //if we have played through the animation once then we hold on the last frame @@ -1021,12 +1028,12 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); } } - + */ { //where are we in the currently defined animation segment? - int animationCurrentFrame = (int)(glm::floor(_currentFrame - _renderAnimationProperties.getFirstFrame())) % updatedFrameCount; + int animationCurrentFrame = (int)(glm::floor(_currentFrame - firstFrame)) % updatedFrameCount; //this gives us the absolute frame value to use by adding the first frame value. - animationCurrentFrame += _renderAnimationProperties.getFirstFrame(); + animationCurrentFrame += firstFrame; @@ -1347,7 +1354,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (model->getRenderItemsNeedUpdate()) { model->updateRenderItems(); } - + /* { DETAILED_PROFILE_RANGE(simulation_physics, "CheckAnimation"); // make a copy of the animation properites @@ -1370,6 +1377,14 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce }); } } + */ + //angus + { + + //_currentFrame = entity->getCurrentlyPlayingFrame(); + } + //angus + if (_animating) { DETAILED_PROFILE_RANGE(simulation_physics, "Animate"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 16892ce3e0..3a0c5c506b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -183,9 +183,9 @@ private: bool _marketplaceEntity { false }; bool _shouldHighlight { false }; bool _animating { false }; - uint64_t _lastAnimated { 0 }; + //uint64_t _lastAnimated { 0 }; float _currentFrame { 0 }; - float _endAnim{ 0 }; + //float _endAnim{ 0 }; }; diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index c871849064..5f5d68be24 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -53,6 +53,7 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, Animation, animation, CurrentlyPlayingFrame, currentlyPlayingFrame); } @@ -73,6 +74,9 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, setLastFrame); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, setHold); + //angus added + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, currentlyPlayingFrame, float, setCurrentlyPlayingFrame); + // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, setFPS, getFPS); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationIsPlaying, bool, setRunning, getRunning); @@ -89,6 +93,7 @@ void AnimationPropertyGroup::merge(const AnimationPropertyGroup& other) { COPY_PROPERTY_IF_CHANGED(firstFrame); COPY_PROPERTY_IF_CHANGED(lastFrame); COPY_PROPERTY_IF_CHANGED(hold); + COPY_PROPERTY_IF_CHANGED(currentlyPlayingFrame); } void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { @@ -195,6 +200,8 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold()); + //angus + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, getCurrentlyPlayingFrame()); return true; } @@ -216,6 +223,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); + READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, float, setCurrentlyPlayingFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FPS, FPS); @@ -226,6 +234,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, CurrentlyPlayingFrame); processedBytes += bytesRead; @@ -258,6 +267,7 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_ALLOW_TRANSLATION, allowTranslation); + CHECK_PROPERTY_CHANGE(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, currentlyPlayingFrame); return changedProperties; } @@ -272,6 +282,7 @@ void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) con COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, getFirstFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, getLastFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, getHold); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentlyPlayingFrame, getCurrentlyPlayingFrame); } bool AnimationPropertyGroup::setProperties(const EntityItemProperties& properties) { @@ -286,6 +297,7 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, setFirstFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, setLastFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, setHold); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentlyPlayingFrame, currentlyPlayingFrame, setCurrentlyPlayingFrame); return somethingChanged; } @@ -301,6 +313,8 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP requestedProperties += PROP_ANIMATION_LAST_FRAME; requestedProperties += PROP_ANIMATION_HOLD; requestedProperties += PROP_ANIMATION_ALLOW_TRANSLATION; + //angus + requestedProperties += PROP_ANIMATION_CURRENTLY_PLAYING_FRAME; return requestedProperties; } @@ -324,6 +338,7 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, getCurrentlyPlayingFrame()); } int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -343,5 +358,6 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); + READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, float, setCurrentlyPlayingFrame); return bytesRead; } diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index 54d4ced92f..8d0087b56d 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -86,6 +86,7 @@ public: DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold DEFINE_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation, allowTranslation, bool, true); + DEFINE_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, CurrentlyPlayingFrame, currentlyPlayingFrame, float, 0.0f); protected: friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 108fc14e30..77fa1231f1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1148,6 +1148,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, Animation, animation, CurrentlyPlayingFrame, currentlyPlayingFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 35d40b669a..3b1f4d60d0 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -40,6 +40,8 @@ enum EntityPropertyList { PROP_ANIMATION_FRAME_INDEX, PROP_ANIMATION_PLAYING, PROP_ANIMATION_ALLOW_TRANSLATION, + //angus + PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, // these properties are supported by the EntityItem base class PROP_REGISTRATION_POINT, diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index c24efa8eec..67357a6905 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -199,19 +199,20 @@ void ModelEntityItem::update(const quint64& now) { if (_previousAnimationProperties != currentAnimationProperties) { qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code"; withWriteLock([&] { - //if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { - // if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { - // _currentFrame = newAnimationProperties.getCurrentFrame(); - // _endAnim = _currentFrame + ( newAnimationProperties.getLastFrame() - newAnimationProperties.getFirstFrame() ); - //_lastAnimated = 0; - // } - //}else if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { - // int currentframe_mod_length = (int)(_currentFrame - (int)(glm::floor(newAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(newAnimationProperties.getLastFrame())) - (int)(glm::floor(newAnimationProperties.getFirstFrame())) + 1); - // _endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; - // } + if ( (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) || (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { + if (!(currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getLastFrame()) && !(currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getFirstFrame())) { + _currentlyPlayingFrame = currentAnimationProperties.getCurrentFrame(); + _endAnim = _currentlyPlayingFrame + ( currentAnimationProperties.getLastFrame() - currentAnimationProperties.getFirstFrame() ); + _lastAnimated = 0; + } + }else if ( _previousAnimationProperties.getLoop() && !currentAnimationProperties.getLoop()) { + int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); + _endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; + } _previousAnimationProperties = currentAnimationProperties; }); } + updateFrameCount(); } @@ -225,6 +226,38 @@ bool ModelEntityItem::needsToCallUpdate() const { return true; } +void ModelEntityItem::updateFrameCount() { + + + if (!_lastAnimated) { + _lastAnimated = usecTimestampNow(); + return; + } + + auto now = usecTimestampNow(); + auto interval = now - _lastAnimated; + _lastAnimated = now; + + + //here we implement the looping animation property + //get entity anim props + bool isLooping = getAnimationLoop(); + int firstFrame = getAnimationFirstFrame(); + int lastFrame = getAnimationLastFrame(); + bool isHolding = getAnimationHold(); + + if (isLooping || (_currentlyPlayingFrame < _endAnim)) { + //else advance the current frame. + //if hold or not playing don't advance the current frame. + //also if the animFrame is outside of first or last frame then don't advance the motion. + if (!isHolding && getAnimationIsPlaying() && !(_previousAnimationProperties.getCurrentFrame() > _previousAnimationProperties.getLastFrame()) && !(_previousAnimationProperties.getCurrentFrame() < _previousAnimationProperties.getFirstFrame())) { + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentlyPlayingFrame += (deltaTime * _previousAnimationProperties.getFPS()); + qCDebug(entities) << "the frame is now " << _currentlyPlayingFrame; + } + } +} + //angus @@ -650,3 +683,10 @@ float ModelEntityItem::getCurrentlyPlayingFrame() const { return _currentlyPlayingFrame; }); } + +int ModelEntityItem::getLastKnownCurrentFrame() const { + return resultWithReadLock([&] { + return _lastKnownCurrentFrame; + }); +} +//angus change \ No newline at end of file diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index c9c33e10c9..3df0ccdc36 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -17,6 +17,7 @@ #include #include "AnimationPropertyGroup.h" + class ModelEntityItem : public EntityItem { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -49,6 +50,7 @@ public: //angus virtual void update(const quint64& now) override; virtual bool needsToCallUpdate() const override; + void updateFrameCount(); //angus virtual void debugDump() const override; @@ -108,6 +110,7 @@ public: bool isAnimatingSomething() const; float getCurrentlyPlayingFrame() const; + int getLastKnownCurrentFrame() const; static const QString DEFAULT_TEXTURES; const QString getTextures() const; @@ -152,7 +155,7 @@ protected: }; QVector _localJointData; - int _lastKnownCurrentFrame; + int _lastKnownCurrentFrame{-1}; rgbColor _color; QString _modelURL; @@ -167,8 +170,12 @@ protected: ShapeType _shapeType = SHAPE_TYPE_NONE; private: - float _currentlyPlayingFrame{ 0 }; + //angus + float _currentlyPlayingFrame{ -1 }; + float _endAnim{ 0 }; + uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; + //angus }; #endif // hifi_ModelEntityItem_h From befa0f8ab54de74211b85361565c86bd9351f138 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 20 Nov 2017 09:11:15 -0800 Subject: [PATCH 10/48] now the update frame is only happening in the assignment client code. added setCurrentlyPlayingFrame to ModelEntityItem.cpp --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 3 ++- libraries/entities/src/ModelEntityItem.cpp | 8 ++++++++ libraries/entities/src/ModelEntityItem.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 07d8716656..42fcd9af6f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -309,7 +309,8 @@ void EntityTreeRenderer::update(bool simulate) { PerformanceTimer perfTimer("ETRupdate"); if (_tree && !_shuttingDown) { EntityTreePointer tree = std::static_pointer_cast(_tree); - tree->update(simulate); + //angus + //tree->update(simulate); // Update the rendereable entities as needed { diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 67357a6905..c6e6a7a069 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -254,6 +254,7 @@ void ModelEntityItem::updateFrameCount() { float deltaTime = (float)interval / (float)USECS_PER_SECOND; _currentlyPlayingFrame += (deltaTime * _previousAnimationProperties.getFPS()); qCDebug(entities) << "the frame is now " << _currentlyPlayingFrame; + setAnimationCurrentlyPlayingFrame(_currentlyPlayingFrame); } } } @@ -609,6 +610,12 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) { }); } +void ModelEntityItem::setAnimationCurrentlyPlayingFrame(float value) { + withWriteLock([&] { + _animationProperties.setCurrentlyPlayingFrame(value); + }); +} + void ModelEntityItem::setAnimationLoop(bool loop) { withWriteLock([&] { _animationProperties.setLoop(loop); @@ -669,6 +676,7 @@ float ModelEntityItem::getAnimationCurrentFrame() const { return _animationProperties.getCurrentFrame(); }); } + //angus change bool ModelEntityItem::isAnimatingSomething() const { return resultWithReadLock([&] { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 3df0ccdc36..1c1c834d82 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -87,6 +87,7 @@ public: void setAnimationURL(const QString& url); void setAnimationCurrentFrame(float value); + void setAnimationCurrentlyPlayingFrame(float value); void setAnimationIsPlaying(bool value); void setAnimationFPS(float value); From 1e5d099b06feaac93e092a4d5e70311b87258714 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 21 Nov 2017 17:36:01 -0800 Subject: [PATCH 11/48] changed the currentlyplayingframe property so that it is updated in RenderableModelEntity.cpp now. Remains to remove everything but initializing currentlyPlayingFrame in ModelEntityRender.cpp --- .../src/RenderableModelEntityItem.cpp | 30 +++++++++---------- .../src/RenderableModelEntityItem.h | 7 +++-- .../entities/src/AnimationPropertyGroup.cpp | 9 ++++++ libraries/entities/src/ModelEntityItem.cpp | 5 +++- libraries/entities/src/ModelEntityItem.h | 2 ++ 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3176010536..a3e90c925f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -995,9 +995,13 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { //get the updated frame from the ModelEntity auto modelAnimProperties = entity->getAnimationProperties(); - withWriteLock([&] { - _currentFrame = modelAnimProperties.getCurrentlyPlayingFrame(); - }); + + + //_currentFrame = modelAnimProperties.getCurrentlyPlayingFrame(); + + //tempbool = modelAnimProperties.getRunning(); + //qCDebug(entitiesrenderer) << "is playing is: " << tempbool; + qCDebug(entitiesrenderer) << "the client frame count is the following " << _currentFrame; if ((firstFrame >= 0) && (firstFrame < lastFrame) && (lastFrame <= frameCount)) { @@ -1005,7 +1009,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { updatedFrameCount = (lastFrame - firstFrame + 1); } - /* + if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; @@ -1025,13 +1029,13 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { //also if the animFrame is outside of first or last frame then don't advance the motion. if (!isHolding && entity->getAnimationIsPlaying() && !( _renderAnimationProperties.getCurrentFrame() > _renderAnimationProperties.getLastFrame() ) && !( _renderAnimationProperties.getCurrentFrame() < _renderAnimationProperties.getFirstFrame() ) ) { float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + _currentlyPlayingFrame += (deltaTime * _renderAnimationProperties.getFPS()); } } - */ + { //where are we in the currently defined animation segment? - int animationCurrentFrame = (int)(glm::floor(_currentFrame - firstFrame)) % updatedFrameCount; + int animationCurrentFrame = (int)(glm::floor(_currentlyPlayingFrame - firstFrame)) % updatedFrameCount; //this gives us the absolute frame value to use by adding the first frame value. animationCurrentFrame += firstFrame; @@ -1354,7 +1358,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (model->getRenderItemsNeedUpdate()) { model->updateRenderItems(); } - /* + { DETAILED_PROFILE_RANGE(simulation_physics, "CheckAnimation"); // make a copy of the animation properites @@ -1373,17 +1377,13 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce int currentframe_mod_length = (int)(_currentFrame - (int)(glm::floor(newAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(newAnimationProperties.getLastFrame())) - (int)(glm::floor(newAnimationProperties.getFirstFrame())) + 1); _endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; } + _currentlyPlayingFrame = newAnimationProperties.getCurrentlyPlayingFrame(); _renderAnimationProperties = newAnimationProperties; }); } } - */ - //angus - { - - //_currentFrame = entity->getCurrentlyPlayingFrame(); - } - //angus + //angus + if (_animating) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3a0c5c506b..e6a970d0eb 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -183,10 +183,11 @@ private: bool _marketplaceEntity { false }; bool _shouldHighlight { false }; bool _animating { false }; - //uint64_t _lastAnimated { 0 }; + uint64_t _lastAnimated { 0 }; float _currentFrame { 0 }; - //float _endAnim{ 0 }; - + float _endAnim{ 0 }; + bool tempbool{ false }; + float _currentlyPlayingFrame{ 0 }; }; } } // namespace diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 5f5d68be24..8488c6fb25 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -109,6 +109,7 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { bool loop = getLoop(); bool hold = getHold(); bool allowTranslation = getAllowTranslation(); + float currentlyPlayingFrame = getCurrentlyPlayingFrame(); QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); QJsonObject settingsAsJsonObject = settingsAsJson.object(); @@ -147,6 +148,10 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { allowTranslation = settingsMap["allowTranslation"].toBool(); } + if (settingsMap.contains("currentlyPlayingFrame")) { + currentlyPlayingFrame = settingsMap["currentlyPlayingFrame"].toFloat(); + } + setAllowTranslation(allowTranslation); setFPS(fps); setCurrentFrame(currentFrame); @@ -155,6 +160,7 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { setLastFrame(lastFrame); setLoop(loop); setHold(hold); + setCurrentlyPlayingFrame(currentlyPlayingFrame); } @@ -179,6 +185,9 @@ void AnimationPropertyGroup::listChangedProperties(QList& out) { if (allowTranslationChanged()) { out << "animation-allowTranslation"; } + if (currentlyPlayingFrameChanged()) { + out << "animation-currentlyPlayingFrame"; + } } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index c6e6a7a069..784193d3d5 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -209,9 +209,10 @@ void ModelEntityItem::update(const quint64& now) { int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); _endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; } - _previousAnimationProperties = currentAnimationProperties; + //_previousAnimationProperties = currentAnimationProperties; }); } + _previousAnimationProperties = currentAnimationProperties; updateFrameCount(); } @@ -256,6 +257,7 @@ void ModelEntityItem::updateFrameCount() { qCDebug(entities) << "the frame is now " << _currentlyPlayingFrame; setAnimationCurrentlyPlayingFrame(_currentlyPlayingFrame); } + } } @@ -611,6 +613,7 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) { } void ModelEntityItem::setAnimationCurrentlyPlayingFrame(float value) { + _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; withWriteLock([&] { _animationProperties.setCurrentlyPlayingFrame(value); }); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 1c1c834d82..2e901ed318 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -176,6 +176,8 @@ private: float _endAnim{ 0 }; uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; + bool _propTestFlag{ true }; + bool _propTestFlag2{ true }; //angus }; From fdf5139a7409c231598d59e4350b85415e062243 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 22 Nov 2017 17:52:13 -0800 Subject: [PATCH 12/48] everything now works with an atomic start time property. but now I will get rid of this and use current frame instead --- .../src/RenderableModelEntityItem.cpp | 33 ++++++++--- .../src/RenderableModelEntityItem.h | 2 +- .../entities/src/AnimationPropertyGroup.cpp | 10 ++-- .../entities/src/AnimationPropertyGroup.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 55 ++++++++++++------- libraries/entities/src/ModelEntityItem.h | 6 +- 6 files changed, 70 insertions(+), 38 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a3e90c925f..80aba9deba 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -997,7 +997,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { auto modelAnimProperties = entity->getAnimationProperties(); - //_currentFrame = modelAnimProperties.getCurrentlyPlayingFrame(); + //_currentFrame = modelAnimProperties.getCurrentFrame(); //tempbool = modelAnimProperties.getRunning(); //qCDebug(entitiesrenderer) << "is playing is: " << tempbool; @@ -1016,26 +1016,44 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { } auto now = usecTimestampNow(); - auto interval = now - _lastAnimated; + + //find out how long it has been since this animation started. + auto interval = now - _currentlyPlayingFrame; + //auto interval = now - _lastAnimated; _lastAnimated = now; + //new global start time code + float nowTime = (float)interval / (float)USECS_PER_SECOND; + float oldCurrentFrame = _currentFrame; + _currentFrame = _renderAnimationProperties.getCurrentFrame() + (nowTime * _renderAnimationProperties.getFPS()); + + //here we implement the looping animation property //if we have played through the animation once then we hold on the last frame - if( isLooping || ( _currentFrame < _endAnim ) ){ + if( isLooping || (_currentFrame < _endAnim ) ){ //else advance the current frame. //if hold or not playing don't advance the current frame. //also if the animFrame is outside of first or last frame then don't advance the motion. if (!isHolding && entity->getAnimationIsPlaying() && !( _renderAnimationProperties.getCurrentFrame() > _renderAnimationProperties.getLastFrame() ) && !( _renderAnimationProperties.getCurrentFrame() < _renderAnimationProperties.getFirstFrame() ) ) { - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentlyPlayingFrame += (deltaTime * _renderAnimationProperties.getFPS()); + //float deltaTime = (float)interval / (float)USECS_PER_SECOND; + //_currentlyPlayingFrame += (deltaTime * _renderAnimationProperties.getFPS()); + //do nothing } + else { + //use old currentFrame + _currentFrame = oldCurrentFrame; + } + } + else { + //make current frame the endanim frame + _currentFrame = _endAnim; } { //where are we in the currently defined animation segment? - int animationCurrentFrame = (int)(glm::floor(_currentlyPlayingFrame - firstFrame)) % updatedFrameCount; + int animationCurrentFrame = (int)(glm::floor(_currentFrame - firstFrame)) % updatedFrameCount; //this gives us the absolute frame value to use by adding the first frame value. animationCurrentFrame += firstFrame; @@ -1369,7 +1387,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce withWriteLock([&] { if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { - _currentFrame = newAnimationProperties.getCurrentFrame(); + _currentFrame = newAnimationProperties.getCurrentFrame();// +((float)newAnimationProperties.getCurrentlyPlayingFrame() / (float)USECS_PER_SECOND)*(newAnimationProperties.getFPS()); _endAnim = _currentFrame + ( newAnimationProperties.getLastFrame() - newAnimationProperties.getFirstFrame() ); _lastAnimated = 0; } @@ -1378,6 +1396,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; } _currentlyPlayingFrame = newAnimationProperties.getCurrentlyPlayingFrame(); + qCDebug(entitiesrenderer) << "renderable update to currently playing frame " << _currentlyPlayingFrame; _renderAnimationProperties = newAnimationProperties; }); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index e6a970d0eb..fdb0cf5d2c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -187,7 +187,7 @@ private: float _currentFrame { 0 }; float _endAnim{ 0 }; bool tempbool{ false }; - float _currentlyPlayingFrame{ 0 }; + quint64 _currentlyPlayingFrame{ 0 }; }; } } // namespace diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 8488c6fb25..67de381d1b 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -75,7 +75,7 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, setHold); //angus added - COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, currentlyPlayingFrame, float, setCurrentlyPlayingFrame); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, currentlyPlayingFrame, quint64, setCurrentlyPlayingFrame); // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, setFPS, getFPS); @@ -109,7 +109,7 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { bool loop = getLoop(); bool hold = getHold(); bool allowTranslation = getAllowTranslation(); - float currentlyPlayingFrame = getCurrentlyPlayingFrame(); + quint64 currentlyPlayingFrame = getCurrentlyPlayingFrame(); QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); QJsonObject settingsAsJsonObject = settingsAsJson.object(); @@ -149,7 +149,7 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { } if (settingsMap.contains("currentlyPlayingFrame")) { - currentlyPlayingFrame = settingsMap["currentlyPlayingFrame"].toFloat(); + currentlyPlayingFrame = settingsMap["currentlyPlayingFrame"].toULongLong(); } setAllowTranslation(allowTranslation); @@ -232,7 +232,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, float, setCurrentlyPlayingFrame); + READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, quint64, setCurrentlyPlayingFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FPS, FPS); @@ -367,6 +367,6 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, float, setCurrentlyPlayingFrame); + READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, quint64, setCurrentlyPlayingFrame); return bytesRead; } diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index 8d0087b56d..1a3da52684 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -86,7 +86,7 @@ public: DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold DEFINE_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation, allowTranslation, bool, true); - DEFINE_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, CurrentlyPlayingFrame, currentlyPlayingFrame, float, 0.0f); + DEFINE_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, CurrentlyPlayingFrame, currentlyPlayingFrame, quint64, 0); protected: friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 784193d3d5..bdf4f6f3f9 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -200,19 +200,23 @@ void ModelEntityItem::update(const quint64& now) { qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code"; withWriteLock([&] { if ( (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) || (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { - if (!(currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getLastFrame()) && !(currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getFirstFrame())) { - _currentlyPlayingFrame = currentAnimationProperties.getCurrentFrame(); - _endAnim = _currentlyPlayingFrame + ( currentAnimationProperties.getLastFrame() - currentAnimationProperties.getFirstFrame() ); - _lastAnimated = 0; - } - }else if ( _previousAnimationProperties.getLoop() && !currentAnimationProperties.getLoop()) { - int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); - _endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; + // if (!(currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getLastFrame()) && !(currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getFirstFrame())) { + // _currentlyPlayingFrame = currentAnimationProperties.getCurrentFrame(); + //_endAnim = _currentlyPlayingFrame + ( currentAnimationProperties.getLastFrame() - currentAnimationProperties.getFirstFrame() ); + //_lastAnimated = 0; + // } + setAnimationCurrentlyPlayingFrame(usecTimestampNow()); } - //_previousAnimationProperties = currentAnimationProperties; + //else if ( _previousAnimationProperties.getLoop() && !currentAnimationProperties.getLoop()) { + // int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); + //_endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; + //} + _previousAnimationProperties = currentAnimationProperties; }); + + qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code, currently playing frame is: " << currentAnimationProperties.getCurrentlyPlayingFrame(); } - _previousAnimationProperties = currentAnimationProperties; + //_previousAnimationProperties = currentAnimationProperties; updateFrameCount(); } @@ -229,36 +233,45 @@ bool ModelEntityItem::needsToCallUpdate() const { void ModelEntityItem::updateFrameCount() { - + if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; } + auto now = usecTimestampNow(); - auto interval = now - _lastAnimated; - _lastAnimated = now; + + //this is now getting the time since the server started the animation. + //auto interval = now - _currentlyPlayingFrame; + //auto interval = now - _lastAnimated; + //_lastAnimated = now; + + //here we implement the looping animation property //get entity anim props + bool isLooping = getAnimationLoop(); int firstFrame = getAnimationFirstFrame(); int lastFrame = getAnimationLastFrame(); bool isHolding = getAnimationHold(); - if (isLooping || (_currentlyPlayingFrame < _endAnim)) { + //if (isLooping || (_currentFrame < _endAnim)) { //else advance the current frame. //if hold or not playing don't advance the current frame. //also if the animFrame is outside of first or last frame then don't advance the motion. if (!isHolding && getAnimationIsPlaying() && !(_previousAnimationProperties.getCurrentFrame() > _previousAnimationProperties.getLastFrame()) && !(_previousAnimationProperties.getCurrentFrame() < _previousAnimationProperties.getFirstFrame())) { - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentlyPlayingFrame += (deltaTime * _previousAnimationProperties.getFPS()); - qCDebug(entities) << "the frame is now " << _currentlyPlayingFrame; - setAnimationCurrentlyPlayingFrame(_currentlyPlayingFrame); + // float deltaTime = (float)interval / (float)USECS_PER_SECOND; + // _currentlyPlayingFrame += (deltaTime * _previousAnimationProperties.getFPS()); + // qCDebug(entities) << "the frame is now " << _currentlyPlayingFrame; + // setAnimationCurrentlyPlayingFrame(_currentlyPlayingFrame); + setAnimationCurrentlyPlayingFrame(now); } - } + //} + } //angus @@ -612,7 +625,7 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) { }); } -void ModelEntityItem::setAnimationCurrentlyPlayingFrame(float value) { +void ModelEntityItem::setAnimationCurrentlyPlayingFrame(quint64 value) { _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; withWriteLock([&] { _animationProperties.setCurrentlyPlayingFrame(value); @@ -689,7 +702,7 @@ bool ModelEntityItem::isAnimatingSomething() const { }); } -float ModelEntityItem::getCurrentlyPlayingFrame() const { +quint64 ModelEntityItem::getCurrentlyPlayingFrame() const { return resultWithReadLock([&] { return _currentlyPlayingFrame; }); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 2e901ed318..dad022ae0a 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -87,7 +87,7 @@ public: void setAnimationURL(const QString& url); void setAnimationCurrentFrame(float value); - void setAnimationCurrentlyPlayingFrame(float value); + void setAnimationCurrentlyPlayingFrame(quint64 value); void setAnimationIsPlaying(bool value); void setAnimationFPS(float value); @@ -110,7 +110,7 @@ public: float getAnimationCurrentFrame() const; bool isAnimatingSomething() const; - float getCurrentlyPlayingFrame() const; + quint64 getCurrentlyPlayingFrame() const; int getLastKnownCurrentFrame() const; static const QString DEFAULT_TEXTURES; @@ -172,7 +172,7 @@ protected: private: //angus - float _currentlyPlayingFrame{ -1 }; + quint64 _currentlyPlayingFrame{ 0 }; float _endAnim{ 0 }; uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; From 2e75016021d41cd4057c9c1f44a5325c2dd5c7cc Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 22 Nov 2017 17:53:21 -0800 Subject: [PATCH 13/48] changes to modelEntity.cpp --- .../src/RenderableModelEntityItem.cpp | 46 +++++++++---------- libraries/entities/src/ModelEntityItem.cpp | 45 +++++++++++------- libraries/entities/src/ModelEntityItem.h | 1 + 3 files changed, 53 insertions(+), 39 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 80aba9deba..b3417e7946 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -991,7 +991,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { int firstFrame = entity->getAnimationFirstFrame(); int lastFrame = entity->getAnimationLastFrame(); bool isHolding = entity->getAnimationHold(); - int updatedFrameCount = frameCount; + int updatedFrameCount = lastFrame - firstFrame + 1; //get the updated frame from the ModelEntity auto modelAnimProperties = entity->getAnimationProperties(); @@ -1018,45 +1018,45 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { auto now = usecTimestampNow(); //find out how long it has been since this animation started. - auto interval = now - _currentlyPlayingFrame; - //auto interval = now - _lastAnimated; + + auto interval = now - _lastAnimated; _lastAnimated = now; - - //new global start time code - float nowTime = (float)interval / (float)USECS_PER_SECOND; float oldCurrentFrame = _currentFrame; - _currentFrame = _renderAnimationProperties.getCurrentFrame() + (nowTime * _renderAnimationProperties.getFPS()); - + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); //here we implement the looping animation property //if we have played through the animation once then we hold on the last frame - if( isLooping || (_currentFrame < _endAnim ) ){ + if( isLooping || (_currentFrame < _renderAnimationProperties.getLastFrame() ) ){ //else advance the current frame. //if hold or not playing don't advance the current frame. //also if the animFrame is outside of first or last frame then don't advance the motion. if (!isHolding && entity->getAnimationIsPlaying() && !( _renderAnimationProperties.getCurrentFrame() > _renderAnimationProperties.getLastFrame() ) && !( _renderAnimationProperties.getCurrentFrame() < _renderAnimationProperties.getFirstFrame() ) ) { - //float deltaTime = (float)interval / (float)USECS_PER_SECOND; - //_currentlyPlayingFrame += (deltaTime * _renderAnimationProperties.getFPS()); - //do nothing + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + while ((_currentFrame - _renderAnimationProperties.getFirstFrame()) > updatedFrameCount) { + _currentFrame -= updatedFrameCount; + } } else { //use old currentFrame _currentFrame = oldCurrentFrame; } - } - else { + }else { //make current frame the endanim frame - _currentFrame = _endAnim; + _currentFrame = _renderAnimationProperties.getLastFrame(); } + //save the last place that we rendered ourselves. + //entity->setAnimationCurrentFrame(_currentFrame); { //where are we in the currently defined animation segment? - int animationCurrentFrame = (int)(glm::floor(_currentFrame - firstFrame)) % updatedFrameCount; + // int animationCurrentFrame = (int)(glm::floor(_currentFrame - firstFrame)) % updatedFrameCount; //this gives us the absolute frame value to use by adding the first frame value. - animationCurrentFrame += firstFrame; - + // animationCurrentFrame += firstFrame; + int animationCurrentFrame = (int)(glm::floor(_currentFrame)); @@ -1383,7 +1383,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { qCDebug(entitiesrenderer) << "this is where the change is currently handled in the rendering code"; - qCDebug(entitiesrenderer) << "getting the currently playing frame from the modelentityitem update" << entity->getCurrentlyPlayingFrame(); + qCDebug(entitiesrenderer) << "getting the currently playing frame from the modelentityitem update" << newAnimationProperties.getCurrentFrame(); withWriteLock([&] { if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { @@ -1392,11 +1392,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _lastAnimated = 0; } }else if ( _renderAnimationProperties.getLoop() && !newAnimationProperties.getLoop()) { - int currentframe_mod_length = (int)(_currentFrame - (int)(glm::floor(newAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(newAnimationProperties.getLastFrame())) - (int)(glm::floor(newAnimationProperties.getFirstFrame())) + 1); - _endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; + //int currentframe_mod_length = (int)(_currentFrame - (int)(glm::floor(newAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(newAnimationProperties.getLastFrame())) - (int)(glm::floor(newAnimationProperties.getFirstFrame())) + 1); + //_endAnim = _currentFrame + ((int)(newAnimationProperties.getLastFrame()) - (int)(newAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; } - _currentlyPlayingFrame = newAnimationProperties.getCurrentlyPlayingFrame(); - qCDebug(entitiesrenderer) << "renderable update to currently playing frame " << _currentlyPlayingFrame; + _currentFrame = newAnimationProperties.getCurrentFrame(); + qCDebug(entitiesrenderer) << "renderable update to current frame " << _currentFrame; _renderAnimationProperties = newAnimationProperties; }); } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index bdf4f6f3f9..b853077ca1 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -199,22 +199,27 @@ void ModelEntityItem::update(const quint64& now) { if (_previousAnimationProperties != currentAnimationProperties) { qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code"; withWriteLock([&] { - if ( (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) || (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { + _previousAnimationProperties = currentAnimationProperties; + if ( (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { // if (!(currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getLastFrame()) && !(currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getFirstFrame())) { // _currentlyPlayingFrame = currentAnimationProperties.getCurrentFrame(); //_endAnim = _currentlyPlayingFrame + ( currentAnimationProperties.getLastFrame() - currentAnimationProperties.getFirstFrame() ); //_lastAnimated = 0; // } - setAnimationCurrentlyPlayingFrame(usecTimestampNow()); + qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code, current frame is: \n\n" << currentAnimationProperties.getCurrentFrame(); + setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); } - //else if ( _previousAnimationProperties.getLoop() && !currentAnimationProperties.getLoop()) { - // int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); - //_endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; - //} - _previousAnimationProperties = currentAnimationProperties; + else { + //else if ( _previousAnimationProperties.getLoop() && !currentAnimationProperties.getLoop()) { + // int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); + //_endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; + //} + setAnimationCurrentFrame(currentAnimationProperties.getCurrentFrame()); + } + }); - qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code, currently playing frame is: " << currentAnimationProperties.getCurrentlyPlayingFrame(); + qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code, current frame is: " << currentAnimationProperties.getCurrentFrame(); } //_previousAnimationProperties = currentAnimationProperties; updateFrameCount(); @@ -244,8 +249,8 @@ void ModelEntityItem::updateFrameCount() { //this is now getting the time since the server started the animation. //auto interval = now - _currentlyPlayingFrame; - //auto interval = now - _lastAnimated; - //_lastAnimated = now; + auto interval = now - _lastAnimated; + _lastAnimated = now; @@ -257,20 +262,28 @@ void ModelEntityItem::updateFrameCount() { int firstFrame = getAnimationFirstFrame(); int lastFrame = getAnimationLastFrame(); bool isHolding = getAnimationHold(); + int updatedFrameCount = lastFrame - firstFrame + 1; - //if (isLooping || (_currentFrame < _endAnim)) { + if (isLooping || (_currentFrame < _previousAnimationProperties.getLastFrame())) { //else advance the current frame. //if hold or not playing don't advance the current frame. //also if the animFrame is outside of first or last frame then don't advance the motion. if (!isHolding && getAnimationIsPlaying() && !(_previousAnimationProperties.getCurrentFrame() > _previousAnimationProperties.getLastFrame()) && !(_previousAnimationProperties.getCurrentFrame() < _previousAnimationProperties.getFirstFrame())) { - // float deltaTime = (float)interval / (float)USECS_PER_SECOND; - // _currentlyPlayingFrame += (deltaTime * _previousAnimationProperties.getFPS()); - // qCDebug(entities) << "the frame is now " << _currentlyPlayingFrame; + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * _previousAnimationProperties.getFPS()); + while ((_currentFrame - _previousAnimationProperties.getFirstFrame()) > updatedFrameCount) { + _currentFrame -= updatedFrameCount; + } + qCDebug(entities) << "the frame is now 1 " << _currentFrame; // setAnimationCurrentlyPlayingFrame(_currentlyPlayingFrame); - setAnimationCurrentlyPlayingFrame(now); + setAnimationCurrentFrame(_currentFrame); } - //} + } else { + _currentFrame = getAnimationLastFrame(); + setAnimationCurrentFrame(_currentFrame); + qCDebug(entities) << "the frame is now 2 " << _currentFrame; + } } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index dad022ae0a..973f49aec4 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -178,6 +178,7 @@ private: AnimationPropertyGroup _previousAnimationProperties; bool _propTestFlag{ true }; bool _propTestFlag2{ true }; + float _currentFrame{ 0 }; //angus }; From d607ca0914445d26e9d23bbeed17517c0ba3a315 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 28 Nov 2017 11:04:48 -0800 Subject: [PATCH 14/48] initialize the _lastAnimated time when the modelEntityRenderer is instantiated, this fixes the sync between interface and the server --- .../src/RenderableModelEntityItem.cpp | 157 +++++++++++------- .../src/RenderableModelEntityItem.h | 7 +- libraries/entities/src/ModelEntityItem.cpp | 133 ++++++++++----- libraries/entities/src/ModelEntityItem.h | 3 +- 4 files changed, 190 insertions(+), 110 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ba0272ed2a..fa24a171f1 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -63,13 +63,17 @@ bool ModelEntityWrapper::isModelLoaded() const { EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity(new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()), [](EntityItem* ptr) { ptr->deleteLater(); }); + entity->setProperties(properties); + return entity; } RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) : ModelEntityWrapper(entityItemID), _dimensionsInitialized(dimensionsInitialized) { + + } RenderableModelEntityItem::~RenderableModelEntityItem() { } @@ -987,34 +991,22 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { } //get entity model anim props - bool isLooping = entity->getAnimationLoop(); - int firstFrame = entity->getAnimationFirstFrame(); - int lastFrame = entity->getAnimationLastFrame(); - bool isHolding = entity->getAnimationHold(); - int updatedFrameCount = lastFrame - firstFrame + 1; - - //get the updated frame from the ModelEntity - auto modelAnimProperties = entity->getAnimationProperties(); - - //_currentFrame = modelAnimProperties.getCurrentFrame(); + int updatedFrameCount = entity->getAnimationLastFrame() - entity->getAnimationFirstFrame() + 1; + - //tempbool = modelAnimProperties.getRunning(); - //qCDebug(entitiesrenderer) << "is playing is: " << tempbool; - - qCDebug(entitiesrenderer) << "the client frame count is the following " << _currentFrame; - - if ((firstFrame >= 0) && (firstFrame < lastFrame) && (lastFrame <= frameCount)) { - //length of animation in now determined by first and last frame - updatedFrameCount = (lastFrame - firstFrame + 1); + if ((entity->getAnimationFirstFrame() < 0) && (entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())){// && (lastFrame <= frameCount)) { + //we don't increment currentframe if the first frame is < zero or > than last frame. + //return; } + if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; } - + auto now = usecTimestampNow(); //find out how long it has been since this animation started. @@ -1022,46 +1014,38 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { auto interval = now - _lastAnimated; _lastAnimated = now; - float oldCurrentFrame = _currentFrame; - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); + //here we implement the looping animation property //if we have played through the animation once then we hold on the last frame - - if( isLooping || (_currentFrame < _renderAnimationProperties.getLastFrame() ) ){ - //else advance the current frame. - //if hold or not playing don't advance the current frame. - //also if the animFrame is outside of first or last frame then don't advance the motion. - if (!isHolding && entity->getAnimationIsPlaying() && !( _renderAnimationProperties.getCurrentFrame() > _renderAnimationProperties.getLastFrame() ) && !( _renderAnimationProperties.getCurrentFrame() < _renderAnimationProperties.getFirstFrame() ) ) { - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * _renderAnimationProperties.getFPS()); - while ((_currentFrame - _renderAnimationProperties.getFirstFrame()) > updatedFrameCount) { - _currentFrame -= updatedFrameCount; + if (!(entity->getAnimationHold()) && entity->getAnimationIsPlaying()) { + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * entity->getAnimationFPS()); + if (_currentFrame > entity->getAnimationLastFrame()) { + if (entity->getAnimationLoop()) { + while ((_currentFrame - entity->getAnimationFirstFrame()) > (updatedFrameCount - 1)) { + _currentFrame -= (updatedFrameCount - 1); + } + }else{ + _currentFrame = entity->getAnimationLastFrame(); + } + }else if (_currentFrame < entity->getAnimationFirstFrame()) { + if (entity->getAnimationFirstFrame() < 0) { + _currentFrame = 0; + }else { + _currentFrame = entity->getAnimationFirstFrame(); } } - else { - //use old currentFrame - _currentFrame = oldCurrentFrame; - } - }else { - //make current frame the endanim frame - _currentFrame = _renderAnimationProperties.getLastFrame(); } - //save the last place that we rendered ourselves. - //entity->setAnimationCurrentFrame(_currentFrame); - - { + qCDebug(entitiesrenderer) << "_currentFrame " << _currentFrame; + + + { //where are we in the currently defined animation segment? - // int animationCurrentFrame = (int)(glm::floor(_currentFrame - firstFrame)) % updatedFrameCount; - //this gives us the absolute frame value to use by adding the first frame value. - // animationCurrentFrame += firstFrame; int animationCurrentFrame = (int)(glm::floor(_currentFrame)); - - - - - + //in the case where the last frame is greater than the framecount then clamp + //it to the end of the animation until it loops around. + if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { animationCurrentFrame = 0; } @@ -1382,23 +1366,65 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // make a copy of the animation properites auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { - qCDebug(entitiesrenderer) << "this is where the change is currently handled in the rendering code"; - qCDebug(entitiesrenderer) << "getting the currently playing frame from the modelentityitem update" << newAnimationProperties.getCurrentFrame(); withWriteLock([&] { - if ( (newAnimationProperties.getCurrentFrame() != _renderAnimationProperties.getCurrentFrame()) || (newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { - if (!(newAnimationProperties.getCurrentFrame() > newAnimationProperties.getLastFrame()) && !(newAnimationProperties.getCurrentFrame() < newAnimationProperties.getFirstFrame())) { + if ((newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { + if (_currentFrame < 0) { + qCDebug(entitiesrenderer) << "point A before assign" << _currentFrame; _currentFrame = newAnimationProperties.getCurrentFrame();// +((float)newAnimationProperties.getCurrentlyPlayingFrame() / (float)USECS_PER_SECOND)*(newAnimationProperties.getFPS()); - _endAnim = _currentFrame + ( newAnimationProperties.getLastFrame() - newAnimationProperties.getFirstFrame() ); - _lastAnimated = 0; + qCDebug(entitiesrenderer) << "point A after assign" << _currentFrame; + qCDebug(entitiesrenderer) << "current " <getAnimationProperties(); + } else { + //if first frame is less than zero then don't do anything. + if (!(entity->getAnimationFirstFrame() < 0)) { + // if the current frame is less than zero, this is from the initialization. + if (_currentFrame < 0) { + qCDebug(entitiesrenderer) << "point D property current frame " << entity->getName() << newAnimationProperties.getCurrentFrame(); + if ((newAnimationProperties.getCurrentFrame() < newAnimationProperties.getLastFrame()) && (newAnimationProperties.getCurrentFrame() > newAnimationProperties.getFirstFrame())) { + + _currentFrame = newAnimationProperties.getCurrentFrame(); + qCDebug(entitiesrenderer) << "point D.1 " << _currentFrame; + qCDebug(entitiesrenderer) << "last animated " << _lastAnimated; + _lastAnimated = usecTimestampNow(); + } + else { + _currentFrame = newAnimationProperties.getFirstFrame(); + qCDebug(entitiesrenderer) << "point D.2 " << _currentFrame; + _lastAnimated = usecTimestampNow(); + qCDebug(entitiesrenderer) << entity->getName() << "last animated " << _lastAnimated; + } + } + } + } } //angus @@ -1410,9 +1436,12 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (!jointsMapped()) { mapJoints(entity, model->getJointNames()); } - animate(entity); + if (!(entity->getAnimationFirstFrame() < 0) && !(entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())) { + animate(entity); + } emit requestRenderUpdate(); } + } void ModelEntityRenderer::flagForCollisionGeometryUpdate() { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index fdb0cf5d2c..7f3ee47534 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -133,7 +133,10 @@ class ModelEntityRenderer : public TypedEntityRenderergetAnimationProperties(); if (_previousAnimationProperties != currentAnimationProperties) { - qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code"; + //qCDebug(entities) << "properties changed in modelentity code" << _currentFrame; withWriteLock([&] { - _previousAnimationProperties = currentAnimationProperties; + if ( (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { - // if (!(currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getLastFrame()) && !(currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getFirstFrame())) { - // _currentlyPlayingFrame = currentAnimationProperties.getCurrentFrame(); - //_endAnim = _currentlyPlayingFrame + ( currentAnimationProperties.getLastFrame() - currentAnimationProperties.getFirstFrame() ); - //_lastAnimated = 0; - // } - qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code, current frame is: \n\n" << currentAnimationProperties.getCurrentFrame(); + _lastAnimated = usecTimestampNow(); + _currentFrame = currentAnimationProperties.getFirstFrame(); + qCDebug(entities) << "point 2 " << _currentFrame; setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); - } - else { - //else if ( _previousAnimationProperties.getLoop() && !currentAnimationProperties.getLoop()) { - // int currentframe_mod_length = (int)(_currentlyPlayingFrame - (int)(glm::floor(currentAnimationProperties.getCurrentFrame()))) % ((int)(glm::floor(currentAnimationProperties.getLastFrame())) - (int)(glm::floor(currentAnimationProperties.getFirstFrame())) + 1); - //_endAnim = _currentlyPlayingFrame + ((int)(currentAnimationProperties.getLastFrame()) - (int)(currentAnimationProperties.getFirstFrame())) - (float)currentframe_mod_length; - //} - setAnimationCurrentFrame(currentAnimationProperties.getCurrentFrame()); + }else if (currentAnimationProperties.getHold() && !_previousAnimationProperties.getHold()) { + //_lastAnimated = 0; + //_currentFrame = currentAnimationProperties.getCurrentFrame(); + qCDebug(entities) << "hold is pressed" << _currentFrame; + }else if (!currentAnimationProperties.getHold() && _previousAnimationProperties.getHold()) { + //_lastAnimated = 0; + //_currentFrame = currentAnimationProperties.getCurrentFrame(); + qCDebug(entities) << "hold is unpressed" << _currentFrame; + }else if (!currentAnimationProperties.getLoop() && _previousAnimationProperties.getLoop()) { + //_lastAnimated = 0; + qCDebug(entities) << "loop is unpressed" << _currentFrame; + }else if (currentAnimationProperties.getLoop() && !_previousAnimationProperties.getLoop()) { + //_lastAnimated = 0; + qCDebug(entities) << "loop is pressed" << _currentFrame; + }else if(currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()){ + _currentFrame = currentAnimationProperties.getCurrentFrame(); + // if (_currentFrame < currentAnimationProperties.getFirstFrame()) { + // _currentFrame = currentAnimationProperties.getFirstFrame(); + // } + // current frame greater than lastframe is dealt with in updateframe. + //_lastAnimated = usecTimestampNow(); + qCDebug(entities) << "point 3 " << _currentFrame; } }); - - qCDebug(entities) << "this is where the _currentFrame change is handled in the ModelEntityItem.cpp code, current frame is: " << currentAnimationProperties.getCurrentFrame(); + _previousAnimationProperties = this->getAnimationProperties(); + //qCDebug(entities) << "point 4 " << _currentFrame; + } + else { + + //if the first frame is less than zero that is an error, so don't do anything. + if (!(getAnimationFirstFrame() < 0)) { + //if the current frame is less than zero then we are restarting the server. + if (_currentFrame < 0) { + qCDebug(entities) << "point 3.5 " << _currentFrame; + //_previousAnimationProperties = currentAnimationProperties; + if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { + _currentFrame = currentAnimationProperties.getCurrentFrame(); + } + else { + _currentFrame = currentAnimationProperties.getFirstFrame(); + setAnimationCurrentFrame(_currentFrame); + _lastAnimated = 0; + } + } + } } //_previousAnimationProperties = currentAnimationProperties; - updateFrameCount(); - + if (isAnimatingSomething()) { + if (!(getAnimationFirstFrame() < 0) && !(getAnimationFirstFrame() > getAnimationLastFrame()) ) { + updateFrameCount(); + } + } } } @@ -252,9 +286,6 @@ void ModelEntityItem::updateFrameCount() { auto interval = now - _lastAnimated; _lastAnimated = now; - - - //here we implement the looping animation property //get entity anim props @@ -263,28 +294,37 @@ void ModelEntityItem::updateFrameCount() { int lastFrame = getAnimationLastFrame(); bool isHolding = getAnimationHold(); int updatedFrameCount = lastFrame - firstFrame + 1; - - if (isLooping || (_currentFrame < _previousAnimationProperties.getLastFrame())) { - //else advance the current frame. - //if hold or not playing don't advance the current frame. - //also if the animFrame is outside of first or last frame then don't advance the motion. - if (!isHolding && getAnimationIsPlaying() && !(_previousAnimationProperties.getCurrentFrame() > _previousAnimationProperties.getLastFrame()) && !(_previousAnimationProperties.getCurrentFrame() < _previousAnimationProperties.getFirstFrame())) { - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * _previousAnimationProperties.getFPS()); - while ((_currentFrame - _previousAnimationProperties.getFirstFrame()) > updatedFrameCount) { - _currentFrame -= updatedFrameCount; - } - qCDebug(entities) << "the frame is now 1 " << _currentFrame; - // setAnimationCurrentlyPlayingFrame(_currentlyPlayingFrame); - setAnimationCurrentFrame(_currentFrame); - } - - } else { - _currentFrame = getAnimationLastFrame(); - setAnimationCurrentFrame(_currentFrame); - qCDebug(entities) << "the frame is now 2 " << _currentFrame; - } + + + + //qCDebug(entities) << "point 5 " << _currentFrame; + + if (!isHolding && getAnimationIsPlaying()) { + float deltaTime = (float)interval / (float)USECS_PER_SECOND; + _currentFrame += (deltaTime * getAnimationFPS()); + if (_currentFrame > getAnimationLastFrame()) { + if (isLooping) { + while ((_currentFrame - getAnimationFirstFrame()) > (updatedFrameCount - 1)) { + _currentFrame -= (updatedFrameCount - 1); + } + } + else { + _currentFrame = getAnimationLastFrame(); + } + } + else if (_currentFrame < getAnimationFirstFrame()) { + if (getAnimationFirstFrame() < 0) { + _currentFrame = 0; + } + else { + _currentFrame = getAnimationFirstFrame(); + } + } + setAnimationCurrentFrame(_currentFrame); + } + + //qCDebug(entities) << "_currentFrame is " << _currentFrame; } //angus @@ -706,6 +746,13 @@ float ModelEntityItem::getAnimationCurrentFrame() const { }); } +float ModelEntityItem::getAnimationFPS() const { + return resultWithReadLock([&] { + return _animationProperties.getFPS(); + }); +} + + //angus change bool ModelEntityItem::isAnimatingSomething() const { return resultWithReadLock([&] { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 973f49aec4..3dd30761ec 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -108,6 +108,7 @@ public: bool getAnimationIsPlaying() const; float getAnimationCurrentFrame() const; + float getAnimationFPS() const; bool isAnimatingSomething() const; quint64 getCurrentlyPlayingFrame() const; @@ -178,7 +179,7 @@ private: AnimationPropertyGroup _previousAnimationProperties; bool _propTestFlag{ true }; bool _propTestFlag2{ true }; - float _currentFrame{ 0 }; + float _currentFrame{ -1 }; //angus }; From 101e67498ad643f4fedb053f589e6075e57c7991 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 28 Nov 2017 14:11:56 -0800 Subject: [PATCH 15/48] cleaned up the code to remove _currentFrame updating in RenderModelEntityItem also removed the unnessary currently playing frame property --- .../src/EntityTreeRenderer.cpp | 5 +- .../src/RenderableModelEntityItem.cpp | 123 +----------------- .../src/RenderableModelEntityItem.h | 6 +- .../entities/src/AnimationPropertyGroup.cpp | 24 ---- .../entities/src/AnimationPropertyGroup.h | 1 - .../entities/src/EntityItemProperties.cpp | 1 - libraries/entities/src/EntityPropertyFlags.h | 2 - libraries/entities/src/ModelEntityItem.cpp | 82 ++++-------- libraries/entities/src/ModelEntityItem.h | 10 +- 9 files changed, 35 insertions(+), 219 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e3bbfca6cd..5dc1308ae3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -402,8 +402,9 @@ void EntityTreeRenderer::update(bool simulate) { PerformanceTimer perfTimer("ETRupdate"); if (_tree && !_shuttingDown) { EntityTreePointer tree = std::static_pointer_cast(_tree); - //angus - //tree->update(simulate); + + //here we update _currentFrame and _lastAnimated and sync with the server properties. + tree->update(simulate); // Update the rendereable entities as needed { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index fa24a171f1..5170596741 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -990,59 +990,10 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } - //get entity model anim props - - int updatedFrameCount = entity->getAnimationLastFrame() - entity->getAnimationFirstFrame() + 1; - - - if ((entity->getAnimationFirstFrame() < 0) && (entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())){// && (lastFrame <= frameCount)) { - //we don't increment currentframe if the first frame is < zero or > than last frame. - //return; - } - - - - if (!_lastAnimated) { - _lastAnimated = usecTimestampNow(); - return; - } - - auto now = usecTimestampNow(); - - //find out how long it has been since this animation started. - - auto interval = now - _lastAnimated; - _lastAnimated = now; - - - - //here we implement the looping animation property - //if we have played through the animation once then we hold on the last frame - if (!(entity->getAnimationHold()) && entity->getAnimationIsPlaying()) { - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _currentFrame += (deltaTime * entity->getAnimationFPS()); - if (_currentFrame > entity->getAnimationLastFrame()) { - if (entity->getAnimationLoop()) { - while ((_currentFrame - entity->getAnimationFirstFrame()) > (updatedFrameCount - 1)) { - _currentFrame -= (updatedFrameCount - 1); - } - }else{ - _currentFrame = entity->getAnimationLastFrame(); - } - }else if (_currentFrame < entity->getAnimationFirstFrame()) { - if (entity->getAnimationFirstFrame() < 0) { - _currentFrame = 0; - }else { - _currentFrame = entity->getAnimationFirstFrame(); - } - } - } - qCDebug(entitiesrenderer) << "_currentFrame " << _currentFrame; - - + //the code to find the current frame is now in modelEntityItem.cpp and we access it below -Angus { //where are we in the currently defined animation segment? - int animationCurrentFrame = (int)(glm::floor(_currentFrame)); + int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); //in the case where the last frame is greater than the framecount then clamp //it to the end of the animation until it loops around. @@ -1361,74 +1312,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->updateRenderItems(); } - { - DETAILED_PROFILE_RANGE(simulation_physics, "CheckAnimation"); - // make a copy of the animation properites - auto newAnimationProperties = entity->getAnimationProperties(); - if (newAnimationProperties != _renderAnimationProperties) { - withWriteLock([&] { - if ((newAnimationProperties.getFirstFrame() != _renderAnimationProperties.getFirstFrame()) || (newAnimationProperties.getLastFrame() != _renderAnimationProperties.getLastFrame()) || (newAnimationProperties.getRunning() && !_renderAnimationProperties.getRunning())) { - if (_currentFrame < 0) { - qCDebug(entitiesrenderer) << "point A before assign" << _currentFrame; - _currentFrame = newAnimationProperties.getCurrentFrame();// +((float)newAnimationProperties.getCurrentlyPlayingFrame() / (float)USECS_PER_SECOND)*(newAnimationProperties.getFPS()); - qCDebug(entitiesrenderer) << "point A after assign" << _currentFrame; - qCDebug(entitiesrenderer) << "current " <getAnimationProperties(); - } else { - //if first frame is less than zero then don't do anything. - if (!(entity->getAnimationFirstFrame() < 0)) { - // if the current frame is less than zero, this is from the initialization. - if (_currentFrame < 0) { - qCDebug(entitiesrenderer) << "point D property current frame " << entity->getName() << newAnimationProperties.getCurrentFrame(); - if ((newAnimationProperties.getCurrentFrame() < newAnimationProperties.getLastFrame()) && (newAnimationProperties.getCurrentFrame() > newAnimationProperties.getFirstFrame())) { - - _currentFrame = newAnimationProperties.getCurrentFrame(); - qCDebug(entitiesrenderer) << "point D.1 " << _currentFrame; - qCDebug(entitiesrenderer) << "last animated " << _lastAnimated; - _lastAnimated = usecTimestampNow(); - } - else { - _currentFrame = newAnimationProperties.getFirstFrame(); - qCDebug(entitiesrenderer) << "point D.2 " << _currentFrame; - _lastAnimated = usecTimestampNow(); - qCDebug(entitiesrenderer) << entity->getName() << "last animated " << _lastAnimated; - } - } - } - - } - } - //angus - + //The code to deal with the change of properties is now in ModelEntityItem.cpp + //That is where _currentFrame and _lastAnimated are updated. if (_animating) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 7f3ee47534..1ca72ce57d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -133,10 +133,7 @@ class ModelEntityRenderer : public TypedEntityRenderer& out) { if (allowTranslationChanged()) { out << "animation-allowTranslation"; } - if (currentlyPlayingFrameChanged()) { - out << "animation-currentlyPlayingFrame"; - } } @@ -209,8 +196,6 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold()); - //angus - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, getCurrentlyPlayingFrame()); return true; } @@ -232,7 +217,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, quint64, setCurrentlyPlayingFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FPS, FPS); @@ -243,7 +227,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation); - DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, CurrentlyPlayingFrame); processedBytes += bytesRead; @@ -276,7 +259,6 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_ALLOW_TRANSLATION, allowTranslation); - CHECK_PROPERTY_CHANGE(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, currentlyPlayingFrame); return changedProperties; } @@ -291,7 +273,6 @@ void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) con COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, getFirstFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, getLastFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, getHold); - COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentlyPlayingFrame, getCurrentlyPlayingFrame); } bool AnimationPropertyGroup::setProperties(const EntityItemProperties& properties) { @@ -306,7 +287,6 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, setFirstFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, setLastFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, setHold); - SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentlyPlayingFrame, currentlyPlayingFrame, setCurrentlyPlayingFrame); return somethingChanged; } @@ -322,8 +302,6 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP requestedProperties += PROP_ANIMATION_LAST_FRAME; requestedProperties += PROP_ANIMATION_HOLD; requestedProperties += PROP_ANIMATION_ALLOW_TRANSLATION; - //angus - requestedProperties += PROP_ANIMATION_CURRENTLY_PLAYING_FRAME; return requestedProperties; } @@ -347,7 +325,6 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, getCurrentlyPlayingFrame()); } int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -367,6 +344,5 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, quint64, setCurrentlyPlayingFrame); return bytesRead; } diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index 1a3da52684..54d4ced92f 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -86,7 +86,6 @@ public: DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold DEFINE_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation, allowTranslation, bool, true); - DEFINE_PROPERTY(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, CurrentlyPlayingFrame, currentlyPlayingFrame, quint64, 0); protected: friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 77fa1231f1..108fc14e30 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1148,7 +1148,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, Animation, animation, CurrentlyPlayingFrame, currentlyPlayingFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 3b1f4d60d0..35d40b669a 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -40,8 +40,6 @@ enum EntityPropertyList { PROP_ANIMATION_FRAME_INDEX, PROP_ANIMATION_PLAYING, PROP_ANIMATION_ALLOW_TRANSLATION, - //angus - PROP_ANIMATION_CURRENTLY_PLAYING_FRAME, // these properties are supported by the EntityItem base class PROP_REGISTRATION_POINT, diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 23b352fc19..4facd1f253 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -33,6 +33,9 @@ EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const E ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { + _lastAnimated = usecTimestampNow(); + qCDebug(entities) << "init last animated " << _lastAnimated; + //set the last animated when interface (re)starts _type = EntityTypes::Model; _lastKnownCurrentFrame = -1; _color[0] = _color[1] = _color[2] = 0; @@ -186,52 +189,45 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit } -//angus +//added update for property fix void ModelEntityItem::update(const quint64& now) { - //put something here - //qCDebug(entities) << "model entity item update" << getName() << " " << getEntityItemID(); { auto currentAnimationProperties = this->getAnimationProperties(); if (_previousAnimationProperties != currentAnimationProperties) { - //qCDebug(entities) << "properties changed in modelentity code" << _currentFrame; - withWriteLock([&] { - + + withWriteLock([&] { if ( (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { - _lastAnimated = usecTimestampNow(); - _currentFrame = currentAnimationProperties.getFirstFrame(); - qCDebug(entities) << "point 2 " << _currentFrame; - setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); + if (_currentFrame < 0) { + _currentFrame = currentAnimationProperties.getCurrentFrame(); + setAnimationCurrentFrame(_currentFrame); + qCDebug(entities) << "restart code hit " << _currentFrame; + } + else { + _lastAnimated = usecTimestampNow(); + qCDebug(entities) << "last animated 1" << _lastAnimated; + _currentFrame = currentAnimationProperties.getFirstFrame(); + qCDebug(entities) << "point 2 " << _currentFrame; + setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); + } }else if (currentAnimationProperties.getHold() && !_previousAnimationProperties.getHold()) { - //_lastAnimated = 0; - //_currentFrame = currentAnimationProperties.getCurrentFrame(); qCDebug(entities) << "hold is pressed" << _currentFrame; }else if (!currentAnimationProperties.getHold() && _previousAnimationProperties.getHold()) { - //_lastAnimated = 0; - //_currentFrame = currentAnimationProperties.getCurrentFrame(); qCDebug(entities) << "hold is unpressed" << _currentFrame; }else if (!currentAnimationProperties.getLoop() && _previousAnimationProperties.getLoop()) { - //_lastAnimated = 0; qCDebug(entities) << "loop is unpressed" << _currentFrame; }else if (currentAnimationProperties.getLoop() && !_previousAnimationProperties.getLoop()) { - //_lastAnimated = 0; qCDebug(entities) << "loop is pressed" << _currentFrame; }else if(currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()){ _currentFrame = currentAnimationProperties.getCurrentFrame(); - // if (_currentFrame < currentAnimationProperties.getFirstFrame()) { - // _currentFrame = currentAnimationProperties.getFirstFrame(); - // } - // current frame greater than lastframe is dealt with in updateframe. - //_lastAnimated = usecTimestampNow(); qCDebug(entities) << "point 3 " << _currentFrame; } }); _previousAnimationProperties = this->getAnimationProperties(); - //qCDebug(entities) << "point 4 " << _currentFrame; } else { @@ -243,11 +239,13 @@ void ModelEntityItem::update(const quint64& now) { //_previousAnimationProperties = currentAnimationProperties; if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { _currentFrame = currentAnimationProperties.getCurrentFrame(); + qCDebug(entities) << "current frame less than zero " << _currentFrame; } else { _currentFrame = currentAnimationProperties.getFirstFrame(); setAnimationCurrentFrame(_currentFrame); - _lastAnimated = 0; + _lastAnimated = usecTimestampNow(); + qCDebug(entities) << "last animated 2" << _lastAnimated; } } } @@ -264,9 +262,6 @@ void ModelEntityItem::update(const quint64& now) { bool ModelEntityItem::needsToCallUpdate() const { - - //put something here - //qCDebug(entities) << "needs to call update"; return true; } @@ -282,29 +277,17 @@ void ModelEntityItem::updateFrameCount() { auto now = usecTimestampNow(); //this is now getting the time since the server started the animation. - //auto interval = now - _currentlyPlayingFrame; auto interval = now - _lastAnimated; _lastAnimated = now; - //here we implement the looping animation property - //get entity anim props - bool isLooping = getAnimationLoop(); - int firstFrame = getAnimationFirstFrame(); - int lastFrame = getAnimationLastFrame(); - bool isHolding = getAnimationHold(); - int updatedFrameCount = lastFrame - firstFrame + 1; + int updatedFrameCount = getAnimationLastFrame() - getAnimationFirstFrame() + 1; - - - - //qCDebug(entities) << "point 5 " << _currentFrame; - - if (!isHolding && getAnimationIsPlaying()) { + if (!getAnimationHold() && getAnimationIsPlaying()) { float deltaTime = (float)interval / (float)USECS_PER_SECOND; _currentFrame += (deltaTime * getAnimationFPS()); if (_currentFrame > getAnimationLastFrame()) { - if (isLooping) { + if (getAnimationLoop()) { while ((_currentFrame - getAnimationFirstFrame()) > (updatedFrameCount - 1)) { _currentFrame -= (updatedFrameCount - 1); } @@ -327,7 +310,7 @@ void ModelEntityItem::updateFrameCount() { //qCDebug(entities) << "_currentFrame is " << _currentFrame; } -//angus + @@ -678,13 +661,6 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) { }); } -void ModelEntityItem::setAnimationCurrentlyPlayingFrame(quint64 value) { - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; - withWriteLock([&] { - _animationProperties.setCurrentlyPlayingFrame(value); - }); -} - void ModelEntityItem::setAnimationLoop(bool loop) { withWriteLock([&] { _animationProperties.setLoop(loop); @@ -753,7 +729,6 @@ float ModelEntityItem::getAnimationFPS() const { } -//angus change bool ModelEntityItem::isAnimatingSomething() const { return resultWithReadLock([&] { return !_animationProperties.getURL().isEmpty() && @@ -762,15 +737,8 @@ bool ModelEntityItem::isAnimatingSomething() const { }); } -quint64 ModelEntityItem::getCurrentlyPlayingFrame() const { - return resultWithReadLock([&] { - return _currentlyPlayingFrame; - }); -} - int ModelEntityItem::getLastKnownCurrentFrame() const { return resultWithReadLock([&] { return _lastKnownCurrentFrame; }); } -//angus change \ No newline at end of file diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 3dd30761ec..4aa52d4cef 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -47,11 +47,11 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - //angus + //update and needstocallupdate added back for the entity property fix virtual void update(const quint64& now) override; virtual bool needsToCallUpdate() const override; void updateFrameCount(); - //angus + virtual void debugDump() const override; void setShapeType(ShapeType type) override; @@ -87,7 +87,6 @@ public: void setAnimationURL(const QString& url); void setAnimationCurrentFrame(float value); - void setAnimationCurrentlyPlayingFrame(quint64 value); void setAnimationIsPlaying(bool value); void setAnimationFPS(float value); @@ -111,7 +110,6 @@ public: float getAnimationFPS() const; bool isAnimatingSomething() const; - quint64 getCurrentlyPlayingFrame() const; int getLastKnownCurrentFrame() const; static const QString DEFAULT_TEXTURES; @@ -173,12 +171,8 @@ protected: private: //angus - quint64 _currentlyPlayingFrame{ 0 }; - float _endAnim{ 0 }; uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; - bool _propTestFlag{ true }; - bool _propTestFlag2{ true }; float _currentFrame{ -1 }; //angus }; From 778d98f56b8b388b012ad08f72ccfb63a3295ca7 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 28 Nov 2017 18:42:03 -0800 Subject: [PATCH 16/48] made some changes to fix coding standard problems in the code, also added the update for the EntityItem base class to the update function --- .../src/EntityTreeRenderer.cpp | 4 +- .../src/RenderableModelEntityItem.cpp | 16 ++--- .../src/RenderableModelEntityItem.h | 4 +- libraries/entities/src/ModelEntityItem.cpp | 62 ++++++++----------- libraries/entities/src/ModelEntityItem.h | 4 +- 5 files changed, 37 insertions(+), 53 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5dc1308ae3..7103e72f54 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -403,7 +403,7 @@ void EntityTreeRenderer::update(bool simulate) { if (_tree && !_shuttingDown) { EntityTreePointer tree = std::static_pointer_cast(_tree); - //here we update _currentFrame and _lastAnimated and sync with the server properties. + // here we update _currentFrame and _lastAnimated and sync with the server properties. tree->update(simulate); // Update the rendereable entities as needed @@ -738,7 +738,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { PickRay ray = _viewState->computePickRay(event->x(), event->y()); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); if (rayPickResult.intersects && rayPickResult.entity) { - //qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; + // qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); PointerEvent pointerEvent(PointerEvent::Release, PointerManager::MOUSE_POINTER_ID, diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5170596741..fa75702b89 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -465,7 +465,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { shapeInfo.setParams(type, dimensions, getCompoundShapeURL()); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { // TODO: assert we never fall in here when model not fully loaded - //assert(_model && _model->isLoaded()); + // assert(_model && _model->isLoaded()); updateModelBounds(); model->updateGeometry(); @@ -992,10 +992,10 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { //the code to find the current frame is now in modelEntityItem.cpp and we access it below -Angus { - //where are we in the currently defined animation segment? + // where are we in the currently defined animation segment? int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); - //in the case where the last frame is greater than the framecount then clamp - //it to the end of the animation until it loops around. + // in the case where the last frame is greater than the framecount then clamp + // it to the end of the animation until it loops around. if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { animationCurrentFrame = 0; @@ -1032,10 +1032,10 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { glm::mat4 translationMat; if (allowTranslation) { - if(index < translations.size()){ + if (index < translations.size()) { translationMat = glm::translate(translations[index]); } - } else if (index < animationJointNames.size()){ + } else if (index < animationJointNames.size()) { QString jointName = fbxJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation if (originalFbxIndices.contains(jointName)) { @@ -1312,8 +1312,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->updateRenderItems(); } - //The code to deal with the change of properties is now in ModelEntityItem.cpp - //That is where _currentFrame and _lastAnimated are updated. + // The code to deal with the change of properties is now in ModelEntityItem.cpp + // That is where _currentFrame and _lastAnimated are updated. if (_animating) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 1ca72ce57d..44ee82713d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -33,7 +33,7 @@ namespace render { namespace entities { class ModelEntityRenderer; } } -//#define MODEL_ENTITY_USE_FADE_EFFECT +// #define MODEL_ENTITY_USE_FADE_EFFECT class ModelEntityWrapper : public ModelEntityItem { using Parent = ModelEntityItem; friend class render::entities::ModelEntityRenderer; @@ -185,8 +185,6 @@ private: bool _animating { false }; uint64_t _lastAnimated { 0 }; float _currentFrame { -1 }; - float _endAnim{ 0 }; - bool tempbool{ false }; }; } } // namespace diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 4facd1f253..594353ee68 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -34,8 +34,7 @@ EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const E ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { _lastAnimated = usecTimestampNow(); - qCDebug(entities) << "init last animated " << _lastAnimated; - //set the last animated when interface (re)starts + // set the last animated when interface (re)starts _type = EntityTypes::Model; _lastKnownCurrentFrame = -1; _color[0] = _color[1] = _color[2] = 0; @@ -190,79 +189,71 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit -//added update for property fix +// added update for property fix void ModelEntityItem::update(const quint64& now) { - { auto currentAnimationProperties = this->getAnimationProperties(); if (_previousAnimationProperties != currentAnimationProperties) { - withWriteLock([&] { - if ( (currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { + if ((currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { if (_currentFrame < 0) { _currentFrame = currentAnimationProperties.getCurrentFrame(); setAnimationCurrentFrame(_currentFrame); - qCDebug(entities) << "restart code hit " << _currentFrame; - } - else { + qCDebug(entities) << "restart code hit last animated is " << _lastAnimated << " now is " << now; + } else { _lastAnimated = usecTimestampNow(); qCDebug(entities) << "last animated 1" << _lastAnimated; _currentFrame = currentAnimationProperties.getFirstFrame(); qCDebug(entities) << "point 2 " << _currentFrame; setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); } - }else if (currentAnimationProperties.getHold() && !_previousAnimationProperties.getHold()) { + } else if (currentAnimationProperties.getHold() && !_previousAnimationProperties.getHold()) { qCDebug(entities) << "hold is pressed" << _currentFrame; - }else if (!currentAnimationProperties.getHold() && _previousAnimationProperties.getHold()) { + } else if (!currentAnimationProperties.getHold() && _previousAnimationProperties.getHold()) { qCDebug(entities) << "hold is unpressed" << _currentFrame; - }else if (!currentAnimationProperties.getLoop() && _previousAnimationProperties.getLoop()) { + } else if (!currentAnimationProperties.getLoop() && _previousAnimationProperties.getLoop()) { qCDebug(entities) << "loop is unpressed" << _currentFrame; - }else if (currentAnimationProperties.getLoop() && !_previousAnimationProperties.getLoop()) { + } else if (currentAnimationProperties.getLoop() && !_previousAnimationProperties.getLoop()) { qCDebug(entities) << "loop is pressed" << _currentFrame; - }else if(currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()){ + } else if (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) { _currentFrame = currentAnimationProperties.getCurrentFrame(); qCDebug(entities) << "point 3 " << _currentFrame; } }); _previousAnimationProperties = this->getAnimationProperties(); - } - else { + } else { - //if the first frame is less than zero that is an error, so don't do anything. + // if the first frame is less than zero that is an error, so don't do anything. if (!(getAnimationFirstFrame() < 0)) { - //if the current frame is less than zero then we are restarting the server. + // if the current frame is less than zero then we are restarting the server. if (_currentFrame < 0) { - qCDebug(entities) << "point 3.5 " << _currentFrame; - //_previousAnimationProperties = currentAnimationProperties; if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { _currentFrame = currentAnimationProperties.getCurrentFrame(); - qCDebug(entities) << "current frame less than zero " << _currentFrame; - } - else { + } else { _currentFrame = currentAnimationProperties.getFirstFrame(); setAnimationCurrentFrame(_currentFrame); _lastAnimated = usecTimestampNow(); - qCDebug(entities) << "last animated 2" << _lastAnimated; } } } } - //_previousAnimationProperties = currentAnimationProperties; + // _previousAnimationProperties = currentAnimationProperties; if (isAnimatingSomething()) { - if (!(getAnimationFirstFrame() < 0) && !(getAnimationFirstFrame() > getAnimationLastFrame()) ) { + if (!(getAnimationFirstFrame() < 0) && !(getAnimationFirstFrame() > getAnimationLastFrame())) { updateFrameCount(); } } } - + EntityItem::update(now); } bool ModelEntityItem::needsToCallUpdate() const { - return true; + //return isAnimatingSomething() || EntityItem::needsToCallUpdate(); + return true; } void ModelEntityItem::updateFrameCount() { @@ -276,7 +267,7 @@ void ModelEntityItem::updateFrameCount() { auto now = usecTimestampNow(); - //this is now getting the time since the server started the animation. + // this is now getting the time since the server started the animation. auto interval = now - _lastAnimated; _lastAnimated = now; @@ -291,23 +282,20 @@ void ModelEntityItem::updateFrameCount() { while ((_currentFrame - getAnimationFirstFrame()) > (updatedFrameCount - 1)) { _currentFrame -= (updatedFrameCount - 1); } - } - else { + } else { _currentFrame = getAnimationLastFrame(); } - } - else if (_currentFrame < getAnimationFirstFrame()) { + } else if (_currentFrame < getAnimationFirstFrame()) { if (getAnimationFirstFrame() < 0) { _currentFrame = 0; - } - else { + } else { _currentFrame = getAnimationFirstFrame(); } } setAnimationCurrentFrame(_currentFrame); } - //qCDebug(entities) << "_currentFrame is " << _currentFrame; + } @@ -709,7 +697,7 @@ float ModelEntityItem::getAnimationLastFrame() const { return _animationProperties.getLastFrame(); }); } -//angus change + bool ModelEntityItem::getAnimationIsPlaying() const { return resultWithReadLock([&] { return _animationProperties.getRunning(); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 4aa52d4cef..c0ca12c7f9 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -47,7 +47,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - //update and needstocallupdate added back for the entity property fix + // update() and needstocallupdate() added back for the entity property fix virtual void update(const quint64& now) override; virtual bool needsToCallUpdate() const override; void updateFrameCount(); @@ -170,11 +170,9 @@ protected: ShapeType _shapeType = SHAPE_TYPE_NONE; private: - //angus uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; float _currentFrame{ -1 }; - //angus }; #endif // hifi_ModelEntityItem_h From 233d693d76634c9d04f80be699b029e325496a48 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 29 Nov 2017 10:51:04 -0800 Subject: [PATCH 17/48] removed debug print statements and fixed negative FPS handling --- .../src/RenderableModelEntityItem.cpp | 9 +-- libraries/entities/src/ModelEntityItem.cpp | 56 +++++++++---------- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index fa75702b89..d5befbe572 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -981,7 +981,6 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } - QVector jointsData; const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy @@ -990,13 +989,12 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } - //the code to find the current frame is now in modelEntityItem.cpp and we access it below -Angus { - // where are we in the currently defined animation segment? + // the current frame is set on the server in update() in ModelEntityItem.cpp int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); + // in the case where the last frame is greater than the framecount then clamp // it to the end of the animation until it loops around. - if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { animationCurrentFrame = 0; } @@ -1314,8 +1312,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // The code to deal with the change of properties is now in ModelEntityItem.cpp // That is where _currentFrame and _lastAnimated are updated. - - if (_animating) { DETAILED_PROFILE_RANGE(simulation_physics, "Animate"); if (!jointsMapped()) { @@ -1326,7 +1322,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } emit requestRenderUpdate(); } - } void ModelEntityRenderer::flagForCollisionGeometryUpdate() { diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 594353ee68..260074da68 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -189,48 +189,47 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit -// added update for property fix +// added update function back for property fix void ModelEntityItem::update(const quint64& now) { { auto currentAnimationProperties = this->getAnimationProperties(); if (_previousAnimationProperties != currentAnimationProperties) { - withWriteLock([&] { - if ((currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { + withWriteLock([&] { + // if we hit start animation or change the first or last frame then restart the animation + if ((currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || + (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || + (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { + + // when we start interface and the property is are set then the current frame is initialized to -1 if (_currentFrame < 0) { + // don't reset _lastAnimated here because we need the timestamp from the ModelEntityItem constructor for when the properties were set _currentFrame = currentAnimationProperties.getCurrentFrame(); setAnimationCurrentFrame(_currentFrame); - qCDebug(entities) << "restart code hit last animated is " << _lastAnimated << " now is " << now; } else { _lastAnimated = usecTimestampNow(); - qCDebug(entities) << "last animated 1" << _lastAnimated; _currentFrame = currentAnimationProperties.getFirstFrame(); - qCDebug(entities) << "point 2 " << _currentFrame; setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); } - } else if (currentAnimationProperties.getHold() && !_previousAnimationProperties.getHold()) { - qCDebug(entities) << "hold is pressed" << _currentFrame; - } else if (!currentAnimationProperties.getHold() && _previousAnimationProperties.getHold()) { - qCDebug(entities) << "hold is unpressed" << _currentFrame; - } else if (!currentAnimationProperties.getLoop() && _previousAnimationProperties.getLoop()) { - qCDebug(entities) << "loop is unpressed" << _currentFrame; - } else if (currentAnimationProperties.getLoop() && !_previousAnimationProperties.getLoop()) { - qCDebug(entities) << "loop is pressed" << _currentFrame; } else if (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) { + // don't reset _lastAnimated here because the currentFrame was set with the previous setting of _lastAnimated _currentFrame = currentAnimationProperties.getCurrentFrame(); - qCDebug(entities) << "point 3 " << _currentFrame; + // qCDebug(entities) << "point 3 " << _currentFrame; } }); _previousAnimationProperties = this->getAnimationProperties(); + } else { - - // if the first frame is less than zero that is an error, so don't do anything. + // else the animation properties have not changed. + // if the first frame is less than zero don't do anything. if (!(getAnimationFirstFrame() < 0)) { - // if the current frame is less than zero then we are restarting the server. + + // if the current frame is less than zero then we have restarted the server. if (_currentFrame < 0) { - if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { + if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && + (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { _currentFrame = currentAnimationProperties.getCurrentFrame(); } else { _currentFrame = currentAnimationProperties.getFirstFrame(); @@ -240,38 +239,40 @@ void ModelEntityItem::update(const quint64& now) { } } } - // _previousAnimationProperties = currentAnimationProperties; + if (isAnimatingSomething()) { if (!(getAnimationFirstFrame() < 0) && !(getAnimationFirstFrame() > getAnimationLastFrame())) { updateFrameCount(); } } } + EntityItem::update(now); } bool ModelEntityItem::needsToCallUpdate() const { - //return isAnimatingSomething() || EntityItem::needsToCallUpdate(); return true; } void ModelEntityItem::updateFrameCount() { - if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; } - auto now = usecTimestampNow(); - // this is now getting the time since the server started the animation. + // update the interval since the last animation. auto interval = now - _lastAnimated; _lastAnimated = now; - + // if fps is negative then increment timestamp and return. + if (getAnimationFPS() < 0.0) { + return; + } + int updatedFrameCount = getAnimationLastFrame() - getAnimationFirstFrame() + 1; if (!getAnimationHold() && getAnimationIsPlaying()) { @@ -298,11 +299,6 @@ void ModelEntityItem::updateFrameCount() { } - - - - - void ModelEntityItem::debugDump() const { qCDebug(entities) << "ModelEntityItem id:" << getEntityItemID(); qCDebug(entities) << " edited ago:" << getEditedAgo(); From 9bc165d8b40e4853e237fdb5aabd625ab466231f Mon Sep 17 00:00:00 2001 From: Daniela Fontes Date: Thu, 30 Nov 2017 18:49:53 +0000 Subject: [PATCH 18/48] Changing to Smaller Avatar Resizes Tablet --- interface/src/avatar/MyAvatar.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index df2089223b..28ecb07d31 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -669,6 +669,12 @@ void MyAvatar::updateSensorToWorldMatrix() { glm::mat4 desiredMat = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), getWorldOrientation(), getWorldPosition()); _sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix); + bool hasSensorToWorldScaleChanged = false; + + if (abs(AvatarData::getSensorToWorldScale() - sensorToWorldScale) > 0.001f) { + hasSensorToWorldScaleChanged = true; + } + lateUpdatePalms(); if (_enableDebugDrawSensorToWorldMatrix) { @@ -677,9 +683,15 @@ void MyAvatar::updateSensorToWorldMatrix() { } _sensorToWorldMatrixCache.set(_sensorToWorldMatrix); - + updateJointFromController(controller::Action::LEFT_HAND, _controllerLeftHandMatrixCache); updateJointFromController(controller::Action::RIGHT_HAND, _controllerRightHandMatrixCache); + + if (hasSensorToWorldScaleChanged) { + emit sensorToWorldScaleChanged(sensorToWorldScale); + //qDebug() << "Debug: emit sensorToWorldScaleChanged " << sensorToWorldScale; + } + } // Update avatar head rotation with sensor data @@ -1404,6 +1416,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene()); _headBoneSet.clear(); emit skeletonChanged(); + } @@ -1439,6 +1452,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN UserActivityLogger::getInstance().changedModel("skeleton", urlString); } markIdentityDataChanged(); + } void MyAvatar::setAttachmentData(const QVector& attachmentData) { From 8b38c03a5624f3fab6981214964628e227021667 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 7 Dec 2017 17:40:58 -0800 Subject: [PATCH 19/48] Allow space characters in material library name --- libraries/fbx/src/OBJReader.cpp | 6 +++--- libraries/fbx/src/OBJReader.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index e0c2efd72e..315c6a86d2 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -56,7 +56,7 @@ float OBJTokenizer::getFloat() { return std::stof((nextToken() != OBJTokenizer::DATUM_TOKEN) ? nullptr : getDatum().data()); } -int OBJTokenizer::nextToken() { +int OBJTokenizer::nextToken(bool allowSpaceChar /*= false*/) { if (_pushedBackToken != NO_PUSHBACKED_TOKEN) { int token = _pushedBackToken; _pushedBackToken = NO_PUSHBACKED_TOKEN; @@ -93,7 +93,7 @@ int OBJTokenizer::nextToken() { _datum = ""; _datum.append(ch); while (_device->getChar(&ch)) { - if (QChar(ch).isSpace() || ch == '\"') { + if ((QChar(ch).isSpace() || ch == '\"') && (!allowSpaceChar || ch != ' ')) { ungetChar(ch); // read until we encounter a special character, then replace it break; } @@ -399,7 +399,7 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi currentMaterialName = QString("part-") + QString::number(_partCounter++); } } else if (token == "mtllib" && !_url.isEmpty()) { - if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { + if (tokenizer.nextToken(true) != OBJTokenizer::DATUM_TOKEN) { break; } QByteArray libraryName = tokenizer.getDatum(); diff --git a/libraries/fbx/src/OBJReader.h b/libraries/fbx/src/OBJReader.h index fb250833cf..45e3f79480 100644 --- a/libraries/fbx/src/OBJReader.h +++ b/libraries/fbx/src/OBJReader.h @@ -11,7 +11,7 @@ public: DATUM_TOKEN = 0x100, COMMENT_TOKEN = 0x101 }; - int nextToken(); + int nextToken(bool allowSpaceChar = false); const QByteArray& getDatum() const { return _datum; } bool isNextTokenFloat(); const QByteArray getLineAsDatum(); // some "filenames" have spaces in them From 46583a90be582da995a220124db9dbf96e8a5bd3 Mon Sep 17 00:00:00 2001 From: Daniela Fontes Date: Sat, 9 Dec 2017 00:14:36 +0000 Subject: [PATCH 20/48] Change abs to fabsf and other corrections requested. --- interface/src/avatar/MyAvatar.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 28ecb07d31..3475b0c940 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -81,6 +81,7 @@ const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amaz const float MyAvatar::ZOOM_MIN = 0.5f; const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_DEFAULT = 1.5f; +const float MIN_SCALE_CHANGED_DELTA = 0.001f; MyAvatar::MyAvatar(QThread* thread) : Avatar(thread), @@ -670,8 +671,7 @@ void MyAvatar::updateSensorToWorldMatrix() { _sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix); bool hasSensorToWorldScaleChanged = false; - - if (abs(AvatarData::getSensorToWorldScale() - sensorToWorldScale) > 0.001f) { + if (fabsf(getSensorToWorldScale() - sensorToWorldScale) > MIN_SCALE_CHANGED_DELTA) { hasSensorToWorldScaleChanged = true; } @@ -683,13 +683,11 @@ void MyAvatar::updateSensorToWorldMatrix() { } _sensorToWorldMatrixCache.set(_sensorToWorldMatrix); - updateJointFromController(controller::Action::LEFT_HAND, _controllerLeftHandMatrixCache); updateJointFromController(controller::Action::RIGHT_HAND, _controllerRightHandMatrixCache); if (hasSensorToWorldScaleChanged) { emit sensorToWorldScaleChanged(sensorToWorldScale); - //qDebug() << "Debug: emit sensorToWorldScaleChanged " << sensorToWorldScale; } } From 068d04c58da8842ad2272e4280635573fcee81e2 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 6 Dec 2017 16:49:27 -0800 Subject: [PATCH 21/48] abstraction of recursion through bullet perf stats --- libraries/physics/src/PhysicsEngine.cpp | 52 ++++++++++++++----------- libraries/physics/src/PhysicsEngine.h | 1 - 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index a64796308e..9ff6a59255 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -10,6 +10,7 @@ // #include +#include #include @@ -328,6 +329,33 @@ void PhysicsEngine::stepSimulation() { } } +using CProfileOperator = std::function; + +CProfileOperator harvestProfile = [](CProfileIterator* profileIterator, QString contextName) { + QString childContextName = contextName + QString("/") + QString(profileIterator->Get_Current_Name()); + uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * profileIterator->Get_Current_Total_Time()); + PerformanceTimer::addTimerRecord(childContextName, time); + }; + +void recurseOpOnPerformanceStats(CProfileOperator op, CProfileIterator* profileIterator, QString contextName) { + QString parentContextName = contextName + QString("/") + QString(profileIterator->Get_Current_Parent_Name()); + // get the stats for the children + int32_t numChildren = 0; + profileIterator->First(); + while (!profileIterator->Is_Done()) { + op(profileIterator, contextName); + profileIterator->Next(); + ++numChildren; + } + // recurse the children + for (int32_t i = 0; i < numChildren; ++i) { + profileIterator->Enter_Child(i); + recurseOpOnPerformanceStats(op, profileIterator, parentContextName); + } + // retreat back to parent + profileIterator->Enter_Parent(); +} + void PhysicsEngine::harvestPerformanceStats() { // unfortunately the full context names get too long for our stats presentation format //QString contextName = PerformanceTimer::getContextName(); // TODO: how to show full context name? @@ -340,7 +368,7 @@ void PhysicsEngine::harvestPerformanceStats() { for (int32_t childIndex = 0; !profileIterator->Is_Done(); ++childIndex) { if (QString(profileIterator->Get_Current_Name()) == "stepSimulation") { profileIterator->Enter_Child(childIndex); - recursivelyHarvestPerformanceStats(profileIterator, contextName); + recurseOpOnPerformanceStats(harvestProfile, profileIterator, contextName); break; } profileIterator->Next(); @@ -348,27 +376,6 @@ void PhysicsEngine::harvestPerformanceStats() { } } -void PhysicsEngine::recursivelyHarvestPerformanceStats(CProfileIterator* profileIterator, QString contextName) { - QString parentContextName = contextName + QString("/") + QString(profileIterator->Get_Current_Parent_Name()); - // get the stats for the children - int32_t numChildren = 0; - profileIterator->First(); - while (!profileIterator->Is_Done()) { - QString childContextName = parentContextName + QString("/") + QString(profileIterator->Get_Current_Name()); - uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * profileIterator->Get_Current_Total_Time()); - PerformanceTimer::addTimerRecord(childContextName, time); - profileIterator->Next(); - ++numChildren; - } - // recurse the children - for (int32_t i = 0; i < numChildren; ++i) { - profileIterator->Enter_Child(i); - recursivelyHarvestPerformanceStats(profileIterator, contextName); - } - // retreat back to parent - profileIterator->Enter_Parent(); -} - void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) { BT_PROFILE("ownershipInfection"); @@ -515,6 +522,7 @@ const VectorOfMotionStates& PhysicsEngine::getChangedMotionStates() { void PhysicsEngine::dumpStatsIfNecessary() { if (_dumpNextStats) { _dumpNextStats = false; + CProfileManager::Increment_Frame_Counter(); CProfileManager::dumpAll(); } } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 3063a4a89a..4e63e8ff3e 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -94,7 +94,6 @@ public: private: QList removeDynamicsForBody(btRigidBody* body); void addObjectToDynamicsWorld(ObjectMotionState* motionState); - void recursivelyHarvestPerformanceStats(CProfileIterator* profileIterator, QString contextName); /// \brief bump any objects that touch this one, then remove contact info void bumpAndPruneContacts(ObjectMotionState* motionState); From fcff9d7e369bb2b8e5c3f4233c9901d942d63465 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 7 Dec 2017 08:58:35 -0800 Subject: [PATCH 22/48] use class hierarchy instead of lambdas --- libraries/physics/src/PhysicsEngine.cpp | 33 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 9ff6a59255..e73b9035e6 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -329,28 +329,38 @@ void PhysicsEngine::stepSimulation() { } } -using CProfileOperator = std::function; - -CProfileOperator harvestProfile = [](CProfileIterator* profileIterator, QString contextName) { - QString childContextName = contextName + QString("/") + QString(profileIterator->Get_Current_Name()); - uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * profileIterator->Get_Current_Total_Time()); - PerformanceTimer::addTimerRecord(childContextName, time); +class CProfileOperator { +public: + CProfileOperator(QString context) : _context(context) { }; + virtual void process(CProfileIterator*) const = 0; +protected: + QString _context; +}; -void recurseOpOnPerformanceStats(CProfileOperator op, CProfileIterator* profileIterator, QString contextName) { - QString parentContextName = contextName + QString("/") + QString(profileIterator->Get_Current_Parent_Name()); +class PhysicsStatsHarvester : public CProfileOperator { +public: + PhysicsStatsHarvester() : CProfileOperator("...") {} + void process(CProfileIterator* itr) const override { + QString name = _context + QString("/") + QString(itr->Get_Current_Name()); + uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * itr->Get_Current_Total_Time()); + PerformanceTimer::addTimerRecord(name, time); + }; +}; + +void recurseOpOnPerformanceStats(const CProfileOperator& op, CProfileIterator* profileIterator) { // get the stats for the children int32_t numChildren = 0; profileIterator->First(); while (!profileIterator->Is_Done()) { - op(profileIterator, contextName); + op.process(profileIterator); profileIterator->Next(); ++numChildren; } // recurse the children for (int32_t i = 0; i < numChildren; ++i) { profileIterator->Enter_Child(i); - recurseOpOnPerformanceStats(op, profileIterator, parentContextName); + recurseOpOnPerformanceStats(op, profileIterator); } // retreat back to parent profileIterator->Enter_Parent(); @@ -368,7 +378,8 @@ void PhysicsEngine::harvestPerformanceStats() { for (int32_t childIndex = 0; !profileIterator->Is_Done(); ++childIndex) { if (QString(profileIterator->Get_Current_Name()) == "stepSimulation") { profileIterator->Enter_Child(childIndex); - recurseOpOnPerformanceStats(harvestProfile, profileIterator, contextName); + PhysicsStatsHarvester harvester; + harvester.process(profileIterator); break; } profileIterator->Next(); From 4540e9e483a2f4803a51854a8fdb070fe5774cc4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 7 Dec 2017 13:08:34 -0800 Subject: [PATCH 23/48] add ability to save simulation stats to file --- libraries/physics/src/PhysicsEngine.cpp | 116 +++++++++++++++++------- libraries/physics/src/PhysicsEngine.h | 1 + 2 files changed, 83 insertions(+), 34 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index e73b9035e6..2eec4a3950 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -10,8 +10,11 @@ // #include + #include +#include + #include #include "CharacterController.h" @@ -331,58 +334,103 @@ void PhysicsEngine::stepSimulation() { class CProfileOperator { public: - CProfileOperator(QString context) : _context(context) { - }; - virtual void process(CProfileIterator*) const = 0; -protected: - QString _context; + CProfileOperator() {} + void recurse(CProfileIterator* itr, QString context) { + // The context string will get too long if we accumulate it properly + //QString newContext = context + QString("/") + itr->Get_Current_Parent_Name(); + // so we use this four-character indentation + QString newContext = context + QString(".../"); + process(itr, newContext); + + // count the children + int32_t numChildren = 0; + itr->First(); + while (!itr->Is_Done()) { + itr->Next(); + ++numChildren; + } + + // recurse the children + if (numChildren > 0) { + // recurse the children + for (int32_t i = 0; i < numChildren; ++i) { + itr->Enter_Child(i); + recurse(itr, newContext); + } + } + // retreat back to parent + itr->Enter_Parent(); + } + virtual void process(CProfileIterator*, QString context) = 0; }; -class PhysicsStatsHarvester : public CProfileOperator { +class StatsHarvester : public CProfileOperator { public: - PhysicsStatsHarvester() : CProfileOperator("...") {} - void process(CProfileIterator* itr) const override { - QString name = _context + QString("/") + QString(itr->Get_Current_Name()); - uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * itr->Get_Current_Total_Time()); + StatsHarvester() {} + void process(CProfileIterator* itr, QString context) override { + QString name = context + itr->Get_Current_Parent_Name(); + uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * itr->Get_Current_Parent_Total_Time()); PerformanceTimer::addTimerRecord(name, time); }; }; -void recurseOpOnPerformanceStats(const CProfileOperator& op, CProfileIterator* profileIterator) { - // get the stats for the children - int32_t numChildren = 0; - profileIterator->First(); - while (!profileIterator->Is_Done()) { - op.process(profileIterator); - profileIterator->Next(); - ++numChildren; +class StatsWriter : public CProfileOperator { +public: + StatsWriter(QString filename) : _file(filename) { + _file.open(QFile::WriteOnly); + if (_file.error() != QFileDevice::NoError) { + qCDebug(physics) << "unable to open file " << _file.fileName() << " to save stepSimulation() stats"; + } } - // recurse the children - for (int32_t i = 0; i < numChildren; ++i) { - profileIterator->Enter_Child(i); - recurseOpOnPerformanceStats(op, profileIterator); + ~StatsWriter() { + _file.close(); } - // retreat back to parent - profileIterator->Enter_Parent(); -} + void process(CProfileIterator* itr, QString context) override { + QString name = context + itr->Get_Current_Parent_Name(); + float time = (btScalar)MSECS_PER_SECOND * itr->Get_Current_Parent_Total_Time(); + if (_file.error() == QFileDevice::NoError) { + QTextStream s(&_file); + s << name << " = " << time << "\n"; + } + } +protected: + QFile _file; +}; void PhysicsEngine::harvestPerformanceStats() { // unfortunately the full context names get too long for our stats presentation format //QString contextName = PerformanceTimer::getContextName(); // TODO: how to show full context name? QString contextName("..."); - CProfileIterator* profileIterator = CProfileManager::Get_Iterator(); - if (profileIterator) { + CProfileIterator* itr = CProfileManager::Get_Iterator(); + if (itr) { // hunt for stepSimulation context - profileIterator->First(); - for (int32_t childIndex = 0; !profileIterator->Is_Done(); ++childIndex) { - if (QString(profileIterator->Get_Current_Name()) == "stepSimulation") { - profileIterator->Enter_Child(childIndex); - PhysicsStatsHarvester harvester; - harvester.process(profileIterator); + itr->First(); + for (int32_t childIndex = 0; !itr->Is_Done(); ++childIndex) { + if (QString(itr->Get_Current_Name()) == "stepSimulation") { + itr->Enter_Child(childIndex); + StatsHarvester harvester; + harvester.recurse(itr, "bt"); break; } - profileIterator->Next(); + itr->Next(); + } + } +} + +void PhysicsEngine::printPerformanceStatsToFile(const QString& filename) { + CProfileIterator* itr = CProfileManager::Get_Iterator(); + if (itr) { + // hunt for stepSimulation context + itr->First(); + for (int32_t childIndex = 0; !itr->Is_Done(); ++childIndex) { + if (QString(itr->Get_Current_Name()) == "stepSimulation") { + itr->Enter_Child(childIndex); + StatsWriter writer(filename); + writer.recurse(itr, ""); + break; + } + itr->Next(); } } } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 4e63e8ff3e..3956dd09d9 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -62,6 +62,7 @@ public: void stepSimulation(); void harvestPerformanceStats(); + void printPerformanceStatsToFile(const QString& filename); void updateContactMap(); bool hasOutgoingChanges() const { return _hasOutgoingChanges; } From 2538204b1eb05d8dd5632e5a530be0d2623ec503 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 7 Dec 2017 16:52:21 -0800 Subject: [PATCH 24/48] expose physics simulation stats to Test JS API --- interface/src/Application.cpp | 7 +++++-- interface/src/Application.h | 2 ++ interface/src/scripting/TestScriptingInterface.cpp | 4 ++++ interface/src/scripting/TestScriptingInterface.h | 5 +++++ libraries/physics/src/PhysicsEngine.cpp | 13 +++++++++++++ libraries/physics/src/PhysicsEngine.h | 9 +++++++-- libraries/physics/src/ThreadSafeDynamicsWorld.cpp | 8 +++++++- 7 files changed, 43 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0176acf108..3745a82b3c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3222,8 +3222,6 @@ void Application::keyPressEvent(QKeyEvent* event) { } } - - void Application::keyReleaseEvent(QKeyEvent* event) { _keysPressed.remove(event->key()); @@ -7506,4 +7504,9 @@ void Application::setAvatarOverrideUrl(const QUrl& url, bool save) { _avatarOverrideUrl = url; _saveAvatarOverrideUrl = save; } + +void Application::saveNextPhysicsStats(QString filename) { + _physicsEngine->saveNextPhysicsStats(filename); +} + #include "Application.moc" diff --git a/interface/src/Application.h b/interface/src/Application.h index 9542c5ccb6..ee16740f20 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -280,6 +280,7 @@ public: void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; } QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; } bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } + void saveNextPhysicsStats(QString filename); signals: void svoImportRequested(const QString& url); @@ -432,6 +433,7 @@ private slots: void handleSandboxStatus(QNetworkReply* reply); void switchDisplayMode(); + private: static void initDisplay(); void init(); diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index d4b4ba1480..b53b9d5d5f 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -141,6 +141,10 @@ void TestScriptingInterface::endTraceEvent(QString name) { tracing::traceEvent(trace_test(), name, tracing::DurationEnd); } +void TestScriptingInterface::savePhysicsSimulationStats(QString filename) { + qApp->saveNextPhysicsStats(filename); +} + void TestScriptingInterface::profileRange(const QString& name, QScriptValue fn) { PROFILE_RANGE(script, name); fn.call(); diff --git a/interface/src/scripting/TestScriptingInterface.h b/interface/src/scripting/TestScriptingInterface.h index 73b8f0ac93..aca07d110b 100644 --- a/interface/src/scripting/TestScriptingInterface.h +++ b/interface/src/scripting/TestScriptingInterface.h @@ -71,6 +71,11 @@ public slots: void endTraceEvent(QString name); + /**jsdoc + * Write detailed timing stats of next physics stepSimulation() to filename + */ + void savePhysicsSimulationStats(QString filename); + Q_INVOKABLE void profileRange(const QString& name, QScriptValue function); private: diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 2eec4a3950..36b677e92f 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "CharacterController.h" #include "ObjectMotionState.h" @@ -294,6 +295,7 @@ void PhysicsEngine::stepSimulation() { float timeStep = btMin(dt, MAX_TIMESTEP); if (_myAvatarController) { + DETAILED_PROFILE_RANGE(simulation_physics, "avatarController"); BT_PROFILE("avatarController"); // TODO: move this stuff outside and in front of stepSimulation, because // the updateShapeIfNecessary() call needs info from MyAvatar and should @@ -465,6 +467,7 @@ void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const } void PhysicsEngine::updateContactMap() { + DETAILED_PROFILE_RANGE(simulation_physics, "updateContactMap"); BT_PROFILE("updateContactMap"); ++_numContactFrames; @@ -582,10 +585,20 @@ void PhysicsEngine::dumpStatsIfNecessary() { if (_dumpNextStats) { _dumpNextStats = false; CProfileManager::Increment_Frame_Counter(); + if (_saveNextStats) { + _saveNextStats = false; + printPerformanceStatsToFile(_statsFilename); + } CProfileManager::dumpAll(); } } +void PhysicsEngine::saveNextPhysicsStats(QString filename) { + _saveNextStats = true; + _dumpNextStats = true; + _statsFilename = filename; +} + // Bullet collision flags are as follows: // CF_STATIC_OBJECT= 1, // CF_KINEMATIC_OBJECT= 2, diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 3956dd09d9..6619a5489d 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -77,6 +77,9 @@ public: /// \brief prints timings for last frame if stats have been requested. void dumpStatsIfNecessary(); + /// \brief saves timings for last frame in filename + void saveNextPhysicsStats(QString filename); + /// \param offset position of simulation origin in domain-frame void setOriginOffset(const glm::vec3& offset) { _originOffset = offset; } @@ -116,6 +119,7 @@ private: QHash _objectDynamics; QHash> _objectDynamicsByBody; std::set _activeStaticBodies; + QString _statsFilename; glm::vec3 _originOffset; @@ -124,8 +128,9 @@ private: uint32_t _numContactFrames = 0; uint32_t _numSubsteps; - bool _dumpNextStats = false; - bool _hasOutgoingChanges = false; + bool _dumpNextStats { false }; + bool _saveNextStats { false }; + bool _hasOutgoingChanges { false }; }; diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index 24cfbc2609..abda5c82fc 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -18,6 +18,7 @@ #include #include "ThreadSafeDynamicsWorld.h" +#include "Profile.h" ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld( btDispatcher* dispatcher, @@ -29,6 +30,7 @@ ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld( int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep, SubStepCallback onSubStep) { + DETAILED_PROFILE_RANGE(simulation_physics, "stepWithCB"); BT_PROFILE("stepSimulationWithSubstepCallback"); int subSteps = 0; if (maxSubSteps) { @@ -68,11 +70,13 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep saveKinematicState(fixedTimeStep*clampedSimulationSteps); { + DETAILED_PROFILE_RANGE(simulation_physics, "applyGravity"); BT_PROFILE("applyGravity"); applyGravity(); } for (int i=0;i Date: Mon, 11 Dec 2017 11:27:33 -0800 Subject: [PATCH 25/48] cleanup prof stats and trace context names --- interface/src/Application.cpp | 18 +++++------- .../src/EntityTreeRenderer.cpp | 10 +++---- libraries/entities/src/EntityItem.cpp | 3 ++ libraries/entities/src/EntitySimulation.cpp | 12 +++----- libraries/entities/src/EntityTree.cpp | 24 ++++++++------- libraries/physics/src/EntityMotionState.cpp | 7 ++++- .../physics/src/PhysicalEntitySimulation.cpp | 29 ++++++++++++------- libraries/physics/src/PhysicsEngine.cpp | 2 +- .../physics/src/ThreadSafeDynamicsWorld.cpp | 2 +- 9 files changed, 59 insertions(+), 48 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3745a82b3c..ed1a9d41d2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4846,8 +4846,7 @@ void Application::update(float deltaTime) { if (_physicsEnabled) { { PROFILE_RANGE(simulation_physics, "PreStep"); - - PerformanceTimer perfTimer("updateStates)"); + PerformanceTimer perfTimer("preStep)"); static VectorOfMotionStates motionStates; _entitySimulation->getObjectsToRemoveFromPhysics(motionStates); _physicsEngine->removeObjects(motionStates); @@ -4880,22 +4879,22 @@ void Application::update(float deltaTime) { } { PROFILE_RANGE(simulation_physics, "Step"); - PerformanceTimer perfTimer("stepSimulation"); + PerformanceTimer perfTimer("step"); getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); } { PROFILE_RANGE(simulation_physics, "PostStep"); - PerformanceTimer perfTimer("harvestChanges"); + PerformanceTimer perfTimer("postStep"); if (_physicsEngine->hasOutgoingChanges()) { // grab the collision events BEFORE handleOutgoingChanges() because at this point // we have a better idea of which objects we own or should own. auto& collisionEvents = _physicsEngine->getCollisionEvents(); getEntities()->getTree()->withWriteLock([&] { - PROFILE_RANGE(simulation_physics, "Harvest"); - PerformanceTimer perfTimer("handleOutgoingChanges"); + PROFILE_RANGE(simulation_physics, "HandleChanges"); + PerformanceTimer perfTimer("handleChanges"); const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates(); _entitySimulation->handleChangedMotionStates(outgoingChanges); @@ -4906,17 +4905,15 @@ void Application::update(float deltaTime) { }); if (!_aboutToQuit) { - // handleCollisionEvents() AFTER handleOutgoinChanges() + // handleCollisionEvents() AFTER handleOutgoingChanges() { PROFILE_RANGE(simulation_physics, "CollisionEvents"); - PerformanceTimer perfTimer("entities"); avatarManager->handleCollisionEvents(collisionEvents); // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk // deadlock.) _entitySimulation->handleCollisionEvents(collisionEvents); } - PROFILE_RANGE(simulation_physics, "UpdateEntities"); // NOTE: the getEntities()->update() call below will wait for lock // and will simulate entity motion (the EntityTree has been given an EntitySimulation). getEntities()->update(true); // update the models... @@ -4927,7 +4924,8 @@ void Application::update(float deltaTime) { myAvatar->harvestResultsFromPhysicsSimulation(deltaTime); } - if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && + if (PerformanceTimer::isActive() && + Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming)) { _physicsEngine->harvestPerformanceStats(); } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5f7899ae74..485d3b68f8 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -251,10 +251,10 @@ void EntityTreeRenderer::shutdown() { } void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction) { - PROFILE_RANGE_EX(simulation_physics, "Add", 0xffff00ff, (uint64_t)_entitiesToAdd.size()); + PROFILE_RANGE_EX(simulation_physics, "AddToScene", 0xffff00ff, (uint64_t)_entitiesToAdd.size()); PerformanceTimer pt("add"); - // Clear any expired entities - // FIXME should be able to use std::remove_if, but it fails due to some + // Clear any expired entities + // FIXME should be able to use std::remove_if, but it fails due to some // weird compilation error related to EntityItemID assignment operators for (auto itr = _entitiesToAdd.begin(); _entitiesToAdd.end() != itr; ) { if (itr->second.expired()) { @@ -272,7 +272,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r continue; } - // Path to the parent transforms is not valid, + // Path to the parent transforms is not valid, // don't add to the scene graph yet if (!entity->isParentPathComplete()) { continue; @@ -296,7 +296,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction) { - PROFILE_RANGE_EX(simulation_physics, "Change", 0xffff00ff, (uint64_t)_changedEntities.size()); + PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size()); PerformanceTimer pt("change"); std::unordered_set changedEntities; _changedEntitiesGuard.withWriteLock([&] { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 48370b02fd..e3abb98a7a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include // usecTimestampNow() #include @@ -984,6 +985,7 @@ void EntityItem::setCollisionSoundURL(const QString& value) { } void EntityItem::simulate(const quint64& now) { + DETAILED_PROFILE_RANGE(simulation_physics, "Simulate"); if (getLastSimulated() == 0) { setLastSimulated(now); } @@ -1039,6 +1041,7 @@ void EntityItem::simulate(const quint64& now) { } bool EntityItem::stepKinematicMotion(float timeElapsed) { + DETAILED_PROFILE_RANGE(simulation_physics, "StepKinematicMotion"); // get all the data Transform transform; glm::vec3 linearVelocity; diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index f91d728d78..36b0d8ab2d 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -29,7 +29,6 @@ void EntitySimulation::setEntityTree(EntityTreePointer tree) { } void EntitySimulation::updateEntities() { - PROFILE_RANGE(simulation_physics, "ES::updateEntities"); QMutexLocker lock(&_mutex); quint64 now = usecTimestampNow(); @@ -38,12 +37,7 @@ void EntitySimulation::updateEntities() { callUpdateOnEntitiesThatNeedIt(now); moveSimpleKinematics(now); updateEntitiesInternal(now); - - { - PROFILE_RANGE(simulation_physics, "Sort"); - PerformanceTimer perfTimer("sortingEntities"); - sortEntitiesThatMoved(); - } + sortEntitiesThatMoved(); } void EntitySimulation::takeEntitiesToDelete(VectorOfEntities& entitiesToDelete) { @@ -101,6 +95,7 @@ void EntitySimulation::changeEntityInternal(EntityItemPointer entity) { // protected void EntitySimulation::expireMortalEntities(const quint64& now) { if (now > _nextExpiry) { + PROFILE_RANGE_EX(simulation_physics, "ExpireMortals", 0xffff00ff, (uint64_t)_mortalEntities.size()); // only search for expired entities if we expect to find one _nextExpiry = quint64(-1); QMutexLocker lock(&_mutex); @@ -146,6 +141,7 @@ void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) { // protected void EntitySimulation::sortEntitiesThatMoved() { + PROFILE_RANGE_EX(simulation_physics, "SortTree", 0xffff00ff, (uint64_t)_entitiesToSort.size()); // NOTE: this is only for entities that have been moved by THIS EntitySimulation. // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. MovingEntitiesOperator moveOperator; @@ -265,7 +261,7 @@ void EntitySimulation::clearEntities() { } void EntitySimulation::moveSimpleKinematics(const quint64& now) { - PROFILE_RANGE_EX(simulation_physics, "Kinematics", 0xffff00ff, (uint64_t)_simpleKinematicEntities.size()); + PROFILE_RANGE_EX(simulation_physics, "MoveSimples", 0xffff00ff, (uint64_t)_simpleKinematicEntities.size()); SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin(); while (itemItr != _simpleKinematicEntities.end()) { EntityItemPointer entity = *itemItr; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index e62399ce95..10fcd19a8c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1770,24 +1770,26 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) { } void EntityTree::update(bool simulate) { - PROFILE_RANGE(simulation_physics, "ET::update"); + PROFILE_RANGE(simulation_physics, "UpdateTree"); fixupNeedsParentFixups(); if (simulate && _simulation) { withWriteLock([&] { _simulation->updateEntities(); - VectorOfEntities pendingDeletes; - _simulation->takeEntitiesToDelete(pendingDeletes); + { + PROFILE_RANGE(simulation_physics, "Deletes"); + VectorOfEntities pendingDeletes; + _simulation->takeEntitiesToDelete(pendingDeletes); + if (pendingDeletes.size() > 0) { + // translate into list of ID's + QSet idsToDelete; - if (pendingDeletes.size() > 0) { - // translate into list of ID's - QSet idsToDelete; + for (auto entity : pendingDeletes) { + idsToDelete.insert(entity->getEntityItemID()); + } - for (auto entity : pendingDeletes) { - idsToDelete.insert(entity->getEntityItemID()); + // delete these things the roundabout way + deleteEntities(idsToDelete, true); } - - // delete these things the roundabout way - deleteEntities(idsToDelete, true); } }); } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 7e8b431ceb..a688d521d6 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -14,8 +14,9 @@ #include #include #include -#include #include +#include +#include #include "BulletUtil.h" #include "EntityMotionState.h" @@ -325,6 +326,7 @@ bool EntityMotionState::isCandidateForOwnership() const { } bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { + DETAILED_PROFILE_RANGE(simulation_physics, "CheckOutOfSync"); // NOTE: we only get here if we think we own the simulation assert(_body); @@ -476,6 +478,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { } bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { + DETAILED_PROFILE_RANGE(simulation_physics, "ShouldSend"); // NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called // after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL. assert(_entity); @@ -516,6 +519,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { } void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) { + DETAILED_PROFILE_RANGE(simulation_physics, "Send"); assert(_entity); assert(entityTreeIsLocked()); @@ -731,6 +735,7 @@ void EntityMotionState::resetMeasuredBodyAcceleration() { } void EntityMotionState::measureBodyAcceleration() { + DETAILED_PROFILE_RANGE(simulation_physics, "MeasureAccel"); // try to manually measure the true acceleration of the object uint32_t thisStep = ObjectMotionState::getWorldSimulationStep(); uint32_t numSubsteps = thisStep - _lastMeasureStep; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 3e87b9437d..e4ba47e205 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -10,12 +10,14 @@ // +#include "PhysicalEntitySimulation.h" + +#include #include "PhysicsHelpers.h" #include "PhysicsLogging.h" #include "ShapeManager.h" -#include "PhysicalEntitySimulation.h" PhysicalEntitySimulation::PhysicalEntitySimulation() { } @@ -274,20 +276,24 @@ void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotio } void PhysicalEntitySimulation::handleChangedMotionStates(const VectorOfMotionStates& motionStates) { + PROFILE_RANGE_EX(simulation_physics, "ChangedEntities", 0x00000000, (uint64_t)motionStates.size()); QMutexLocker lock(&_mutex); // walk the motionStates looking for those that correspond to entities - for (auto stateItr : motionStates) { - ObjectMotionState* state = &(*stateItr); - assert(state); - if (state->getType() == MOTIONSTATE_TYPE_ENTITY) { - EntityMotionState* entityState = static_cast(state); - EntityItemPointer entity = entityState->getEntity(); - assert(entity.get()); - if (entityState->isCandidateForOwnership()) { - _outgoingChanges.insert(entityState); + { + PROFILE_RANGE_EX(simulation_physics, "Filter", 0x00000000, (uint64_t)motionStates.size()); + for (auto stateItr : motionStates) { + ObjectMotionState* state = &(*stateItr); + assert(state); + if (state->getType() == MOTIONSTATE_TYPE_ENTITY) { + EntityMotionState* entityState = static_cast(state); + EntityItemPointer entity = entityState->getEntity(); + assert(entity.get()); + if (entityState->isCandidateForOwnership()) { + _outgoingChanges.insert(entityState); + } + _entitiesToSort.insert(entity); } - _entitiesToSort.insert(entity); } } @@ -302,6 +308,7 @@ void PhysicalEntitySimulation::handleChangedMotionStates(const VectorOfMotionSta } // look for entities to prune or update + PROFILE_RANGE_EX(simulation_physics, "Prune/Send", 0x00000000, (uint64_t)_outgoingChanges.size()); QSet::iterator stateItr = _outgoingChanges.begin(); while (stateItr != _outgoingChanges.end()) { EntityMotionState* state = *stateItr; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 36b677e92f..fe794772e2 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -412,7 +412,7 @@ void PhysicsEngine::harvestPerformanceStats() { if (QString(itr->Get_Current_Name()) == "stepSimulation") { itr->Enter_Child(childIndex); StatsHarvester harvester; - harvester.recurse(itr, "bt"); + harvester.recurse(itr, "step/"); break; } itr->Next(); diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index abda5c82fc..5b8c0d5843 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -122,7 +122,7 @@ void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { } void ThreadSafeDynamicsWorld::synchronizeMotionStates() { - DETAILED_PROFILE_RANGE(simulation_physics, "syncMotionStates"); + PROFILE_RANGE(simulation_physics, "SyncMotionStates"); BT_PROFILE("syncMotionStates"); _changedMotionStates.clear(); From 74a1f5de9643bb06f0adec7b5dd437dfc1603eb3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 11 Dec 2017 11:30:00 -0800 Subject: [PATCH 26/48] remove bullet stats when physics stats disabled --- interface/src/Menu.cpp | 3 ++- interface/src/ui/Stats.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9bbb72357b..2d15134b70 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -645,7 +645,8 @@ Menu::Menu() { // Developer > Timing >>> MenuWrapper* timingMenu = developerMenu->addMenu("Timing"); MenuWrapper* perfTimerMenu = timingMenu->addMenu("Performance Timer"); - addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails, 0, false); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails, 0, false, + qApp, SLOT(enablePerfStats(bool))); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index e194551add..f991420fe8 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -78,6 +78,8 @@ bool Stats::includeTimingRecord(const QString& name) { return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); } else if (name.startsWith("/paintGL/")) { return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); + } else if (name.startsWith("step/")) { + return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming); } return true; } From ce96fa70788bbce962f4e2d53bfc9ad7f00f2bfc Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Dec 2017 17:32:58 -0800 Subject: [PATCH 27/48] change hysteresis values based on testing --- interface/src/raypick/StylusPointer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/raypick/StylusPointer.cpp b/interface/src/raypick/StylusPointer.cpp index 21d257048c..5afbc2058a 100644 --- a/interface/src/raypick/StylusPointer.cpp +++ b/interface/src/raypick/StylusPointer.cpp @@ -23,10 +23,10 @@ static const float WEB_STYLUS_LENGTH = 0.2f; static const float TABLET_MIN_HOVER_DISTANCE = -0.1f; static const float TABLET_MAX_HOVER_DISTANCE = 0.1f; static const float TABLET_MIN_TOUCH_DISTANCE = -0.1f; -static const float TABLET_MAX_TOUCH_DISTANCE = 0.01f; +static const float TABLET_MAX_TOUCH_DISTANCE = 0.005f; static const float HOVER_HYSTERESIS = 0.01f; -static const float TOUCH_HYSTERESIS = 0.02f; +static const float TOUCH_HYSTERESIS = 0.001f; static const float STYLUS_MOVE_DELAY = 0.33f * USECS_PER_SECOND; static const float TOUCH_PRESS_TO_MOVE_DEADSPOT = 0.0481f; From 29538851b61c17a8e8561dd1534942e535f40589 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 11 Dec 2017 18:50:07 -0800 Subject: [PATCH 28/48] Made the changes from the latest code review, except getting rid of the while loop. --- .../src/RenderableModelEntityItem.cpp | 4 +-- .../src/RenderableModelEntityItem.h | 1 - .../entities/src/AnimationPropertyGroup.cpp | 9 +++--- libraries/entities/src/ModelEntityItem.cpp | 31 ++++++++++--------- libraries/entities/src/ModelEntityItem.h | 4 +-- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 4686cc94bc..e578e4858d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -992,7 +992,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { return; } - { + { // the current frame is set on the server in update() in ModelEntityItem.cpp int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); @@ -1313,7 +1313,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } // The code to deal with the change of properties is now in ModelEntityItem.cpp - // That is where _currentFrame and _lastAnimated are updated. + // That is where _currentFrame and _lastAnimated were updated. if (_animating) { DETAILED_PROFILE_RANGE(simulation_physics, "Animate"); if (!jointsMapped()) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 44ee82713d..b4f2665692 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -184,7 +184,6 @@ private: bool _shouldHighlight { false }; bool _animating { false }; uint64_t _lastAnimated { 0 }; - float _currentFrame { -1 }; }; } } // namespace diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 932bdbf8c0..2af56fb6b2 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -22,24 +22,25 @@ const float AnimationPropertyGroup::MAXIMUM_POSSIBLE_FRAME = 100000.0f; bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b) { return - (a._url == b._url) && + (a._currentFrame == b._currentFrame) && (a._running == b._running) && (a._loop == b._loop) && + (a._hold == b._hold) && (a._firstFrame == b._firstFrame) && (a._lastFrame == b._lastFrame) && - (a._hold == b._hold); + (a._url == b._url); } bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b) { return - (a._url != b._url) || (a._currentFrame != b._currentFrame) || (a._running != b._running) || (a._loop != b._loop) || + (a._hold != b._hold) || (a._firstFrame != b._firstFrame) || (a._lastFrame != b._lastFrame) || - (a._hold != b._hold); + (a._url != b._url); } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 260074da68..4ade724a82 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -207,11 +207,16 @@ void ModelEntityItem::update(const quint64& now) { // don't reset _lastAnimated here because we need the timestamp from the ModelEntityItem constructor for when the properties were set _currentFrame = currentAnimationProperties.getCurrentFrame(); setAnimationCurrentFrame(_currentFrame); + qCDebug(entities) << "setting first frame 1 " << _currentFrame; } else { - _lastAnimated = usecTimestampNow(); + _lastAnimated = usecTimestampNow(); _currentFrame = currentAnimationProperties.getFirstFrame(); setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); + qCDebug(entities) << "setting first frame 2" << _currentFrame; } + } else if (!currentAnimationProperties.getRunning() && _previousAnimationProperties.getRunning()) { + _currentFrame = currentAnimationProperties.getFirstFrame(); + setAnimationCurrentFrame(_currentFrame); } else if (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) { // don't reset _lastAnimated here because the currentFrame was set with the previous setting of _lastAnimated _currentFrame = currentAnimationProperties.getCurrentFrame(); @@ -228,13 +233,15 @@ void ModelEntityItem::update(const quint64& now) { // if the current frame is less than zero then we have restarted the server. if (_currentFrame < 0) { + //qCDebug(entities) << "setting first frame 3 " << _currentFrame; if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { - _currentFrame = currentAnimationProperties.getCurrentFrame(); + // _currentFrame = currentAnimationProperties.getCurrentFrame(); } else { - _currentFrame = currentAnimationProperties.getFirstFrame(); - setAnimationCurrentFrame(_currentFrame); - _lastAnimated = usecTimestampNow(); + //qCDebug(entities) << "setting first frame 4 " << _currentFrame; + // _currentFrame = currentAnimationProperties.getFirstFrame(); + // setAnimationCurrentFrame(_currentFrame); + // _lastAnimated = usecTimestampNow(); } } } @@ -269,7 +276,7 @@ void ModelEntityItem::updateFrameCount() { _lastAnimated = now; // if fps is negative then increment timestamp and return. - if (getAnimationFPS() < 0.0) { + if (getAnimationFPS() < 0.0f) { return; } @@ -280,8 +287,9 @@ void ModelEntityItem::updateFrameCount() { _currentFrame += (deltaTime * getAnimationFPS()); if (_currentFrame > getAnimationLastFrame()) { if (getAnimationLoop()) { - while ((_currentFrame - getAnimationFirstFrame()) > (updatedFrameCount - 1)) { - _currentFrame -= (updatedFrameCount - 1); + //_currentFrame = getAnimationFirstFrame() + (int)(glm::floor(_currentFrame - getAnimationFirstFrame())) % (updatedFrameCount - 1); + while (_currentFrame > (getAnimationFirstFrame() + (updatedFrameCount - 1))) { + _currentFrame = _currentFrame - (updatedFrameCount - 1); } } else { _currentFrame = getAnimationLastFrame(); @@ -293,6 +301,7 @@ void ModelEntityItem::updateFrameCount() { _currentFrame = getAnimationFirstFrame(); } } + qCDebug(entities) << "in update frame " << _currentFrame; setAnimationCurrentFrame(_currentFrame); } @@ -720,9 +729,3 @@ bool ModelEntityItem::isAnimatingSomething() const { (_animationProperties.getFPS() != 0.0f); }); } - -int ModelEntityItem::getLastKnownCurrentFrame() const { - return resultWithReadLock([&] { - return _lastKnownCurrentFrame; - }); -} diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index c0ca12c7f9..7fee022011 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -110,8 +110,6 @@ public: float getAnimationFPS() const; bool isAnimatingSomething() const; - int getLastKnownCurrentFrame() const; - static const QString DEFAULT_TEXTURES; const QString getTextures() const; void setTextures(const QString& textures); @@ -172,7 +170,7 @@ protected: private: uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; - float _currentFrame{ -1 }; + float _currentFrame{ -1.0f }; }; #endif // hifi_ModelEntityItem_h From 079d9639e477844bdb79f213cafc21334f15f806 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 12 Dec 2017 09:12:11 -0800 Subject: [PATCH 29/48] Got rid of the while loop in updateFrameCount in ModelEntityItem_cpp --- libraries/entities/src/ModelEntityItem.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 4ade724a82..3215ab9dd0 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -287,10 +287,7 @@ void ModelEntityItem::updateFrameCount() { _currentFrame += (deltaTime * getAnimationFPS()); if (_currentFrame > getAnimationLastFrame()) { if (getAnimationLoop()) { - //_currentFrame = getAnimationFirstFrame() + (int)(glm::floor(_currentFrame - getAnimationFirstFrame())) % (updatedFrameCount - 1); - while (_currentFrame > (getAnimationFirstFrame() + (updatedFrameCount - 1))) { - _currentFrame = _currentFrame - (updatedFrameCount - 1); - } + _currentFrame = getAnimationFirstFrame() + (int)(glm::floor(_currentFrame - getAnimationFirstFrame())) % (updatedFrameCount - 1); } else { _currentFrame = getAnimationLastFrame(); } From 87fa919ac8d2c38198c515df3e9dcdb49c32bc23 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 12 Dec 2017 14:11:25 -0800 Subject: [PATCH 30/48] save files to Documents by default --- .../src/scripting/TestScriptingInterface.cpp | 14 ++++-- libraries/shared/src/Trace.cpp | 45 +++++-------------- libraries/shared/src/shared/FileUtils.cpp | 45 +++++++++++++++++-- libraries/shared/src/shared/FileUtils.h | 3 ++ 4 files changed, 66 insertions(+), 41 deletions(-) diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index b53b9d5d5f..74a15db0ce 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -11,11 +11,12 @@ #include #include +#include #include #include -#include -#include #include +#include +#include #include "Application.h" @@ -141,8 +142,13 @@ void TestScriptingInterface::endTraceEvent(QString name) { tracing::traceEvent(trace_test(), name, tracing::DurationEnd); } -void TestScriptingInterface::savePhysicsSimulationStats(QString filename) { - qApp->saveNextPhysicsStats(filename); +void TestScriptingInterface::savePhysicsSimulationStats(QString originalPath) { + QString path = FileUtils::replaceDateTimeTokens(originalPath); + path = FileUtils::computeDocumentPath(path); + if (!FileUtils::canCreateFile(path)) { + return; + } + qApp->saveNextPhysicsStats(path); } void TestScriptingInterface::profileRange(const QString& name, QScriptValue fn) { diff --git a/libraries/shared/src/Trace.cpp b/libraries/shared/src/Trace.cpp index d7feb65ff3..3f6a2dd643 100644 --- a/libraries/shared/src/Trace.cpp +++ b/libraries/shared/src/Trace.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -31,6 +30,8 @@ #include "Gzip.h" #include "PortableHighResolutionClock.h" +#include "SharedLogging.h" +#include "shared/FileUtils.h" #include "shared/GlobalAppProperties.h" using namespace tracing; @@ -104,30 +105,13 @@ void TraceEvent::writeJson(QTextStream& out) const { #endif } -void Tracer::serialize(const QString& originalPath) { - - QString path = originalPath; - - // Filter for specific tokens potentially present in the path: - auto now = QDateTime::currentDateTime(); - - path = path.replace("{DATE}", now.date().toString("yyyyMMdd")); - path = path.replace("{TIME}", now.time().toString("HHmm")); - - // If the filename is relative, turn it into an absolute path relative to the document directory. - QFileInfo originalFileInfo(path); - if (originalFileInfo.isRelative()) { - QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - path = docsLocation + "/" + path; - QFileInfo info(path); - if (!info.absoluteDir().exists()) { - QString originalRelativePath = originalFileInfo.path(); - QDir(docsLocation).mkpath(originalRelativePath); - } +void Tracer::serialize(const QString& filename) { + QString fullPath = FileUtils::replaceDateTimeTokens(filename); + fullPath = FileUtils::computeDocumentPath(fullPath); + if (!FileUtils::canCreateFile(fullPath)) { + return; } - - std::list currentEvents; { std::lock_guard guard(_eventsMutex); @@ -137,11 +121,6 @@ void Tracer::serialize(const QString& originalPath) { } } - // If the file exists and we can't remove it, fail early - if (QFileInfo(path).exists() && !QFile::remove(path)) { - return; - } - // If we can't open a temp file for writing, fail early QByteArray data; { @@ -159,15 +138,16 @@ void Tracer::serialize(const QString& originalPath) { out << "\n]"; } - if (path.endsWith(".gz")) { + if (fullPath.endsWith(".gz")) { QByteArray compressed; gzip(data, compressed); data = compressed; - } - + } + { - QFile file(path); + QFile file(fullPath); if (!file.open(QIODevice::WriteOnly)) { + qDebug(shared) << "failed to open file '" << fullPath << "'"; return; } file.write(data); @@ -191,7 +171,6 @@ void Tracer::serialize(const QString& originalPath) { } } } }; - data = document.toJson(QJsonDocument::Compact); } #endif diff --git a/libraries/shared/src/shared/FileUtils.cpp b/libraries/shared/src/shared/FileUtils.cpp index 8c962dfd6d..dba0af7b16 100644 --- a/libraries/shared/src/shared/FileUtils.cpp +++ b/libraries/shared/src/shared/FileUtils.cpp @@ -12,6 +12,7 @@ #include "FileUtils.h" +#include #include #include #include @@ -20,6 +21,8 @@ #include #include +#include "../SharedLogging.h" + QString FileUtils::readFile(const QString& filename) { QFile file(filename); @@ -82,20 +85,54 @@ QString FileUtils::standardPath(QString subfolder) { // standard path // Mac: ~/Library/Application Support/Interface QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (!subfolder.startsWith("/")) { subfolder.prepend("/"); } - if (!subfolder.endsWith("/")) { subfolder.append("/"); } - path.append(subfolder); QDir logDir(path); if (!logDir.exists(path)) { logDir.mkpath(path); } - return path; } + +QString FileUtils::replaceDateTimeTokens(const QString& originalPath) { + // Filter for specific tokens potentially present in the path: + auto now = QDateTime::currentDateTime(); + QString path = originalPath; + path.replace("{DATE}", now.date().toString("yyyyMMdd")); + path.replace("{TIME}", now.time().toString("HHmm")); + return path; +} + + +QString FileUtils::computeDocumentPath(const QString& originalPath) { + // If the filename is relative, turn it into an absolute path relative to the document directory. + QString path = originalPath; + QFileInfo originalFileInfo(originalPath); + if (originalFileInfo.isRelative()) { + QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + path = docsLocation + "/" + originalPath; + } + return path; +} + +bool FileUtils::canCreateFile(const QString& fullPath) { + // If the file exists and we can't remove it, fail early + QFileInfo fileInfo(fullPath); + if (fileInfo.exists() && !QFile::remove(fullPath)) { + qDebug(shared) << "unable to overwrite file '" << fullPath << "'"; + return false; + } + QDir dir(fileInfo.absolutePath()); + if (!dir.exists()) { + if (!dir.mkpath(fullPath)) { + qDebug(shared) << "unable to create dir '" << dir.absolutePath() << "'"; + return false; + } + } + return true; +} diff --git a/libraries/shared/src/shared/FileUtils.h b/libraries/shared/src/shared/FileUtils.h index 4f2c1b7af5..d68fcd8a44 100644 --- a/libraries/shared/src/shared/FileUtils.h +++ b/libraries/shared/src/shared/FileUtils.h @@ -21,6 +21,9 @@ public: static QString standardPath(QString subfolder); static QString readFile(const QString& filename); static QStringList readLines(const QString& filename, QString::SplitBehavior splitBehavior = QString::KeepEmptyParts); + static QString replaceDateTimeTokens(const QString& path); + static QString computeDocumentPath(const QString& path); + static bool canCreateFile(const QString& fullPath); }; #endif // hifi_FileUtils_h From 139976d8bb68597967c1f4ab7cc945fb8073ab38 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 12 Dec 2017 16:19:17 -0800 Subject: [PATCH 31/48] allow staging METAVERSE_SERVER_URL to be toggled by env --- assignment-client/src/entities/EntityServer.cpp | 2 +- domain-server/src/DomainServer.cpp | 6 +++--- ice-server/src/IceServer.cpp | 2 +- interface/src/Application.cpp | 2 +- interface/src/commerce/Ledger.cpp | 2 +- interface/src/networking/CloseEventSender.cpp | 2 +- interface/src/ui/AddressBarDialog.h | 2 +- .../src/ui/overlays/ContextOverlayInterface.cpp | 4 ++-- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 1 - libraries/entities/src/EntityTree.cpp | 2 +- libraries/networking/src/AccountManager.h | 2 +- libraries/networking/src/NetworkingConstants.h | 17 +++++++++++++++-- .../src/OAuthNetworkAccessManager.cpp | 2 +- .../script-engine/src/XMLHttpRequestClass.cpp | 2 +- libraries/ui/src/ui/types/RequestFilters.cpp | 2 +- tools/ac-client/src/ACClientApp.cpp | 2 +- tools/atp-client/src/ATPClientApp.cpp | 2 +- 18 files changed, 34 insertions(+), 22 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 995a5bad27..ecdf14ebec 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -477,7 +477,7 @@ void EntityServer::startDynamicDomainVerification() { QNetworkRequest networkRequest; networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/location"); QJsonObject request; request["certificate_id"] = i.key(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c2fe3af7c1..2d8bf7418a 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -94,7 +94,7 @@ bool DomainServer::forwardMetaverseAPIRequest(HTTPConnection* connection, root.insert(requestSubobjectKey, subobject); QJsonDocument doc { root }; - QUrl url { NetworkingConstants::METAVERSE_SERVER_URL.toString() + metaversePath }; + QUrl url { NetworkingConstants::METAVERSE_SERVER_URL().toString() + metaversePath }; QNetworkRequest req(url); req.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); @@ -420,7 +420,7 @@ bool DomainServer::optionallySetupOAuth() { // if we don't have an oauth provider URL then we default to the default node auth url if (_oauthProviderURL.isEmpty()) { - _oauthProviderURL = NetworkingConstants::METAVERSE_SERVER_URL; + _oauthProviderURL = NetworkingConstants::METAVERSE_SERVER_URL(); } auto accountManager = DependencyManager::get(); @@ -2159,7 +2159,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonDocument doc(root); - QUrl url { NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/api/v1/places/" + place_id }; + QUrl url { NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/api/v1/places/" + place_id }; url.setQuery("access_token=" + accessTokenVariant->toString()); diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp index f8bf1f62ae..3cf1e1450e 100644 --- a/ice-server/src/IceServer.cpp +++ b/ice-server/src/IceServer.cpp @@ -208,7 +208,7 @@ void IceServer::requestDomainPublicKey(const QUuid& domainID) { // send a request to the metaverse API for the public key for this domain auto& networkAccessManager = NetworkAccessManager::getInstance(); - QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL }; + QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL() }; QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID)); publicKeyURL.setPath(publicKeyPath); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0176acf108..3e4ab16908 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -971,7 +971,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // set the account manager's root URL and trigger a login request if we don't have the access token accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto addressManager = DependencyManager::get(); diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b0d293584c..3257a634c7 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -130,7 +130,7 @@ QString amountString(const QString& label, const QString&color, const QJsonValue return result + QString(""); } -static const QString MARKETPLACE_ITEMS_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace/items/"; +static const QString MARKETPLACE_ITEMS_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace/items/"; void Ledger::historySuccess(QNetworkReply& reply) { // here we send a historyResult with some extra stuff in it // Namely, the styled text we'd like to show. The issue is the diff --git a/interface/src/networking/CloseEventSender.cpp b/interface/src/networking/CloseEventSender.cpp index de8bd897b2..fe939afe05 100644 --- a/interface/src/networking/CloseEventSender.cpp +++ b/interface/src/networking/CloseEventSender.cpp @@ -28,7 +28,7 @@ QNetworkRequest createNetworkRequest() { QNetworkRequest request; - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); requestURL.setPath(USER_ACTIVITY_URL); request.setUrl(requestURL); diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index cab533cce3..66f208ca90 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -30,7 +30,7 @@ public: bool forwardEnabled() { return _forwardEnabled; } bool useFeed() { return _useFeed; } void setUseFeed(bool useFeed) { if (_useFeed != useFeed) { _useFeed = useFeed; emit useFeedChanged(); } } - QString metaverseServerUrl() { return NetworkingConstants::METAVERSE_SERVER_URL.toString(); } + QString metaverseServerUrl() { return NetworkingConstants::METAVERSE_SERVER_URL().toString(); } signals: void backEnabledChanged(); diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index de644f165b..c41663fcc9 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -289,7 +289,7 @@ void ContextOverlayInterface::openInspectionCertificate() { QNetworkRequest networkRequest; networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); QJsonObject request; request["certificate_id"] = entityProperties.getCertificateID(); @@ -359,7 +359,7 @@ void ContextOverlayInterface::openInspectionCertificate() { } } -static const QString MARKETPLACE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace/items/"; +static const QString MARKETPLACE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace/items/"; void ContextOverlayInterface::openMarketplace() { // lets open the tablet and go to the current item in diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 48370b02fd..503bdd8349 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2840,7 +2840,7 @@ void EntityItem::retrieveMarketplacePublicKey() { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest; networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); requestURL.setPath("/api/v1/commerce/marketplace_key"); QJsonObject request; networkRequest.setUrl(requestURL); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 9f7ba1cc80..c7b08f2110 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index e62399ce95..0d91f3787e 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1308,7 +1308,7 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt QNetworkRequest networkRequest; networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); QJsonObject request; request["certificate_id"] = certID; diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 7d97687d0b..87b17d00d5 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -97,7 +97,7 @@ public: void setTemporaryDomain(const QUuid& domainID, const QString& key); const QString& getTemporaryDomainKey(const QUuid& domainID) { return _accountInfo.getTemporaryDomainKey(domainID); } - QUrl getMetaverseServerURL() { return NetworkingConstants::METAVERSE_SERVER_URL; } + QUrl getMetaverseServerURL() { return NetworkingConstants::METAVERSE_SERVER_URL(); } public slots: void requestAccessToken(const QString& login, const QString& password); diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index 0c210e4360..20d98563c5 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -12,15 +12,28 @@ #ifndef hifi_NetworkingConstants_h #define hifi_NetworkingConstants_h +#include #include namespace NetworkingConstants { // If you want to use STAGING instead of STABLE, - // don't forget to ALSO change the Domain Server Metaverse Server URL inside of: + // links from the Domain Server web interface (like the connect account token generation) + // will still point at stable unless you ALSO change the Domain Server Metaverse Server URL inside of: // \domain-server\resources\web\js\shared.js + + // You can avoid changing that and still effectively use a connected domain on staging + // if you manually generate a personal access token for the domains scope + // at https://staging.highfidelity.com/user/tokens/new?for_domain_server=true + const QUrl METAVERSE_SERVER_URL_STABLE("https://metaverse.highfidelity.com"); const QUrl METAVERSE_SERVER_URL_STAGING("https://staging.highfidelity.com"); - const QUrl METAVERSE_SERVER_URL = METAVERSE_SERVER_URL_STABLE; + + static const QUrl METAVERSE_SERVER_URL() { + static const QUrl serverURL = QProcessEnvironment::systemEnvironment().contains("HIFI_STAGING_METAVERSE") + ? METAVERSE_SERVER_URL_STAGING + : METAVERSE_SERVER_URL_STABLE; + return serverURL; + }; } #endif // hifi_NetworkingConstants_h diff --git a/libraries/networking/src/OAuthNetworkAccessManager.cpp b/libraries/networking/src/OAuthNetworkAccessManager.cpp index 15d5acbc67..a30786efa4 100644 --- a/libraries/networking/src/OAuthNetworkAccessManager.cpp +++ b/libraries/networking/src/OAuthNetworkAccessManager.cpp @@ -35,7 +35,7 @@ QNetworkReply* OAuthNetworkAccessManager::createRequest(QNetworkAccessManager::O auto accountManager = DependencyManager::get(); if (accountManager->hasValidAccessToken() - && req.url().host() == NetworkingConstants::METAVERSE_SERVER_URL.host()) { + && req.url().host() == NetworkingConstants::METAVERSE_SERVER_URL().host()) { QNetworkRequest authenticatedRequest(req); authenticatedRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index 1d3c8fda32..62384f9d97 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -22,7 +22,7 @@ #include "ScriptEngine.h" #include "XMLHttpRequestClass.h" -const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/api/"; +const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/api/"; Q_DECLARE_METATYPE(QByteArray*) diff --git a/libraries/ui/src/ui/types/RequestFilters.cpp b/libraries/ui/src/ui/types/RequestFilters.cpp index 0a0e67756d..d8658f1c14 100644 --- a/libraries/ui/src/ui/types/RequestFilters.cpp +++ b/libraries/ui/src/ui/types/RequestFilters.cpp @@ -20,7 +20,7 @@ namespace { bool isAuthableHighFidelityURL(const QUrl& url) { - auto metaverseServerURL = NetworkingConstants::METAVERSE_SERVER_URL; + auto metaverseServerURL = NetworkingConstants::METAVERSE_SERVER_URL(); static const QStringList HF_HOSTS = { "highfidelity.com", "highfidelity.io", metaverseServerURL.toString(), "metaverse.highfidelity.io" diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index e00560158f..88884a4fee 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -106,7 +106,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : auto accountManager = DependencyManager::get(); accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto nodeList = DependencyManager::get(); diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index c5edf27b67..9fd1bf8d4f 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -145,7 +145,7 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : auto accountManager = DependencyManager::get(); accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto nodeList = DependencyManager::get(); From 7a81c3e8e785d775ac736310daff443eeed52722 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 12 Dec 2017 16:32:43 -0800 Subject: [PATCH 32/48] allow passing of custom URL on env --- libraries/networking/src/NetworkingConstants.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index 20d98563c5..a4726f9b1a 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -28,9 +28,12 @@ namespace NetworkingConstants { const QUrl METAVERSE_SERVER_URL_STABLE("https://metaverse.highfidelity.com"); const QUrl METAVERSE_SERVER_URL_STAGING("https://staging.highfidelity.com"); + // You can change the return of this function if you want to use a custom metaverse URL at compile time + // or you can pass a custom URL via the env variable static const QUrl METAVERSE_SERVER_URL() { - static const QUrl serverURL = QProcessEnvironment::systemEnvironment().contains("HIFI_STAGING_METAVERSE") - ? METAVERSE_SERVER_URL_STAGING + static const QString HIFI_METAVERSE_URL_ENV = "HIFI_METAVERSE_URL"; + static const QUrl serverURL = QProcessEnvironment::systemEnvironment().contains(HIFI_METAVERSE_URL_ENV) + ? QUrl(QProcessEnvironment::systemEnvironment().value(HIFI_METAVERSE_URL_ENV)) : METAVERSE_SERVER_URL_STABLE; return serverURL; }; From c4a7f4843a03d0ac65d9321879c5afe35d56c3dd Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 12 Dec 2017 17:02:07 -0800 Subject: [PATCH 33/48] Much more stable hips IK target. Target is now estimated in sensor space from the head, which is very deterministic and not prone to feedback from the IK system. Previous the hip was estimated from accumulated IK error deltas, which was not stable, as the error would tend to accumulate if the IK targets could not be reached. --- interface/src/avatar/MySkeletonModel.cpp | 69 ++++++++++++++++++++++++ interface/src/avatar/MySkeletonModel.h | 3 ++ 2 files changed, 72 insertions(+) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index a707031167..f249be33ea 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -9,9 +9,12 @@ #include "MySkeletonModel.h" #include +#include #include "Application.h" #include "InterfaceLogging.h" +#include "AnimUtil.h" + MySkeletonModel::MySkeletonModel(Avatar* owningAvatar, QObject* parent) : SkeletonModel(owningAvatar, parent) { } @@ -30,6 +33,39 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle }; } +static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { + glm::mat4 hipsMat = myAvatar->deriveBodyFromHMDSensor(); + glm::vec3 hipsPos = extractTranslation(hipsMat); + glm::quat hipsRot = glmExtractRotation(hipsMat); + + glm::mat4 avatarToWorldMat = myAvatar->getTransform().getMatrix(); + glm::mat4 worldToSensorMat = glm::inverse(myAvatar->getSensorToWorldMatrix()); + glm::mat4 avatarToSensorMat = worldToSensorMat * avatarToWorldMat; + + // dampen hips rotation, by mixing it with the avatar orientation in sensor space + const float MIX_RATIO = 0.5f; + hipsRot = safeLerp(glmExtractRotation(avatarToSensorMat), hipsRot, MIX_RATIO); + + if (isFlying) { + // rotate the hips back to match the flying animation. + + const float TILT_ANGLE = 0.523f; + const glm::quat tiltRot = glm::angleAxis(TILT_ANGLE, transformVectorFast(avatarToSensorMat, -Vectors::UNIT_X)); + + glm::vec3 headPos; + int headIndex = myAvatar->getJointIndex("Head"); + if (headIndex != -1) { + headPos = transformPoint(avatarToSensorMat, myAvatar->getAbsoluteJointTranslationInObjectFrame(headIndex)); + } else { + headPos = transformPoint(myAvatar->getSensorToWorldMatrix(), myAvatar->getHMDSensorPosition()); + } + hipsRot = tiltRot * hipsRot; + hipsPos = headPos + tiltRot * (hipsPos - headPos); + } + + return AnimPose(hipsRot * Quaternions::Y_180, hipsPos); +} + // Called within Model::simulate call, below. void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { const FBXGeometry& geometry = getFBXGeometry(); @@ -124,6 +160,39 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } } + // if hips are not under direct control, estimate the hips position. + if (avatarHeadPose.isValid() && !params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Hips]) { + bool isFlying = (myAvatar->getCharacterController()->getState() == CharacterController::State::Hover || myAvatar->getCharacterController()->computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS); + + if (!_prevHipsValid) { + AnimPose hips = computeHipsInSensorFrame(myAvatar, isFlying); + _prevHips = hips; + } + + AnimPose hips = computeHipsInSensorFrame(myAvatar, isFlying); + + // smootly lerp hips, in sensorframe, with different coeff for horiz and vertical translation. + const float ROT_ALPHA = 0.9f; + const float TRANS_HORIZ_ALPHA = 0.9f; + const float TRANS_VERT_ALPHA = 0.1f; + float hipsY = hips.trans().y; + hips.trans() = lerp(hips.trans(), _prevHips.trans(), TRANS_HORIZ_ALPHA); + hips.trans().y = lerp(hipsY, _prevHips.trans().y, TRANS_VERT_ALPHA); + hips.rot() = safeLerp(hips.rot(), _prevHips.rot(), ROT_ALPHA); + + _prevHips = hips; + _prevHipsValid = true; + + glm::mat4 invRigMat = glm::inverse(myAvatar->getTransform().getMatrix() * Matrices::Y_180); + AnimPose sensorToRigPose(invRigMat * myAvatar->getSensorToWorldMatrix()); + + params.primaryControllerPoses[Rig::PrimaryControllerType_Hips] = sensorToRigPose * hips; + params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Hips] = true; + + } else { + _prevHipsValid = false; + } + params.isTalking = head->getTimeWithoutTalking() <= 1.5f; // pass detailed torso k-dops to rig. diff --git a/interface/src/avatar/MySkeletonModel.h b/interface/src/avatar/MySkeletonModel.h index ad0ae1b8e9..d9f57a439a 100644 --- a/interface/src/avatar/MySkeletonModel.h +++ b/interface/src/avatar/MySkeletonModel.h @@ -25,6 +25,9 @@ public: private: void updateFingers(); + + AnimPose _prevHips; // sensor frame + bool _prevHipsValid { false }; }; #endif // hifi_MySkeletonModel_h From e709561a62bdc752025ff23b7cd15e2832b2bcdc Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 13 Dec 2017 12:14:49 -0700 Subject: [PATCH 34/48] Fix getActiveDevice deadlocks on Linux --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 942c9f71a5..12220a8079 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -679,7 +679,9 @@ void OffscreenQmlSurface::create() { // Setup the update of the QML media components with the current audio output device QObject::connect(&_audioOutputUpdateTimer, &QTimer::timeout, this, [this]() { - new AudioHandler(sharedFromThis(), _currentAudioOutputDevice); + if (_currentAudioOutputDevice.size() > 0) { + new AudioHandler(sharedFromThis(), _currentAudioOutputDevice); + } }); int waitForAudioQmlMs = 200; _audioOutputUpdateTimer.setInterval(waitForAudioQmlMs); @@ -695,6 +697,7 @@ void OffscreenQmlSurface::create() { } void OffscreenQmlSurface::changeAudioOutputDevice(const QString& deviceName, bool isHtmlUpdate) { + _currentAudioOutputDevice = deviceName; if (_rootItem != nullptr && !isHtmlUpdate) { QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection); } @@ -702,18 +705,16 @@ void OffscreenQmlSurface::changeAudioOutputDevice(const QString& deviceName, boo } void OffscreenQmlSurface::forceHtmlAudioOutputDeviceUpdate() { - auto audioIO = DependencyManager::get(); - QString deviceName = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName(); - QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, - Q_ARG(QString, deviceName), Q_ARG(bool, true)); + if (_currentAudioOutputDevice.size() > 0) { + QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, + Q_ARG(QString, _currentAudioOutputDevice), Q_ARG(bool, true)); + } } void OffscreenQmlSurface::forceQmlAudioOutputDeviceUpdate() { if (QThread::currentThread() != qApp->thread()) { QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection); } else { - auto audioIO = DependencyManager::get(); - _currentAudioOutputDevice = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName(); if (_audioOutputUpdateTimer.isActive()) { _audioOutputUpdateTimer.stop(); } From 627ce8ab87ffa252be83fca5f4851d0d0ecd550f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 14 Dec 2017 08:52:21 +1300 Subject: [PATCH 35/48] Enable user connection with "x" key when capslock is on --- scripts/system/makeUserConnection.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index 392ff3c0b5..fedadbb2b4 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -892,12 +892,14 @@ } function keyPressEvent(event) { - if ((event.text === "x") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) { + if ((event.text.toUpperCase() === "X") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl + && !event.isAlt) { updateTriggers(1.0, true, Controller.Standard.RightHand); } } function keyReleaseEvent(event) { - if ((event.text === "x") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) { + if ((event.text.toUpperCase() === "X") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl + && !event.isAlt) { updateTriggers(0.0, true, Controller.Standard.RightHand); } } From b4df1155076b67e7e3895d9056694ef539074833 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 13 Dec 2017 12:53:01 -0800 Subject: [PATCH 36/48] Protect against use of null HazePointer. --- libraries/render-utils/src/DrawHaze.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 4431c1bbc3..c92703fe87 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -169,7 +169,9 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu auto hazeStage = args->_scene->getStage(); if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { model::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); - batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); + if (hazePointer) { + batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); + } } batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer()); @@ -178,7 +180,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu if (lightStage) { model::LightPointer keyLight; keyLight = lightStage->getCurrentKeyLight(); - if (keyLight != nullptr) { + if (keyLight) { batch.setUniformBuffer(HazeEffect_LightingMapSlot, keyLight->getLightSchemaBuffer()); } } From 79f012424477365ca9952dd573891e8091acd60c Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 13 Dec 2017 15:02:03 -0800 Subject: [PATCH 37/48] Protect against use of null HazePointer. --- libraries/render-utils/src/DrawHaze.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index c92703fe87..da07f5bd9b 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -171,6 +171,9 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu model::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); if (hazePointer) { batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); + } else { + // Something is wrong, so just quit Haze + return; } } From e581c66b5696ea27f73cdc5962623ea6542952b9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 13 Dec 2017 16:11:46 -0700 Subject: [PATCH 38/48] added mutex for audio handler --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 4 +++- libraries/ui/src/ui/OffscreenQmlSurface.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 12220a8079..112d70c394 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -680,7 +680,9 @@ void OffscreenQmlSurface::create() { // Setup the update of the QML media components with the current audio output device QObject::connect(&_audioOutputUpdateTimer, &QTimer::timeout, this, [this]() { if (_currentAudioOutputDevice.size() > 0) { - new AudioHandler(sharedFromThis(), _currentAudioOutputDevice); + QMutexLocker lock(&_audioHandlerMutex); + QString audioDeviceName = _currentAudioOutputDevice; + new AudioHandler(sharedFromThis(), audioDeviceName); } }); int waitForAudioQmlMs = 200; diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 4c23c62c12..370ddb4f2f 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -173,6 +173,7 @@ private: uint64_t _lastRenderTime { 0 }; uvec2 _size; + QMutex _audioHandlerMutex; QTimer _audioOutputUpdateTimer; QString _currentAudioOutputDevice; From 483443d2181f74f14b1c8b370afd047e995e6c04 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 13 Dec 2017 17:02:36 -0700 Subject: [PATCH 39/48] No mutex --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 4 +--- libraries/ui/src/ui/OffscreenQmlSurface.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 112d70c394..12220a8079 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -680,9 +680,7 @@ void OffscreenQmlSurface::create() { // Setup the update of the QML media components with the current audio output device QObject::connect(&_audioOutputUpdateTimer, &QTimer::timeout, this, [this]() { if (_currentAudioOutputDevice.size() > 0) { - QMutexLocker lock(&_audioHandlerMutex); - QString audioDeviceName = _currentAudioOutputDevice; - new AudioHandler(sharedFromThis(), audioDeviceName); + new AudioHandler(sharedFromThis(), _currentAudioOutputDevice); } }); int waitForAudioQmlMs = 200; diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 370ddb4f2f..4c23c62c12 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -173,7 +173,6 @@ private: uint64_t _lastRenderTime { 0 }; uvec2 _size; - QMutex _audioHandlerMutex; QTimer _audioOutputUpdateTimer; QString _currentAudioOutputDevice; From 0b598ea9483e5c79713a92ab43c249b14b797b0a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 13 Dec 2017 17:26:23 -0800 Subject: [PATCH 40/48] fix RPATH for oven so it loads things from macdeployqt --- tools/oven/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/oven/CMakeLists.txt b/tools/oven/CMakeLists.txt index 321f81ba8f..5e30b84803 100644 --- a/tools/oven/CMakeLists.txt +++ b/tools/oven/CMakeLists.txt @@ -8,13 +8,14 @@ setup_memory_debugger() if (WIN32) package_libraries_for_deployment() -endif () - -if (UNIX) +elseif (UNIX) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) target_compile_options(PUBLIC oven "-pthread") endif() -endif () +elseif (APPLE) + # Fix up the rpath so macdeployqt works + set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks") +endif() install_beside_console() From 88831ff08a4923480cf18656aa7e7307d3fd82f2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 13 Dec 2017 18:08:39 -0800 Subject: [PATCH 41/48] don't trigger unix step on apple for oven --- tools/oven/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/oven/CMakeLists.txt b/tools/oven/CMakeLists.txt index 5e30b84803..00344179bd 100644 --- a/tools/oven/CMakeLists.txt +++ b/tools/oven/CMakeLists.txt @@ -8,7 +8,7 @@ setup_memory_debugger() if (WIN32) package_libraries_for_deployment() -elseif (UNIX) +elseif (UNIX AND NOT APPLE) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) target_compile_options(PUBLIC oven "-pthread") From 5bc113c81844d9d7753c8214ab67dd6f41f60d7c Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 13 Dec 2017 19:07:23 -0800 Subject: [PATCH 42/48] deleted some debug print statements in ModelEntityItemcpp and deleted else statement that was superfluous --- libraries/entities/src/ModelEntityItem.cpp | 28 ++++------------------ 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 3215ab9dd0..323584c7ee 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -207,12 +207,10 @@ void ModelEntityItem::update(const quint64& now) { // don't reset _lastAnimated here because we need the timestamp from the ModelEntityItem constructor for when the properties were set _currentFrame = currentAnimationProperties.getCurrentFrame(); setAnimationCurrentFrame(_currentFrame); - qCDebug(entities) << "setting first frame 1 " << _currentFrame; } else { _lastAnimated = usecTimestampNow(); _currentFrame = currentAnimationProperties.getFirstFrame(); setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); - qCDebug(entities) << "setting first frame 2" << _currentFrame; } } else if (!currentAnimationProperties.getRunning() && _previousAnimationProperties.getRunning()) { _currentFrame = currentAnimationProperties.getFirstFrame(); @@ -220,31 +218,11 @@ void ModelEntityItem::update(const quint64& now) { } else if (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) { // don't reset _lastAnimated here because the currentFrame was set with the previous setting of _lastAnimated _currentFrame = currentAnimationProperties.getCurrentFrame(); - // qCDebug(entities) << "point 3 " << _currentFrame; } }); _previousAnimationProperties = this->getAnimationProperties(); - } else { - // else the animation properties have not changed. - // if the first frame is less than zero don't do anything. - if (!(getAnimationFirstFrame() < 0)) { - - // if the current frame is less than zero then we have restarted the server. - if (_currentFrame < 0) { - //qCDebug(entities) << "setting first frame 3 " << _currentFrame; - if ((currentAnimationProperties.getCurrentFrame() < currentAnimationProperties.getLastFrame()) && - (currentAnimationProperties.getCurrentFrame() > currentAnimationProperties.getFirstFrame())) { - // _currentFrame = currentAnimationProperties.getCurrentFrame(); - } else { - //qCDebug(entities) << "setting first frame 4 " << _currentFrame; - // _currentFrame = currentAnimationProperties.getFirstFrame(); - // setAnimationCurrentFrame(_currentFrame); - // _lastAnimated = usecTimestampNow(); - } - } - } } if (isAnimatingSomething()) { @@ -263,6 +241,10 @@ bool ModelEntityItem::needsToCallUpdate() const { } void ModelEntityItem::updateFrameCount() { + + if (_currentFrame < 0.0f) { + return; + } if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); @@ -298,7 +280,7 @@ void ModelEntityItem::updateFrameCount() { _currentFrame = getAnimationFirstFrame(); } } - qCDebug(entities) << "in update frame " << _currentFrame; + // qCDebug(entities) << "in update frame " << _currentFrame; setAnimationCurrentFrame(_currentFrame); } From b6a88bbdda6b380f0365e5c2a4a52a1c58690de4 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 14 Dec 2017 10:20:46 -0800 Subject: [PATCH 43/48] Invalid WAV files should always be logged and not played --- libraries/audio/src/Sound.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 476a8d4d88..672c0b69b3 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -96,9 +96,13 @@ void SoundProcessor::run() { QByteArray outputAudioByteArray; int sampleRate = interpretAsWav(rawAudioByteArray, outputAudioByteArray); - if (sampleRate != 0) { - downSample(outputAudioByteArray, sampleRate); + if (sampleRate == 0) { + qCDebug(audio) << "Unsupported WAV file type"; + emit onError(300, "Failed to load sound file, reason: unsupported WAV file type"); + return; } + + downSample(outputAudioByteArray, sampleRate); } else if (fileName.endsWith(RAW_EXTENSION)) { // check if this was a stereo raw file // since it's raw the only way for us to know that is if the file was called .stereo.raw From 74a5f0881ff60159b583f269dcc7d7d74a8f9a12 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 14 Dec 2017 11:56:36 -0800 Subject: [PATCH 44/48] Fix broken Buy buttons on Marketplace --- scripts/system/html/js/marketplacesInject.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 878c3b51f1..b361f1120b 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -265,8 +265,10 @@ }); $('.grid-item').find('#price-or-edit').find('a').each(function() { - $(this).attr('data-href', $(this).attr('href')); - $(this).attr('href', '#'); + if ($(this).attr('href') !== '#') { // Guard necessary because of the AJAX nature of Marketplace site + $(this).attr('data-href', $(this).attr('href')); + $(this).attr('href', '#'); + } cost = $(this).closest('.col-xs-3').find('.item-cost').text(); $(this).closest('.col-xs-3').prev().attr("class", 'col-xs-6'); From 32acc8ad4780f746bbbbb26ca8233fe60230e0e4 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 8 Dec 2017 00:20:35 +0300 Subject: [PATCH 45/48] 8992 Login window is small in tablet --- interface/resources/qml/LoginDialog/LinkAccountBody.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 300bcd46f0..0e2f2a5282 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -52,7 +52,11 @@ Item { targetHeight += hifi.dimensions.contentSpacing.y + additionalInformation.height } - parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)); + var newWidth = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)); + if(!isNaN(newWidth)) { + parent.width = root.width = newWidth; + } + parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + (keyboardEnabled && keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : hifi.dimensions.contentSpacing.y); } From 53e1c57e3b2c4eee5fe08d3b6be3fce9487e148a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 15 Dec 2017 13:46:15 -0700 Subject: [PATCH 46/48] Make lasers scale with avatar --- scripts/system/controllers/controllerDispatcher.js | 4 ++++ scripts/system/controllers/grab.js | 1 + 2 files changed, 5 insertions(+) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 915b3b3680..51f927f224 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -412,6 +412,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}], posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true), hover: true, + scaleWithAvatar: true, distanceScaleEnd: true, hand: LEFT_HAND }); @@ -421,6 +422,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}], posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true), hover: true, + scaleWithAvatar: true, distanceScaleEnd: true, hand: RIGHT_HAND }); @@ -431,6 +433,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true), triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}], hover: true, + scaleWithAvatar: true, distanceScaleEnd: true, hand: LEFT_HAND }); @@ -441,6 +444,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true), triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}], hover: true, + scaleWithAvatar: true, distanceScaleEnd: true, hand: RIGHT_HAND }); diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 7733ca1d28..a51cea67f8 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -269,6 +269,7 @@ function Grabber() { joint: "Mouse", filter: Picks.PICK_ENTITIES, faceAvatar: true, + scaleWithAvatar: true, enabled: true, renderStates: renderStates }); From e2df9e29e20a5944d85817b14180fb137833749f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 15 Dec 2017 16:46:27 -0800 Subject: [PATCH 47/48] Fix for crash in AnimSkeleton::getNumJoints() When initAnimGraph is called it asynchronously loads the Animation graph in the background. If the model url is changed, or the Model is deleted in between the initial load and it's completion, It's possible to access a bad Rig::_animSkeleton pointer. The fix is to hold onto the _animSkeleton pointer via a weak ref. --- libraries/animation/src/Rig.cpp | 13 +++++++++++-- libraries/animation/src/Rig.h | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 78aa1f4ba8..44745c5c2d 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1641,9 +1641,17 @@ void Rig::initAnimGraph(const QUrl& url) { // load the anim graph _animLoader.reset(new AnimNodeLoader(url)); _animLoading = true; - connect(_animLoader.get(), &AnimNodeLoader::success, [this](AnimNode::Pointer nodeIn) { + std::weak_ptr weakSkeletonPtr = _animSkeleton; + connect(_animLoader.get(), &AnimNodeLoader::success, [this, weakSkeletonPtr](AnimNode::Pointer nodeIn) { _animNode = nodeIn; - _animNode->setSkeleton(_animSkeleton); + + // abort load if the previous skeleton was deleted. + auto sharedSkeletonPtr = weakSkeletonPtr.lock(); + if (!sharedSkeletonPtr) { + return; + } + + _animNode->setSkeleton(sharedSkeletonPtr); if (_userAnimState.clipNodeEnum != UserAnimState::None) { // restore the user animation we had before reset. @@ -1651,6 +1659,7 @@ void Rig::initAnimGraph(const QUrl& url) { _userAnimState = { UserAnimState::None, "", 30.0f, false, 0.0f, 0.0f }; overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame); } + // restore the role animations we had before reset. for (auto& roleAnimState : _roleAnimStates) { auto roleState = roleAnimState.second; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index e738ad1c19..1ec4d9527f 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -31,7 +31,7 @@ class AnimInverseKinematics; // Rig instances are reentrant. // However only specific methods thread-safe. Noted below. -class Rig : public QObject, public std::enable_shared_from_this { +class Rig : public QObject { Q_OBJECT public: struct StateHandler { From 5e194102939e558c39ea6c7a63d4ffeb3e527a8d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 17 Dec 2017 15:23:40 +1300 Subject: [PATCH 48/48] Fix handshake satyhing on when release "x" if Ctrl or similar pressed --- scripts/system/makeUserConnection.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index fedadbb2b4..d9003ffeaa 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -898,8 +898,7 @@ } } function keyReleaseEvent(event) { - if ((event.text.toUpperCase() === "X") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl - && !event.isAlt) { + if (event.text.toUpperCase() === "X" && !event.isAutoRepeat) { updateTriggers(0.0, true, Controller.Standard.RightHand); } }