[Libreoffice-commits] core.git: Branch 'private/quwex/gsoc-box2d-experimental' - 3 commits - animations/source include/xmloff offapi/com offapi/UnoApi_offapi.mk slideshow/source xmloff/source

Sarper Akdemir (via logerrit) logerrit at kemper.freedesktop.org
Fri Aug 14 00:18:25 UTC 2020


Rebased ref, commits from common ancestor:
commit b371cdccacdb9a957d0a3c46e7e64168be356dcc
Author:     Sarper Akdemir <q.sarperakdemir at gmail.com>
AuthorDate: Fri Aug 14 01:18:14 2020 +0300
Commit:     Sarper Akdemir <q.sarperakdemir at gmail.com>
CommitDate: Fri Aug 14 03:17:30 2020 +0300

    wip add bounciness velocity and density options to physics animations
    
    Change-Id: Ifaba785e82c8ee17be00711a3e7a75257e7704ae

diff --git a/animations/source/animcore/animcore.cxx b/animations/source/animcore/animcore.cxx
index 88e42772936a..107353cf327a 100644
--- a/animations/source/animcore/animcore.cxx
+++ b/animations/source/animcore/animcore.cxx
@@ -24,6 +24,7 @@
 #include <com/sun/star/animations/XAnimateColor.hpp>
 #include <com/sun/star/animations/XAnimateSet.hpp>
 #include <com/sun/star/animations/XAnimateMotion.hpp>
+#include <com/sun/star/animations/XAnimatePhysics.hpp>
 #include <com/sun/star/animations/XAnimateTransform.hpp>
 #include <com/sun/star/animations/XParallelTimeContainer.hpp>
 #include <com/sun/star/animations/XTransitionFilter.hpp>
@@ -104,6 +105,7 @@ namespace animcore
 namespace {
 
 class AnimationNodeBase :   public XAnimateMotion,
+                            public XAnimatePhysics,
                             public XAnimateColor,
                             public XTransitionFilter,
                             public XAnimateSet,
@@ -224,6 +226,16 @@ public:
     virtual Any SAL_CALL getOrigin() override;
     virtual void SAL_CALL setOrigin( const Any& _origin ) override;
 
+    // XAnimatePhysics
+    virtual Any SAL_CALL getStartVelocityX() override;
+    virtual void SAL_CALL setStartVelocityX( const Any& _startvelocityx ) override;
+    virtual Any SAL_CALL getStartVelocityY() override;
+    virtual void SAL_CALL setStartVelocityY( const Any& _startvelocityy ) override;
+    virtual Any SAL_CALL getDensity() override;
+    virtual void SAL_CALL setDensity( const Any& _density ) override;
+    virtual Any SAL_CALL getBounciness() override;
+    virtual void SAL_CALL setBounciness( const Any& _bounciness ) override;
+
     // XAnimateTransform
     virtual sal_Int16 SAL_CALL getTransformType() override;
     virtual void SAL_CALL setTransformType( sal_Int16 _transformtype ) override;
@@ -322,6 +334,9 @@ private:
     // attributes for XAnimateMotion
     Any maPath, maOrigin;
 
+    // attributes for XAnimatePhysics
+    Any maStartVelocityX, maStartVelocityY, maDensity, maBounciness;
+
     // attributes for XAnimateTransform
     sal_Int16 mnTransformType;
 
@@ -671,8 +686,8 @@ Any SAL_CALL AnimationNode::queryInterface( const Type& aType )
         case AnimationNodeType::ANIMATEPHYSICS:
             aRet = ::cppu::queryInterface(
                 aType,
-                static_cast< XAnimate * >( static_cast< XAnimateMotion * >(this) ),
-                static_cast< XAnimateMotion * >( this ) );
+                static_cast< XAnimate * >( static_cast< XAnimatePhysics * >(this) ),
+                static_cast< XAnimatePhysics * >( this ) );
             break;
         case AnimationNodeType::ANIMATECOLOR:
             aRet = ::cppu::queryInterface(
@@ -767,7 +782,7 @@ void AnimationNode::initTypeProvider( sal_Int16 nNodeType ) throw()
         pTypeAr[nPos++] = cppu::UnoType<XAnimateMotion>::get();
         break;
     case AnimationNodeType::ANIMATEPHYSICS:
-        pTypeAr[nPos++] = cppu::UnoType<XAnimateMotion>::get();
+        pTypeAr[nPos++] = cppu::UnoType<XAnimatePhysics>::get();
         break;
     case AnimationNodeType::ANIMATECOLOR:
         pTypeAr[nPos++] = cppu::UnoType<XAnimateColor>::get();
@@ -1584,6 +1599,72 @@ void SAL_CALL AnimationNode::setOrigin( const Any& _origin )
     fireChangeListener();
 }
 
