diff --git a/Editor/premake5.lua b/Editor/premake5.lua index a32b896..de713ef 100644 --- a/Editor/premake5.lua +++ b/Editor/premake5.lua @@ -16,6 +16,8 @@ includedirs{ -- I'd prefer if didn't need these.. -- We'll figure that out some time later + "../libs/physx/physx/include", + "../libs/physx/pxshared/include", incfolder["lua"], incfolder["spdlog"], incfolder["glm"], diff --git a/Editor/src/UI/EditorWindow.h b/Editor/src/UI/EditorWindow.h index bc8ed06..283619c 100644 --- a/Editor/src/UI/EditorWindow.h +++ b/Editor/src/UI/EditorWindow.h @@ -5,7 +5,7 @@ class EditorWindow { public: - EditorWindow(const std::string& name ) { ImGui::Begin(name.c_str()); } + EditorWindow(const std::string& name, ImGuiWindowFlags_ flags = ImGuiWindowFlags_None ) { ImGui::Begin(name.c_str(), false ,flags); } diff --git a/Editor/src/UI/GUIRenderer.h b/Editor/src/UI/GUIRenderer.h index ba24536..4788e3a 100644 --- a/Editor/src/UI/GUIRenderer.h +++ b/Editor/src/UI/GUIRenderer.h @@ -22,6 +22,7 @@ public: ImGui_ImplGlfw_InitForOpenGL(window.GetGLFWHandle(), true); ImGui_ImplOpenGL3_Init("#version 450"); + ImGuizmo::SetImGuiContext(ImGui::GetCurrentContext()); ImGuizmo::SetOrthographic(true); } diff --git a/Editor/src/UI/MainMenuBar.h b/Editor/src/UI/MainMenuBar.h index e8786f9..1dd26a4 100644 --- a/Editor/src/UI/MainMenuBar.h +++ b/Editor/src/UI/MainMenuBar.h @@ -138,6 +138,33 @@ public: } } + void DebugMenu() + { + if (ImGui::BeginMenu("Debug")) { + ImGui::EndMenu(); + } + } + + void SelectMenu() { + if (ImGui::BeginMenu("Select")) { + ImGui::EndMenu(); + } + } + + void WindowMenu() { + if (ImGui::BeginMenu("Window")) { + + ImGui::EndMenu(); + } + } + + void Help() { + if (ImGui::BeginMenu("Help")) { + ImGui::EndMenu(); + } + } + + ~MainMenuBar() { ImGui::EndMainMenuBar(); } private: char* path = nullptr; diff --git a/Editor/src/UI/widgets.h b/Editor/src/UI/widgets.h index 6d1e27d..6dec587 100644 --- a/Editor/src/UI/widgets.h +++ b/Editor/src/UI/widgets.h @@ -17,6 +17,11 @@ typedef void ( *voidFunction ) (void); using namespace YoggieEngine; +auto matrix = glm::mat4(1.0f); +auto worldOrigin = glm::mat4(1.0f); +auto projection = glm::perspective(45.0f, 0.89f, 0.001f, 1.0f); +auto view = glm::mat4(1.0f); + inline void ComponentView(const std::string& componentName, voidFunction func) { ImGuiWindowFlags_ window_flags = ImGuiWindowFlags_None; @@ -123,28 +128,108 @@ public: } }; + class Viewport : EditorWindow { public: - Viewport (Framebuffer& fb) : EditorWindow("SceneView") { - ImGui::Image( + Viewport (Framebuffer& fb, Camera cam ) : EditorWindow("SceneView") + { + ImVec2 WinPos = ImGui::GetWindowPos(); + ImVec2 ContentRegionMin = ImGui::GetWindowContentRegionMin(); + ImVec2 ContentRegionMax = ImGui::GetWindowContentRegionMax(); + ImVec2 ScreenSpaceMin = { ContentRegionMin.x + WinPos.x, ContentRegionMin.y + WinPos.y }; + ImVec2 ScreenSpaceMax = { ContentRegionMax.x + WinPos.x,ContentRegionMax.y + WinPos.y }; + + + ImGui::Image( (void*)(intptr_t)fb.GetColourAttachment(), ImVec2{ (float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight() } ); - //ImGuizmo::SetDrawlist(); - //ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, ImGui::GetWindowWidth(), ImGui::GetWindowHeight()); - //ImGuizmo::Enable(true); - //ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(trans)); + + ImGuizmo::Enable(true); + ImGuizmo::SetRect(ScreenSpaceMin.x, ScreenSpaceMin.y,ContentRegionMax.x, ContentRegionMax.y); + + ImGuizmo::ViewManipulate(glm::value_ptr(cam.ViewMatrix), 1, { ScreenSpaceMin.x,ScreenSpaceMin.y }, { 90,90 }, 0x22CCCCCC); + ImGuizmo::DrawGrid(glm::value_ptr(cam.ViewMatrix), glm::value_ptr(cam.ProjectionMatrix), glm::value_ptr(worldOrigin), 100.0f); + + // Matrix is the model matrix we would want to manipulate + ImGuizmo::Manipulate(glm::value_ptr(cam.ViewMatrix), glm::value_ptr(cam.ProjectionMatrix), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(matrix)); } }; + +int selectedGfxAPI = 0; +int selectedPhysicsEngine = 0; +glm::vec3 Gravity = glm::vec3(0.0f, -9.81f, 0.0f); +bool ShowAdvancedOptions = false; +bool DebugEngine = false; class Settings : EditorWindow { public: - Settings() : EditorWindow("Settings") { - ImGui::LabelText("##title-settings", "Fine grain control over your engine... "); + Settings() : EditorWindow("Settings") + { + ImGui::LabelText("##title-settings", "Fine grain control over the engine!"); + + if (ImGui::BeginCombo("Graphics API", GraphicsAPI[selectedGfxAPI])) { + for (int i = 0; i < 3; i++) { + bool isSelected = i == selectedGfxAPI; + if (ImGui::Selectable(GraphicsAPI[i], isSelected)) { + selectedGfxAPI = i; + } + + if(isSelected) + ImGui::SetItemDefaultFocus(); + } + + ImGui::EndCombo(); + } + + ImGui::NewLine(); + + if (ImGui::BeginCombo("Physics Engine", PhysicsEngine[selectedPhysicsEngine])) { + for (int i = 0; i < 2; i++) { + bool isSelected = i == selectedPhysicsEngine; + if (ImGui::Selectable(PhysicsEngine[i], isSelected)) { + selectedGfxAPI = i; + } + + if (isSelected) + ImGui::SetItemDefaultFocus(); + } + + ImGui::EndCombo(); + } + + ImGui::InputFloat3("Gravity", glm::value_ptr(Gravity)); + + ImGui::NewLine(); + if (ImGui::Button("Show Advanced options ")) { + ShowAdvancedOptions = !ShowAdvancedOptions; + } + + if (ShowAdvancedOptions) + { + ImGui::Checkbox("Debug Engine", &DebugEngine); + + } + } + +private: + + + const char* PhysicsEngine[2] = { + "PhysX", + "Jolt Physics" + }; + + const char* GraphicsAPI[3] = { + "OpenGL", + "Vulkan", + "Metal (Apple)" + }; + }; class ProjectInfo : EditorWindow { @@ -183,6 +268,9 @@ public: ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f, 0.f, 0.f, 0.f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.f, 1.f, 1.f, 0.2f)); + Texture folderIcon = Texture("rsc/folderIcon.png"); + Texture assetIcon = Texture("rsc/assetIcon.png"); + int row = 0; int column = 0; @@ -197,14 +285,14 @@ public: if (asset.isFolder) { ImGui::ImageButton( - (ImTextureID)(Texture("rsc/folderIcon.png")).GetID(), + (ImTextureID)folderIcon.GetID(), ImVec2{ (float)iconSize,(float)iconSize }); ImGui::Text(asset.GetName(), row); } else { ImGui::ImageButton( - (ImTextureID)(Texture("rsc/assetIcon.png")).GetID(), + (ImTextureID)assetIcon.GetID(), ImVec2{ (float)iconSize, (float)iconSize }); ImGui::Text(asset.GetName(), row); @@ -217,12 +305,58 @@ public: ImGui::PopStyleColor(3); ImGui::EndTable(); + const GLuint textures[2]{ assetIcon.GetID(), folderIcon.GetID() }; + glDeleteTextures(2, textures ); } } private: - static Texture folderIcon; - static Texture AssetIcon; int iconSize = 60; +}; + +#define RuntimeControlWindowFlags (ImGuiWindowFlags_)(ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse) + +struct ButtonInfo { + const char* Name; + ImVec4 Color; +}; + + +class RuntimeControls : EditorWindow { +public: + RuntimeControls() : EditorWindow("RuntimeControls", RuntimeControlWindowFlags) { + + ImGui::SameLine((ImGui::GetWindowContentRegionMax().x / 2) - ( numButtons * buttonSize.x )); + for (int i = 0; i < numButtons; i++) { + ImVec4 color = button[i].Color; + 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(button[i].Name, buttonSize)) { + + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::SameLine(); + + } + } + +private: + ImVec2 buttonSize = ImVec2{ 90 ,25 }; + unsigned int numButtons = 2; + ButtonInfo button[2] = { + {"Play" , ImVec4{ 0.001 * 12 , 0.001 * 201 , 0.001* 69, 1.0f}}, + {"Simulate", ImVec4{ 0.001 * 14, 0.001 * 157, 0.001 * 201, 1.0f}} + }; + }; \ No newline at end of file diff --git a/Editor/src/app.cpp b/Editor/src/app.cpp index 643141d..0c9cc34 100644 --- a/Editor/src/app.cpp +++ b/Editor/src/app.cpp @@ -1,5 +1,6 @@ #include "../../YoggieEngine/src/EntryPoint.h" #include "../../YoggieEngine/src/AssetManager/ModelImporter.h" +#include "../../YoggieEngine/src/Physics/Physics.h" #include @@ -18,105 +19,64 @@ const unsigned int MS_PER_UPDATE = 2; void CreateTestProject(std::unique_ptr& project, Scene& scene); +RendererConfig EditorSceneRendererConfig{ + 1200, // Screen Width + 700, // Screen Height + glm::vec3{0,0,0}, // Clear Color + true // Depth testing +}; + class Editor : public Application { public: - Editor() : Application("Editor"){ - } - - void Run() override + Editor() + : Application("Editor"), + AppWindow(1200,700), + framebuffer(new Framebuffer(1200,700)), + viewportRenderer(EditorSceneRendererConfig), + EditorGUIRenderer(AppWindow), + Selected((entt::entity)-1) { - - auto NativeEditorWindow = NativeWindow(1200, 700); - - framebuffer = new Framebuffer(800, 600); - auto renderer = Renderer(RendererConfig{ - 1200, // Screen Width - 700, // Screen Height - glm::vec3{0,0,0}, // Clear Color - true // Depth testing - }); - - auto GuiRenderer = GUIRenderer(NativeEditorWindow); - - Selected = (entt::entity)-1; - - CreateTestProject(CurrentProject, ActiveScene); - - ActiveScene.Start(); - - renderer.setCurrentFrameBuffer(*framebuffer); - - - double previous = glfwGetTime(); - double lag = 0.0; - while (!NativeEditorWindow.WindowShouldClose()) - { - - double current = glfwGetTime(); - double elapsed = current - previous; - previous = current; - lag += elapsed; - - NativeEditorWindow.Poll(); - - while (lag >= MS_PER_UPDATE) - { - ActiveScene.Update(); - lag -= MS_PER_UPDATE; - } - - // submit DrawCommands for all render3DComponents - - auto group = ActiveScene.getReg().view(); - group.each([&renderer](auto enity, TransformComponent& t, Render3DComponent& renderComponent) { - renderer.Submit(renderComponent, t); - }); - - - - renderer.Render(); - - GuiRenderer.Begin(); - RenderGUI(); - GuiRenderer.End(); - - NativeEditorWindow.SwapBuffers(); - glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); - - - } - - - delete framebuffer; - ActiveScene.Stop(); - + viewportRenderer.setCurrentFrameBuffer(*framebuffer); } - - void RenderGUI() { + void RenderScene() { + // submit DrawCommands for all render3DComponents + auto group = ActiveScene.getReg().view(); + group.each([&](auto enity, TransformComponent& t, Render3DComponent& renderComponent) { + viewportRenderer.Submit(renderComponent, t); + }); + + viewportRenderer.Render(); + } + + void RenderEditorGUI() { + EditorGUIRenderer.Begin(); ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); // Show a menu bar { - MainMenuBar menuBar= MainMenuBar(); + MainMenuBar menuBar = MainMenuBar(); menuBar.ApplicationMenu(CurrentProject); menuBar.SceneMenu(CurrentProject, ActiveScene); - /*menuBar.SelectMenu(); + menuBar.SelectMenu(); menuBar.WindowMenu(); menuBar.DebugMenu(); menuBar.Help(); - */ - } { - ProjectInfo projectInfo(*(CurrentProject.get())); + ProjectInfo projectInfo(*(CurrentProject.get())); } { - Viewport sceneview = Viewport(*framebuffer); + Viewport sceneview = Viewport(*framebuffer, viewportRenderer.getCamera()); } + { + RuntimeControls rc = RuntimeControls(); + } + + { SceneExplorer explorer(Selected, ActiveScene); } @@ -132,14 +92,14 @@ public: } { - Settings settings(); + Settings settings = Settings(); } { - // AssetFinder assetsView = AssetFinder(); + // AssetFinder assetsView = AssetFinder(); } - - + + { Console console = Console(); console.Show(); @@ -147,15 +107,74 @@ public: ImGui::ShowDemoWindow(); ImGui::ShowMetricsWindow(); + EditorGUIRenderer.End(); + } + + void Run() override + { + CreateTestProject(CurrentProject, ActiveScene); + ActiveScene.Start(); + + + // Create the physics engine demo! + Physics Physics; + //Physics.Demo(); + + + double previous = glfwGetTime(); + double lag = 0.0; + while (!AppWindow.WindowShouldClose()) + { + + double current = glfwGetTime(); + double elapsed = current - previous; + previous = current; + lag += elapsed; + + AppWindow.Poll(); + + if (SimulatePhysics) + { + Physics.Step(1.0f / 60.0f); + } + + + while (lag >= MS_PER_UPDATE) + { + ActiveScene.Update(); + lag -= MS_PER_UPDATE; + } + + RenderScene(); + + RenderEditorGUI(); + + AppWindow.SwapBuffers(); + glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); + + + } + + delete framebuffer; + ActiveScene.Stop(); } private: + NativeWindow AppWindow; + + Framebuffer* framebuffer; + Renderer viewportRenderer; + + GUIRenderer EditorGUIRenderer; + + // Editor State + bool SimulatePhysics = false; + entt::entity Selected; + std::unique_ptr CurrentProject; Scene ActiveScene; - entt::entity Selected; - Framebuffer* framebuffer ; }; @@ -180,7 +199,7 @@ void CreateTestProject(std::unique_ptr& project, Scene& scene ) { // Create a cube auto model = importer.Import("build/Debug/Models/Cube.obj"); - auto cube = scene.AddEntity("cube"); + auto cube = scene.AddEntity("Cube"); auto& render3DComponent = cube.AddComponent(); render3DComponent.mesh = *(model->renderable->mesh); diff --git a/README.md b/README.md index b4be66e..affaeff 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,9 @@ \ \ - + \ + \ + ## Planning see [TODO](docs/TODO.md) \ see [Features](Features.md) diff --git a/Screenshots/YoggieEditorV0.2.png b/Screenshots/YoggieEditorV0.2.png new file mode 100644 index 0000000..4a73eeb --- /dev/null +++ b/Screenshots/YoggieEditorV0.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af4e792b18eeb1d5d7869aea08ff6a4d60b3546a30d107ddfab557063ca489d2 +size 138633 diff --git a/Screenshots/YoggieEditor_workingGuizmo.png b/Screenshots/YoggieEditor_workingGuizmo.png new file mode 100644 index 0000000..74a40b2 --- /dev/null +++ b/Screenshots/YoggieEditor_workingGuizmo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d14493a79fb5d0f6c841141145ff761d7a01aee7d2a27aa6350b00ff9dfbd62c +size 95277