diff --git a/.gitignore b/.gitignore index 0c7b5d1..540eec1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /Box2D_v2.2.1.zip /Box2D-2.3.1.tar.gz +/Box2D-2.4.0.tar.gz diff --git a/630.patch b/630.patch new file mode 100644 index 0000000..1ae0955 --- /dev/null +++ b/630.patch @@ -0,0 +1,156 @@ +From 131b311fe32d328b68c21443a28b08390815e9ac Mon Sep 17 00:00:00 2001 +From: Julien Bernard +Date: Fri, 7 Aug 2020 15:24:53 +0200 +Subject: [PATCH 1/2] add install for cmake + +--- + CMakeLists.txt | 14 ++++++++++++++ + src/CMakeLists.txt | 41 +++++++++++++++++++++++++++++++++++++++-- + src/box2dConfig.cmake | 3 +++ + 3 files changed, 56 insertions(+), 2 deletions(-) + create mode 100644 src/box2dConfig.cmake + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 92b2c00f9..987d0fb1a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -5,6 +5,15 @@ project(box2d VERSION 2.4.0) + + # set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo" CACHE STRING "" FORCE) + ++include(GNUInstallDirs) ++ ++if(NOT CMAKE_CONFIGURATION_TYPES) ++ if(NOT CMAKE_BUILD_TYPE) ++ message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") ++ set(CMAKE_BUILD_TYPE "RelWithDebInfo") ++ endif() ++endif() ++ + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + + add_subdirectory(src) +@@ -39,3 +48,8 @@ if (BOX2D_BUILD_TESTBED) + set_property(TARGET testbed PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/testbed") + endif() + endif() ++ ++install( ++ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/box2d" ++ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ++) +diff --git a/src/box2dConfig.cmake b/src/box2dConfig.cmake +new file mode 100644 +index 000000000..e5f8bc00b +--- /dev/null ++++ b/src/box2dConfig.cmake +@@ -0,0 +1,3 @@ ++get_filename_component(BOX2D_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) ++include("${BOX2D_CMAKE_DIR}/box2dTargets.cmake") ++include("${BOX2D_CMAKE_DIR}/box2dConfigVersion.cmake") + +From 82317c288e9052eb3272afd4f4db2a0d5654c69d Mon Sep 17 00:00:00 2001 +From: Julien Bernard +Date: Sat, 8 Aug 2020 22:32:01 +0200 +Subject: [PATCH 2/2] install documentation too + +--- + docs/CMakeLists.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt +index 623bc5e35..edffb4edd 100644 +--- a/docs/CMakeLists.txt ++++ b/docs/CMakeLists.txt +@@ -26,3 +26,7 @@ add_custom_target(docs ALL "${DOXYGEN_EXECUTABLE}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/docs" + COMMENT "Generating HTML documentation" VERBATIM) + ++install( ++ DIRECTORY "${CMAKE_BINARY_DIR}/docs/html" ++ DESTINATION "${CMAKE_INSTALL_DOCDIR}" ++) +--- box2d-2.4.0/src/CMakeLists.txt~ 2020-07-27 01:03:45.000000000 -0500 ++++ box2d-2.4.0/src/CMakeLists.txt 2020-08-10 10:11:13.717443059 -0500 +@@ -95,13 +95,40 @@ + ../include/box2d/b2_world_callbacks.h + ../include/box2d/box2d.h) + +-add_library(box2d STATIC ${BOX2D_SOURCE_FILES} ${BOX2D_HEADER_FILES}) +-target_include_directories(box2d PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) ++add_library(box2d ${BOX2D_SOURCE_FILES} ${BOX2D_HEADER_FILES}) ++target_include_directories(box2d PUBLIC $ $) + target_include_directories(box2d PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + set_target_properties(box2d PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO ++ VERSION ${PROJECT_VERSION} ++ SOVERSION ${PROJECT_VERSION_MAJOR} ++) ++ ++generate_export_header(box2d ++ BASE_NAME b2 ++ EXPORT_MACRO_NAME B2_API ++ EXPORT_FILE_NAME b2_api.h ++ STATIC_DEFINE B2_STATIC ++) ++ ++if (NOT BUILD_SHARED_LIBS) ++ target_compile_definitions(box2d ++ PUBLIC ++ B2_STATIC ++ ) ++endif() ++ ++target_compile_definitions(box2d ++ PRIVATE ++ box2d_EXPORTS ++) ++ ++install( ++ FILES ++ "${CMAKE_CURRENT_BINARY_DIR}/b2_api.h" ++ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/box2d" + ) + + source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "src" FILES ${BOX2D_SOURCE_FILES}) +--- box2d-2.4.0/src/CMakeLists.txt~ 2020-08-10 10:22:41.000000000 -0500 ++++ box2d-2.4.0/src/CMakeLists.txt 2020-08-10 10:28:32.215330614 -0500 +@@ -135,3 +135,35 @@ + + source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "src" FILES ${BOX2D_SOURCE_FILES}) + source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" PREFIX "include" FILES ${BOX2D_HEADER_FILES}) ++ ++install( ++ TARGETS box2d ++ EXPORT box2dTargets ++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ++ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ++) ++ ++install( ++ EXPORT box2dTargets ++ NAMESPACE box2d:: ++ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d" ++) ++ ++install( ++ FILES box2dConfig.cmake ++ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d" ++) ++ ++include(CMakePackageConfigHelpers) ++ ++write_basic_package_version_file( ++ "${CMAKE_CURRENT_BINARY_DIR}/box2dConfigVersion.cmake" ++ VERSION ${PROJECT_VERSION} ++ COMPATIBILITY SameMajorVersion ++) ++ ++install( ++ FILES "${CMAKE_CURRENT_BINARY_DIR}/box2dConfigVersion.cmake" ++ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d" ++) +\ No newline at end of file diff --git a/631.patch b/631.patch new file mode 100644 index 0000000..802e525 --- /dev/null +++ b/631.patch @@ -0,0 +1,1647 @@ +From 1e7275aa705cb9dfc18d0d55986423aec7cd038b Mon Sep 17 00:00:00 2001 +From: Julien Bernard +Date: Fri, 7 Aug 2020 21:08:04 +0200 +Subject: [PATCH 1/3] modify CMakeLists.txt to support shared libraries + +--- + CMakeLists.txt | 4 ++++ + src/CMakeLists.txt | 23 ++++++++++++++++++++++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 92b2c00f9..924bbf5e0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -7,6 +7,10 @@ project(box2d VERSION 2.4.0) + + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + ++set(CMAKE_CXX_VISIBILITY_PRESET hidden) ++ ++option(BUILD_SHARED_LIBS "Build Box2D as a shared library" OFF) ++ + add_subdirectory(src) + + option(BOX2D_BUILD_UNIT_TESTS "Build the Box2D unit tests" ON) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 6ef515f8c..429887359 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -1,3 +1,5 @@ ++include(GenerateExportHeader) ++ + set(BOX2D_SOURCE_FILES + collision/b2_broad_phase.cpp + collision/b2_chain_shape.cpp +From f5b2c8e0aa92b0cd9641ce44725f11d1119dce80 Mon Sep 17 00:00:00 2001 +From: Julien Bernard +Date: Fri, 7 Aug 2020 22:13:55 +0200 +Subject: [PATCH 2/3] fully support Box2D as shared library + +- add B2_API where relevant +- add missing variable declarations (mainly for testbed) +- C++ify some included headers +--- + include/box2d/b2_block_allocator.h | 5 ++-- + include/box2d/b2_body.h | 7 +++--- + include/box2d/b2_broad_phase.h | 5 ++-- + include/box2d/b2_chain_shape.h | 3 ++- + include/box2d/b2_circle_shape.h | 3 ++- + include/box2d/b2_collision.h | 38 ++++++++++++++-------------- + include/box2d/b2_contact.h | 10 +++++--- + include/box2d/b2_contact_manager.h | 5 ++-- + include/box2d/b2_distance.h | 24 ++++++++++-------- + include/box2d/b2_distance_joint.h | 5 ++-- + include/box2d/b2_draw.h | 11 ++++---- + include/box2d/b2_dynamic_tree.h | 5 ++-- + include/box2d/b2_edge_shape.h | 7 +++--- + include/box2d/b2_fixture.h | 9 ++++--- + include/box2d/b2_friction_joint.h | 5 ++-- + include/box2d/b2_gear_joint.h | 4 +-- + include/box2d/b2_growable_stack.h | 5 ++-- + include/box2d/b2_joint.h | 13 +++++----- + include/box2d/b2_math.h | 40 ++++++++++++++++-------------- + include/box2d/b2_motor_joint.h | 7 +++--- + include/box2d/b2_mouse_joint.h | 7 +++--- + include/box2d/b2_polygon_shape.h | 3 ++- + include/box2d/b2_prismatic_joint.h | 5 ++-- + include/box2d/b2_pulley_joint.h | 7 +++--- + include/box2d/b2_revolute_joint.h | 7 +++--- + include/box2d/b2_rope.h | 11 ++++---- + include/box2d/b2_rope_joint.h | 5 ++-- + include/box2d/b2_settings.h | 24 ++++++++++-------- + include/box2d/b2_shape.h | 7 +++--- + include/box2d/b2_stack_allocator.h | 5 ++-- + include/box2d/b2_time_of_impact.h | 14 ++++++++--- + include/box2d/b2_time_step.h | 11 ++++---- + include/box2d/b2_timer.h | 3 ++- + include/box2d/b2_weld_joint.h | 7 +++--- + include/box2d/b2_wheel_joint.h | 5 ++-- + include/box2d/b2_world.h | 7 +++--- + include/box2d/b2_world_callbacks.h | 13 +++++----- + src/CMakeLists.txt | 18 ++++++++++++-- + 38 files changed, 218 insertions(+), 152 deletions(-) + +diff --git a/include/box2d/b2_block_allocator.h b/include/box2d/b2_block_allocator.h +index 48957343e..95c12de89 100644 +--- a/include/box2d/b2_block_allocator.h ++++ b/include/box2d/b2_block_allocator.h +@@ -23,7 +23,8 @@ + #ifndef B2_BLOCK_ALLOCATOR_H + #define B2_BLOCK_ALLOCATOR_H + +-#include "box2d/b2_settings.h" ++#include "b2_api.h" ++#include "b2_settings.h" + + const int32 b2_blockSizeCount = 14; + +@@ -33,7 +34,7 @@ struct b2Chunk; + /// This is a small object allocator used for allocating small + /// objects that persist for more than one time step. + /// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp +-class b2BlockAllocator ++class B2_API b2BlockAllocator + { + public: + b2BlockAllocator(); +diff --git a/include/box2d/b2_body.h b/include/box2d/b2_body.h +index 6ba8574de..81a791391 100644 +--- a/include/box2d/b2_body.h ++++ b/include/box2d/b2_body.h +@@ -23,6 +23,7 @@ + #ifndef B2_BODY_H + #define B2_BODY_H + ++#include "b2_api.h" + #include "b2_math.h" + #include "b2_shape.h" + +@@ -51,7 +52,7 @@ enum b2BodyType + + /// A body definition holds all the data needed to construct a rigid body. + /// You can safely re-use body definitions. Shapes are added to a body after construction. +-struct b2BodyDef ++struct B2_API b2BodyDef + { + /// This constructor sets the body definition default values. + b2BodyDef() +@@ -128,7 +129,7 @@ struct b2BodyDef + }; + + /// A rigid body. These are created via b2World::CreateBody. +-class b2Body ++class B2_API b2Body + { + public: + /// Creates a fixture and attach it to this body. Use this function if you need +@@ -398,7 +399,7 @@ class b2Body + friend class b2ContactManager; + friend class b2ContactSolver; + friend class b2Contact; +- ++ + friend class b2DistanceJoint; + friend class b2FrictionJoint; + friend class b2GearJoint; +diff --git a/include/box2d/b2_broad_phase.h b/include/box2d/b2_broad_phase.h +index cf1cf6773..cc882ab47 100644 +--- a/include/box2d/b2_broad_phase.h ++++ b/include/box2d/b2_broad_phase.h +@@ -23,11 +23,12 @@ + #ifndef B2_BROAD_PHASE_H + #define B2_BROAD_PHASE_H + ++#include "b2_api.h" + #include "b2_settings.h" + #include "b2_collision.h" + #include "b2_dynamic_tree.h" + +-struct b2Pair ++struct B2_API b2Pair + { + int32 proxyIdA; + int32 proxyIdB; +@@ -36,7 +37,7 @@ struct b2Pair + /// The broad-phase is used for computing pairs and performing volume queries and ray casts. + /// This broad-phase does not persist pairs. Instead, this reports potentially new pairs. + /// It is up to the client to consume the new pairs and to track subsequent overlap. +-class b2BroadPhase ++class B2_API b2BroadPhase + { + public: + +diff --git a/include/box2d/b2_chain_shape.h b/include/box2d/b2_chain_shape.h +index 9ba0b8b1c..da2605d62 100644 +--- a/include/box2d/b2_chain_shape.h ++++ b/include/box2d/b2_chain_shape.h +@@ -23,6 +23,7 @@ + #ifndef B2_CHAIN_SHAPE_H + #define B2_CHAIN_SHAPE_H + ++#include "b2_api.h" + #include "b2_shape.h" + + class b2EdgeShape; +@@ -32,7 +33,7 @@ class b2EdgeShape; + /// This provides a counter-clockwise winding like the polygon shape. + /// Connectivity information is used to create smooth collisions. + /// @warning the chain will not collide properly if there are self-intersections. +-class b2ChainShape : public b2Shape ++class B2_API b2ChainShape : public b2Shape + { + public: + b2ChainShape(); +diff --git a/include/box2d/b2_circle_shape.h b/include/box2d/b2_circle_shape.h +index 009d77db5..5e330f5a7 100644 +--- a/include/box2d/b2_circle_shape.h ++++ b/include/box2d/b2_circle_shape.h +@@ -23,10 +23,11 @@ + #ifndef B2_CIRCLE_SHAPE_H + #define B2_CIRCLE_SHAPE_H + ++#include "b2_api.h" + #include "b2_shape.h" + + /// A solid circle shape +-class b2CircleShape : public b2Shape ++class B2_API b2CircleShape : public b2Shape + { + public: + b2CircleShape(); +diff --git a/include/box2d/b2_collision.h b/include/box2d/b2_collision.h +index aaa207b35..a6a5472cb 100644 +--- a/include/box2d/b2_collision.h ++++ b/include/box2d/b2_collision.h +@@ -23,8 +23,10 @@ + #ifndef B2_COLLISION_H + #define B2_COLLISION_H + ++#include ++ ++#include "b2_api.h" + #include "b2_math.h" +-#include + + /// @file + /// Structures and functions used for computing contact points, distance +@@ -39,7 +41,7 @@ const uint8 b2_nullFeature = UCHAR_MAX; + + /// The features that intersect to form the contact point + /// This must be 4 bytes or less. +-struct b2ContactFeature ++struct B2_API b2ContactFeature + { + enum Type + { +@@ -54,7 +56,7 @@ struct b2ContactFeature + }; + + /// Contact ids to facilitate warm starting. +-union b2ContactID ++union B2_API b2ContactID + { + b2ContactFeature cf; + uint32 key; ///< Used to quickly compare contact ids. +@@ -70,7 +72,7 @@ union b2ContactID + /// This structure is stored across time steps, so we keep it small. + /// Note: the impulses are used for internal caching and may not + /// provide reliable contact forces, especially for high speed collisions. +-struct b2ManifoldPoint ++struct B2_API b2ManifoldPoint + { + b2Vec2 localPoint; ///< usage depends on manifold type + float normalImpulse; ///< the non-penetration impulse +@@ -94,7 +96,7 @@ struct b2ManifoldPoint + /// account for movement, which is critical for continuous physics. + /// All contact scenarios must be expressed in one of these types. + /// This structure is stored across time steps, so we keep it small. +-struct b2Manifold ++struct B2_API b2Manifold + { + enum Type + { +@@ -111,7 +113,7 @@ struct b2Manifold + }; + + /// This is used to compute the current state of a contact manifold. +-struct b2WorldManifold ++struct B2_API b2WorldManifold + { + /// Evaluate the manifold with supplied transforms. This assumes + /// modest motion from the original state. This does not change the +@@ -137,18 +139,18 @@ enum b2PointState + + /// Compute the point states given two manifolds. The states pertain to the transition from manifold1 + /// to manifold2. So state1 is either persist or remove while state2 is either add or persist. +-void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], ++B2_API void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], + const b2Manifold* manifold1, const b2Manifold* manifold2); + + /// Used for computing contact manifolds. +-struct b2ClipVertex ++struct B2_API b2ClipVertex + { + b2Vec2 v; + b2ContactID id; + }; + + /// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). +-struct b2RayCastInput ++struct B2_API b2RayCastInput + { + b2Vec2 p1, p2; + float maxFraction; +@@ -156,14 +158,14 @@ struct b2RayCastInput + + /// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2 + /// come from b2RayCastInput. +-struct b2RayCastOutput ++struct B2_API b2RayCastOutput + { + b2Vec2 normal; + float fraction; + }; + + /// An axis aligned bounding box. +-struct b2AABB ++struct B2_API b2AABB + { + /// Verify that the bounds are sorted. + bool IsValid() const; +@@ -220,36 +222,36 @@ struct b2AABB + }; + + /// Compute the collision manifold between two circles. +-void b2CollideCircles(b2Manifold* manifold, ++B2_API void b2CollideCircles(b2Manifold* manifold, + const b2CircleShape* circleA, const b2Transform& xfA, + const b2CircleShape* circleB, const b2Transform& xfB); + + /// Compute the collision manifold between a polygon and a circle. +-void b2CollidePolygonAndCircle(b2Manifold* manifold, ++B2_API void b2CollidePolygonAndCircle(b2Manifold* manifold, + const b2PolygonShape* polygonA, const b2Transform& xfA, + const b2CircleShape* circleB, const b2Transform& xfB); + + /// Compute the collision manifold between two polygons. +-void b2CollidePolygons(b2Manifold* manifold, ++B2_API void b2CollidePolygons(b2Manifold* manifold, + const b2PolygonShape* polygonA, const b2Transform& xfA, + const b2PolygonShape* polygonB, const b2Transform& xfB); + + /// Compute the collision manifold between an edge and a circle. +-void b2CollideEdgeAndCircle(b2Manifold* manifold, ++B2_API void b2CollideEdgeAndCircle(b2Manifold* manifold, + const b2EdgeShape* polygonA, const b2Transform& xfA, + const b2CircleShape* circleB, const b2Transform& xfB); + + /// Compute the collision manifold between an edge and a polygon. +-void b2CollideEdgeAndPolygon(b2Manifold* manifold, ++B2_API void b2CollideEdgeAndPolygon(b2Manifold* manifold, + const b2EdgeShape* edgeA, const b2Transform& xfA, + const b2PolygonShape* circleB, const b2Transform& xfB); + + /// Clipping for contact manifolds. +-int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], ++B2_API int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], + const b2Vec2& normal, float offset, int32 vertexIndexA); + + /// Determine if two generic shapes overlap. +-bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, ++B2_API bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, + const b2Shape* shapeB, int32 indexB, + const b2Transform& xfA, const b2Transform& xfB); + +diff --git a/include/box2d/b2_contact.h b/include/box2d/b2_contact.h +index d4c59c620..eef7b3b6a 100644 +--- a/include/box2d/b2_contact.h ++++ b/include/box2d/b2_contact.h +@@ -23,6 +23,7 @@ + #ifndef B2_CONTACT_H + #define B2_CONTACT_H + ++#include "b2_api.h" + #include "b2_collision.h" + #include "b2_fixture.h" + #include "b2_math.h" +@@ -55,7 +56,7 @@ typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA, + b2BlockAllocator* allocator); + typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator); + +-struct b2ContactRegister ++struct B2_API b2ContactRegister + { + b2ContactCreateFcn* createFcn; + b2ContactDestroyFcn* destroyFcn; +@@ -67,7 +68,7 @@ struct b2ContactRegister + /// is an edge. A contact edge belongs to a doubly linked list + /// maintained in each attached body. Each contact has two contact + /// nodes, one for each attached body. +-struct b2ContactEdge ++struct B2_API b2ContactEdge + { + b2Body* other; ///< provides quick access to the other body attached. + b2Contact* contact; ///< the contact +@@ -78,7 +79,7 @@ struct b2ContactEdge + /// The class manages contact between two shapes. A contact exists for each overlapping + /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist + /// that has no contact points. +-class b2Contact ++class B2_API b2Contact + { + public: + +@@ -350,4 +351,7 @@ inline float b2Contact::GetTangentSpeed() const + return m_tangentSpeed; + } + ++/// internal for testbed, do not use ++extern B2_API bool g_blockSolve; ++ + #endif +diff --git a/include/box2d/b2_contact_manager.h b/include/box2d/b2_contact_manager.h +index efa156847..fbd3b4d40 100644 +--- a/include/box2d/b2_contact_manager.h ++++ b/include/box2d/b2_contact_manager.h +@@ -23,6 +23,7 @@ + #ifndef B2_CONTACT_MANAGER_H + #define B2_CONTACT_MANAGER_H + ++#include "b2_api.h" + #include "b2_broad_phase.h" + + class b2Contact; +@@ -31,7 +32,7 @@ class b2ContactListener; + class b2BlockAllocator; + + // Delegate of b2World. +-class b2ContactManager ++class B2_API b2ContactManager + { + public: + b2ContactManager(); +@@ -44,7 +45,7 @@ class b2ContactManager + void Destroy(b2Contact* c); + + void Collide(); +- ++ + b2BroadPhase m_broadPhase; + b2Contact* m_contactList; + int32 m_contactCount; +diff --git a/include/box2d/b2_distance.h b/include/box2d/b2_distance.h +index 3fcefc413..12e993fe6 100644 +--- a/include/box2d/b2_distance.h ++++ b/include/box2d/b2_distance.h +@@ -23,13 +23,14 @@ + #ifndef B2_DISTANCE_H + #define B2_DISTANCE_H + ++#include "b2_api.h" + #include "b2_math.h" + + class b2Shape; + + /// A distance proxy is used by the GJK algorithm. + /// It encapsulates any shape. +-struct b2DistanceProxy ++struct B2_API b2DistanceProxy + { + b2DistanceProxy() : m_vertices(nullptr), m_count(0), m_radius(0.0f) {} + +@@ -61,7 +62,7 @@ struct b2DistanceProxy + + /// Used to warm start b2Distance. + /// Set count to zero on first call. +-struct b2SimplexCache ++struct B2_API b2SimplexCache + { + float metric; ///< length or area + uint16 count; +@@ -71,8 +72,8 @@ struct b2SimplexCache + + /// Input for b2Distance. + /// You have to option to use the shape radii +-/// in the computation. Even +-struct b2DistanceInput ++/// in the computation. Even ++struct B2_API b2DistanceInput + { + b2DistanceProxy proxyA; + b2DistanceProxy proxyB; +@@ -82,7 +83,7 @@ struct b2DistanceInput + }; + + /// Output for b2Distance. +-struct b2DistanceOutput ++struct B2_API b2DistanceOutput + { + b2Vec2 pointA; ///< closest point on shapeA + b2Vec2 pointB; ///< closest point on shapeB +@@ -93,12 +94,12 @@ struct b2DistanceOutput + /// Compute the closest points between two shapes. Supports any combination of: + /// b2CircleShape, b2PolygonShape, b2EdgeShape. The simplex cache is input/output. + /// On the first call set b2SimplexCache.count to zero. +-void b2Distance(b2DistanceOutput* output, +- b2SimplexCache* cache, ++B2_API void b2Distance(b2DistanceOutput* output, ++ b2SimplexCache* cache, + const b2DistanceInput* input); + + /// Input parameters for b2ShapeCast +-struct b2ShapeCastInput ++struct B2_API b2ShapeCastInput + { + b2DistanceProxy proxyA; + b2DistanceProxy proxyB; +@@ -108,7 +109,7 @@ struct b2ShapeCastInput + }; + + /// Output results for b2ShapeCast +-struct b2ShapeCastOutput ++struct B2_API b2ShapeCastOutput + { + b2Vec2 point; + b2Vec2 normal; +@@ -167,4 +168,7 @@ inline const b2Vec2& b2DistanceProxy::GetSupportVertex(const b2Vec2& d) const + return m_vertices[bestIndex]; + } + ++/// internal for testbed, do not use ++extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; ++ + #endif +diff --git a/include/box2d/b2_distance_joint.h b/include/box2d/b2_distance_joint.h +index b339e9239..51793fbac 100644 +--- a/include/box2d/b2_distance_joint.h ++++ b/include/box2d/b2_distance_joint.h +@@ -23,6 +23,7 @@ + #ifndef B2_DISTANCE_JOINT_H + #define B2_DISTANCE_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Distance joint definition. This requires defining an anchor point on both +@@ -30,7 +31,7 @@ + /// so that the initial configuration can violate the constraint + /// slightly. This helps when saving and loading a game. + /// @warning Do not use a zero or short length. +-struct b2DistanceJointDef : public b2JointDef ++struct B2_API b2DistanceJointDef : public b2JointDef + { + b2DistanceJointDef() + { +@@ -65,7 +66,7 @@ struct b2DistanceJointDef : public b2JointDef + + /// A distance joint constrains two points on two bodies to remain at a fixed + /// distance from each other. You can view this as a massless, rigid rod. +-class b2DistanceJoint : public b2Joint ++class B2_API b2DistanceJoint : public b2Joint + { + public: + +diff --git a/include/box2d/b2_draw.h b/include/box2d/b2_draw.h +index 10cbf866f..a4d171187 100644 +--- a/include/box2d/b2_draw.h ++++ b/include/box2d/b2_draw.h +@@ -23,10 +23,11 @@ + #ifndef B2_DRAW_H + #define B2_DRAW_H + ++#include "b2_api.h" + #include "b2_math.h" + + /// Color for debug drawing. Each value has the range [0,1]. +-struct b2Color ++struct B2_API b2Color + { + b2Color() {} + b2Color(float rIn, float gIn, float bIn, float aIn = 1.0f) +@@ -44,7 +45,7 @@ struct b2Color + + /// Implement and register this class with a b2World to provide debug drawing of physics + /// entities in your game. +-class b2Draw ++class B2_API b2Draw + { + public: + b2Draw(); +@@ -65,7 +66,7 @@ class b2Draw + + /// Get the drawing flags. + uint32 GetFlags() const; +- ++ + /// Append flags to the current flags. + void AppendFlags(uint32 flags); + +@@ -80,10 +81,10 @@ class b2Draw + + /// Draw a circle. + virtual void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) = 0; +- ++ + /// Draw a solid circle. + virtual void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) = 0; +- ++ + /// Draw a line segment. + virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0; + +diff --git a/include/box2d/b2_dynamic_tree.h b/include/box2d/b2_dynamic_tree.h +index b3ddb97ca..a3df1175d 100644 +--- a/include/box2d/b2_dynamic_tree.h ++++ b/include/box2d/b2_dynamic_tree.h +@@ -23,13 +23,14 @@ + #ifndef B2_DYNAMIC_TREE_H + #define B2_DYNAMIC_TREE_H + ++#include "b2_api.h" + #include "b2_collision.h" + #include "b2_growable_stack.h" + + #define b2_nullNode (-1) + + /// A node in the dynamic tree. The client does not interact with this directly. +-struct b2TreeNode ++struct B2_API b2TreeNode + { + bool IsLeaf() const + { +@@ -64,7 +65,7 @@ struct b2TreeNode + /// object to move by small amounts without triggering a tree update. + /// + /// Nodes are pooled and relocatable, so we use node indices rather than pointers. +-class b2DynamicTree ++class B2_API b2DynamicTree + { + public: + /// Constructing the tree initializes the node pool. +diff --git a/include/box2d/b2_edge_shape.h b/include/box2d/b2_edge_shape.h +index ed79b43e2..b930ee872 100644 +--- a/include/box2d/b2_edge_shape.h ++++ b/include/box2d/b2_edge_shape.h +@@ -23,12 +23,13 @@ + #ifndef B2_EDGE_SHAPE_H + #define B2_EDGE_SHAPE_H + ++#include "b2_api.h" + #include "b2_shape.h" + + /// A line segment (edge) shape. These can be connected in chains or loops + /// to other edge shapes. Edges created independently are two-sided and do +-/// no provide smooth movement across junctions. +-class b2EdgeShape : public b2Shape ++/// no provide smooth movement across junctions. ++class B2_API b2EdgeShape : public b2Shape + { + public: + b2EdgeShape(); +@@ -60,7 +61,7 @@ class b2EdgeShape : public b2Shape + + /// @see b2Shape::ComputeMass + void ComputeMass(b2MassData* massData, float density) const override; +- ++ + /// These are the edge vertices + b2Vec2 m_vertex1, m_vertex2; + +diff --git a/include/box2d/b2_fixture.h b/include/box2d/b2_fixture.h +index 4cdde74d8..3c8aa27a1 100644 +--- a/include/box2d/b2_fixture.h ++++ b/include/box2d/b2_fixture.h +@@ -23,6 +23,7 @@ + #ifndef B2_FIXTURE_H + #define B2_FIXTURE_H + ++#include "b2_api.h" + #include "b2_body.h" + #include "b2_collision.h" + #include "b2_shape.h" +@@ -33,7 +34,7 @@ class b2BroadPhase; + class b2Fixture; + + /// This holds contact filtering data. +-struct b2Filter ++struct B2_API b2Filter + { + b2Filter() + { +@@ -57,7 +58,7 @@ struct b2Filter + + /// A fixture definition is used to create a fixture. This class defines an + /// abstract fixture definition. You can reuse fixture definitions safely. +-struct b2FixtureDef ++struct B2_API b2FixtureDef + { + /// The constructor sets the default fixture definition values. + b2FixtureDef() +@@ -95,7 +96,7 @@ struct b2FixtureDef + }; + + /// This proxy is used internally to connect fixtures to the broad-phase. +-struct b2FixtureProxy ++struct B2_API b2FixtureProxy + { + b2AABB aabb; + b2Fixture* fixture; +@@ -108,7 +109,7 @@ struct b2FixtureProxy + /// such as friction, collision filters, etc. + /// Fixtures are created via b2Body::CreateFixture. + /// @warning you cannot reuse fixtures. +-class b2Fixture ++class B2_API b2Fixture + { + public: + /// Get the type of the child shape. You can use this to down cast to the concrete shape. +diff --git a/include/box2d/b2_friction_joint.h b/include/box2d/b2_friction_joint.h +index d7b88245e..99922c3a3 100644 +--- a/include/box2d/b2_friction_joint.h ++++ b/include/box2d/b2_friction_joint.h +@@ -23,10 +23,11 @@ + #ifndef B2_FRICTION_JOINT_H + #define B2_FRICTION_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Friction joint definition. +-struct b2FrictionJointDef : public b2JointDef ++struct B2_API b2FrictionJointDef : public b2JointDef + { + b2FrictionJointDef() + { +@@ -56,7 +57,7 @@ struct b2FrictionJointDef : public b2JointDef + + /// Friction joint. This is used for top-down friction. + /// It provides 2D translational friction and angular friction. +-class b2FrictionJoint : public b2Joint ++class B2_API b2FrictionJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_gear_joint.h b/include/box2d/b2_gear_joint.h +index 69e67a199..18237a142 100644 +--- a/include/box2d/b2_gear_joint.h ++++ b/include/box2d/b2_gear_joint.h +@@ -27,7 +27,7 @@ + + /// Gear joint definition. This definition requires two existing + /// revolute or prismatic joints (any combination will work). +-struct b2GearJointDef : public b2JointDef ++struct B2_API b2GearJointDef : public b2JointDef + { + b2GearJointDef() + { +@@ -57,7 +57,7 @@ struct b2GearJointDef : public b2JointDef + /// of length or units of 1/length. + /// @warning You have to manually destroy the gear joint if joint1 or joint2 + /// is destroyed. +-class b2GearJoint : public b2Joint ++class B2_API b2GearJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_growable_stack.h b/include/box2d/b2_growable_stack.h +index a24984f0c..ae39db9d5 100644 +--- a/include/box2d/b2_growable_stack.h ++++ b/include/box2d/b2_growable_stack.h +@@ -23,8 +23,9 @@ + #ifndef B2_GROWABLE_STACK_H + #define B2_GROWABLE_STACK_H + ++#include ++ + #include "b2_settings.h" +-#include + + /// This is a growable LIFO stack with an initial capacity of N. + /// If the stack size exceeds the initial capacity, the heap is used +@@ -56,7 +57,7 @@ class b2GrowableStack + T* old = m_stack; + m_capacity *= 2; + m_stack = (T*)b2Alloc(m_capacity * sizeof(T)); +- memcpy(m_stack, old, m_count * sizeof(T)); ++ std::memcpy(m_stack, old, m_count * sizeof(T)); + if (old != m_array) + { + b2Free(old); +diff --git a/include/box2d/b2_joint.h b/include/box2d/b2_joint.h +index c33ec90af..73ead3f90 100644 +--- a/include/box2d/b2_joint.h ++++ b/include/box2d/b2_joint.h +@@ -23,6 +23,7 @@ + #ifndef B2_JOINT_H + #define B2_JOINT_H + ++#include "b2_api.h" + #include "b2_math.h" + + class b2Body; +@@ -47,7 +48,7 @@ enum b2JointType + e_motorJoint + }; + +-struct b2Jacobian ++struct B2_API b2Jacobian + { + b2Vec2 linear; + float angularA; +@@ -59,7 +60,7 @@ struct b2Jacobian + /// is an edge. A joint edge belongs to a doubly linked list + /// maintained in each attached body. Each joint has two joint + /// nodes, one for each attached body. +-struct b2JointEdge ++struct B2_API b2JointEdge + { + b2Body* other; ///< provides quick access to the other body attached. + b2Joint* joint; ///< the joint +@@ -68,7 +69,7 @@ struct b2JointEdge + }; + + /// Joint definitions are used to construct joints. +-struct b2JointDef ++struct B2_API b2JointDef + { + b2JointDef() + { +@@ -96,18 +97,18 @@ struct b2JointDef + }; + + /// Utility to compute linear stiffness values from frequency and damping ratio +-void b2LinearStiffness(float& stiffness, float& damping, ++B2_API void b2LinearStiffness(float& stiffness, float& damping, + float frequencyHertz, float dampingRatio, + const b2Body* bodyA, const b2Body* bodyB); + + /// Utility to compute rotational stiffness values frequency and damping ratio +-void b2AngularStiffness(float& stiffness, float& damping, ++B2_API void b2AngularStiffness(float& stiffness, float& damping, + float frequencyHertz, float dampingRatio, + const b2Body* bodyA, const b2Body* bodyB); + + /// The base joint class. Joints are used to constraint two bodies together in + /// various fashions. Some joints also feature limits and motors. +-class b2Joint ++class B2_API b2Joint + { + public: + +diff --git a/include/box2d/b2_math.h b/include/box2d/b2_math.h +index afe421ba8..08d130841 100644 +--- a/include/box2d/b2_math.h ++++ b/include/box2d/b2_math.h +@@ -23,20 +23,22 @@ + #ifndef B2_MATH_H + #define B2_MATH_H + ++#include ++ ++#include "b2_api.h" + #include "b2_settings.h" +-#include + + /// This function is used to ensure that a floating point number is not a NaN or infinity. + inline bool b2IsValid(float x) + { +- return isfinite(x); ++ return std::isfinite(x); + } + +-#define b2Sqrt(x) sqrtf(x) +-#define b2Atan2(y, x) atan2f(y, x) ++#define b2Sqrt(x) std::sqrt(x) ++#define b2Atan2(y, x) std::atan2(y, x) + + /// A 2D column vector. +-struct b2Vec2 ++struct B2_API b2Vec2 + { + /// Default constructor does nothing (for performance). + b2Vec2() {} +@@ -52,7 +54,7 @@ struct b2Vec2 + + /// Negate this vector. + b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; } +- ++ + /// Read from and indexed element. + float operator () (int32 i) const + { +@@ -70,7 +72,7 @@ struct b2Vec2 + { + x += v.x; y += v.y; + } +- ++ + /// Subtract a vector from this vector. + void operator -= (const b2Vec2& v) + { +@@ -127,7 +129,7 @@ struct b2Vec2 + }; + + /// A 2D column vector with 3 elements. +-struct b2Vec3 ++struct B2_API b2Vec3 + { + /// Default constructor does nothing (for performance). + b2Vec3() {} +@@ -166,7 +168,7 @@ struct b2Vec3 + }; + + /// A 2-by-2 matrix. Stored in column-major order. +-struct b2Mat22 ++struct B2_API b2Mat22 + { + /// The default constructor does nothing (for performance). + b2Mat22() {} +@@ -240,7 +242,7 @@ struct b2Mat22 + }; + + /// A 3-by-3 matrix. Stored in column-major order. +-struct b2Mat33 ++struct B2_API b2Mat33 + { + /// The default constructor does nothing (for performance). + b2Mat33() {} +@@ -282,7 +284,7 @@ struct b2Mat33 + }; + + /// Rotation +-struct b2Rot ++struct B2_API b2Rot + { + b2Rot() {} + +@@ -290,16 +292,16 @@ struct b2Rot + explicit b2Rot(float angle) + { + /// TODO_ERIN optimize +- s = sinf(angle); +- c = cosf(angle); ++ s = std::sin(angle); ++ c = std::cos(angle); + } + + /// Set using an angle in radians. + void Set(float angle) + { + /// TODO_ERIN optimize +- s = sinf(angle); +- c = cosf(angle); ++ s = std::sin(angle); ++ c = std::cos(angle); + } + + /// Set to the identity rotation +@@ -333,7 +335,7 @@ struct b2Rot + + /// A transform contains translation and rotation. It is used to represent + /// the position and orientation of rigid frames. +-struct b2Transform ++struct B2_API b2Transform + { + /// The default constructor does nothing. + b2Transform() {} +@@ -363,7 +365,7 @@ struct b2Transform + /// Shapes are defined with respect to the body origin, which may + /// no coincide with the center of mass. However, to support dynamics + /// we must interpolate the center of mass position. +-struct b2Sweep ++struct B2_API b2Sweep + { + /// Get the interpolated transform at a specific time. + /// @param transform the output transform +@@ -387,7 +389,7 @@ struct b2Sweep + }; + + /// Useful constant +-extern const b2Vec2 b2Vec2_zero; ++extern B2_API const b2Vec2 b2Vec2_zero; + + /// Perform the dot product on two vectors. + inline float b2Dot(const b2Vec2& a, const b2Vec2& b) +@@ -704,7 +706,7 @@ inline void b2Sweep::Advance(float alpha) + inline void b2Sweep::Normalize() + { + float twoPi = 2.0f * b2_pi; +- float d = twoPi * floorf(a0 / twoPi); ++ float d = twoPi * std::floor(a0 / twoPi); + a0 -= d; + a -= d; + } +diff --git a/include/box2d/b2_motor_joint.h b/include/box2d/b2_motor_joint.h +index c3f1adcbb..c88115f20 100644 +--- a/include/box2d/b2_motor_joint.h ++++ b/include/box2d/b2_motor_joint.h +@@ -23,10 +23,11 @@ + #ifndef B2_MOTOR_JOINT_H + #define B2_MOTOR_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Motor joint definition. +-struct b2MotorJointDef : public b2JointDef ++struct B2_API b2MotorJointDef : public b2JointDef + { + b2MotorJointDef() + { +@@ -46,7 +47,7 @@ struct b2MotorJointDef : public b2JointDef + + /// The bodyB angle minus bodyA angle in radians. + float angularOffset; +- ++ + /// The maximum motor force in N. + float maxForce; + +@@ -60,7 +61,7 @@ struct b2MotorJointDef : public b2JointDef + /// A motor joint is used to control the relative motion + /// between two bodies. A typical usage is to control the movement + /// of a dynamic body with respect to the ground. +-class b2MotorJoint : public b2Joint ++class B2_API b2MotorJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_mouse_joint.h b/include/box2d/b2_mouse_joint.h +index ebaa02592..fcbc56a70 100644 +--- a/include/box2d/b2_mouse_joint.h ++++ b/include/box2d/b2_mouse_joint.h +@@ -23,11 +23,12 @@ + #ifndef B2_MOUSE_JOINT_H + #define B2_MOUSE_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Mouse joint definition. This requires a world target point, + /// tuning parameters, and the time step. +-struct b2MouseJointDef : public b2JointDef ++struct B2_API b2MouseJointDef : public b2JointDef + { + b2MouseJointDef() + { +@@ -61,7 +62,7 @@ struct b2MouseJointDef : public b2JointDef + /// NOTE: this joint is not documented in the manual because it was + /// developed to be used in the testbed. If you want to learn how to + /// use the mouse joint, look at the testbed. +-class b2MouseJoint : public b2Joint ++class B2_API b2MouseJoint : public b2Joint + { + public: + +diff --git a/include/box2d/b2_polygon_shape.h b/include/box2d/b2_polygon_shape.h +index 52f4cc0ec..5a4e563f8 100644 +--- a/include/box2d/b2_polygon_shape.h ++++ b/include/box2d/b2_polygon_shape.h +@@ -22,13 +22,14 @@ + #ifndef B2_POLYGON_SHAPE_H + #define B2_POLYGON_SHAPE_H + ++#include "b2_api.h" + #include "b2_shape.h" + + /// A solid convex polygon. It is assumed that the interior of the polygon is to + /// the left of each edge. + /// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices. + /// In most cases you should not need many vertices for a convex polygon. +-class b2PolygonShape : public b2Shape ++class B2_API b2PolygonShape : public b2Shape + { + public: + b2PolygonShape(); +diff --git a/include/box2d/b2_prismatic_joint.h b/include/box2d/b2_prismatic_joint.h +index 09cbad540..9d12d2126 100644 +--- a/include/box2d/b2_prismatic_joint.h ++++ b/include/box2d/b2_prismatic_joint.h +@@ -23,6 +23,7 @@ + #ifndef B2_PRISMATIC_JOINT_H + #define B2_PRISMATIC_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Prismatic joint definition. This requires defining a line of +@@ -31,7 +32,7 @@ + /// can violate the constraint slightly. The joint translation is zero + /// when the local anchor points coincide in world space. Using local + /// anchors and a local axis helps when saving and loading a game. +-struct b2PrismaticJointDef : public b2JointDef ++struct B2_API b2PrismaticJointDef : public b2JointDef + { + b2PrismaticJointDef() + { +@@ -87,7 +88,7 @@ struct b2PrismaticJointDef : public b2JointDef + /// along an axis fixed in bodyA. Relative rotation is prevented. You can + /// use a joint limit to restrict the range of motion and a joint motor to + /// drive the motion or to model joint friction. +-class b2PrismaticJoint : public b2Joint ++class B2_API b2PrismaticJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_pulley_joint.h b/include/box2d/b2_pulley_joint.h +index 14f12c41f..6b1445641 100644 +--- a/include/box2d/b2_pulley_joint.h ++++ b/include/box2d/b2_pulley_joint.h +@@ -23,13 +23,14 @@ + #ifndef B2_PULLEY_JOINT_H + #define B2_PULLEY_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + const float b2_minPulleyLength = 2.0f; + + /// Pulley joint definition. This requires two ground anchors, + /// two dynamic body anchor points, and a pulley ratio. +-struct b2PulleyJointDef : public b2JointDef ++struct B2_API b2PulleyJointDef : public b2JointDef + { + b2PulleyJointDef() + { +@@ -80,7 +81,7 @@ struct b2PulleyJointDef : public b2JointDef + /// work better when combined with prismatic joints. You should also cover the + /// the anchor points with static shapes to prevent one side from going to + /// zero length. +-class b2PulleyJoint : public b2Joint ++class B2_API b2PulleyJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +@@ -129,7 +130,7 @@ class b2PulleyJoint : public b2Joint + b2Vec2 m_groundAnchorB; + float m_lengthA; + float m_lengthB; +- ++ + // Solver shared + b2Vec2 m_localAnchorA; + b2Vec2 m_localAnchorB; +diff --git a/include/box2d/b2_revolute_joint.h b/include/box2d/b2_revolute_joint.h +index f202e3551..36ad5314e 100644 +--- a/include/box2d/b2_revolute_joint.h ++++ b/include/box2d/b2_revolute_joint.h +@@ -23,6 +23,7 @@ + #ifndef B2_REVOLUTE_JOINT_H + #define B2_REVOLUTE_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Revolute joint definition. This requires defining an anchor point where the +@@ -35,7 +36,7 @@ + /// 1. you might not know where the center of mass will be. + /// 2. if you add/remove shapes from a body and recompute the mass, + /// the joints will be broken. +-struct b2RevoluteJointDef : public b2JointDef ++struct B2_API b2RevoluteJointDef : public b2JointDef + { + b2RevoluteJointDef() + { +@@ -90,7 +91,7 @@ struct b2RevoluteJointDef : public b2JointDef + /// a joint limit that specifies a lower and upper angle. You can use a motor + /// to drive the relative rotation about the shared point. A maximum motor torque + /// is provided so that infinite forces are not generated. +-class b2RevoluteJoint : public b2Joint ++class B2_API b2RevoluteJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +@@ -161,7 +162,7 @@ class b2RevoluteJoint : public b2Joint + void Draw(b2Draw* draw) const override; + + protected: +- ++ + friend class b2Joint; + friend class b2GearJoint; + +diff --git a/include/box2d/b2_rope.h b/include/box2d/b2_rope.h +index 5f1cc4073..920e0a454 100644 +--- a/include/box2d/b2_rope.h ++++ b/include/box2d/b2_rope.h +@@ -23,6 +23,7 @@ + #ifndef B2_ROPE_H + #define B2_ROPE_H + ++#include "b2_api.h" + #include "b2_math.h" + + class b2Draw; +@@ -45,7 +46,7 @@ enum b2BendingModel + }; + + /// +-struct b2RopeTuning ++struct B2_API b2RopeTuning + { + b2RopeTuning() + { +@@ -75,8 +76,8 @@ struct b2RopeTuning + bool warmStart; + }; + +-/// +-struct b2RopeDef ++/// ++struct B2_API b2RopeDef + { + b2RopeDef() + { +@@ -95,8 +96,8 @@ struct b2RopeDef + b2RopeTuning tuning; + }; + +-/// +-class b2Rope ++/// ++class B2_API b2Rope + { + public: + b2Rope(); +diff --git a/include/box2d/b2_rope_joint.h b/include/box2d/b2_rope_joint.h +index b254b3a22..9d3ead211 100644 +--- a/include/box2d/b2_rope_joint.h ++++ b/include/box2d/b2_rope_joint.h +@@ -23,13 +23,14 @@ + #ifndef B2_ROPE_JOINT_H + #define B2_ROPE_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Rope joint definition. This requires two body anchor points and + /// a maximum lengths. + /// Note: by default the connected objects will not collide. + /// see collideConnected in b2JointDef. +-struct b2RopeJointDef : public b2JointDef ++struct B2_API b2RopeJointDef : public b2JointDef + { + b2RopeJointDef() + { +@@ -59,7 +60,7 @@ struct b2RopeJointDef : public b2JointDef + /// would have some sponginess, so I chose not to implement it + /// that way. See b2DistanceJoint if you want to dynamically + /// control length. +-class b2RopeJoint : public b2Joint ++class B2_API b2RopeJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_settings.h b/include/box2d/b2_settings.h +index 3b17e12fb..e2f8f2ebe 100644 +--- a/include/box2d/b2_settings.h ++++ b/include/box2d/b2_settings.h +@@ -23,9 +23,11 @@ + #ifndef B2_SETTINGS_H + #define B2_SETTINGS_H + +-#include +-#include +-#include ++#include ++#include ++#include ++ ++#include "b2_api.h" + + #if !defined(NDEBUG) + #define b2DEBUG +@@ -134,22 +136,22 @@ typedef unsigned int uint32; + // Memory Allocation + + /// Implement this function to use your own memory allocator. +-void* b2Alloc(int32 size); ++B2_API void* b2Alloc(int32 size); + + /// If you implement b2Alloc, you should also implement this function. +-void b2Free(void* mem); ++B2_API void b2Free(void* mem); + + /// Logging function. +-void b2Log(const char* string, ...); ++B2_API void b2Log(const char* string, ...); + + /// Dump to a file. Only one dump file allowed at a time. +-void b2OpenDump(const char* fileName); +-void b2Dump(const char* string, ...); +-void b2CloseDump(); ++B2_API void b2OpenDump(const char* fileName); ++B2_API void b2Dump(const char* string, ...); ++B2_API void b2CloseDump(); + + /// Version numbering scheme. + /// See http://en.wikipedia.org/wiki/Software_versioning +-struct b2Version ++struct B2_API b2Version + { + int32 major; ///< significant changes + int32 minor; ///< incremental changes +@@ -157,6 +159,6 @@ struct b2Version + }; + + /// Current version. +-extern b2Version b2_version; ++extern B2_API b2Version b2_version; + + #endif +diff --git a/include/box2d/b2_shape.h b/include/box2d/b2_shape.h +index 27e3d14bc..cbed2b863 100644 +--- a/include/box2d/b2_shape.h ++++ b/include/box2d/b2_shape.h +@@ -23,13 +23,14 @@ + #ifndef B2_SHAPE_H + #define B2_SHAPE_H + ++#include "b2_api.h" + #include "b2_math.h" + #include "b2_collision.h" + + class b2BlockAllocator; + + /// This holds the mass data computed for a shape. +-struct b2MassData ++struct B2_API b2MassData + { + /// The mass of the shape, usually in kilograms. + float mass; +@@ -44,10 +45,10 @@ struct b2MassData + /// A shape is used for collision detection. You can create a shape however you like. + /// Shapes used for simulation in b2World are created automatically when a b2Fixture + /// is created. Shapes may encapsulate a one or more child shapes. +-class b2Shape ++class B2_API b2Shape + { + public: +- ++ + enum Type + { + e_circle = 0, +diff --git a/include/box2d/b2_stack_allocator.h b/include/box2d/b2_stack_allocator.h +index 780ab7945..1db2af5d9 100644 +--- a/include/box2d/b2_stack_allocator.h ++++ b/include/box2d/b2_stack_allocator.h +@@ -23,12 +23,13 @@ + #ifndef B2_STACK_ALLOCATOR_H + #define B2_STACK_ALLOCATOR_H + ++#include "b2_api.h" + #include "b2_settings.h" + + const int32 b2_stackSize = 100 * 1024; // 100k + const int32 b2_maxStackEntries = 32; + +-struct b2StackEntry ++struct B2_API b2StackEntry + { + char* data; + int32 size; +@@ -38,7 +39,7 @@ struct b2StackEntry + // This is a stack allocator used for fast per step allocations. + // You must nest allocate/free pairs. The code will assert + // if you try to interleave multiple allocate/free pairs. +-class b2StackAllocator ++class B2_API b2StackAllocator + { + public: + b2StackAllocator(); +diff --git a/include/box2d/b2_time_of_impact.h b/include/box2d/b2_time_of_impact.h +index bb3031fcb..14d4b7a90 100644 +--- a/include/box2d/b2_time_of_impact.h ++++ b/include/box2d/b2_time_of_impact.h +@@ -23,11 +23,12 @@ + #ifndef B2_TIME_OF_IMPACT_H + #define B2_TIME_OF_IMPACT_H + ++#include "b2_api.h" + #include "b2_math.h" + #include "b2_distance.h" + + /// Input parameters for b2TimeOfImpact +-struct b2TOIInput ++struct B2_API b2TOIInput + { + b2DistanceProxy proxyA; + b2DistanceProxy proxyB; +@@ -37,7 +38,7 @@ struct b2TOIInput + }; + + /// Output parameters for b2TimeOfImpact. +-struct b2TOIOutput ++struct B2_API b2TOIOutput + { + enum State + { +@@ -57,6 +58,13 @@ struct b2TOIOutput + /// non-tunneling collisions. If you change the time interval, you should call this function + /// again. + /// Note: use b2Distance to compute the contact point and normal at the time of impact. +-void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input); ++B2_API void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input); ++ ++/// internal for testbed, do not use ++extern B2_API int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; ++/// internal for testbed, do not use ++extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; ++/// internal for testbed, do not use ++extern B2_API float b2_toiTime, b2_toiMaxTime; + + #endif +diff --git a/include/box2d/b2_time_step.h b/include/box2d/b2_time_step.h +index f0304a300..13d6292ec 100644 +--- a/include/box2d/b2_time_step.h ++++ b/include/box2d/b2_time_step.h +@@ -22,10 +22,11 @@ + #ifndef B2_TIME_STEP_H + #define B2_TIME_STEP_H + ++#include "b2_api.h" + #include "b2_math.h" + + /// Profiling data. Times are in milliseconds. +-struct b2Profile ++struct B2_API b2Profile + { + float step; + float collide; +@@ -38,7 +39,7 @@ struct b2Profile + }; + + /// This is an internal structure. +-struct b2TimeStep ++struct B2_API b2TimeStep + { + float dt; // time step + float inv_dt; // inverse time step (0 if dt == 0). +@@ -49,21 +50,21 @@ struct b2TimeStep + }; + + /// This is an internal structure. +-struct b2Position ++struct B2_API b2Position + { + b2Vec2 c; + float a; + }; + + /// This is an internal structure. +-struct b2Velocity ++struct B2_API b2Velocity + { + b2Vec2 v; + float w; + }; + + /// Solver Data +-struct b2SolverData ++struct B2_API b2SolverData + { + b2TimeStep step; + b2Position* positions; +diff --git a/include/box2d/b2_timer.h b/include/box2d/b2_timer.h +index a664de833..7893c3270 100644 +--- a/include/box2d/b2_timer.h ++++ b/include/box2d/b2_timer.h +@@ -23,11 +23,12 @@ + #ifndef B2_TIMER_H + #define B2_TIMER_H + ++#include "b2_api.h" + #include "b2_settings.h" + + /// Timer for profiling. This has platform specific code and may + /// not work on every platform. +-class b2Timer ++class B2_API b2Timer + { + public: + +diff --git a/include/box2d/b2_weld_joint.h b/include/box2d/b2_weld_joint.h +index fd5537f34..f226c8a46 100644 +--- a/include/box2d/b2_weld_joint.h ++++ b/include/box2d/b2_weld_joint.h +@@ -23,12 +23,13 @@ + #ifndef B2_WELD_JOINT_H + #define B2_WELD_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Weld joint definition. You need to specify local anchor points + /// where they are attached and the relative body angle. The position + /// of the anchor points is important for computing the reaction torque. +-struct b2WeldJointDef : public b2JointDef ++struct B2_API b2WeldJointDef : public b2JointDef + { + b2WeldJointDef() + { +@@ -54,7 +55,7 @@ struct b2WeldJointDef : public b2JointDef + + /// The bodyB angle minus bodyA angle in the reference state (radians). + float referenceAngle; +- ++ + /// The rotational stiffness in N*m + /// Disable softness with a value of 0 + float stiffness; +@@ -65,7 +66,7 @@ struct b2WeldJointDef : public b2JointDef + + /// A weld joint essentially glues two bodies together. A weld joint may + /// distort somewhat because the island constraint solver is approximate. +-class b2WeldJoint : public b2Joint ++class B2_API b2WeldJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_wheel_joint.h b/include/box2d/b2_wheel_joint.h +index 1b8f43739..8576adbd2 100644 +--- a/include/box2d/b2_wheel_joint.h ++++ b/include/box2d/b2_wheel_joint.h +@@ -23,6 +23,7 @@ + #ifndef B2_WHEEL_JOINT_H + #define B2_WHEEL_JOINT_H + ++#include "b2_api.h" + #include "b2_joint.h" + + /// Wheel joint definition. This requires defining a line of +@@ -31,7 +32,7 @@ + /// can violate the constraint slightly. The joint translation is zero + /// when the local anchor points coincide in world space. Using local + /// anchors and a local axis helps when saving and loading a game. +-struct b2WheelJointDef : public b2JointDef ++struct B2_API b2WheelJointDef : public b2JointDef + { + b2WheelJointDef() + { +@@ -91,7 +92,7 @@ struct b2WheelJointDef : public b2JointDef + /// along an axis fixed in bodyA and rotation in the plane. In other words, it is a point to + /// line constraint with a rotational motor and a linear spring/damper. The spring/damper is + /// initialized upon creation. This joint is designed for vehicle suspensions. +-class b2WheelJoint : public b2Joint ++class B2_API b2WheelJoint : public b2Joint + { + public: + b2Vec2 GetAnchorA() const override; +diff --git a/include/box2d/b2_world.h b/include/box2d/b2_world.h +index 3ddc136e3..57d37096c 100644 +--- a/include/box2d/b2_world.h ++++ b/include/box2d/b2_world.h +@@ -23,6 +23,7 @@ + #ifndef B2_WORLD_H + #define B2_WORLD_H + ++#include "b2_api.h" + #include "b2_block_allocator.h" + #include "b2_contact_manager.h" + #include "b2_math.h" +@@ -42,7 +43,7 @@ class b2Joint; + /// The world class manages all physics entities, dynamic simulation, + /// and asynchronous queries. The world also contains efficient memory + /// management facilities. +-class b2World ++class B2_API b2World + { + public: + /// Construct a world object. +@@ -58,7 +59,7 @@ class b2World + + /// Register a contact filter to provide specific control over collision. + /// Otherwise the default filter is used (b2_defaultFilter). The listener is +- /// owned by you and must remain in scope. ++ /// owned by you and must remain in scope. + void SetContactFilter(b2ContactFilter* filter); + + /// Register a contact event listener. The listener is owned by you and must +@@ -185,7 +186,7 @@ class b2World + + /// Change the global gravity vector. + void SetGravity(const b2Vec2& gravity); +- ++ + /// Get the global gravity vector. + b2Vec2 GetGravity() const; + +diff --git a/include/box2d/b2_world_callbacks.h b/include/box2d/b2_world_callbacks.h +index e1e75c9e9..da45640e2 100644 +--- a/include/box2d/b2_world_callbacks.h ++++ b/include/box2d/b2_world_callbacks.h +@@ -23,6 +23,7 @@ + #ifndef B2_WORLD_CALLBACKS_H + #define B2_WORLD_CALLBACKS_H + ++#include "b2_api.h" + #include "b2_settings.h" + + struct b2Vec2; +@@ -37,7 +38,7 @@ struct b2Manifold; + /// Joints and fixtures are destroyed when their associated + /// body is destroyed. Implement this listener so that you + /// may nullify references to these joints and shapes. +-class b2DestructionListener ++class B2_API b2DestructionListener + { + public: + virtual ~b2DestructionListener() {} +@@ -53,7 +54,7 @@ class b2DestructionListener + + /// Implement this class to provide collision filtering. In other words, you can implement + /// this class if you want finer control over contact creation. +-class b2ContactFilter ++class B2_API b2ContactFilter + { + public: + virtual ~b2ContactFilter() {} +@@ -66,7 +67,7 @@ class b2ContactFilter + /// Contact impulses for reporting. Impulses are used instead of forces because + /// sub-step forces may approach infinity for rigid body collisions. These + /// match up one-to-one with the contact points in b2Manifold. +-struct b2ContactImpulse ++struct B2_API b2ContactImpulse + { + float normalImpulses[b2_maxManifoldPoints]; + float tangentImpulses[b2_maxManifoldPoints]; +@@ -82,7 +83,7 @@ struct b2ContactImpulse + /// You should strive to make your callbacks efficient because there may be + /// many callbacks per time step. + /// @warning You cannot create/destroy Box2D entities inside these callbacks. +-class b2ContactListener ++class B2_API b2ContactListener + { + public: + virtual ~b2ContactListener() {} +@@ -124,7 +125,7 @@ class b2ContactListener + + /// Callback class for AABB queries. + /// See b2World::Query +-class b2QueryCallback ++class B2_API b2QueryCallback + { + public: + virtual ~b2QueryCallback() {} +@@ -136,7 +137,7 @@ class b2QueryCallback + + /// Callback class for ray casts. + /// See b2World::RayCast +-class b2RayCastCallback ++class B2_API b2RayCastCallback + { + public: + virtual ~b2RayCastCallback() {} +--- a/include/box2d/b2_distance.h~ 2020-08-10 09:42:32.000000000 -0500 ++++ b/include/box2d/b2_distance.h 2020-08-10 09:44:56.966717299 -0500 +@@ -118,7 +118,7 @@ + }; + + /// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction. +-bool b2ShapeCast(b2ShapeCastOutput* output, const b2ShapeCastInput* input); ++B2_API bool b2ShapeCast(b2ShapeCastOutput* output, const b2ShapeCastInput* input); + + ////////////////////////////////////////////////////////////////////////// + diff --git a/Box2D-2.3.1-cmake.patch b/Box2D-2.3.1-cmake.patch deleted file mode 100644 index 8eb91aa..0000000 --- a/Box2D-2.3.1-cmake.patch +++ /dev/null @@ -1,136 +0,0 @@ -This fixes the CMake build. Fixed upstream here: -https://code.google.com/p/box2d/source/detail?r=313 - -This does not use the bundled glew and glfw. - -Lubomir Rintel - -diff -urp Box2D-2.3.1/CMakeLists.txt Box2D-2.3.1.fix/CMakeLists.txt ---- Box2D-2.3.1/CMakeLists.txt 2015-02-20 14:14:39.000000000 +0100 -+++ Box2D-2.3.1.fix/CMakeLists.txt 2015-02-20 14:31:34.347669244 +0100 -@@ -26,8 +26,6 @@ if(BOX2D_BUILD_EXAMPLES) - - # Testbed and dependencies. - find_package(OpenGL REQUIRED) -- add_subdirectory(freeglut) -- add_subdirectory(glui) - add_subdirectory(Testbed) - endif(BOX2D_BUILD_EXAMPLES) - -diff -urp Box2D-2.3.1/Testbed/CMakeLists.txt Box2D-2.3.1.fix/Testbed/CMakeLists.txt ---- Box2D-2.3.1/Testbed/CMakeLists.txt 2015-02-20 14:14:39.000000000 +0100 -+++ Box2D-2.3.1.fix/Testbed/CMakeLists.txt 2015-02-20 14:32:42.322404515 +0100 -@@ -1,13 +1,17 @@ - # Some flags for Freeglut and GLUI. --add_definitions( -DFREEGLUT_EXPORTS -DFREEGLUT_STATIC -D_CRT_SECURE_NO_WARNINGS ) -+add_definitions( -D_CRT_SECURE_NO_WARNINGS ) - - # Define the framework files. - set(Testbed_Framework_SRCS - Framework/Main.cpp -- Framework/Render.cpp -- Framework/Render.h -+ Framework/RenderGL3.cpp -+ Framework/RenderGL3.h - Framework/Test.cpp - Framework/Test.h -+ Framework/DebugDraw.cpp -+ Framework/DebugDraw.h -+ Framework/imgui.cpp -+ Framework/imgui.h - ) - - #define the test files. -@@ -72,7 +76,7 @@ if(APPLE) - # We are not using the Apple's framework version, but X11's - include_directories( /usr/X11/include ) - link_directories( /usr/X11/lib ) -- set (OPENGL_LIBRARIES GL GLU GLUT X11) -+ set (OPENGL_LIBRARIES GL GLU X11) - elseif(WIN32) - set (ADDITIONAL_LIBRARIES winmm) - endif(APPLE) -@@ -85,8 +89,8 @@ add_executable(Testbed - target_link_libraries ( - Testbed - Box2D -- freeglut_static -- glui -+ glfw -+ GLEW - ${ADDITIONAL_LIBRARIES} - ${OPENGL_LIBRARIES} - ) -diff --git a/Testbed/Framework/Test.h b/Testbed/Framework/Test.h -index 7e621d4..bb4cb13 100644 ---- a/Testbed/Framework/Test.h -+++ b/Testbed/Framework/Test.h -@@ -25,7 +25,7 @@ - #if defined(__APPLE__) - #include - #else --#include -+#include - #endif - #include - -diff --git a/Testbed/Framework/DebugDraw.cpp b/Testbed/Framework/DebugDraw.cpp -index 8299611..2a7da6b 100644 ---- a/Testbed/Framework/DebugDraw.cpp -+++ b/Testbed/Framework/DebugDraw.cpp -@@ -21,10 +21,10 @@ - #if defined(__APPLE_CC__) - #include - #else --#include -+#include - #endif - --#include -+#include - #include - #include - -diff --git a/Testbed/Framework/Main.cpp b/Testbed/Framework/Main.cpp -index b494da9..79e2c05 100644 ---- a/Testbed/Framework/Main.cpp -+++ b/Testbed/Framework/Main.cpp -@@ -24,10 +24,10 @@ - #if defined(__APPLE__) - #include - #else --#include -+#include - #endif - --#include -+#include - #include - - #ifdef _MSC_VER -diff --git a/Testbed/Framework/RenderGL3.cpp b/Testbed/Framework/RenderGL3.cpp -index 4613541..115cb93 100644 ---- a/Testbed/Framework/RenderGL3.cpp -+++ b/Testbed/Framework/RenderGL3.cpp -@@ -25,7 +25,7 @@ - #ifdef __APPLE__ - #include - #else --#include -+#include - #include - #endif - -diff --git a/Testbed/Framework/Test.h b/Testbed/Framework/Test.h -index bb4cb13..f6c69f3 100644 ---- a/Testbed/Framework/Test.h -+++ b/Testbed/Framework/Test.h -@@ -27,7 +27,7 @@ - #else - #include - #endif --#include -+#include - - #include - diff --git a/Box2D.spec b/Box2D.spec index b2e96ff..82c9859 100644 --- a/Box2D.spec +++ b/Box2D.spec @@ -1,17 +1,14 @@ +%global __cmake_in_source_build 1 Name: Box2D -Version: 2.3.1 -Release: 13%{?dist} +Version: 2.4.0 +Release: 1%{?dist} Summary: A 2D Physics Engine for Games License: zlib URL: http://box2d.org/ -# "Google Code no longer allows for downloads, therefore you will have to use SVN to get v2.3.1" -# -# svn checkout http://box2d.googlecode.com/svn/tags/v2.3.1/Box2D Box2D-2.3.1 -# (^^^ beware only legacy IP works, IPv6 seems broken) -# tar --exclude .svn -czf Box2D-2.3.1.tar.gz Box2D-2.3.1 -Source0: %{name}-%{version}.tar.gz -Patch0: Box2D-2.3.1-cmake.patch +Source0: https://github.com/erincatto/box2d/archive/v%{version}/%{name}-%{version}.tar.gz +Patch0: 630.patch +Patch1: 631.patch BuildRequires: gcc BuildRequires: gcc-c++ BuildRequires: cmake libXi-devel glew-devel glfw-devel @@ -35,40 +32,34 @@ we encourage you to give credit to Box2D in your product. These are the development files. %prep -%setup -q +%setup -qn box2d-%{version} %patch0 -p1 +%patch1 -p1 rm -rf glew glfw %build -sed -i 's/\r//' License.txt -sed -i 's/\r//' Readme.txt -pushd Box2D -%cmake -DBOX2D_INSTALL=ON -DBOX2D_BUILD_SHARED=ON .. +%cmake -DBOX2D_INSTALL=ON -DBOX2D_BUILD_SHARED=ON . make %install -pushd Box2D make install DESTDIR=%{buildroot} -find %{buildroot} -name '*.cmake' | xargs rm -find %{buildroot} -name '*.a' | xargs rm - - %ldconfig_scriptlets - - %files -%doc License.txt -%{_libdir}/*.so.* +%license LICENSE +%{_libdir}/*.so.2* %files devel -%doc Readme.txt Documentation/ +%doc README.md docs/ %{_libdir}/*.so -%{_includedir}/Box2D - +%{_includedir}/box2d +%{_libdir}/cmake/box2d/*.cmake %changelog +* Mon Aug 10 2020 Gwyn Ciesla - 2.4.0-1 +- 2.4.0 with patch for cmake shared libs. + * Mon Jul 27 2020 Fedora Release Engineering - 2.3.1-13 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild diff --git a/sources b/sources index 2493703..7044b5b 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -ab0674782d4ef754ea2578a704dc2945 Box2D-2.3.1.tar.gz +SHA512 (Box2D-2.4.0.tar.gz) = ce6f9b2d60343e9b87743d9a6703534e89d74f7e34d357510df965c72ac5fcaea4e4904856c9323fe2896cee9afd0dfc2927c11ea3093d93f2da109218c49fee