Editor Refactor

This refactor of the editor code makes the code more maintainable.

All widget objects have now moved away from RAII and are now just allocated object that live for the entirety of the applications lifetime.
This feels better as I am used to this style plus constantly pushing and popping objects from the stack seems a little wasteful (although I as of right now have no way to prove that it is ).
main
Nigel Barink 2023-01-14 17:27:37 +01:00
parent 79b68fbff1
commit 145338d666
40 changed files with 1138 additions and 1044 deletions

View File

@ -0,0 +1,68 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "EditorWindow.h"
#include "AssetManagement/AssetManager.h"
class AssetFinder : EditorWindow {
public:
AssetFinder() : EditorWindow("Assets") {}
void Draw() override {
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));
YoggieEngine::Texture folderIcon = YoggieEngine::Texture("rsc/folderIcon.png");
YoggieEngine::Texture assetIcon = YoggieEngine::Texture("rsc/assetIcon.png");
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();
const GLuint textures[2]{ assetIcon.GetID(), folderIcon.GetID() };
glDeleteTextures(2, textures);
}
}
private:
int iconSize = 60;
};

View File

@ -0,0 +1,129 @@
#include "SceneSerializer.h"
#include "../../YoggieEngine/src/YoggieEngine.h"
#include <yaml-cpp/yaml.h>
#include <yaml-cpp/node/type.h>
#include <filesystem>
void WriteFile(std::string& emitter, std::filesystem::path path)
{
std::cout << "Writing Scene file to: " << path.u8string() << std::endl;
std::ofstream sceneFile;
sceneFile.open(path.u8string());
sceneFile << emitter.c_str();
sceneFile.close();
}
YAML::Emitter& operator<< (YAML::Emitter& emitter, glm::vec3& vector) {
emitter << YAML::Flow << YAML::BeginSeq << vector.x << vector.y << vector.x << YAML::EndSeq;
return emitter;
}
std::string Serialize(YoggieEngine::Scene& scene) {
YAML::Emitter emitter;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Scene" << YAML::Value << "test-Scene";
emitter << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq;
scene.getReg().each([&emitter, &scene](entt::entity enttNumber) {
YoggieEngine::Entity entity = YoggieEngine::Entity(enttNumber, &scene);
emitter << YAML::BeginMap;
emitter << YAML::Key << "Entity" << YAML::Value << entity.GetComponent<YoggieEngine::IdentifierComponent>().name;
if (entity.HasComponent<YoggieEngine::IdentifierComponent>()) {
emitter << YAML::Key << "Ident";
emitter << YAML::BeginMap;
emitter << YAML::Value << entity.GetComponent<YoggieEngine::IdentifierComponent>().name;
emitter << YAML::EndMap;
}
if (entity.HasComponent<YoggieEngine::TransformComponent>()) {
emitter << YAML::Key << "Transform" << YAML::Value;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Position";
emitter << YAML::Value << entity.GetComponent<YoggieEngine::TransformComponent>().Position;
emitter << YAML::Key << "Rotation";
emitter << YAML::Value << entity.GetComponent<YoggieEngine::TransformComponent>().Rotation;
emitter << YAML::Key << "Scale";
emitter << YAML::Value << entity.GetComponent<YoggieEngine::TransformComponent>().Scale;
emitter << YAML::EndMap;
}
if (entity.HasComponent<YoggieEngine::LightComponent>()) {
emitter << YAML::Key << "Light";
emitter << YAML::Value;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Color";
emitter << YAML::Value << entity.GetComponent<YoggieEngine::LightComponent>().Color;
emitter << YAML::EndMap;
}
emitter << YAML::EndMap;
});
emitter << YAML::EndSeq;
emitter << YAML::EndMap;
return std::string(emitter.c_str());
}
void SaveScene(std::filesystem::path path, YoggieEngine::Scene& scene) {
std::string YAMLString = Serialize(scene);
WriteFile(YAMLString, path);
}
void LoadScene(std::filesystem::path path, YoggieEngine::Scene& scene)
{
auto sceneYAML = YAML::LoadFile(path.u8string());
if (!sceneYAML["Scene"]) {
spdlog::error("Not a scene file!");
return;
}
scene.getReg().clear();
std::string SceneName = sceneYAML["Scene"].as<std::string>();
auto entities = sceneYAML["Entities"];
for (const auto& entity : entities) {
std::string entityID = entity["Ident"].as<std::string>();
YoggieEngine::Entity SE = scene.AddEntity(entityID);
if (entity["Transform"])
{
YoggieEngine::TransformComponent tc = SE.GetComponent <YoggieEngine::TransformComponent> ();
auto positionNode = entity["Transform"]["Position"];
tc.Position = glm::vec3(positionNode[0].as<float>(), positionNode[1].as<float>(), positionNode[2].as<float>());
auto rotationNode = entity["Transform"]["Rotation"];
tc.Rotation = glm::vec3(rotationNode[0].as<float>(), rotationNode[1].as<float>(), rotationNode[2].as<float>());
auto scaleNode = entity["Transform"]["Scale"];
tc.Scale = glm::vec3(scaleNode[0].as<float>(), scaleNode[1].as<float>(), scaleNode[2].as<float>());
}
if (entity["Light"]) {
YoggieEngine::LightComponent lc = SE.AddComponent<YoggieEngine::LightComponent>();
lc.Color = glm::vec3(entity["Light"]["Color"][0].as<float>(), entity["Light"]["Color"][1].as<float>(), entity["Light"]["Color"][2].as<float>());
}
}
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <entt/entity/fwd.hpp>
#include <glm/glm.hpp>
#include <yaml-cpp/yaml.h>
#include <filesystem>
#include "../../YoggieEngine/src/YoggieEngine.h"
void WriteFile(std::string& emitter, std::filesystem::path path);
YAML::Emitter& operator<< (YAML::Emitter& emitter, glm::vec3& vector);
std::string Serialize(YoggieEngine::Scene& scene);
void SaveScene(std::filesystem::path path, YoggieEngine::Scene& scene);
void LoadScene(std::filesystem::path path, YoggieEngine::Scene& scene);

View File

@ -1,22 +1,25 @@
#include "Console.h"
#include <stdio.h>
#include "EditorConsole.h"
EditorConsole::EditorConsole()
: Items(ImVector<char*>()), AutoScroll(false), ScrollToBottom(false)
Console::Console()
: EditorWindow("Console"), Items(ImVector<char*>()), AutoScroll(false), ScrollToBottom(false)
{
AddLog("Hello Editor console!");
}
EditorConsole::~EditorConsole() {
Console::~Console() {
}
void EditorConsole::Draw() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
void Console::Show() {
Draw();
}
for (int i = 0; i < Items.Size; i++)
void Console::Draw() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
for (int i = 0; i < Items.Size; i++)
{
const char* item = Items[i];
ImGui::TextUnformatted(item);
@ -24,7 +27,7 @@ void EditorConsole::Draw() {
}
void EditorConsole::AddLog(const char* fmt, ...) {
void Console::AddLog(const char* fmt, ...) {
char buf[1024];
va_list args;
va_start(args, fmt);

22
Editor/src/Console.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "EditorWindow.h"
#include <imgui.h>
class Console : public EditorWindow {
public:
Console();
~Console();
void Draw() override;
void Show();
void AddLog(const char* fmt, ...);
private:
ImVector<char*> Items;
bool AutoScroll;
bool ScrollToBottom;
};

View File

@ -4,7 +4,7 @@
#include <nfd.h>
#include <iostream>
#include <functional>
#include "Project.h"
#include "Project/Project.h"
struct DialogSpec {
const std::string& id;
const std::string& Title;

26
Editor/src/EditorWindow.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <imgui.h>
#include <string>
class EditorWindow {
public:
EditorWindow (const std::string& name, ImGuiWindowFlags_ flags = ImGuiWindowFlags_None ) : name(name) , flags(flags) {}
void Update()
{
ImGui::Begin(name.c_str(), false, flags);
Draw();
ImGui::End();
}
~EditorWindow() = default;
protected:
std::string name;
private:
ImGuiWindowFlags_ flags;
virtual void Draw() = 0;
};

188
Editor/src/MainMenuBar.cpp Normal file
View File

@ -0,0 +1,188 @@
#include "MainMenuBar.h"
#include <nfd.h>
#include "AssetManagement/AssetManager.h"
MainMenuBar::MainMenuBar()
{
ImGui::BeginMainMenuBar();
}
void MainMenuBar::ApplicationMenu(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.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);
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 MainMenuBar::SceneMenu(Project& project, YoggieEngine::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,
"build/Debug/Assets"//project.get()->GetProjectDirectory() / "Assets"
);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Import MeshAsset (temp)"))
{
auto result = NFD_OpenDialog("mesh", NULL, &path);
switch (result) {
case(NFD_OKAY):
{
YoggieEngine::Mesh* importedMesh = AssetManager::LoadFromAssetFile(path);
if (importedMesh != nullptr)
{
auto full_name = std::filesystem::path(path);
auto importedModel = scene.AddEntity(full_name.filename().u8string());
auto& rendererComponent = importedModel.AddComponent<YoggieEngine::Render3DComponent>();
rendererComponent.mesh = *importedMesh;
}
}
break;
case(NFD_CANCEL):
spdlog::debug("User cancelled action");
break;
case(NFD_ERROR):
spdlog::warn("Something went wrong!");
break;
}
}
ImGui::EndMenu();
}
}
void MainMenuBar::DebugMenu()
{
if (ImGui::BeginMenu("Debug")) {
ImGui::EndMenu();
}
}
void MainMenuBar::SelectMenu() {
if (ImGui::BeginMenu("Select")) {
ImGui::EndMenu();
}
}
void MainMenuBar::WindowMenu() {
if (ImGui::BeginMenu("Window")) {
ImGui::EndMenu();
}
}
void MainMenuBar::Help() {
if (ImGui::BeginMenu("Help")) {
ImGui::EndMenu();
}
}
MainMenuBar::~MainMenuBar()
{
ImGui::EndMainMenuBar();
}

30
Editor/src/MainMenuBar.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <imgui.h>
#include "AssetManagement/SceneSerializer.h"
#include "../../YoggieEngine/src/Scene/Scene.h"
#include "Project/Project.h"
class MainMenuBar {
public:
MainMenuBar();
void ApplicationMenu(Project& project);
void SceneMenu(Project& project, YoggieEngine::Scene& scene);
void DebugMenu();
void SelectMenu();
void WindowMenu();
void Help();
~MainMenuBar();
private:
char* path = nullptr;
};

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

View File

@ -0,0 +1,7 @@
#include "ProjectInfo.h"
void ProjectInfo::Draw()
{
ImGui::Text("Project: %s", project.GetName().c_str());
ImGui::Text("Directory: %s", project.GetProjectDirectory().u8string().c_str());
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "../EditorWindow.h"
#include "Project.h"
class ProjectInfo : public EditorWindow {
public:
ProjectInfo(Project& project) : EditorWindow("Project Info"), project(project) {}
void Draw() override;
private:
Project& project;
};

View File

@ -0,0 +1,48 @@
#include "Settings.h"
void Settings::Draw() {
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);
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "../EditorWindow.h"
class Settings : public EditorWindow {
public:
Settings() : EditorWindow("Settings") {}
void Draw() override;
private:
int selectedGfxAPI = 0;
int selectedPhysicsEngine = 0;
glm::vec3 Gravity = glm::vec3(0.0f, -9.81f, 0.0f);
bool ShowAdvancedOptions = false;
bool DebugEngine = false;
const char* PhysicsEngine[2] = {
"PhysX",
"Jolt Physics"
};
const char* GraphicsAPI[3] = {
"OpenGL",
"Vulkan",
"Metal (Apple)"
};
};

View File

@ -0,0 +1,104 @@
#include "Inspector.h"
void Inspector::Draw()
{
}
void Inspector::AddComponentDropDown(YoggieEngine::Entity& selected)
{
static char* names[] = { "Script Component", "Camera Component", "Light Component" };
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 "
<< selected.GetComponent<YoggieEngine::IdentifierComponent>().name << std::endl;
}
ImGui::EndPopup();
}
ImGui::NewLine();
}
void Inspector::ShowComponents(YoggieEngine::Entity& selected)
{
auto component = selected.GetComponent<YoggieEngine::IdentifierComponent>();
ImGui::InputText("Name:", (char*)component.name.c_str(), component.name.size() * sizeof(char), ImGuiInputTextFlags_ReadOnly);
if (selected.HasComponent<YoggieEngine::TransformComponent>()) {
auto& transform = selected.GetComponent<YoggieEngine::TransformComponent>();
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat3("Position", glm::value_ptr(transform.Position), 0.1f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.1f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform.Scale), 0.1f, 0.0f);
}
if (selected.HasComponent<YoggieEngine::RelationComponent>()) {
ImGui::Text("Has relation");
}
}
if (selected.HasComponent<YoggieEngine::Render3DComponent>()) {
auto& render3d = selected.GetComponent<YoggieEngine::Render3DComponent>();
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(render3d.color));
ImGui::Checkbox("Use static rendering:", &render3d.isStatic);
}
}
static bool deferred = true;
if (selected.HasComponent<YoggieEngine::LightComponent>()) {
auto& light = selected.GetComponent<YoggieEngine::LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
ImGui::Checkbox("Deferred", &deferred);
}
}
if (selected.HasComponent <YoggieEngine::CameraComponent>()) {
auto& camera = selected.GetComponent<YoggieEngine::CameraComponent>();
if (ImGui::CollapsingHeader("Camera")) {
ImGui::DragFloat3("Position:", glm::value_ptr(camera.Position), 0.01f);
ImGui::DragFloat3("Rotation:", glm::value_ptr(camera.Rotation), 0.01f);
}
}
if (selected.HasComponent<YoggieEngine::RigidBody>()) {
auto& rigibody = selected.GetComponent<YoggieEngine::RigidBody>();
if (ImGui::CollapsingHeader("RigidBody")) {
}
}
if (selected.HasComponent<YoggieEngine::ScriptComponent>()) {
ComponentView("Scripting", [] {
ImGui::LabelText("##--", "Hello scripting");
});
}
}
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();
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "../EditorWindow.h"
typedef void (*voidFunction) (void);
inline void ComponentView(const std::string& componentName, voidFunction func);
class Inspector : public EditorWindow {
public:
Inspector() : EditorWindow("Inspector") {}
void Draw()override;
void AddComponentDropDown(YoggieEngine::Entity& selected);
void ShowComponents(YoggieEngine::Entity& selected);
};

