diff options
author | Sarper Akdemir <q.sarperakdemir@gmail.com> | 2020-08-13 03:40:25 +0300 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2020-08-21 16:32:14 +0200 |
commit | b240db92100aec92e0e659c6b404ed1cd0ffcbc3 (patch) | |
tree | e6609a8e946e1f4855b57d51acdf3e5834b5d9b9 /slideshow/source/engine | |
parent | 76f3218b32acbc1b67bd291ac84067c83f6e3c2f (diff) |
make physics animations handle sequential animations correctly
fixes a bug where if there is a sequence of animations between
two physics animations that change the position, rotation or visibility
of a shape - changes are not picked up by the latter physics animation.
Change-Id: Ie8bb8b32588f4c7bf16317b5229adc5b0334d192
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100715
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Tested-by: Jenkins
Diffstat (limited to 'slideshow/source/engine')
-rw-r--r-- | slideshow/source/engine/animationfactory.cxx | 4 | ||||
-rw-r--r-- | slideshow/source/engine/box2dtools.cxx | 181 |
2 files changed, 144 insertions, 41 deletions
diff --git a/slideshow/source/engine/animationfactory.cxx b/slideshow/source/engine/animationfactory.cxx index efc4587356dd..8f6534a30539 100644 --- a/slideshow/source/engine/animationfactory.cxx +++ b/slideshow/source/engine/animationfactory.cxx @@ -323,7 +323,9 @@ namespace slideshow::internal { mpShapeManager->notifyShapeUpdate( mpShape ); if ( mpBox2DWorld->isInitialized() ) - mpBox2DWorld->queueDynamicPositionUpdate( mpShape->getXShape(), rOutPos ); + { + mpBox2DWorld->queueShapePathAnimationUpdate( mpShape->getXShape(), mpAttrLayer ); + } } return true; diff --git a/slideshow/source/engine/box2dtools.cxx b/slideshow/source/engine/box2dtools.cxx index f99e03bcd893..bdeabc12e985 100644 --- a/slideshow/source/engine/box2dtools.cxx +++ b/slideshow/source/engine/box2dtools.cxx @@ -206,6 +206,7 @@ box2DWorld::box2DWorld(const ::basegfx::B2DVector& rSlideSize) , mbHasWorldStepper(false) , mpXShapeToBodyMap() , maShapeParallelUpdateQueue() + , maShapeSequentialUpdate() { } @@ -255,6 +256,13 @@ void box2DWorld::createStaticFrameAroundSlide(const ::basegfx::B2DVector& rSlide pStaticBody->CreateFixture(&aFixtureDef); } +void box2DWorld::setShapePosition(const css::uno::Reference<com::sun::star::drawing::XShape> xShape, + const basegfx::B2DPoint& rOutPos) +{ + Box2DBodySharedPtr pBox2DBody = mpXShapeToBodyMap.find(xShape)->second; + pBox2DBody->setPosition(rOutPos); +} + void box2DWorld::setShapePositionByLinearVelocity( const css::uno::Reference<com::sun::star::drawing::XShape> xShape, const basegfx::B2DPoint& rOutPos, const double fPassedTime) @@ -276,6 +284,13 @@ void box2DWorld::setShapeLinearVelocity( pBox2DBody->setLinearVelocity(rVelocity); } +void box2DWorld::setShapeAngle(const css::uno::Reference<com::sun::star::drawing::XShape> xShape, + const double fAngle) +{ + Box2DBodySharedPtr pBox2DBody = mpXShapeToBodyMap.find(xShape)->second; + pBox2DBody->setAngle(fAngle); +} + void box2DWorld::setShapeAngleByAngularVelocity( const css::uno::Reference<com::sun::star::drawing::XShape> xShape, const double fAngle, const double fPassedTime) @@ -307,41 +322,75 @@ void box2DWorld::setShapeCollision( void box2DWorld::processUpdateQueue(const double fPassedTime) { - while (!maShapeParallelUpdateQueue.empty()) + if (maShapeSequentialUpdate.empty()) { - Box2DDynamicUpdateInformation& aQueueElement = maShapeParallelUpdateQueue.front(); - - if (aQueueElement.mnDelayForSteps > 0) + while (!maShapeParallelUpdateQueue.empty()) { - // it was queued as a delayed action, skip it, don't pop - aQueueElement.mnDelayForSteps--; + Box2DDynamicUpdateInformation& aQueueElement = maShapeParallelUpdateQueue.front(); + + if (aQueueElement.mnDelayForSteps > 0) + { + // it was queued as a delayed action, skip it, don't pop + aQueueElement.mnDelayForSteps--; + } + else + { + switch (aQueueElement.meUpdateType) + { + default: + case BOX2D_UPDATE_POSITION: + setShapePositionByLinearVelocity(aQueueElement.mxShape, + aQueueElement.maPosition, fPassedTime); + break; + case BOX2D_UPDATE_ANGLE: + setShapeAngleByAngularVelocity(aQueueElement.mxShape, aQueueElement.mfAngle, + fPassedTime); + break; + case BOX2D_UPDATE_SIZE: + break; + case BOX2D_UPDATE_VISIBILITY: + setShapeCollision(aQueueElement.mxShape, aQueueElement.mbVisibility); + break; + case BOX2D_UPDATE_LINEAR_VELOCITY: + setShapeLinearVelocity(aQueueElement.mxShape, aQueueElement.maVelocity); + break; + case BOX2D_UPDATE_ANGULAR_VELOCITY: + setShapeAngularVelocity(aQueueElement.mxShape, + aQueueElement.mfAngularVelocity); + } + maShapeParallelUpdateQueue.pop(); + } } - else + } + else + { + // clear the Parallel Update Queue since the updates in it + // are not relevant now - if there's any + maShapeParallelUpdateQueue = {}; + + for (auto& aIt : maShapeSequentialUpdate) { - switch (aQueueElement.meUpdateType) + const css::uno::Reference<css::drawing::XShape>& xShape = aIt.first.first; + const box2DNonsimulatedShapeUpdateType eUpdateType = aIt.first.second; + const Box2DStaticUpdateInformation& rUpdateInformation = aIt.second; + + switch (eUpdateType) { default: case BOX2D_UPDATE_POSITION: - setShapePositionByLinearVelocity(aQueueElement.mxShape, - aQueueElement.maPosition, fPassedTime); + setShapePosition(xShape, rUpdateInformation.maPosition); break; case BOX2D_UPDATE_ANGLE: - setShapeAngleByAngularVelocity(aQueueElement.mxShape, aQueueElement.mfAngle, - fPassedTime); - break; - case BOX2D_UPDATE_SIZE: + setShapeAngle(xShape, rUpdateInformation.mfAngle); break; case BOX2D_UPDATE_VISIBILITY: - setShapeCollision(aQueueElement.mxShape, aQueueElement.mbVisibility); - break; - case BOX2D_UPDATE_LINEAR_VELOCITY: - setShapeLinearVelocity(aQueueElement.mxShape, aQueueElement.maVelocity); + setShapeCollision(xShape, rUpdateInformation.mbVisibility); break; - case BOX2D_UPDATE_ANGULAR_VELOCITY: - setShapeAngularVelocity(aQueueElement.mxShape, aQueueElement.mfAngularVelocity); } - maShapeParallelUpdateQueue.pop(); } + + // After applying all required updates empty map + maShapeSequentialUpdate.clear(); } } @@ -389,9 +438,10 @@ void box2DWorld::queueDynamicPositionUpdate( void box2DWorld::queueLinearVelocityUpdate( const css::uno::Reference<com::sun::star::drawing::XShape>& xShape, - const basegfx::B2DVector& rVelocity) + const basegfx::B2DVector& rVelocity, const int nDelayForSteps) { - Box2DDynamicUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_LINEAR_VELOCITY, 1 }; + Box2DDynamicUpdateInformation aQueueElement + = { xShape, {}, BOX2D_UPDATE_LINEAR_VELOCITY, nDelayForSteps }; aQueueElement.maVelocity = rVelocity; maShapeParallelUpdateQueue.push(aQueueElement); } @@ -406,9 +456,10 @@ void box2DWorld::queueDynamicRotationUpdate( void box2DWorld::queueAngularVelocityUpdate( const css::uno::Reference<com::sun::star::drawing::XShape>& xShape, - const double fAngularVelocity) + const double fAngularVelocity, const int nDelayForSteps) { - Box2DDynamicUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_ANGULAR_VELOCITY, 1 }; + Box2DDynamicUpdateInformation aQueueElement + = { xShape, {}, BOX2D_UPDATE_ANGULAR_VELOCITY, nDelayForSteps }; aQueueElement.mfAngularVelocity = fAngularVelocity; maShapeParallelUpdateQueue.push(aQueueElement); } @@ -421,25 +472,64 @@ void box2DWorld::queueShapeVisibilityUpdate( maShapeParallelUpdateQueue.push(aQueueElement); } +void box2DWorld::queueShapePathAnimationUpdate( + const css::uno::Reference<com::sun::star::drawing::XShape>& xShape, + const slideshow::internal::ShapeAttributeLayerSharedPtr& pAttrLayer) +{ + // Workaround for PathAnimations since they do not have their own AttributeType + // - using PosX makes it register a DynamicPositionUpdate - + queueShapeAnimationUpdate(xShape, pAttrLayer, slideshow::internal::AttributeType::PosX); +} + void box2DWorld::queueShapeAnimationUpdate( const css::uno::Reference<com::sun::star::drawing::XShape>& xShape, const slideshow::internal::ShapeAttributeLayerSharedPtr& pAttrLayer, const slideshow::internal::AttributeType eAttrType) { - switch (eAttrType) + if (mbHasWorldStepper) // if there's a physics animation going on { - case slideshow::internal::AttributeType::Visibility: - queueShapeVisibilityUpdate(xShape, pAttrLayer->getVisibility()); - return; - case slideshow::internal::AttributeType::Rotate: - queueDynamicRotationUpdate(xShape, pAttrLayer->getRotationAngle()); - return; - case slideshow::internal::AttributeType::PosX: - case slideshow::internal::AttributeType::PosY: - queueDynamicPositionUpdate(xShape, { pAttrLayer->getPosX(), pAttrLayer->getPosY() }); - return; - default: - return; + switch (eAttrType) + { + case slideshow::internal::AttributeType::Visibility: + queueShapeVisibilityUpdate(xShape, pAttrLayer->getVisibility()); + return; + case slideshow::internal::AttributeType::Rotate: + queueDynamicRotationUpdate(xShape, pAttrLayer->getRotationAngle()); + return; + case slideshow::internal::AttributeType::PosX: + case slideshow::internal::AttributeType::PosY: + queueDynamicPositionUpdate(xShape, + { pAttrLayer->getPosX(), pAttrLayer->getPosY() }); + return; + default: + return; + } + } + else + { + Box2DStaticUpdateInformation aStaticUpdateInformation; + switch (eAttrType) + { + case slideshow::internal::AttributeType::Visibility: + aStaticUpdateInformation.mbVisibility = pAttrLayer->getVisibility(); + maShapeSequentialUpdate[std::make_pair(xShape, BOX2D_UPDATE_VISIBILITY)] + = aStaticUpdateInformation; + return; + case slideshow::internal::AttributeType::Rotate: + aStaticUpdateInformation.mfAngle = pAttrLayer->getRotationAngle(); + maShapeSequentialUpdate[std::make_pair(xShape, BOX2D_UPDATE_ANGLE)] + = aStaticUpdateInformation; + return; + case slideshow::internal::AttributeType::PosX: + case slideshow::internal::AttributeType::PosY: + aStaticUpdateInformation.maPosition + = basegfx::B2DPoint(pAttrLayer->getPosX(), pAttrLayer->getPosY()); + maShapeSequentialUpdate[std::make_pair(xShape, BOX2D_UPDATE_POSITION)] + = aStaticUpdateInformation; + return; + default: + return; + } } } @@ -450,11 +540,11 @@ void box2DWorld::queueShapeAnimationEndUpdate( switch (eAttrType) { case slideshow::internal::AttributeType::Rotate: - queueAngularVelocityUpdate(xShape, 0.0f); + queueAngularVelocityUpdate(xShape, 0.0, 1); return; case slideshow::internal::AttributeType::PosX: case slideshow::internal::AttributeType::PosY: - queueLinearVelocityUpdate(xShape, { 0, 0 }); + queueLinearVelocityUpdate(xShape, { 0, 0 }, 1); return; default: return; @@ -617,6 +707,12 @@ box2DBody::box2DBody(std::shared_ptr<b2Body> pBox2DBody, double fScaleFactor) return ::basegfx::B2DPoint(fX, fY); } +void box2DBody::setPosition(const basegfx::B2DPoint& rPos) +{ + mpBox2DBody->SetTransform(convertB2DPointToBox2DVec2(rPos, mfScaleFactor), + mpBox2DBody->GetAngle()); +} + void box2DBody::setPositionByLinearVelocity(const basegfx::B2DPoint& rDesiredPos, const double fPassedTime) { @@ -675,6 +771,11 @@ double box2DBody::getAngle() return ::basegfx::rad2deg(-fAngle); } +void box2DBody::setAngle(const double fAngle) +{ + mpBox2DBody->SetTransform(mpBox2DBody->GetPosition(), ::basegfx::deg2rad(-fAngle)); +} + void box2DBody::setType(box2DBodyType eType) { mpBox2DBody->SetType(getBox2DInternalBodyType(eType)); |