Rebased ref, commits from common ancestor: commit 3703bbd896f24b6f62e924c58332f80531ad381c Author: Sarper Akdemir <q.sarperakde...@gmail.com> AuthorDate: Thu Aug 6 10:32:55 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@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.sarperakde...@gmail.com> AuthorDate: Mon Jul 27 23:02:48 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@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.sarperakde...@gmail.com> AuthorDate: Thu Jun 25 20:33:05 2020 +0300 Commit: Sarper Akdemir <q.sarperakde...@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 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits