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

Sarper Akdemir (via logerrit) logerrit at kemper.freedesktop.org
Thu Aug 6 13:31:31 UTC 2020


Rebased ref, commits from common ancestor:
commit 3703bbd896f24b6f62e924c58332f80531ad381c
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: Thu Aug 6 16:30:22 2020 +0300

    make simulated animations always processed last
    
    Change-Id: I92d436aced6ef3ee2c8b0bf0167c1f7e642ba3b5

diff --git a/slideshow/source/engine/activitiesqueue.cxx b/slideshow/source/engine/activitiesqueue.cxx
index ba982385356e..38e79d1e5677 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 is kept in a different
+                // ActivityQueue, and later added to the end of the maCurrentActivitiesWaiting
+                // at the start 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 add 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..94089e0b65bf 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::ANIMATESIMULATED )
+            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..76dc981f8f65 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,11 @@ namespace slideshow
                                                                  // await processing for this
                                                                  // round
 
+            ActivityQueue           maCurrentActivitiesToBeProcessedLast; // activities that will be
+                                                                          // added to the end of
+                                                                          // maCurrentActivitiesWaiting at
+                                                                          // the start of process()
+
             ActivityQueue           maCurrentActivitiesReinsert;    // currently running
                                                                       // activities, that are
                                                                       // already processed for
commit 28aaa58be299ddd9e4fcf86756cd075c08c681a9
Author:     Sarper Akdemir <q.sarperakdemir at gmail.com>
AuthorDate: Mon Jul 27 23:02:48 2020 +0300
Commit:     Sarper Akdemir <q.sarperakdemir at gmail.com>
CommitDate: Thu Aug 6 16:30:22 2020 +0300

    work-in-progress complex shapes
    
    Change-Id: I807bbde92c143b8c96792b3d8bf9603a31216486

diff --git a/slideshow/source/engine/box2dtools.cxx b/slideshow/source/engine/box2dtools.cxx
index 8729300184f6..90f1d1853dba 100644
--- a/slideshow/source/engine/box2dtools.cxx
+++ b/slideshow/source/engine/box2dtools.cxx
@@ -11,6 +11,13 @@
 #include <Box2D/Box2D.h>
 
 #include <shapemanager.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+
+#include <svx/svdobj.hxx>
+#include <svx/svdoashp.hxx>
 
 #define BOX2D_SLIDE_SIZE_IN_METERS 100.00f
 
@@ -62,6 +69,124 @@ b2Vec2 convertB2DPointToBox2DVec2(const basegfx::B2DPoint& aPoint, const double
     return { static_cast<float>(aPoint.getX() * fScaleFactor),
              static_cast<float>(aPoint.getY() * -fScaleFactor) };
 }
