summaryrefslogtreecommitdiff
path: root/slideshow/source/inc/box2dtools.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'slideshow/source/inc/box2dtools.hxx')
-rw-r--r--slideshow/source/inc/box2dtools.hxx317
1 files changed, 317 insertions, 0 deletions
diff --git a/slideshow/source/inc/box2dtools.hxx b/slideshow/source/inc/box2dtools.hxx
new file mode 100644
index 000000000000..0824a3c260c5
--- /dev/null
+++ b/slideshow/source/inc/box2dtools.hxx
@@ -0,0 +1,317 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include "shape.hxx"
+#include "shapeattributelayer.hxx"
+#include <unordered_map>
+#include <queue>
+
+class b2Body;
+class b2World;
+
+namespace slideshow::internal
+{
+class ShapeManager;
+typedef std::shared_ptr<ShapeManager> ShapeManagerSharedPtr;
+}
+
+namespace box2d::utils
+{
+class box2DBody;
+class box2DWorld;
+typedef std::shared_ptr<box2DWorld> Box2DWorldSharedPtr;
+typedef std::shared_ptr<box2DBody> Box2DBodySharedPtr;
+
+enum box2DBodyType
+{
+ BOX2D_STATIC_BODY = 0,
+ BOX2D_KINEMATIC_BODY,
+ BOX2D_DYNAMIC_BODY
+};
+
+enum box2DNonsimulatedShapeUpdateType
+{
+ BOX2D_UPDATE_POSITION,
+ BOX2D_UPDATE_ANGLE,
+ BOX2D_UPDATE_SIZE,
+ BOX2D_UPDATE_VISIBILITY,
+ BOX2D_UPDATE_LINEAR_VELOCITY,
+ BOX2D_UPDATE_ANGULAR_VELOCITY
+};
+
+/// Holds required information to perform an update to box2d
+/// body of a shape that was altered by an animation effect
+struct Box2DShapeUpdateInformation
+{
+ css::uno::Reference<css::drawing::XShape> mxShape;
+ union {
+ ::basegfx::B2DPoint maPosition;
+ ::basegfx::B2DVector maVelocity;
+ double mfAngle;
+ double mfAngularVelocity;
+ bool mbVisibility;
+ };
+ box2DNonsimulatedShapeUpdateType meUpdateType;
+ int mnDelayForSteps = 0;
+};
+
+/** Class that manages the Box2D World
+
+ This class is used when there's a simulated animation going on,
+ it handles the stepping through the simulated world, updating the
+ shapes in the simulated world if they were changed by ongoing animations.
+ */
+class box2DWorld
+{
+private:
+ /// Pointer to the real Box2D World that this class manages for simulations
+ std::unique_ptr<b2World> mpBox2DWorld;
+ /// Scale factor for conversions between LO user space coordinates to Box2D World coordinates
+ double mfScaleFactor;
+ bool mbShapesInitialized;
+ bool mbHasWorldStepper;
+ std::unordered_map<css::uno::Reference<css::drawing::XShape>, Box2DBodySharedPtr>
+ mpXShapeToBodyMap;
+ /// Holds any information needed to keep LO animations and Box2D world in sync
+ std::queue<Box2DShapeUpdateInformation> maShapeUpdateQueue;
+
+ /// Creates a static frame in Box2D world that corresponds to the slide borders
+ void createStaticFrameAroundSlide(const ::basegfx::B2DVector& rSlideSize);
+
+ /** Sets shape's corresponding Box2D body to specified position
+
+ Sets shape's corresponding Box2D body to specified position as if
+ the body had velocity to reach that point in given time frame
+
+ @param xShape
+ Shape reference
+
+ @param rOutPos
+ Position in LO user space coordinates
+
+ @param fPassedTime
+ Time frame which the Box2D body should move to the specified position.
+ */
+ void setShapePositionByLinearVelocity(const css::uno::Reference<css::drawing::XShape> xShape,
+ const ::basegfx::B2DPoint& rOutPos,
+ const double fPassedTime);
+ /// Sets linear velocity of the shape's corresponding body in the Box2D world
+ void setShapeLinearVelocity(const css::uno::Reference<com::sun::star::drawing::XShape> xShape,
+ const basegfx::B2DVector& rVelocity);
+
+ /** Sets shape's corresponding Box2D body to specified angle
+
+ Sets shape's corresponding Box2D body to specified angle as if
+ the body had angular velocity to reach that point in given time frame
+
+ @param xShape
+ Shape reference
+
+ @param fAngle
+ Position in LO user space coordinates
+
+ @param fPassedTime
+ Time frame which the Box2D body should move to the specified position.
+ */
+ void setShapeAngleByAngularVelocity(
+ const css::uno::Reference<com::sun::star::drawing::XShape> xShape, const double fAngle,
+ const double fPassedTime);
+
+ /// Sets angular velocity of the shape's corresponding body in the Box2D world
+ void setShapeAngularVelocity(const css::uno::Reference<com::sun::star::drawing::XShape> xShape,
+ const double fAngularVelocity);
+
+ /** Set whether a shape can have collision in the Box2D World
+
+ Used for animations that change the visibility of the shape.
+
+ @param xShape
+ Shape reference
+
+ @param bCanCollide
+ true if collisions should be enabled for the corresponding Box2D body of this shape
+ and false if it should be disabled.
+ */
+ void setShapeCollision(const css::uno::Reference<com::sun::star::drawing::XShape> xShape,
+ const bool bCanCollide);
+ /** Process the updates queued in the maShapeUpdateQueue
+
+ Called on each step of the box2DWorld.
+
+ @param fPassedTime
+ Time frame to process the updates accordingly (needed for proper simulations)
+ */
+ void processUpdateQueue(const double fPassedTime);
+
+ /// Simulate and step through time in the Box2D World
+ void step(const float fTimeStep = 1.0f / 100.0f, const int nVelocityIterations = 6,
+ const int nPositionIterations = 2);
+
+public:
+ box2DWorld(const ::basegfx::B2DVector& rSlideSize);
+ ~box2DWorld();
+
+ bool initiateWorld(const ::basegfx::B2DVector& rSlideSize);
+
+ /** Simulate and step through a given amount of time in the Box2D World
+
+ @param fPassedTime
+ Amount of time to step through
+
+ @return Amount of time actually stepped through, since it is possible
+ to only step through a multiple of fTimeStep
+ */
+ double stepAmount(const double fPassedTime, const float fTimeStep = 1.0f / 100.0f,
+ const int nVelocityIterations = 6, const int nPositionIterations = 2);
+
+ /// @return whether shapes in the slide are initialized as Box2D bodies or not
+ bool shapesInitialized();
+ /// @return whether the Box2D shape is initialized or not
+ bool isInitialized();
+
+ /** Make the Box2D body corresponding to the given shape a dynamic one
+
+ A dynamic body will be affected by other bodies and the gravity.
+
+ @param pShape
+ Pointer to the shape to alter the corresponding Box2D body of
+ */
+ Box2DBodySharedPtr makeShapeDynamic(const slideshow::internal::ShapeSharedPtr pShape);
+
+ /** Make the Box2D body a dynamic one
+
+ A dynamic body will be affected by other bodies and the gravity.
+
+ @param pBox2DBody
+ Pointer to the Box2D body
+ */
+ Box2DBodySharedPtr makeBodyDynamic(const Box2DBodySharedPtr pBox2DBody);
+
+ /** Make the Box2D body corresponding to the given shape a static one
+
+ A static body will not be affected by other bodies and the gravity.
+
+ @param pShape
+ Pointer to the shape to alter the corresponding Box2D body of
+ */
+ Box2DBodySharedPtr makeShapeStatic(const slideshow::internal::ShapeSharedPtr pShape);
+
+ /** Make the Box2D body a dynamic one
+
+ A static body will not be affected by other bodies and the gravity.
+
+ @param pBox2DBody
+ Pointer to the Box2D body
+ */
+ 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);
+
+ /// Initiate all the shapes in the current slide in the box2DWorld as static ones
+ void
+ initateAllShapesAsStaticBodies(const slideshow::internal::ShapeManagerSharedPtr pShapeManager);
+
+ /// @return whether the box2DWorld has a stepper or not
+ bool hasWorldStepper();
+
+ /// Set the flag for whether the box2DWorld has a stepper or not
+ void setHasWorldStepper(const bool bHasWorldStepper);
+
+ /// Queue a position update the next step of the box2DWorld for the corresponding body
+ void queuePositionUpdate(css::uno::Reference<css::drawing::XShape> xShape,
+ const ::basegfx::B2DPoint& rOutPos);
+
+ /// Queue a linear velocity update for the corresponding body
+ /// to take place after the next step of the box2DWorld
+ void queueLinearVelocityUpdate(css::uno::Reference<css::drawing::XShape> xShape,
+ const ::basegfx::B2DVector& rVelocity);
+
+ /// Queue a rotation update on the next step of the box2DWorld for the corresponding body
+ void queueRotationUpdate(css::uno::Reference<com::sun::star::drawing::XShape> xShape,
+ const double fAngle);
+
+ /// Queue an angular velocity update for the corresponding body
+ /// to take place after the next step of the box2DWorld
+ void queueAngularVelocityUpdate(css::uno::Reference<com::sun::star::drawing::XShape> xShape,
+ const double fAngularVelocity);
+
+ /// Queue an update that changes collision of the corresponding body
+ /// on the next step of the box2DWorld, used for animations that change visibility
+ void queueShapeVisibilityUpdate(css::uno::Reference<css::drawing::XShape> xShape,
+ const bool bVisibility);
+};
+
+/// Class that manages a single box2D Body
+class box2DBody
+{
+private:
+ /// Pointer to the body that this class manages
+ std::shared_ptr<b2Body> mpBox2DBody;
+ /// Scale factor for conversions between LO user space coordinates to Box2D World coordinates
+ double mfScaleFactor;
+
+public:
+ box2DBody(std::shared_ptr<b2Body> pBox2DBody, double fScaleFactor);
+
+ /// @return current position in LO user space coordinates
+ ::basegfx::B2DPoint getPosition();
+
+ /** Sets body to specified position
+
+ Sets body to specified position as if the body had
+ velocity to reach that point in given time frame
+
+ @param rDesiredPos
+ Position to arrive in the time frame
+
+ @param fPassedTime
+ Amount of time for the movement to take place
+ */
+ void setPositionByLinearVelocity(const ::basegfx::B2DPoint& rDesiredPos,
+ const double fPassedTime);
+
+ /// Sets linear velocity of the body
+ void setLinearVelocity(const ::basegfx::B2DVector& rVelocity);
+
+ /** Sets body to specified angle of rotation
+
+ Sets body to specified rotation as if the body had
+ angular velocity to reach that state in given time frame
+
+ @param fDesiredAngle
+ Rotation angle to arrive in the time frame
+
+ @param fPassedTime
+ Amount of time for the movement to take place
+ */
+ void setAngleByAngularVelocity(const double fDesiredAngle, const double fPassedTime);
+
+ /// Sets angular velocity of the body
+ void setAngularVelocity(const double fAngularVelocity);
+
+ /// Sets whether the body have collisions or not
+ void setCollision(const bool bCanCollide);
+
+ /// @return current angle of rotation of the body
+ double getAngle();
+
+ /// Set type of the body
+ void setType(box2DBodyType eType);
+
+ /// @return type of the body
+ box2DBodyType getType();
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */