ECS with entt

This commit is contained in:
Erris
2026-02-17 00:50:43 +01:00
parent 86392e0790
commit d4c420d5b4
30 changed files with 1314 additions and 222 deletions

View File

@@ -2,8 +2,10 @@
#define OPEN_ENGINE_HPP
#include "open_engine/orthographic_camera_controller.hpp"
#include "open_engine/scene/native_scriptable_entity.hpp"
#include "open_engine/imgui/imgui_layer.hpp"
#include "open_engine/events/key_event.hpp"
#include "open_engine/scene/components.hpp"
#include "open_engine/application.hpp"
#include "open_engine/ref_scope.hpp"
#include "open_engine/logging.hpp"
@@ -21,7 +23,9 @@
#include "open_engine/renderer/renderer2d.hpp"
#include "open_engine/renderer/renderer.hpp"
#include "open_engine/renderer/texture.hpp"
#include "open_engine/scene/components.hpp"
#include "open_engine/renderer/buffer.hpp"
#include "open_engine/renderer/shader.hpp"
#include "open_engine/scene/entity.hpp"
#include "open_engine/scene/scene.hpp"
#endif // OPEN_ENGINE_HPP

View File

@@ -22,6 +22,7 @@ namespace OpenEngine {
void QueueLayerPop(Ref<Layer> layer);
void QueueOverlayPush(Ref<Layer> layer);
void QueueOverlayPop(Ref<Layer> layer);
ImGuiLayer* GetImGuiLayer() { return imgui_layer.get(); };
inline static Application& Get() { return *instance; };

View File

@@ -14,6 +14,7 @@
#define BIT(x) (1 << x)
#define BIND_EVENT_FN(function) std::bind(&function, this, std::placeholders::_1)
//#define BIND_EVENT_FN(function) std::bind(&function, this, std::placeholders::_1)
#define BIND_EVENT_FN(fn) [this](auto&&...args) -> decltype(auto) { return this->fn(std::forward<decltype(args)>(args)...); }
#endif // CORE_HPP

View File

@@ -1,6 +1,7 @@
#ifndef IMGUI_LAYER_HPP
#define IMGUI_LAYER_HPP
#include "open_engine/events/key_event.hpp"
#include "open_engine/events/event.hpp"
#include "open_engine/layer.hpp"
@@ -15,11 +16,15 @@ namespace OpenEngine {
virtual void OnDetach() override;
virtual void OnImGuiRender() override;
virtual void OnEvent(Event& event) override;
bool CloseWindow(OpenEngine::KeyPressedEvent& event);
void SetBlockEvents(bool block) { block_events = block; };
void Begin();
void End();
private:
bool block_events = false;
float previous_frame_time = 0.0f;
};
}

View File

@@ -1,5 +1,5 @@
#ifndef CAMERA_HPP
#define CAMERA_HPP
#ifndef ORTHOGRAPHIC_CAMERA_HPP
#define ORTHOGRAPHIC_CAMERA_HPP
#include <glm/fwd.hpp>
#include <glm/glm.hpp>
@@ -33,4 +33,4 @@ namespace OpenEngine {
};
}
#endif // CAMERA_HPP
#endif // ORTHOGRAPHIC_CAMERA_HPP

View File

@@ -7,6 +7,7 @@
#include <iostream>
#include <sstream>
#include <cstdint>
#include <memory>
#include <array>

View File

@@ -0,0 +1,26 @@
#ifndef CAMERA_HPP
#define CAMERA_HPP
#include <glm/glm.hpp>
namespace OpenEngine {
class Camera
{
public:
Camera() = default;
~Camera() = default;
Camera(const glm::mat4& projection)
: projection(projection)
{
};
const glm::mat4& GetProjection() const { return projection; };
protected:
glm::mat4 projection = glm::mat4(1.0f);
};
}
#endif // CAMERA_HPP

View File