View File

@ -0,0 +1,13 @@
#include "SceneExplorer.h"
void SceneExplorer::Draw()
{
scene.getReg().each([&](entt::entity enttNumber) {
YoggieEngine::Entity entity = YoggieEngine::Entity(enttNumber, &scene);
auto id = entity.GetComponent<YoggieEngine::IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), enttNumber == selected)) {
selected = enttNumber;
}
});
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "../EditorWindow.h"
#include "../../src/Scene/Entity.h"
class SceneExplorer : public EditorWindow {
public:
SceneExplorer(entt::entity& selected, YoggieEngine::Scene& scene)
: EditorWindow("SceneExplorer"), scene(scene), selected(selected)
{}
void Draw() override;
private:
entt::entity selected;
YoggieEngine::Scene& scene;
};

View File

@ -0,0 +1,27 @@
#include "RuntimeControls.h"
void RuntimeControls::Draw() {
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();
}
}

View File

@ -0,0 +1,26 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "../EditorWindow.h"
#define RuntimeControlWindowFlags (ImGuiWindowFlags_)(ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse)
struct ButtonInfo {
const char* Name;
ImVec4 Color;
};
class RuntimeControls : public EditorWindow {
public:
RuntimeControls() : EditorWindow("RuntimeControls", RuntimeControlWindowFlags) {}
void Draw() override;
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}}
};
};

