#pragma once #include #include #include #include #include #include #include "AssetManagement/SceneSerializer.h" #include "AssetManagement/AssetFinder.h" #include "PropertyPanels/Inspector.h" #include "AssetManagement/uuid.h" #include "Project/Settings.h" #include "Console.h" #include "AssetManagement/AssetLoaders/ModelLoader.h" #include "IconsMaterialDesign.h" #include "Project/Project.h" #include #include "EditorCamera.h" #include "../../YoggieEngine/src/Graphics/Memory/VertexArray.h" #include "../../YoggieEngine/src/Graphics/Memory/Buffer.h" using namespace YoggieEngine; class EditorLayer : public Layer { public: EditorLayer() : Layer(), Logo("rsc/Yoggie.png"), inspector(Selected), scene(), renderer() { spdlog::info("Colour attachment id: {0}", renderer.getCurrentFrameBuffer().GetColourAttachment()); Selected = YoggieEngine::Entity((entt::entity)-1, &scene); AssetRegistry assetManager = AssetRegistry(); // ModelLoader modelLoader = ModelLoader(); spdlog::info("{0}", project.GetProjectDirectory().string()); //auto latern = modelLoader.LoadAsset(std::filesystem::path("build/debug/Models/Latern.gltf")); //spdlog::info("Loaded mesh: {0}", latern.GetName()); } void OnStartup() override { std::string path = (std::filesystem::current_path()).string(); project.setProjectDirectory(path); assetsView = AssetFinder(project.GetProjectDirectory()); LoadLastOrEmptyProject(); auto cubePath = std::filesystem::path("build/debug/Models/cube.obj"); cube = (ModelLoader()).LoadAsset(cubePath); //Settings settings = Settings(); //Console console = Console(); } glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, -5.0f); glm::vec3 cameraRotation = glm::vec3(0.0f); void OnUpdate() override { scene.Update(); /* * if (Sceneview.isFocused) { UpdateSceneCamera(sceneview); } */ auto components = scene.getReg().view(); for(auto component : components){ auto& renderComponent = YoggieEngine::Entity(component, &scene).GetComponent(); renderComponent.mesh = cube; if (renderComponent.VAO == 0 || renderComponent.IBO == 0) { VertexArray va = VertexArray(); Buffer vertexBuffer = Buffer(); Buffer elementBuffer = Buffer(); va.Create(); va.Bind(); vertexBuffer.createBuffer(); vertexBuffer.Bind(false); vertexBuffer.setBufferData((void*)&renderComponent.mesh.vertices[0], renderComponent.mesh.vertices.size() * sizeof(Vertex), false); elementBuffer.createBuffer(); elementBuffer.Bind(true); elementBuffer.setBufferData((void*)&renderComponent.mesh.elements[0], renderComponent.mesh.elements.size() * sizeof(unsigned int), true); va.AttachAttribute(0, 3, sizeof(Vertex)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); va.Unbind(); vertexBuffer.Unbind(false); elementBuffer.Unbind(true); renderComponent.VAO = va.getID(); renderComponent.IBO = elementBuffer.getBufferID(); } } camera->view = glm::translate(glm::mat4(1.0f), cameraPosition) * glm::toMat4(glm::quat(cameraRotation)); renderer.Render(scene, *camera); } ImGuizmo::OPERATION activeOperation = ImGuizmo::OPERATION::TRANSLATE; void OnUI() override { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { ImGui::GetWindowWidth(), 7 }); ImGui::BeginMainMenuBar(); int scaleFactor = 30; ImGui::Image((ImTextureID)Logo.GetID(), { Logo.getSize().x / scaleFactor , Logo.getSize().y / scaleFactor }); ImGui::PopStyleVar(); if (ImGui::BeginMenu("App")) { if (ImGui::MenuItem("Load Project")) { nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path); switch (result) { case(NFD_OKAY): //Project::LoadProject(path, project); //AssetRegistry::setAssetPath(project.GetProjectDirectory()); //AssetRegistry::BuildAssetView(); break; case(NFD_CANCEL): break; case(NFD_ERROR): spdlog::error("NFD_Error: {0}", NFD_GetError()); break; } } if (ImGui::MenuItem("Save project as...")) { nfdresult_t result = NFD_SaveDialog({ "yproj" }, NULL, &path); switch (result) { case(NFD_OKAY): spdlog::info("Save as: {0}", path); //Project::SaveProject(path, project); break; case(NFD_CANCEL): break; case(NFD_ERROR): spdlog::error("NFD_Error: {0}", NFD_GetError()); break; } } ImGui::EndMenu(); } if (ImGui::BeginMenu("Scene")) { if (ImGui::MenuItem("Save scene")) { nfdresult_t result = NFD_SaveDialog({ "yscene" }, NULL, &path); switch (result) { case(NFD_OKAY): //SaveScene(path, scene); //project.AddScene(scene); break; case(NFD_CANCEL): break; case(NFD_ERROR): std::cout << "NFD_Error: " << NFD_GetError() << std::endl; break; } } if (ImGui::MenuItem("Load scene")) { auto result = NFD_OpenDialog({ "yscene" }, NULL, &path); switch (result) { case (NFD_OKAY): //LoadScene(path, scene); break; case(NFD_CANCEL): break; case(NFD_ERROR): std::cout << "NFD_Error: " << NFD_GetError() << std::endl; break; } } if (ImGui::MenuItem("Add Entity")) { //scene.AddEntity("New Entity"); } if (ImGui::MenuItem("Import Model")) { auto result = NFD_OpenDialog("obj,fbx,gltf", NULL, &path); switch (result) { case(NFD_OKAY): // Import Model AssetRegistry::LoadFromSource( path, "build/Debug/Assets"//project.get()->GetProjectDirectory() / "Assets" ); break; case(NFD_CANCEL): break; case(NFD_ERROR): std::cout << "NFD_Error: " << NFD_GetError() << std::endl; break; } } if (ImGui::MenuItem("Import MeshAsset (temp)")) { auto result = NFD_OpenDialog("mesh", NULL, &path); switch (result) { case(NFD_OKAY): { YoggieEngine::Mesh* importedMesh = AssetRegistry::LoadFromAssetFile(path); if (importedMesh != nullptr) { auto full_name = std::filesystem::path(path); // auto importedModel = scene.AddEntity(full_name.filename().u8string()); // auto& rendererComponent = importedModel.AddComponent(); // rendererComponent.mesh = *importedMesh; } } break; case(NFD_CANCEL): spdlog::debug("User cancelled action"); break; case(NFD_ERROR): spdlog::warn("Something went wrong!"); break; } } ImGui::EndMenu(); } ImGui::SameLine(ImGui::GetWindowWidth() / 4 * 3); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.3f, 0.3f, 1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::Button(ICON_MD_ROCKET_LAUNCH "Project"); ImGui::SameLine(ImGui::GetWindowWidth() - 120); /* ImGui::PopStyleColor(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.1f, 0.1f, 0.1f, 0.01f)); if (ImGui::Button(ICON_MD_MINIMIZE)) { spdlog::info("Minimize"); } if (ImGui::Button(ICON_MD_MAXIMIZE)) { spdlog::info("Maximize"); } if (ImGui::Button(ICON_MD_CLOSE)) { spdlog::info("Quit"); } */ ImGui::PopStyleColor(1); ImGui::PopStyleVar(); ImGui::EndMainMenuBar(); ImGui::Begin("RuntimeControls"); ImGui::BeginGroup(); ImGui::SameLine(); ImGui::Text(ICON_MD_TRANSFORM); auto spacing = 10; float buttonWidth = 75.0f; float buttonHeight = 30; float ColorIntensity = 0.5f; float ColorIntensityHovered = 0.75; float ColorIntensityActive = 0.85; float yPadding = 6.f; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{0, yPadding }); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.0f,ColorIntensity ,0.0f ,1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.0f,ColorIntensityHovered ,0.0f ,1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.0f,ColorIntensityActive ,0.0f ,1.0f }); ImGui::SameLine(0, spacing); if (ImGui::Button("Translate", { buttonWidth,buttonHeight })) activeOperation = ImGuizmo::OPERATION::TRANSLATE; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 0, yPadding }); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ ColorIntensity, 0.0f ,0.0f ,1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ ColorIntensityHovered, 0.0f ,0.0f ,1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ ColorIntensityActive, 0.0f ,0.0f ,1.0f }); ImGui::SameLine(0, spacing); if (ImGui::Button("Rotate", { buttonWidth,buttonHeight })) activeOperation = ImGuizmo::OPERATION::ROTATE; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 0, yPadding }); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.0f, 0.0f ,ColorIntensity ,1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.0f, 0.0f ,ColorIntensityHovered ,1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.0f, 0.0f ,ColorIntensityActive ,1.0f }); ImGui::SameLine(0, spacing); if (ImGui::Button("Scale", { buttonWidth,buttonHeight })) activeOperation = ImGuizmo::OPERATION::SCALE; ImGui::PopStyleColor(9); ImGui::PopStyleVar(3); ImGui::EndGroup(); ImGui::SameLine((ImGui::GetWindowContentRegionMax().x / 2) - (90)); auto color = ImVec4{ 0.001 * 12 , 0.001 * 201 , 0.001 * 69, 1.0f }; ImGui::PushStyleColor(ImGuiCol_Button, color); const float strengthIncrease = 1.5f; ImGui::PushStyleColor( ImGuiCol_ButtonHovered, ImVec4{ color.x * strengthIncrease, color.y * strengthIncrease, color.z * strengthIncrease, color.w } ); if (ImGui::Button(ICON_MD_PLAY_ARROW, { 90,25 })) { // Play game } ImGui::PopStyleColor(2); ImGui::SameLine(); color = ImVec4{ 0.001 * 14, 0.001 * 157, 0.001 * 201, 1.0f }; ImGui::PushStyleColor(ImGuiCol_Button, color); ImGui::PushStyleColor( ImGuiCol_ButtonHovered, ImVec4{ color.x * strengthIncrease, color.y * strengthIncrease, color.z * strengthIncrease, color.w } ); if (ImGui::Button(ICON_MD_ELECTRIC_BOLT, { 90,25 })) { // Simulate physics } ImGui::PopStyleColor(2); ImGui::End(); unsigned int viewportWindowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0,0 }); ImGui::Begin("SceneView",nullptr,viewportWindowFlags); ImGui::Image((ImTextureID)(intptr_t)renderer.getCurrentFrameBuffer().GetColourAttachment(), ImVec2{(float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight()}); //ImGuizmo::ViewManipulate(glm::value_ptr(cameraView), 1, ImGui::GetWindowPos(), { 90,90 }, 0x22CCCCCCC); if(Selected.isValid()){ ImGuizmo::SetOrthographic(false); ImGuizmo::SetDrawlist(); ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, ImGui::GetWindowWidth(), ImGui::GetWindowHeight()); const auto& ProjMatrix = camera->projection; const glm::mat4& viewMatrix = ((EditorCamera*)camera)->view; glm::mat4 cameraView = glm::inverse(viewMatrix); glm::mat4 cameraDelta = glm::mat4(1.0f); auto& tc = Selected.GetComponent(); auto transform = tc.GetTransform(); ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(ProjMatrix), activeOperation, ImGuizmo::WORLD, glm::value_ptr(transform), nullptr, nullptr); if(ImGuizmo::IsUsing()) tc.Decompose(transform); } ImGui::End(); ImGui::PopStyleVar(); ImGui::Begin("EditorCamera"); ImGui::SliderFloat3("position", glm::value_ptr(cameraPosition), -50, 50); ImGui::End(); ImGui::Begin(ICON_MD_MENU "SceneExplorer",nullptr); scene.getReg().each([&](entt::entity enttNumber) { YoggieEngine::Entity entity = YoggieEngine::Entity(enttNumber, &scene); auto id = entity.GetComponent(); if (ImGui::Selectable(id.name.c_str(), entity == Selected)) { Selected = YoggieEngine::Entity(enttNumber, &scene); } }); ImGui::End(); inspector.Update(); //settings.Update(); //console.Update(); assetsView.Update(); ImGui::ShowDemoWindow(); //ImGui::ShowMetricsWindow(); } void OnCreate() override { spdlog::info(" Layer Create!" ); } void OnDestroy() override { spdlog::info( " Layer Destroy!" ); } private: Inspector inspector; AssetFinder assetsView; bool SimulatePhysics = true; YoggieEngine::Entity Selected; Project project; Scene scene; char* path = nullptr; Texture Logo; Renderer renderer; Camera* camera = new EditorCamera(); Mesh cube ; void LoadLastOrEmptyProject() { // Check if there is a last known loaded project and // load that one . // Otherwise load no project.. // OR // Load an empty project. mINI::INIStructure ini; if (std::filesystem::exists("build\\Debug\\Editor.ini")) { mINI::INIFile file("build\\Debug\\Editor.ini"); file.read(ini); } else { spdlog::debug("Could not find an `Editor.ini` file."); } if (ini["editor"]["openlastproject"] == "TRUE") { Project::LoadProject(ini["cache"]["project"], project); LoadScene(ini["cache"]["scene"], scene); } else { spdlog::debug("Starting without a project. Please create one."); } } void UpdateSceneCamera() { const float movement_speed = 0.01f; static float lastX = 400, lastY = 300; const float sensitivity = 0.1; static bool firstMouse = true; /* if (MouseButtonPressed(YOGGIE_MOUSE_BUTTON_RIGHT)) { glfwSetInputMode((GLFWwindow*)appWindow->GetHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); auto newX = getCursorPosX(appWindow); auto newY = getCursorPosY(appWindow); if (firstMouse) { lastX = newX; lastY = newY; firstMouse = false; } float xoffset = newX - lastX; float yoffset = newY - lastY; lastX = newX; lastY = newY; xoffset *= sensitivity; yoffset *= sensitivity; sceneview.cam.Rotation.x += (xoffset / 2); sceneview.cam.Rotation.y += (xoffset /2); sceneview.cam.Rotation.z += yoffset; if (sceneview.cam.pitch > 89.0f) sceneview.cam.pitch = 89.0f; if (sceneview.cam.pitch < -89.0f) sceneview.cam.pitch = -89.0f; } else if (firstMouse == false) { glfwSetInputMode((GLFWwindow*)appWindow->GetHandle(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); firstMouse = true; } */ /* EditorCamera& cam = sceneview.GetCamera(); if (keyIsPressed(YOGGIE_KEY_UP)) cam.Rotation.x += movement_speed; if (keyIsPressed(YOGGIE_KEY_DOWN)) cam.Rotation.x -= movement_speed; if (keyIsPressed(YOGGIE_KEY_LEFT)) cam.Rotation.y += movement_speed; if (keyIsPressed(YOGGIE_KEY_RIGHT)) cam.Rotation.y -= movement_speed; cam.Update(); */ /* // Check for Camara movement input here! if (keyIsPressed(YOGGIE_KEY_W)) sceneview.cam.Position -= sceneview.cam.Front * movement_speed; if (keyIsPressed(YOGGIE_KEY_A)) sceneview.cam.Position += sceneview.cam.Right * movement_speed; if (keyIsPressed(YOGGIE_KEY_S)) sceneview.cam.Position += sceneview.cam.Front * movement_speed; if (keyIsPressed(YOGGIE_KEY_D)) sceneview.cam.Position -= sceneview.cam.Right * movement_speed; */ } };