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

77
editor/imgui.ini Normal file
View File

@@ -0,0 +1,77 @@
[Window][Debug##Default]
Pos=60,60
Size=166,153
Collapsed=0
[Window][Dear ImGui Demo]
Pos=899,10
Size=358,368
Collapsed=0
[Window][Dear ImGui Style Editor]
Pos=136,23
Size=353,682
Collapsed=0
[Window][Example: Log]
Pos=431,613
Size=409,223
Collapsed=0
DockId=0x00000006,0
[Window][My First Tool]
Pos=181,56
Size=388,464
Collapsed=0
[Window][DockSpace Demo]
Size=1259,688
Collapsed=0
[Window][Dear ImGui Debug Log]
Pos=1349,371
Size=644,567
Collapsed=0
[Window][Example: Console]
Pos=0,19
Size=519,669
Collapsed=0
DockId=0x00000003,0
[Window][Example: Assets Browser]
Pos=842,613
Size=326,223
Collapsed=0
DockId=0x00000009,0
[Window][Example: Property editor]
Pos=0,19
Size=429,817
Collapsed=0
DockId=0x00000005,0
[Window][Example: Property editor/##tree_37EC733C]
IsChild=1
Size=300,782
[Table][0xB6880529,2]
RefScale=13
Column 0 Sort=0v
[Table][0x2048C668,2]
RefScale=13
Column 0 Width=4
Column 1 Weight=2.0000
[Docking][Data]
DockSpace ID=0xC0DFADC4 Pos=0,19 Size=1259,669 Split=X Selected=0x5E5F7166
DockNode ID=0x00000005 Parent=0xC0DFADC4 SizeRef=429,817 Selected=0x256ED220
DockNode ID=0x0000000A Parent=0xC0DFADC4 SizeRef=1143,817 Split=X
DockNode ID=0x00000003 Parent=0x0000000A SizeRef=519,669 Selected=0x1BCA3180
DockNode ID=0x00000004 Parent=0x0000000A SizeRef=751,669 Split=Y
DockNode ID=0x00000007 Parent=0x00000004 SizeRef=860,592 CentralNode=1
DockNode ID=0x00000008 Parent=0x00000004 SizeRef=860,223 Split=X Selected=0x38CCB771
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=649,223 Selected=0x38CCB771
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=517,223 Selected=0xD2C213DD

View File

@@ -1,209 +1,292 @@
#ifndef EDITOR_HPP #ifndef EDITOR_HPP
#define EDITOR_HPP #define EDITOR_HPP
#include "open_engine/input/input_system.hpp" #include "open_engine/ref_scope.hpp"
#include <view_layer.hpp> #include "panels/scene_hierarchy.hpp"
#include <open_engine.hpp> #include <open_engine.hpp>
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/matrix.hpp> #include <glm/matrix.hpp>
#include <glm/fwd.hpp> #include <entt/entt.hpp>
#include <imgui.h>
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cstdint>
#include <imgui.h>
class EditorLayer : public OpenEngine::Layer namespace OpenEngine {
{
public: class CameraController : public NativeScriptableEntity
EditorLayer(OpenEngine::Ref<ViewLayer>& view_layer) {
: OpenEngine::Layer("editor_layer"), public:
view(view_layer) void OnCreate()
{
};
void OnUpdate()
{
auto delta = Time::DeltaTime();
auto& transform = GetComponent<TransformComponent>();
if (Input::IsKeyPressed(KeyCode::Up))
transform.transform[3][1] += 5.0 * delta;
if (Input::IsKeyPressed(KeyCode::Down))
transform.transform[3][1] -= 5.0 * delta;
if (Input::IsKeyPressed(KeyCode::Right))
transform.transform[3][0] += 5.0 * delta;
if (Input::IsKeyPressed(KeyCode::Left))
transform.transform[3][0] -= 5.0 * delta;
};
void OnDestroy()
{
};
};
class EditorLayer : public Layer
{
public:
EditorLayer()
: Layer("editor_layer")/*,
camera((float)Application::Get().GetWindow().GetWidth() /
Application::Get().GetWindow().GetHeight(), 1.0f)
*/
{ {
} }
~EditorLayer() {}; ~EditorLayer() {};
void OnAttach() override entt::registry registry;
{
OE_PROFILE_FUNCTION();
}
void OnDetach() override void OnAttach() override
{
}
void OnUpdate() override
{
OpenEngine::Renderer2D::ResetStats();
{ {
OE_PROFILE_FUNCTION(); OE_PROFILE_FUNCTION();
view->GetCamera().OnUpdate(); FramebufferSpecification specs;
specs.width = 1280;
specs.height = 720;
framebuffer = FrameBuffer::Create(specs);
scene = CreateRef<Scene>();
sq_entity = scene->CreateEntity("square");
sq_entity.AddComponents<TransformComponent>();
sq_entity.AddComponents<SpriteRendererComponent>(glm::vec4(1.0f, 0.0f, 0.0f, 1.0f));
camera_bis = scene->CreateEntity("Main camera");
camera_bis.AddComponents<TransformComponent>();
camera_bis.AddComponents<CameraComponent>();
camera_bis.AddComponents<NativeScriptComponent>().Bind<CameraController>();
scene_hierarchy.SetContext(scene);
} }
OpenEngine::Renderer2D::EndScene(); void OnDetach() override
}
void OnEvent(OpenEngine::Event& event) override
{
OE_PROFILE_FUNCTION();
{ {
OE_PROFILE_SCOPE("Camera OnEvent");
view->GetCamera().OnEvent(event);
}
}
float remap(float value, float minInput, float maxInput, float minOutput, float maxOutput) {
// 1. Normalize the input to a 0.0 - 1.0 range
float t = (value - minInput) / (maxInput - minInput);
// 2. Use glm::mix to interpolate between the output range
return glm::mix(minOutput, maxOutput, t);
}
glm::vec3 ScreenToWorld(
float screenX,
float screenY,
float screenZ, // depth value (0.0 = near plane, 1.0 = far plane)
const glm::mat4& view,
const glm::mat4& projection,
int viewportWidth,
int viewportHeight)
{
// 1. Convert screen coordinates to normalized device coordinates (NDC)
// Screen space: origin at top-left, Y points down
// NDC space: origin at center, range [-1, 1] for x and y
float x = (2.0f * screenX) / viewportWidth - 1.0f;
float y = 1.0f - (2.0f * screenY) / viewportHeight; // Flip Y
float z = 2.0f * screenZ - 1.0f; // [0,1] -> [-1,1]
glm::vec4 clipCoords(x, y, z, 1.0f);
// 2. Transform from clip space to view space
glm::mat4 invProjection = glm::inverse(projection);
glm::vec4 viewCoords = invProjection * clipCoords;
// 3. Transform from view space to world space
glm::mat4 invView = glm::inverse(view);
glm::vec4 worldCoords = invView * viewCoords;
// 4. Perspective divide
if (worldCoords.w != 0.0f) {
worldCoords /= worldCoords.w;
} }
return glm::vec3(worldCoords); void OnUpdate() override
}
void OnImGuiRender() override
{
OE_PROFILE_FUNCTION();
OpenEngine::Ref<OpenEngine::FrameBuffer> framebuffer = view->GetFramebuffer();
ImGui::DockSpaceOverViewport();
ImGui::Begin("Square settings");
//ImGui::SliderFloat("Angle", &angle, -360, 360);
//ImGui::ColorPicker4("Rectangle color", &rectangle_color[0]);
for (auto& result : profiling_results)
{ {
char label[50]; FramebufferSpecification spec = framebuffer->GetSpecification();
strcpy(label, "%.3fms "); if (viewport_size.x > 0.0f && viewport_size.y > 0.0f &&
strcat(label, result.name); (spec.width != viewport_size.x || spec.height != viewport_size.y))
ImGui::Text(label, result.duration); {
framebuffer->Resize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
//camera.OnResize(viewport_size.x, viewport_size.y);
}
{
OE_PROFILE_SCOPE("Setting up Rendering");
//camera.OnUpdate();
framebuffer->Bind();
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
}
Renderer2D::ResetStats();
RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
RenderCommand::Clear();
//Renderer2D::BeginScene(camera.GetCamera());
/*
for (float y = -5.0f; y < 5.0f; y += 0.5f) {
for (float x = -5.0f; x < 5.0f; x += 0.5f) {
glm::vec4 gradient_color = {(x + 5.0f) / 10.0f, 0.3f, (y + 5.0f) / 10.0f, 1.0f};
Renderer2D::DrawQuad({{x, y, 0.0f}, glm::vec3(0.45f, 0.45f, 0.0f)}, gradient_color);
}
}
Transform tr5 = {
glm::vec3(world_pos_cursor.x, world_pos_cursor.y, 0.9f),
glm::vec3(0.1f, 0.1f, 0.0f), 0.0f};
Renderer2D::DrawQuad(tr5, {1, 1, 1, 1});
*/
scene->OnUpdate();
//Renderer2D::EndScene();
framebuffer->Unbind();
} }
profiling_results.clear(); void OnEvent(Event& event) override
{
OE_PROFILE_FUNCTION();
//camera.OnEvent(event);
}
float remap(float value, float minInput, float maxInput, float minOutput, float maxOutput) {
// 1. Normalize the input to a 0.0 - 1.0 range
float t = (value - minInput) / (maxInput - minInput);
// 2. Use glm::mix to interpolate between the output range
return glm::mix(minOutput, maxOutput, t);
}
glm::vec3 ScreenToWorld(
float screenX,
float screenY,
float screenZ, // depth value (0.0 = near plane, 1.0 = far plane)
const glm::mat4& view,
const glm::mat4& projection,
int viewportWidth,
int viewportHeight)
{
// 1. Convert screen coordinates to normalized device coordinates (NDC)
// Screen space: origin at top-left, Y points down
// NDC space: origin at center, range [-1, 1] for x and y
float x = (2.0f * screenX) / viewportWidth - 1.0f;
float y = 1.0f - (2.0f * screenY) / viewportHeight; // Flip Y
float z = 2.0f * screenZ - 1.0f; // [0,1] -> [-1,1]
glm::vec4 clipCoords(x, y, z, 1.0f);
// 2. Transform from clip space to view space
glm::mat4 invProjection = glm::inverse(projection);
glm::vec4 viewCoords = invProjection * clipCoords;
// 3. Transform from view space to world space
glm::mat4 invView = glm::inverse(view);
glm::vec4 worldCoords = invView * viewCoords;
// 4. Perspective divide
if (worldCoords.w != 0.0f) {
worldCoords /= worldCoords.w;
}
return glm::vec3(worldCoords);
};
void DrawViewport()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 });
ImGui::Begin("Viewport");
bool focused = ImGui::IsWindowFocused();
bool hovered = ImGui::IsWindowHovered();
Application::Get().GetImGuiLayer()->SetBlockEvents(!focused || !hovered);
ImVec2 viewport_panel_size = ImGui::GetContentRegionAvail();
ImGui::End();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 });
ImGui::Begin("Viewport");
ImVec2 viewport_panel_size = ImGui::GetContentRegionAvail();
if (viewport_size != *((glm::vec2*)&viewport_panel_size)) {
framebuffer->Resize(viewport_panel_size.x, viewport_panel_size.y);
viewport_size = { viewport_panel_size.x, viewport_panel_size.y }; viewport_size = { viewport_panel_size.x, viewport_panel_size.y };
view->GetCamera().OnResize(viewport_panel_size.x, viewport_panel_size.y); ImVec2 imgui_cursor_position = ImGui::GetCursorScreenPos();
} auto pair_position = Input::GetMousePosition();
uint32_t texture_id = framebuffer->GetColorAttachmentRendererID(); glm::vec2 mouse_position = { pair_position.first, pair_position.second };
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) int max_x = viewport_size.x + imgui_cursor_position.x;
int max_y = viewport_size.y + imgui_cursor_position.y;
if (focused || hovered) {
float x = mouse_position.x - imgui_cursor_position.x;
float y = mouse_position.y - imgui_cursor_position.y;
/*
auto& cam = camera.GetCamera();
world_pos_cursor = ScreenToWorld(x, y, 0.0f,
cam.GetViewMatrix(),
cam.GetProjectionMatrix(),
viewport_size.x,
viewport_size.y);
*/
}
uint32_t texture_id = framebuffer->GetColorAttachmentRendererID();
ImGui::Image((void*)(uint64_t)texture_id, ImVec2{ viewport_size.x, viewport_size.y }, ImVec2{ 0, 1 }, ImVec2{ 1, 0 });
ImGui::End();
ImGui::PopStyleVar();
};
void DrawStats()
{ {
if (ImGui::BeginTabItem("Avocado")) auto stats = Renderer2D::GetStats();
{ static float time = 0;
ImVec2 imgui_cursor_position = ImGui::GetCursorScreenPos();
auto pair_position = OpenEngine::Input::GetMousePosition(); time += Time::DeltaTime();
glm::vec2 mouse_position = { pair_position.first, pair_position.second };
int max_x = viewport_size.x + imgui_cursor_position.x; if (time >= 1) {
int max_y = viewport_size.y + imgui_cursor_position.y; time = 0;
if ((mouse_position.x <= max_x && mouse_position.x >= imgui_cursor_position.x)
&& (mouse_position.y <= max_y && mouse_position.y >= imgui_cursor_position.y)) {
float x = mouse_position.x - imgui_cursor_position.x;
float y = mouse_position.y - imgui_cursor_position.y;
auto& camera = view->GetCamera().GetCamera();
auto world_coords = ScreenToWorld(x, y, 0.0f,
camera.GetViewMatrix(),
camera.GetProjectionMatrix(),
viewport_size.x,
viewport_size.y);
view->SetCursorPos({ world_coords.x, world_coords.y });
}
ImGui::Image((void*)texture_id, ImVec2{ viewport_size.x, viewport_size.y }, ImVec2{ 0, 1 }, ImVec2{ 1, 0 });
ImGui::EndTabItem();
} }
if (ImGui::BeginTabItem("Broccoli"))
{
ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Cucumber"))
{
ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::End();
ImGui::PopStyleVar();
auto stats = OpenEngine::Renderer2D::GetStats(); ImGui::Begin("Statistics");
static float time = 0; ImGui::Text("FPS: %0.0f", 1 / Time::DeltaTime());
ImGui::Text("Renderer2D:");
ImGui::Text("\t\tDraw calls: %d", stats.draw_calls);
ImGui::Text("\t\tQuad count: %d", stats.quad_count);
ImGui::Text("\t\tVertices count: %d", stats.GetToralVertexCount());
ImGui::Text("\t\tIndices count: %d", stats.GetToralIndexCount());
time += OpenEngine::Time::DeltaTime(); /*
for (auto& result : profiling_results)
{
char label[50];
strcpy(label, "%.3fms ");
strcat(label, result.name);
ImGui::Text(label, result.duration);
}
if (time >= 1) { profiling_results.clear();
time = 0; */
}
ImGui::Begin("Statistics"); ImGui::End();
ImGui::Text("FPS: %0.0f", 1 / OpenEngine::Time::DeltaTime()); };
ImGui::Text("Renderer2D:");
ImGui::Text("\t\tDraw calls: %d", stats.draw_calls);
ImGui::Text("\t\tQuad count: %d", stats.quad_count);
ImGui::Text("\t\tVertices count: %d", stats.GetToralVertexCount());
ImGui::Text("\t\tIndices count: %d", stats.GetToralIndexCount());
ImGui::ShowDemoWindow();
ImGui::End();
}
private: void OnImGuiRender() override
std::vector<OpenEngine::Time::ProfilingResult> profiling_results; {
OE_PROFILE_FUNCTION();
glm::vec2 viewport_size = { 0.0f, 0.0f }; ImGui::DockSpaceOverViewport();
OpenEngine::Ref<ViewLayer> view; DrawStats();
}; scene_hierarchy.OnImGuiRender();
DrawViewport();
ImGui::ShowDemoWindow();
};
private:
std::vector<Time::ProfilingResult> profiling_results;
glm::vec2 world_pos_cursor = { 0.0f, 0.0f };
glm::vec2 viewport_size = { 0.0f, 0.0f };
Ref<OpenEngine::FrameBuffer> framebuffer;
SceneHierarchy scene_hierarchy;
//OrthographicCameraController camera;
Entity camera_bis;
Ref<Scene> scene;
Entity sq_entity;
};
}
class EditorApp : public OpenEngine::Application class EditorApp : public OpenEngine::Application
{ {

View File

@@ -31,7 +31,7 @@ class LevelEditor : public ViewLayer
GetCamera().OnUpdate(); GetCamera().OnUpdate();
GetFramebuffer()->Bind(); GetFramebuffer()->Bind();
} }
OpenEngine::RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f}); OpenEngine::RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
OpenEngine::RenderCommand::Clear(); OpenEngine::RenderCommand::Clear();
@@ -47,7 +47,6 @@ class LevelEditor : public ViewLayer
} }
auto& cursor = GetCursorPos(); auto& cursor = GetCursorPos();
OE_TRACE("world coordinates: {} {}", cursor.x, cursor.y);
OpenEngine::Transform tr5 = {glm::vec3(cursor.x, cursor.y, 0.9f), glm::vec3(0.1f, 0.1f, 0.0f), 0.0f}; OpenEngine::Transform tr5 = {glm::vec3(cursor.x, cursor.y, 0.9f), glm::vec3(0.1f, 0.1f, 0.0f), 0.0f};
OpenEngine::Renderer2D::DrawQuad(tr5, {1, 1, 1, 1}); OpenEngine::Renderer2D::DrawQuad(tr5, {1, 1, 1, 1});
@@ -58,14 +57,8 @@ class LevelEditor : public ViewLayer
void OnEvent(OpenEngine::Event& event) override void OnEvent(OpenEngine::Event& event) override
{ {
auto& cursor = GetCursorPos(); OE_PROFILE_FUNCTION();
OE_TRACE("world coordinates: {} {}", cursor.x, cursor.y); GetCamera().OnEvent(event);
OpenEngine::Transform tr5 = {glm::vec3(cursor.x, cursor.y, 0.9f), glm::vec3(1.0f, 1.0f, 0.0f), 0.0f};
OpenEngine::Renderer2D::DrawQuad(tr5, {1, 1, 1, 1});
OpenEngine::Renderer2D::EndScene();
GetFramebuffer()->Unbind();
}; };
void OnDetach() override {}; void OnDetach() override {};

