Application and layers refactoring

This commit is contained in:
Antoine Pilote
2023-10-15 03:09:47 -04:00
parent 4e23e6a54b
commit 8c581fbc14
19 changed files with 524 additions and 119 deletions
+16 -110
View File
@@ -33,7 +33,11 @@
#include <src/Rendering/SceneRenderer.h>
#include "src/Misc/WindowTheming.h"
#include <src/Core/Application.h>
#include <src/Core/EntryPoint.h>
#include "src/EditorApplication.h"
struct LaunchSettings
{
@@ -109,123 +113,25 @@ LaunchSettings ParseLaunchSettings(const std::vector<std::string>& arguments)
return launchSettings;
}
int ApplicationMain(int argc, char* argv[])
Nuake::Application* Nuake::CreateApplication(int argc, char** argv)
{
using namespace Nuake;
// Parse launch arguments
const auto& arguments = ParseArguments(argc, argv);
LaunchSettings launchSettings = ParseLaunchSettings(arguments);
ApplicationSpecification specification
{
.Name = "Editor",
.WindowWidth = 1600,
.WindowHeight = 900,
.VSync = true
};
#ifdef NK_DEBUG
launchSettings.windowTitle += "(DEBUG BUILD)";
#endif // NK_DEBUG
// Initialize Engine & Window
Engine::Init();
auto window = Engine::GetCurrentWindow();
window->SetSize(launchSettings.resolution);
window->SetTitle(launchSettings.windowTitle);
if (launchSettings.monitor >= 0)
{
window->SetMonitor(launchSettings.monitor);
}
WindowTheming::SetWindowDarkMode(window);
Logger::Log("Creating editor ", "window", CRITICAL);
// Initialize Editor
Nuake::EditorInterface editor;
Logger::Log("Created editor ", "window", CRITICAL);
// Load project in argument
if (!launchSettings.projectPath.empty())
{
Logger::Log("Loading project", "window", CRITICAL);
editor.LoadProject(launchSettings.projectPath);
}
// Start application main loop
GizmoDrawer gizmoDrawer = GizmoDrawer(&editor);
while (!window->ShouldClose())
{
Nuake::Engine::Tick(); // Update
Nuake::Engine::Draw(); // Render
// Render editor
Nuake::Vector2 WindowSize = window->GetSize();
glViewport(0, 0, WindowSize.x, WindowSize.y);
Nuake::Renderer2D::BeginDraw(WindowSize);
auto sceneFramebuffer = window->GetFrameBuffer();
Ref<Nuake::Scene> currentScene = Nuake::Engine::GetCurrentScene();
// Draw gizmos
sceneFramebuffer->Bind();
{
//glDepthMask(false);
Ref<EditorCamera> camera;
if (currentScene)
{
camera = currentScene->m_EditorCamera;
//currentScene->m_SceneRenderer->GetGBuffer().GetTexture(GL_COLOR_ATTACHMENT3)->Unbind();
//glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, currentScene->m_SceneRenderer->GetGBuffer().GetTexture(GL_COLOR_ATTACHMENT3)->GetID(), 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, currentScene->m_SceneRenderer->GetGBuffer().GetTexture(GL_DEPTH_ATTACHMENT)->GetID(), 0);
}
if (currentScene && !Nuake::Engine::IsPlayMode())
{
glEnable(GL_LINE_SMOOTH);
if (editor.ShouldDrawAxis())
{
//gizmoDrawer.DrawAxis(currentScene);
}
if (editor.ShouldDrawCollision())
{
gizmoDrawer.DrawGizmos(currentScene, false);
glDepthFunc(GL_GREATER);
gizmoDrawer.DrawGizmos(currentScene, true);
glDepthFunc(GL_LESS);
}
}
//glDepthMask(true);
}
sceneFramebuffer->Unbind();
// Update & Draw editor
editor.Draw();
editor.Update(Nuake::Engine::GetTimestep());
Nuake::Engine::EndDraw();
}
Nuake::Engine::Close();
return 0;
}
#ifdef NK_WIN
#ifdef NK_DIST
#include "windows.h"
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cdmline, int cmdshow)
{
return ApplicationMain(__argc, __argv);
}
#endif
specification.Name += "(DEBUG BUILD)";
#endif
int main(int argc, char* argv[])
{
return ApplicationMain(argc, argv);
return new EditorApplication(specification);
}
+26
View File
@@ -0,0 +1,26 @@
#include "EditorApplication.h"
#include "Engine.h"
#include "Windows/EditorInterface.h"
#include "Misc/GizmoDrawer.h"
#include "EditorLayer.h"
#include <glad/glad.h>
void EditorApplication::OnInit()
{
using namespace Nuake;
Engine::Init();
m_Window = Engine::GetCurrentWindow();
m_Window->SetSize({ m_Specification.WindowWidth, m_Specification.WindowHeight });
m_Window->SetTitle(m_Specification.Name);
PushLayer(CreateScope<EditorLayer>());
}
void EditorApplication::OnShutdown()
{
Nuake::Engine::Close();
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <src/Core/Application.h>
#include <src/Window.h>
#include "Windows/EditorInterface.h"
#include "Misc/GizmoDrawer.h"
class EditorApplication : public Nuake::Application
{
public:
EditorApplication(const Nuake::ApplicationSpecification& specification)
: Application(specification),
m_Editor(nullptr)
{
}
virtual void OnInit() override;
// virtual void OnUpdate() override;
virtual void OnShutdown() override;
private:
Nuake::EditorInterface* m_Editor;
};
+73
View File
@@ -0,0 +1,73 @@
#include "EditorLayer.h"
#include "Windows/EditorInterface.h"
#include "Misc/GizmoDrawer.h"
#include <glad/glad.h>
void EditorLayer::OnAttach()
{
m_EditorInterface = new Nuake::EditorInterface();
m_GizmoDrawer = new GizmoDrawer(m_EditorInterface);
}
void EditorLayer::OnUpdate()
{
using namespace Nuake;
Nuake::Engine::Tick();
Nuake::Engine::Draw();
auto sceneFramebuffer = GetApplication().GetWindow()->GetFrameBuffer();
// Draw gizmos
if (Ref<Nuake::Scene> currentScene = Nuake::Engine::GetCurrentScene(); currentScene)
{
sceneFramebuffer->Bind();
{
Ref<EditorCamera> camera;
if (currentScene)
{
camera = currentScene->m_EditorCamera;
//currentScene->m_SceneRenderer->GetGBuffer().GetTexture(GL_COLOR_ATTACHMENT3)->Unbind();
//glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, currentScene->m_SceneRenderer->GetGBuffer().GetTexture(GL_COLOR_ATTACHMENT3)->GetID(), 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, currentScene->m_SceneRenderer->GetGBuffer().GetTexture(GL_DEPTH_ATTACHMENT)->GetID(), 0);
}
if (currentScene && !Nuake::Engine::IsPlayMode())
{
glEnable(GL_LINE_SMOOTH);
if (m_EditorInterface->ShouldDrawAxis())
{
m_GizmoDrawer->DrawAxis(currentScene, false);
glDepthFunc(GL_GREATER);
m_GizmoDrawer->DrawAxis(currentScene, true);
glDepthFunc(GL_LESS);
}
if (m_EditorInterface->ShouldDrawCollision())
{
m_GizmoDrawer->DrawGizmos(currentScene, false);
glDepthFunc(GL_GREATER);
m_GizmoDrawer->DrawGizmos(currentScene, true);
glDepthFunc(GL_LESS);
}
}
}
sceneFramebuffer->Unbind();
}
m_EditorInterface->Draw();
m_EditorInterface->Update(Nuake::Engine::GetTimestep());
Nuake::Engine::EndDraw();
}
void EditorLayer::OnDetach()
{
delete m_EditorInterface;
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <src/Core/Layer.h>
namespace Nuake {
class EditorInterface;
}
class GizmoDrawer;
class EditorLayer : public Nuake::Layer
{
public:
virtual void OnAttach() override;
virtual void OnUpdate() override;
virtual void OnDetach() override;
private:
Nuake::EditorInterface* m_EditorInterface;
GizmoDrawer* m_GizmoDrawer;
};
+8 -6
View File
@@ -162,14 +162,9 @@ bool GizmoDrawer::IsEntityInSelection(Nuake::Entity entity)
return false;
}
void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
void GizmoDrawer::DrawAxis(Ref<Scene> scene, bool occluded)
{
using namespace Nuake;
//RenderCommand::Disable(RendererEnum::DEPTH_TEST);
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
// Draw Axis lignes.
//glDepthFunc(GL_ALWAYS); // Disable built-in depth testing
//glDepthMask(false); // Disable writing to the depth buffer
{
m_LineShader->Bind();
m_LineShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
@@ -178,6 +173,13 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
m_AxisLineBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 6);
}
}
void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
{
using namespace Nuake;
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
glLineWidth(2.0f);
auto boxColliderView = scene->m_Registry.view<TransformComponent, BoxColliderComponent>();
+3 -1
View File
@@ -49,10 +49,12 @@ private:
public:
GizmoDrawer(EditorInterface* editor);
GizmoDrawer() = default;
~GizmoDrawer() = default;
void DrawGizmos(Ref<Scene> scene, bool occluded);
void DrawAxis(Ref<Scene> scene, bool occlude);
private:
void GenerateSphereGizmo();
+1 -1
View File
@@ -219,7 +219,7 @@ namespace Nuake
{
SaveRecentFile();
queuedProjectPath = _Projects[SelectedProject].Path;;
queuedProjectPath = _Projects[SelectedProject].Path;
}
//ImGui::PopStyleColor();
+1 -1
View File
@@ -29,7 +29,7 @@ namespace Nuake
public:
static void Init(); // Initialize the engine.
static void Tick(); // Updates everything, called everyframe.
static void Tick(); // Updates everything, called every frame.
static void Close(); // Shutdown the engine.
static void EnterPlayMode(); // Start the game
+9
View File
@@ -22,6 +22,8 @@ namespace Nuake {
m_AudioThreadRunning = false;
m_AudioThread.join();
m_Soloud->deinit();
}
void AudioManager::Initialize()
@@ -35,6 +37,13 @@ namespace Nuake {
m_Soloud->init(SoLoud::Soloud::CLIP_ROUNDOFF, SoLoud::Soloud::ALSA);
#endif
if (m_AudioThread.joinable())
{
m_AudioThreadRunning = false;
m_AudioThread.join();
}
m_AudioThreadRunning = true;
m_AudioThread = std::thread(&AudioManager::AudioThreadLoop, this);
Logger::Log("Audio manager initialized", "audio", VERBOSE);
+58
View File
@@ -0,0 +1,58 @@
#include "Application.h"
#include "Layer.h"
#include <filesystem>
namespace Nuake {
Application::Application(const ApplicationSpecification& appSpecification)
: m_Specification(appSpecification),
m_Running(true)
{
if (!appSpecification.Headless)
{
m_Window = Window::Get();
}
}
void Application::PushLayer(Scope<Layer> layer)
{
layer->OnAttach();
layer->SetApplicationOwner(this);
m_LayerStack.PushLayer(std::move(layer));
}
void Application::PushOverlay(Scope<Layer> layer)
{
layer->OnAttach();
layer->SetApplicationOwner(this);
m_LayerStack.PushOverlayLayer(std::move(layer));
}
void Application::Run()
{
while (m_Running)
{
for (auto& layer : m_LayerStack)
{
layer->OnUpdate();
}
if (!m_Specification.Headless)
{
for (auto& layer : m_LayerStack)
{
layer->OnDraw();
}
}
}
}
void Application::Exit()
{
for (auto& layer : m_LayerStack)
{
layer->OnDetach();
}
}
}
+89
View File
@@ -0,0 +1,89 @@
#pragma once
#include "IApplicationModule.h"
#include "Core.h"
#include "LayerStack.h"
#include <string>
#include <Vector>
#include <src/Window.h>
namespace Nuake {
struct ApplicationSpecification
{
std::string Name = "Application";
uint32_t WindowWidth = 1280;
uint32_t WindowHeight = 720;
bool VSync = true;
std::string WorkingDirectory = "";
bool Headless = false;
};
class Application
{
public:
Application(const ApplicationSpecification& appSpecification);
virtual ~Application() {};
void Run();
void Exit();
virtual void OnInit() {};
virtual void OnUpdate() {};
virtual void OnShutdown() {};
virtual void OnEvent() {};
inline const std::string& GetName() const { return m_Specification.Name; }
void PushLayer(Scope<Layer> layer);
void PushOverlay(Scope<Layer> layer);
// Only accepts IApplicationModule type class
template<typename T>
T& PushModule(Scope<IApplicationModule> applicationModule)
{
static_assert(std::is_base_of<IApplicationModule, T>::value, "Type must be derived from IApplicationModule");
auto* rawPtr = applicationModule.get(); // Get a raw pointer to the module.
m_ApplicationModules.push_back(std::move(applicationModule));
return *dynamic_cast<T*>(rawPtr);
}
// Only accepts IApplicationModule type class
template <typename T>
T& GetModule()
{
static_assert(std::is_base_of<IApplicationModule, T>::value, "Type must be derived from IApplicationModule");
auto resultFindIt = std::find_if(
m_ApplicationModules.begin(),
m_ApplicationModules.end(),
[](IApplicationModule& module)
{
return dynamic_cast<T*>(&module) != nullptr;
}
);
if (resultFindIt == m_ApplicationModules.end())
{
throw std::runtime_error("Module not found.");
}
return dynamic_cast<T&>(*resultFindIt);
}
inline Ref<Window> GetWindow() const { return m_Window; }
protected:
ApplicationSpecification m_Specification;
std::vector<Scope<IApplicationModule>> m_ApplicationModules;
LayerStack m_LayerStack;
bool m_Running;
Ref<Window> m_Window;
};
// Implemented by the client
Application* CreateApplication(int argc, char** argv);
}
+1
View File
@@ -5,6 +5,7 @@
#include <string>
#include <vector>
#include <queue>
#include <stdexcept>
#define ASSERT(x) if (!(x)) assert(false)
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "Application.h"
bool g_ApplicationRunning = true;
namespace Nuake {
int Main(int argc, char** argv)
{
while (g_ApplicationRunning)
{
Application* app = CreateApplication(argc, argv);
app->OnInit();
app->Run();
app->Exit();
delete app;
g_ApplicationRunning = false;
}
return 1;
}
}
#ifdef NK_WIN
#ifdef NK_DIST
#include "windows.h"
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cdmline, int cmdshow)
{
return ApplicationMain(__argc, __argv);
}
#else
#define REGULAR_MAIN
#endif
#else
#define REGULAR_MAIN
#endif
#ifdef REGULAR_MAIN
int main(int argc, char** argv)
{
return Nuake::Main(argc, argv);
}
#endif
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Core.h"
namespace Nuake {
enum class EventType
{
None = 0,
WindowClose, WindowResize, WindowFocus, WindowLostFocus, WindowMoved,
AppUpdate, AppRender, AppEvent, AppCloseEvent
};
class Event
{
virtual EventType GetEventType() const = 0;
virtual const std::string_view& GetName() const = 0;
};
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <string>
namespace Nuake
{
class IApplicationModule
{
private:
std::string m_Name;
public:
IApplicationModule(const std::string& name) : m_Name(name) {}
virtual ~IApplicationModule() {}
virtual void OnInit() = 0;
virtual void OnUpdate() = 0;
virtual void OnExit() = 0;
};
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include "Core.h"
#include "Application.h"
namespace Nuake {
class Layer
{
public:
Layer(const std::string& name = "Layer") : m_Name(name) { };
virtual ~Layer() = default;
virtual void OnAttach() {};
virtual void OnUpdate() {};
virtual void OnDetach() {};
virtual void OnDraw() {};
// TODO: OnEvent
inline const std::string& GetName() const { return m_Name; }
// This is used for layer to have access to the
// application that owns them and their modules.
void SetApplicationOwner(Application* application) { m_Application = application; }
Application& GetApplication() { return *m_Application; }
private:
std::string m_Name;
protected:
Application* m_Application;
};
}
+40
View File
@@ -0,0 +1,40 @@
#include "LayerStack.h"
#include "Layer.h"
namespace Nuake {
LayerStack::LayerStack()
{
m_LayerInsert = m_Layers.begin();
}
void LayerStack::PushLayer(Ref<Layer> layer)
{
m_LayerInsert = m_Layers.emplace(m_LayerInsert, std::move(layer));
}
void LayerStack::PushOverlayLayer(Ref<Layer> layer)
{
m_Layers.emplace_back(std::move(layer));
}
void LayerStack::PopLayer(Ref<Layer> layer)
{
auto it = std::find(m_Layers.begin(), m_Layers.end(), layer);
if (it != m_Layers.end())
{
m_Layers.erase(it);
m_LayerInsert--;
}
}
void LayerStack::PopOverlayLayer(Ref<Layer> layer)
{
auto it = std::find(m_Layers.begin(), m_Layers.end(), layer);
if (it != m_Layers.end())
{
m_Layers.erase(it);
}
}
}
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include "Core.h"
#include <vector>
namespace Nuake {
class Layer;
class LayerStack
{
public:
LayerStack();
~LayerStack() = default;
void PushLayer(Ref<Layer> layer);
void PopLayer(Ref<Layer> layer);
void PushOverlayLayer(Ref<Layer> layer);
void PopOverlayLayer(Ref<Layer> layer);
std::vector<Ref<Layer>>::iterator begin() { return m_Layers.begin(); }
std::vector<Ref<Layer>>::iterator end() { return m_Layers.end(); }
private:
std::vector<Ref<Layer>> m_Layers;
std::vector<Ref<Layer>>::iterator m_LayerInsert;
};
}