Applying better design choices for general engine

Renderer is causing a big memory leak because it never deletes its Vertex Array
This commit is contained in:
Nigel Barink 2022-11-12 22:40:36 +01:00
parent 4b84707f98
commit a1ec94e983
19 changed files with 626 additions and 635 deletions

View File

@ -1,13 +0,0 @@
#pragma once
#include "Project/Project.h"
struct EditorContext {
std::shared_ptr<Project> CurrentProject;
Scene MainScene;
EditorContext() = default;
EditorContext(EditorContext& other) = default;
~EditorContext() = default;
};

View File

@ -20,7 +20,7 @@ void Project::SaveProject(std::filesystem::path path, Project& project)
projectFile.close(); projectFile.close();
} }
void Project::LoadProject(std::filesystem::path path, std::shared_ptr<Project>& project) void Project::LoadProject(std::filesystem::path path, std::unique_ptr<Project>& project)
{ {
std::string YAMLProject; std::string YAMLProject;
std::stringstream sstream; std::stringstream sstream;
@ -36,8 +36,8 @@ void Project::LoadProject(std::filesystem::path path, std::shared_ptr<Project>&
YAML::Node node = YAML::Load(YAMLProject); YAML::Node node = YAML::Load(YAMLProject);
// this is probably not perfect but it seems to work for now // this is probably not perfect but it seems to work for now
project.reset(); project.release();
project = std::make_shared<Project>(node.as<Project>()); project = std::make_unique<Project>(node.as<Project>());
std::cout << "loading..." << project.get()->Name << std::endl; std::cout << "loading..." << project.get()->Name << std::endl;

View File

@ -14,7 +14,7 @@ public:
const std::filesystem::path GetProjectDirectory() { return ProjectDirectory; } const std::filesystem::path GetProjectDirectory() { return ProjectDirectory; }
static void SaveProject(std::filesystem::path path, Project& project); static void SaveProject(std::filesystem::path path, Project& project);
static void LoadProject(std::filesystem::path path, std::shared_ptr<Project>& project); static void LoadProject(std::filesystem::path path, std::unique_ptr<Project>& project);
private: private:
std::string Name; std::string Name;
std::filesystem::path ProjectDirectory; std::filesystem::path ProjectDirectory;

View File

@ -1,78 +0,0 @@
#pragma once
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include "../../YoggieEngine/src/Graphics/Memory/Framebuffer.h"
#include "../../YoggieEngine/src/PerfCounter.h"
#include "../../YoggieEngine/src/Scene/Entity.h"
#include "Project/Project.h"
#include "AssetManagement/AssetManager.h"
class EditorRuntime : public ApplicationRuntime {
public:
EditorRuntime() = default;
void Start() override
{
CurrentProject = std::make_shared<Project>("Random");
std::string path = (std::filesystem::current_path()).string();
CurrentProject.get()->setProjectDirectory(path);
AssetManager::Init();
AssetManager::setAssetPath(CurrentProject.get()->GetProjectDirectory());
AssetManager::BuildAssetView();
framebuffer = new Framebuffer(800, 600);
// Create a level and load it as the current level
auto importer = ModelImporter();
// Create a cube
Model = importer.Import("build/Debug/Models/Cube.obj");
cube = MainScene.AddEntity("cube");
auto& render3DComponent = cube.AddComponent<Render3DComponent>();
render3DComponent.mesh = *(Model->renderable->mesh);
cube.GetComponent<TransformComponent>().Position = glm::vec3(1.0f, 0.0f, 5.0f);
auto cube2 = MainScene.AddEntity("Cube1");
auto& rendercube2 = cube2.AddComponent<Render3DComponent>();
rendercube2.mesh = *(Model->renderable->mesh);
// create an ambient light source
auto AmbientLight = MainScene.AddEntity("AmbientLight");
auto light = AmbientLight.AddComponent<LightComponent>();
light.Color = glm::vec3(1.0f);
light.Strength = 1.0f;
Selected = (entt::entity)-1;
}
void Update() override
{
}
void FixedUpdate() override
{
}
void Stop() override
{
}
private:
std::shared_ptr<Project> CurrentProject = nullptr;
Scene MainScene;
Framebuffer* framebuffer;
SceneObject* Model;
Entity cube;
entt::entity Selected;
friend class Editor;
};

View File

@ -0,0 +1,14 @@
#pragma once
#include <imgui.h>
#include <string>
class EditorWindow {
public:
EditorWindow(const std::string& name ) { ImGui::Begin(name.c_str()); }
~EditorWindow() { ImGui::End(); }
};

View File

@ -0,0 +1,64 @@
#pragma once
#include <imgui.h>
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_glfw.h>
#include <ImGuizmo.h>
#include "../../src/YoggieEngine.h"
class GUIRenderer {
public:
GUIRenderer(YoggieEngine::NativeWindow& window ) {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_DockingEnable;
io.Fonts->AddFontFromFileTTF("build/Debug/Fonts/Roboto-Regular.ttf", 18);
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window.GetGLFWHandle(), true);
ImGui_ImplOpenGL3_Init("#version 440");
}
void Begin ()
{
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
ImGuizmo::SetOrthographic(true);
ImGuizmo::BeginFrame();
}
void End()
{
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* last_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(last_context);
}
}
~GUIRenderer(){
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
};

145
Editor/src/UI/MainMenuBar.h Normal file
View File

@ -0,0 +1,145 @@
#pragma once
#include <imgui.h>
class MainMenuBar {
public:
MainMenuBar() { ImGui::BeginMainMenuBar(); }
void ApplicationMenu(std::unique_ptr<Project>& project) {
if (ImGui::BeginMenu("Application")) {
if (ImGui::MenuItem("Load Project"))
{
nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
Project::LoadProject(path, project);
AssetManager::setAssetPath(project.get()->GetProjectDirectory());
AssetManager::BuildAssetView();
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Save project as...")) {
nfdresult_t result = NFD_SaveDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
std::cout << "Save as: " << path << std::endl;
Project::SaveProject(path, *project.get());
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Preferences"))
{
}
if (ImGui::MenuItem("Exit"))
{
// TODO: Exit application
}
ImGui::EndMenu();
}
}
void SceneMenu(std::unique_ptr<Project>& project, Scene& scene) {
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);
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
AssetManager::LoadFromSource(
path,
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):
AssetManager::LoadFromAssetFile(path);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
break;
}
}
ImGui::EndMenu();
}
}
~MainMenuBar() { ImGui::EndMainMenuBar(); }
private:
char* path = nullptr;
};

