ECS with entt
This commit is contained in:
77
editor/imgui.ini
Normal file
77
editor/imgui.ini
Normal 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
|
||||
|
||||
@@ -1,209 +1,292 @@
|
||||
#ifndef EDITOR_HPP
|
||||
#define EDITOR_HPP
|
||||
|
||||
#include "open_engine/input/input_system.hpp"
|
||||
#include <view_layer.hpp>
|
||||
#include "open_engine/ref_scope.hpp"
|
||||
#include "panels/scene_hierarchy.hpp"
|
||||
#include <open_engine.hpp>
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/matrix.hpp>
|
||||
#include <glm/fwd.hpp>
|
||||
#include <imgui.h>
|
||||
#include <entt/entt.hpp>
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <cstdint>
|
||||
#include <imgui.h>
|
||||
|
||||
class EditorLayer : public OpenEngine::Layer
|
||||
{
|
||||
public:
|
||||
EditorLayer(OpenEngine::Ref<ViewLayer>& view_layer)
|
||||
: OpenEngine::Layer("editor_layer"),
|
||||
view(view_layer)
|
||||
namespace OpenEngine {
|
||||
|
||||
class CameraController : public NativeScriptableEntity
|
||||
{
|
||||
public:
|
||||
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
|
||||
{
|
||||
OE_PROFILE_FUNCTION();
|
||||
}
|
||||
entt::registry registry;
|
||||
|
||||
void OnDetach() override
|
||||
{
|
||||
}
|
||||
|
||||
void OnUpdate() override
|
||||
{
|
||||
|
||||
OpenEngine::Renderer2D::ResetStats();
|
||||
void OnAttach() override
|
||||
{
|
||||
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 OnEvent(OpenEngine::Event& event) override
|
||||
{
|
||||
OE_PROFILE_FUNCTION();
|
||||
|
||||
void OnDetach() override
|
||||
{
|
||||
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 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)
|
||||
void OnUpdate() override
|
||||
{
|
||||
char label[50];
|
||||
strcpy(label, "%.3fms ");
|
||||
strcat(label, result.name);
|
||||
ImGui::Text(label, result.duration);
|
||||
FramebufferSpecification spec = framebuffer->GetSpecification();
|
||||
if (viewport_size.x > 0.0f && viewport_size.y > 0.0f &&
|
||||
(spec.width != viewport_size.x || spec.height != viewport_size.y))
|
||||
{
|
||||
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 };
|
||||
|
||||
view->GetCamera().OnResize(viewport_panel_size.x, viewport_panel_size.y);
|
||||
}
|
||||
uint32_t texture_id = framebuffer->GetColorAttachmentRendererID();
|
||||
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
|
||||
if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
|
||||
ImVec2 imgui_cursor_position = ImGui::GetCursorScreenPos();
|
||||
auto pair_position = Input::GetMousePosition();
|
||||
glm::vec2 mouse_position = { pair_position.first, pair_position.second };
|
||||
|
||||
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"))
|
||||
{
|
||||
ImVec2 imgui_cursor_position = ImGui::GetCursorScreenPos();
|
||||
auto stats = Renderer2D::GetStats();
|
||||
static float time = 0;
|
||||
|
||||
auto pair_position = OpenEngine::Input::GetMousePosition();
|
||||
glm::vec2 mouse_position = { pair_position.first, pair_position.second };
|
||||
time += Time::DeltaTime();
|
||||
|
||||
int max_x = viewport_size.x + imgui_cursor_position.x;
|
||||
int max_y = viewport_size.y + imgui_cursor_position.y;
|
||||
|
||||
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 (time >= 1) {
|
||||
time = 0;
|
||||
}
|
||||
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();
|
||||
static float time = 0;
|
||||
ImGui::Begin("Statistics");
|
||||
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) {
|
||||
time = 0;
|
||||
}
|
||||
profiling_results.clear();
|
||||
*/
|
||||
|
||||
ImGui::Begin("Statistics");
|
||||
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();
|
||||
}
|
||||
ImGui::End();
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<OpenEngine::Time::ProfilingResult> profiling_results;
|
||||
void OnImGuiRender() override
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ class LevelEditor : public ViewLayer
|
||||
GetCamera().OnUpdate();
|
||||
GetFramebuffer()->Bind();
|
||||
}
|
||||
|
||||
|
||||
OpenEngine::RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
|
||||
OpenEngine::RenderCommand::Clear();
|
||||
|
||||
@@ -47,7 +47,6 @@ class LevelEditor : public ViewLayer
|
||||
}
|
||||
|
||||
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::Renderer2D::DrawQuad(tr5, {1, 1, 1, 1});
|
||||
|
||||
@@ -58,14 +57,8 @@ class LevelEditor : public ViewLayer
|
||||
|
||||
void OnEvent(OpenEngine::Event& event) override
|
||||
{
|
||||
auto& cursor = GetCursorPos();
|
||||
OE_TRACE("world coordinates: {} {}", cursor.x, cursor.y);
|
||||
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();
|
||||
OE_PROFILE_FUNCTION();
|
||||
GetCamera().OnEvent(event);
|
||||
};
|
||||
|
||||
void OnDetach() override {};
|
||||
|
||||
40
editor/include/panels/scene_hierarchy.hpp
Normal file
40
editor/include/panels/scene_hierarchy.hpp
Normal 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
|
||||
@@ -9,18 +9,14 @@
|
||||
#include <overlay.hpp>
|
||||
#include <modding.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
EditorApp::EditorApp()
|
||||
: Application("OpenEngine Editor")
|
||||
{
|
||||
OpenEngine::Ref<OpenEngine::Layer> modding_layer = std::make_shared<Modding>();
|
||||
OpenEngine::Ref<ViewLayer> view = OpenEngine::CreateRef<LevelEditor>();
|
||||
OpenEngine::Ref<OpenEngine::Layer> initial_layer = std::make_shared<EditorLayer>(view);
|
||||
OpenEngine::Ref<OpenEngine::Layer> control_layer = std::make_shared<ControlLayer>(initial_layer);
|
||||
OpenEngine::Ref<OpenEngine::Layer> modding_layer = OpenEngine::CreateRef<Modding>();
|
||||
OpenEngine::Ref<OpenEngine::Layer> editor_layer = OpenEngine::CreateRef<OpenEngine::EditorLayer>();
|
||||
OpenEngine::Ref<OpenEngine::Layer> control_layer = OpenEngine::CreateRef<ControlLayer>(editor_layer);
|
||||
|
||||
QueueLayerPush(view);
|
||||
QueueLayerPush(initial_layer);
|
||||
QueueLayerPush(editor_layer);
|
||||
QueueLayerPush(control_layer);
|
||||
QueueLayerPush(modding_layer);
|
||||
}
|
||||
|
||||
150
editor/src/panels/scene_hierarchy.cpp
Normal file
150
editor/src/panels/scene_hierarchy.cpp
Normal 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();
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user