+
+// expects rPolygon to have coordinates relative to it's center
+void addTriangleVectorToBody(const basegfx::triangulator::B2DTriangleVector& rTriangleVector,
+                             b2Body* aBody, const float fDensity, const float fFriction,
+                             const float fRestitution, const double fScaleFactor)
+{
+    for (const basegfx::triangulator::B2DTriangle& aTriangle : rTriangleVector)
+    {
+        b2FixtureDef aFixture;
+        b2PolygonShape aPolygonShape;
+        b2Vec2 aTriangleVertices[3]
+            = { convertB2DPointToBox2DVec2(aTriangle.getA(), fScaleFactor),
+                convertB2DPointToBox2DVec2(aTriangle.getB(), fScaleFactor),
+                convertB2DPointToBox2DVec2(aTriangle.getC(), fScaleFactor) };
+
+        bool bValidPointDistance = true;
+        for (int a = 0; a < 3; a++)
+        {
+            for (int b = 0; b < 3; b++)
+            {
+                if (a == b)
+                    continue;
+                if (b2DistanceSquared(aTriangleVertices[a], aTriangleVertices[b]) < 0.003f)
+                {
+                    bValidPointDistance = false;
+                }
+            }
+        }
+        if (bValidPointDistance)
+        {
+            aPolygonShape.Set(aTriangleVertices, 3);
+            aFixture.shape = &aPolygonShape;
+            aFixture.density = fDensity;
+            aFixture.friction = fFriction;
+            aFixture.restitution = fRestitution;
+            aBody->CreateFixture(&aFixture);
+        }
+    }
+}
+
+// expects rPolygon to have coordinates relative to it's center
+void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody, const float fDensity,
+                        const float fFriction, const float fRestitution, const double fScaleFactor)
+{
+    basegfx::B2DPolygon aPolygon = basegfx::utils::removeNeutralPoints(rPolygon);
+    const float fHalfWidth = 0.1;
+    bool bHaveEdgeA = false;
+    b2Vec2 aEdgeBoxVertices[4];
+
+    for (sal_uInt32 nIndex = 0; nIndex < aPolygon.count(); nIndex++)
+    {
+        b2FixtureDef aFixture;
+        b2PolygonShape aPolygonShape;
+
+        basegfx::B2DPoint aPointA;
+        basegfx::B2DPoint aPointB;
+        if (nIndex != 0)
+        {
+            aPointA = aPolygon.getB2DPoint(nIndex - 1);
+            aPointB = aPolygon.getB2DPoint(nIndex);
+        }
+        else if (/* nIndex == 0 && */ aPolygon.isClosed())
+        {
+            // start by connecting the last point to the first one
+            aPointA = aPolygon.getB2DPoint(aPolygon.count() - 1);
+            aPointB = aPolygon.getB2DPoint(nIndex);
+        }
+        else // the polygon isn't closed, won't connect last and first points
+        {
+            continue;
+        }
+
+        b2Vec2 aEdgeUnitVec = (convertB2DPointToBox2DVec2(aPointB, fScaleFactor)
+                               - convertB2DPointToBox2DVec2(aPointA, fScaleFactor));
+        aEdgeUnitVec.Normalize();
+
+        b2Vec2 aEdgeNormal(-aEdgeUnitVec.y, aEdgeUnitVec.x);
+
+        if (!bHaveEdgeA)
+        {
+            aEdgeBoxVertices[0]
+                = convertB2DPointToBox2DVec2(aPointA, fScaleFactor) + fHalfWidth * aEdgeNormal;
+            aEdgeBoxVertices[1]
+                = convertB2DPointToBox2DVec2(aPointA, fScaleFactor) + -fHalfWidth * aEdgeNormal;
+            bHaveEdgeA = true;
+        }
+        aEdgeBoxVertices[2]
+            = convertB2DPointToBox2DVec2(aPointB, fScaleFactor) + fHalfWidth * aEdgeNormal;
+        aEdgeBoxVertices[3]
+            = convertB2DPointToBox2DVec2(aPointB, fScaleFactor) + -fHalfWidth * aEdgeNormal;
+
+        bool bValidPointDistance
+            = (b2DistanceSquared(aEdgeBoxVertices[0], aEdgeBoxVertices[2]) > 0.003f);
+
+        if (bValidPointDistance)
+        {
+            aPolygonShape.Set(aEdgeBoxVertices, 4);
+            aFixture.shape = &aPolygonShape;
+            aFixture.density = fDensity;
+            aFixture.friction = fFriction;
+            aFixture.restitution = fRestitution;
+            aBody->CreateFixture(&aFixture);
+
+            aEdgeBoxVertices[0] = aEdgeBoxVertices[2];
+            aEdgeBoxVertices[1] = aEdgeBoxVertices[3];
+        }
+    }
+}
+
+void addEdgeShapeToBody(const basegfx::B2DPolyPolygon& rPolyPolygon, b2Body* aBody,
+                        const float fDensity, const float fFriction, const float fRestitution,
+                        const double fScaleFactor)
+{
+    for (const basegfx::B2DPolygon& rPolygon : rPolyPolygon)
+    {
+        addEdgeShapeToBody(rPolygon, aBody, fDensity, fFriction, fRestitution, fScaleFactor);
+    }
+}
 }
 
 box2DWorld::box2DWorld(const ::basegfx::B2DVector& rSlideSize)