View File

@ -1,134 +0,0 @@
#pragma once
#include <yaml-cpp/yaml.h>
#include <yaml-cpp/node/type.h>
#include <string>
#include <filesystem>
#include <fstream>
#include "../../YoggieEngine/src/Scene/Entity.h"
void WriteFile(std::string& emitter, std::filesystem::path path)
{
std::cout << "Writing Scene file to: " << path.u8string() << std::endl;
std::ofstream sceneFile;
sceneFile.open(path.u8string());
sceneFile << emitter.c_str();
sceneFile.close();
}
YAML::Emitter& operator<< (YAML::Emitter& emitter, glm::vec3& vector) {
emitter << YAML::Flow << YAML::BeginSeq << vector.x << vector.y << vector.x << YAML::EndSeq;
return emitter;
}
std::string Serialize( Scene& scene) {
YAML::Emitter emitter;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Scene" << YAML::Value << "test-Scene";
emitter << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq;
scene.getReg().each([&scene, &emitter](auto enttNumber) {
Entity entity = Entity(enttNumber, &scene);
emitter << YAML::BeginMap;
emitter << YAML::Key << "Entity" << YAML::Value << entity.GetComponent<IdentifierComponent>().name;
if (entity.HasComponent<IdentifierComponent>()) {
emitter << YAML::Key << "Ident";
emitter << YAML::BeginMap;
emitter << YAML::Value << entity.GetComponent<IdentifierComponent>().name;
emitter << YAML::EndMap;
}
if (entity.HasComponent<TransformComponent>()) {
emitter << YAML::Key << "Transform" << YAML::Value ;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Position";
emitter << YAML::Value << entity.GetComponent<TransformComponent>().Position;
emitter << YAML::Key << "Rotation";
emitter << YAML::Value << entity.GetComponent<TransformComponent>().Rotation;
emitter << YAML::Key << "Scale";
emitter << YAML::Value << entity.GetComponent<TransformComponent>().Scale;
emitter << YAML::EndMap;
}
if (entity.HasComponent<LightComponent>()) {
emitter << YAML::Key << "Light";
emitter << YAML::Value;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Color";
emitter << YAML::Value << entity.GetComponent<LightComponent>().Color;
emitter << YAML::EndMap;
}
emitter << YAML::EndMap;
});
emitter << YAML::EndSeq;
emitter << YAML::EndMap;
return std::string(emitter.c_str());
}
void SaveScene(std::filesystem::path path, Scene& scene) {
std::string YAMLString = Serialize(scene);
WriteFile(YAMLString, path);
}
void LoadScene(std::filesystem::path path, Scene& scene)
{
auto sceneYAML = YAML::LoadFile(path.u8string());
if (!sceneYAML["Scene"]) {
spdlog::error("Not a scene file!");
return;
}
scene.getReg().clear();
std::string SceneName = sceneYAML["Scene"].as<std::string>();
auto entities = sceneYAML["Entities"];
for (const auto& entity : entities) {
std::string entityID = entity["Ident"].as<std::string>();
YoggieEngine::Entity SE = scene.AddEntity(entityID);
if (entity["Transform"])
{
TransformComponent tc = SE.GetComponent<TransformComponent>();
auto positionNode = entity["Transform"]["Position"];
tc.Position = glm::vec3(positionNode[0].as<float>(), positionNode[1].as<float>(), positionNode[2].as<float>());
auto rotationNode = entity["Transform"]["Rotation"];
tc.Rotation = glm::vec3(rotationNode[0].as<float>(), rotationNode[1].as<float>(), rotationNode[2].as<float>());
auto scaleNode = entity["Transform"]["Scale"];
tc.Scale = glm::vec3(scaleNode[0].as<float>(), scaleNode[1].as<float>(), scaleNode[2].as<float>());
}
if (entity["Light"]) {
LightComponent lc = SE.AddComponent<LightComponent>();
lc.Color = glm::vec3(entity["Light"]["Color"][0].as<float>(), entity["Light"]["Color"][1].as<float>(), entity["Light"]["Color"][2].as<float>());
}
}
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <imgui.h>
class EditorConsole
{
public:
EditorConsole();
~EditorConsole();
void Draw();
void AddLog(const char* fmt, ...);
private:
ImVector<char*> Items;
bool AutoScroll;
bool ScrollToBottom;
};

View File

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

View File

@ -1,70 +0,0 @@
#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 450");
ImGuizmo::SetImGuiContext(ImGui::GetCurrentContext());
ImGuizmo::SetOrthographic(true);
}
void Begin ()
{
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
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();
}
};

