mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-21 14:49:19 +02:00
ECS System WIP
This commit is contained in:
69
entitysystem/ECScene.cpp
Normal file
69
entitysystem/ECScene.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "ECScene.h"
|
||||
#include "utilities/Logs.h"
|
||||
|
||||
ECScene::ECScene()
|
||||
: m_loaded(false)
|
||||
{
|
||||
}
|
||||
|
||||
ECScene::~ECScene()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
void ECScene::Load()
|
||||
{
|
||||
if (m_loaded)
|
||||
return;
|
||||
|
||||
m_systems.Create(m_world);
|
||||
OnLoad();
|
||||
m_loaded = true;
|
||||
}
|
||||
void ECScene::Unload()
|
||||
{
|
||||
if (!m_loaded)
|
||||
return;
|
||||
|
||||
OnUnload();
|
||||
m_world.Clear();
|
||||
m_loaded = false;
|
||||
}
|
||||
|
||||
void ECScene::Update(float dt)
|
||||
{
|
||||
if (!m_loaded){
|
||||
|
||||
return;
|
||||
}
|
||||
m_systems.Update(m_world, dt);
|
||||
OnUpdate(dt);
|
||||
}
|
||||
|
||||
|
||||
ECWorld& ECScene::World()
|
||||
{
|
||||
return m_world;
|
||||
}
|
||||
|
||||
const ECWorld& ECScene::World() const
|
||||
{
|
||||
return m_world;
|
||||
}
|
||||
|
||||
void ECScene::OnLoad()
|
||||
{
|
||||
}
|
||||
|
||||
void ECScene::OnUnload()
|
||||
{;
|
||||
}
|
||||
|
||||
void ECScene::OnUpdate(float dt)
|
||||
{
|
||||
(void)dt;
|
||||
}
|
||||
42
entitysystem/ECScene.h
Normal file
42
entitysystem/ECScene.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_ECSCENE_H
|
||||
#define EU07_ECSCENE_H
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ECWorld.h"
|
||||
#include "systems/SystemManager.h"
|
||||
|
||||
class ECScene
|
||||
{
|
||||
public:
|
||||
ECScene();
|
||||
virtual ~ECScene();
|
||||
|
||||
void Load();
|
||||
void Unload();
|
||||
void Update(float dt);
|
||||
|
||||
ECWorld& World();
|
||||
const ECWorld& World() const;
|
||||
|
||||
protected:
|
||||
virtual void OnLoad();
|
||||
virtual void OnUnload();
|
||||
virtual void OnUpdate(float dt);
|
||||
|
||||
protected:
|
||||
ECWorld m_world;
|
||||
SystemManager m_systems;
|
||||
|
||||
private:
|
||||
bool m_loaded;
|
||||
};
|
||||
|
||||
|
||||
#endif //EU07_ECSCENE_H
|
||||
54
entitysystem/ECWorld.cpp
Normal file
54
entitysystem/ECWorld.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "ECWorld.h"
|
||||
#include "entitysystem/components/BasicComponents.h"
|
||||
|
||||
entt::entity ECWorld::CreateEntity()
|
||||
{
|
||||
return m_registry.create();
|
||||
}
|
||||
|
||||
void ECWorld::DestroyEntity(entt::entity entity)
|
||||
{
|
||||
if (m_registry.valid(entity))
|
||||
m_registry.destroy(entity);
|
||||
}
|
||||
|
||||
void ECWorld::Clear()
|
||||
{
|
||||
m_registry.clear();
|
||||
}
|
||||
|
||||
bool ECWorld::IsAlive(entt::entity entity) const
|
||||
{
|
||||
return m_registry.valid(entity);
|
||||
}
|
||||
|
||||
|
||||
entt::entity ECWorld::FindEntityByName(const std::string& name) const
|
||||
{
|
||||
auto view = m_registry.view<ECSComponent::Identification>();
|
||||
|
||||
for (auto entity : view)
|
||||
{
|
||||
const auto& id = view.get<ECSComponent::Identification>(entity);
|
||||
if (id.Name.ToString() == name)
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
return entt::null;
|
||||
}
|
||||
|
||||
entt::registry& ECWorld::Registry()
|
||||
{
|
||||
return m_registry;
|
||||
}
|
||||
|
||||
const entt::registry& ECWorld::Registry() const
|
||||
{
|
||||
return m_registry;
|
||||
}
|
||||
135
entitysystem/ECWorld.h
Normal file
135
entitysystem/ECWorld.h
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_ECWORLD_H
|
||||
#define EU07_ECWORLD_H
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
class ECWorld
|
||||
{
|
||||
public:
|
||||
ECWorld() = default;
|
||||
~ECWorld() = default;
|
||||
|
||||
entt::entity CreateEntity();
|
||||
void DestroyEntity(entt::entity entity);
|
||||
void Clear();
|
||||
|
||||
bool IsAlive(entt::entity entity) const;
|
||||
|
||||
entt::registry& Registry();
|
||||
const entt::registry& Registry() const;
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T& AddComponent(entt::entity entity, Args&&... args);
|
||||
|
||||
template<typename T>
|
||||
bool HasComponent(entt::entity entity) const;
|
||||
|
||||
template<typename T>
|
||||
T* GetComponent(entt::entity entity);
|
||||
|
||||
template<typename T>
|
||||
const T* GetComponent(entt::entity entity) const;
|
||||
|
||||
template<typename T>
|
||||
void RemoveComponent(entt::entity entity);
|
||||
|
||||
entt::entity FindEntityByName(const std::string& name) const;
|
||||
|
||||
template<typename... Components>
|
||||
auto View()
|
||||
{
|
||||
return m_registry.view<Components...>();
|
||||
}
|
||||
|
||||
template<typename... Components, typename Func>
|
||||
void Each(Func&& func)
|
||||
{
|
||||
auto view = m_registry.view<Components...>();
|
||||
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto components = std::forward_as_tuple(view.get<Components>(entity)...);
|
||||
|
||||
std::apply([&](Components&... comps)
|
||||
{
|
||||
func(entity, comps...);
|
||||
}, components);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<entt::entity> GetEntities() const
|
||||
{
|
||||
std::vector<entt::entity> entities;
|
||||
auto *storage = m_registry.storage<entt::entity>();
|
||||
|
||||
for (auto entity : *storage)
|
||||
{
|
||||
|
||||
entities.push_back(entity);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
std::size_t GetEntityCount() const
|
||||
{
|
||||
return m_registry.storage<entt::entity>()->size();
|
||||
}
|
||||
|
||||
private:
|
||||
entt::registry m_registry;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T& ECWorld::AddComponent(entt::entity entity, Args&&... args)
|
||||
{
|
||||
static_assert(std::is_constructible_v<T, Args...>,
|
||||
"Component must be constructible with provided arguments");
|
||||
|
||||
if (m_registry.all_of<T>(entity))
|
||||
{
|
||||
return m_registry.replace<T>(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
return m_registry.emplace<T>(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ECWorld::HasComponent(entt::entity entity) const
|
||||
{
|
||||
return m_registry.all_of<T>(entity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* ECWorld::GetComponent(entt::entity entity)
|
||||
{
|
||||
return m_registry.try_get<T>(entity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* ECWorld::GetComponent(entt::entity entity) const
|
||||
{
|
||||
return m_registry.try_get<T>(entity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ECWorld::RemoveComponent(entt::entity entity)
|
||||
{
|
||||
if (m_registry.all_of<T>(entity))
|
||||
m_registry.remove<T>(entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern ECWorld& GetComponentSystem();
|
||||
#define ECS GetComponentSystem()
|
||||
#endif //EU07_ECWORLD_H
|
||||
59
entitysystem/SceneManager.cpp
Normal file
59
entitysystem/SceneManager.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "SceneManager.h"
|
||||
#include "ECScene.h"
|
||||
|
||||
SceneManager::SceneManager() = default;
|
||||
|
||||
SceneManager::~SceneManager()
|
||||
{
|
||||
if (m_currentScene)
|
||||
m_currentScene->Unload();
|
||||
}
|
||||
|
||||
void SceneManager::SetScene(std::unique_ptr<ECScene> scene)
|
||||
{
|
||||
m_pendingScene = std::move(scene);
|
||||
if (m_currentScene)
|
||||
m_currentScene->Load();
|
||||
}
|
||||
|
||||
void SceneManager::Update(float dt)
|
||||
{
|
||||
if (m_pendingScene)
|
||||
SwitchScene();
|
||||
|
||||
if (m_currentScene){
|
||||
m_currentScene->Update(dt);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SceneManager::SwitchScene()
|
||||
{
|
||||
if (m_currentScene)
|
||||
m_currentScene->Unload();
|
||||
|
||||
m_currentScene = std::move(m_pendingScene);
|
||||
|
||||
if (m_currentScene)
|
||||
m_currentScene->Load();
|
||||
}
|
||||
|
||||
ECScene* SceneManager::CurrentScene()
|
||||
{
|
||||
return m_currentScene.get();
|
||||
}
|
||||
|
||||
const ECScene* SceneManager::CurrentScene() const
|
||||
{
|
||||
return m_currentScene.get();
|
||||
}
|
||||
|
||||
bool SceneManager::HasScene() const
|
||||
{
|
||||
return m_currentScene != nullptr;
|
||||
}
|
||||
40
entitysystem/SceneManager.h
Normal file
40
entitysystem/SceneManager.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_SCENEMANAGER_H
|
||||
#define EU07_SCENEMANAGER_H
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class ECScene;
|
||||
|
||||
class SceneManager
|
||||
{
|
||||
public:
|
||||
SceneManager();
|
||||
~SceneManager();
|
||||
|
||||
void SetScene(std::unique_ptr<ECScene> scene);
|
||||
void Update(float dt);
|
||||
|
||||
ECScene* CurrentScene();
|
||||
const ECScene* CurrentScene() const;
|
||||
|
||||
bool HasScene() const;
|
||||
|
||||
private:
|
||||
void SwitchScene();
|
||||
|
||||
private:
|
||||
std::unique_ptr<ECScene> m_currentScene;
|
||||
std::unique_ptr<ECScene> m_pendingScene;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //EU07_SCENEMANAGER_H
|
||||
@@ -3,11 +3,14 @@
|
||||
*/
|
||||
#ifndef EU07_BASICCOMPONENTS_H
|
||||
#define EU07_BASICCOMPONENTS_H
|
||||
#include "audio/sound.h"
|
||||
#include "entt/entity/entity.hpp"
|
||||
#include "glm/vec3.hpp"
|
||||
#include "glm/gtc/quaternion.hpp"
|
||||
#include <string>
|
||||
#include "registry/FName.h"
|
||||
#include "utils/uuid.hpp"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace ECSComponent
|
||||
{
|
||||
@@ -16,18 +19,23 @@ namespace ECSComponent
|
||||
///</summary>
|
||||
struct Transform
|
||||
{
|
||||
glm::vec3 Position{0.f}; // object position
|
||||
glm::dvec3 Position{0.f}; // object position
|
||||
glm::quat Rotation{1.f, 0.f, 0.f, 0.f}; // object rotation
|
||||
glm::vec3 Scale{1.f}; // object scale
|
||||
};
|
||||
|
||||
struct Velocity
|
||||
{
|
||||
glm::vec3 Value{0.f}; // object velocity
|
||||
};
|
||||
|
||||
///< summary>
|
||||
/// Basic component for naming entities
|
||||
/// in future for scenery hierarchy
|
||||
///</summary>
|
||||
struct Identification
|
||||
{
|
||||
std::string Name; // object name - may contain slashes for editor hierarchy "directories"
|
||||
FName Name; // object name - may contain slashes for editor hierarchy "directories"
|
||||
std::uint64_t Id{0}; // id in scene
|
||||
};
|
||||
|
||||
@@ -39,6 +47,16 @@ struct Parent
|
||||
entt::entity value{entt::null};
|
||||
};
|
||||
|
||||
struct SoundComponent
|
||||
{
|
||||
sound_source sound; // sound source
|
||||
float volume = 1.0f; // 0–1
|
||||
float pitch = 1.0f; // speed / pitch
|
||||
float range = 1.0f; // range
|
||||
bool loop = false;
|
||||
bool playOnStart = false;
|
||||
bool isPlaying = false;
|
||||
};
|
||||
///< summary>
|
||||
/// Empty component for entities that are disabled and should not be processed by systems
|
||||
///</summary>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef EU07_RENDERCOMPONENTS_H
|
||||
#define EU07_RENDERCOMPONENTS_H
|
||||
|
||||
#include "registry/FName.h"
|
||||
#include "rendering/geometrybank.h"
|
||||
|
||||
namespace ECSComponent
|
||||
{
|
||||
/// <summary>
|
||||
@@ -11,6 +14,8 @@ namespace ECSComponent
|
||||
/// </remarks>
|
||||
struct MeshRenderer
|
||||
{
|
||||
gfx::geometry_handle meshHandle;
|
||||
bool visible = true;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -19,7 +24,53 @@ struct MeshRenderer
|
||||
/// <remarks>Currently empty
|
||||
/// TODO: Add component members
|
||||
/// </remarks>
|
||||
struct SpotLight{};
|
||||
struct SpotLight
|
||||
{
|
||||
glm::vec3 Color{ 1.0f, 1.0f, 1.0f };
|
||||
|
||||
float Intensity = 1.0f;
|
||||
float Range = 25.0f;
|
||||
|
||||
float InnerAngle = 15.0f;
|
||||
float OuterAngle = 25.0f;
|
||||
|
||||
bool CastShadows = false;
|
||||
bool Enabled = true;
|
||||
};
|
||||
|
||||
// TODO: AreaLight like blender
|
||||
// TODO: SunLight for scene
|
||||
|
||||
|
||||
struct ParticleEmitter
|
||||
{
|
||||
FName particleEffectPath = ("");
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
struct Decal
|
||||
{
|
||||
FName decalTexturePath = ("");
|
||||
float size = 1.0f;
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
struct Billboard
|
||||
{
|
||||
FName texturePath = ("");
|
||||
float size = 1.0f;
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
struct Line {
|
||||
glm::vec3 start{ 0.0f };
|
||||
glm::vec3 end{ 1.0f, 0.0f, 0.0f };
|
||||
glm::vec3 color{ 1.0f, 1.0f, 1.0f };
|
||||
float thickness = 1.0f;
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Component for entities that can be rendered with LOD
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
//
|
||||
// Created by Hirek on 3/14/2026.
|
||||
//
|
||||
|
||||
#include "ecs.h"
|
||||
|
||||
void ECS::ClearWorld()
|
||||
{
|
||||
world_.clear();
|
||||
}
|
||||
|
||||
entt::entity ECS::CreateObject()
|
||||
{
|
||||
const auto e = world_.create();
|
||||
world_.emplace<ECSComponent::Transform>(e);
|
||||
// add UID
|
||||
auto id = world_.emplace<ECSComponent::Identification>(e);
|
||||
id.Id = nextId_++;
|
||||
return e;
|
||||
}
|
||||
|
||||
void ECS::DestroyObject(entt::entity Entity)
|
||||
{
|
||||
if (Entity == entt::null) // check if Entity is not null
|
||||
return;
|
||||
if (!world_.valid(Entity)) // check if exist
|
||||
return;
|
||||
world_.destroy(Entity);
|
||||
}
|
||||
|
||||
bool ECS::ValidObject(entt::entity entity) const
|
||||
{
|
||||
return entity != entt::null && world_.valid(entity);
|
||||
}
|
||||
|
||||
entt::entity ECS::FindById(std::uint64_t id)
|
||||
{
|
||||
auto view = world_.view<const ECSComponent::Identification>();
|
||||
for (auto e : view)
|
||||
{
|
||||
const auto &ident = view.get<ECSComponent::Identification>(e);
|
||||
if (ident.Id == id)
|
||||
return e;
|
||||
}
|
||||
return entt::null;
|
||||
}
|
||||
|
||||
std::vector<entt::entity> ECS::FindByName(std::string_view name)
|
||||
{
|
||||
std::vector<entt::entity> result;
|
||||
|
||||
auto view = world_.view<const ECSComponent::Identification>();
|
||||
for (auto e : view)
|
||||
{
|
||||
const auto &ident = view.get<ECSComponent::Identification>(e);
|
||||
if (ident.Name == name)
|
||||
{
|
||||
result.push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ECS &GetComponentSystem()
|
||||
{
|
||||
static ECS _ecs;
|
||||
return _ecs;
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
//
|
||||
// Created by Hirek on 3/14/2026.
|
||||
//
|
||||
|
||||
#ifndef EU07_ECS_H
|
||||
#define EU07_ECS_H
|
||||
#include "components/BasicComponents.h"
|
||||
#include "entt/entity/registry.hpp"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
class ECS final
|
||||
{
|
||||
private:
|
||||
entt::registry world_; // scene registry
|
||||
std::uint64_t nextId_ = 1; // 0 is invalid/none
|
||||
|
||||
|
||||
public:
|
||||
//
|
||||
// World lifecycle
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Clears the world, removing all entities and components
|
||||
/// </summary>
|
||||
void ClearWorld();
|
||||
|
||||
//
|
||||
// Objects
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Creates new object with basic components (Transform, Identification) and returns its entity handle.
|
||||
/// </summary>
|
||||
/// <returns>Entity handle of created object</returns>
|
||||
entt::entity CreateObject();
|
||||
|
||||
/// <summary>
|
||||
/// Destroys object with it's all components
|
||||
/// </summary>
|
||||
/// <param name="Entity">Entity to be removed</param>
|
||||
void DestroyObject(entt::entity Entity);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if object with given entity handle exists in the registry
|
||||
/// </summary>
|
||||
/// <param name="entity">Entity handle to check</param>
|
||||
/// <returns>true if object exists, false otherwise</returns>
|
||||
bool ValidObject(entt::entity entity) const;
|
||||
|
||||
//
|
||||
// Identification lookups
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Finds object with given UID. Returns null entity if not found.
|
||||
/// </summary>
|
||||
/// <param name="id">UID of object</param>
|
||||
entt::entity FindById(std::uint64_t id);
|
||||
|
||||
/// <summary>
|
||||
/// Finds objects with given name. Returns empty vector if not found.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of object</param>
|
||||
/// <remarks>May return more than 1 as many objects can have the same name</remarks>
|
||||
std::vector<entt::entity> FindByName(std::string_view name);
|
||||
|
||||
//
|
||||
// Components
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Adds component of type T to entity, forwarding provided arguments to component constructor. If component already exists, it will be replaced.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Component type</typeparam>
|
||||
/// <param name="entity">Entity to which component will be added</param>
|
||||
/// <param name="args">Arguments forwarded to component constructor</param>
|
||||
/// <returns>Reference to added component</returns>
|
||||
template <class T, class... Args> T &AddComponent(entt::entity entity, Args &&...args)
|
||||
{
|
||||
return world_.emplace<T>(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns entity's component
|
||||
/// </summary>
|
||||
/// <typeparam name="T"> type</typeparam>
|
||||
/// <param name="entity">Entity to which component will be added</param>
|
||||
/// <returns>Reference to added component</returns>
|
||||
template <class T> T &GetComponent(entt::entity entity)
|
||||
{
|
||||
return world_.get<T>(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns entity's component
|
||||
/// </summary>
|
||||
/// <typeparam name="T"> type</typeparam>
|
||||
/// <param name="entity">Entity to which component will be added</param>
|
||||
/// <returns>Reference to added component</returns>
|
||||
template <class T> const T &GetComponent(entt::entity entity) const
|
||||
{
|
||||
return world_.get<T>(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get component of type T from entity. Returns nullptr if component does not exist.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Component type</typeparam>
|
||||
/// <param name="entity">Entity from which component will be retrieved</param>
|
||||
/// <returns>Pointer to component if exists, nullptr otherwise</returns>
|
||||
template <class T> T *TryGetComponent(entt::entity entity)
|
||||
{
|
||||
return world_.try_get<T>(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get component of type T from entity. Returns nullptr if component does not exist.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Component type</typeparam>
|
||||
/// <param name="entity">Entity from which component will be retrieved</param>
|
||||
/// <returns>Pointer to component if exists, nullptr otherwise</returns>
|
||||
template <class T> const T *TryGetComponent(entt::entity entity) const
|
||||
{
|
||||
return world_.try_get<T>(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if entity has component of type T.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Component type</typeparam>
|
||||
/// <param name="entity">Entity to check</param>
|
||||
/// <returns>true if entity has component, false otherwise</returns>
|
||||
template <class... T> bool HasComponent(entt::entity entity) const
|
||||
{
|
||||
return world_.all_of<T...>(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes component of type T from entity. Does nothing if component does not exist.
|
||||
/// </summary> <typeparam name="T">Component type</typeparam>
|
||||
/// <param name="entity">Entity from which component will be removed</param>
|
||||
template <class... T> void RemoveComponent(entt::entity entity)
|
||||
{
|
||||
world_.remove<T...>(entity);
|
||||
}
|
||||
};
|
||||
|
||||
extern ECS& GetComponentSystem();
|
||||
#define CS GetComponentSystem()
|
||||
#endif // EU07_ECS_H
|
||||
35
entitysystem/scenes/GameScene.cpp
Normal file
35
entitysystem/scenes/GameScene.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "GameScene.h"
|
||||
|
||||
|
||||
#include "entitysystem/components/BasicComponents.h"
|
||||
#include "entitysystem/components/RenderComponents.h"
|
||||
#include "entitysystem/systems/MovementSystem.h"
|
||||
#include "utilities/Logs.h"
|
||||
|
||||
GameScene::GameScene() = default;
|
||||
GameScene::~GameScene() = default ;
|
||||
|
||||
void GameScene::OnLoad()
|
||||
{
|
||||
m_systems.AddSystem<MovementSystem>();
|
||||
|
||||
}
|
||||
|
||||
void GameScene::OnUpdate(float dt)
|
||||
{
|
||||
|
||||
//auto& world = World();
|
||||
|
||||
//auto view = world.View<ECSComponent::Transform>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void GameScene::OnUnload()
|
||||
{
|
||||
World().Clear();
|
||||
}
|
||||
30
entitysystem/scenes/GameScene.h
Normal file
30
entitysystem/scenes/GameScene.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_GAMESCENE_H
|
||||
#define EU07_GAMESCENE_H
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "entitysystem/ECScene.h"
|
||||
|
||||
class GameScene final : public ECScene
|
||||
{
|
||||
public:
|
||||
GameScene();
|
||||
~GameScene() override;
|
||||
|
||||
private:
|
||||
void OnLoad() override;
|
||||
void OnUnload() override;
|
||||
void OnUpdate(float dt) override;
|
||||
|
||||
private:
|
||||
void CreateTestEntities();
|
||||
};
|
||||
|
||||
|
||||
#endif //EU07_GAMESCENE_H
|
||||
5
entitysystem/systems/BaseSystem.cpp
Normal file
5
entitysystem/systems/BaseSystem.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "BaseSystem.h"
|
||||
25
entitysystem/systems/BaseSystem.h
Normal file
25
entitysystem/systems/BaseSystem.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_BASICSYSTEM_H
|
||||
#define EU07_BASICSYSTEM_H
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
class ECWorld;
|
||||
|
||||
class BaseSystem
|
||||
{
|
||||
public:
|
||||
virtual ~BaseSystem() = default;
|
||||
|
||||
virtual void OnCreate(ECWorld& world) {}
|
||||
virtual void OnDestroy(ECWorld& world) {}
|
||||
|
||||
virtual void Update(ECWorld& world, float dt) {}
|
||||
};
|
||||
|
||||
|
||||
#endif //EU07_BASICSYSTEM_H
|
||||
29
entitysystem/systems/MovementSystem.cpp
Normal file
29
entitysystem/systems/MovementSystem.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "MovementSystem.h"
|
||||
#include "entitysystem/ECWorld.h"
|
||||
#include "entitysystem/components/BasicComponents.h"
|
||||
#include "utilities/Logs.h"
|
||||
|
||||
|
||||
void MovementSystem::Update(ECWorld& world, float dt)
|
||||
{
|
||||
constexpr double damping = 0.90; // 0.0 = instant stop, 1.0 = without damping
|
||||
|
||||
world.Each<ECSComponent::Transform, ECSComponent::Velocity>(
|
||||
[dt](auto entity, auto& transform, auto& velocity)
|
||||
{
|
||||
|
||||
transform.Position += velocity.Value * dt;
|
||||
|
||||
velocity.Value *= damping;
|
||||
|
||||
if (glm::length(velocity.Value) < 0.001)
|
||||
{
|
||||
velocity.Value = glm::dvec3(0.0);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
25
entitysystem/systems/MovementSystem.h
Normal file
25
entitysystem/systems/MovementSystem.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_MOVEMENTSYSTEM_H
|
||||
#define EU07_MOVEMENTSYSTEM_H
|
||||
|
||||
|
||||
#pragma once
|
||||
#include "BaseSystem.h"
|
||||
|
||||
namespace ECSComponent
|
||||
{
|
||||
struct Transform;
|
||||
struct Velocity;
|
||||
}
|
||||
|
||||
class MovementSystem : public BaseSystem
|
||||
{
|
||||
public:
|
||||
void Update(ECWorld& world, float dt) override;
|
||||
};
|
||||
|
||||
|
||||
#endif //EU07_MOVEMENTSYSTEM_H
|
||||
33
entitysystem/systems/SystemManager.cpp
Normal file
33
entitysystem/systems/SystemManager.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#include "SystemManager.h"
|
||||
#include "entitysystem/systems/BaseSystem.h"
|
||||
#include "entitysystem/ECWorld.h"
|
||||
#include "utilities/Logs.h"
|
||||
|
||||
SystemManager::~SystemManager() = default;
|
||||
|
||||
void SystemManager::Create(ECWorld& world)
|
||||
{
|
||||
WriteLog("[SystemManager] Creating systems");
|
||||
for (auto& system : m_systems){
|
||||
system->OnCreate(world);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SystemManager::Destroy(ECWorld& world)
|
||||
{
|
||||
WriteLog("[SystemManager] Destroying systems");
|
||||
for (auto& system : m_systems)
|
||||
system->OnDestroy(world);
|
||||
}
|
||||
|
||||
void SystemManager::Update(ECWorld& world, float dt)
|
||||
{
|
||||
|
||||
for (auto& system : m_systems)
|
||||
system->Update(world, dt);
|
||||
}
|
||||
46
entitysystem/systems/SystemManager.h
Normal file
46
entitysystem/systems/SystemManager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by Daniu
|
||||
//
|
||||
|
||||
#ifndef EU07_SYSTEMMANAGER_H
|
||||
#define EU07_SYSTEMMANAGER_H
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseSystem.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class ECWorld;
|
||||
|
||||
class SystemManager
|
||||
{
|
||||
public:
|
||||
SystemManager() = default;
|
||||
~SystemManager();
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T& AddSystem(Args&&... args)
|
||||
{
|
||||
static_assert(std::is_base_of_v<BaseSystem, T>);
|
||||
auto system = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
T& ref = *system;
|
||||
m_systems.emplace_back(std::move(system));
|
||||
return ref;
|
||||
}
|
||||
|
||||
void Create(ECWorld& world);
|
||||
void Destroy(ECWorld& world);
|
||||
|
||||
void Update(ECWorld& world, float dt);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<BaseSystem>> m_systems;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //EU07_SYSTEMMANAGER_H
|
||||
Reference in New Issue
Block a user