View File

@@ -0,0 +1,40 @@
#ifndef SCENE_HIERARCHY_HPP
#define SCENE_HIERARCHY_HPP
#include "imgui.h"
#include <open_engine.hpp>
namespace OpenEngine {
class SceneHierarchy
{
public:
SceneHierarchy() = default;
SceneHierarchy(const Ref<Scene>& scene);
void SetContext(const Ref<Scene>& scene);
void OnImGuiRender();
private:
void DrawEntityNode(Entity& entity);
void DrawComponents(Entity& entity);
template <typename T>
void DrawComponentDrawer(Entity& entity, const char* header)
{
if (entity.HasComponent<T>())
if (ImGui::TreeNodeEx((void*)typeid(T).hash_code(), ImGuiTreeNodeFlags_DefaultOpen, "%s", header)) {
entity.GetComponents<T>().OnImGuiRender(entity);
ImGui::TreePop();
ImGui::Separator();
}
}
private:
Ref<Scene> scene;
Entity selected_context, renamed_entity;
double last_selected_time = 10.0;
};
}
#endif // SCENE_HIERARCHY_HPP

View File

@@ -9,18 +9,14 @@
#include <overlay.hpp> #include <overlay.hpp>
#include <modding.hpp> #include <modding.hpp>
#include <memory>
EditorApp::EditorApp() EditorApp::EditorApp()
: Application("OpenEngine Editor") : Application("OpenEngine Editor")
{ {
OpenEngine::Ref<OpenEngine::Layer> modding_layer = std::make_shared<Modding>(); OpenEngine::Ref<OpenEngine::Layer> modding_layer = OpenEngine::CreateRef<Modding>();
OpenEngine::Ref<ViewLayer> view = OpenEngine::CreateRef<LevelEditor>(); OpenEngine::Ref<OpenEngine::Layer> editor_layer = OpenEngine::CreateRef<OpenEngine::EditorLayer>();
OpenEngine::Ref<OpenEngine::Layer> initial_layer = std::make_shared<EditorLayer>(view); OpenEngine::Ref<OpenEngine::Layer> control_layer = OpenEngine::CreateRef<ControlLayer>(editor_layer);
OpenEngine::Ref<OpenEngine::Layer> control_layer = std::make_shared<ControlLayer>(initial_layer);
QueueLayerPush(view); QueueLayerPush(editor_layer);
QueueLayerPush(initial_layer);
QueueLayerPush(control_layer); QueueLayerPush(control_layer);
QueueLayerPush(modding_layer); QueueLayerPush(modding_layer);
} }