View File

@ -1,187 +0,0 @@
#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,
"build/Debug/Assets"//project.get()->GetProjectDirectory() / "Assets"
);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Import MeshAsset (temp)"))
{
auto result = NFD_OpenDialog("mesh", NULL, &path);
switch (result) {
case(NFD_OKAY):
{
YoggieEngine::Mesh* importedMesh = AssetManager::LoadFromAssetFile(path);
if (importedMesh != nullptr)
{
auto full_name = std::filesystem::path(path);
auto importedModel = scene.AddEntity(full_name.filename().u8string());
auto& rendererComponent = importedModel.AddComponent<Render3DComponent>();
rendererComponent.mesh = *importedMesh;
}
}
break;
case(NFD_CANCEL):
spdlog::debug("User cancelled action");
break;
case(NFD_ERROR):
spdlog::warn("Something went wrong!");
break;
}
}
ImGui::EndMenu();
}
}
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;
};

View File

@ -1,377 +0,0 @@
#pragma once
#include <string>
#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;
auto matrix = glm::mat4(1.0f);
auto worldOrigin = glm::mat4(1.0f);
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());
func();
ImGui::EndChild();
ImGui::PopStyleVar();
}
class Inspector : EditorWindow {
public:
Inspector() : EditorWindow("Inspector") {}
void AddComponentDropDown(Entity& selected )
{
static char* names[] = { "Script Component", "Camera Component", "Light Component"};
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 "
<< selected.GetComponent<IdentifierComponent>().name << std::endl;
}
ImGui::EndPopup();
}
ImGui::NewLine();
}
void ShowComponents(Entity& selected)
{
auto component = selected.GetComponent<IdentifierComponent>();
ImGui::InputText("Name:", (char*)component.name.c_str(), component.name.size() * sizeof(char), 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.1f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.1f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform.Scale), 0.1f, 0.0f);
}
if (selected.HasComponent<RelationComponent>()) {
ImGui::Text("Has relation");
}
}
if (selected.HasComponent<Render3DComponent>()) {
auto& render3d = selected.GetComponent<Render3DComponent>();
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(render3d.color));
ImGui::Checkbox("Use static rendering:", &render3d.isStatic);
}
}
static bool deferred = true;
if (selected.HasComponent<LightComponent>()) {
auto& light = selected.GetComponent<LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
ImGui::Checkbox("Deferred", &deferred);
}
}
if (selected.HasComponent <CameraComponent>()) {
auto& camera = selected.GetComponent<CameraComponent>();
if (ImGui::CollapsingHeader("Camera")) {
ImGui::DragFloat3("Position:",glm::value_ptr(camera.Position), 0.01f);
ImGui::DragFloat3("Rotation:", glm::value_ptr(camera.Rotation), 0.01f);
}
}
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 (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::Enable(true);
ImGuizmo::SetRect(ScreenSpaceMin.x, ScreenSpaceMin.y,ContentRegionMax.x, ContentRegionMax.y);
glm::mat4 transposed_view = glm::transpose(cam.ViewMatrix);
ImGuizmo::DrawGrid(glm::value_ptr(cam.ViewMatrix), glm::value_ptr(cam.ProjectionMatrix), glm::value_ptr(worldOrigin), 100.0f);
ImGuizmo::ViewManipulate(glm::value_ptr(transposed_view), 1, { ScreenSpaceMin.x,ScreenSpaceMin.y }, { 90,90 }, 0x22CCCCCC);
// 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(cam.ViewMatrix));
if (ImGui::IsWindowFocused() )
{
isFocused = true;
}
else {
isFocused = false;
}
}
bool isFocused = false;
};
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 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 {
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));
Texture folderIcon = Texture("rsc/folderIcon.png");
Texture assetIcon = Texture("rsc/assetIcon.png");
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();
const GLuint textures[2]{ assetIcon.GetID(), folderIcon.GetID() };
glDeleteTextures(2, textures );
}
}
private:
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}}
};
};

