#include #include #include "ProjectInterface.h" #include "EditorInterface.h" #include "Engine.h" #include "src/Core/Logger.h" #include "src/Vendors/imgui/imgui.h" #include "src/Vendors/imgui/ImGuizmo.h" #include "src/Scene/Entities/ImGuiHelper.h" #include "src/Rendering/Textures/Texture.h" #include "src/Rendering/Textures/MaterialManager.h" #include "src/Physics/PhysicsManager.h" #include "src/Vendors/glm/gtc/type_ptr.hpp" #include "src/Vendors/glm/gtx/matrix_decompose.hpp" #include "src/Resource/FontAwesome5.h" #include #include "src/Scene/Scene.h" #include "src/Scene/Components/Components.h" #include "src/Scene/Components/BoxCollider.h" #include "src/Scene/Systems/QuakeMapBuilder.h" #include "src/Scene/Components/LightComponent.h" #include "../UIComponents/Viewport.h" #include #include #include #include "src/Rendering/Renderer.h" #include #include "src/Core/Input.h" #include "../Actions/EditorSelection.h" #include "FileSystemUI.h" #include "../Misc/InterfaceFonts.h" #include "WelcomeWindow.h" #include "LoadingSplash.h" #include "src/Rendering/SceneRenderer.h" #include #include #include "UIDemoWindow.h" #include #include #include #include #include #include "../Commands/Commands/Commands.h" namespace Nuake { Ref userInterface; ImFont* normalFont; ImFont* boldFont; ImFont* EditorInterface::bigIconFont; EditorInterface::EditorInterface(CommandBuffer& commandBuffer) : mCommandBuffer(&commandBuffer) { Logger::Log("Creating editor windows", "window", CRITICAL); filesystem = new FileSystemUI(this); _WelcomeWindow = new WelcomeWindow(this); _audioWindow = new AudioWindow(); Logger::Log("Building fonts", "window", CRITICAL); BuildFonts(); Logger::Log("Loading imgui from mem", "window", CRITICAL); using namespace Nuake::StaticResources; ImGui::LoadIniSettingsFromMemory((const char*)StaticResources::Resources_default_layout_ini); } void EditorInterface::Init() { ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_AutoHideTabBar; ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->Pos); ImGui::SetNextWindowSize(viewport->Size); ImGui::SetNextWindowViewport(viewport->ID); ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGui::DockSpaceOverViewport(viewport, dockspace_flags); //this->filesystem = FileSystemUI(); } ImVec2 LastSize = ImVec2(); void EditorInterface::DrawViewport() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(4, 4)); std::string name = ICON_FA_GAMEPAD + std::string(" Scene"); if (ImGui::Begin(name.c_str())) { ImGui::PopStyleVar(); Overlay(); ImGuizmo::BeginFrame(); ImGuizmo::SetOrthographic(false); ImVec2 regionAvail = ImGui::GetContentRegionAvail(); Vector2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y); Ref framebuffer = Engine::GetCurrentWindow()->GetFrameBuffer(); if (framebuffer->GetSize() != viewportPanelSize) framebuffer->QueueResize(viewportPanelSize); Ref texture = framebuffer->GetTexture(); ImVec2 imagePos = ImGui::GetWindowPos() + ImGui::GetCursorPos(); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); m_ViewportPos = { imagePos.x, imagePos.y }; ImGui::Image((void*)texture->GetID(), regionAvail, ImVec2(0, 1), ImVec2(1, 0)); ImGui::PopStyleVar(); const Vector2& mousePos = Input::GetMousePosition(); const ImVec2& windowPos = ImGui::GetWindowPos() + ImVec2(0, 30.0); const ImVec2& windowSize = ImGui::GetWindowSize() - ImVec2(0, 30.0); const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x; const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y; m_IsHoveringViewport = isInsideWidth && isInsideHeight; ImGuizmo::SetDrawlist(); ImGuizmo::AllowAxisFlip(true); ImGuizmo::SetRect(imagePos.x, imagePos.y + 0.0f, viewportPanelSize.x, viewportPanelSize.y); if (m_DrawGrid && !Engine::IsPlayMode()) { ImGuizmo::DrawGrid(glm::value_ptr(Engine::GetCurrentScene()->GetCurrentCamera()->GetTransform()), glm::value_ptr(Engine::GetCurrentScene()->GetCurrentCamera()->GetPerspective()), glm::value_ptr(glm::identity()), 100.f); } if (Selection.Type == EditorSelectionType::Entity && !Engine::IsPlayMode()) { TransformComponent& tc = Selection.Entity.GetComponent(); Matrix4 transform = tc.GetGlobalTransform(); const auto& editorCam = Engine::GetCurrentScene()->GetCurrentCamera(); Matrix4 cameraView = editorCam->GetTransform(); Matrix4 cameraProjection = editorCam->GetPerspective(); // Imguizmo calculates the delta from the gizmo, ImGuizmo::Manipulate( glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), CurrentOperation, CurrentMode, glm::value_ptr(transform) ); if (ImGuizmo::IsUsing()) { // Since imguizmo returns a transform in global space and we want the local transform, // we need to multiply by the inverse of the parent's global transform in order to revert // the changes from the parent transform. Matrix4 localTransform = Matrix4(transform); ParentComponent& parent = Selection.Entity.GetComponent(); if (parent.HasParent) { const auto& parentTransformComponent = parent.Parent.GetComponent(); const Matrix4& parentTransform = parentTransformComponent.GetGlobalTransform(); localTransform = glm::inverse(parentTransform) * localTransform; } // Decompose local transform float decomposedPosition[3]; float decomposedEuler[3]; float decomposedScale[3]; ImGuizmo::DecomposeMatrixToComponents(glm::value_ptr(localTransform), decomposedPosition, decomposedEuler, decomposedScale); const auto& localPosition = Vector3(decomposedPosition[0], decomposedPosition[1], decomposedPosition[2]); const auto& localScale = Vector3(decomposedScale[0], decomposedScale[1], decomposedScale[2]); localTransform[0] /= localScale.x; localTransform[1] /= localScale.y; localTransform[2] /= localScale.z; const auto& rotationMatrix = Matrix3(localTransform); const Quat& localRotation = glm::normalize(Quat(rotationMatrix)); const Matrix4& rotationMatrix4 = glm::mat4_cast(localRotation); const Matrix4& scaleMatrix = glm::scale(Matrix4(1.0f), localScale); const Matrix4& translationMatrix = glm::translate(Matrix4(1.0f), localPosition); const Matrix4& newLocalTransform = translationMatrix * rotationMatrix4 * scaleMatrix; tc.Translation = localPosition; if (CurrentOperation != ImGuizmo::SCALE) { tc.Rotation = localRotation; } tc.Scale = localScale; tc.LocalTransform = newLocalTransform; tc.Dirty = true; } } if (ImGui::IsWindowHovered() && m_IsHoveringViewport && !m_IsViewportFocused && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_2)) { ImGui::FocusWindow(ImGui::GetCurrentWindow()); } m_IsViewportFocused = ImGui::IsWindowFocused(); if (!Engine::IsPlayMode() && ImGui::GetIO().WantCaptureMouse && m_IsHoveringViewport && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_1) && !ImGuizmo::IsUsing() && m_IsViewportFocused) { const auto windowPosNuake = Vector2(windowPos.x, windowPos.y); auto& gbuffer = Engine::GetCurrentScene()->m_SceneRenderer->GetGBuffer(); auto pixelPos = Input::GetMousePosition() - windowPosNuake; pixelPos.y = gbuffer.GetSize().y - pixelPos.y; // imgui coords are inverted on the Y axis auto gizmoBuffer = Engine::GetCurrentWindow()->GetFrameBuffer(); gizmoBuffer->Bind(); bool foundSomethingToSelect = false; if (const int result = gizmoBuffer->ReadPixel(1, pixelPos); result > 0) { auto ent = Entity{ (entt::entity)(result - 1), Engine::GetCurrentScene().get() }; if (ent.IsValid()) { Selection = EditorSelection(ent); foundSomethingToSelect = true; } } gizmoBuffer->Unbind(); if(!foundSomethingToSelect) { gbuffer.Bind(); if (const int result = gbuffer.ReadPixel(3, pixelPos); result > 0) { auto ent = Entity{ (entt::entity)(result - 1), Engine::GetCurrentScene().get() }; if (ent.IsValid()) { Selection = EditorSelection(ent); } } else { Selection = EditorSelection(); // None } gbuffer.Unbind(); } } } else { ImGui::PopStyleVar(); } ImGui::End(); } void EditorInterface::DrawStatusBar() { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8, 8 }); ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)ImGui::GetMainViewport(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; float height = ImGui::GetFrameHeight(); ImGui::PushStyleColor(ImGuiCol_MenuBarBg, { m_StatusBarColor.r, m_StatusBarColor.g, m_StatusBarColor.b, m_StatusBarColor.a }); if (ImGui::BeginViewportSideBar("##MainStatusBar", viewport, ImGuiDir_Down, height, window_flags)) { if (ImGui::BeginMenuBar()) { ImGui::Text(m_StatusMessage.c_str()); ImGui::SameLine(); const float remainingWidth = ImGui::GetContentRegionAvail().x; auto nuakeLogoTexture = TextureManager::Get()->GetTexture("Resources/Images/logo_white.png"); auto nuakeSize = nuakeLogoTexture->GetSize(); float sizeDiff = height / nuakeSize.y; float scale = 0.5f; const float logoWidth = nuakeSize.x * sizeDiff; std::string version = "dev"; #ifdef NK_DEBUG version += " - debug"; #endif ImVec2 textSize = ImGui::CalcTextSize(version.c_str()); ImGui::Dummy({ remainingWidth - (logoWidth / 1.75f) - textSize.x - 8, height }); ImGui::SameLine(); ImGui::Text(version.c_str()); ImGui::SameLine(); ImGui::SetCursorPosY(height / 4.0 ); ImGui::Image((ImTextureID)(nuakeLogoTexture->GetID()), ImVec2(logoWidth, height) * scale, ImVec2{0, 1}, ImVec2{1, 0}); ImGui::EndMenuBar(); } ImGui::End(); } ImGui::PopStyleColor(); ImGui::PopStyleVar(); } void EditorInterface::DrawMenuBars() { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8, 8 }); ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)ImGui::GetMainViewport(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; float height = ImGui::GetFrameHeight(); if (ImGui::BeginViewportSideBar("##SecondaryMenuBar", viewport, ImGuiDir_Up, height, window_flags)) { if (ImGui::BeginMenuBar()) { float availWidth = ImGui::GetContentRegionAvail().x; float windowWidth = ImGui::GetWindowWidth(); float used = windowWidth - availWidth; float half = windowWidth / 2.0; float needed = half - used; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2)); ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0)); ImGui::Dummy({ ImGui::GetContentRegionAvail().x / 2.0f - (76.0f / 2.0f), 8.0f }); ImGui::SameLine(); if (Engine::IsPlayMode() && Engine::GetTimeScale() != 0.0f) { ImGui::PushStyleColor(ImGuiCol_Text, { 97.0 / 255.0, 0, 1, 1 }); if (ImGui::Button(ICON_FA_PAUSE, ImVec2(30, 30)) || (Input::IsKeyPressed(Key::F6))) { Engine::SetGameState(GameState::Paused); SetStatusMessage("Paused"); } ImGui::PopStyleColor(); } else { if (ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)) || Input::IsKeyPressed(Key::F5)) { if (Engine::GetGameState() == GameState::Paused) { PushCommand(SetGameState(GameState::Playing)); std::string statusMessage = ICON_FA_RUNNING + std::string(" Playing..."); SetStatusMessage(statusMessage.c_str(), { 97.0 / 255.0, 0, 1, 1 }); } else { this->SceneSnapshot = Engine::GetCurrentScene()->Copy(); SetStatusMessage("Building .Net solution..."); auto job = [this]() { ScriptingEngineNet::Get().BuildProjectAssembly(Engine::GetProject()); }; Selection = EditorSelection(); JobSystem::Get().Dispatch(job, [this]() { SetStatusMessage("Entering play mode..."); PushCommand(SetGameState(GameState::Playing)); std::string statusMessage = ICON_FA_RUNNING + std::string(" Playing..."); SetStatusMessage(statusMessage.c_str(), { 97.0 / 255.0, 0, 1, 1 }); }); } } if (ImGui::BeginItemTooltip()) { ImGui::Text("Build & Play"); ImGui::EndTooltip(); } } ImGui::SameLine(); const bool wasPlayMode = Engine::IsPlayMode(); if (!wasPlayMode) { ImGui::BeginDisabled(); } if ((ImGui::Button(ICON_FA_STOP, ImVec2(30, 30)) || Input::IsKeyPressed(Key::F5)) && Engine::IsPlayMode()) { Engine::ExitPlayMode(); Engine::LoadScene(SceneSnapshot); Selection = EditorSelection(); SetStatusMessage("Ready"); } if (!wasPlayMode) { ImGui::EndDisabled(); } else { if (ImGui::BeginItemTooltip()) { ImGui::Text("Exit play mode"); ImGui::EndTooltip(); } } //if (ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)) || (Input::IsKeyPressed(GLFW_KEY_F5) && !Engine::IsPlayMode())) //{ // SceneSnapshot = Engine::GetCurrentScene()->Copy(); // Engine::EnterPlayMode(); //} // //ImGui::SameLine(); // //if ((ImGui::Button(ICON_FA_STOP, ImVec2(30, 30)) || Input::IsKeyPressed(GLFW_KEY_F8)) && Engine::IsPlayMode()) //{ // Engine::ExitPlayMode(); // // Engine::LoadScene(SceneSnapshot); // Selection = EditorSelection(); //} ImGui::SameLine(); ImGui::PopStyleColor(); float lineHeight = 130.0f; float separatorHeight = lineHeight * 8.0f; float separatorThickness = 1.0f; ImVec2 curPos = ImGui::GetCursorPos(); ImVec2 min = ImVec2(curPos.x - separatorThickness, curPos.y - separatorHeight); ImVec2 max = ImVec2(curPos.x + separatorThickness, curPos.y - separatorHeight); ImGui::GetWindowDrawList()->AddRectFilled(min, max, IM_COL32(255, 255, 255, 32), 2.0f); ImGui::SameLine(); const int sizeofRightPart = 176; ImGui::Dummy(ImVec2(ImGui::GetContentRegionAvail().x - sizeofRightPart, 30)); ImGui::SameLine(); const auto& io = ImGui::GetIO(); float frameTime = 1000.0f / io.Framerate; int fps = (int)io.Framerate; ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1, 0.1, 0.1, 1)); ImGui::BeginChild("FPS", ImVec2(70, 30), false); std::string text = std::to_string(fps) + " fps"; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x / 1.25 - ImGui::CalcTextSize(text.c_str()).x - ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15 - (ImGui::CalcTextSize(text.c_str()).y) / 2.0); ImGui::Text(text.c_str()); ImGui::EndChild(); ImGui::SameLine(); ImGui::BeginChild("frametime", ImVec2(70, 30), false); std::ostringstream out; out.precision(2); out << std::fixed << frameTime; text = out.str() + " ms"; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x / 1.25 - ImGui::CalcTextSize(text.c_str()).x - ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15 - (ImGui::CalcTextSize(text.c_str()).y) / 2.0); ImGui::Text(text.c_str()); ImGui::EndChild(); ImGui::SameLine(); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2)); ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0)); if (ImGui::Button(ICON_FA_HAMMER, ImVec2(30, 30))) { JobSystem::Get().Dispatch([]() { Nuake::ScriptingEngineNet::Get().BuildProjectAssembly(Engine::GetProject()); }, []() {} ); } if (ImGui::BeginItemTooltip()) { ImGui::Text("Built .Net project"); ImGui::EndTooltip(); } ImGui::PopStyleColor(); ImGui::PopStyleVar(); ImGui::PopStyleColor(); ImGui::PopStyleVar(); ImGui::PopStyleVar(1); ImGui::EndMenuBar(); } ImGui::End(); } ImGui::PopStyleVar(); } static int selected = 0; Entity QueueDeletion; void EditorInterface::DrawEntityTree(Entity e) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{ 0.0f, 0.0f }); ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_FramePadding | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAllColumns; NameComponent& nameComponent = e.GetComponent(); std::string name = nameComponent.Name; ParentComponent& parent = e.GetComponent(); if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == e) base_flags |= ImGuiTreeNodeFlags_Selected; ImGui::TableNextColumn(); // Write in normal font. ImGui::PushFont(normalFont); // If has no childrens draw tree node leaf if (parent.Children.size() <= 0) { base_flags |= ImGuiTreeNodeFlags_Leaf; } if (nameComponent.IsPrefab && e.HasComponent()) { ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255)); } bool open = ImGui::TreeNodeEx(name.c_str(), base_flags); if(nameComponent.IsPrefab && e.HasComponent()) ImGui::PopStyleColor(); else if (ImGui::BeginDragDropSource()) { ImGui::SetDragDropPayload("ENTITY", (void*)&e, sizeof(Entity)); ImGui::Text(name.c_str()); ImGui::EndDragDropSource(); } if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY")) { Entity payload_entity = *(const Entity*)payload->Data; // Check if entity is already parent. ParentComponent& parentPayload = payload_entity.GetComponent(); if (!EntityContainsItself(payload_entity, e) && parentPayload.Parent != e && std::count(parent.Children.begin(), parent.Children.end(), payload_entity) == 0) { if (parentPayload.HasParent) { // Erase remove idiom. ParentComponent& childOfParent = parentPayload.Parent.GetComponent(); childOfParent.Children.erase(std::remove(childOfParent.Children.begin(), childOfParent.Children.end(), payload_entity), childOfParent.Children.end()); } parentPayload.Parent = e; parentPayload.HasParent = true; parent.Children.push_back(payload_entity); } } ImGui::EndDragDropTarget(); } if (ImGui::IsItemClicked()) Selection = EditorSelection(e); if (ImGui::BeginPopupContextItem()) { Selection = EditorSelection(e); Entity entity = Selection.Entity; if (entity.HasComponent()) { // Moves the editor camera to the camera position and direction. if (ImGui::Selectable("Focus camera")) { Ref editorCam = Engine::GetCurrentScene()->m_EditorCamera; Vector3 camDirection = entity.GetComponent().CameraInstance->GetDirection(); camDirection.z *= -1.0f; editorCam->SetTransform(glm::inverse(entity.GetComponent().GetGlobalTransform())); } ImGui::Separator(); } if (ImGui::Selectable("Remove")) { QueueDeletion = e; } if (entity.GetComponent().HasParent && ImGui::Selectable("Move to root")) { auto& parentComp = Selection.Entity.GetComponent(); if (parentComp.HasParent) { auto& parentParentComp = parentComp.Parent.GetComponent(); parentParentComp.RemoveChildren(entity); parentComp.HasParent = false; } } if (ImGui::Selectable("Save entity as a new prefab")) { Ref newPrefab = Prefab::CreatePrefabFromEntity(Selection.Entity); std::string savePath = FileDialog::SaveFile("*.prefab"); if (!String::EndsWith(savePath, ".prefab")) { savePath += ".prefab"; } if (!savePath.empty()) { newPrefab->SaveAs(savePath); Selection.Entity.AddComponent().PrefabInstance = newPrefab; FileSystem::Scan(); FileSystemUI::m_CurrentDirectory = FileSystem::RootDirectory; } } ImGui::EndPopup(); } ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5, 0.5, 0.5, 1.0), GetEntityTypeName(e).c_str()); ImGui::TableNextColumn(); { bool& isVisible = e.GetComponent().Visible; std::string visibilityIcon = isVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH; ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 }); if (ImGui::Button(visibilityIcon.c_str(), {40, 0})) { isVisible = !isVisible; } ImGui::PopStyleColor(); } if (open) { // Caching list to prevent deletion while iterating. std::vector childrens = parent.Children; for (auto& c : childrens) DrawEntityTree(c); ImGui::TreePop(); } ImGui::PopStyleVar(); ImGui::PopFont(); } #define BEGIN_COLLAPSE_HEADER(names) \ UIFont* names##_boldFont = new UIFont(Fonts::Bold); \ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 0.f)); \ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 8.f)); \ bool names##_Opened = ImGui::CollapsingHeader((std::string(" ") + #names).c_str()); \ ImGui::PopStyleVar(); \ delete names##_boldFont; \ if (names##_Opened) { \ #define END_COLLAPSE_HEADER() \ } \ ImGui::PopStyleVar(); \ void EditorInterface::DrawSceneTree() { Ref scene = Engine::GetCurrentScene(); if (!scene) return; const Ref env = Engine::GetCurrentScene()->GetEnvironment(); if (ImGui::Begin((ICON_FA_MOUNTAIN + std::string(" Environment")).c_str())) { BEGIN_COLLAPSE_HEADER(SKY); if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); ImGui::TableNextColumn(); { // Title ImGui::Text("Sky Type"); ImGui::TableNextColumn(); // Here we create a dropdown for every sky type. const char* SkyTypes[] = { "Procedural Sky", "Color" }; static int currentSkyType = (int)env->CurrentSkyType; ImGui::Combo("##SkyType", ¤tSkyType, SkyTypes, IM_ARRAYSIZE(SkyTypes)); env->CurrentSkyType = (SkyType)currentSkyType; ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string ResetType = ICON_FA_UNDO + std::string("##ResetType"); if (ImGui::Button(ResetType.c_str())) env->CurrentSkyType = SkyType::ProceduralSky; ImGui::PopStyleColor(); } if (env->CurrentSkyType == SkyType::ProceduralSky) { ImGui::TableNextColumn(); { // Sun Intensity ImGui::Text("Sun Intensity"); ImGui::TableNextColumn(); ImGui::DragFloat("##Sun Intensity", &env->ProceduralSkybox->SunIntensity, 0.1f, 0.0f, 1000.0f); ImGui::TableNextColumn(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSunIntensity = ICON_FA_UNDO + std::string("##ResetSunIntensity"); if (ImGui::Button(resetSunIntensity.c_str())) env->ProceduralSkybox->SunIntensity = 100.0f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Sun Direction ImGui::Text("Sun Direction"); ImGui::TableNextColumn(); Vector3 sunDirection = env->ProceduralSkybox->GetSunDirection(); ImGuiHelper::DrawVec3("##Sun Direction", &sunDirection); env->ProceduralSkybox->SunDirection = glm::normalize(sunDirection); ImGui::TableNextColumn(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSunDirection = ICON_FA_UNDO + std::string("##resetSunDirection"); if (ImGui::Button(resetSunDirection.c_str())) env->ProceduralSkybox->SunDirection = Vector3(0.20000f, 0.95917f, 0.20000f); ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Surface Radius ImGui::Text("Surface Radius"); ImGui::TableNextColumn(); ImGui::DragFloat("##surfaceRadius", &env->ProceduralSkybox->SurfaceRadius, 100.f, 0.0f); ImGui::TableNextColumn(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSurfaceRadius = ICON_FA_UNDO + std::string("##resetSurfaceRadius"); if (ImGui::Button(resetSurfaceRadius.c_str())) env->ProceduralSkybox->SurfaceRadius = 6360e3f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Atmosphere Radius ImGui::Text("Atmosphere Radius"); ImGui::TableNextColumn(); ImGui::DragFloat("##AtmosphereRadius", &env->ProceduralSkybox->AtmosphereRadius, 100.f, 0.0f); ImGui::TableNextColumn(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetAtmosphereRadius = ICON_FA_UNDO + std::string("##resetAtmosphereRadius"); if (ImGui::Button(resetAtmosphereRadius.c_str())) env->ProceduralSkybox->AtmosphereRadius = 6380e3f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Center point ImGui::Text("Center Point"); ImGui::TableNextColumn(); ImGuiHelper::DrawVec3("##Center Point", &env->ProceduralSkybox->CenterPoint, 0.0f, 100.0f, 100.0f); ImGui::TableNextColumn(); if (env->ProceduralSkybox->CenterPoint.y < -env->ProceduralSkybox->AtmosphereRadius) env->ProceduralSkybox->CenterPoint.y = -env->ProceduralSkybox->AtmosphereRadius + 1.f; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetCenterPoint = ICON_FA_UNDO + std::string("##resetAtmosphereRadius"); if (ImGui::Button(resetCenterPoint.c_str())) env->ProceduralSkybox->CenterPoint = Vector3(0, -env->ProceduralSkybox->AtmosphereRadius, 0); ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Mie Scattering ImGui::Text("Mie Scattering"); ImGui::TableNextColumn(); Vector3 mieScattering = env->ProceduralSkybox->MieScattering * 10000.0f; ImGuiHelper::DrawVec3("##Mie Scattering", &mieScattering, 0.0f, 100.0f, 0.01f); if (mieScattering.x < 0) mieScattering.x = 0; if (mieScattering.y < 0) mieScattering.y = 0; if (mieScattering.z < 0) mieScattering.z = 0; env->ProceduralSkybox->MieScattering = mieScattering / 10000.0f; ImGui::TableNextColumn(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetMieScattering = ICON_FA_UNDO + std::string("##resetMieScattering"); if (ImGui::Button(resetMieScattering.c_str())) env->ProceduralSkybox->MieScattering = Vector3(2e-5f); ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // RayleighScattering ImGui::Text("Rayleigh Scattering"); ImGui::TableNextColumn(); Vector3 rayleighScattering = env->ProceduralSkybox->RayleighScattering * 10000.0f; ImGuiHelper::DrawVec3("##Ray Scattering", &rayleighScattering, 0.0f, 100.0f, 0.01f); if (rayleighScattering.r < 0) rayleighScattering.r = 0; if (rayleighScattering.g < 0) rayleighScattering.g = 0; if (rayleighScattering.b < 0) rayleighScattering.b = 0; env->ProceduralSkybox->RayleighScattering = rayleighScattering / 10000.0f; ImGui::TableNextColumn(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetRayScattering = ICON_FA_UNDO + std::string("##resetRayScattering"); if (ImGui::Button(resetRayScattering.c_str())) env->ProceduralSkybox->RayleighScattering = Vector3(58e-7f, 135e-7f, 331e-7f); ImGui::PopStyleColor(); } } if (env->CurrentSkyType == SkyType::ClearColor) { ImGui::TableNextColumn(); // Title ImGui::Text("Clear color"); ImGui::TableNextColumn(); // Color picker ImGui::ColorEdit4("##clearColor", &env->AmbientColor.r, ImGuiColorEditFlags_NoAlpha); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetColor = ICON_FA_UNDO + std::string("##ResetColor"); if (ImGui::Button(resetColor.c_str())) env->AmbientColor = Color(0, 0, 0, 1); ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Ambient Term"); ImGui::TableNextColumn(); // Here we create a dropdown for every sky type. ImGui::DragFloat("##AmbientTerm", &env->AmbientTerm, 0.001f, 0.00f, 1.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string ResetType = ICON_FA_UNDO + std::string("##ambient"); if (ImGui::Button(ResetType.c_str())) env->AmbientTerm = 0.25f; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(BLOOM) if (ImGui::BeginTable("BloomTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); ImGui::TableNextColumn(); { // Title ImGui::Text("Bloom"); ImGui::TableNextColumn(); ImGui::Checkbox("##Enabled", &env->BloomEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetBloom = ICON_FA_UNDO + std::string("##resetBloom"); if (ImGui::Button(resetBloom.c_str())) env->BloomEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Bloom Threshold"); ImGui::TableNextColumn(); float threshold = env->mBloom->GetThreshold(); ImGui::DragFloat("##Threshold", &threshold, 0.01f, 0.0f, 500.0f); env->mBloom->SetThreshold(threshold); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetBloomThreshold"); if (ImGui::Button(resetBloomThreshold.c_str())) env->mBloom->SetThreshold(2.4f); ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Bloom Quality"); ImGui::TableNextColumn(); int iteration = env->mBloom->GetIteration(); int oldIteration = iteration; ImGui::DragInt("##quality", &iteration, 1.0f, 0, 4); if (oldIteration != iteration) { env->mBloom->SetIteration(iteration); } ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetQuality = ICON_FA_UNDO + std::string("##resetQuality"); if (ImGui::Button(resetQuality.c_str())) env->mBloom->SetIteration(3); ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(VOLUMETRIC) if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); ImGui::TableNextColumn(); { // Title ImGui::Text("Volumetric"); ImGui::TableNextColumn(); ImGui::Checkbox("##VolumetricEnabled", &env->VolumetricEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Volumetric Scattering"); ImGui::TableNextColumn(); float fogAmount = env->mVolumetric->GetFogAmount(); ImGui::DragFloat("##Volumetric Scattering", &fogAmount, .001f, 0.f, 1.0f); env->mVolumetric->SetFogAmount(fogAmount); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetBloomThreshold"); if (ImGui::Button(resetBloomThreshold.c_str())) env->mBloom->SetThreshold(2.4f); ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Step count"); ImGui::TableNextColumn(); int stepCount = env->mVolumetric->GetStepCount(); ImGui::DragInt("##Volumetric Step Count", &stepCount, 1.f, 0.0f); env->mVolumetric->SetStepCount(stepCount); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetQuality = ICON_FA_UNDO + std::string("##resetQuality"); if (ImGui::Button(resetQuality.c_str())) env->VolumetricStepCount = 50.f; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(SSAO) if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); ImGui::TableNextColumn(); { // Title ImGui::Text("SSAO"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSAOEnabled", &env->SSAOEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSSAO = ICON_FA_UNDO + std::string("##resetSSAO"); if (ImGui::Button(resetSSAO.c_str())) env->SSAOEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("SSAO Strength"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSAOStrength", &env->mSSAO->Strength, 0.1f, 0.0f, 10.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetRadius = ICON_FA_UNDO + std::string("##resetStrength"); if (ImGui::Button(resetRadius.c_str())) env->mSSAO->Strength = 2.0f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("SSAO Radius"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSAORadius", &env->mSSAO->Radius, 0.001f, 0.0f, 1.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetRadius = ICON_FA_UNDO + std::string("##resetRadius"); if (ImGui::Button(resetRadius.c_str())) env->mSSAO->Radius = 0.5f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("SSAO Bias"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSAOBias", &env->mSSAO->Bias, 0.0001f, 0.0f, 0.5f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetSSAOBias"); if (ImGui::Button(resetBloomThreshold.c_str())) env->mSSAO->Bias = 0.025f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("SSAO Area"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSAOArea", &env->mSSAO->Area, 0.0001f, 0.0f, 0.5f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetSSAOArea"); if (ImGui::Button(resetBloomThreshold.c_str())) env->mSSAO->Area = 0.0075f; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("SSAO Falloff"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSAOFalloff", &env->mSSAO->Falloff, 0.0001f, 0.0f, 0.5f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetSSAOFalloff"); if (ImGui::Button(resetBloomThreshold.c_str())) env->mSSAO->Falloff = 0.0022f; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(SSR) if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); SSR* ssr = env->mSSR.get(); { ImGui::TableNextColumn(); // Title ImGui::Text("SSR"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSREnabled", &env->SSREnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSSR = ICON_FA_UNDO + std::string("##resetSSR"); if (ImGui::Button(resetSSR.c_str())) env->SSREnabled = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("SSR RayStep"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSRRS", &ssr->RayStep, 0.01f, 0.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("iterationCount"); ImGui::TableNextColumn(); ImGui::DragInt("##SSRRSi", &ssr->IterationCount, 1, 1); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("distanceBias"); ImGui::TableNextColumn(); ImGui::DragFloat("##SSRRSid", &ssr->DistanceBias, 0.01f, 0.f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("sampleCount"); ImGui::TableNextColumn(); ImGui::DragInt("##SSRRSids", &ssr->SampleCount, 1, 0); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Sampling Enabled"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSRRSidss", &ssr->SamplingEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Expo"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSRRSidsse", &ssr->ExpoStep); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Adaptive Steps"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSRRSidssse", &ssr->AdaptiveStep); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Binary Searcg"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSRRSidsssbe", &ssr->BinarySearch); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("Debug"); ImGui::TableNextColumn(); ImGui::Checkbox("##SSRRSidsssbed", &ssr->DebugDraw); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::TableNextColumn(); { // Title ImGui::Text("samplingCoefficient"); ImGui::TableNextColumn(); ImGui::DragFloat("##samplingCoefficient", &ssr->SampleingCoefficient, 0.001f, 0.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(DOF) if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); { ImGui::TableNextColumn(); // Title ImGui::Text("DOF Enabled"); ImGui::TableNextColumn(); ImGui::Checkbox("##dofEnabled", &env->DOFEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSSR = ICON_FA_UNDO + std::string("##resetrBarrelDistortionEnabled"); if (ImGui::Button(resetSSR.c_str())) env->DOFEnabled = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Focal Depth"); ImGui::TableNextColumn(); ImGui::DragFloat("##doffocalDepth", &env->DOFFocalDepth); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetdofFocalDepth = ICON_FA_UNDO + std::string("##resetdofFocalDepth"); if (ImGui::Button(resetdofFocalDepth.c_str())) env->DOFFocalDepth = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Focal Length"); ImGui::TableNextColumn(); ImGui::DragFloat("##doffocalLength", &env->DOFFocalLength); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFFocalLength = ICON_FA_UNDO + std::string("##resetDOFFocalLength"); if (ImGui::Button(resetDOFFocalLength.c_str())) env->DOFFocalLength = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("fStop"); ImGui::TableNextColumn(); ImGui::DragFloat("##doffstop", &env->DOFFstop); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFFstop = ICON_FA_UNDO + std::string("##resetDOFFstop"); if (ImGui::Button(resetDOFFstop.c_str())) env->DOFFstop = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Auto focus"); ImGui::TableNextColumn(); ImGui::Checkbox("##dofautofocus", &env->DOFAutoFocus); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFFstop = ICON_FA_UNDO + std::string("##resetdofautofocus"); if (ImGui::Button(resetDOFFstop.c_str())) env->DOFAutoFocus = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Display auto focus"); ImGui::TableNextColumn(); ImGui::Checkbox("##dofshowautofocus", &env->DOFShowFocus); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFShowautofocus = ICON_FA_UNDO + std::string("##resetdofshowautofocus"); if (ImGui::Button(resetDOFShowautofocus.c_str())) env->DOFShowFocus = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Manual focus"); ImGui::TableNextColumn(); ImGui::Checkbox("##dofmanualfocus", &env->DOFManualFocus); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFShowautofocus = ICON_FA_UNDO + std::string("##resetdofshowautofocus"); if (ImGui::Button(resetDOFShowautofocus.c_str())) env->DOFShowFocus = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("fStop"); ImGui::TableNextColumn(); ImGui::DragFloat("##doffstop", &env->DOFFstop); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFFstop = ICON_FA_UNDO + std::string("##resetDOFFstop"); if (ImGui::Button(resetDOFFstop.c_str())) env->DOFFstop = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("DOF Start"); ImGui::TableNextColumn(); ImGui::DragFloat("##dofstart", &env->DOFStart); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFFstop = ICON_FA_UNDO + std::string("##resetdofstartp"); if (ImGui::Button(resetDOFFstop.c_str())) env->DOFStart = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("DOF Distance"); ImGui::TableNextColumn(); ImGui::DragFloat("##dofdistance", &env->DOFDist); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFDist = ICON_FA_UNDO + std::string("##resetDOFDist"); if (ImGui::Button(resetDOFDist.c_str())) env->DOFDist = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("DOF Threshold"); ImGui::TableNextColumn(); ImGui::DragFloat("##dofthreshold", &env->DOFThreshold, 0.001f, 0.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFDist = ICON_FA_UNDO + std::string("##resetDOFDist"); if (ImGui::Button(resetDOFDist.c_str())) env->DOFDist = 1.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("DOF Feather"); ImGui::TableNextColumn(); ImGui::DragFloat("##doffeather", &env->DOFFeather, 0.001f, 0.0f, 1.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetDOFDist = ICON_FA_UNDO + std::string("##resetdoffeather"); if (ImGui::Button(resetDOFDist.c_str())) env->DOFDist = 1.0f; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(BARREL_DISTORTION) if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); { ImGui::TableNextColumn(); // Title ImGui::Text("Barrel Distortion"); ImGui::TableNextColumn(); ImGui::Checkbox("##BarrelEnabled", &env->BarrelDistortionEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSSR = ICON_FA_UNDO + std::string("##resetrBarrelDistortionEnabled"); if (ImGui::Button(resetSSR.c_str())) env->BarrelDistortionEnabled = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Distortion"); ImGui::TableNextColumn(); ImGui::DragFloat("##distortion", &env->BarrelDistortion, 0.01f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->BarrelDistortion = 0.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Edge Distortion"); ImGui::TableNextColumn(); ImGui::DragFloat("##edgedistortion", &env->BarrelEdgeDistortion, 0.01f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->BarrelEdgeDistortion = 0.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Scale Adjustement"); ImGui::TableNextColumn(); ImGui::DragFloat("##barrelScale", &env->BarrelScale, 0.01f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->BarrelScale = 1.0f; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() BEGIN_COLLAPSE_HEADER(VIGNETTE) if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("name", 0, 0.3); ImGui::TableSetupColumn("set", 0, 0.6); ImGui::TableSetupColumn("reset", 0, 0.1); { ImGui::TableNextColumn(); // Title ImGui::Text("Vignette Enabled"); ImGui::TableNextColumn(); ImGui::Checkbox("##VignetteEnabled", &env->VignetteEnabled); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetSSR = ICON_FA_UNDO + std::string("##resetrBarrelDistortionEnabled"); if (ImGui::Button(resetSSR.c_str())) env->VignetteEnabled = false; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Intensity"); ImGui::TableNextColumn(); ImGui::DragFloat("##vignetteIntensity", &env->VignetteIntensity, 0.1f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VignetteIntensity = 0.0f; ImGui::PopStyleColor(); } { ImGui::TableNextColumn(); // Title ImGui::Text("Extend"); ImGui::TableNextColumn(); ImGui::DragFloat("##vignetteExtend", &env->VignetteExtend, 0.01f, 0.0f); ImGui::TableNextColumn(); // Reset button ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); if (ImGui::Button(resetVolumetric.c_str())) env->VignetteExtend = 0.0f; ImGui::PopStyleColor(); } ImGui::EndTable(); } END_COLLAPSE_HEADER() } ImGui::End(); std::string title = ICON_FA_TREE + std::string(" Hierarchy"); if (ImGui::Begin(title.c_str())) { std::string searchQuery = ""; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8, 8 }); ImGui::InputTextWithHint("##search", "Search entity", &searchQuery, 0, 0, 0); ImGui::PopStyleVar(); ImGui::SameLine(); if (UI::PrimaryButton("Add Entity", { ImGui::GetContentRegionAvail().x, 0 })) { ImGui::OpenPopup("create_entity_popup"); } ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8, 8 }); if (ImGui::BeginPopup("create_entity_new_popup")) { ImGui::BeginChild("entity_child", ImVec2(442, 442), ImGuiChildFlags_AlwaysUseWindowPadding); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputTextWithHint("##search", "Search entity", &searchQuery, 0, 0, 0); ImGui::PopItemWidth(); //ImGui::Button("Empty", { 130, 130 }); auto textureManager = TextureManager::Get(); ImVec2 buttonSize = { 120, 120 }; ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/cube.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/cube.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/light.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/physics.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/shape.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/code.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/box.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::ImageButton((ImTextureID)textureManager->GetTexture("Resources/Images/wrench.png")->GetID(), buttonSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::BeginDisabled(); ImGui::Button("Addons", { 130, 130 }); ImGui::EndDisabled(); ImGui::EndChild(); ImGui::EndPopup(); } ImGui::PopStyleVar(); if (ImGui::BeginPopup("create_entity_popup")) { if (ImGui::MenuItem("Empty")) { Engine::GetCurrentScene()->CreateEntity("Empty"); } if(ImGui::BeginMenu("3D")) { if (ImGui::MenuItem("Camera")) { Engine::GetCurrentScene()->CreateEntity("Camera").AddComponent(); } if (ImGui::MenuItem("Model")) { Engine::GetCurrentScene()->CreateEntity("Model").AddComponent(); } if (ImGui::MenuItem("Skinned Model")) { Engine::GetCurrentScene()->CreateEntity("Skinned Model").AddComponent(); } if (ImGui::MenuItem("Sprite")) { Engine::GetCurrentScene()->CreateEntity("Sprite").AddComponent(); } if (ImGui::MenuItem("Particle Emitter")) { Engine::GetCurrentScene()->CreateEntity("Particle Emitter").AddComponent(); } if (ImGui::MenuItem("Light")) { Engine::GetCurrentScene()->CreateEntity("Light").AddComponent(); } if (ImGui::MenuItem("Quake Map")) { Engine::GetCurrentScene()->CreateEntity("Quake Map").AddComponent(); } ImGui::EndMenu(); } if (ImGui::BeginMenu("Physics")) { if (ImGui::MenuItem("Character Controller")) { Engine::GetCurrentScene()->CreateEntity("Character Controller").AddComponent(); } if (ImGui::MenuItem("Rigid Body")) { Engine::GetCurrentScene()->CreateEntity("Rigid Body").AddComponent(); } ImGui::EndMenu(); } if (ImGui::BeginMenu("Colliders")) { if (ImGui::MenuItem("Box Collider")) { Engine::GetCurrentScene()->CreateEntity("Box Collider").AddComponent(); } if (ImGui::MenuItem("Sphere Collider")) { Engine::GetCurrentScene()->CreateEntity("Sphere Collider").AddComponent(); } if (ImGui::MenuItem("Capsule Collider")) { Engine::GetCurrentScene()->CreateEntity("Capsule Collider").AddComponent(); } if (ImGui::MenuItem("Cylinder Collider")) { Engine::GetCurrentScene()->CreateEntity("Cylinder Collider").AddComponent(); } if (ImGui::MenuItem("Mesh Collider")) { Engine::GetCurrentScene()->CreateEntity("Mesh Collider").AddComponent(); } ImGui::EndMenu(); } if (ImGui::BeginMenu("Audio")) { if (ImGui::MenuItem("Audio Emitter")) { Engine::GetCurrentScene()->CreateEntity("Audio Emitter").AddComponent(); } ImGui::EndMenu(); } if (ImGui::BeginMenu("Script")) { if (ImGui::MenuItem("Script")) { Engine::GetCurrentScene()->CreateEntity("Script").AddComponent(); } ImGui::EndMenu(); } ImGui::EndPopup(); } // Draw a tree of entities. ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(26.f / 255.0f, 26.f / 255.0f, 26.f / 255.0f, 1)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 }); if (ImGui::BeginChild("Scene tree", ImGui::GetContentRegionAvail(), false)) { if (ImGui::BeginTable("entity_table", 3, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn(" Label", ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("Visibility ", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed); ImGui::TableHeadersRow(); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0)); std::vector entities = scene->GetAllEntities(); for (Entity e : entities) { ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanFullWidth; std::string name = e.GetComponent().Name; // If selected add selected flag. if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == e) base_flags |= ImGuiTreeNodeFlags_Selected; // Write in normal font. ImGui::PushFont(normalFont); // Draw all entity without parents. if (!e.GetComponent().HasParent) { // Recursively draw childrens. DrawEntityTree(e); } // Pop font. ImGui::PopFont(); // Right click menu //if (ImGui::BeginPopupContextItem()) // ImGui::EndPopup(); } ImGui::PopStyleVar(); } ImGui::EndTable(); } ImGui::EndChild(); ImGui::PopStyleVar(); ImGui::PopStyleColor(); if (ImGui::BeginDragDropTarget()) // Drag n drop new prefab file into scene tree { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Prefab")) { char* file = (char*)payload->Data; std::string fullPath = std::string(file, 256); std::string relPath = FileSystem::AbsoluteToRelative(fullPath); Prefab::New(relPath); } ImGui::EndDragDropTarget(); } // Deleted entity queue if (QueueDeletion.GetHandle() != -1) { Engine::GetCurrentScene()->DestroyEntity(QueueDeletion); // Clear Selection Selection = EditorSelection(); QueueDeletion = Entity{ (entt::entity)-1, scene.get() }; } } ImGui::End(); } bool EditorInterface::EntityContainsItself(Entity source, Entity target) { ParentComponent& targeParentComponent = target.GetComponent(); if (!targeParentComponent.HasParent) return false; Entity currentParent = target.GetComponent().Parent; while (currentParent != source) { if (currentParent.GetComponent().HasParent) currentParent = currentParent.GetComponent().Parent; else return false; if (currentParent == source) return true; } return true; } bool LogErrors = true; bool LogWarnings = true; bool LogDebug = true; bool AutoScroll = true; void EditorInterface::DrawLogger() { if (ImGui::Begin("Logger")) { ImGui::Checkbox("Errors", &LogErrors); ImGui::SameLine(); ImGui::Checkbox("Warning", &LogWarnings); ImGui::SameLine(); ImGui::Checkbox("Debug", &LogDebug); ImGui::SameLine(); ImGui::Checkbox("Autoscroll", &AutoScroll); //ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); //if (ImGui::BeginChild("Log window", ImGui::GetContentRegionAvail(), false)) //{ //ImGui::PopStyleVar(); ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Hideable; if (ImGui::BeginTable("LogTable", 3, flags)) { ImGui::TableSetupColumn("Severity", ImGuiTableColumnFlags_WidthFixed, 64.0f); ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_WidthFixed, 64.0f); ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch, 1.0f); ImGui::TableNextColumn(); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(4, 4)); for (auto& l : Logger::GetLogs()) { if (l.type == LOG_TYPE::VERBOSE && !LogDebug) continue; if (l.type == LOG_TYPE::WARNING && !LogWarnings) continue; if (l.type == LOG_TYPE::CRITICAL && !LogErrors) continue; std::string severityText = ""; if (l.type == LOG_TYPE::VERBOSE) severityText = "verbose"; else if (l.type == LOG_TYPE::WARNING) severityText = "warning"; else severityText = "critical"; ImVec4 colorGreen = ImVec4(0.59, 0.76, 0.47, 1.0); ImGui::PushStyleColor(ImGuiCol_Text, colorGreen); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.59, 0.76, 0.47, 0.2)), -1); const std::string timeString = " [" + l.time + "]"; ImGui::Text(timeString.c_str()); ImGui::PopStyleColor(); ImGui::TableNextColumn(); ImVec4 colorBlue = ImVec4(98 / 255.0, 174 / 255.0, 239 / 255.0, 1.); ImGui::PushStyleColor(ImGuiCol_Text, colorBlue); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(98 / 255.0, 174 / 255.0, 239 / 255.0, 0.2)), -1); ImGui::Text(l.logger.c_str()); ImGui::PopStyleColor(); ImGui::TableNextColumn(); ImVec4 color = ImVec4(1, 1, 1, 1.0); ImGui::PushStyleColor(ImGuiCol_Text, color); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(1, 1, 1, 0.0)), -1); std::string displayMessage = l.message + "(" + std::to_string(l.count) + ")"; ImGui::TextWrapped(displayMessage.c_str()); ImGui::PopStyleColor(); ImGui::TableNextColumn(); } ImGui::PopStyleVar(); if (AutoScroll) { ImGui::SetScrollY(ImGui::GetScrollMaxY()); } ImGui::EndTable(); } } ImGui::End(); } void EditorInterface::Overlay() { // FIXME-VIEWPORT: Select a default viewport const float DISTANCE = 10.0f; int corner = 0; ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; if (corner != -1) { window_flags |= ImGuiWindowFlags_NoMove; ImGuiViewport* viewport = ImGui::GetWindowViewport(); ImVec2 work_area_pos = ImGui::GetCurrentWindow()->Pos; // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any! ImVec2 work_area_size = ImGui::GetCurrentWindow()->Size; ImVec2 window_pos = ImVec2((corner & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE)); ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); ImGui::SetNextWindowViewport(viewport->ID); } ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f); if (ImGui::Begin("Example: Simple overlay", &m_ShowOverlay, window_flags)) { ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100); if (ImGui::Button(ICON_FA_ARROWS_ALT) || Input::IsKeyDown(Key::W)) { CurrentOperation = ImGuizmo::OPERATION::TRANSLATE; } ImGui::SameLine(); if (ImGui::Button(ICON_FA_SYNC_ALT) || Input::IsKeyDown(Key::E)) { CurrentOperation = ImGuizmo::OPERATION::ROTATE; } ImGui::SameLine(); if (ImGui::Button(ICON_FA_EXPAND_ALT) || Input::IsKeyDown(Key::R)) { CurrentOperation = ImGuizmo::OPERATION::SCALE; } ImGui::PopStyleVar(); } ImGui::PopStyleVar(); ImGui::End(); int corner2 = 1; window_flags |= ImGuiWindowFlags_NoMove; ImGuiViewport* viewport = ImGui::GetWindowViewport(); ImVec2 work_area_pos = ImGui::GetCurrentWindow()->Pos; // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any! ImVec2 work_area_size = ImGui::GetCurrentWindow()->Size; ImVec2 window_pos = ImVec2((corner2 & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner2 & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE)); ImVec2 window_pos_pivot = ImVec2((corner2 & 1) ? 1.0f : 0.0f, (corner2 & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos + ImVec2(0, 30), ImGuiCond_Always, window_pos_pivot); ImGui::SetNextWindowViewport(viewport->ID); ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f); ImGui::SetNextWindowSize(ImVec2(16, ImGui::GetContentRegionAvail().y - DISTANCE * 2.0 - 30.0)); if (ImGui::Begin("Controls", &m_ShowOverlay, window_flags)) { const auto& editorCam = Engine::GetCurrentScene()->m_EditorCamera; const float camSpeed = editorCam->Speed; const float maxSpeed = 50.0f; const float minSpeed = 0.1f; const float normalizedSpeed = glm::clamp(camSpeed / maxSpeed, 0.0f, 1.0f); ImVec2 start = ImGui::GetWindowPos() - ImVec2(0.0, 4.0) ; ImVec2 end = start + ImGui::GetWindowSize() - ImVec2(0, 16.0); ImVec2 startOffset = ImVec2(start.x , end.y - (normalizedSpeed * (ImGui::GetWindowHeight() - 15.0))); ImGui::GetWindowDrawList()->AddRectFilled(startOffset + ImVec2(0, 10.0), end + ImVec2(0.0, 15.0), IM_COL32(255, 255, 255, 180), 8.0f, ImDrawFlags_RoundCornersAll); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100); ImGui::PopStyleVar(); } ImGui::PopStyleVar(); ImGui::End(); } void NewProject() { if (Engine::GetProject() && Engine::GetProject()->FileExist()) Engine::GetProject()->Save(); std::string selectedProject = FileDialog::SaveFile("Project file\0*.project"); if(!String::EndsWith(selectedProject, ".project")) selectedProject += ".project"; if (selectedProject.empty()) // Hit cancel return; auto backslashSplits = String::Split(selectedProject, '\\'); auto fileName = backslashSplits[backslashSplits.size() - 1]; std::string finalPath = String::Split(selectedProject, '.')[0]; // We need to create a folder if (const auto& dirPath = finalPath; !std::filesystem::create_directory(dirPath)) { // Should we continue? Logger::Log("Failed creating project directory: " + dirPath); } finalPath += "/" + fileName; Ref project = Project::New(String::Split(fileName, '.')[0], "no description", finalPath); Engine::LoadProject(project); Engine::LoadScene(Scene::New()); Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name); } ProjectInterface pInterface; void OpenProject() { // Parse the project and load it. std::string projectPath = FileDialog::OpenFile("Project file\0*.project"); if (projectPath == "") // Hit cancel. return; FileSystem::SetRootDirectory(FileSystem::GetParentPath(projectPath)); Ref project = Project::New(); if (!project->Deserialize(FileSystem::ReadFile(projectPath, true))) { Logger::Log("Error loading project: " + projectPath, "editor", CRITICAL); return; } project->FullPath = projectPath; Engine::LoadProject(project); pInterface.m_CurrentProject = project; Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name); } void OpenScene() { // Parse the project and load it. std::string projectPath = FileDialog::OpenFile(".scene"); Ref scene = Scene::New(); const std::string& fileContent = FileSystem::ReadFile(projectPath, true); if (!scene->Deserialize(json::parse(fileContent))) { Logger::Log("Error failed loading scene: " + projectPath, "editor", CRITICAL); return; } scene->Path = FileSystem::AbsoluteToRelative(projectPath); Engine::LoadScene(scene); } void EditorInterface::DrawMenuBar() { if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("New project", "CTRL+N")) { NewProject(); Selection = EditorSelection(); } if (ImGui::MenuItem("Open...")) { OpenProject(); Selection = EditorSelection(); } if (ImGui::MenuItem("Save", "CTRL+S")) { PushCommand(SaveProjectCommand(Engine::GetProject())); Selection = EditorSelection(); SetStatusMessage("Project saved."); } if (ImGui::MenuItem("Save as...", "CTRL+SHIFT+S")) { std::string savePath = FileDialog::SaveFile("*.project"); Engine::GetProject()->SaveAs(savePath); Selection = EditorSelection(); } ImGui::Separator(); if (ImGui::MenuItem("Set current scene as default")) { Engine::GetProject()->DefaultScene = Engine::GetCurrentScene(); SetStatusMessage("Current scene set as project default."); } ImGui::Separator(); if (ImGui::MenuItem("New scene")) { Engine::LoadScene(Scene::New()); Selection = EditorSelection(); SetStatusMessage("New scene created."); } if (ImGui::MenuItem("Open scene...", "CTRL+O")) { OpenScene(); Selection = EditorSelection(); } if (ImGui::MenuItem("Save scene", "CTR+SHIFT+L+S")) { Engine::GetCurrentScene()->Save(); Selection = EditorSelection(); SetStatusMessage("Scene saved succesfully."); } if (ImGui::MenuItem("Save scene as...", "CTRL+SHIFT+S")) { std::string savePath = FileDialog::SaveFile("*.scene"); Engine::GetCurrentScene()->SaveAs(savePath); Selection = EditorSelection(); } ImGui::EndMenu(); } if (ImGui::BeginMenu("Edit")) { if (ImGui::MenuItem("Undo", "CTRL+Z")) {} if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item ImGui::Separator(); if (ImGui::MenuItem("Cut", "CTRL+X")) {} if (ImGui::MenuItem("Copy", "CTRL+C")) {} if (ImGui::MenuItem("Paste", "CTRL+V")) {} ImGui::Separator(); if(ImGui::MenuItem("Trenchbroom Configurator", NULL, m_ShowTrenchbroomConfigurator)) { m_ShowTrenchbroomConfigurator = !m_ShowTrenchbroomConfigurator; } ImGui::EndMenu(); } if (ImGui::BeginMenu("View")) { if (ImGui::MenuItem("Draw grid", NULL, m_DrawGrid)) { m_DrawGrid = !m_DrawGrid; } if (ImGui::MenuItem("Draw Axis", NULL, m_DrawAxis)) { m_DrawAxis = !m_DrawAxis; } if (ImGui::MenuItem("Draw collisions", NULL, m_DebugCollisions)) { m_DebugCollisions = !m_DebugCollisions; PhysicsManager::Get().SetDrawDebug(m_DebugCollisions); } if (ImGui::MenuItem("Settings", NULL)) {} ImGui::EndMenu(); } if (ImGui::BeginMenu("Entity")) { if (ImGui::BeginMenu("Create new")) { if (ImGui::MenuItem("Empty")) { auto ent = Engine::GetCurrentScene()->CreateEntity("Empty entity"); } if (ImGui::MenuItem("Light")) { auto ent = Engine::GetCurrentScene()->CreateEntity("Light"); ent.AddComponent(); } if (ImGui::MenuItem("Camera")) { auto ent = Engine::GetCurrentScene()->CreateEntity("Camera"); ent.AddComponent(); } if (ImGui::MenuItem("Rigidbody")) { auto ent = Engine::GetCurrentScene()->CreateEntity("Rigidbody"); ent.AddComponent(); } if (ImGui::MenuItem("Trenchbroom map")) { auto ent = Engine::GetCurrentScene()->CreateEntity("Trenchbroom map"); ent.AddComponent(); } if (ImGui::MenuItem("Model")) { auto ent = Engine::GetCurrentScene()->CreateEntity("Model"); ent.AddComponent(); } ImGui::EndMenu(); } if (ImGui::MenuItem("Delete selected", NULL)); if (ImGui::MenuItem("Duplicate selected", NULL)) {} ImGui::EndMenu(); } if (ImGui::BeginMenu(".Net")) { if (ImGui::MenuItem("Generate Solution", NULL)) { Nuake::ScriptingEngineNet::Get().GenerateSolution(FileSystem::Root, Engine::GetProject()->Name); Nuake::Logger::Log("Generated Solution."); SetStatusMessage("Visual studio solution generated succesfully."); } #ifdef NK_DEBUG if (ImGui::MenuItem("Copy Nuake.NET", NULL)) { Nuake::ScriptingEngineNet::Get().CopyNuakeNETAssemblies(FileSystem::Root); Nuake::Logger::Log("Copied Nuake.Net Assemblies."); SetStatusMessage("Nuake.Net assemblies succesfully copied."); } #endif // NK_DEBUG ImGui::EndMenu(); } if (ImGui::BeginMenu("Debug")) { if (ImGui::MenuItem("Show ImGui demo", NULL, m_ShowImGuiDemo)) m_ShowImGuiDemo = !m_ShowImGuiDemo; if (ImGui::MenuItem("Rebuild Shaders", NULL)) { Nuake::Logger::Log("Rebuilding Shaders..."); Nuake::ShaderManager::RebuildShaders(); Nuake::Logger::Log("Shaders Rebuilt."); SetStatusMessage("Shaders rebuilt."); } ImGui::EndMenu(); } if (ImGui::BeginMenu("Quit")) ImGui::EndMenu(); ImGui::EndMainMenuBar(); } } bool isLoadingProject = false; bool isLoadingProjectQueue = false; UIDemoWindow m_DemoWindow; int frameCount = 2; void EditorInterface::Draw() { Init(); if (isLoadingProjectQueue) { _WelcomeWindow->LoadQueuedProject(); isLoadingProjectQueue = false; auto window = Window::Get(); window->SetDecorated(true); window->SetSize({ 1900, 1000 }); window->Center(); frameCount = 0; return; } // Shortcuts if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) { if(ImGui::IsKeyPressed(ImGuiKey_S)) { Engine::GetProject()->Save(); Engine::GetCurrentScene()->Save(); Selection = EditorSelection(); } else if(ImGui::IsKeyPressed(ImGuiKey_O)) { OpenScene(); Selection = EditorSelection(); } else if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyPressed(ImGuiKey_S)) { std::string savePath = FileDialog::SaveFile("*.project"); Engine::GetProject()->SaveAs(savePath); Selection = EditorSelection(); } } if (_WelcomeWindow->IsProjectQueued() && frameCount > 0) { // draw splash LoadingSplash::Get().Draw(); frameCount--; if (frameCount == 0) { isLoadingProjectQueue = true; } return; } if (!Engine::GetProject()) { _WelcomeWindow->Draw(); return; } pInterface.m_CurrentProject = Engine::GetProject(); m_DemoWindow.Draw(); _audioWindow->Draw(); if (m_ShowTrenchbroomConfigurator) { m_TrenchhbroomConfigurator.Draw(); } DrawMenuBar(); DrawMenuBars(); DrawStatusBar(); pInterface.DrawEntitySettings(); DrawViewport(); DrawSceneTree(); SelectionPanel.Draw(Selection); DrawLogger(); filesystem->Draw(); filesystem->DrawDirectoryExplorer(); if (m_ShowImGuiDemo) ImGui::ShowDemoWindow(); } void EditorInterface::Update(float ts) { if (!Engine::GetCurrentScene() || Engine::IsPlayMode()) { return; } auto& editorCam = Engine::GetCurrentScene()->m_EditorCamera; editorCam->Update(ts, m_IsHoveringViewport && m_IsViewportFocused); const bool entityIsSelected = Selection.Type == EditorSelectionType::Entity && Selection.Entity.IsValid(); if (editorCam->IsFlying() && entityIsSelected && Input::IsKeyPressed(Key::F)) { editorCam->IsMoving = true; editorCam->TargetPos = Selection.Entity.GetComponent().GetGlobalPosition(); } if (entityIsSelected && Input::IsKeyPressed(Key::ESCAPE)) { Selection = EditorSelection(); } } void EditorInterface::BuildFonts() { ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.5f, 0.5f)); FontManager::LoadFonts(); } std::string EditorInterface::GetEntityTypeName(const Entity& entity) const { std::string entityTypeName = ""; if (entity.HasComponent()) { entityTypeName = "Light"; } if (entity.HasComponent()) { entityTypeName = "Rigidbody"; } if (entity.HasComponent()) { entityTypeName = "Character Controller"; } if (entity.HasComponent()) { entityTypeName = "Bone"; } if (entity.HasComponent()) { entityTypeName = "Prefab"; } if (entity.HasComponent()) { entityTypeName = "Audio Emitter"; } if (entity.HasComponent()) { entityTypeName = "Particle Emitter"; } if (entity.HasComponent()) { entityTypeName = "Quake Map"; } if (entity.HasComponent()) { entityTypeName = "Model"; } if (entity.HasComponent()) { entityTypeName = "Skinned Model"; } return entityTypeName; } void EditorInterface::PushCommand(ICommand&& command) { mCommandBuffer->PushCommand(command); } bool EditorInterface::LoadProject(const std::string& projectPath) { FileSystem::SetRootDirectory(FileSystem::GetParentPath(projectPath)); auto project = Project::New(); auto projectFileData = FileSystem::ReadFile(projectPath, true); Logger::Log("Reading file project: " + projectFileData, "window", CRITICAL); try { Logger::Log("Starting deserializing", "window", CRITICAL); project->Deserialize(json::parse(projectFileData)); project->FullPath = projectPath; Engine::LoadProject(project); filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory; } catch (std::exception exception) { Logger::Log("Error loading project: " + projectPath, "editor", CRITICAL); SetStatusMessage("Error loading project: " + projectPath); Logger::Log(exception.what()); return false; } return true; } }