@@ -1,9 +1,10 @@
#ifndef RENDERER2D_HPP
#define RENDERER2D_HPP
#include "open_engine/orthographic_camera.hpp"
#include "open_engine/renderer/subtexture2d.hpp"
#include "open_engine/orthographic_camera.hpp"
#include "open_engine/renderer/texture.hpp"
#include "open_engine/renderer/camera.hpp"
#include "open_engine/ref_scope.hpp"
#include <glm/fwd.hpp>
@@ -32,6 +33,7 @@ namespace OpenEngine {
static void Shutdown();
static void BeginScene(const OrthographicCamera& camera);
static void BeginScene(const Camera& camera, const glm::mat4& transform);
static void EndScene();
static void Flush();
@@ -39,6 +41,10 @@ namespace OpenEngine {
static void DrawQuad(const Transform& transform_data, const Ref<Texture2D>& texture, float tiling_factor = 1.0f);
static void DrawQuad(const Transform& transform_data, const Ref<Subtexture2D>& subtexture, float tiling_factor = 1.0f);
static void DrawQuad(const glm::mat4& transform, const glm::vec4& color);
static void DrawQuad(const glm::mat4& transform, const Ref<Texture2D>& texture, float tiling_factor = 1.0f);
static void DrawQuad(const glm::mat4& transform, const Ref<Subtexture2D>& subtexture, float tiling_factor = 1.0f);
static void ResetStats();
static const Statistics& GetStats();

View File

@@ -0,0 +1,151 @@
#ifndef COMPONENTS_HPP
#define COMPONENTS_HPP
#include "open_engine/scene/native_scriptable_entity.hpp"
#include "open_engine/scene/scene_camera.hpp"
#include <cstring>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <imgui.h>
#include <string>
namespace OpenEngine {
struct TagComponent
{
std::string tag;
TagComponent() = default;
TagComponent(const TagComponent&) = default;
TagComponent(const std::string& tag)
: tag(tag) {}
void OnImGuiRender(Entity& entity)
{
char buffer[256];
std::memset(buffer, 0, sizeof(buffer));
std::strncpy(buffer, tag.c_str(), sizeof(buffer));
ImGui::Text("Name");
if (ImGui::InputText("##tagEditor", buffer, sizeof(buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)
|| (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)))
tag = buffer;
};
};
struct TransformComponent
{
glm::mat4 transform{ 1.0f };
TransformComponent() = default;
TransformComponent(const TransformComponent&) = default;
TransformComponent(const glm::mat4& transform_mat)
: transform(transform_mat) {}
operator glm::mat4() { return transform; };
operator const glm::mat4() const { return transform; };
void OnImGuiRender(Entity& entity)
{
ImGui::DragFloat3("Position", glm::value_ptr(transform[3]), 0.1f);
};
};
struct SpriteRendererComponent
{
glm::vec4 color{ 1.0f, 1.0f, 1.0f, 1.0f };
SpriteRendererComponent() = default;
SpriteRendererComponent(const SpriteRendererComponent&) = default;
SpriteRendererComponent(const glm::vec4& color)
: color(color) {}
void OnImGuiRender(Entity& entity)
{
ImGui::ColorEdit4("color", glm::value_ptr(color));
};
};
struct CameraComponent
{
SceneCamera camera;
bool primary = true;
bool fixed_aspect_ratio = false;
CameraComponent() = default;
CameraComponent(const CameraComponent&) = default;
void OnImGuiRender(Entity& entity)
{
ImGui::Checkbox("Is primary", &primary);
const char* projection_type_strings[] = {"Perspective", "Orthographic"};
const char* current_projection_type = projection_type_strings[(int)camera.GetProjectionType()];
if (ImGui::BeginCombo("Projection", current_projection_type)) {
for (int i = 0; i < 2; i++) {
bool is_selected = current_projection_type == projection_type_strings[i];
if (ImGui::Selectable(projection_type_strings[i], is_selected)) {
current_projection_type = projection_type_strings[i];
camera.SetProjectionType((SceneCamera::ProjectionType)i);
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective) {
float fov = camera.GetVerticalFov();
if (ImGui::DragFloat("Fov", &fov, 0.1f))
camera.SetVerticalFov(fov);
float near_clip = camera.GetPerspectiveNearClip();
if (ImGui::DragFloat("Near clip", &near_clip, 0.1f))
camera.SetPerspectiveNearClip(near_clip);
float far_clip = camera.GetPerspectiveFarClip();
if (ImGui::DragFloat("Far clip", &far_clip, 0.1f))
camera.SetPerspectiveFarClip(far_clip);
}
else if (camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic) {
ImGui::Checkbox("Has fixed aspect ratio", &fixed_aspect_ratio);
float ortho_size = camera.GetOrthographicSize();
if (ImGui::DragFloat("Orthographic size", &ortho_size, 0.1f))
camera.SetOrthographicSize(ortho_size);
float near_clip = camera.GetOrthographicNearClip();
if (ImGui::DragFloat("Near clip", &near_clip, 0.1f))
camera.SetOrthographicNearClip(near_clip);
float far_clip = camera.GetOrthographicFarClip();
if (ImGui::DragFloat("Far clip", &far_clip, 0.1f))
camera.SetOrthographicFarClip(far_clip);
}
};
};
struct NativeScriptComponent
{
NativeScriptableEntity* instance = nullptr;
NativeScriptableEntity* (*InstanciateScript)();
void (*DestroyInstanceScript)(NativeScriptComponent*);
template <typename T>
void Bind()
{
InstanciateScript = []() { return static_cast<NativeScriptableEntity*>(new T()); };
DestroyInstanceScript = [](NativeScriptComponent* nsc)
{
(delete nsc->instance);
nsc->instance = nullptr;
};
}
};
}
#endif // COMPONENTS_HPP

View File

@@ -0,0 +1,64 @@
#ifndef ENTITY_HPP
#define ENTITY_HPP
#include "open_engine/core.hpp"
#include "open_engine/scene/scene.hpp"
#include <entt/entt.hpp>
#include <utility>
namespace OpenEngine {
class Entity
{
public:
Entity() = default;
Entity(entt::entity handle, Scene* scene);
Entity(const Entity& other) = default;
template<typename T, typename ... Args>
T& AddComponents(Args&&... args)
{
OE_ASSERT(!HasComponent<T>(), "Entity already has component.");
return scene->registry.emplace<T>(handle, std::forward<Args>(args)...);
};
template<typename T, typename ... Args>
T& GetComponents(Args&&... args)
{
OE_ASSERT(HasComponent<T>(), "Entity doesn't have component.");
return scene->registry.get<T>(handle);
};
template<typename T>
void RemoveComponents()
{
OE_ASSERT(HasComponent<T>(), "Entity doesn't have component.");
scene->registry.remove<T>(handle);
};
template<typename T>
bool HasComponent()
{
return scene->registry.all_of<T>(handle);
};
operator bool() const { return handle != entt::null; };
operator uint32_t() const { return (uint32_t)handle; };
bool operator ==(const Entity& other) const {
return handle == other.handle && scene == other.scene;
};
bool operator !=(const Entity& other) const {
return !operator==(other);
};
private:
entt::entity handle { entt::null };
OpenEngine::Scene* scene = nullptr;
};
}
#endif // ENTITY_HPP

View File

@@ -0,0 +1,27 @@
#ifndef NATIVE_SCRIPTABLE_ENTITY_HPP
#define NATIVE_SCRIPTABLE_ENTITY_HPP
#include "open_engine/scene/entity.hpp"
namespace OpenEngine {
class NativeScriptableEntity
{
public:
virtual ~NativeScriptableEntity() = default;
template <typename T>
T& GetComponent() { return entity.GetComponents<T>(); };
protected:
virtual void OnCreate() {};
virtual void OnUpdate() {};
virtual void OnDestroy() {};
private:
Entity entity;
friend class Scene;
};
}
#endif // NATIVE_SCRIPTABLE_ENTITY_HPP

View File

@@ -0,0 +1,33 @@
#ifndef SCENE_HPP
#define SCENE_HPP
#include <cstdint>
#include <entt/entt.hpp>
namespace OpenEngine {
class Entity;
class Scene
{
public:
Scene() {};
~Scene() = default;
Entity CreateEntity(const std::string& name = std::string());
void OnUpdate();
void OnViewportResize(uint32_t width, uint32_t height);
entt::registry& GetRegistry() { return registry; };
private:
entt::registry registry;
uint32_t viewport_width = 0, viewport_height = 0;
friend class Entity;
};
}
#endif // SCENE_HPP

View File

@@ -0,0 +1,74 @@
#ifndef SCENE_CAMERA_HPP
#define SCENE_CAMERA_HPP
#include "open_engine/renderer/camera.hpp"
#include <cstdint>
namespace OpenEngine {
class SceneCamera : public Camera
{
public:
enum class ProjectionType { Perspective = 0, Orthographic = 1 };
public:
SceneCamera();
virtual ~SceneCamera() = default;
void SetViewportSize(uint32_t width, uint32_t height);
ProjectionType GetProjectionType() { return projection_type; };
void SetProjectionType(ProjectionType type) {
projection_type = type;
RecalculateProjection();
};
void SetOrthographic(float size, float near_clip, float far_clip);
void SetPerspective(float fov, float near_clip, float far_clip);
float GetOrthographicSize() const { return orthographic_size; }
void SetOrthographicSize(float size) {
orthographic_size = size;
RecalculateProjection();
};
float GetOrthographicNearClip() const { return orthographic_near; };
void SetOrthographicNearClip(float near) {
orthographic_near = near;
RecalculateProjection();
};
float GetOrthographicFarClip() const { return orthographic_far; };
void SetOrthographicFarClip(float far) {
orthographic_far = far;
RecalculateProjection();
};
float GetVerticalFov() const { return fov; }
void SetVerticalFov(float fov_value) {
fov = fov_value;
RecalculateProjection();
};
float GetPerspectiveNearClip() const { return perspective_near; };
void SetPerspectiveNearClip(float near) {
perspective_near = near;
RecalculateProjection();
};
float GetPerspectiveFarClip() const { return perspective_far; };
void SetPerspectiveFarClip(float far) {
perspective_far = far;
RecalculateProjection();
};
private:
void RecalculateProjection();
private:
ProjectionType projection_type = ProjectionType::Orthographic;
float orthographic_size = 10.0f;
float orthographic_near = -1.0f, orthographic_far = 1.0f;
float fov = 45.0f;
float perspective_near = 0.01f, perspective_far = 1000.0f;
float aspect_ratio = 0.0f;
};
}
#endif // SCENE_CAMERA_HPP