View File

@@ -0,0 +1,150 @@
#include "open_engine/scene/components.hpp"
#include <cstdint>
#include <cstring>
#include <panels/scene_hierarchy.hpp>
#include <imgui.h>
namespace OpenEngine {
SceneHierarchy::SceneHierarchy(const Ref<Scene>& scene)
: scene(scene)
{
}
void SceneHierarchy::SetContext(const Ref<Scene>& context)
{
scene = context;
}
void SceneHierarchy::OnImGuiRender()
{
ImGui::Begin("Scene");
for (auto entity_entt : scene->GetRegistry().view<TagComponent>()) {
Entity entity{ entity_entt, scene.get() };
DrawEntityNode(entity);
}
if ((ImGui::IsMouseDown(0) && ImGui::IsWindowHovered())
|| (ImGui::IsKeyDown(ImGuiKey_Escape) && ImGui::IsWindowHovered()))
{
selected_context = {};
renamed_entity = {};
}
if (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight | ImGuiPopupFlags_NoOpenOverItems))
{
if (ImGui::MenuItem("Create Empty Entity"))
{
scene->CreateEntity("Empty entity");
}
ImGui::EndPopup();
}
ImGui::End();
ImGui::Begin("Properties");
if (selected_context) {
DrawComponents(selected_context);
if (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight | ImGuiPopupFlags_NoOpenOverItems))
{
if (ImGui::MenuItem("Add transform"))
{
selected_context.AddComponents<TransformComponent>();
}
if (ImGui::MenuItem("Add Sprite"))
{
selected_context.AddComponents<SpriteRendererComponent>();
}
if (ImGui::MenuItem("Add camera"))
{
selected_context.AddComponents<CameraComponent>();
}
ImGui::EndPopup();
}
}
ImGui::End();
}
void SceneHierarchy::DrawEntityNode(Entity& entity)
{
auto& tag = entity.GetComponents<TagComponent>().tag;
if (renamed_entity == entity && selected_context == entity) {
char buffer[255];
std::memset(buffer, 0, sizeof(buffer));
std::strncpy(buffer, tag.c_str(), sizeof(buffer));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
ImGui::SetKeyboardFocusHere();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputText("##tagEditor", buffer, sizeof(buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)
|| (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0))) {
tag = buffer;
renamed_entity = {};
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
renamed_entity = {};
ImGui::PopStyleVar();
} else {
ImGuiTreeNodeFlags flags = ((selected_context == entity) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow;
flags |= ImGuiTreeNodeFlags_SpanAvailWidth;
bool opened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, "%s", tag.c_str());
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
// FocusViewportOnEntity(entity); // future implementation
renamed_entity = {};
} else if (ImGui::IsItemClicked()) {
double current_time = ImGui::GetTime();
double double_click_time = ImGui::GetIO().MouseDoubleClickTime; // Usually ~0.3s
if (selected_context == entity) {
renamed_entity = entity;
if (current_time - last_selected_time > double_click_time)
{
renamed_entity = entity;
}
} else {
// First time selecting
selected_context = entity;
last_selected_time = current_time;
}
}
if (opened)
ImGui::TreePop();
}
}
void SceneHierarchy::DrawComponents(Entity& entity)
{
if (entity.HasComponent<TagComponent>())
entity.GetComponents<TagComponent>().OnImGuiRender(entity);
DrawComponentDrawer<TransformComponent>(entity, "Transform");
DrawComponentDrawer<SpriteRendererComponent>(entity, "Sprite");
DrawComponentDrawer<CameraComponent>(entity, "Camera");
}
}
/*
if (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight | ImGuiPopupFlags_NoOpenOverItems))
{
if (ImGui::MenuItem("Create Empty Entity"))
{
// m_Context->CreateEntity("Empty Entity");
}
ImGui::EndPopup();
}
*/