View File

@ -1,219 +0,0 @@
#include "widgets.h"
#include "EditorConsole.h"
#include <iostream>
#include "../../YoggieEngine/src/Scene/Components.h"
#include "../../YoggieEngine/src/Scene/Entity.h"
#include "../AssetManagement/AssetManager.h"
class Editor;
void ComponentView(const std::string& componentName, voidFunction func)
{
ImGuiWindowFlags_ window_flags = ImGuiWindowFlags_None;
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
ImGui::BeginChild(componentName.c_str());
func();
ImGui::EndChild();
ImGui::PopStyleVar();
}
void Inspector(entt::entity ent , Scene& scene) {
ImGui::Begin("Inspector");
static char* names[] = { "Script Component", "Camera Component" };
static float Zoom = 90;
static glm::vec3 Position = glm::vec3(0.0f, 0.0f, 0.0f);
static glm::vec3 Rotation = glm::vec3(0.0f, 0.0f, 0.0f);
if (scene.getReg().valid(ent)) {
Entity entity = Entity(ent, &scene);
if (ImGui::Button("Add Component"))
ImGui::OpenPopup("Component picker");
ImGui::SameLine();
if (ImGui::BeginPopup("Component picker")) {
for (int i = 0; i < IM_ARRAYSIZE(names); i++)
if (ImGui::MenuItem(names[i])) {
std::cout << "Add a " << names[i] << " to "
<< entity.GetComponent<IdentifierComponent>().name << std::endl;
}
ImGui::EndPopup();
}
ImGui::NewLine();
auto component = entity.GetComponent<IdentifierComponent>();
char* buf = new char(component.name.size());
strcpy(buf, component.name.c_str());
ImGui::InputText("Name:",buf , sizeof(buf), ImGuiInputTextFlags_ReadOnly);
if (entity.HasComponent<TransformComponent>()) {
auto& transform = entity.GetComponent<TransformComponent>();
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat3("Position", glm::value_ptr(transform.Position), 0.01f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.01f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform.Scale), 0.01f, 0.0f);
}
}
if (entity.HasComponent<Render3DComponent>()) {
auto& render3d = entity.GetComponent<Render3DComponent>();
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(render3d.color));
}
}
if (entity.HasComponent<LightComponent>()) {
auto& light = entity.GetComponent<LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat("Strength", &light.Strength, 0.001f);
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
}
}
if (entity.HasComponent <CameraComponent>()) {
auto& camera = entity.GetComponent<CameraComponent>();
ComponentView("Camera", [] {
ImGui::SliderFloat("Zoom", &Zoom, 10, 190);
ImGui::InputFloat3("Position:", &Position[0]);
ImGui::InputFloat3("Rotation:", &Rotation[0]);
});
}
if (entity.HasComponent<ScriptComponent>()) {
ComponentView("Scripting", [] {
ImGui::LabelText("##--", "Hello scripting");
});
}
}
ImGui::End();
}
void SceneExplorer(entt::entity& selected, Scene& scene )
{
ImGui::Begin("Scene Explorer");
scene.getReg().each([&](entt::entity enttNumber) {
Entity entity = Entity(enttNumber, &scene);
auto id = entity.GetComponent<IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), enttNumber == selected )) {
selected = enttNumber;
}
});
ImGui::End();
}
void Viewport(Framebuffer& framebuffer) {
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar ;
ImGui::Begin("Viewport", false, viewportWindowFlags);
ImGui::Image((void*)(intptr_t)framebuffer.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));
ImGui::End();
}
void GamePort(Framebuffer& framebuffer)
{
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar;
ImGui::Begin("Game", false, viewportWindowFlags);
ImGui::Image((void*)(intptr_t)framebuffer.GetColourAttachment(), { ImGui::GetWindowWidth(), ImGui::GetWindowHeight() });
ImGui::End();
}
void Settings() {
ImGui::Begin("Settings");
ImGui::LabelText("##title-settings", "Fine grain control over your engine... ");
ImGui::End();
}
auto console = EditorConsole();
void Console() {
ImGui::Begin("Console", false);
console.Draw();
ImGui::End();
}
void AssetsFinder() {
static YoggieEngine::Texture folderIcon ("rsc/folderIcon.png");
static YoggieEngine::Texture AssetIcon("rsc/assetIcon.png");
static int iconSize = 60;
ImGui::Begin("Asset-Finder", false);
ImGui::DragInt("IconSize", &iconSize, 1, 30, 90);
if (ImGui::BeginTable("##resources", 3))
{
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.f, 0.f, 0.f));
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));
int row = 0;
int column = 0 ;
for (auto& asset : AssetManager::assets) {
if (column % 3 == 0) {
ImGui::TableNextRow();
column = 0;
row++;
}
ImGui::TableSetColumnIndex(column);
if (asset.isFolder) {
ImGui::ImageButton(
(ImTextureID)folderIcon.GetID(),
ImVec2{ (float)iconSize,(float)iconSize });
ImGui::Text(asset.GetName(), row);
}
else {
ImGui::ImageButton(
(ImTextureID)AssetIcon.GetID(),
ImVec2{ (float)iconSize, (float)iconSize });
ImGui::Text(asset.GetName(), row);
}
column++;
}
ImGui::PopStyleColor(3);
ImGui::EndTable();
}
ImGui::End();
}