+// XAnimatePhysics
+Any SAL_CALL AnimationNode::getStartVelocityX()
+{
+    Guard< Mutex > aGuard( maMutex );
+    return maStartVelocityX;
+}
+
+
+// XAnimatePhysics
+void SAL_CALL AnimationNode::setStartVelocityX( const Any& _startvelocityx )
+{
+    Guard< Mutex > aGuard( maMutex );
+    maStartVelocityX = _startvelocityx;
+    fireChangeListener();
+}
+
+// XAnimatePhysics
+Any SAL_CALL AnimationNode::getStartVelocityY()
+{
+    Guard< Mutex > aGuard( maMutex );
+    return maStartVelocityY;
+}
+
+
+// XAnimatePhysics
+void SAL_CALL AnimationNode::setStartVelocityY( const Any& _startvelocityy )
+{
+    Guard< Mutex > aGuard( maMutex );
+    maStartVelocityY = _startvelocityy;
+    fireChangeListener();
+}
+
+
+// XAnimatePhysics
+Any SAL_CALL AnimationNode::getDensity()
+{
+    Guard< Mutex > aGuard( maMutex );
+    return maDensity;
+}
+
+
+// XAnimatePhysics
+void SAL_CALL AnimationNode::setDensity( const Any& _density )
+{
+    Guard< Mutex > aGuard( maMutex );
+    maDensity = _density;
+    fireChangeListener();
+}
+
+
+// XAnimatePhysics
+Any SAL_CALL AnimationNode::getBounciness()
+{
+    Guard< Mutex > aGuard( maMutex );
+    return maBounciness;
+}
+
+
+// XAnimatePhysics
+void SAL_CALL AnimationNode::setBounciness( const Any& _bounciness )
+{
+    Guard< Mutex > aGuard( maMutex );
+    maBounciness = _bounciness;
+    fireChangeListener();
+}
+
 
 // XAnimateTransform
 sal_Int16 SAL_CALL AnimationNode::getTransformType()
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index ffa9206d4f44..13fd270d5fb9 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1445,6 +1445,10 @@ namespace xmloff::token {
         XML_PERSPECTIVE,
         XML_PHDTHESIS,
         XML_PHONG,
+        XML_PHYSICS_ANIMATION_START_VELOCITY_X,
+        XML_PHYSICS_ANIMATION_START_VELOCITY_Y,
+        XML_PHYSICS_ANIMATION_DENSITY,
+        XML_PHYSICS_ANIMATION_BOUNCINESS,
         XML_PIE_OFFSET,
         XML_PLACEHOLDER,
         XML_PLACEHOLDER_TYPE,
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 8d78a3c2f696..50f9e87c9dc2 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -1680,6 +1680,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/animations,\
 	XAnimate \
 	XAnimateColor \
 	XAnimateMotion \
+	XAnimatePhysics \
 	XAnimateSet \
 	XAnimateTransform \
 	XAnimationListener \
diff --git a/offapi/com/sun/star/animations/XAnimatePhysics.idl b/offapi/com/sun/star/animations/XAnimatePhysics.idl
new file mode 100644
index 000000000000..0b644bcd6528
--- /dev/null
+++ b/offapi/com/sun/star/animations/XAnimatePhysics.idl
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#ifndef __com_sun_star_animations_XAnimatePhysics_idl__
+#define __com_sun_star_animations_XAnimatePhysics_idl__
+
+#include <com/sun/star/animations/XAnimate.idl>
+
+
+ module com {  module sun {  module star {  module animations {
+
+
+/** Interface for physics animation.
+*/
+interface XAnimatePhysics : XAnimate
+{
+    /** Specifies an optional starting velocity
+     */
+    [attribute] any StartVelocityX;
+
+    /** Specifies an optional starting velocity
+     */
+    [attribute] any StartVelocityY;
+
+    /** Specifies an optional density value
+    */
+    [attribute] any Density;
+
+    /** Specifies an optional bounciness value
+
+        Takes a value between (0,1], 1 being no energy loss on collisions
+        Has a default value of 0.1
+    */
+    [attribute] any Bounciness;
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/slideshow/source/engine/animationfactory.cxx b/slideshow/source/engine/animationfactory.cxx
index d6198439b327..920dee35f0eb 100644
--- a/slideshow/source/engine/animationfactory.cxx
+++ b/slideshow/source/engine/animationfactory.cxx
@@ -362,6 +362,9 @@ namespace slideshow::internal
                                     const double                 fDuration,
                                     const ShapeManagerSharedPtr& rShapeManager,
                                     const ::basegfx::B2DVector&  rSlideSize,
+                                    const ::basegfx::B2DVector&  rStartVelocity,
+                                    const double                 fDensity,
+                                    const double                 fBounciness,
                                     int                          nFlags ) :
                     mpShape(),
                     mpAttrLayer(),
@@ -372,6 +375,9 @@ namespace slideshow::internal
                     mpBox2DBody(),
                     mpBox2DWorld( pBox2DWorld ),
                     mfDuration(fDuration),
+                    maStartVelocity(rStartVelocity),
+                    mfDensity(fDensity),
+                    mfBounciness(fBounciness),
                     mfPreviousElapsedTime(0.00f),
                     mbIsBox2dWorldStepper(false)
                 {
@@ -411,7 +417,7 @@ namespace slideshow::internal
                     ENSURE_OR_THROW( rAttrLayer,
                                      "PhysicsAnimation::start(): Invalid attribute layer" );
 
-                    mpBox2DBody = mpBox2DWorld->makeShapeDynamic( rShape );
+                    mpBox2DBody = mpBox2DWorld->makeShapeDynamic( rShape->getXShape(), maStartVelocity, mfDensity, mfBounciness );
 
                     if( !mbAnimationStarted )
                     {
@@ -495,6 +501,9 @@ namespace slideshow::internal
                 box2d::utils::Box2DBodySharedPtr   mpBox2DBody;
                 box2d::utils::Box2DWorldSharedPtr  mpBox2DWorld;
                 double                             mfDuration;
+                const ::basegfx::B2DVector         maStartVelocity;
+                const double                       mfDensity;
+                const double                       mfBounciness;
                 double                             mfPreviousElapsedTime;
                 bool                               mbIsBox2dWorldStepper;
             };
@@ -1468,11 +1477,17 @@ namespace slideshow::internal
                                                                               const double                      fDuration,
                                                                               const ShapeManagerSharedPtr&      rShapeManager,
                                                                               const ::basegfx::B2DVector&       rSlideSize,
+                                                                              const ::basegfx::B2DVector&       rStartVelocity,
+                                                                              const double                      fDensity,
+                                                                              const double                      fBounciness,
                                                                               int                               nFlags )
         {
             return std::make_shared<PhysicsAnimation>( pBox2DWorld, fDuration,
                                    rShapeManager,
                                    rSlideSize,
+                                   rStartVelocity,
+                                   fDensity,
+                                   fBounciness,
                                    nFlags );
         }
 
diff --git a/slideshow/source/engine/animationnodes/animationphysicsnode.cxx b/slideshow/source/engine/animationnodes/animationphysicsnode.cxx
index 28e247c30d6c..c056d999f850 100644
--- a/slideshow/source/engine/animationnodes/animationphysicsnode.cxx
+++ b/slideshow/source/engine/animationnodes/animationphysicsnode.cxx
@@ -19,6 +19,12 @@
 
 #include "animationphysicsnode.hxx"
 #include <animationfactory.hxx>
+#include <o3tl/any.hxx>
+
+#define DEFAULT_START_VELOCITY_X 0.0
+#define DEFAULT_START_VELOCITY_Y 0.0
+#define DEFAULT_DENSITY 1
+#define DEFAULT_BOUNCINESS 0.1
 
 namespace slideshow::internal
 {
@@ -34,12 +40,41 @@ AnimationActivitySharedPtr AnimationPhysicsNode::createActivity() const
     ENSURE_OR_THROW((mxPhysicsMotionNode->getDuration() >>= fDuration),
                     "Couldn't get the animation duration.");
 
+    ::css::uno::Any aTemp;
+    double fStartVelocityX;
+    aTemp = mxPhysicsMotionNode->getStartVelocityX();
+    if (aTemp.hasValue())
+        aTemp >>= fStartVelocityX;
+    else
+        fStartVelocityX = DEFAULT_START_VELOCITY_X;
+
+    double fStartVelocityY;
+    aTemp = mxPhysicsMotionNode->getStartVelocityY();
+    if (aTemp.hasValue())
+        aTemp >>= fStartVelocityY;
+    else
+        fStartVelocityY = DEFAULT_START_VELOCITY_Y;
+
+    double fDensity;
+    aTemp = mxPhysicsMotionNode->getDensity();
+    if (aTemp.hasValue())
+        aTemp >>= fDensity;
+    else
+        fDensity = DEFAULT_DENSITY;
+
+    double fBounciness;
+    aTemp = mxPhysicsMotionNode->getBounciness();
+    if (aTemp.hasValue())
+        aTemp >>= fBounciness;
+    else
+        fBounciness = DEFAULT_BOUNCINESS;
+
     ActivitiesFactory::CommonParameters const aParms(fillCommonParameters());
     return ActivitiesFactory::createSimpleActivity(
         aParms,
-        AnimationFactory::createPhysicsAnimation(getContext().mpBox2DWorld, fDuration,
-                                                 getContext().mpSubsettableShapeManager,
-                                                 getSlideSize(), 0),
+        AnimationFactory::createPhysicsAnimation(
+            getContext().mpBox2DWorld, fDuration, getContext().mpSubsettableShapeManager,
+            getSlideSize(), { fStartVelocityX, fStartVelocityY }, fDensity, fBounciness, 0),
         true);
 }
 
diff --git a/slideshow/source/engine/animationnodes/animationphysicsnode.hxx b/slideshow/source/engine/animationnodes/animationphysicsnode.hxx
index 15ac8911e916..5c82a7c5b164 100644
--- a/slideshow/source/engine/animationnodes/animationphysicsnode.hxx
+++ b/slideshow/source/engine/animationnodes/animationphysicsnode.hxx
@@ -20,6 +20,7 @@
 
 #include "animationbasenode.hxx"
 #include <com/sun/star/animations/XAnimateMotion.hpp>
+#include <com/sun/star/animations/XAnimatePhysics.hpp>
 
 namespace slideshow
 {
@@ -45,7 +46,7 @@ protected:
 private:
     virtual AnimationActivitySharedPtr createActivity() const override;
 
-    css::uno::Reference<css::animations::XAnimateMotion> mxPhysicsMotionNode;
+    css::uno::Reference<css::animations::XAnimatePhysics> mxPhysicsMotionNode;
 };
 
 } // namespace internal
diff --git a/slideshow/source/engine/box2dtools.cxx b/slideshow/source/engine/box2dtools.cxx
index 0dbc7be63f2a..f22d1c6f3e86 100644
--- a/slideshow/source/engine/box2dtools.cxx
+++ b/slideshow/source/engine/box2dtools.cxx
@@ -20,6 +20,7 @@
 #include <svx/svdoashp.hxx>
 
 #define BOX2D_SLIDE_SIZE_IN_METERS 100.00f
+#define DEFAULT_BOUNCINESS 0.1
 
 namespace box2d::utils
 {
@@ -549,6 +550,13 @@ void box2DWorld::queueShapeAnimationEndUpdate(
     }
 }
 
+void box2DWorld::alertAnimationEndForShape(const slideshow::internal::ShapeSharedPtr& pShape)
+{
+    Box2DBodySharedPtr pBox2DBody = mpXShapeToBodyMap.find(pShape->getXShape())->second;
+    makeBodyStatic(pBox2DBody);
+    pBox2DBody->setRestitution(DEFAULT_BOUNCINESS);
+}
+
 void box2DWorld::step(const float fTimeStep, const int nVelocityIterations,
                       const int nPositionIterations)
 {
@@ -584,10 +592,15 @@ bool box2DWorld::isInitialized()
         return false;
 }
 
-Box2DBodySharedPtr box2DWorld::makeShapeDynamic(const slideshow::internal::ShapeSharedPtr& pShape)
+Box2DBodySharedPtr
+box2DWorld::makeShapeDynamic(const css::uno::Reference<css::drawing::XShape>& xShape,
+                             const basegfx::B2DVector& rStartVelocity, const double fDensity,
+                             const double fBounciness)
 {
     assert(mpBox2DWorld);
-    Box2DBodySharedPtr pBox2DBody = mpXShapeToBodyMap.find(pShape->getXShape())->second;
+    Box2DBodySharedPtr pBox2DBody = mpXShapeToBodyMap.find(xShape)->second;
+    pBox2DBody->setDensityAndRestitution(fDensity, fBounciness);
+    queueLinearVelocityUpdate(xShape, rStartVelocity);
     return makeBodyDynamic(pBox2DBody);
 }
 
@@ -776,6 +789,25 @@ void box2DBody::setAngle(double fAngle)
     mpBox2DBody->SetTransform(mpBox2DBody->GetPosition(), ::basegfx::deg2rad(-fAngle));
 }
 
+void box2DBody::setDensityAndRestitution(const double fDensity, const double fRestitution)
+{
+    for (b2Fixture* pFixture = mpBox2DBody->GetFixtureList(); pFixture;
+         pFixture = pFixture->GetNext())
+    {
+        pFixture->SetDensity(static_cast<float>(fDensity));
+        pFixture->SetRestitution(static_cast<float>(fRestitution));
+    }
+}
+
+void box2DBody::setRestitution(const double fRestitution)
+{
+    for (b2Fixture* pFixture = mpBox2DBody->GetFixtureList(); pFixture;
+         pFixture = pFixture->GetNext())
+    {
+        pFixture->SetRestitution(static_cast<float>(fRestitution));
+    }
+}
+
 void box2DBody::setType(box2DBodyType eType)
 {
     mpBox2DBody->SetType(getBox2DInternalBodyType(eType));
diff --git a/slideshow/source/inc/animationfactory.hxx b/slideshow/source/inc/animationfactory.hxx
index 0517a7a79ee4..853546705cc7 100644
--- a/slideshow/source/inc/animationfactory.hxx
+++ b/slideshow/source/inc/animationfactory.hxx
@@ -139,6 +139,9 @@ namespace slideshow
                                                                const double                            fDuration,
                                                                const ShapeManagerSharedPtr&            rShapeManager,
                                                                const ::basegfx::B2DVector&             rSlideSize,
+                                                               const ::basegfx::B2DVector&             rStartVelocity,
+                                                               const double                            fDensity,
+                                                               const double                            fBounciness,
                                                                int                                     nFlags );
         }
     }
diff --git a/slideshow/source/inc/box2dtools.hxx b/slideshow/source/inc/box2dtools.hxx
index e5d9c94577e5..09259e790479 100644
--- a/slideshow/source/inc/box2dtools.hxx
+++ b/slideshow/source/inc/box2dtools.hxx
@@ -221,7 +221,9 @@ public:
         @param pShape
         Pointer to the shape to alter the corresponding Box2D body of
      */
-    Box2DBodySharedPtr makeShapeDynamic(const slideshow::internal::ShapeSharedPtr& pShape);
+    Box2DBodySharedPtr makeShapeDynamic(const css::uno::Reference<css::drawing::XShape>& xShape,
+                                        const basegfx::B2DVector& rStartVelocity,
+                                        const double fDensity, const double fBounciness);
 
     /** Make the Box2D body a dynamic one
 
@@ -285,6 +287,8 @@ public:
 
     void queueShapeAnimationEndUpdate(const css::uno::Reference<css::drawing::XShape>& xShape,
                                       const slideshow::internal::AttributeType eAttrType);
+
+    void alertAnimationEndForShape(const slideshow::internal::ShapeSharedPtr& pShape);
 };
 
 /// Class that manages a single box2D Body
@@ -345,6 +349,10 @@ public:
 
     void setAngle(double fAngle);
 
+    void setDensityAndRestitution(const double fDensity, const double fRestitution);
+
+    void setRestitution(const double fRestitution);
+
     /// Set type of the body
     void setType(box2DBodyType eType);
 
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 03e777185d0e..c9045ca3036f 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1451,6 +1451,10 @@ namespace xmloff::token {
         TOKEN( "perspective",                     XML_PERSPECTIVE ),
         TOKEN( "phdthesis",                       XML_PHDTHESIS ),
         TOKEN( "phong",                           XML_PHONG ),
+        TOKEN( "velocity-x",                      XML_PHYSICS_ANIMATION_START_VELOCITY_X ),
+        TOKEN( "velocity-y",                      XML_PHYSICS_ANIMATION_START_VELOCITY_Y ),
+        TOKEN( "density",                         XML_PHYSICS_ANIMATION_DENSITY ),
+        TOKEN( "bounciness",                      XML_PHYSICS_ANIMATION_BOUNCINESS ),
         TOKEN( "pie-offset",                      XML_PIE_OFFSET ),
         TOKEN( "placeholder",                     XML_PLACEHOLDER ),
         TOKEN( "placeholder-type",                XML_PLACEHOLDER_TYPE ),
diff --git a/xmloff/source/draw/animationexport.cxx b/xmloff/source/draw/animationexport.cxx
index f217e46a709d..13f296e57500 100644
--- a/xmloff/source/draw/animationexport.cxx
+++ b/xmloff/source/draw/animationexport.cxx
@@ -23,6 +23,7 @@
 #include <com/sun/star/animations/Timing.hpp>
 #include <com/sun/star/animations/Event.hpp>
 #include <com/sun/star/animations/XAnimateMotion.hpp>
+#include <com/sun/star/animations/XAnimatePhysics.hpp>
 #include <com/sun/star/animations/XAnimateTransform.hpp>
 #include <com/sun/star/animations/XTransitionFilter.hpp>
 #include <com/sun/star/animations/XIterateContainer.hpp>
@@ -1243,9 +1244,40 @@ void AnimationsExporterImpl::exportAnimate( const Reference< XAnimate >& xAnimat
         case AnimationNodeType::ANIMATEPHYSICS:
         {
             eElementToken = XML_ANIMATEPHYSICS;
+            double fTemp;
 
-            Reference< XAnimateMotion > xAnimateMotion( xAnimate, UNO_QUERY_THROW );
-            aTemp = xAnimateMotion->getOrigin();
+            Reference< XAnimatePhysics > xAnimatePhysics( xAnimate, UNO_QUERY_THROW );
+            aTemp = xAnimatePhysics->getStartVelocityX();
+            if( aTemp.hasValue() )
+            {
+                aTemp >>= fTemp;
+                ::sax::Converter::convertDouble( sTmp, fTemp );
+                mxExport->AddAttribute( XML_NAMESPACE_LO_EXT, XML_PHYSICS_ANIMATION_START_VELOCITY_X, sTmp.makeStringAndClear() );
+            }
+
+            aTemp = xAnimatePhysics->getStartVelocityY();
+            if( aTemp.hasValue() )
+            {
+                aTemp >>= fTemp;
+                ::sax::Converter::convertDouble( sTmp, fTemp );
+                mxExport->AddAttribute( XML_NAMESPACE_LO_EXT, XML_PHYSICS_ANIMATION_START_VELOCITY_Y, sTmp.makeStringAndClear() );
+            }
+
+            aTemp = xAnimatePhysics->getDensity();
+            if( aTemp.hasValue() )
+            {
+                aTemp >>= fTemp;
+                ::sax::Converter::convertDouble( sTmp, fTemp );
+                mxExport->AddAttribute( XML_NAMESPACE_LO_EXT, XML_PHYSICS_ANIMATION_DENSITY, sTmp.makeStringAndClear() );
+            }
+
+            aTemp = xAnimatePhysics->getBounciness();
+            if( aTemp.hasValue() )
+            {
+                aTemp >>= fTemp;
+                ::sax::Converter::convertDouble( sTmp, fTemp );
+                mxExport->AddAttribute( XML_NAMESPACE_LO_EXT, XML_PHYSICS_ANIMATION_BOUNCINESS, sTmp.makeStringAndClear() );
+            }
         }
         break;
 
diff --git a/xmloff/source/draw/animationimport.cxx b/xmloff/source/draw/animationimport.cxx
index 52e020e8f939..ad34a6ad22ee 100644
--- a/xmloff/source/draw/animationimport.cxx
+++ b/xmloff/source/draw/animationimport.cxx
@@ -27,6 +27,7 @@
 #include <com/sun/star/animations/SequenceTimeContainer.hpp>
 #include <com/sun/star/animations/XIterateContainer.hpp>
 #include <com/sun/star/animations/XAnimateMotion.hpp>
+#include <com/sun/star/animations/XAnimatePhysics.hpp>
 #include <com/sun/star/animations/XAnimateColor.hpp>
 #include <com/sun/star/animations/XAnimateTransform.hpp>
 #include <com/sun/star/animations/XTransitionFilter.hpp>
@@ -923,6 +924,38 @@ void AnimationNodeContext::init_node(  const css::uno::Reference< css::xml::sax:
             }
             break;
 
+            case XML_ELEMENT(LO_EXT, XML_PHYSICS_ANIMATION_START_VELOCITY_X):
+            {
+                Reference< XAnimatePhysics > xAnimatePhysics( mxNode, UNO_QUERY );
+                if( xAnimatePhysics.is() )
+                    xAnimatePhysics->setStartVelocityX( makeAny(rValue.toDouble()) );
+            }
+            break;
+
+            case XML_ELEMENT(LO_EXT, XML_PHYSICS_ANIMATION_START_VELOCITY_Y):
+            {
+                Reference< XAnimatePhysics > xAnimatePhysics( mxNode, UNO_QUERY );
+                if( xAnimatePhysics.is() )
+                    xAnimatePhysics->setStartVelocityY( makeAny(rValue.toDouble()) );
+            }
+            break;
+
+            case XML_ELEMENT(LO_EXT, XML_PHYSICS_ANIMATION_DENSITY):
+            {
+                Reference< XAnimatePhysics > xAnimatePhysics( mxNode, UNO_QUERY );
+                if( xAnimatePhysics.is() )
+                    xAnimatePhysics->setDensity( makeAny(rValue.toDouble()) );
+            }
+            break;
+
+            case XML_ELEMENT(LO_EXT, XML_PHYSICS_ANIMATION_BOUNCINESS):
+            {
+                Reference< XAnimatePhysics > xAnimatePhysics( mxNode, UNO_QUERY );
+                if( xAnimatePhysics.is() )
+                    xAnimatePhysics->setBounciness( makeAny(rValue.toDouble()) );
+            }
+            break;
+
             case XML_ELEMENT(ANIMATION, XML_COLOR_INTERPOLATION):
             case XML_ELEMENT(ANIMATION_OOO, XML_COLOR_INTERPOLATION):
             {
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 368cf7d67014..2a55186fdb3e 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -1361,6 +1361,10 @@ percentage-style
 perspective
 phdthesis
 phong
+velocity-x
+velocity-y
+density
+bounciness
 pie-offset
 placeholder
 placeholder-type
commit 85f0083c217741919f4d4fb0023c2e927043df52
Author:     Sarper Akdemir <q.sarperakdemir at gmail.com>
AuthorDate: Thu Aug 13 03:40:25 2020 +0300
Commit:     Sarper Akdemir <q.sarperakdemir at gmail.com>
CommitDate: Fri Aug 14 03:17:29 2020 +0300

    make physics animations handle sequential animations correctly
    
    Change-Id: Ie8bb8b32588f4c7bf16317b5229adc5b0334d192

diff --git a/slideshow/source/engine/animationfactory.cxx b/slideshow/source/engine/animationfactory.cxx
index bc1848f68435..d6198439b327 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->queuePositionUpdate( 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 68ab37fb6868..0dbc7be63f2a 100644
--- a/slideshow/source/engine/box2dtools.cxx
+++ b/slideshow/source/engine/box2dtools.cxx
@@ -203,7 +203,8 @@ box2DWorld::box2DWorld(const ::basegfx::B2DVector& rSlideSize)
     , mbShapesInitialized(false)
     , mbHasWorldStepper(false)
     , mpXShapeToBodyMap()
-    , maShapeUpdateQueue()
+    , maShapeParallelUpdateQueue()
+    , maShapeSequentialUpdate()
 {
 }
 
@@ -253,6 +254,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)
@@ -274,6 +282,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)
@@ -305,41 +320,75 @@ void box2DWorld::setShapeCollision(
 
 void box2DWorld::processUpdateQueue(const double fPassedTime)
 {
-    while (!maShapeUpdateQueue.empty())
+    if (maShapeSequentialUpdate.empty())
     {
-        Box2DShapeUpdateInformation& aQueueElement = maShapeUpdateQueue.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)
+            css::uno::Reference<css::drawing::XShape> xShape = aIt.first.first;
+            box2DNonsimulatedShapeUpdateType eUpdateType = aIt.first.second;
+            Box2DStaticUpdateInformation& aUpdateInformation = aIt.second;
+
+            switch (eUpdateType)
             {
                 default:
                 case BOX2D_UPDATE_POSITION:
-                    setShapePositionByLinearVelocity(aQueueElement.mxShape,
-                                                     aQueueElement.maPosition, fPassedTime);
+                    setShapePosition(xShape, aUpdateInformation.maPosition);
                     break;
                 case BOX2D_UPDATE_ANGLE:
-                    setShapeAngleByAngularVelocity(aQueueElement.mxShape, aQueueElement.mfAngle,
-                                                   fPassedTime);
-                    break;
-                case BOX2D_UPDATE_SIZE:
+                    setShapeAngle(xShape, aUpdateInformation.mfAngle);
                     break;
                 case BOX2D_UPDATE_VISIBILITY:
-                    setShapeCollision(aQueueElement.mxShape, aQueueElement.mbVisibility);
-                    break;
-                case BOX2D_UPDATE_LINEAR_VELOCITY:
-                    setShapeLinearVelocity(aQueueElement.mxShape, aQueueElement.maVelocity);
+                    setShapeCollision(xShape, aUpdateInformation.mbVisibility);
                     break;
-                case BOX2D_UPDATE_ANGULAR_VELOCITY:
-                    setShapeAngularVelocity(aQueueElement.mxShape, aQueueElement.mfAngularVelocity);
             }
-            maShapeUpdateQueue.pop();
         }
+
+        // After applying all required updates empty map
+        maShapeSequentialUpdate.clear();
     }
 }
 
@@ -376,47 +425,58 @@ void box2DWorld::setHasWorldStepper(const bool bHasWorldStepper)
     mbHasWorldStepper = bHasWorldStepper;
 }
 
-void box2DWorld::queuePositionUpdate(
+void box2DWorld::queueDynamicPositionUpdate(
     const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
     const basegfx::B2DPoint& rOutPos)
 {
-    Box2DShapeUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_POSITION };
+    Box2DDynamicUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_POSITION };
     aQueueElement.maPosition = rOutPos;
-    maShapeUpdateQueue.push(aQueueElement);
+    maShapeParallelUpdateQueue.push(aQueueElement);
 }
 
 void box2DWorld::queueLinearVelocityUpdate(
     const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
-    const basegfx::B2DVector& rVelocity)
+    const basegfx::B2DVector& rVelocity, const int nDelayForSteps)
 {
-    Box2DShapeUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_LINEAR_VELOCITY, 1 };
+    Box2DDynamicUpdateInformation aQueueElement
+        = { xShape, {}, BOX2D_UPDATE_LINEAR_VELOCITY, nDelayForSteps };
     aQueueElement.maVelocity = rVelocity;
-    maShapeUpdateQueue.push(aQueueElement);
+    maShapeParallelUpdateQueue.push(aQueueElement);
 }
 
-void box2DWorld::queueRotationUpdate(
+void box2DWorld::queueDynamicRotationUpdate(
     const css::uno::Reference<com::sun::star::drawing::XShape>& xShape, const double fAngle)
 {
-    Box2DShapeUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_ANGLE };
+    Box2DDynamicUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_ANGLE };
     aQueueElement.mfAngle = fAngle;
-    maShapeUpdateQueue.push(aQueueElement);
+    maShapeParallelUpdateQueue.push(aQueueElement);
 }
 
 void box2DWorld::queueAngularVelocityUpdate(
     const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
-    const double fAngularVelocity)
+    const double fAngularVelocity, const int nDelayForSteps)
 {
-    Box2DShapeUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_ANGULAR_VELOCITY, 1 };
+    Box2DDynamicUpdateInformation aQueueElement
+        = { xShape, {}, BOX2D_UPDATE_ANGULAR_VELOCITY, nDelayForSteps };
     aQueueElement.mfAngularVelocity = fAngularVelocity;
-    maShapeUpdateQueue.push(aQueueElement);
+    maShapeParallelUpdateQueue.push(aQueueElement);
 }
 
 void box2DWorld::queueShapeVisibilityUpdate(
     const css::uno::Reference<com::sun::star::drawing::XShape>& xShape, const bool bVisibility)
 {
-    Box2DShapeUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_VISIBILITY };
+    Box2DDynamicUpdateInformation aQueueElement = { xShape, {}, BOX2D_UPDATE_VISIBILITY };
     aQueueElement.mbVisibility = bVisibility;
-    maShapeUpdateQueue.push(aQueueElement);
+    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(
@@ -424,20 +484,50 @@ void box2DWorld::queueShapeAnimationUpdate(
     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:
-            queueRotationUpdate(xShape, pAttrLayer->getRotationAngle());
-            return;
-        case slideshow::internal::AttributeType::PosX:
-        case slideshow::internal::AttributeType::PosY:
-            queuePositionUpdate(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;
+        }
     }
 }
 
@@ -448,11 +538,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(double fAngle)
+{
+    mpBox2DBody->SetTransform(mpBox2DBody->GetPosition(), ::basegfx::deg2rad(-fAngle));
+}
+
 void box2DBody::setType(box2DBodyType eType)
 {
     mpBox2DBody->SetType(getBox2DInternalBodyType(eType));
diff --git a/slideshow/source/inc/box2dtools.hxx b/slideshow/source/inc/box2dtools.hxx
index 7f01f09eb607..e5d9c94577e5 100644
--- a/slideshow/source/inc/box2dtools.hxx
+++ b/slideshow/source/inc/box2dtools.hxx
@@ -12,6 +12,7 @@
 #include "shape.hxx"
 #include "shapeattributelayer.hxx"
 #include "attributemap.hxx"
+#include <map>
 #include <unordered_map>
 #include <queue>
 
@@ -50,7 +51,7 @@ enum box2DNonsimulatedShapeUpdateType
 
 /// Holds required information to perform an update to box2d
 /// body of a shape that was altered by an animation effect
-struct Box2DShapeUpdateInformation
+struct Box2DDynamicUpdateInformation
 {
     css::uno::Reference<css::drawing::XShape> mxShape;
     union {
@@ -64,6 +65,13 @@ struct Box2DShapeUpdateInformation
     int mnDelayForSteps = 0;
 };
 
+union Box2DStaticUpdateInformation {
+    ::basegfx::B2DPoint maPosition;
+    bool mbVisibility;
+    double mfAngle;
+    Box2DStaticUpdateInformation() {}
+};
+
 /** Class that manages the Box2D World
 
     This class is used when there's a simulated animation going on,
@@ -78,15 +86,25 @@ private:
     /// Scale factor for conversions between LO user space coordinates to Box2D World coordinates
     double mfScaleFactor;
     bool mbShapesInitialized;
+    /// Holds whether or not there is a Physics Animation node that
+    /// is stepping the Box2D World
     bool mbHasWorldStepper;
     std::unordered_map<css::uno::Reference<css::drawing::XShape>, Box2DBodySharedPtr>
         mpXShapeToBodyMap;
     /// Holds any information needed to keep LO animations and Box2D world in sync
-    std::queue<Box2DShapeUpdateInformation> maShapeUpdateQueue;
+    /// if they are ongoing on parallel
+    std::queue<Box2DDynamicUpdateInformation> maShapeParallelUpdateQueue;
+    /// Holds necessary information if a shape was altered by an animation update
+    /// while there was no Physics animation going on in parallel
+    std::map<std::pair<css::uno::Reference<css::drawing::XShape>, box2DNonsimulatedShapeUpdateType>,
+             Box2DStaticUpdateInformation>
+        maShapeSequentialUpdate;
 
     /// Creates a static frame in Box2D world that corresponds to the slide borders
     void createStaticFrameAroundSlide(const ::basegfx::B2DVector& rSlideSize);
 
+    void setShapePosition(const css::uno::Reference<css::drawing::XShape> xShape,
+                          const ::basegfx::B2DPoint& rOutPos);
     /** Sets shape's corresponding Box2D body to specified position
 
         Sets shape's corresponding Box2D body to specified position as if
@@ -108,6 +126,8 @@ private:
     void setShapeLinearVelocity(const css::uno::Reference<com::sun::star::drawing::XShape> xShape,
                                 const basegfx::B2DVector& rVelocity);
 
+    void setShapeAngle(const css::uno::Reference<com::sun::star::drawing::XShape> xShape,
+                       const double fAngle);
     /** Sets shape's corresponding Box2D body to specified angle
 
         Sets shape's corresponding Box2D body to specified angle as if
@@ -157,14 +177,15 @@ private:
               const int nPositionIterations = 2);
 
     /// Queue a rotation update on the next step of the box2DWorld for the corresponding body
-    void queueRotationUpdate(const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
-                             const double fAngle);
+    void
+    queueDynamicRotationUpdate(const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
+                               const double fAngle);
 
     /// Queue an angular velocity update for the corresponding body
     /// to take place after the next step of the box2DWorld
     void
     queueAngularVelocityUpdate(const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
-                               const double fAngularVelocity);
+                               const double fAngularVelocity, const int nDelayForSteps = 0);
 
     /// Queue an update that changes collision of the corresponding body
     /// on the next step of the box2DWorld, used for animations that change visibility
@@ -244,19 +265,24 @@ public:
     void setHasWorldStepper(const bool bHasWorldStepper);
 
     /// Queue a position update the next step of the box2DWorld for the corresponding body
-    void queuePositionUpdate(const css::uno::Reference<css::drawing::XShape>& xShape,
-                             const ::basegfx::B2DPoint& rOutPos);
+    void queueDynamicPositionUpdate(const css::uno::Reference<css::drawing::XShape>& xShape,
+                                    const ::basegfx::B2DPoint& rOutPos);
 
     /// Queue a linear velocity update for the corresponding body
     /// to take place after the next step of the box2DWorld
     void queueLinearVelocityUpdate(const css::uno::Reference<css::drawing::XShape>& xShape,
-                                   const ::basegfx::B2DVector& rVelocity);
+                                   const ::basegfx::B2DVector& rVelocity,
+                                   const int nDelayForSteps = 0);
 
     void
     queueShapeAnimationUpdate(const css::uno::Reference<css::drawing::XShape>& xShape,
                               const slideshow::internal::ShapeAttributeLayerSharedPtr& pAttrLayer,
                               const slideshow::internal::AttributeType eAttrType);
 
+    void queueShapePathAnimationUpdate(
+        const css::uno::Reference<com::sun::star::drawing::XShape>& xShape,
+        const slideshow::internal::ShapeAttributeLayerSharedPtr& pAttrLayer);
+
     void queueShapeAnimationEndUpdate(const css::uno::Reference<css::drawing::XShape>& xShape,
                                       const slideshow::internal::AttributeType eAttrType);
 };
@@ -276,6 +302,8 @@ public:
     /// @return current position in LO user space coordinates
     ::basegfx::B2DPoint getPosition();
 
+    void setPosition(const ::basegfx::B2DPoint& rPos);
+
     /** Sets body to specified position
 
         Sets body to specified position as if the body had
@@ -315,6 +343,8 @@ public:
     /// @return current angle of rotation of the body
     double getAngle();
 
+    void setAngle(double fAngle);
+
     /// Set type of the body
     void setType(box2DBodyType eType);
 
commit 9e29649b3ea8295e78cb395a88e12884fa57b599
Author:     Sarper Akdemir <q.sarperakdemir at gmail.com>
AuthorDate: Thu Aug 6 10:32:55 2020 +0300
Commit:     Sarper Akdemir <q.sarperakdemir at gmail.com>
CommitDate: Fri Aug 14 03:05:01 2020 +0300

    make physics animation effects always processed last
    
    Makes it possible to add activities that will be processed last in the queue.
    
    Makes physics animation effects queued this way.
    
    And fixes the bug that makes physics animation effects appear
    out of sync for a frame with the shapes that other in parallel
    animation effects control.
    
    Change-Id: I92d436aced6ef3ee2c8b0bf0167c1f7e642ba3b5

diff --git a/slideshow/source/engine/activitiesqueue.cxx b/slideshow/source/engine/activitiesqueue.cxx
index ba982385356e..38825c6b5f06 100644
--- a/slideshow/source/engine/activitiesqueue.cxx
+++ b/slideshow/source/engine/activitiesqueue.cxx
@@ -50,6 +50,8 @@ namespace slideshow::internal
             {
                 for( const auto& pActivity : maCurrentActivitiesWaiting )
                     pActivity->dispose();
+                for( const auto& pActivity : maCurrentActivitiesToBeProcessedLast )
+                    pActivity->dispose();
                 for( const auto& pActivity : maCurrentActivitiesReinsert )
                     pActivity->dispose();
             }
@@ -59,7 +61,7 @@ namespace slideshow::internal
             }
         }
 
-        bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity )
+        bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity, const bool bProcessLast )
         {
             OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" );
 
@@ -67,7 +69,17 @@ namespace slideshow::internal
                 return false;
 
             // add entry to waiting list
-            maCurrentActivitiesWaiting.push_back( pActivity );
+            if( !bProcessLast )
+            {
+                maCurrentActivitiesWaiting.push_back( pActivity );
+            }
+            else
+            {
+                // Activities that should be processed last are kept in a different
+                // ActivityQueue, and later appended to the end of the maCurrentActivitiesWaiting
+                // on the beginning of ActivitiesQueue::process()
+                maCurrentActivitiesToBeProcessedLast.push_back( pActivity );
+            }
 
             return true;
         }
@@ -76,6 +88,12 @@ namespace slideshow::internal
         {
             SAL_INFO("slideshow.verbose", "ActivitiesQueue: outer loop heartbeat" );
 
+            // If there are activities to be processed last append them to the end of the ActivitiesQueue
+            maCurrentActivitiesWaiting.insert( maCurrentActivitiesWaiting.end(),
+                                               maCurrentActivitiesToBeProcessedLast.begin(),
+                                               maCurrentActivitiesToBeProcessedLast.end() );
+            maCurrentActivitiesToBeProcessedLast.clear();
+
             // accumulate time lag for all activities, and lag time
             // base if necessary:
             double fLag = 0.0;
diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx
index 4dcb640795aa..7999b5a7654a 100644
--- a/slideshow/source/engine/animationnodes/animationbasenode.cxx
+++ b/slideshow/source/engine/animationnodes/animationbasenode.cxx
@@ -23,6 +23,7 @@
 #include <com/sun/star/animations/Timing.hpp>
 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
+#include <com/sun/star/animations/AnimationNodeType.hpp>
 
 #include "nodetools.hxx"
 #include <doctreenode.hxx>
@@ -294,7 +295,10 @@ void AnimationBaseNode::activate_st()
         mpActivity->setTargets( getShape(), maAttributeLayerHolder.get() );
 
         // add to activities queue
-        getContext().mrActivitiesQueue.addActivity( mpActivity );
+        if( mxAnimateNode->getType() == css::animations::AnimationNodeType::ANIMATEPHYSICS )
+            getContext().mrActivitiesQueue.addActivity(mpActivity, true);
+        else
+            getContext().mrActivitiesQueue.addActivity( mpActivity );
     }
     else {
         // Actually, DO generate the event for empty activity,
diff --git a/slideshow/source/inc/activitiesqueue.hxx b/slideshow/source/inc/activitiesqueue.hxx
index b4f88b1b39d1..fff8b67bd779 100644
--- a/slideshow/source/inc/activitiesqueue.hxx
+++ b/slideshow/source/inc/activitiesqueue.hxx
@@ -57,7 +57,7 @@ namespace slideshow
 
             /** Add the given activity to the queue.
              */
-            bool addActivity( const ActivitySharedPtr& pActivity );
+            bool addActivity( const ActivitySharedPtr& pActivity, const bool bProcessLast = false );
 
             /** Process the activities queue.
 
@@ -96,6 +96,9 @@ namespace slideshow
                                                                  // await processing for this
                                                                  // round
 
+            ActivityQueue           maCurrentActivitiesToBeProcessedLast; // activities that will be
+                                                                          // processed last in the queue
+
             ActivityQueue           maCurrentActivitiesReinsert;    // currently running
                                                                       // activities, that are
                                                                       // already processed for


More information about the Libreoffice-commits mailing list