#ifndef EDITOR_HPP #define EDITOR_HPP #include "open_engine/input/input_system.hpp" #include #include #include #include #include #include #include #include #include class EditorLayer : public OpenEngine::Layer { public: EditorLayer(OpenEngine::Ref& view_layer) : OpenEngine::Layer("editor_layer"), view(view_layer) { } ~EditorLayer() {}; void OnAttach() override { OE_PROFILE_FUNCTION(); } void OnDetach() override { } void OnUpdate() override { OpenEngine::Renderer2D::ResetStats(); { OE_PROFILE_FUNCTION(); view->GetCamera().OnUpdate(); } OpenEngine::Renderer2D::EndScene(); } 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 OnImGuiRender() override { OE_PROFILE_FUNCTION(); OpenEngine::Ref 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]; strcpy(label, "%.3fms "); strcat(label, result.name); ImGui::Text(label, result.duration); } profiling_results.clear(); 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)) { if (ImGui::BeginTabItem("Avocado")) { ImVec2 imgui_cursor_position = ImGui::GetCursorScreenPos(); auto pair_position = OpenEngine::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 ((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(); static float time = 0; time += OpenEngine::Time::DeltaTime(); if (time >= 1) { time = 0; } 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(); } private: std::vector profiling_results; glm::vec2 viewport_size = { 0.0f, 0.0f }; OpenEngine::Ref view; }; class EditorApp : public OpenEngine::Application { public: EditorApp(); ~EditorApp(); }; #endif // EDITOR_HPP