View File

@ -1,28 +1,240 @@
#pragma once #pragma once
#include <glm/glm.hpp>
#include <imgui.h>
#include <string> #include <string>
#include <entt/entt.hpp> #include <glm/glm.hpp>
#include <entt/entity/fwd.hpp>
#include <imgui.h>
#include "../../libs/guizmo/ImGuizmo.h" #include "../../libs/guizmo/ImGuizmo.h"
#include "../../YoggieEngine/src/YoggieEngine.h" #include "../../YoggieEngine/src/YoggieEngine.h"
#include "../../src/Scene/Entity.h"
#include "EditorWindow.h"
#include "EditorConsole.h"
#include "../Project/Project.h"
#include "../AssetManagement/AssetManager.h"
typedef void ( *voidFunction ) (void); typedef void ( *voidFunction ) (void);
using namespace YoggieEngine; using namespace YoggieEngine;
void ComponentView(const std::string& componentName, voidFunction func); inline void ComponentView(const std::string& componentName, voidFunction func)
{
ImGuiWindowFlags_ window_flags = ImGuiWindowFlags_None;
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
ImGui::BeginChild(componentName.c_str());
void Inspector(entt::entity entity, Scene& scene); func();
void SceneExplorer(entt::entity& selected, Scene& scene); ImGui::EndChild();
ImGui::PopStyleVar();
}
void Viewport(Framebuffer& framebuffer); class Inspector : EditorWindow {
public:
Inspector() : EditorWindow("Inspector") {}
void GamePort(Framebuffer& framebuffer); void AddComponentDropDown(Entity& selected )
{
static char* names[] = { "Script Component", "Camera Component" };
if (ImGui::Button("Add Component"))
ImGui::OpenPopup("Component picker");
void Settings(); ImGui::SameLine();
if (ImGui::BeginPopup("Component picker")) {
void Console(); for (int i = 0; i < IM_ARRAYSIZE(names); i++)
if (ImGui::MenuItem(names[i])) {
std::cout << "Add a " << names[i] << " to "
<< selected.GetComponent<IdentifierComponent>().name << std::endl;
}
void AssetsFinder(); ImGui::EndPopup();
}
ImGui::NewLine();
}
void ShowComponents(Entity& selected)
{
auto component = selected.GetComponent<IdentifierComponent>();
char* buf = new char(component.name.size());
strcpy(buf, component.name.c_str());
ImGui::InputText("Name:", buf, sizeof(buf), ImGuiInputTextFlags_ReadOnly);
if (selected.HasComponent<TransformComponent>()) {
auto& transform = selected.GetComponent<TransformComponent>();
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat3("Position", glm::value_ptr(transform.Position), 0.01f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.01f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform.Scale), 0.01f, 0.0f);
}
}
if (selected.HasComponent<Render3DComponent>()) {
auto& render3d = selected.GetComponent<Render3DComponent>();
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(render3d.color));
}
}
if (selected.HasComponent<LightComponent>()) {
auto& light = selected.GetComponent<LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat("Strength", &light.Strength, 0.001f);
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
}
}
if (selected.HasComponent <CameraComponent>()) {
auto& camera = selected.GetComponent<CameraComponent>();
static float Zoom = 90;
static glm::vec3 Position, Rotation = glm::vec3(0.0f);
ComponentView("Camera", [] {
ImGui::SliderFloat("Zoom", &Zoom, 10, 190);
ImGui::InputFloat3("Position:", &Position[0]);
ImGui::InputFloat3("Rotation:", &Rotation[0]);
});
}
if (selected.HasComponent<ScriptComponent>()) {
ComponentView("Scripting", [] {
ImGui::LabelText("##--", "Hello scripting");
});
}
}
};
class SceneExplorer : EditorWindow {
public:
SceneExplorer(entt::entity& selected , Scene& scene) : EditorWindow("SceneExplorer") {
scene.getReg().each([&](entt::entity enttNumber) {
Entity entity = Entity(enttNumber, &scene);
auto id = entity.GetComponent<IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), enttNumber == selected)) {
selected = enttNumber;
}
});
}
};
class Viewport : EditorWindow {
public:
Viewport (Scene& scene) : EditorWindow("SceneView") {
Framebuffer framebuffer = Framebuffer((int)ImGui::GetWindowWidth(),(int)ImGui::GetWindowHeight());
Renderer renderer = Renderer();
renderer.Prepare(scene);
renderer.Render(&framebuffer, scene);
ImGui::Image(
(void*)(intptr_t)framebuffer.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));
}
};
class Settings : EditorWindow {
public:
Settings() : EditorWindow("Settings") {
ImGui::LabelText("##title-settings", "Fine grain control over your engine... ");
}
};
class ProjectInfo : EditorWindow {
public:
ProjectInfo(Project& project) : EditorWindow("Project Info") {
ImGui::Text("Project: %s", project.GetName().c_str());
ImGui::Text("Directory: %s", project.GetProjectDirectory().u8string().c_str());
}
};
class Console : EditorWindow {
public:
Console() : EditorWindow("Console") {
s_console = std::make_unique<EditorConsole>();
}
void Show() {
s_console.get()->Draw();
}
private:
std::unique_ptr<EditorConsole> s_console;
};
class AssetFinder : EditorWindow {
public:
AssetFinder() : EditorWindow("Assets") {
ImGui::DragInt("IconSize", &iconSize, 1, 30, 90);
if (ImGui::BeginTable("##resources", 3))
{
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.f, 0.f, 0.f));
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));
int row = 0;
int column = 0;
for (auto& asset : AssetManager::assets) {
if (column % 3 == 0) {
ImGui::TableNextRow();
column = 0;
row++;
}
ImGui::TableSetColumnIndex(column);
if (asset.isFolder) {
ImGui::ImageButton(
(ImTextureID)folderIcon.GetID(),
ImVec2{ (float)iconSize,(float)iconSize });
ImGui::Text(asset.GetName(), row);
}
else {
ImGui::ImageButton(
(ImTextureID)AssetIcon.GetID(),
ImVec2{ (float)iconSize, (float)iconSize });
ImGui::Text(asset.GetName(), row);
}
column++;
}
ImGui::PopStyleColor(3);
ImGui::EndTable();
}
}
private:
Texture folderIcon = Texture("rsc/folderIcon.png");
Texture AssetIcon = Texture("rsc/assetIcon.png");
int iconSize = 60;
};

