|
|
@ -0,0 +1,139 @@ |
|
|
|
#pragma once |
|
|
|
#include <memory> |
|
|
|
#include <vector> |
|
|
|
#include <chrono> |
|
|
|
#include <utility> |
|
|
|
#include <ranges> |
|
|
|
#include "transform.h" |
|
|
|
#include "component.h" |
|
|
|
|
|
|
|
namespace ant::core { |
|
|
|
struct entity { |
|
|
|
[[nodiscard]] auto transform() const -> ant::core::transform<float> { |
|
|
|
return m_transform; |
|
|
|
} |
|
|
|
auto transform() -> ant::core::transform<float>& { |
|
|
|
return m_transform; |
|
|
|
} |
|
|
|
[[nodiscard]] auto world_transform() const -> ant::core::transform<float> { |
|
|
|
ant::core::transform<float> ret{{0,0},0}; |
|
|
|
if(auto parent = m_parent.lock(); parent) { |
|
|
|
ret = parent->world_transform(); |
|
|
|
} |
|
|
|
auto transform_pivot = transform(); |
|
|
|
if(ret.angle != 0.0f) { |
|
|
|
transform_pivot.position.X *= std::cos(ret.angle*std::numbers::pi/180); |
|
|
|
transform_pivot.position.Y *= std::sin(ret.angle*std::numbers::pi/180); |
|
|
|
} |
|
|
|
return ret + transform_pivot; |
|
|
|
} |
|
|
|
[[nodiscard]] auto parent() const -> std::shared_ptr<entity> { |
|
|
|
return m_parent.lock(); |
|
|
|
} |
|
|
|
[[nodiscard]] auto is_visible() const -> bool { |
|
|
|
if(auto parent = m_parent.lock(); parent){ |
|
|
|
if(not parent->is_visible()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return m_is_visible; |
|
|
|
} |
|
|
|
[[nodiscard]] auto visibility_flag() const -> bool { |
|
|
|
return m_is_visible; |
|
|
|
} |
|
|
|
[[nodiscard]] auto find_components(std::string name) const -> std::vector<std::shared_ptr<component>> { |
|
|
|
decltype(m_components) ret; |
|
|
|
auto source = m_components | std::views::filter([&](const auto& elem) {return name == elem->name();}); |
|
|
|
std::ranges::copy(source, std::back_inserter(ret)); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
[[nodiscard]] auto components_list() const -> const std::vector<std::shared_ptr<component>>& { |
|
|
|
return m_components; |
|
|
|
} |
|
|
|
[[nodiscard]] auto components_list() -> std::vector<std::shared_ptr<component>>& { |
|
|
|
return m_components; |
|
|
|
} |
|
|
|
template<std::derived_from<component> ComponentType, typename... ARGS> |
|
|
|
auto add_component(ARGS&&... constructor_args) -> std::shared_ptr<entity> { |
|
|
|
auto component = std::make_shared<ComponentType>(std::forward<ARGS>(constructor_args)...); |
|
|
|
auto self = m_self.lock(); |
|
|
|
component->m_owner = self; |
|
|
|
m_components.push_back(component); |
|
|
|
component->initialize(); |
|
|
|
return self; |
|
|
|
} |
|
|
|
auto set_visible(bool visible) -> bool { |
|
|
|
return std::exchange(m_is_visible, visible); |
|
|
|
} |
|
|
|
virtual void initialize() {} |
|
|
|
virtual void render() { |
|
|
|
if(not visibility_flag()) return; |
|
|
|
for(auto& child : m_children | std::views::filter([](const std::shared_ptr<entity>& elem){return elem->visibility_flag();})) { |
|
|
|
child->render(); |
|
|
|
} |
|
|
|
for(auto& component : m_components) { |
|
|
|
component->render(); |
|
|
|
} |
|
|
|
} |
|
|
|
virtual void update(std::chrono::duration<double> delta_time) { |
|
|
|
for(auto& child : m_children) { |
|
|
|
child->update(delta_time); |
|
|
|
} |
|
|
|
for(auto& component : m_components) { |
|
|
|
component->update(delta_time); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
entity(const std::shared_ptr<entity>& parent) |
|
|
|
: m_is_visible(true) |
|
|
|
, m_parent(parent) |
|
|
|
, m_children() |
|
|
|
, m_components() |
|
|
|
, m_transform{.position = {0,0}, .angle = 0} |
|
|
|
{} |
|
|
|
|
|
|
|
entity() |
|
|
|
: m_is_visible(true) |
|
|
|
, m_parent(std::shared_ptr<entity>(nullptr)) |
|
|
|
, m_children() |
|
|
|
, m_components() |
|
|
|
, m_transform{.position = {0,0}, .angle = 0} |
|
|
|
{} |
|
|
|
private: |
|
|
|
bool m_is_visible; |
|
|
|
std::weak_ptr<entity> m_parent; |
|
|
|
std::weak_ptr<entity> m_self; |
|
|
|
std::vector<std::shared_ptr<entity>> m_children; |
|
|
|
std::vector<std::shared_ptr<component>> m_components; |
|
|
|
ant::core::transform<float> m_transform; |
|
|
|
|
|
|
|
template<std::derived_from<entity> EntityType> |
|
|
|
friend auto make_entity(const std::shared_ptr<entity>& parent, auto&&... ARGS) -> std::shared_ptr<EntityType>; |
|
|
|
|
|
|
|
template<std::derived_from<entity> EntityType> |
|
|
|
friend auto make_entity(auto&&... ARGS) -> std::shared_ptr<EntityType>; |
|
|
|
}; |
|
|
|
|
|
|
|
template<std::derived_from<entity> EntityType> |
|
|
|
[[nodiscard]] auto make_entity(const std::shared_ptr<entity>& parent, auto&&... ARGS) -> std::shared_ptr<EntityType> { |
|
|
|
auto object = std::make_shared<EntityType>(std::forward<decltype(ARGS)>(ARGS)...); |
|
|
|
const std::shared_ptr<entity>& entity_router = object; |
|
|
|
entity_router->m_parent = parent; |
|
|
|
entity_router->m_self = object; |
|
|
|
if(parent) { |
|
|
|
parent->m_children.push_back(object); |
|
|
|
} |
|
|
|
object->initialize(); |
|
|
|
return object; |
|
|
|
} |
|
|
|
|
|
|
|
template<std::derived_from<entity> EntityType> |
|
|
|
[[nodiscard]] auto make_entity(auto&&... ARGS) -> std::shared_ptr<EntityType> { |
|
|
|
auto object = std::make_shared<EntityType>(std::shared_ptr<entity>(nullptr), std::forward<decltype(ARGS)>(ARGS)...); |
|
|
|
const std::shared_ptr<entity>& entity_router = object; |
|
|
|
entity_router->m_parent = std::shared_ptr<entity>(nullptr); |
|
|
|
entity_router->m_self = object; |
|
|
|
object->initialize(); |
|
|
|
return object; |
|
|
|
} |
|
|
|
} |