59
imgui.ini Normal file
View File

@@ -0,0 +1,59 @@
[Window][WindowOverViewport_11111111]
Pos=0,0
Size=1272,1386
Collapsed=0
[Window][Statistics]
Pos=0,0
Size=404,149
Collapsed=0
DockId=0x00000001,0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Square settings]
Pos=1037,307
Size=235,1079
Collapsed=0
DockId=0x00000008,0
[Window][Viewport]
Pos=406,0
Size=629,1386
Collapsed=0
DockId=0x00000006,0
[Window][Dear ImGui Demo]
Pos=1037,0
Size=235,1386
Collapsed=0
DockId=0x00000007,0
[Window][Scene]
Pos=0,151
Size=404,264
Collapsed=0
DockId=0x00000009,0
[Window][Properties]
Pos=0,417
Size=404,969
Collapsed=0
DockId=0x0000000A,0
[Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,0 Size=1272,1386 Split=X
DockNode ID=0x00000003 Parent=0x08BD597D SizeRef=1035,1386 Split=X
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=404,1386 Split=Y Selected=0x553E127E
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=274,149 Selected=0x553E127E
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=274,1235 Split=Y Selected=0xE601B12F
DockNode ID=0x00000009 Parent=0x00000002 SizeRef=498,264 Selected=0xE601B12F
DockNode ID=0x0000000A Parent=0x00000002 SizeRef=498,969 Selected=0x8C72BEA8
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=629,1386 CentralNode=1 Selected=0xC450F867
DockNode ID=0x00000004 Parent=0x08BD597D SizeRef=235,1386 Split=Y Selected=0x5E5F7166
DockNode ID=0x00000007 Parent=0x00000004 SizeRef=235,305 Selected=0x5E5F7166
DockNode ID=0x00000008 Parent=0x00000004 SizeRef=235,1079 Selected=0xA5FF3A7A

24
licenses/entt.md Normal file
View File

@@ -0,0 +1,24 @@
This software uses the EnTT library.
The EnTT library is used under the MIT License, see bellow.
The MIT License (MIT)
Copyright (c) 2017-2026 Michele Caini, author of EnTT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copy of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copy or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

20
licenses/fmt.md Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

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

View File

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

View File

@@ -14,6 +14,7 @@
#define BIT(x) (1 << x) #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 #endif // CORE_HPP

View File

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

View File

@@ -1,5 +1,5 @@
#ifndef CAMERA_HPP #ifndef ORTHOGRAPHIC_CAMERA_HPP
#define CAMERA_HPP #define ORTHOGRAPHIC_CAMERA_HPP
#include <glm/fwd.hpp> #include <glm/fwd.hpp>
#include <glm/glm.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 <iostream>
#include <sstream> #include <sstream>
#include <cstdint>
#include <memory> #include <memory>
#include <array> #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 #ifndef RENDERER2D_HPP
#define RENDERER2D_HPP #define RENDERER2D_HPP
#include "open_engine/orthographic_camera.hpp"
#include "open_engine/renderer/subtexture2d.hpp" #include "open_engine/renderer/subtexture2d.hpp"
#include "open_engine/orthographic_camera.hpp"
#include "open_engine/renderer/texture.hpp" #include "open_engine/renderer/texture.hpp"
#include "open_engine/renderer/camera.hpp"
#include "open_engine/ref_scope.hpp" #include "open_engine/ref_scope.hpp"
#include <glm/fwd.hpp> #include <glm/fwd.hpp>
@@ -32,6 +33,7 @@ namespace OpenEngine {
static void Shutdown(); static void Shutdown();
static void BeginScene(const OrthographicCamera& camera); static void BeginScene(const OrthographicCamera& camera);
static void BeginScene(const Camera& camera, const glm::mat4& transform);
static void EndScene(); static void EndScene();
static void Flush(); 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<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 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 void ResetStats();
static const Statistics& GetStats(); 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

View File

@@ -1,14 +1,14 @@
#include "imgui.h"
#include "instrumentor.hpp"
#include <pch.hpp> #include <pch.hpp>
#include <imgui/imgui_layer.hpp> #include <imgui/imgui_layer.hpp>
#include <opengl/imgui_opengl.h> #include <opengl/imgui_opengl.h>
#include <opengl/imgui_glfw.h> #include <opengl/imgui_glfw.h>
#include <instrumentor.hpp>
#include <application.hpp> #include <application.hpp>
#include <layer.hpp> #include <layer.hpp>
#include "imgui.h"
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@@ -340,10 +340,10 @@ namespace OpenEngine {
void ImGuiLayer::OnEvent(Event& event) void ImGuiLayer::OnEvent(Event& event)
{ {
/* if (block_events) {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
event.handled |= event.IsInCategory(EventCategoryMouse) & io.WantCaptureMouse; event.handled |= event.IsInCategory(EventCategoryMouse) & io.WantCaptureMouse;
event.handled |= event.IsInCategory(EventCategoryKeyboard) & io.WantCaptureKeyboard; event.handled |= event.IsInCategory(EventCategoryKeyboard) & io.WantCaptureKeyboard;
*/ }
} }
} }