@@ -224,7 +349,8 @@ void box2DWorld::initateAllShapesAsStaticBodies(
         slideshow::internal::ShapeSharedPtr pShape = aIt->second;
         if (pShape->isForeground())
         {
-            Box2DBodySharedPtr pBox2DBody = createStaticBodyFromBoundingBox(pShape);
+            Box2DBodySharedPtr pBox2DBody = createStaticBody(pShape);
+
             mpXShapeToBodyMap.insert(std::make_pair(pShape->getXShape(), pBox2DBody));
             if (!pShape->isVisible())
             {
@@ -352,14 +478,12 @@ Box2DBodySharedPtr box2DWorld::makeBodyStatic(const Box2DBodySharedPtr pBox2DBod
     return pBox2DBody;
 }
 
-Box2DBodySharedPtr
-box2DWorld::createStaticBodyFromBoundingBox(const slideshow::internal::ShapeSharedPtr& rShape,
-                                            const float fDensity, const float fFriction)
+Box2DBodySharedPtr box2DWorld::createStaticBody(const slideshow::internal::ShapeSharedPtr& rShape,
+                                                const float fDensity, const float fFriction)
 {
     assert(mpBox2DWorld);
+
     ::basegfx::B2DRectangle aShapeBounds = rShape->getBounds();
-    double fShapeWidth = aShapeBounds.getWidth() * mfScaleFactor;
-    double fShapeHeight = aShapeBounds.getHeight() * mfScaleFactor;
 
     b2BodyDef aBodyDef;
     aBodyDef.type = b2_staticBody;
@@ -369,16 +493,63 @@ box2DWorld::createStaticBodyFromBoundingBox(const slideshow::internal::ShapeShar
         pB2Body->GetWorld()->DestroyBody(pB2Body);
     });
 
-    b2PolygonShape aDynamicBox;
-    aDynamicBox.SetAsBox(static_cast<float>(fShapeWidth / 2), static_cast<float>(fShapeHeight / 2));
+    SdrObject* pSdrObject = SdrObject::getSdrObjectFromXShape(rShape->getXShape());
 
-    b2FixtureDef aFixtureDef;
-    aFixtureDef.shape = &aDynamicBox;
-    aFixtureDef.density = fDensity;
-    aFixtureDef.friction = fFriction;
-    aFixtureDef.restitution = 0.1f;
+    auto aShapeType = rShape->getXShape()->getShapeType();
+
+    basegfx::B2DPolyPolygon aPolyPolygon;
+    // workaround:
+    // TakeXorPoly() doesn't return beziers for CustomShapes and we want the beziers
+    // so that we can decide the complexity of the polygons generated from them
+    if (aShapeType == "com.sun.star.drawing.CustomShape")
+    {
+        aPolyPolygon = static_cast<SdrObjCustomShape*>(pSdrObject)->GetLineGeometry(true);
+    }
+    else
+    {
+        aPolyPolygon = pSdrObject->TakeXorPoly();
+    }
+
+    // make beziers into polygons, using a high degree angle as fAngleBound in
+    // adaptiveSubdivideByAngle reduces complexity of the resulting polygon shapes
+    aPolyPolygon = aPolyPolygon.areControlPointsUsed()
+                       ? basegfx::utils::adaptiveSubdivideByAngle(aPolyPolygon, 20)
+                       : aPolyPolygon;
+    aPolyPolygon.removeDoublePoints();
+
+    // make polygon coordinates relative to the center of the shape instead of top left of the slide
+    aPolyPolygon
+        = basegfx::utils::distort(aPolyPolygon, aPolyPolygon.getB2DRange(),
+                                  { -aShapeBounds.getWidth() / 2, -aShapeBounds.getHeight() / 2 },
+                                  { aShapeBounds.getWidth() / 2, -aShapeBounds.getHeight() / 2 },
+                                  { -aShapeBounds.getWidth() / 2, aShapeBounds.getHeight() / 2 },
+                                  { aShapeBounds.getWidth() / 2, aShapeBounds.getHeight() / 2 });
+
+    if (pSdrObject->IsClosedObj() && !pSdrObject->IsEdgeObj() && pSdrObject->HasFillStyle())
+    {
+        basegfx::triangulator::B2DTriangleVector aTriangleVector;
+        for (auto& rPolygon : aPolyPolygon)
+        {
+            if (rPolygon.isClosed())
+            {
+                basegfx::triangulator::B2DTriangleVector aTempTriangleVector(
+                    basegfx::triangulator::triangulate(rPolygon));
+                aTriangleVector.insert(aTriangleVector.end(), aTempTriangleVector.begin(),
+                                       aTempTriangleVector.end());
+            }
+            else
+            {
+                addEdgeShapeToBody(rPolygon, pBody.get(), fDensity, fFriction, 0.1f, mfScaleFactor);
+            }
+        }
+        addTriangleVectorToBody(aTriangleVector, pBody.get(), fDensity, fFriction, 0.1f,
+                                mfScaleFactor);
+    }
+    else
+    {
+        addEdgeShapeToBody(aPolyPolygon, pBody.get(), fDensity, fFriction, 0.1f, mfScaleFactor);
+    }
 
-    pBody->CreateFixture(&aFixtureDef);
     return std::make_shared<box2DBody>(pBody, mfScaleFactor);
 }
 
@@ -415,7 +586,6 @@ void box2DBody::setAngleByAngularVelocity(const double fDesiredAngle, const doub
 
     double fDeltaAngle = fDesiredAngle - getAngle();
 
-    // temporary hack for repeating animation effects
     while (fDeltaAngle > 180
            || fDeltaAngle < -180) // if it is bigger than 180 opposite rotation is actually closer
         fDeltaAngle += fDeltaAngle > 0 ? -360 : +360;
diff --git a/slideshow/source/inc/box2dtools.hxx b/slideshow/source/inc/box2dtools.hxx
index 0824a3c260c5..a468b886fcba 100644
--- a/slideshow/source/inc/box2dtools.hxx
+++ b/slideshow/source/inc/box2dtools.hxx
@@ -213,10 +213,9 @@ public:
      */
     Box2DBodySharedPtr makeBodyStatic(const Box2DBodySharedPtr pBox2DBody);
 
-    /// Create a static body from the given shape's bounding box
-    Box2DBodySharedPtr
-    createStaticBodyFromBoundingBox(const slideshow::internal::ShapeSharedPtr& rShape,
-                                    const float fDensity = 1.0f, const float fFriction = 0.3f);
+    /// Create a static body from the given shape's geometry
+    Box2DBodySharedPtr createStaticBody(const slideshow::internal::ShapeSharedPtr& rShape,
+                                        const float fDensity = 1.0f, const float fFriction = 0.3f);
 
     /// Initiate all the shapes in the current slide in the box2DWorld as static ones
     void
commit 025eb4e4a2d855001402b176c2e92993a7775377
Author:     Sarper Akdemir <q.sarperakdemir at gmail.com>
AuthorDate: Thu Jun 25 20:33:05 2020 +0300
Commit:     Sarper Akdemir <q.sarperakdemir at gmail.com>
CommitDate: Thu Aug 6 16:24:27 2020 +0300

    make simulated animations importable-exportable
    
    Makes simulated animations importable and exportable
    on content.xml. Uses two new xml tokens animateSimulation
    and motion-simulated.
    
    Also creates a new category on the animation effect pane
    called Simulated Motion and one new animation called Simulated Basic.
    
    Change-Id: I38b0511f973668655cff78becebe3f1e628d9083

diff --git a/animations/source/animcore/animcore.component b/animations/source/animcore/animcore.component
index 2f490aa0ae06..bcc7f58aaac3 100644
--- a/animations/source/animcore/animcore.component
+++ b/animations/source/animcore/animcore.component
@@ -30,6 +30,10 @@
   <implementation name="animcore::AnimateMotion"
       constructor="com_sun_star_animations_AnimateMotion_get_implementation">
     <service name="com.sun.star.animations.AnimateMotion"/>
+  </implementation>
+    <implementation name="animcore::AnimateSimulation"
+      constructor="com_sun_star_animations_AnimateSimulation_get_implementation">
+    <service name="com.sun.star.animations.AnimateSimulation"/>
   </implementation>
   <implementation name="animcore::AnimateSet"
       constructor="com_sun_star_animations_AnimateSet_get_implementation">
diff --git a/animations/source/animcore/animcore.cxx b/animations/source/animcore/animcore.cxx
index f3ffe8c4190a..e529ccfe6ba9 100644
--- a/animations/source/animcore/animcore.cxx
+++ b/animations/source/animcore/animcore.cxx
@@ -291,7 +291,7 @@ private:
     const sal_Int16 mnNodeType;
 
     // for XTypeProvider
-    static std::array<Sequence< Type >*, 12> mpTypes;
+    static std::array<Sequence< Type >*, 13> mpTypes;
 
     // attributes for the XAnimationNode interface implementation
     Any maBegin, maDuration, maEnd, maEndSync, maRepeatCount, maRepeatDuration;
@@ -394,7 +394,7 @@ Any SAL_CALL TimeContainerEnumeration::nextElement()
 }
 
 
-std::array<Sequence< Type >*, 12> AnimationNode::mpTypes = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+std::array<Sequence< Type >*, 13> AnimationNode::mpTypes = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
 
 AnimationNode::AnimationNode( sal_Int16 nNodeType )
 :   maChangeListener(maMutex),
@@ -565,6 +565,16 @@ static OUString getImplementationName_ANIMATEMOTION()
     return "animcore::AnimateMotion";
 }
 
+static Sequence<OUString> getSupportedServiceNames_ANIMATESIMULATION()
+{
+    return { "com.sun.star.animations.AnimateSimulation" };
+}
+
+static OUString getImplementationName_ANIMATESIMULATION()
+{
+    return "animcore::AnimateSimulation";
+}
+
 static Sequence<OUString> getSupportedServiceNames_ANIMATETRANSFORM()
 {
     return { "com.sun.star.animations.AnimateTransform" };
@@ -658,6 +668,12 @@ Any SAL_CALL AnimationNode::queryInterface( const Type& aType )
                 static_cast< XAnimate * >( static_cast< XAnimateMotion * >(this) ),
                 static_cast< XAnimateMotion * >( this ) );
             break;
+        case AnimationNodeType::ANIMATESIMULATED:
+            aRet = ::cppu::queryInterface(
+                aType,
+                static_cast< XAnimate * >( static_cast< XAnimateMotion * >(this) ),
+                static_cast< XAnimateMotion * >( this ) );
+            break;
         case AnimationNodeType::ANIMATECOLOR:
             aRet = ::cppu::queryInterface(
                 aType,
@@ -717,6 +733,7 @@ void AnimationNode::initTypeProvider( sal_Int16 nNodeType ) throw()
         8, // TRANSITIONFILTER
         8, // AUDIO
         8, // COMMAND
+        8, // ANIMATESIMULATED
     };
 
     // collect types
@@ -749,6 +766,9 @@ void AnimationNode::initTypeProvider( sal_Int16 nNodeType ) throw()
     case AnimationNodeType::ANIMATEMOTION:
         pTypeAr[nPos++] = cppu::UnoType<XAnimateMotion>::get();
         break;
+    case AnimationNodeType::ANIMATESIMULATED:
+        pTypeAr[nPos++] = cppu::UnoType<XAnimateMotion>::get();
+        break;
     case AnimationNodeType::ANIMATECOLOR:
         pTypeAr[nPos++] = cppu::UnoType<XAnimateColor>::get();
         break;
@@ -817,6 +837,8 @@ OUString AnimationNode::getImplementationName()
         return getImplementationName_ANIMATECOLOR();
     case AnimationNodeType::ANIMATEMOTION:
         return getImplementationName_ANIMATEMOTION();
+    case AnimationNodeType::ANIMATESIMULATED:
+        return getImplementationName_ANIMATESIMULATION();
     case AnimationNodeType::TRANSITIONFILTER:
         return getImplementationName_TRANSITIONFILTER();
     case AnimationNodeType::ANIMATETRANSFORM:
@@ -854,6 +876,8 @@ Sequence< OUString > AnimationNode::getSupportedServiceNames()
         return getSupportedServiceNames_ANIMATECOLOR();
     case AnimationNodeType::ANIMATEMOTION:
         return getSupportedServiceNames_ANIMATEMOTION();
+    case AnimationNodeType::ANIMATESIMULATED:
+        return getSupportedServiceNames_ANIMATESIMULATION();
     case AnimationNodeType::TRANSITIONFILTER:
         return getSupportedServiceNames_TRANSITIONFILTER();
     case AnimationNodeType::ANIMATETRANSFORM:
@@ -2041,6 +2065,13 @@ com_sun_star_animations_AnimateMotion_get_implementation(css::uno::XComponentCon
     return cppu::acquire(new animcore::AnimationNode(ANIMATEMOTION));
 }
 
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_animations_AnimateSimulation_get_implementation(css::uno::XComponentContext*,
+                                                             css::uno::Sequence<css::uno::Any> const &)
+{
+    return cppu::acquire(new animcore::AnimationNode(ANIMATESIMULATED));
+}
+
 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
 com_sun_star_animations_AnimateTransform_get_implementation(css::uno::XComponentContext*,
                                                              css::uno::Sequence<css::uno::Any> const &)
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 49178ebdc996..4e3a23dacffd 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -2791,6 +2791,7 @@ namespace xmloff::token {
         XML_MULTIPLY,
         XML_ANIMATE,
         XML_ANIMATEMOTION,
+        XML_ANIMATESIMULATION,
         XML_ANIMATETRANSFORM,
         XML_ANIMATECOLOR,
         XML_TRANSITIONFILTER,
@@ -2986,6 +2987,7 @@ namespace xmloff::token {
         XML_EXIT,
         XML_EMPHASIS,
         XML_MOTION_PATH,
+        XML_MOTION_SIMULATED,
         XML_OLE_ACTION,
         XML_MEDIA_CALL,
         XML_ON_CLICK,
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 68a493cfa6ac..cef77ecc02f8 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -29,6 +29,7 @@ $(eval $(call gb_UnoApi_use_api,offapi,\
 $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/animations,\
 	AnimateColor \
 	AnimateMotion \
+	AnimateSimulation \
 	AnimateSet \
 	Audio \
 	Command \
diff --git a/offapi/com/sun/star/animations/AnimateSimulation.idl b/offapi/com/sun/star/animations/AnimateSimulation.idl
new file mode 100644
index 000000000000..475e0dd0f3c1
--- /dev/null
+++ b/offapi/com/sun/star/animations/AnimateSimulation.idl
@@ -0,0 +1,25 @@
+/* -*- 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_AnimateSimulation_idl__
+#define __com_sun_star_animations_AnimateSimulation_idl__
+
+#include <com/sun/star/animations/XAnimationNode.idl>
+
+
+module com {  module sun {  module star {  module animations {
+
+
+service AnimateSimulation : com::sun::star::animations::XAnimationNode;
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/offapi/com/sun/star/presentation/EffectPresetClass.idl b/offapi/com/sun/star/presentation/EffectPresetClass.idl
index 9ff0e1201a63..50b08d0913fd 100644
--- a/offapi/com/sun/star/presentation/EffectPresetClass.idl
+++ b/offapi/com/sun/star/presentation/EffectPresetClass.idl
@@ -40,6 +40,7 @@ constants EffectPresetClass
     const short EXIT = 2;
     const short EMPHASIS = 3;
     const short MOTIONPATH = 4;
+    const short MOTIONSIMULATION = 7;
     const short OLEACTION = 5;
     const short MEDIACALL = 6;
 };
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Effects.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Effects.xcu
index 1f9267d958e1..09bab98334f4 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Effects.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Effects.xcu
@@ -1035,6 +1035,11 @@
           <value xml:lang="en-US">Vertical Figure 8</value>
         </prop>
       </node>
+      <node oor:name="libo-motionsimulated-basic" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Simulated Basic</value>
+        </prop>
+      </node>
       <node oor:name="ooo-media-start" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Start media</value>
@@ -2574,5 +2579,15 @@
         </prop>
       </node>
     </node>
+    <node oor:name="MotionSimulated">
+      <node oor:name="basic" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Basic</value>
+        </prop>
+        <prop oor:name="Effects" oor:type="oor:string-list">
+          <value oor:separator=";">libo-motionsimulated-basic</value>
+        </prop>
+      </node>
+    </node>
   </node>
 </oor:component-data>
diff --git a/officecfg/registry/schema/org/openoffice/Office/UI/Effects.xcs b/officecfg/registry/schema/org/openoffice/Office/UI/Effects.xcs
index d57104e3d121..873f2facfcb8 100644
--- a/officecfg/registry/schema/org/openoffice/Office/UI/Effects.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/UI/Effects.xcs
@@ -143,6 +143,11 @@
           <desc>Contains all the categories that don't fit anywhere else."</desc>
         </info>
       </set>
+      <set oor:name="MotionSimulated" oor:node-type="PresetCategory">
+        <info>
+          <desc>Contains the categories for simulated animation effects."</desc>
+        </info>
+      </set>
     </group>
   </component>
 </oor:component-schema>
diff --git a/sd/inc/CustomAnimationPreset.hxx b/sd/inc/CustomAnimationPreset.hxx
index b05f1675c6a7..3d25010a0b4e 100644
--- a/sd/inc/CustomAnimationPreset.hxx
+++ b/sd/inc/CustomAnimationPreset.hxx
@@ -105,6 +105,7 @@ public:
     SAL_DLLPRIVATE const PresetCategoryList& getExitPresets() const { return maExitPresets; }
     SAL_DLLPRIVATE const PresetCategoryList& getMotionPathsPresets() const { return maMotionPathsPresets; }
     SAL_DLLPRIVATE const PresetCategoryList& getMiscPresets() const { return maMiscPresets; }
+    SAL_DLLPRIVATE const PresetCategoryList& getMotionSimulatedPresets() const { return maMotionSimulatedPresets; }
 
     SAL_DLLPRIVATE void changePresetSubType( const CustomAnimationEffectPtr& pEffect, const OUString& rPresetSubType ) const;
 
@@ -127,6 +128,7 @@ private:
     PresetCategoryList maExitPresets;
     PresetCategoryList maMotionPathsPresets;
     PresetCategoryList maMiscPresets;
+    PresetCategoryList maMotionSimulatedPresets;
 
     //! Maps per-language the animation presets.
     SAL_DLLPRIVATE static std::map<OUString, CustomAnimationPresets>  mPresetsMap;
diff --git a/sd/inc/strings.hrc b/sd/inc/strings.hrc
index 0e093d1da84b..b339def6569d 100644
--- a/sd/inc/strings.hrc
+++ b/sd/inc/strings.hrc
@@ -434,6 +434,7 @@
 #define STR_CUSTOMANIMATION_EMPHASIS                    NC_("STR_CUSTOMANIMATION_EMPHASIS", "Emphasis: %1")
 #define STR_CUSTOMANIMATION_EXIT                        NC_("STR_CUSTOMANIMATION_EXIT", "Exit: %1")
 #define STR_CUSTOMANIMATION_MOTION_PATHS                NC_("STR_CUSTOMANIMATION_MOTION_PATHS", "Motion Paths: %1")
+#define STR_CUSTOMANIMATION_MOTION_SIMULATION           NC_("STR_CUSTOMANIMATION_MOTION_SIMULATION", "Simulated Motion: %1")
 #define STR_CUSTOMANIMATION_MISC                        NC_("STR_CUSTOMANIMATION_MISC", "Misc: %1")
 #define STR_SLIDETRANSITION_NONE                        NC_("STR_SLIDETRANSITION_NONE", "None")
 
diff --git a/sd/source/core/CustomAnimationPreset.cxx b/sd/source/core/CustomAnimationPreset.cxx
index 3be4e76941f8..bec05fa14259 100644
--- a/sd/source/core/CustomAnimationPreset.cxx
+++ b/sd/source/core/CustomAnimationPreset.cxx
@@ -349,6 +349,8 @@ void CustomAnimationPresets::importResources()
         importPresets( xConfigProvider, "/org.openoffice.Office.UI.Effects/Presets/MotionPaths", maMotionPathsPresets );
 
         importPresets( xConfigProvider, "/org.openoffice.Office.UI.Effects/Presets/Misc", maMiscPresets );
+
+        importPresets( xConfigProvider, "/org.openoffice.Office.UI.Effects/Presets/MotionSimulated", maMotionSimulatedPresets );
     }
     catch (const lang::WrappedTargetException&)
     {
@@ -502,6 +504,7 @@ Reference< XAnimationNode > CustomAnimationPresets::getRandomPreset( sal_Int16 n
     case EffectPresetClass::EXIT:       pCategoryList = &maExitPresets; break;
     case EffectPresetClass::EMPHASIS:   pCategoryList = &maEmphasisPresets; break;
     case EffectPresetClass::MOTIONPATH: pCategoryList = &maMotionPathsPresets; break;
+    case EffectPresetClass::MOTIONSIMULATION: pCategoryList = &maMotionSimulatedPresets; break;
     default:
         pCategoryList = nullptr;
     }
diff --git a/sd/source/ui/animations/CustomAnimationList.cxx b/sd/source/ui/animations/CustomAnimationList.cxx
index 0e2762ce762e..63fe7b391a97 100644
--- a/sd/source/ui/animations/CustomAnimationList.cxx
+++ b/sd/source/ui/animations/CustomAnimationList.cxx
@@ -252,6 +252,8 @@ CustomAnimationListEntryItem::CustomAnimationListEntryItem(const OUString& aDesc
         msEffectName = SdResId(STR_CUSTOMANIMATION_EMPHASIS); break;
     case EffectPresetClass::MOTIONPATH:
         msEffectName = SdResId(STR_CUSTOMANIMATION_MOTION_PATHS); break;
+    case EffectPresetClass::MOTIONSIMULATION:
+        msEffectName = SdResId(STR_CUSTOMANIMATION_MOTION_SIMULATION); break;
     default:
         msEffectName = SdResId(STR_CUSTOMANIMATION_MISC); break;
     }
@@ -371,6 +373,7 @@ void CustomAnimationListEntryItem::PaintEffect(vcl::RenderContext& rRenderContex
     case EffectPresetClass::EMPHASIS:
         sImage = BMP_CUSTOMANIMATION_EMPHASIS_EFFECT; break;
     case EffectPresetClass::MOTIONPATH:
+    case EffectPresetClass::MOTIONSIMULATION:
         sImage = BMP_CUSTOMANIMATION_MOTION_PATH; break;
     case EffectPresetClass::OLEACTION:
         sImage = BMP_CUSTOMANIMATION_OLE; break;
diff --git a/sd/source/ui/animations/CustomAnimationPane.cxx b/sd/source/ui/animations/CustomAnimationPane.cxx
index 45e44c0d8628..cdcc1cb97cc3 100644
--- a/sd/source/ui/animations/CustomAnimationPane.cxx
+++ b/sd/source/ui/animations/CustomAnimationPane.cxx
@@ -585,6 +585,7 @@ void CustomAnimationPane::updateControls()
             case EffectPresetClass::EMPHASIS: nCategoryPos = 1; break;
             case EffectPresetClass::EXIT: nCategoryPos = 2; break;
             case EffectPresetClass::MOTIONPATH: nCategoryPos = 3; break;
+            case EffectPresetClass::MOTIONSIMULATION: nCategoryPos = 5; break;
             default:
                 break;
         }
@@ -2186,6 +2187,7 @@ sal_Int32 CustomAnimationPane::fillAnimationLB( bool bHasText )
         case 2:rCategoryList = rPresets.getExitPresets();break;
         case 3:rCategoryList = rPresets.getMotionPathsPresets();break;
         case 4:rCategoryList = rPresets.getMiscPresets();break;
+        case 5:rCategoryList = rPresets.getMotionSimulatedPresets();break;
     }
 
     sal_Int32 nFirstEffect = -1;
diff --git a/sd/uiconfig/simpress/ui/customanimationspanel.ui b/sd/uiconfig/simpress/ui/customanimationspanel.ui
index 94184323a775..333cf74793ba 100644
--- a/sd/uiconfig/simpress/ui/customanimationspanel.ui
+++ b/sd/uiconfig/simpress/ui/customanimationspanel.ui
@@ -290,6 +290,7 @@
                   <item translatable="yes" context="customanimationspanel|categorylb">Exit</item>
                   <item translatable="yes" context="customanimationspanel|categorylb">Motion Paths</item>
                   <item translatable="yes" context="customanimationspanel|categorylb">Misc Effects</item>
+                  <item translatable="yes" context="customanimationspanel|categorylb">Simulated Motion</item>
                 </items>
               </object>
               <packing>
diff --git a/sd/xml/effects.xml b/sd/xml/effects.xml
index 393ad5d50263..bcb83865c7ae 100644
--- a/sd/xml/effects.xml
+++ b/sd/xml/effects.xml
@@ -2639,6 +2639,13 @@
             </anim:par>
         </anim:par>
     </anim:par>
+    <anim:par smil:begin="indefinite" smil:fill="hold">
+        <anim:par smil:begin="0" smil:fill="hold">
+            <anim:par smil:begin="0" smil:fill="hold" pres:node-type="on-click" pres:preset-class="motion-simulated" pres:preset-id="libo-motionsimulated-basic">
+                <anim:animateSimulation smil:dur="4" smil:fill="hold"/>
+            </anim:par>
+        </anim:par>
+    </anim:par>
     <anim:par smil:begin="indefinite" smil:fill="hold">
         <anim:par smil:begin="0" smil:fill="hold">
             <anim:par smil:begin="0" smil:fill="hold" pres:node-type="on-click" pres:preset-class="media-call" pres:preset-id="ooo-media-start">
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 8d9a70f5e082..d0528ca80e33 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -2792,6 +2792,7 @@ namespace xmloff::token {
         TOKEN( "multiply",                  XML_MULTIPLY ),
         TOKEN( "animate",                       XML_ANIMATE ),
         TOKEN( "animateMotion",             XML_ANIMATEMOTION ),
+        TOKEN( "animateSimulation",         XML_ANIMATESIMULATION ),
         TOKEN( "animateTransform",          XML_ANIMATETRANSFORM ),
         TOKEN( "animateColor",              XML_ANIMATECOLOR ),
         TOKEN( "transitionFilter",          XML_TRANSITIONFILTER ),
@@ -2987,6 +2988,7 @@ namespace xmloff::token {
         TOKEN( "exit",              XML_EXIT ),
         TOKEN( "emphasis",          XML_EMPHASIS ),
         TOKEN( "motion-path",           XML_MOTION_PATH ),
+        TOKEN( "motion-simulated",      XML_MOTION_SIMULATED ),
         TOKEN( "ole-action",            XML_OLE_ACTION ),
         TOKEN( "media-call",            XML_MEDIA_CALL ),
         TOKEN( "on-click",          XML_ON_CLICK ),
diff --git a/xmloff/source/draw/animationexport.cxx b/xmloff/source/draw/animationexport.cxx
index 7aa293e75716..25ff6357523f 100644
--- a/xmloff/source/draw/animationexport.cxx
+++ b/xmloff/source/draw/animationexport.cxx
@@ -357,6 +357,7 @@ const SvXMLEnumMapEntry<sal_Int16> aAnimations_EnumMap_EffectPresetClass[] =
     { XML_MOTION_PATH,  EffectPresetClass::MOTIONPATH },
     { XML_OLE_ACTION,   EffectPresetClass::OLEACTION },
     { XML_MEDIA_CALL,   EffectPresetClass::MEDIACALL },
+    { XML_MOTION_SIMULATED, EffectPresetClass::MOTIONSIMULATION },
     { XML_TOKEN_INVALID, 0 }
 };
 const SvXMLEnumMapEntry<sal_Int16> aAnimations_EnumMap_EffectNodeType[] =
@@ -697,6 +698,7 @@ void AnimationsExporterImpl::prepareNode( const Reference< XAnimationNode >& xNo
         case AnimationNodeType::ANIMATE:
         case AnimationNodeType::SET:
         case AnimationNodeType::ANIMATEMOTION:
+        case AnimationNodeType::ANIMATESIMULATED:
         case AnimationNodeType::ANIMATECOLOR:
         case AnimationNodeType::ANIMATETRANSFORM:
         case AnimationNodeType::TRANSITIONFILTER:
@@ -947,6 +949,7 @@ void AnimationsExporterImpl::exportNode( const Reference< XAnimationNode >& xNod
         case AnimationNodeType::ANIMATE:
         case AnimationNodeType::SET:
         case AnimationNodeType::ANIMATEMOTION:
+        case AnimationNodeType::ANIMATESIMULATED:
         case AnimationNodeType::ANIMATECOLOR:
         case AnimationNodeType::ANIMATETRANSFORM:
         case AnimationNodeType::TRANSITIONFILTER:
@@ -1089,6 +1092,10 @@ void AnimationsExporterImpl::exportAnimate( const Reference< XAnimate >& xAnimat
         {
             eAttributeName = XML_ANIMATEMOTION;
         }
+        else if( nNodeType == AnimationNodeType::ANIMATESIMULATED )
+        {
+            eAttributeName = XML_ANIMATESIMULATION;
+        }
         else
         {
             OUString sTemp( xAnimate->getAttributeName() );
@@ -1234,6 +1241,15 @@ void AnimationsExporterImpl::exportAnimate( const Reference< XAnimate >& xAnimat
         }
         break;
 
+        case AnimationNodeType::ANIMATESIMULATED:
+        {
+            eElementToken = XML_ANIMATESIMULATION;
+
+            Reference< XAnimateMotion > xAnimateMotion( xAnimate, UNO_QUERY_THROW );
+            aTemp = xAnimateMotion->getOrigin();
+        }
+        break;
+
         case AnimationNodeType::ANIMATECOLOR:
         {
             eElementToken = XML_ANIMATECOLOR;
@@ -1437,6 +1453,7 @@ void AnimationsExporterImpl::convertValue( XMLTokenEnum eAttributeName, OUString
         case XML_HEIGHT:
         case XML_ANIMATETRANSFORM:
         case XML_ANIMATEMOTION:
+        case XML_ANIMATESIMULATION:
         {
             if( auto aString = o3tl::tryAccess<OUString>(rValue) )
             {
diff --git a/xmloff/source/draw/animationimport.cxx b/xmloff/source/draw/animationimport.cxx
index ebccff3d1a22..0cddb5169f80 100644
--- a/xmloff/source/draw/animationimport.cxx
+++ b/xmloff/source/draw/animationimport.cxx
@@ -460,6 +460,8 @@ AnimationNodeContext::AnimationNodeContext(
                 pServiceName = "com.sun.star.animations.AnimateSet"; break;
             case XML_ANIMATEMOTION:
                 pServiceName = "com.sun.star.animations.AnimateMotion"; break;
+            case XML_ANIMATESIMULATION:
+                pServiceName = "com.sun.star.animations.AnimateSimulation"; break;
             case XML_ANIMATECOLOR:
                 pServiceName = "com.sun.star.animations.AnimateColor"; break;
             case XML_ANIMATETRANSFORM:
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 34b9af91e03c..18f75351e199 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -2620,6 +2620,7 @@ additive
 multiply
 animate
 animateMotion
+animateSimulation
 animateTransform
 animateColor
 transitionFilter
@@ -2802,6 +2803,7 @@ entrance
 exit
 emphasis
 motion-path
+motion-simulated
 ole-action
 media-call
 on-click


More information about the Libreoffice-commits mailing list