View File

@ -0,0 +1,55 @@
#include "Viewport.h"
Viewport::Viewport(YoggieEngine::Scene& scene ):
EditorWindow("SceneView"),
renderer(YoggieEngine::RendererConfig{ 1200, 700, glm::vec3(0), true }),
cam(glm::vec3(14.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 90),
scene(scene)
{
renderer.SetMainCamera(cam);
}
void Viewport::Draw() {
auto group = scene.getReg().view<YoggieEngine::TransformComponent, YoggieEngine::Render3DComponent>();
group.each([&](auto enity, YoggieEngine::TransformComponent& t, YoggieEngine::Render3DComponent& renderComponent) {
renderer.Submit(renderComponent, t);
});
cam.Update();
renderer.Render(scene);
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)renderer.getCurrentFrameBuffer().GetColourAttachment(),
ImVec2{ (float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight() }
);
ImGuizmo::Enable(true);
ImGuizmo::SetRect(ScreenSpaceMin.x, ScreenSpaceMin.y, ContentRegionMax.x, ContentRegionMax.y);
glm::mat4 transposed_view = glm::transpose(cam.ViewMatrix);
//ImGuizmo::DrawGrid(glm::value_ptr(cam.ViewMatrix), glm::value_ptr(cam.ProjectionMatrix), glm::value_ptr(worldOrigin), 100.0f);
//ImGuizmo::ViewManipulate(glm::value_ptr(cam.ViewMatrix), 1, { ScreenSpaceMin.x,ScreenSpaceMin.y }, { 90,90 }, 0x22CCCCCC);
// 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(cam.ViewMatrix));
if (ImGui::IsWindowFocused())
{
isFocused = true;
}
else {
isFocused = false;
}
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "../EditorWindow.h"
#include <glm/glm.hpp>
#include <imgui.h>
#include "../../libs/guizmo/ImGuizmo.h"
class Viewport : public EditorWindow {
public:
bool isFocused = false;
YoggieEngine::Camera cam;
Viewport(YoggieEngine::Scene& scene);
void Draw() override;
private:
YoggieEngine::Renderer renderer;
YoggieEngine::Scene& scene;
};

View File

@ -8,84 +8,63 @@
#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 "AssetManagement/SceneSerializer.h"
#include "AssetManagement/AssetManager.h"
#include "UI/MainMenuBar.h"
void CreateTestProject(std::unique_ptr<Project>& project, Scene& scene);
RendererConfig EditorSceneRendererConfig{
1200, // Screen Width
700, // Screen Height
glm::vec3{0,0,0}, // Clear Color
true // Depth testing
};
glm::vec3 temp = glm::vec3(0);
Camera cam = Camera(glm::vec3(14.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 90);
#include "Views/Viewport.h"
#include "PropertyPanels/SceneExplorer.h"
#include "AssetManagement/AssetFinder.h"
#include "MainMenuBar.h"
#include "PropertyPanels/Inspector.h"
#include "Project/ProjectInfo.h"
#include "Runtime/RuntimeControls.h"
#include "Project/Settings.h"
#include "Console.h"
using namespace YoggieEngine;
class Editor : public Application {
public:
Editor()
: Application("Editor"),
AppWindow(1200,700),
framebuffer(new Framebuffer(1200,700)),
viewportRenderer(EditorSceneRendererConfig),
EditorGUIRenderer(AppWindow),
Selected((entt::entity)-1)
Editor() : Application("Editor"), Selected((entt::entity)-1){}
void Run() override
{
LoadLastOrEmptyProject();
init_inputSystem(&AppWindow);
viewportRenderer.setCurrentFrameBuffer(*framebuffer);
}
MainMenuBar menuBar = MainMenuBar();
ProjectInfo projectInfo(project);
Viewport sceneview = Viewport(scene);
RuntimeControls rc = RuntimeControls();
SceneExplorer explorer(Selected, scene);
Inspector inspector = Inspector();
Settings settings = Settings();
// AssetFinder assetsView = AssetFinder();
Console console = Console();
void RenderScene() {
// submit DrawCommands for all render3DComponents
auto group = ActiveScene.getReg().view<TransformComponent, Render3DComponent>();
group.each([&](auto enity, TransformComponent& t, Render3DComponent& renderComponent) {
viewportRenderer.Submit(renderComponent, t);
});
// Render scene
viewportRenderer.Render(ActiveScene);
}
void RenderEditorGUI() {
EditorGUIRenderer.Begin();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
// Show a menu bar
double previous = glfwGetTime();
double lag = 0.0;
while (!appWindow.WindowShouldClose())
{
MainMenuBar menuBar = MainMenuBar();
menuBar.ApplicationMenu(CurrentProject);
menuBar.SceneMenu(CurrentProject, ActiveScene);
menuBar.SelectMenu();
menuBar.WindowMenu();
menuBar.DebugMenu();
menuBar.Help();
}
{
ProjectInfo projectInfo(*(CurrentProject.get()));
}
{
Viewport sceneview = Viewport(*framebuffer, viewportRenderer.getCamera());
if (sceneview.isFocused)
PollEvents();
double now = glfwGetTime();
double elapsed = now - previous ;
previous = now;
lag += elapsed;
if (sceneview.isFocused)
{
const float movement_speed = 0.1f;
static float lastX = 400, lastY = 300;
const float sensitivity = 0.1;
static bool firstMouse = true;
if (MouseButtonPressed(YOGGIE_MOUSE_BUTTON_RIGHT) ){
glfwSetInputMode(AppWindow.GetGLFWHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
auto newX = getCursorPosX(&AppWindow);
auto newY = getCursorPosY(&AppWindow);
if (MouseButtonPressed(YOGGIE_MOUSE_BUTTON_RIGHT)) {
glfwSetInputMode(appWindow.GetGLFWHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
auto newX = getCursorPosX(&appWindow);
auto newY = getCursorPosY(&appWindow);
if (firstMouse)
{
@ -104,139 +83,124 @@ public:
xoffset *= sensitivity;
yoffset *= sensitivity;
cam.yaw += xoffset;
cam.pitch += yoffset;
sceneview.cam.yaw += xoffset;
sceneview.cam.pitch += yoffset;
if (cam.pitch > 89.0f)
cam.pitch = 89.0f;
if (cam.pitch < -89.0f)
cam.pitch = -89.0f;
if (sceneview.cam.pitch > 89.0f)
sceneview.cam.pitch = 89.0f;
if (sceneview.cam.pitch < -89.0f)
sceneview.cam.pitch = -89.0f;
}
else if (firstMouse == false)
{
glfwSetInputMode(AppWindow.GetGLFWHandle(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
firstMouse = true;
glfwSetInputMode(appWindow.GetGLFWHandle(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
firstMouse = true;
}
// Check for Camara movement input here!
if (keyIsPressed(YOGGIE_KEY_W))
cam.Position += cam.Front * movement_speed;
sceneview.cam.Position += sceneview.cam.Front * movement_speed;
if (keyIsPressed(YOGGIE_KEY_A))
cam.Position -= cam.Right * movement_speed;
sceneview.cam.Position -= sceneview.cam.Right * movement_speed;
if (keyIsPressed(YOGGIE_KEY_S))
cam.Position -= cam.Front * movement_speed;
sceneview.cam.Position -= sceneview.cam.Front * movement_speed;
if (keyIsPressed(YOGGIE_KEY_D))
cam.Position += cam.Right * movement_speed;
sceneview.cam.Position += sceneview.cam.Right * movement_speed;
}
}
GuiBegin();
{
RuntimeControls rc = RuntimeControls();
}
{
SceneExplorer explorer(Selected, ActiveScene);
}
{
Inspector inspector = Inspector();
if (ActiveScene.getReg().valid(Selected)) {
Entity SelectedEntity = Entity(Selected, &ActiveScene);
// Show a menu bar
menuBar.ApplicationMenu(project);
menuBar.SceneMenu(project, scene);
menuBar.SelectMenu();
menuBar.WindowMenu();
menuBar.DebugMenu();
menuBar.Help();
if (scene.getReg().valid(Selected)) {
Entity SelectedEntity = Entity(Selected, &scene);
inspector.AddComponentDropDown(SelectedEntity);
inspector.ShowComponents(SelectedEntity);
}
}
{
Settings settings = Settings();
}
{
// AssetFinder assetsView = AssetFinder();
}
{
Console console = Console();
console.Show();
}
ImGui::ShowDemoWindow();
ImGui::ShowMetricsWindow();
EditorGUIRenderer.End();
}
void Run() override
{
CreateTestProject(CurrentProject, ActiveScene);
ActiveScene.Start();
// Create the physics engine demo!
Physics Physics;
Physics.Demo();
/*Physics.EnableDebugVisuals();
Physics.Step(0);
Physics.SubmitMesh();
*/
double previous = glfwGetTime();
double lag = 0.0;
while (!AppWindow.WindowShouldClose())
{
double current = glfwGetTime();
double elapsed = current - previous;
previous = current;
lag += elapsed;
AppWindow.Poll();
cam.Update();
projectInfo.Update();
sceneview.Update();
rc.Update();
explorer.Update();
settings.Update();
inspector.Update();
console.Update();
Physics.Step(elapsed);
ActiveScene.Update();
RenderScene();
/*Physics.DebugRender(*framebuffer);*/
RenderEditorGUI();
AppWindow.SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
ImGui::ShowDemoWindow();
ImGui::ShowMetricsWindow();
GuiEnd();
SwapBuffers();
}
delete framebuffer;
ActiveScene.Stop();
}
void LoadLastOrEmptyProject() {
// Check if there is a last known loaded project and
// load that one .
// Otherwise load no project..
// OR
// Load an empty project.
std::string path = (std::filesystem::current_path()).string();
project.setProjectDirectory(path);
AssetManager::Init();
AssetManager::setAssetPath(project.GetProjectDirectory());
AssetManager::BuildAssetView();
// Create a level and load it as the current level
auto importer = ModelImporter();
// create an ambient light source
auto light = scene.AddEntity("Light");
auto& lightComponent = light.AddComponent<LightComponent>();
lightComponent.Color = glm::vec3(1.0f);
// 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("Cube2");
auto& rendercube2 = cube2.AddComponent<Render3DComponent>();
rendercube2.mesh = *(model->renderable->mesh);
auto& relationcube = cube.AddComponent<RelationComponent>(cube2);
auto& rigidbodycomp = cube.AddComponent<RigidBody>();
auto& rigidbodycomp2 = cube2.AddComponent<RigidBody>();
auto Grass = scene.AddEntity("Grass/Window-Pane");
//auto& renderGrass = Grass.AddComponent<Render3DComponent>();
}
private:
NativeWindow AppWindow;
Framebuffer* framebuffer;
Renderer viewportRenderer;
GUIRenderer EditorGUIRenderer;
// Editor State
bool SimulatePhysics = true;
entt::entity Selected;
std::unique_ptr<Project> CurrentProject;
Scene ActiveScene;
Project project;
Scene scene;
};
@ -245,43 +209,3 @@ YoggieEngine::Application* CreateApplication() {
return new Editor();
}
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 an ambient light source
auto light = scene.AddEntity("Light");
auto lightComponent = light.AddComponent<LightComponent>();
lightComponent.Color = glm::vec3(1.0f);
// 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("Cube2");
auto& rendercube2 = cube2.AddComponent<Render3DComponent>();
rendercube2.mesh = *(model->renderable->mesh);
auto relationcube = cube.AddComponent<RelationComponent>(cube2);
auto Grass = scene.AddEntity("Grass/Window-Pane");
//auto& renderGrass = Grass.AddComponent<Render3DComponent>();
}

View File

@ -1,16 +1,37 @@
#include <YoggieEngine.h>
#include "Application.h"
#include <imgui.h>
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_glfw.h>
#include "../../libs/guizmo/ImGuizmo.h"
namespace YoggieEngine {
Application::Application(const std::string& name)
: m_AppName(name)
: m_AppName(name), appWindow(1200, 700)
{
// Initialize engine should possibly happen here
EngineInstrumentation::PerfomanceSamplerInit();
// Initilize ImGui for this application
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(appWindow.GetGLFWHandle(), true);
ImGui_ImplOpenGL3_Init("#version 450");
ImGuizmo::SetImGuiContext(ImGui::GetCurrentContext());
ImGuizmo::SetOrthographic(true);
init_inputSystem(&appWindow);
}
@ -19,5 +40,46 @@ namespace YoggieEngine {
}
Application::~Application() {}
void Application::PollEvents() {
appWindow.Poll();
}
void Application::SwapBuffers()
{
appWindow.SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Application::GuiBegin() {
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
ImGuizmo::BeginFrame();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
}
void Application::GuiEnd() {
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);
}
}
Application::~Application() {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
}

View File

@ -10,9 +10,17 @@ namespace YoggieEngine {
~Application();
virtual void Run();
void PollEvents();
void SwapBuffers();
void GuiBegin();
void GuiEnd();
protected:
std::string m_AppName;
NativeWindow appWindow;
friend class ApplicationRuntime;
};

View File

@ -3,6 +3,7 @@ namespace YoggieEngine {
class Camera {
public:
Camera() = default;
Camera(const Camera& other);
Camera(glm::vec3 position, glm::vec3 rotation, float zoom);
~Camera();

View File

@ -6,7 +6,6 @@
#include "../Graphics/Memory/VertexArray.h"
#include "../Graphics/Primitives/DrawCommand.h"
extern YoggieEngine::Camera cam;
namespace YoggieEngine {
unsigned int quadVAO = 0;
unsigned int quadVBO = 0;
@ -159,10 +158,6 @@ Renderer::Renderer(RendererConfig& config)
Renderer::~Renderer(){}
Camera& Renderer::getCamera() {
return cam;
}
void SubmitVegetationDemo() {
@ -250,8 +245,8 @@ void Renderer::GeometryPass() {
gBufferShader.setUniformVec3("Color", command.color);
gBufferShader.setUniformMat4("Model", command.transform.LocalTransform);
gBufferShader.setUniformMat4("View", cam.ViewMatrix);
gBufferShader.setUniformMat4("Projection", cam.ProjectionMatrix);
gBufferShader.setUniformMat4("View", MainCamera.ViewMatrix);
gBufferShader.setUniformMat4("Projection", MainCamera.ProjectionMatrix);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(command.num_elements),
GL_UNSIGNED_INT, NULL);
@ -266,8 +261,8 @@ void Renderer::SkyboxPass() {
// Render skybox
glDepthMask(GL_FALSE);
SkyboxShader.Use();
SkyboxShader.setUniformMat4("projection", cam.ProjectionMatrix);
SkyboxShader.setUniformMat4("view", glm::mat4(glm::mat3(cam.ViewMatrix))); // remove rotation from the view matrix
SkyboxShader.setUniformMat4("projection", MainCamera.ProjectionMatrix);
SkyboxShader.setUniformMat4("view", glm::mat4(glm::mat3(MainCamera.ViewMatrix))); // remove rotation from the view matrix
glBindVertexArray(skyboxVAO);
glBindTexture(GL_TEXTURE_CUBE_MAP, sky.getID());
glDrawArrays(GL_TRIANGLES, 0, 36);
@ -314,7 +309,7 @@ void Renderer::lightingPass(Scene& scene){
lightnr++;
});
lightingPassShader.setUniformVec3("viewPos", getCamera().Position);
lightingPassShader.setUniformVec3("viewPos", MainCamera.Position);
// render to quad
if (quadVAO == 0)
@ -353,8 +348,8 @@ void Renderer::BlendingPass() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, grassTexture.GetID());
BlendingShader.setUniformMat4("V", cam.ViewMatrix);
BlendingShader.setUniformMat4("P", cam.ProjectionMatrix);
BlendingShader.setUniformMat4("V", MainCamera.ViewMatrix);
BlendingShader.setUniformMat4("P", MainCamera.ProjectionMatrix);
for (unsigned int i = 0; i < vegetation.size(); i++) {
@ -372,10 +367,6 @@ void Renderer::BlendingPass() {
}
void Renderer::Render(Scene& scene)
{
SubmitVegetationDemo();
@ -409,8 +400,8 @@ void Renderer::Render(Scene& scene)
forwardShader.setUniformVec3("Color", command.color);
forwardShader.setUniformMat4("M", command.transform.LocalTransform);
forwardShader.setUniformMat4("V", cam.ViewMatrix);
forwardShader.setUniformMat4("P", cam.ProjectionMatrix);
forwardShader.setUniformMat4("V", MainCamera.ViewMatrix);
forwardShader.setUniformMat4("P", MainCamera.ProjectionMatrix);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(command.num_elements),
GL_UNSIGNED_INT, NULL);
@ -432,7 +423,6 @@ void Renderer::Render(Scene& scene)
*/
commands.clear();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

View File

@ -8,6 +8,7 @@
#include "../Scene/Components.h"
#include"../Scene/Scene.h"
#include "Graphics/Primitives/DrawCommand.h"
#include "Primitives/Camera.h"
namespace YoggieEngine {
@ -29,8 +30,9 @@ namespace YoggieEngine {
void setCurrentFrameBuffer(const Framebuffer& fb);
void setClearColor(const glm::vec3& ClearColor);
Camera& getCamera();
void SetMainCamera(const Camera& camera) { MainCamera = camera; }
Framebuffer& getCurrentFrameBuffer() { return m_framebuffer; }
private:
void GeometryPass();
void SkyboxPass();
@ -45,7 +47,7 @@ namespace YoggieEngine {
glm::vec3 m_clearColor;
bool m_depthTest;
std::vector<DrawCommand> commands;
Camera MainCamera;
unsigned int skyboxVAO = 0;
CubeMap sky;

View File

@ -28,7 +28,6 @@ namespace YoggieEngine {
gMaterial = nullptr;
mScene = nullptr;
}
Physics::~Physics()
@ -153,6 +152,19 @@ namespace YoggieEngine {
}
void Physics::addRigidBody(glm::mat4& transform)
{
PxShape* shape = mPhysics->createShape(PxBoxGeometry(1.0f, 1.0f, 1.0f), *gMaterial);
PxTransform localtm = PxTransform((const PxMat44&) transform);
PxRigidDynamic* body = mPhysics->createRigidDynamic(localtm);
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
mScene->addActor(*body);
}
void Physics::createScene()
{
PxSceneDesc sceneDesc(mPhysics->getTolerancesScale());

View File

@ -31,17 +31,21 @@ namespace YoggieEngine {
void DebugRender(Framebuffer& framebuffer);
void addRigidBody(glm::mat4& transform);
void createScene();
void createGroundPlane();
void SetupPvdDebug();
private:
Shader debugDraw = Shader("build/Debug/Shaders/forward/debug.vert", "build/Debug/Shaders/forward/debug.frag");
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity);
void createStack(const PxTransform& t, PxU32 size, PxReal halfextent);
void createScene();
void createGroundPlane();
void SetupPvdDebug();
// Memory Management

View File

@ -42,6 +42,21 @@ namespace YoggieEngine {
std::string file; // TODO : replace with proper properties
};
struct RigidBody {
float Mass;
// Physics Material
};
struct BoxCollider {
glm::vec3 extents;
};
struct PlaneCollider {
};
struct Render3DComponent {
unsigned int VAO = 0;
unsigned int IBO = 0;

View File

@ -26,6 +26,7 @@ namespace YoggieEngine{
void Scene::Start()
{
// Execute start functions in scripts etc....
}
void Scene::Update()

View File

@ -31,6 +31,7 @@ extern "C"
// Main library stuff
#include "Platform/Window.h"
#include "Graphics/Primitives/Mesh.h"
@ -53,3 +54,4 @@ extern "C"
#include "Scene/Scene.h"
#include "Scene/Components.h"
#include "Application.h"