View File

@@ -1,3 +1,4 @@
#include "logging.hpp"
#include <pch.hpp> #include <pch.hpp>
#include <core.hpp> #include <core.hpp>
@@ -6,6 +7,7 @@
#include <glad/glad.h> #include <glad/glad.h>
namespace OpenEngine { namespace OpenEngine {
static const uint32_t max_framebuffer_size = 8192;
OpenGLFramebuffer::OpenGLFramebuffer(const FramebufferSpecification& spec) OpenGLFramebuffer::OpenGLFramebuffer(const FramebufferSpecification& spec)
: specs(spec) : specs(spec)
{ {
@@ -61,6 +63,10 @@ namespace OpenEngine {
void OpenGLFramebuffer::Resize(uint32_t width, uint32_t height) void OpenGLFramebuffer::Resize(uint32_t width, uint32_t height)
{ {
if (width == 0 || height == 0 || width > max_framebuffer_size || height > max_framebuffer_size) {
OE_CORE_WARN("Attempted to resize framebuffer to {} {}", width, height);
return;
}
specs.width = width; specs.width = width;
specs.height = height; specs.height = height;

View File

@@ -0,0 +1,7 @@
#include <pch.hpp>
#include <open_engine/renderer/camera.hpp>
namespace OpenEngine {
}

View File

@@ -7,10 +7,11 @@
#include <renderer/buffer.hpp> #include <renderer/buffer.hpp>
#include <renderer/shader.hpp> #include <renderer/shader.hpp>
#include <cstdint> #include <glm/ext/quaternion_common.hpp>
#include <glm/fwd.hpp>
#include <glm/trigonometric.hpp>
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <glm/trigonometric.hpp>
#include <glm/fwd.hpp>
#include <cstdint>
namespace OpenEngine { namespace OpenEngine {
struct QuadVertex struct QuadVertex
@@ -135,6 +136,21 @@ namespace OpenEngine {
renderer_data.texture_slot_index = 1; renderer_data.texture_slot_index = 1;
} }
void Renderer2D::BeginScene(const Camera& camera, const glm::mat4& transform)
{
OE_PROFILE_FUNCTION();
glm::mat4 view_projection = camera.GetProjection() * glm::inverse(transform);
renderer_data.texture_shader->Bind();
renderer_data.texture_shader->SetMat4("u_ViewProjection", view_projection);
renderer_data.quad_index_count = 0;
renderer_data.quad_vertex_ptr = renderer_data.quad_vertex_base;
renderer_data.texture_slot_index = 1;
}
void Renderer2D::EndScene() void Renderer2D::EndScene()
{ {
OE_PROFILE_FUNCTION(); OE_PROFILE_FUNCTION();
@@ -196,17 +212,7 @@ namespace OpenEngine {
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f }) * glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
* glm::scale(glm::mat4(1.0f), transform_data.size); * glm::scale(glm::mat4(1.0f), transform_data.size);
for (size_t i = 0; i < quad_vertex_count; i++) { DrawQuad(transform, texture);
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
renderer_data.quad_vertex_ptr->color = color;
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
renderer_data.quad_vertex_ptr->tex_index = texture_index;
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
renderer_data.quad_vertex_ptr++;
}
renderer_data.quad_index_count += 6;
renderer_data.stats.quad_count++;
} }
void Renderer2D::DrawQuad(const Transform& transform_data, const Ref<Subtexture2D>& subtexture, float tiling_factor) void Renderer2D::DrawQuad(const Transform& transform_data, const Ref<Subtexture2D>& subtexture, float tiling_factor)
@@ -246,17 +252,7 @@ namespace OpenEngine {
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f }) * glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
* glm::scale(glm::mat4(1.0f), transform_data.size); * glm::scale(glm::mat4(1.0f), transform_data.size);
for (size_t i = 0; i < quad_vertex_count; i++) { DrawQuad(transform, subtexture);
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
renderer_data.quad_vertex_ptr->color = color;
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
renderer_data.quad_vertex_ptr->tex_index = texture_index;
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
renderer_data.quad_vertex_ptr++;
}
renderer_data.quad_index_count += 6;
renderer_data.stats.quad_count++;
} }
void Renderer2D::DrawQuad(const Transform& transform_data, const glm::vec4& color) void Renderer2D::DrawQuad(const Transform& transform_data, const glm::vec4& color)
@@ -277,6 +273,104 @@ namespace OpenEngine {
* glm::scale(glm::mat4(1.0f), transform_data.size); * glm::scale(glm::mat4(1.0f), transform_data.size);
DrawQuad(transform, color);
}
void Renderer2D::DrawQuad(const glm::mat4& transform, const Ref<Texture2D>& texture, float tiling_factor)
{
OE_PROFILE_FUNCTION();
constexpr size_t quad_vertex_count = 4;
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
FlushAndReset();
constexpr glm::vec4 color = glm::vec4(1.0f);
float texture_index = 0;
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
texture_index = (float)i;
break;
}
}
if (texture_index == 0) {
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
FlushAndReset();
texture_index = (float)renderer_data.texture_slot_index;
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
renderer_data.texture_slot_index++;
}
for (size_t i = 0; i < quad_vertex_count; i++) {
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
renderer_data.quad_vertex_ptr->color = color;
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
renderer_data.quad_vertex_ptr->tex_index = texture_index;
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
renderer_data.quad_vertex_ptr++;
}
renderer_data.quad_index_count += 6;
renderer_data.stats.quad_count++;
}
void Renderer2D::DrawQuad(const glm::mat4& transform, const Ref<Subtexture2D>& subtexture, float tiling_factor)
{
OE_PROFILE_FUNCTION();
constexpr size_t quad_vertex_count = 4;
const glm::vec2* texture_coords = subtexture->GetCoords();
const Ref<Texture2D>& texture = subtexture->GetTexture();
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
FlushAndReset();
constexpr glm::vec4 color = glm::vec4(1.0f);
float texture_index = 0;
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
texture_index = (float)i;
break;
}
}
if (texture_index == 0) {
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
FlushAndReset();
texture_index = (float)renderer_data.texture_slot_index;
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
renderer_data.texture_slot_index++;
}
for (size_t i = 0; i < quad_vertex_count; i++) {
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
renderer_data.quad_vertex_ptr->color = color;
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
renderer_data.quad_vertex_ptr->tex_index = texture_index;
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
renderer_data.quad_vertex_ptr++;
}
renderer_data.quad_index_count += 6;
renderer_data.stats.quad_count++;
}
void Renderer2D::DrawQuad(const glm::mat4& transform, const glm::vec4& color)
{
OE_PROFILE_FUNCTION();
constexpr size_t quad_vertex_count = 4;
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
FlushAndReset();
for (size_t i = 0; i < quad_vertex_count; i++) { for (size_t i = 0; i < quad_vertex_count; i++) {
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i]; renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
renderer_data.quad_vertex_ptr->color = color; renderer_data.quad_vertex_ptr->color = color;
@@ -290,6 +384,7 @@ namespace OpenEngine {
renderer_data.stats.quad_count++; renderer_data.stats.quad_count++;
} }
void Renderer2D::ResetStats() void Renderer2D::ResetStats()
{ {
memset(&renderer_data.stats, 0, sizeof(Statistics)); memset(&renderer_data.stats, 0, sizeof(Statistics));

View File

@@ -0,0 +1,60 @@
#include <glm/trigonometric.hpp>
#include <pch.hpp>
#include <scene/scene_camera.hpp>
#include <glm/ext/matrix_clip_space.hpp>
namespace OpenEngine {
SceneCamera::SceneCamera()
{
RecalculateProjection();
}
void SceneCamera::SetOrthographic(float size, float near_clip, float far_clip)
{
projection_type = ProjectionType::Orthographic;
orthographic_size = size;
orthographic_near = near_clip;
orthographic_far = far_clip;
RecalculateProjection();
}
void SceneCamera::SetPerspective(float fov_value, float near_clip, float far_clip)
{
projection_type = ProjectionType::Perspective;
fov = fov_value;
perspective_near = near_clip;
perspective_far = far_clip;
RecalculateProjection();
}
void SceneCamera::SetViewportSize(uint32_t width, uint32_t height)
{
aspect_ratio = (float)width / (float)height;
RecalculateProjection();
}
void SceneCamera::RecalculateProjection()
{
if (projection_type == ProjectionType::Orthographic) {
float ortho_left = -orthographic_size * aspect_ratio * 0.5;
float ortho_right = orthographic_size * aspect_ratio * 0.5;
float ortho_bottom = orthographic_size * -0.5;
float ortho_top = orthographic_size * 0.5;
projection = glm::ortho(
ortho_left, ortho_right,
ortho_bottom, ortho_top,
orthographic_near, orthographic_far);
}
else if (projection_type == ProjectionType::Perspective) {
projection = glm::perspective(
glm::radians(fov), aspect_ratio,
perspective_near, perspective_far);
}
}
}

View File

@@ -0,0 +1,10 @@
#include <pch.hpp>
#include <scene/entity.hpp>
namespace OpenEngine {
Entity::Entity(entt::entity handle, Scene* scene)
: handle(handle), scene(scene)
{
}
}

View File

@@ -0,0 +1 @@
#include <pch.hpp>

View File

@@ -0,0 +1,78 @@
#include <pch.hpp>
#include <scene/scene.hpp>
#include <renderer/renderer2d.hpp>
#include <scene/entity.hpp>
#include <scene/components.hpp>
namespace OpenEngine {
Entity Scene::CreateEntity(const std::string& name)
{
Entity entity = { registry.create(), this };
auto& tag = entity.AddComponents<TagComponent>();
tag.tag = name.empty() ? "Entity" : name;
return entity;
}
void Scene::OnUpdate()
{
{
OE_PROFILE_SCOPE("Updating Sripts");
registry.view<NativeScriptComponent>().each([=, this](auto entity, auto& nsc)
{
if (!nsc.instance) {
nsc.instance = nsc.InstanciateScript();
nsc.instance->entity = Entity{ entity, this };
nsc.instance->OnCreate();
}
nsc.instance->OnUpdate();
});
}
Camera* main_camera = nullptr;
glm::mat4* main_transform = nullptr;
{
auto camera_view = registry.view<CameraComponent, TransformComponent>();
for (auto entity : camera_view) {
auto [camera_component, transform] = camera_view.get<CameraComponent, TransformComponent>(entity);
if (camera_component.primary) {
main_camera = &camera_component.camera;
main_transform = &transform.transform;
break;
}
}
if (main_camera) {
Renderer2D::BeginScene(main_camera->GetProjection(), *main_transform);
auto view = registry.view<TransformComponent, SpriteRendererComponent>();
for (const auto& entity : view) {
auto [transform, sprite] = view.get<TransformComponent, SpriteRendererComponent>(entity);
Renderer2D::DrawQuad(transform.transform, sprite.color);
}
Renderer2D::EndScene();
}
}
}
void Scene::OnViewportResize(uint32_t width, uint32_t height)
{
viewport_width = width;
viewport_height = height;
auto view = registry.view<CameraComponent>();
for (auto entity : view) {
auto& camera_comp = view.get<CameraComponent>(entity);
if (!camera_comp.fixed_aspect_ratio)
camera_comp.camera.SetViewportSize(width, height);
}
}
}