Rebased ref, commits from common ancestor: commit 6b5b1b7175ad778d23e6429ddfcd9fa71a6a8131 Author: Sarper Akdemir <q.sarperakde...@gmail.com> AuthorDate: Thu Aug 6 10:32:55 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@gmail.com> CommitDate: Tue Aug 11 16:58:11 2020 +0300
make physics based animation effects 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..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..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 7251b6aaae7c3bcf0dec2267839abdedfe454a6c Author: Sarper Akdemir <q.sarperakde...@gmail.com> AuthorDate: Mon Jul 27 23:02:48 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@gmail.com> CommitDate: Tue Aug 11 16:58:10 2020 +0300 add support for complex shapes in physics animation effects Makes it possible to represent complex shapes of LibreOffice in physics animation effects by closely approximating their geometry. Therefore enables more convincing animation effects. Change-Id: I807bbde92c143b8c96792b3d8bf9603a31216486 diff --git a/slideshow/source/engine/box2dtools.cxx b/slideshow/source/engine/box2dtools.cxx index c188234105d7..68ab37fb6868 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,132 @@ b2Vec2 convertB2DPointToBox2DVec2(const basegfx::B2DPoint& aPoint, const double return { static_cast<float>(aPoint.getX() * fScaleFactor), static_cast<float>(aPoint.getY() * -fScaleFactor) }; } + +// expects rTriangleVector to have coordinates relative to the shape's bounding box 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 nPointIndexA = 0; nPointIndexA < 3; nPointIndexA++) + { + for (int nPointIndexB = 0; nPointIndexB < 3; nPointIndexB++) + { + if (nPointIndexA == nPointIndexB) + continue; + + // check whether the triangle would be a degenerately small one + if (b2DistanceSquared(aTriangleVertices[nPointIndexA], + aTriangleVertices[nPointIndexB]) + < 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); + + // value that somewhat defines half width of the quadrilateral + // that will be representing edge segment in the box2d world + const float fHalfWidth = 0.1f; + bool bHasPreviousQuadrilateralEdge = false; + b2Vec2 aQuadrilateralVertices[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 (!bHasPreviousQuadrilateralEdge) + { + aQuadrilateralVertices[0] + = convertB2DPointToBox2DVec2(aPointA, fScaleFactor) + fHalfWidth * aEdgeNormal; + aQuadrilateralVertices[1] + = convertB2DPointToBox2DVec2(aPointA, fScaleFactor) + -fHalfWidth * aEdgeNormal; + bHasPreviousQuadrilateralEdge = true; + } + aQuadrilateralVertices[2] + = convertB2DPointToBox2DVec2(aPointB, fScaleFactor) + fHalfWidth * aEdgeNormal; + aQuadrilateralVertices[3] + = convertB2DPointToBox2DVec2(aPointB, fScaleFactor) + -fHalfWidth * aEdgeNormal; + + bool bValidPointDistance + = b2DistanceSquared(aQuadrilateralVertices[0], aQuadrilateralVertices[2]) > 0.003f; + + if (bValidPointDistance) + { + aPolygonShape.Set(aQuadrilateralVertices, 4); + aFixture.shape = &aPolygonShape; + aFixture.density = fDensity; + aFixture.friction = fFriction; + aFixture.restitution = fRestitution; + aBody->CreateFixture(&aFixture); + + // prepare the quadrilateral edge for next connection + aQuadrilateralVertices[0] = aQuadrilateralVertices[2]; + aQuadrilateralVertices[1] = aQuadrilateralVertices[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 +357,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()) { @@ -394,14 +528,12 @@ Box2DBodySharedPtr box2DWorld::makeBodyStatic(const Box2DBodySharedPtr& pBox2DBo 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; @@ -411,16 +543,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; + rtl::OUString 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); } diff --git a/slideshow/source/inc/box2dtools.hxx b/slideshow/source/inc/box2dtools.hxx index dacf24845b45..7f01f09eb607 100644 --- a/slideshow/source/inc/box2dtools.hxx +++ b/slideshow/source/inc/box2dtools.hxx @@ -229,10 +229,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 08f11b0847aae0013a49ff3e65dc3646261b01e0 Author: Sarper Akdemir <q.sarperakde...@gmail.com> AuthorDate: Thu Jun 25 20:33:05 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@gmail.com> CommitDate: Tue Aug 11 16:58:10 2020 +0300 make physics based animation effects importable-exportable Makes physics based animation effects importable and exportable on content.xml. Uses one new xml token animateSimulation. Also adds a new animation preset called Physics Basic that is available under Emphasis animation effect category. Change-Id: I38b0511f973668655cff78becebe3f1e628d9083 diff --git a/animations/source/animcore/animcore.component b/animations/source/animcore/animcore.component index 2f490aa0ae06..cd691f05e0ba 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::AnimatePhysics" + constructor="com_sun_star_animations_AnimatePhysics_get_implementation"> + <service name="com.sun.star.animations.AnimatePhysics"/> </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..88e42772936a 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_ANIMATEPHYSICS() +{ + return { "com.sun.star.animations.AnimatePhysics" }; +} + +static OUString getImplementationName_ANIMATEPHYSICS() +{ + return "animcore::AnimatePhysics"; +} + 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::ANIMATEPHYSICS: + 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, // ANIMATEPHYSICS }; // 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::ANIMATEPHYSICS: + 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::ANIMATEPHYSICS: + return getImplementationName_ANIMATEPHYSICS(); 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::ANIMATEPHYSICS: + return getSupportedServiceNames_ANIMATEPHYSICS(); 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_AnimatePhysics_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new animcore::AnimationNode(ANIMATEPHYSICS)); +} + 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..ffa9206d4f44 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_ANIMATEPHYSICS, XML_ANIMATETRANSFORM, XML_ANIMATECOLOR, XML_TRANSITIONFILTER, diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 68a493cfa6ac..8d78a3c2f696 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 \ + AnimatePhysics \ AnimateSet \ Audio \ Command \ diff --git a/offapi/com/sun/star/animations/AnimatePhysics.idl b/offapi/com/sun/star/animations/AnimatePhysics.idl new file mode 100644 index 000000000000..87fe960e611c --- /dev/null +++ b/offapi/com/sun/star/animations/AnimatePhysics.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_AnimatePhysics_idl__ +#define __com_sun_star_animations_AnimatePhysics_idl__ + +#include <com/sun/star/animations/XAnimationNode.idl> + + +module com { module sun { module star { module animations { + + +service AnimatePhysics : com::sun::star::animations::XAnimationNode; + + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Effects.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Effects.xcu index 1f9267d958e1..84156c1d3722 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-physics-basic" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Physics 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> @@ -2500,7 +2505,7 @@ <value xml:lang="en-US">Exciting</value> </prop> <prop oor:name="Effects" oor:type="oor:string-list"> - <value oor:separator=";">ooo-emphasis-blast;ooo-emphasis-bold-reveal;ooo-emphasis-style-emphasis;ooo-emphasis-wave;ooo-emphasis-blink</value> + <value oor:separator=";">ooo-emphasis-blast;ooo-emphasis-bold-reveal;ooo-emphasis-style-emphasis;ooo-emphasis-wave;ooo-emphasis-blink;libo-physics-basic</value> </prop> </node> </node> diff --git a/sd/xml/effects.xml b/sd/xml/effects.xml index 393ad5d50263..d3e03da56ee2 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="emphasis" pres:preset-id="libo-physics-basic"> + <anim:animatePhysics 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..03e777185d0e 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( "animatePhysics", XML_ANIMATEPHYSICS ), TOKEN( "animateTransform", XML_ANIMATETRANSFORM ), TOKEN( "animateColor", XML_ANIMATECOLOR ), TOKEN( "transitionFilter", XML_TRANSITIONFILTER ), diff --git a/xmloff/source/draw/animationexport.cxx b/xmloff/source/draw/animationexport.cxx index 7aa293e75716..f217e46a709d 100644 --- a/xmloff/source/draw/animationexport.cxx +++ b/xmloff/source/draw/animationexport.cxx @@ -697,6 +697,7 @@ void AnimationsExporterImpl::prepareNode( const Reference< XAnimationNode >& xNo case AnimationNodeType::ANIMATE: case AnimationNodeType::SET: case AnimationNodeType::ANIMATEMOTION: + case AnimationNodeType::ANIMATEPHYSICS: case AnimationNodeType::ANIMATECOLOR: case AnimationNodeType::ANIMATETRANSFORM: case AnimationNodeType::TRANSITIONFILTER: @@ -947,6 +948,7 @@ void AnimationsExporterImpl::exportNode( const Reference< XAnimationNode >& xNod case AnimationNodeType::ANIMATE: case AnimationNodeType::SET: case AnimationNodeType::ANIMATEMOTION: + case AnimationNodeType::ANIMATEPHYSICS: case AnimationNodeType::ANIMATECOLOR: case AnimationNodeType::ANIMATETRANSFORM: case AnimationNodeType::TRANSITIONFILTER: @@ -1089,6 +1091,10 @@ void AnimationsExporterImpl::exportAnimate( const Reference< XAnimate >& xAnimat { eAttributeName = XML_ANIMATEMOTION; } + else if( nNodeType == AnimationNodeType::ANIMATEPHYSICS ) + { + eAttributeName = XML_ANIMATEPHYSICS; + } else { OUString sTemp( xAnimate->getAttributeName() ); @@ -1234,6 +1240,15 @@ void AnimationsExporterImpl::exportAnimate( const Reference< XAnimate >& xAnimat } break; + case AnimationNodeType::ANIMATEPHYSICS: + { + eElementToken = XML_ANIMATEPHYSICS; + + Reference< XAnimateMotion > xAnimateMotion( xAnimate, UNO_QUERY_THROW ); + aTemp = xAnimateMotion->getOrigin(); + } + break; + case AnimationNodeType::ANIMATECOLOR: { eElementToken = XML_ANIMATECOLOR; @@ -1295,7 +1310,14 @@ void AnimationsExporterImpl::exportAnimate( const Reference< XAnimate >& xAnimat break; } - SvXMLElementExport aElement( *mxExport, XML_NAMESPACE_ANIMATION, eElementToken, true, true ); + if( eElementToken == XML_ANIMATEPHYSICS ) // not a standart should use the extension namespace + { + SvXMLElementExport aElement( *mxExport, XML_NAMESPACE_LO_EXT, eElementToken, true, true ); + } + else + { + SvXMLElementExport aElement( *mxExport, XML_NAMESPACE_ANIMATION, eElementToken, true, true ); + } } catch (const Exception&) @@ -1437,6 +1459,7 @@ void AnimationsExporterImpl::convertValue( XMLTokenEnum eAttributeName, OUString case XML_HEIGHT: case XML_ANIMATETRANSFORM: case XML_ANIMATEMOTION: + case XML_ANIMATEPHYSICS: { if( auto aString = o3tl::tryAccess<OUString>(rValue) ) { diff --git a/xmloff/source/draw/animationimport.cxx b/xmloff/source/draw/animationimport.cxx index ebccff3d1a22..52e020e8f939 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_ANIMATEPHYSICS: + pServiceName = "com.sun.star.animations.AnimatePhysics"; 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..368cf7d67014 100644 --- a/xmloff/source/token/tokens.txt +++ b/xmloff/source/token/tokens.txt @@ -2620,6 +2620,7 @@ additive multiply animate animateMotion +animatePhysics animateTransform animateColor transitionFilter commit fd753b04a17b91921849b12e1098a403d698d247 Author: Sarper Akdemir <q.sarperakde...@gmail.com> AuthorDate: Mon Aug 10 15:30:26 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@gmail.com> CommitDate: Tue Aug 11 16:58:10 2020 +0300 add version tag to ANIMATEPHYSICS Change-Id: Ia6db8ca10a0311ae8492cdc5ab518efaba611cb2 diff --git a/offapi/com/sun/star/animations/AnimationNodeType.idl b/offapi/com/sun/star/animations/AnimationNodeType.idl index d0cd6e268fd6..7c6abb105947 100644 --- a/offapi/com/sun/star/animations/AnimationNodeType.idl +++ b/offapi/com/sun/star/animations/AnimationNodeType.idl @@ -68,7 +68,10 @@ constants AnimationNodeType /** Defines a command effect. */ const short COMMAND = 11; - /** Defines a physics animation */ + /** Defines a physics animation + + @since LibreOffice 7.1 + */ const short ANIMATEPHYSICS = 12; }; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits