diff --git a/Build/xcode5/PlayRho.xcodeproj/project.pbxproj b/Build/xcode5/PlayRho.xcodeproj/project.pbxproj index 6a5ac6294c..5610252bf8 100644 --- a/Build/xcode5/PlayRho.xcodeproj/project.pbxproj +++ b/Build/xcode5/PlayRho.xcodeproj/project.pbxproj @@ -136,6 +136,8 @@ 4768D3FD1E414A0100574143 /* Vector2.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4768D3FA1E414A0100574143 /* Vector2.hpp */; }; 4768D4001E54E7CC00574143 /* StepConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4768D3FF1E54E7CB00574143 /* StepConf.cpp */; }; 476E8ABE1FC8CD9F00705BB5 /* UnitVec2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 476E8ABD1FC8CD9F00705BB5 /* UnitVec2.cpp */; }; + 476E8AC31FCF926F00705BB5 /* FunctionalShapeVisitor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 476E8AC11FCF926F00705BB5 /* FunctionalShapeVisitor.hpp */; }; + 476E8AC71FCFA0D400705BB5 /* FunctionalJointVisitor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 476E8AC51FCFA0D400705BB5 /* FunctionalJointVisitor.hpp */; }; 4775A9381E05B032001C2332 /* StepConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4775A9371E05B032001C2332 /* StepConf.cpp */; }; 47791F801F92DB0700E257AF /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 47791F7A1F92D78F00E257AF /* imgui_draw.cpp */; }; 47791F811F92DB0D00E257AF /* imgui_impl_glfw_gl3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 47791F7C1F92D83500E257AF /* imgui_impl_glfw_gl3.cpp */; }; @@ -512,6 +514,8 @@ 4768D3FA1E414A0100574143 /* Vector2.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Vector2.hpp; sourceTree = ""; }; 4768D3FF1E54E7CB00574143 /* StepConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StepConf.cpp; sourceTree = ""; }; 476E8ABD1FC8CD9F00705BB5 /* UnitVec2.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnitVec2.cpp; sourceTree = ""; }; + 476E8AC11FCF926F00705BB5 /* FunctionalShapeVisitor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FunctionalShapeVisitor.hpp; sourceTree = ""; }; + 476E8AC51FCFA0D400705BB5 /* FunctionalJointVisitor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FunctionalJointVisitor.hpp; sourceTree = ""; }; 477329D61F9BEFA200C521B4 /* SolarSystem.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SolarSystem.hpp; sourceTree = ""; }; 4775A9371E05B032001C2332 /* StepConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StepConf.cpp; sourceTree = ""; }; 47791F761F901B8700E257AF /* iforce2d_Trajectories.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = iforce2d_Trajectories.hpp; sourceTree = ""; }; @@ -940,6 +944,7 @@ 80BB8938141C3E5900F1753A /* DiskShape.hpp */, 80BB8939141C3E5900F1753A /* EdgeShape.cpp */, 80BB893A141C3E5900F1753A /* EdgeShape.hpp */, + 476E8AC11FCF926F00705BB5 /* FunctionalShapeVisitor.hpp */, 474AFBF61EB1B2CB002AA6C8 /* MultiShape.cpp */, 474AFBF71EB1B2CB002AA6C8 /* MultiShape.hpp */, 80BB893B141C3E5900F1753A /* PolygonShape.cpp */, @@ -1070,6 +1075,7 @@ 80BB8971141C3E5900F1753A /* FrictionJoint.hpp */, 4787D6C41F2EA1DB008C115E /* FrictionJointDef.cpp */, 4787D6C51F2EA1DB008C115E /* FrictionJointDef.hpp */, + 476E8AC51FCFA0D400705BB5 /* FunctionalJointVisitor.hpp */, 80BB8972141C3E5900F1753A /* GearJoint.cpp */, 80BB8973141C3E5900F1753A /* GearJoint.hpp */, 4787D6C81F2EA3A1008C115E /* GearJointDef.cpp */, @@ -1275,6 +1281,7 @@ buildActionMask = 2147483647; files = ( 4726DD1F1D305E5D0012A882 /* ContactFeature.hpp in Headers */, + 476E8AC71FCFA0D400705BB5 /* FunctionalJointVisitor.hpp in Headers */, 80BB8987141C3E5900F1753A /* PlayRho.hpp in Headers */, 47D28D9D1F6F28C70094C032 /* WrongState.hpp in Headers */, 4731DE581DEC908600E7F931 /* UnitVec2.hpp in Headers */, @@ -1298,6 +1305,7 @@ 4734B2211DC1340500F15E29 /* Span.hpp in Headers */, 80BB8998141C3E5900F1753A /* DiskShape.hpp in Headers */, 472724301E315E1A00C64921 /* Fixed.hpp in Headers */, + 476E8AC31FCF926F00705BB5 /* FunctionalShapeVisitor.hpp in Headers */, 47C85D211F0DA14500F70C56 /* Templates.hpp in Headers */, 80BB899A141C3E5900F1753A /* EdgeShape.hpp in Headers */, 470F94CC1EC4D95D00AA3C82 /* BodyAtty.hpp in Headers */, diff --git a/PlayRho/Collision/Shapes/FunctionalShapeVisitor.hpp b/PlayRho/Collision/Shapes/FunctionalShapeVisitor.hpp new file mode 100644 index 0000000000..2863717798 --- /dev/null +++ b/PlayRho/Collision/Shapes/FunctionalShapeVisitor.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_COLLISION_SHAPES_FUNCTIONALSHAPEVISITOR_HPP +#define PLAYRHO_COLLISION_SHAPES_FUNCTIONALSHAPEVISITOR_HPP + +#include +#include +#include + +namespace playrho { + + /// @brief Functional shape visitor class. + /// @note This class is intended to provide an alternate interface for visiting shapes + /// via the use of lamdas instead of having to subclass ShapeVisitor. + /// @sa ShapeVisitor + class FunctionalShapeVisitor: public ShapeVisitor + { + public: + /// @brief Procedure alias. + template + using Proc = std::function; + + /// @brief Tuple alias. + using Tuple = std::tuple< + Proc, + Proc, + Proc, + Proc, + Proc + >; + + Tuple procs; ///< Procedures. + + /// @brief Uses given procedure. + /// @note Provide a builder pattern mutator method. + template + FunctionalShapeVisitor& Use(const Proc& proc) noexcept + { + std::get>(procs) = proc; + return *this; + } + + // Overrides of all the base class's Visit methods... + // Uses decltype to ensure the correctly typed invocation of the Handle method. + void Visit(const DiskShape& arg) override { Handle(arg); } + void Visit(const EdgeShape& arg) override { Handle(arg); } + void Visit(const PolygonShape& arg) override { Handle(arg); } + void Visit(const ChainShape& arg) override { Handle(arg); } + void Visit(const MultiShape& arg) override { Handle(arg); } + + private: + + /// @brief Handles the joint through the established function. + template + inline void Handle(T arg) const + { + const auto& proc = std::get>(procs); + if (proc) + { + proc(arg); + } + } + }; + +} // namespace playrho + +#endif // PLAYRHO_COLLISION_SHAPES_FUNCTIONALSHAPEVISITOR_HPP + diff --git a/PlayRho/Dynamics/Joints/FunctionalJointVisitor.hpp b/PlayRho/Dynamics/Joints/FunctionalJointVisitor.hpp new file mode 100644 index 0000000000..fb385bb6d9 --- /dev/null +++ b/PlayRho/Dynamics/Joints/FunctionalJointVisitor.hpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_DYNAMICS_JOINTS_FUNCTIONALJOINTVISITOR_HPP +#define PLAYRHO_DYNAMICS_JOINTS_FUNCTIONALJOINTVISITOR_HPP + +#include +#include +#include +#include + +namespace playrho { + + /// @brief Functional joint visitor class. + /// @note This class is intended to provide an alternate interface for visiting joints + /// via the use of lamdas instead of having to subclass JointVisitor. + class FunctionalJointVisitor: public JointVisitor + { + public: + /// @brief Procedure alias. + template + using Proc = std::function; + + //using Tuple = std::tuple...>; + //FunctionalJointVisitor(const Tuple& v): procs{v} {} + + /// @brief Tuple alias. + using Tuple = std::tuple< + Proc, + Proc< RevoluteJoint&>, + Proc, + Proc< PrismaticJoint&>, + Proc, + Proc< DistanceJoint&>, + Proc, + Proc< PulleyJoint&>, + Proc, + Proc< MouseJoint&>, + Proc, + Proc< GearJoint&>, + Proc, + Proc< WheelJoint&>, + Proc, + Proc< WeldJoint&>, + Proc, + Proc< FrictionJoint&>, + Proc, + Proc< RopeJoint&>, + Proc, + Proc< MotorJoint&> + >; + + Tuple procs; ///< Procedures. + + /// @brief Uses given procedure. + /// @note Provide a builder pattern mutator method. + template + FunctionalJointVisitor& Use(const Proc& proc) noexcept + { + std::get>(procs) = proc; + return *this; + } + + // Overrides of all the base class's Visit methods... + // Uses decltype to ensure the correctly typed invocation of the Handle method. + void Visit(const RevoluteJoint& arg) override { Handle(arg); } + void Visit(RevoluteJoint& arg) override { Handle(arg); } + void Visit(const PrismaticJoint& arg) override { Handle(arg); } + void Visit(PrismaticJoint& arg) override { Handle(arg); } + void Visit(const DistanceJoint& arg) override { Handle(arg); } + void Visit(DistanceJoint& arg) override { Handle(arg); } + void Visit(const PulleyJoint& arg) override { Handle(arg); } + void Visit(PulleyJoint& arg) override { Handle(arg); } + void Visit(const MouseJoint& arg) override { Handle(arg); } + void Visit(MouseJoint& arg) override { Handle(arg); } + void Visit(const GearJoint& arg) override { Handle(arg); } + void Visit(GearJoint& arg) override { Handle(arg); } + void Visit(const WheelJoint& arg) override { Handle(arg); } + void Visit(WheelJoint& arg) override { Handle(arg); } + void Visit(const WeldJoint& arg) override { Handle(arg); } + void Visit(WeldJoint& arg) override { Handle(arg); } + void Visit(const FrictionJoint& arg) override { Handle(arg); } + void Visit(FrictionJoint& arg) override { Handle(arg); } + void Visit(const RopeJoint& arg) override { Handle(arg); } + void Visit(RopeJoint& arg) override { Handle(arg); } + void Visit(const MotorJoint& arg) override { Handle(arg); } + void Visit(MotorJoint& arg) override { Handle(arg); } + + private: + + /// @brief Handles the joint through the established function. + template + inline void Handle(T arg) const + { + const auto& proc = std::get>(procs); + if (proc) + { + proc(arg); + } + } + }; + +} // namespace playrho + +#endif // PLAYRHO_DYNAMICS_JOINTS_FUNCTIONALJOINTVISITOR_HPP + diff --git a/Testbed/Framework/Test.hpp b/Testbed/Framework/Test.hpp index 24258fe439..61d9655d0b 100644 --- a/Testbed/Framework/Test.hpp +++ b/Testbed/Framework/Test.hpp @@ -23,8 +23,9 @@ #include #include #include -#include +#include #include +#include #include #include "Drawer.hpp" #include "UiState.hpp" @@ -418,12 +419,10 @@ inline void ForAll(World& world, const std::function& action); template <> inline void ForAll(World& world, const std::function& action) { + auto visitor = FunctionalJointVisitor{}.Use(action); const auto range = world.GetJoints(); std::for_each(std::begin(range), std::end(range), [&](Joint* j) { - if (GetType(*j) == JointType::Revolute) - { - action(*reinterpret_cast(j)); - } + j->Accept(visitor); }); }