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

View File

@ -14,7 +14,7 @@ public:
const std::filesystem::path GetProjectDirectory() { return ProjectDirectory; }
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:
std::string Name;
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
#include <glm/glm.hpp>
#include <imgui.h>
#include <string>
#include <entt/entt.hpp>
#include <entt/entity/fwd.hpp>
#include <glm/glm.hpp>
#include <imgui.h>
#include "../../libs/guizmo/ImGuizmo.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);
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 <imgui.h>
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_glfw.h>
#include <ImGuizmo.h>
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include <nfd.h>
@ -10,36 +7,37 @@
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "UI/GUIRenderer.h"
#include "UI/Widgets.h"
#include "Project/Project.h"
#include "SceneSerializer.h"
#include "EditorContext.h"
#include "SceneRuntime.h"
#include "AssetManagement/AssetManager.h"
#include "UI/MainMenuBar.h"
const unsigned int MS_PER_UPDATE = 2;
void CreateTestProject(std::unique_ptr<Project>& project, Scene& scene);
class Editor : public Application {
public:
Editor() : Application("Editor") {}
void Run() override
{
BarinkWindow mainWindow = BarinkWindow(1200, 700);
InputSystem = new InputManager();
renderer = new Renderer();
auto NativeEditorWindow = NativeWindow(1200, 700);
//auto renderer = 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 lag = 0.0;
renderer->Prepare(activeRuntime.MainScene);
while (!mainWindow.WindowShouldClose())
while (!NativeEditorWindow.WindowShouldClose())
{
double current = glfwGetTime();
@ -47,235 +45,77 @@ public:
previous = current;
lag += elapsed;
InputSystem->PollEvents();
NativeEditorWindow.Poll();
while (lag >= MS_PER_UPDATE)
{
activeRuntime.Update();
ActiveScene.Update();
lag -= MS_PER_UPDATE;
}
renderer->Render(activeRuntime.framebuffer, activeRuntime.MainScene);
// renderer.Render(framebuffer, ActiveScene);
ImGuiBegin();
RenderGUI();
ImGuiEnd();
mainWindow.SwapBuffers();
GuiRenderer.Begin();
RenderGUI();
GuiRenderer.End();
NativeEditorWindow.SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
}
activeRuntime.Stop();
delete InputSystem;
delete renderer;
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
ActiveScene.Stop();
}
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);
}
}
void RenderGUI() {
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
// Show a menu bar
{
MainMenuBar menuBar= MainMenuBar();
menuBar.ApplicationMenu(CurrentProject);
menuBar.SceneMenu(CurrentProject, ActiveScene);
}
ImGui::BeginMainMenuBar();
{
ProjectInfo projectInfo(*(CurrentProject.get()));
}
if (ImGui::BeginMenu("Application")) {
{
Viewport sceneview = Viewport(ActiveScene);
}
if (ImGui::MenuItem("Load Project"))
{
nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
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"))
{
}
if (ImGui::MenuItem("Exit"))
{
// TODO: Exit application
}
ImGui::EndMenu();
{
SceneExplorer explorer(Selected, ActiveScene);
}
if (ImGui::BeginMenu("Scene")) {
if (ImGui::MenuItem("Save scene"))
{
nfdresult_t result = NFD_SaveDialog({ "yscene" }, NULL, &scenePath);
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;
}
{
Inspector inspector = Inspector();
if (ActiveScene.getReg().valid(Selected)) {
Entity SelectedEntity = Entity(Selected, &ActiveScene);
inspector.AddComponentDropDown(SelectedEntity);
inspector.ShowComponents(SelectedEntity);
}
if (ImGui::MenuItem("Load scene"))
{
auto result = NFD_OpenDialog({ "yscene" }, NULL, &openScenePath);
switch (result) {
case (NFD_OKAY):
LoadScene(openScenePath, activeRuntime.MainScene);
break;
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();
}
{
Settings();
}
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();
AssetsFinder();
Console();
{
AssetFinder assetsView = AssetFinder();
}
{
Console console = Console();
console.Show();
}
ImGui::ShowDemoWindow();
ImGui::ShowMetricsWindow();
@ -284,14 +124,9 @@ public:
private:
EditorContext context;
EditorRuntime activeRuntime ;
char* path = nullptr;
char* savePath = nullptr;
char* scenePath = nullptr;
char* openScenePath = nullptr;
char* modelImportPath = nullptr;
std::unique_ptr<Project> CurrentProject;
Scene ActiveScene;
entt::entity Selected;
};
@ -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"
namespace YoggieEngine {
// forward declaration
class InputManager;
class Application {
public:
Application(const std::string& name);
@ -13,21 +10,7 @@ namespace YoggieEngine {
protected:
std::string m_AppName;
Renderer* renderer = nullptr;
InputManager* InputSystem = nullptr;
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
#include "Application.h"
#include "YoggieEngine.h"
extern YoggieEngine::Application* CreateApplication();

View File

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

View File

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

View File

@ -1,17 +1,9 @@
#include <YoggieEngine.h>
#include "Window.h"
namespace YoggieEngine {
bool BarinkWindow::InitGLFW() {
if (!glfwInit())
{
spdlog::error("Failed to initialise GLFW!");
return false;
}
return true;
}
BarinkWindow::BarinkWindow(const int width, const int height) :
void LoadGLExtensions();
NativeWindow::NativeWindow(const int width, const int height) :
Width(width), Height(height), FullScreen(false)
{
if (InitGLFW() == false) {
@ -20,12 +12,13 @@ namespace YoggieEngine {
glfwWindowHint(GLFW_DOUBLEBUFFER, 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);
@ -36,53 +29,58 @@ namespace YoggieEngine {
return;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
spdlog::error("Failed to initialize GLAD!\n");
exit(-1);
}
// Set vsync off !!
glfwSwapInterval(0);
VulkanSupported = glfwVulkanSupported();
SetContext();
glfwGetFramebufferSize(window, &Width, &Height);
glViewport(0, 0, Width, Height);
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
LoadGLExtensions();
}
BarinkWindow::~BarinkWindow() {
void NativeWindow::SetViewPort(int width, int height) {
glViewport(0, 0, width, height);
}
NativeWindow::~NativeWindow() {
glfwTerminate();
}
GLFWwindow* BarinkWindow::windowptr()
{
return window;
}
bool BarinkWindow::WindowShouldClose() {
bool NativeWindow::WindowShouldClose() {
return glfwWindowShouldClose(window);
}
void BarinkWindow::Poll()
void NativeWindow::SetContext()
{
glfwMakeContextCurrent(window);
}
void NativeWindow::Poll()
{
glfwPollEvents();
}
void BarinkWindow::SwapBuffers()
void NativeWindow::SwapBuffers()
{
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/EventListener.h"
namespace YoggieEngine {
class BarinkWindow : EventListener {
private:
GLFWwindow* window;
bool FullScreen;
bool VulkanSupported;
int Width, Height;
static bool InitGLFW();
class NativeWindow {
public:
BarinkWindow(const int width, const int height);
~BarinkWindow();
NativeWindow(const int width, const int height);
~NativeWindow();
GLFWwindow* windowptr();
void ReceiveEvent(Event& incident) override;
bool WindowShouldClose();
void SetViewPort(int width , int height);
void Poll();
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;
}
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);
void Start();
void Update();
void FixedUpdate();
void Stop();
entt::registry& getReg() { return m_registry; }
private:

View File

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