View File

@ -1,8 +1,5 @@
#include "../../YoggieEngine/src/EntryPoint.h" #include "../../YoggieEngine/src/EntryPoint.h"
#include <imgui.h> #include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_glfw.h>
#include <ImGuizmo.h>
#include <nfd.h> #include <nfd.h>
@ -10,36 +7,37 @@
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include "UI/GUIRenderer.h"
#include "UI/Widgets.h" #include "UI/Widgets.h"
#include "Project/Project.h" #include "Project/Project.h"
#include "SceneSerializer.h" #include "SceneSerializer.h"
#include "EditorContext.h"
#include "SceneRuntime.h"
#include "AssetManagement/AssetManager.h" #include "AssetManagement/AssetManager.h"
#include "UI/MainMenuBar.h"
const unsigned int MS_PER_UPDATE = 2; const unsigned int MS_PER_UPDATE = 2;
void CreateTestProject(std::unique_ptr<Project>& project, Scene& scene);
class Editor : public Application { class Editor : public Application {
public: public:
Editor() : Application("Editor") {} Editor() : Application("Editor") {}
void Run() override void Run() override
{ {
BarinkWindow mainWindow = BarinkWindow(1200, 700); auto NativeEditorWindow = NativeWindow(1200, 700);
InputSystem = new InputManager(); //auto renderer = Renderer();
renderer = new Renderer(); auto GuiRenderer = GUIRenderer(NativeEditorWindow);
InputSystem->attach(&mainWindow); Selected = (entt::entity)-1;
InitImGui(mainWindow); CreateTestProject(CurrentProject, ActiveScene);
activeRuntime.Start(); ActiveScene.Start();
double previous = glfwGetTime(); double previous = glfwGetTime();
double lag = 0.0; double lag = 0.0;
renderer->Prepare(activeRuntime.MainScene);
while (!mainWindow.WindowShouldClose()) while (!NativeEditorWindow.WindowShouldClose())
{ {
double current = glfwGetTime(); double current = glfwGetTime();
@ -47,81 +45,29 @@ public:
previous = current; previous = current;
lag += elapsed; lag += elapsed;
NativeEditorWindow.Poll();
InputSystem->PollEvents();
while (lag >= MS_PER_UPDATE) while (lag >= MS_PER_UPDATE)
{ {
activeRuntime.Update(); ActiveScene.Update();
lag -= MS_PER_UPDATE; lag -= MS_PER_UPDATE;
} }
renderer->Render(activeRuntime.framebuffer, activeRuntime.MainScene); // renderer.Render(framebuffer, ActiveScene);
ImGuiBegin();
GuiRenderer.Begin();
RenderGUI(); RenderGUI();
ImGuiEnd(); GuiRenderer.End();
mainWindow.SwapBuffers(); NativeEditorWindow.SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
} }
activeRuntime.Stop(); ActiveScene.Stop();
delete InputSystem;
delete renderer;
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
void InitImGui(BarinkWindow& window )
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_DockingEnable;
io.Fonts->AddFontFromFileTTF("build/Debug/Fonts/Roboto-Regular.ttf", 18);
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window.windowptr(), true);
ImGui_ImplOpenGL3_Init("#version 440");
}
void ImGuiBegin() {
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
ImGuizmo::SetOrthographic(true);
ImGuizmo::BeginFrame();
}
void ImGuiEnd() {
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* last_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(last_context);
}
} }
@ -129,153 +75,47 @@ public:
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
// Show a menu bar // Show a menu bar
ImGui::BeginMainMenuBar();
if (ImGui::BeginMenu("Application")) {
if (ImGui::MenuItem("Load Project"))
{ {
nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path); MainMenuBar menuBar= MainMenuBar();
switch (result) { menuBar.ApplicationMenu(CurrentProject);
case(NFD_OKAY): menuBar.SceneMenu(CurrentProject, ActiveScene);
Project::LoadProject(path, activeRuntime.CurrentProject);
AssetManager::setAssetPath(activeRuntime.CurrentProject.get()->GetProjectDirectory());
AssetManager::BuildAssetView();
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
} }
}
if (ImGui::MenuItem("Save project as...")) {
nfdresult_t result = NFD_SaveDialog({ "yproj" }, NULL, &savePath);
switch (result) {
case(NFD_OKAY):
std::cout << "Save as: " << savePath << std::endl;
Project::SaveProject(savePath, *activeRuntime.CurrentProject.get());
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Preferences"))
{ {
ProjectInfo projectInfo(*(CurrentProject.get()));
} }
if (ImGui::MenuItem("Exit"))
{ {
// TODO: Exit application Viewport sceneview = Viewport(ActiveScene);
} }
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scene")) {
if (ImGui::MenuItem("Save scene"))
{ {
nfdresult_t result = NFD_SaveDialog({ "yscene" }, NULL, &scenePath); SceneExplorer explorer(Selected, ActiveScene);
switch (result) {
case(NFD_OKAY):
SaveScene(scenePath, activeRuntime.MainScene);
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, &openScenePath); Inspector inspector = Inspector();
switch (result) { if (ActiveScene.getReg().valid(Selected)) {
case (NFD_OKAY): Entity SelectedEntity = Entity(Selected, &ActiveScene);
LoadScene(openScenePath, activeRuntime.MainScene); inspector.AddComponentDropDown(SelectedEntity);
break; inspector.ShowComponents(SelectedEntity);
case(NFD_CANCEL): }
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
} }
}
if (ImGui::MenuItem("Add Entity"))
{ {
activeRuntime.MainScene.AddEntity("New Entity");
}
if (ImGui::MenuItem("Import Model"))
{
auto result = NFD_OpenDialog( "obj,fbx,gltf" , NULL, &modelImportPath);
switch (result) {
case(NFD_OKAY):
// Import Model
AssetManager::LoadFromSource(modelImportPath, activeRuntime.CurrentProject.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, &modelImportPath);
switch (result) {
case(NFD_OKAY):
AssetManager::LoadFromAssetFile(modelImportPath);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
break;
}
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
ImGui::Begin("ProjectInfo");
ImGui::Text("Project: %s", activeRuntime.CurrentProject.get()->GetName().c_str());
ImGui::Text("Directory: %s", activeRuntime.CurrentProject.get()->GetProjectDirectory().u8string().c_str());
ImGui::End();
//ShowStats();
Viewport(*activeRuntime.framebuffer);
GamePort(*activeRuntime.framebuffer);
SceneExplorer(activeRuntime.Selected, activeRuntime.MainScene);
Inspector(activeRuntime.Selected, activeRuntime.MainScene);
Settings(); Settings();
AssetsFinder(); }
Console();
{
AssetFinder assetsView = AssetFinder();
}
{
Console console = Console();
console.Show();
}
ImGui::ShowDemoWindow(); ImGui::ShowDemoWindow();
ImGui::ShowMetricsWindow(); ImGui::ShowMetricsWindow();
@ -284,14 +124,9 @@ public:
private: private:
EditorContext context; std::unique_ptr<Project> CurrentProject;
EditorRuntime activeRuntime ; Scene ActiveScene;
char* path = nullptr; entt::entity Selected;
char* savePath = nullptr;
char* scenePath = nullptr;
char* openScenePath = nullptr;
char* modelImportPath = nullptr;
}; };
@ -301,12 +136,34 @@ YoggieEngine::Application* CreateApplication() {
} }
void CreateTestProject(std::unique_ptr<Project>& project, Scene& scene ) {
project = std::make_unique<Project>();
std::string path = (std::filesystem::current_path()).string();
project.get()->setProjectDirectory(path);
AssetManager::Init();
AssetManager::setAssetPath(project.get()->GetProjectDirectory());
AssetManager::BuildAssetView();
// Create a level and load it as the current level
auto importer = ModelImporter();
// Create a cube
auto model = importer.Import("build/Debug/Models/Cube.obj");
auto cube = scene.AddEntity("cube");
auto& render3DComponent = cube.AddComponent<Render3DComponent>();
render3DComponent.mesh = *(model->renderable->mesh);
cube.GetComponent<TransformComponent>().Position = glm::vec3(1.0f, 0.0f, 5.0f);
auto cube2 = scene.AddEntity("Cube1");
auto& rendercube2 = cube2.AddComponent<Render3DComponent>();
rendercube2.mesh = *(model->renderable->mesh);
// create an ambient light source
auto AmbientLight = scene.AddEntity("AmbientLight");
auto light = AmbientLight.AddComponent<LightComponent>();
light.Color = glm::vec3(1.0f);
light.Strength = 1.0f;
}

View File

@ -2,9 +2,6 @@
#include "YoggieEngine.h" #include "YoggieEngine.h"
namespace YoggieEngine { namespace YoggieEngine {
// forward declaration
class InputManager;
class Application { class Application {
public: public:
Application(const std::string& name); Application(const std::string& name);
@ -13,21 +10,7 @@ namespace YoggieEngine {
protected: protected:
std::string m_AppName; std::string m_AppName;
Renderer* renderer = nullptr;
InputManager* InputSystem = nullptr;
friend class ApplicationRuntime; friend class ApplicationRuntime;
}; };
class ApplicationRuntime {
public:
virtual void Start() = 0;
virtual void Update() = 0;
virtual void FixedUpdate() = 0;
virtual void Stop() = 0;
};
}; };

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "Application.h" #include "YoggieEngine.h"
extern YoggieEngine::Application* CreateApplication(); extern YoggieEngine::Application* CreateApplication();

View File

@ -55,9 +55,6 @@ namespace YoggieEngine {
{ {
std::cout << "Framebuffer is incomplete!" << std::endl; std::cout << "Framebuffer is incomplete!" << std::endl;
} }
else {
std::cout << "Framebuffer is complete!" << std::endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -67,7 +64,7 @@ namespace YoggieEngine {
Framebuffer::~Framebuffer() Framebuffer::~Framebuffer()
{ {
glDeleteTextures(1, &ColourAttachment); glDeleteTextures(1, &ColourAttachment);
glDeleteRenderbuffers(1, &DepthAttachment); glDeleteTextures(1, &DepthAttachment);
glDeleteFramebuffers(1, &Id); glDeleteFramebuffers(1, &Id);
} }
} }

View File

@ -6,10 +6,8 @@
namespace YoggieEngine { namespace YoggieEngine {
Texture::Texture(const std::string texturePath) { Texture::Texture(const std::string texturePath) {
int width, height, channels; int width, height, channels;
unsigned char* data = stbi_load(texturePath.c_str(), &width, &height, &channels, 0); unsigned char* data = stbi_load(texturePath.c_str(), &width, &height, &channels, 0);
std::cout << channels << std::endl;
if (data) { if (data) {
glGenTextures(1, &Id); glGenTextures(1, &Id);

View File

@ -1,17 +1,9 @@
#include <YoggieEngine.h> #include <YoggieEngine.h>
#include "Window.h" #include "Window.h"
namespace YoggieEngine { namespace YoggieEngine {
bool BarinkWindow::InitGLFW() { void LoadGLExtensions();
if (!glfwInit())
{
spdlog::error("Failed to initialise GLFW!");
return false;
}
return true; NativeWindow::NativeWindow(const int width, const int height) :
}
BarinkWindow::BarinkWindow(const int width, const int height) :
Width(width), Height(height), FullScreen(false) Width(width), Height(height), FullScreen(false)
{ {
if (InitGLFW() == false) { if (InitGLFW() == false) {
@ -20,12 +12,13 @@ namespace YoggieEngine {
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_TRUE); glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_TRUE);
// No window decorations such as a border, a close widget
// glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
// glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
// Disable resizing the window
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
if( FullScreen )
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
if( !Resizable)
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
if (!VSync)
glfwSwapInterval(0);
window = glfwCreateWindow(Width, Height, "BarinkEngine", NULL, NULL); window = glfwCreateWindow(Width, Height, "BarinkEngine", NULL, NULL);
@ -36,53 +29,58 @@ namespace YoggieEngine {
return; return;
} }
glfwMakeContextCurrent(window); SetContext();
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
spdlog::error("Failed to initialize GLAD!\n");
exit(-1);
}
// Set vsync off !!
glfwSwapInterval(0);
VulkanSupported = glfwVulkanSupported();
glfwGetFramebufferSize(window, &Width, &Height); glfwGetFramebufferSize(window, &Width, &Height);
glViewport(0, 0, Width, Height); LoadGLExtensions();
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
} }
BarinkWindow::~BarinkWindow() { void NativeWindow::SetViewPort(int width, int height) {
glViewport(0, 0, width, height);
}
NativeWindow::~NativeWindow() {
glfwTerminate(); glfwTerminate();
} }
GLFWwindow* BarinkWindow::windowptr() bool NativeWindow::WindowShouldClose() {
{
return window;
}
bool BarinkWindow::WindowShouldClose() {
return glfwWindowShouldClose(window); return glfwWindowShouldClose(window);
} }
void BarinkWindow::Poll() void NativeWindow::SetContext()
{
glfwMakeContextCurrent(window);
}
void NativeWindow::Poll()
{ {
glfwPollEvents(); glfwPollEvents();
} }
void BarinkWindow::SwapBuffers() void NativeWindow::SwapBuffers()
{ {
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
void BarinkWindow::ReceiveEvent(Event& incident) bool NativeWindow::InitGLFW()
{ {
//std::cout << "EVENT RECEIVED: " << incident.name << std::endl; if (!glfwInit())
{
spdlog::error("Failed to initialise GLFW!");
return false;
}
return true;
}
void LoadGLExtensions()
{
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
spdlog::error("Failed to initialize GLAD!\n");
exit(-1);
}
} }
} }

View File

@ -7,27 +7,35 @@
#include "../EventSystem/Event.h" #include "../EventSystem/Event.h"
#include "../EventSystem/EventListener.h" #include "../EventSystem/EventListener.h"
namespace YoggieEngine { namespace YoggieEngine {
class BarinkWindow : EventListener { class NativeWindow {
private:
GLFWwindow* window;
bool FullScreen;
bool VulkanSupported;
int Width, Height;
static bool InitGLFW();
public: public:
BarinkWindow(const int width, const int height); NativeWindow(const int width, const int height);
~BarinkWindow(); ~NativeWindow();
GLFWwindow* windowptr();
void ReceiveEvent(Event& incident) override;
bool WindowShouldClose(); bool WindowShouldClose();
void SetViewPort(int width , int height);
void Poll(); void Poll();
void SwapBuffers(); void SwapBuffers();
GLFWwindow* GetGLFWHandle() { return window; }
const int getWidth()const { return Width; }
const int getHeight()const { return Height; }
private:
GLFWwindow* window;
bool FullScreen = false;
bool Resizable = true;
bool VSync = false;
int Width, Height;
void SetContext();
static bool InitGLFW();
}; };
} }

View File

@ -23,4 +23,26 @@ namespace YoggieEngine{
return entity; return entity;
} }
void Scene::Start()
{
// Execute start functions in scripts etc....
}
void Scene::Update()
{
// Execute Update functions in scripts etc....
}
void Scene::FixedUpdate()
{
// Execute step through physics simulation step....
}
void Scene::Stop()
{
// Execute stop functions in scripts etc....
}
} }

View File

@ -9,6 +9,11 @@ namespace YoggieEngine {
Entity AddEntity(std::string name); Entity AddEntity(std::string name);
void Start();
void Update();
void FixedUpdate();
void Stop();
entt::registry& getReg() { return m_registry; } entt::registry& getReg() { return m_registry; }
private: private:

View File

@ -40,7 +40,5 @@ extern "C"
#include "EventSystem/EventEmitter.h" #include "EventSystem/EventEmitter.h"
#include "EventSystem/EventListener.h" #include "EventSystem/EventListener.h"
#include "Input/InputManager.h"
#include "Scene/Scene.h" #include "Scene/Scene.h"
#include "Application.h" #include "Application.h"