From bf55f21d7946d0bc9148a9e7b863fb0409ddeb39 Mon Sep 17 00:00:00 2001 From: deliriuminthevoid Date: Fri, 22 Sep 2023 02:06:39 +0300 Subject: [PATCH 01/13] one file rough game MVP --- CMakeLists.txt | 2 + battle_tanks/client/CMakeLists.txt | 27 + battle_tanks/client/battle_tanks.cpp | 645 ++++ .../client/game_data/atlases/bullet_1.png | Bin 0 -> 7045 bytes .../client/game_data/atlases/tank.png | Bin 0 -> 4403 bytes .../client/game_data/atlases/tower.png | Bin 0 -> 2588 bytes battle_tanks/client/headers/debug_draw.hpp | 46 + battle_tanks/client/sources/debug_draw.cpp | 111 + external/headers/boost/di.hpp | 3355 +++++++++++++++++ gitattributes | 2 + vcpkg.json | 5 +- 11 files changed, 4192 insertions(+), 1 deletion(-) create mode 100644 battle_tanks/client/CMakeLists.txt create mode 100644 battle_tanks/client/battle_tanks.cpp create mode 100644 battle_tanks/client/game_data/atlases/bullet_1.png create mode 100644 battle_tanks/client/game_data/atlases/tank.png create mode 100644 battle_tanks/client/game_data/atlases/tower.png create mode 100644 battle_tanks/client/headers/debug_draw.hpp create mode 100644 battle_tanks/client/sources/debug_draw.cpp create mode 100644 external/headers/boost/di.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index af072a7..e8e749d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,3 +38,5 @@ add_subdirectory ("lesson_22") add_subdirectory ("lesson_23") add_subdirectory ("lesson_26") add_subdirectory ("lesson_27") + +add_subdirectory ("battle_tanks/client") diff --git a/battle_tanks/client/CMakeLists.txt b/battle_tanks/client/CMakeLists.txt new file mode 100644 index 0000000..7f7f248 --- /dev/null +++ b/battle_tanks/client/CMakeLists.txt @@ -0,0 +1,27 @@ +project(battle_tanks_client) + +file(GLOB_RECURSE SOURCES "./*.cpp") + +include_directories(${PROJECT_SOURCE_DIR}/headers) + +find_package(SFML COMPONENTS system window graphics CONFIG REQUIRED) +find_package(box2d CONFIG REQUIRED) + +add_executable (${PROJECT_NAME} ${SOURCES}) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/game_data DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +if (CMAKE_VERSION VERSION_GREATER 3.12) + set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) +endif() + +target_link_libraries(${PROJECT_NAME} + PRIVATE + sfml-system + sfml-network + sfml-graphics + sfml-window + box2d::box2d +) + +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../external/headers) \ No newline at end of file diff --git a/battle_tanks/client/battle_tanks.cpp b/battle_tanks/client/battle_tanks.cpp new file mode 100644 index 0000000..7da50bc --- /dev/null +++ b/battle_tanks/client/battle_tanks.cpp @@ -0,0 +1,645 @@ +#include +#include +#include + +#include +#include + +#include "boost/di.hpp" + +#include "debug_draw.hpp" + +typedef long long unsigned uuid; +static uuid current_uuid{ 1 }; +uuid generate_uuid() +{ + return current_uuid++; +} + +float deg_to_rad(float rotation) +{ + return static_cast(std::numbers::pi * static_cast(rotation) / 180.0); +} + +class container; +class render_object; + +enum class move_action +{ + stop = 0, + forward, + backward, +}; + +enum rotate_action +{ + stop = 0, + left, + right, +}; + +enum class game_object_type : unsigned +{ + unknown = 0, + tank, + bullet, + wall, + brick +}; + +struct game_object_b2d_link +{ + game_object_type type{ game_object_type::unknown }; + uuid id{ 0 }; +}; + +class game_object +{ +public: + explicit game_object(uuid id) : id_{ id } + { + } + + virtual ~game_object() = default; + +public: + virtual void initialize() = 0; + virtual void update(float delta_time) = 0; + virtual void free() = 0; + +public: + const std::shared_ptr& get_render_object() const + { + return render_object_; + } + + const b2Body* get_physics_body() const + { + return physics_body_; + } + +protected: + std::shared_ptr render_object_{ nullptr }; + b2Body* physics_body_{ nullptr }; + uuid id_; +}; + +class game_scene +{ +public: + void update(float delta_time) const + { + //physics_world_.Step(delta_time, 8, 3); + for (const auto& game_object : game_objects_) + { + game_object->update(delta_time); + } + } + + void add_game_object(const std::shared_ptr& game_object) + { + game_objects_.push_back(game_object); + } + + void remove_game_object(const std::shared_ptr& game_object) + { + for (auto it = game_objects_.begin(); it != game_objects_.end(); ++it) + { + if (*it == game_object) + { + game_objects_.erase(it); + break; + } + } + } + +private: + std::vector> game_objects_{}; + + //b2World physics_world_{ { 0.0f, 0.0f } }; +}; + +class render_object : public sf::Transformable +{ + friend container; + +public: + virtual ~render_object() override = default; + +public: + void free() + { + if (parent_ != nullptr) + { + //TODO: fix + //parent_->remove_child(std::shared_ptr(this)); + //parent_ = nullptr; + } + } + +protected: + virtual void draw(const std::shared_ptr& render_target, const sf::Transform& parent_transform) const = 0; + +private: + std::shared_ptr parent_{ nullptr }; +}; + +class container : public render_object +{ +public: + virtual ~container() override = default; + +public: + void add_child(const std::shared_ptr& child) + { + if (child->parent_ != nullptr) + { + child->parent_->remove_child(child); + } + + children_.push_back(child); + //child->parent_ = std::shared_ptr(this); //TODO: fix + } + + void remove_child(const std::shared_ptr& child) + { + for (auto it = children_.begin(); it != children_.end(); ++it) + { + if (*it == child) + { + children_.erase(it); + break; + } + } + } + +protected: + void draw(const std::shared_ptr& render_target, const sf::Transform& parent_transform) const override + { + const sf::Transform transform = parent_transform * getTransform(); + for (const auto& ch : children_) + { + ch->draw(render_target, transform); + } + } + +protected: + std::vector> children_{}; +}; + +class render_scene final : public container +{ +public: + explicit render_scene(const std::shared_ptr& render_target) : render_target_{ render_target } + { + } + + virtual ~render_scene() override = default; + +public: + void draw_scene() const + { + container::draw(render_target_, getTransform()); + } + +private: + std::shared_ptr render_target_{ nullptr }; +}; + +class texture_render_data +{ +public: + explicit texture_render_data(const std::string& path) + { + texture_ = std::make_shared(); + texture_->loadFromFile(path); + texture_->setSmooth(true); + texture_size_ = texture_->getSize(); + } + +public: + std::shared_ptr get_texture() const + { + return texture_; + } + + sf::Vector2u get_size() const + { + return texture_size_; + } + +private: + std::shared_ptr texture_{ nullptr }; + sf::Vector2u texture_size_{}; +}; + + +class sprite : public render_object +{ +public: + explicit sprite(const std::string& path) + { + texture_render_data_ = std::make_shared(path); + sprite_.setTexture(*texture_render_data_->get_texture()); + } + + explicit sprite(const std::shared_ptr& texture_render_data) + { + texture_render_data_ = texture_render_data; + sprite_.setTexture(*texture_render_data_->get_texture()); + } + + virtual ~sprite() override = default; + +protected: + void draw(const std::shared_ptr& render_target, const sf::Transform& parent_transform) const override + { + if (texture_render_data_ == nullptr) + { + return; + } + render_target->draw(sprite_, parent_transform * getTransform()); + } + +private: + sf::Sprite sprite_{}; + std::shared_ptr texture_render_data_{ nullptr }; +}; + +//TODO:: create object poll for such objects +class bullet : public game_object +{ +public: + bullet(const uuid id, float velocity, const std::shared_ptr& render_data, b2Body* body) : + game_object(id), velocity_{ velocity }, render_data_{ render_data } + { + physics_body_ = body ; + } + + virtual ~bullet() override = default; + +public: + virtual void initialize() override + { + render_object_ = std::make_shared(render_data_); + } + + virtual void update(float delta_time) override + { + if (render_object_ == nullptr || velocity_ == 0.0f) + { + return; + } + + /* + const auto position = render_object_->getPosition(); + const auto rotation = render_object_->getRotation(); + const auto rad_rotation = static_cast(std::numbers::pi * static_cast(rotation) / 180.0); + + const auto new_position_x = position.x + std::sin(rad_rotation) * velocity_ * delta_time; + const auto new_position_y = position.y + -std::cos(rad_rotation) * velocity_ * delta_time; + + render_object_->setPosition(new_position_x, new_position_y); + */ + auto& ph_body_pos = physics_body_->GetPosition(); + const float ph_body_rot = physics_body_->GetAngle(); + + render_object_->setPosition({ ph_body_pos.x * 10.0f, ph_body_pos.y * 10.0f }); + render_object_->setRotation(std::fmod( + static_cast(static_cast(ph_body_rot) * 180.0f / std::numbers::pi), 360.0f) + ); + + //TODO: delete bullet if it out of game field (field_size_) + } + + virtual void free() override + { + if (render_object_ != nullptr) + { + render_object_->free(); + render_object_ = nullptr; + } + } + +private: + float velocity_{ 0.0f }; + sf::Vector2f position_{}; + sf::Vector2u field_size_{}; + + std::shared_ptr render_data_{ nullptr }; +}; + +class physics_contact_listener final : public b2ContactListener +{ + void BeginContact(b2Contact* contact) override + { + b2Fixture* fixture_a = contact->GetFixtureA(); + b2Fixture* fixture_b = contact->GetFixtureB(); + + // Check if fixtureA or fixtureB is your object, and perform actions accordingly. + // For example, you can check user data associated with the fixtures. + b2Body* body_a = fixture_a->GetBody(); + b2Body* body_b = fixture_b->GetBody(); + b2BodyUserData user_data_a = body_a->GetUserData(); + b2BodyUserData user_data_b = body_b->GetUserData(); + + const game_object_b2d_link* link_a{ nullptr }; + const game_object_b2d_link* link_b{ nullptr }; + + if (user_data_a.pointer != 0) + { + link_a = reinterpret_cast(user_data_a.pointer); + if (link_a->type == game_object_type::bullet) + { + //std::cout << "Bullet collision detected!" << std::endl; + } + } + + if (user_data_b.pointer != 0) + { + link_b = reinterpret_cast(user_data_b.pointer); + if (link_b->type == game_object_type::bullet) + { + //std::cout << "Bullet collision detected!" << std::endl; + } + } + + // Perform collision handling here. + //std::cout << "Collision detected!" << std::endl; + } +}; + +int main() +{ + constexpr float pixels_per_meters{ 10.0f }; // 1 meter = 10 pixels + const sf::Vector2u game_field_size{ 800, 600 }; + + auto window = std::make_shared(sf::VideoMode(game_field_size.x, game_field_size.y), "Battle Tanks"); + //window->setFramerateLimit(20); + + sf::Clock clock; + game_scene game; + render_scene root_node{window}; + b2World physics_world{ { 0.0f, 0.0f } }; + physics_world.SetAllowSleeping(true); + //physics_world.SetContinuousPhysics(true); + auto* contact_listener = new physics_contact_listener(); + physics_world.SetContactListener(contact_listener); + SFMLDebugDraw draw{ *window, pixels_per_meters }; + draw.AppendFlags(b2Draw::e_shapeBit); + physics_world.SetDebugDraw(&draw); + + // + auto tank_texture_render_data = std::make_shared("game_data/atlases/tank.png"); + auto tower_texture_render_data = std::make_shared("game_data/atlases/tower.png"); + auto bullet_texture_render_data = std::make_shared("game_data/atlases/bullet_1.png"); + // + + // + move_action tank_move_action{}; + rotate_action tank_rotate_action{}; + rotate_action tower_rotate_action{}; + bool tank_fire{ false }; + + sf::Vector2u tank_texture_size = tank_texture_render_data->get_size(); + + const auto tank_container = std::make_shared(); + tank_container->setPosition(100.0, 100.0); + tank_container->setOrigin(static_cast(tank_texture_size.x) / 2.0f, static_cast(tank_texture_size.y) / 2.0f); + root_node.add_child(tank_container); + + const auto tank_base_sprite = std::make_shared(tank_texture_render_data); + tank_container->add_child(tank_base_sprite); + + const auto tank_tower_sprite = std::make_shared(tower_texture_render_data); + tank_tower_sprite->setPosition(16.5f, 27.0f); + tank_tower_sprite->setOrigin(10.0f, 67.0f); + tank_container->add_child(tank_tower_sprite); + + b2BodyDef tank_body_def; + tank_body_def.type = b2_dynamicBody; + tank_body_def.position.Set(100.0f / pixels_per_meters, 100.0f / pixels_per_meters); + auto tank_body = physics_world.CreateBody(&tank_body_def); + b2PolygonShape tank_shape; + tank_shape.SetAsBox( + static_cast(tank_texture_size.x) / pixels_per_meters / 2, + static_cast(tank_texture_size.y) / pixels_per_meters / 2 + ); + tank_body->CreateFixture(&tank_shape, 1.0f); + // + + // + b2Vec2 bottom_right_point = b2Vec2{ + static_cast(game_field_size.x) / pixels_per_meters, + static_cast(game_field_size.y) / pixels_per_meters + }; + b2BodyDef edge_body_def; + edge_body_def.type = b2_staticBody; + auto edges_body = physics_world.CreateBody(&edge_body_def); + + b2EdgeShape top_edge_shape; + top_edge_shape.SetTwoSided(b2Vec2(0.0f, 0.0f), b2Vec2(bottom_right_point.x, 0.0f)); + edges_body->CreateFixture(&top_edge_shape, 1.0f); + + b2EdgeShape bottom_edge_shape; + bottom_edge_shape.SetTwoSided(b2Vec2(0.0f, bottom_right_point.y), bottom_right_point); + edges_body->CreateFixture(&bottom_edge_shape, 1.0f); + + b2EdgeShape left_edge_shape; + left_edge_shape.SetTwoSided(b2Vec2(0.0f, 0.0f), b2Vec2(0.0f, bottom_right_point.y)); + edges_body->CreateFixture(&left_edge_shape, 1.0f); + + b2EdgeShape right_edge_shape; + right_edge_shape.SetTwoSided(b2Vec2(bottom_right_point.x, 0.0f), bottom_right_point); + edges_body->CreateFixture(&right_edge_shape, 1.0f); + // + + auto bullet_creation_time = std::chrono::high_resolution_clock::now(); + while (window->isOpen()) + { + float delta_time = clock.restart().asSeconds(); + + sf::Event event; + while (window->pollEvent(event)) + { + if (event.type == sf::Event::Closed || + (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Escape)) + { + window->close(); + } + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W)) + { + tank_move_action = move_action::forward; + } + else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S)) + { + tank_move_action = move_action::backward; + } + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A)) + { + tank_rotate_action = left; + } + else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) + { + tank_rotate_action = right; + } + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left)) + { + tower_rotate_action = left; + } + else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right)) + { + tower_rotate_action = right; + } + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Space)) + { + tank_fire = true; + } + + if (event.type == sf::Event::KeyReleased) + { + if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::S) + { + tank_move_action = move_action::stop; + } + + if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::D) + { + tank_rotate_action = stop; + } + + if (event.key.code == sf::Keyboard::Left || event.key.code == sf::Keyboard::Right) + { + tower_rotate_action = stop; + } + + if (event.key.code == sf::Keyboard::Space) + { + tank_fire = false; + } + } + } + + if (tank_fire) + { + auto bullet_current_time = std::chrono::high_resolution_clock::now(); + + if (std::chrono::duration_cast(bullet_current_time - bullet_creation_time).count() >= 1000) + { + bullet_creation_time = bullet_current_time; + const float bullet_rotation_rad = deg_to_rad(tank_tower_sprite->getRotation() + tank_container->getRotation()); + const b2Vec2 bullet_pos{ + (tank_container->getPosition().x + 80 * std::sin(bullet_rotation_rad)) / pixels_per_meters, + (tank_container->getPosition().y - 80 * std::cos(bullet_rotation_rad)) / pixels_per_meters + }; + b2BodyDef bullet_body_def; + bullet_body_def.type = b2_dynamicBody; + bullet_body_def.position.Set(bullet_pos.x, bullet_pos.y); + auto bullet_body = physics_world.CreateBody(&bullet_body_def); + b2PolygonShape bullet_shape; + bullet_shape.SetAsBox( + static_cast(bullet_texture_render_data->get_size().x) / pixels_per_meters / 2, + static_cast(bullet_texture_render_data->get_size().y) / pixels_per_meters / 2 + ); + bullet_body->CreateFixture(&bullet_shape, 1.0f); + uuid bullet_id = generate_uuid(); + auto* bullet_link = new game_object_b2d_link{ game_object_type::bullet, bullet_id }; + bullet_body->GetUserData().pointer = reinterpret_cast(bullet_link); + + auto force = b2Vec2{ + std::sin(bullet_rotation_rad) * 500.0f / pixels_per_meters, + -std::cos(bullet_rotation_rad) * 500.0f / pixels_per_meters + }; + bullet_body->SetTransform(bullet_pos, bullet_rotation_rad); + bullet_body->SetLinearVelocity(force); + + const auto bt = std::make_shared(bullet_id, 500.0f, bullet_texture_render_data, bullet_body); + bt->initialize(); + bt->get_render_object()->setOrigin( + static_cast(bullet_texture_render_data->get_size().x) / 2.0f, + static_cast(bullet_texture_render_data->get_size().y) / 2.0f + ); + game.add_game_object(bt); + root_node.add_child(bt->get_render_object()); + } + } + + const auto rad_rotation = tank_body->GetAngle(); + auto tower_rotation = tank_tower_sprite->getRotation(); + + constexpr float move_speed = 100.0; + if (tank_move_action == move_action::forward) + { + auto force = b2Vec2{ + std::sin(rad_rotation) * move_speed / pixels_per_meters, + -std::cos(rad_rotation) * move_speed / pixels_per_meters + }; + + tank_body->SetLinearVelocity(force); + } + else if (tank_move_action == move_action::backward) + { + auto force = b2Vec2{ + -std::sin(rad_rotation) * move_speed / pixels_per_meters, + std::cos(rad_rotation) * move_speed / pixels_per_meters + }; + + tank_body->SetLinearVelocity(force); + } + else + { + tank_body->SetLinearVelocity({ 0.0f, 0.0f }); + } + + constexpr float rotate_speed = 90.0f; + constexpr float rotate_speed_rad = static_cast(std::numbers::pi) / 2.0f; + if (tank_rotate_action == left) + { + tank_body->SetAngularVelocity(-rotate_speed_rad); + } + else if (tank_rotate_action == right) + { + tank_body->SetAngularVelocity(rotate_speed_rad); + } + else + { + tank_body->SetAngularVelocity(0.0f); + } + + if (tower_rotate_action == left) + { + tower_rotation -= rotate_speed * delta_time; + } + else if (tower_rotate_action == right) + { + tower_rotation += rotate_speed * delta_time; + } + + auto& ph_body_pos = tank_body->GetPosition(); + float ph_body_rot = tank_body->GetAngle(); + + tank_container->setPosition({ph_body_pos.x * pixels_per_meters, ph_body_pos.y * pixels_per_meters}); + tank_container->setRotation(std::fmod( + static_cast(static_cast(ph_body_rot) * 180.0f / std::numbers::pi), 360.0f) + ); + tank_tower_sprite->setRotation(tower_rotation); + + window->clear(sf::Color::Black); + + physics_world.Step(delta_time, 8, 3); + game.update(delta_time); + root_node.draw_scene(); + physics_world.DebugDraw(); + + window->display(); + } + + physics_world.DestroyBody(tank_body); + tank_body = nullptr; + + return 0; +} diff --git a/battle_tanks/client/game_data/atlases/bullet_1.png b/battle_tanks/client/game_data/atlases/bullet_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ac6687fe5282930c22547164244c3076363edc7b GIT binary patch literal 7045 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 z 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 + +class SFMLDebugDraw : public b2Draw +{ +private: + sf::RenderWindow* m_window; + //float m_pixels_per_meter; + static float pixels_per_meter; + +public: + SFMLDebugDraw(sf::RenderWindow& window, float pixels_per_meters); + + /// Convert Box2D's OpenGL style color definition[0-1] to SFML's color definition[0-255], with optional alpha byte[Default - opaque] + static sf::Color GLColorToSFML(const b2Color& color, sf::Uint8 alpha = 255) + { + return sf::Color(static_cast(color.r * 255), static_cast(color.g * 255), static_cast(color.b * 255), alpha); + } + + /// Convert Box2D's vector to SFML vector [Default - scales the vector up by SCALE constants amount] + static sf::Vector2f B2VecToSFVec(const b2Vec2& vector, bool scaleToPixels = true) + { + return sf::Vector2f(vector.x * (scaleToPixels ? pixels_per_meter : 1.f), vector.y * (scaleToPixels ? pixels_per_meter : 1.f)); + } + + /// Draw a closed polygon provided in CCW order. + void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color); + + /// Draw a solid closed polygon provided in CCW order. + void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color); + + /// Draw a circle. + void DrawCircle(const b2Vec2& center, float radius, const b2Color& color); + + /// Draw a solid circle. + void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color); + + /// Draw a line segment. + void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color); + + /// Draw a transform. Choose your own length scale. + void DrawTransform(const b2Transform& xf); + + void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override; +}; diff --git a/battle_tanks/client/sources/debug_draw.cpp b/battle_tanks/client/sources/debug_draw.cpp new file mode 100644 index 0000000..5c7f13a --- /dev/null +++ b/battle_tanks/client/sources/debug_draw.cpp @@ -0,0 +1,111 @@ +#include "SFML/Graphics.hpp" + +#include "debug_draw.hpp" + +float SFMLDebugDraw::pixels_per_meter = 30.f; + +SFMLDebugDraw::SFMLDebugDraw(sf::RenderWindow& window, float pixels_per_meters) : m_window(&window) +{ + pixels_per_meter = pixels_per_meters; +} + +void SFMLDebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) +{ + sf::ConvexShape polygon(vertexCount); + sf::Vector2f center; + for (int i = 0; i < vertexCount; i++) + { + //polygon.setPoint(i, SFMLDraw::B2VecToSFVec(vertices[i])); + sf::Vector2f transformedVec = SFMLDebugDraw::B2VecToSFVec(vertices[i]); + polygon.setPoint(i, sf::Vector2f(std::floor(transformedVec.x), std::floor(transformedVec.y))); // flooring the coords to fix distorted lines on flat surfaces + } // they still show up though.. but less frequently + polygon.setOutlineThickness(-1.f); + polygon.setFillColor(sf::Color::Transparent); + polygon.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); + + m_window->draw(polygon); +} +void SFMLDebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) +{ + sf::ConvexShape polygon(vertexCount); + for (int i = 0; i < vertexCount; i++) + { + //polygon.setPoint(i, SFMLDraw::B2VecToSFVec(vertices[i])); + sf::Vector2f transformedVec = SFMLDebugDraw::B2VecToSFVec(vertices[i]); + polygon.setPoint(i, sf::Vector2f(std::floor(transformedVec.x), std::floor(transformedVec.y))); // flooring the coords to fix distorted lines on flat surfaces + } // they still show up though.. but less frequently + polygon.setOutlineThickness(-1.f); + polygon.setFillColor(SFMLDebugDraw::GLColorToSFML(color, 60)); + polygon.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); + + m_window->draw(polygon); +} +void SFMLDebugDraw::DrawCircle(const b2Vec2& center, float radius, const b2Color& color) +{ + sf::CircleShape circle(radius * pixels_per_meter); + circle.setOrigin(radius * pixels_per_meter, radius * pixels_per_meter); + circle.setPosition(SFMLDebugDraw::B2VecToSFVec(center)); + circle.setFillColor(sf::Color::Transparent); + circle.setOutlineThickness(-1.f); + circle.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); + + m_window->draw(circle); +} +void SFMLDebugDraw::DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) +{ + sf::CircleShape circle(radius * pixels_per_meter); + circle.setOrigin(radius * pixels_per_meter, radius * pixels_per_meter); + circle.setPosition(SFMLDebugDraw::B2VecToSFVec(center)); + circle.setFillColor(SFMLDebugDraw::GLColorToSFML(color, 60)); + circle.setOutlineThickness(1.f); + circle.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); + + b2Vec2 endPoint = center + radius * axis; + sf::Vertex line[2] = + { + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(center), SFMLDebugDraw::GLColorToSFML(color)), + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(endPoint), SFMLDebugDraw::GLColorToSFML(color)), + }; + + m_window->draw(circle); + m_window->draw(line, 2, sf::Lines); +} +void SFMLDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) +{ + sf::Vertex line[] = + { + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(p1), SFMLDebugDraw::GLColorToSFML(color)), + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(p2), SFMLDebugDraw::GLColorToSFML(color)) + }; + + m_window->draw(line, 2, sf::Lines); +} +void SFMLDebugDraw::DrawTransform(const b2Transform& xf) +{ + float lineLength = 0.4; + + /*b2Vec2 xAxis(b2Vec2(xf.p.x + (lineLength * xf.q.c), xf.p.y + (lineLength * xf.q.s)));*/ + b2Vec2 xAxis = xf.p + lineLength * xf.q.GetXAxis(); + sf::Vertex redLine[] = + { + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(xf.p), sf::Color::Red), + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(xAxis), sf::Color::Red) + }; + + // You might notice that the ordinate(Y axis) points downward unlike the one in Box2D testbed + // That's because the ordinate in SFML coordinate system points downward while the OpenGL(testbed) points upward + /*b2Vec2 yAxis(b2Vec2(xf.p.x + (lineLength * -xf.q.s), xf.p.y + (lineLength * xf.q.c)));*/ + b2Vec2 yAxis = xf.p + lineLength * xf.q.GetYAxis(); + sf::Vertex greenLine[] = + { + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(xf.p), sf::Color::Green), + sf::Vertex(SFMLDebugDraw::B2VecToSFVec(yAxis), sf::Color::Green) + }; + + m_window->draw(redLine, 2, sf::Lines); + m_window->draw(greenLine, 2, sf::Lines); +} + +void SFMLDebugDraw::DrawPoint(const b2Vec2& p, float size, const b2Color& color) +{ +} diff --git a/external/headers/boost/di.hpp b/external/headers/boost/di.hpp new file mode 100644 index 0000000..a07a2eb --- /dev/null +++ b/external/headers/boost/di.hpp @@ -0,0 +1,3355 @@ +// +// Copyright (c) 2012-2020 Kris Jusiak (kris at jusiak dot net) +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once +#if (__cplusplus < 201305L && _MSC_VER < 1900) +#error "[Boost::ext].DI requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)" +#else +#define BOOST_DI_VERSION 1'3'0 +#define BOOST_DI_NAMESPACE_BEGIN \ + namespace boost { \ + inline namespace ext { \ + namespace di { \ + inline namespace v1_3_0 { +#define BOOST_DI_NAMESPACE_END \ + } \ + } \ + } \ + } +#if !defined(BOOST_DI_CFG_DIAGNOSTICS_LEVEL) +#define BOOST_DI_CFG_DIAGNOSTICS_LEVEL 1 +#endif +#if defined(BOOST_DI_CFG_FWD) +BOOST_DI_CFG_FWD +#endif +#define __BOOST_DI_COMPILER(arg, ...) __BOOST_DI_COMPILER_IMPL(arg, __VA_ARGS__) +#define __BOOST_DI_COMPILER_IMPL(arg, ...) arg##__VA_ARGS__ +#if defined(__clang__) +#define __CLANG__ __BOOST_DI_COMPILER(__clang_major__, __clang_minor__) +#define __BOOST_DI_UNUSED __attribute__((unused)) +#define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] +#define __BOOST_DI_TYPE_WKND(T) +#define __BOOST_DI_ACCESS_WKND private +#define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND \ + {} +#elif defined(__GNUC__) +#define __GCC__ +#define __BOOST_DI_UNUSED __attribute__((unused)) +#define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] +#define __BOOST_DI_TYPE_WKND(T) +#define __BOOST_DI_ACCESS_WKND private +#define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND \ + {} +#elif defined(_MSC_VER) +#define __MSVC__ +#if !defined(__has_include) +#define __has_include(...) 0 +#endif +#define __BOOST_DI_UNUSED +#define __BOOST_DI_DEPRECATED(...) __declspec(deprecated(__VA_ARGS__)) +#define __BOOST_DI_TYPE_WKND(T) (T &&) +#define __BOOST_DI_ACCESS_WKND public +#define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND +#endif +#if !defined(__has_builtin) +#define __has_builtin(...) 0 +#endif +#if !defined(__has_extension) +#define __has_extension(...) 0 +#endif +#if defined(__CLANG__) +#if (!BOOST_DI_CFG_DIAGNOSTICS_LEVEL) +#pragma clang diagnostic error "-Wdeprecated-declarations" +#else +#pragma clang diagnostic warning "-Wdeprecated-declarations" +#endif +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wundefined-inline" +#pragma clang diagnostic error "-Wundefined-internal" +#pragma clang diagnostic ignored "-Wmissing-field-initializers" +#elif defined(__GCC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic error "-Wdeprecated-declarations" +#if (__GNUC__ < 6) +#pragma GCC diagnostic error "-Werror" +#endif +#elif defined(__MSVC__) +#pragma warning(disable : 4503) +#pragma warning(disable : 4822) +#pragma warning(disable : 4505) +#endif +#if defined(_LIBCPP_VERSION) +#define NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD { +#else +#define NAMESPACE_STD_BEGIN namespace std { +#endif +#if defined(_LIBCPP_VERSION) +#define NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD +#else +#define NAMESPACE_STD_END } +#endif +#if __has_include(<__config>) +#include <__config> +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +class shared_ptr; +template +class weak_ptr; +template +class unique_ptr; +NAMESPACE_STD_END +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +class vector; +NAMESPACE_STD_END +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +class set; +NAMESPACE_STD_END +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +class initializer_list; +NAMESPACE_STD_END +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +class tuple; +NAMESPACE_STD_END +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +class move_iterator; +NAMESPACE_STD_END +#endif +#if __has_include() +#include +#else +NAMESPACE_STD_BEGIN +template +struct char_traits; +NAMESPACE_STD_END +#endif +// clang-format off +#if __has_include() +// clang-format on +#include +#else +namespace boost { +template +class shared_ptr; +} +#endif +BOOST_DI_NAMESPACE_BEGIN +struct _ { + _(...) {} +}; +namespace aux { +using swallow = int[]; +template +using owner = T; +template +struct valid { + using type = int; +}; +template +using valid_t = typename valid::type; +template +struct type {}; +struct none_type {}; +template +struct non_type {}; +template +struct always { + static constexpr auto value = true; +}; +template +struct never { + static constexpr auto value = false; +}; +template +struct identity { + using type = T; +}; +template +struct type_list { + using type = type_list; +}; +template +struct bool_list { + using type = bool_list; +}; +template +struct pair { + using type = pair; + using first = T1; + using second = T2; +}; +template +struct inherit : Ts... { + using type = inherit; +}; +template +struct join { + using type = type_list<>; +}; +template +struct join { + using type = T; +}; +template +struct join, type_list, Ts...> : join, Ts...> {}; +template +struct join, type_list, type_list, type_list, type_list, type_list, + type_list, type_list, type_list, type_list, type_list, type_list, + type_list, type_list, type_list, type_list, type_list, Us...> + : join, + Us...> {}; +template +using join_t = typename join::type; +template +struct index_sequence { + using type = index_sequence; +}; +#if __has_builtin(__make_integer_seq) +template +struct integer_sequence { + using type = index_sequence; +}; +template +struct make_index_sequence_impl { + using type = typename __make_integer_seq::type; +}; +#else +template +struct build_index_sequence; +template +struct build_index_sequence, index_sequence> { + using type = index_sequence; +}; +template +struct make_index_sequence_impl { + using type = typename build_index_sequence::type, + typename make_index_sequence_impl::type>::type; +}; +template <> +struct make_index_sequence_impl<0> : index_sequence<> {}; +template <> +struct make_index_sequence_impl<1> : index_sequence<0> {}; +template <> +struct make_index_sequence_impl<2> : index_sequence<0, 1> {}; +template <> +struct make_index_sequence_impl<3> : index_sequence<0, 1, 2> {}; +template <> +struct make_index_sequence_impl<4> : index_sequence<0, 1, 2, 3> {}; +template <> +struct make_index_sequence_impl<5> : index_sequence<0, 1, 2, 3, 4> {}; +template <> +struct make_index_sequence_impl<6> : index_sequence<0, 1, 2, 3, 4, 5> {}; +template <> +struct make_index_sequence_impl<7> : index_sequence<0, 1, 2, 3, 4, 5, 6> {}; +template <> +struct make_index_sequence_impl<8> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7> {}; +template <> +struct make_index_sequence_impl<9> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8> {}; +template <> +struct make_index_sequence_impl<10> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8, 9> {}; +#endif +template +using make_index_sequence = typename make_index_sequence_impl::type; +} +namespace placeholders { +__BOOST_DI_UNUSED static const struct arg { +} _{}; +} +template +struct named {}; +struct no_name { + constexpr auto operator()() const noexcept { return ""; } +}; +template +struct ctor_traits; +template +struct self {}; +struct ignore_policies {}; +namespace core { +template +struct any_type_fwd; +template +struct any_type_ref_fwd; +template +struct any_type_1st_fwd; +template +struct any_type_1st_ref_fwd; +struct dependency_base {}; +struct injector_base {}; +template +struct dependency__ : T { + using T::create; + using T::is_referable; + using T::try_create; +}; +template +struct injector__ : T { + using T::cfg; + using T::create_impl; + using T::create_successful_impl; +#if defined(__MSVC__) + template + using is_creatable = typename T::template is_creatable; + template + using try_create = typename T::template try_create; +#else + using T::is_creatable; + using T::try_create; +#endif +}; +template +struct array; +struct deduced {}; +struct none {}; +template +class dependency; +} +namespace scopes { +class deduce; +class instance; +class singleton; +class unique; +} +#define __BOOST_DI_REQUIRES(...) typename ::boost::ext::di::v1_3_0::aux::enable_if<__VA_ARGS__, int>::type +#define __BOOST_DI_REQUIRES_MSG(...) typename ::boost::ext::di::v1_3_0::aux::concept_check<__VA_ARGS__>::type +namespace aux { +template +T&& declval(); +template +struct integral_constant { + using type = integral_constant; + static constexpr T value = V; +}; +using true_type = integral_constant; +using false_type = integral_constant; +template +struct conditional { + using type = T; +}; +template +struct conditional { + using type = F; +}; +template +using conditional_t = typename conditional::type; +template +struct enable_if {}; +template +struct enable_if { + using type = T; +}; +template +using enable_if_t = typename enable_if::type; +template +struct concept_check { + static_assert(T::value, "constraint not satisfied"); +}; +template <> +struct concept_check { + using type = int; +}; +template +struct remove_reference { + using type = T; +}; +template +struct remove_reference { + using type = T; +}; +template +struct remove_reference { + using type = T; +}; +template +using remove_reference_t = typename remove_reference::type; +template +struct remove_pointer { + using type = T; +}; +template +struct remove_pointer { + using type = T; +}; +template +using remove_pointer_t = typename remove_pointer::type; +template +struct remove_smart_ptr { + using type = T; +}; +template +struct remove_smart_ptr> { + using type = T; +}; +template +struct remove_smart_ptr> { + using type = T; +}; +template +struct remove_smart_ptr> { + using type = T; +}; +template +struct remove_smart_ptr> { + using type = T; +}; +template +using remove_smart_ptr_t = typename remove_smart_ptr::type; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +struct remove_qualifiers { + using type = T; +}; +template +using remove_qualifiers_t = typename remove_qualifiers::type; +template +struct remove_extent { + using type = T; +}; +template +struct remove_extent { + using type = T; +}; +template +using remove_extent_t = typename remove_extent::type; +template +struct deref_type { + using type = T; +}; +template +struct deref_type> { + using type = remove_qualifiers_t::type>; +}; +template +struct deref_type> { + using type = remove_qualifiers_t::type>; +}; +template +struct deref_type> { + using type = remove_qualifiers_t::type>; +}; +template +struct deref_type> { + using type = remove_qualifiers_t::type>; +}; +template +struct deref_type> { + using type = core::array::type>>; +}; +template +struct deref_type> { + using type = core::array::type>>; +}; +template +struct deref_type> { + using type = core::array::type>>; +}; +template +using decay_t = typename deref_type>::type; +template +struct is_same : false_type {}; +template +struct is_same : true_type {}; +template +struct is_base_of : integral_constant {}; +template +struct is_class : integral_constant {}; +template +struct is_abstract : integral_constant {}; +template +struct is_polymorphic : integral_constant {}; +template +struct is_final : integral_constant {}; +template +using is_valid_expr = true_type; +#if __has_extension(is_constructible) && !((__clang_major__ == 3) && (__clang_minor__ == 5)) +template +using is_constructible = integral_constant; +#else +template +decltype(void(T(declval()...)), true_type{}) test_is_constructible(int); +template +false_type test_is_constructible(...); +template +struct is_constructible : decltype(test_is_constructible(0)) {}; +#endif +template +using is_constructible_t = typename is_constructible::type; +template +decltype(void(T{declval()...}), true_type{}) test_is_braces_constructible(int); +template +false_type test_is_braces_constructible(...); +template +using is_braces_constructible = decltype(test_is_braces_constructible(0)); +template +using is_braces_constructible_t = typename is_braces_constructible::type; +#if defined(__MSVC__) +template +struct is_copy_constructible : integral_constant {}; +template +struct is_default_constructible : integral_constant {}; +#else +template +using is_copy_constructible = is_constructible; +template +using is_default_constructible = is_constructible; +#endif +#if defined(__CLANG__) || defined(__MSVC__) +template +struct is_convertible : integral_constant {}; +#else +struct test_is_convertible__ { + template + static void test(T); +}; +template (declval()))> +true_type test_is_convertible(int); +template +false_type test_is_convertible(...); +template +using is_convertible = decltype(test_is_convertible(0)); +#endif +template > +using is_narrowed = integral_constant::value && !is_class::value && !is_same::value>; +template +struct is_array : false_type {}; +template +struct is_array : true_type {}; +template +true_type is_complete_impl(int); +template +false_type is_complete_impl(...); +template +struct is_complete : decltype(is_complete_impl(0)) {}; +template +is_base_of is_a_impl(int); +template +false_type is_a_impl(...); +template +struct is_a : decltype(is_a_impl(0)) {}; +template +struct is_unique_impl; +template +struct not_unique : false_type { + using type = not_unique; +}; +template <> +struct not_unique<> : true_type { + using type = not_unique; +}; +template +struct is_unique_impl : not_unique<> {}; +template +struct is_unique_impl + : conditional_t, T1>::value, not_unique, is_unique_impl>, Ts...>> {}; +template +using is_unique = is_unique_impl; +template +struct unique; +template +struct unique, T, Ts...> : conditional_t, inherit...>>::value, + unique, Ts...>, unique, Ts...>> {}; +template +struct unique> : type_list {}; +template +using unique_t = typename unique, Ts...>::type; +false_type has_shared_ptr__(...); +#if !defined(BOOST_DI_DISABLE_SHARED_PTR_DEDUCTION) +template +auto has_shared_ptr__(T&&) -> is_valid_expr{})>; +#endif +template +decltype(::boost::ext::di::v1_3_0::aux::declval().operator()(::boost::ext::di::v1_3_0::aux::declval()...), + ::boost::ext::di::v1_3_0::aux::true_type()) +is_invocable_impl(int); +template +::boost::ext::di::v1_3_0::aux::false_type is_invocable_impl(...); +template +struct is_invocable : decltype(is_invocable_impl(0)) {}; +struct callable_base_impl { + void operator()(...) {} +}; +template +struct callable_base : callable_base_impl, + aux::conditional_t::value && !aux::is_final::value, T, aux::none_type> {}; +template +aux::false_type is_callable_impl(T*, aux::non_type* = 0); +aux::true_type is_callable_impl(...); +template +struct is_callable : decltype(is_callable_impl(aux::declval*>())) {}; +template +struct is_empty_expr : false_type {}; +template +#if defined(__MSVC__) +struct is_empty_expr()())>> : integral_constant { +}; +#else +struct is_empty_expr()), decltype(declval()())>> : true_type { +}; +#endif +template +struct function_traits; +template +struct function_traits { + using result_type = R; + using args = type_list; +}; +template +struct function_traits { + using result_type = R; + using args = type_list; +}; +template +struct function_traits { + using result_type = R; + using args = type_list; +}; +template +struct function_traits { + using result_type = R; + using args = type_list; +}; +template +using function_traits_t = typename function_traits::args; +} +namespace core { +template ::type> +struct bindings_impl; +template +struct bindings_impl { + using type = typename T::deps; +}; +template +struct bindings_impl { + using type = aux::type_list; +}; +#if defined(__MSVC__) +template +struct bindings : aux::join_t::type...> {}; +template +using bindings_t = typename bindings::type; +#else +template +using bindings_t = aux::join_t::type...>; +#endif +} +namespace concepts { +template +struct type_ { + template + struct named { + struct is_bound_more_than_once : aux::false_type {}; + }; + struct is_bound_more_than_once : aux::false_type {}; + struct is_neither_a_dependency_nor_an_injector : aux::false_type {}; + struct has_disallowed_qualifiers : aux::false_type {}; + struct is_abstract : +#if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL >= 2) + // clang-format off + decltype( + T{} + ), +// clang-format on +#endif + aux::false_type { + }; + template + struct is_not_related_to : aux::false_type {}; +}; +template +struct any_of : aux::false_type {}; +template +struct is_supported + : aux::is_same::value...>, + aux::bool_list<(aux::is_constructible::value && + (aux::is_a::value || + aux::is_a::value || aux::is_empty_expr::value))...>> { +}; +template +struct get_not_supported; +template +struct get_not_supported { + using type = T; +}; +template +struct get_not_supported + : aux::conditional::value || aux::is_a::value, + typename get_not_supported::type, T> {}; +template +struct is_unique; +template +struct unique_dependency : aux::type {}; +template +struct unique_dependency::value)> + : aux::pair, typename T::priority> {}; +template +struct is_unique> : aux::is_unique::type...> {}; +template +struct get_is_unique_error_impl : aux::true_type {}; +template +struct get_is_unique_error_impl, TPriority>>> { + using type = typename type_::template named::is_bound_more_than_once; +}; +template +struct get_is_unique_error_impl, TPriority>>> { + using type = typename type_::is_bound_more_than_once; +}; +template +struct get_is_unique_error_impl> { + using type = typename type_::is_bound_more_than_once; +}; +template +struct get_is_unique_error; +template +struct get_is_unique_error> + : get_is_unique_error_impl::type...>::type> {}; +template +using boundable_bindings = + aux::conditional_t::value, typename get_is_unique_error>::type, + typename type_::type>::is_neither_a_dependency_nor_an_injector>; +template +struct get_any_of_error : aux::conditional::value...>, + aux::bool_list::value...>>::value, + aux::true_type, any_of> {}; +template +struct is_related { + static constexpr auto value = true; +}; +template +struct is_related { + static constexpr auto value = + aux::is_base_of::value || (aux::is_convertible::value && !aux::is_narrowed::value); +}; +template +struct is_abstract { + static constexpr auto value = false; +}; +template +struct is_abstract { + static constexpr auto value = aux::is_abstract::value; +}; +auto boundable_impl(any_of<>&&) -> aux::true_type; +template +auto boundable_impl(any_of&&) + -> aux::conditional_t>::value, decltype(boundable_impl(aux::declval>())), + typename type_::has_disallowed_qualifiers>; +template +using boundable_impl__ = aux::conditional_t< + is_related::value && aux::is_complete::value, I, T>::value, + aux::conditional_t::value, T>::value, typename type_::is_abstract, aux::true_type>, + typename type_::template is_not_related_to>; +template +auto boundable_impl(I&&, T&&) -> aux::conditional_t>::value || !aux::is_complete::value, + boundable_impl__, typename type_::has_disallowed_qualifiers>; +template +auto boundable_impl(I&&, T&&, aux::valid<>&&) + -> aux::conditional_t::value && aux::is_complete::value, I, T>::value, aux::true_type, + typename type_::template is_not_related_to>; +template +auto boundable_impl(I*[], T&&) -> aux::conditional_t>::value, boundable_impl__, + typename type_::has_disallowed_qualifiers>; +template +auto boundable_impl(I[], T&&) -> aux::conditional_t>::value, boundable_impl__, + typename type_::has_disallowed_qualifiers>; +template +auto boundable_impl(aux::type_list&&) -> boundable_bindings; +template +auto boundable_impl(concepts::any_of&&, T&&) -> + typename get_any_of_error(), aux::declval()))...>::type; +template +auto boundable_impl(aux::type&&) -> typename get_is_unique_error_impl::type>::type; +aux::true_type boundable_impl(...); +template +struct boundable__ { + using type = decltype(boundable_impl(aux::declval()...)); +}; +template +using boundable = typename boundable__::type; +} +namespace type_traits { +struct stack {}; +struct heap {}; +template +struct memory_traits { + using type = stack; +}; +template +struct memory_traits { + using type = heap; +}; +template +struct memory_traits { + using type = typename memory_traits::type; +}; +template +struct memory_traits> { + using type = heap; +}; +template +struct memory_traits> { + using type = heap; +}; +template +struct memory_traits> { + using type = heap; +}; +template +struct memory_traits> { + using type = heap; +}; +template +struct memory_traits::value)> { + using type = heap; +}; +} +namespace concepts { +template +struct scope { + struct is_referable {}; + struct try_create {}; + struct create {}; + template + struct requires_ : aux::false_type {}; +}; +template +struct scope__ { + template + struct scope { + template + using is_referable = aux::true_type; + template + T try_create(const TProvider&); + template + T create(const TProvider&); + }; +}; +template +struct config__ { + template + struct scope_traits { + using type = scope__; + }; + template + struct memory_traits { + using type = type_traits::heap; + }; +}; +template +struct provider__ { + using config = config__; + template + aux::conditional_t::value, T, T*> try_get(const TMemory& = {}) const; + template + T* get(const TMemory& = {}) const { + return nullptr; + } + config& cfg() const; +}; +template +typename scope::template requires_::is_referable, typename scope<_, _>::try_create, + typename scope<_, _>::create> +scopable_impl(...); +template +auto scopable_impl(T&&) + -> aux::is_valid_expr::template is_referable<_, config__<_>>, + decltype(T::template scope<_, _>::template try_create<_, _>(provider__<_>{})), + decltype(aux::declval>().template create<_, _>(provider__<_>{}))>; +template +struct scopable__ { + using type = decltype(scopable_impl(aux::declval())); +}; +template +using scopable = typename scopable__::type; +} +namespace core { +template > +struct pool; +template +using pool_t = pool>; +template +struct pool> : TArgs... { + template + explicit pool(Ts... args) noexcept : Ts(static_cast(args))... {} + template + pool(const aux::type_list&, TPool p) noexcept : pool(static_cast(p)...) { + (void)p; + } + template + pool& operator=(T&& other) noexcept { + (void)aux::swallow{0, (static_cast(*this).operator=(static_cast(other)), 0)...}; + return *this; + } +}; +} +#if !defined(BOOST_DI_CFG_CTOR_LIMIT_SIZE) +#define BOOST_DI_CFG_CTOR_LIMIT_SIZE 10 +#endif +namespace type_traits { +template +struct is_injectable : ::boost::ext::di::v1_3_0::aux::false_type {}; +template +struct is_injectable> + : ::boost::ext::di::v1_3_0::aux::true_type {}; +struct direct {}; +struct uniform {}; +template +using get = T; +template