39 Commits

Author SHA1 Message Date
391fd5a8a8 WIP: Switching from Premake to CMake build system 2025-06-15 20:55:15 +02:00
7349c0eb16 Basics of the meta Asset Management 2023-06-05 17:48:11 +02:00
19b630104c Big clean up, getting ready for new AssetManagement
* Removing Old EventSystem
* Removing Assets from Editor project
* Clean up of EditorLayer.h
* Moving primitives of renderer out of their subfolder
2023-06-05 17:47:40 +02:00
7ec13a7020 Adding more input handlers 2023-05-17 19:41:48 +02:00
4a84df7c3e Ignore more dirty submodules 2023-05-16 22:06:45 +02:00
a297c7cb3a Adding googletest as a submodule 2023-05-16 22:04:32 +02:00
8ef886df83 Clean up layer stack code, input now goes through each layer 2023-05-16 21:59:10 +02:00
817d0bdca9 Adding tests for decompose function
Added scale and rotation decompose test
2023-05-16 20:43:05 +02:00
c640ac574b Fixed translation issue with Imguizmo 2023-05-16 20:18:26 +02:00
0b2148ad55 Adding more things to .gitignore 2023-05-13 21:37:53 +02:00
95f77209cf Fixing lvalue errors on linux build
nfd is not yet linking on Linux
2023-05-13 21:33:57 +02:00
f7e087ee8d remove yaml-cpp from root directory, Add tests project 2023-05-13 20:13:25 +02:00
e52db0fafd Remove Runtime Project 2023-05-13 20:10:47 +02:00
5bdc0034d1 Moving premake5.lua build file to their individual submodule folder 2023-05-13 20:10:25 +02:00
ceb485018f Rudimentary implementation of the translate,Rotate,Scale tools 2023-05-13 18:10:24 +02:00
daf26c304b Added a few thing , and started simplifying renderer
- Added context menu to Inspector
- Added check to see if project path exists.
- Simplifying the renderer design
2023-05-13 01:31:37 +02:00
550c1b6e5b Updated Editor architecture
- Everything editor related will be happening in EditorLayer
- Added an icon font
- Added proper icon
- Added project badge in main menu bar
- Texture class now keeps track of the texture width and height
2023-05-11 20:27:07 +02:00
c82398205a Script component inspector, glfwErrorCallback etc...
* Filling out script component inspector
* adding error_callback for glfw
* Measuring gflwInit time
* Moving Swap interval set to be after making context current
2023-05-09 19:38:53 +02:00
43fc721413 Replacing a few std::cout with spdlog::info/error 2023-05-09 19:36:34 +02:00
52747202d3 Mark two git submodules to ignore when their working tree has changes 2023-05-08 22:18:14 +02:00
fef75ec64b Started Working on an assetsystem for loading more complex models 2023-05-08 22:08:08 +02:00
3c38e2a988 Editor Layer + Updating Camera System
Started updating the camera system, Moving editor logic to an Editor layer
2023-05-08 22:07:29 +02:00
e9852fe0e7 Implementing started properly implementing Gizmo
Adding GetTransform to the transform component such that the proper view transform can be calculated for any scene camera
2023-05-08 22:06:01 +02:00
8e202f9d59 Introducing application layers
This feature is not really used yet but will help in the future simplify the propegation of events
2023-05-08 22:01:44 +02:00
d8627d0357 Removing unused TransformTree definition files 2023-05-07 20:44:42 +02:00
ec8045c4f4 Added Asset selection in Render3D component view (Not functional yet!) 2023-05-07 15:25:31 +02:00
042dc3a457 Update Transform Component view of the editor 2023-05-07 15:24:23 +02:00
28927d9a4e Moved model file loading logic to the editor code base 2023-05-06 21:06:49 +02:00
89f5b1497f Can move around scene again .. working on Rendering engine still 2023-05-03 16:40:43 +02:00
7448017701 Further abstraction of platform window handling
We could now build our own native window class and stop relying on GLFW. However this won't be important for now!
2023-01-31 18:41:46 +01:00
ba69726e33 Updated gitignore and added submodule
- Added a filebrowser for imgui submodule
- Added gitignore entries for two submodules
2023-01-14 22:18:15 +01:00
7223c20f1d Changed selected type
Moving away from using the pure ENTT library types and starting to use my own
2023-01-14 22:11:09 +01:00
282844b905 Load the previously loaded project and scene on startup
(read from an ini file)
2023-01-14 21:44:48 +01:00
145338d666 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 ).
2023-01-14 17:27:37 +01:00
79b68fbff1 deferred rendering can be enabled for certain meshes 2023-01-13 17:55:45 +01:00
13f67a7cdb Basic input handling, Editor camera Movement 2023-01-04 19:01:58 +01:00
d5a6ddb9d5 Moving vegetation test to the renderer 2023-01-04 15:57:08 +01:00
0f9be33bd6 Primitive Blending functionality 2023-01-01 17:02:44 +01:00
75aa577211 Relation widget + small memory leak solved 2023-01-01 17:00:48 +01:00
131 changed files with 5359 additions and 2671 deletions

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text

10
.gitignore vendored
View File

@ -16,4 +16,12 @@ x64/
*.gltf
!sponza.gltf
imgui.ini
imgui.ini
libs/physx/physx/include/
libs/physx/physx/compiler/
libs/physx/physx/buildtools/
libs/physx/physx/bin/
libs/nativefiledialog/build/
.docker
**/bin/

14
.gitmodules vendored
View File

@ -14,6 +14,7 @@
[submodule "ImGui"]
path = libs/ImGui
url = https://github.com/ocornut/imgui.git
ignore = dirty
[submodule "assimp"]
path = libs/assimp
url = https://github.com/assimp/assimp.git
@ -24,15 +25,28 @@
[submodule "libs/physx"]
path = libs/physx
url = https://git.barink.dev/Nigel/PhysX.git
ignore = dirty
[submodule "libs/entt"]
path = libs/entt
url = https://github.com/skypjack/entt.git
[submodule "libs/guizmo"]
path = libs/guizmo
url = https://github.com/CedricGuillemet/ImGuizmo.git
ignore = dirty
[submodule "libs/yaml-cpp"]
path = libs/yaml-cpp
url = https://git.barink.dev/Nigel/yaml-cpp.git
ignore = dirty
[submodule "libs/nativefiledialog"]
path = libs/nativefiledialog
url = https://git.barink.dev/Nigel/nativefiledialog.git
ignore = dirty
[submodule "libs/mINI"]
path = libs/mINI
url = https://github.com/pulzed/mINI.git
[submodule "libs/imgui-filebrowser"]
path = libs/imgui-filebrowser
url = https://github.com/AirGuanZ/imgui-filebrowser.git
[submodule "libs/googletest"]
path = libs/googletest
url = https://github.com/google/googletest.git

21
CmakeLists.txt Normal file
View File

@ -0,0 +1,21 @@
CMAKE_MINIMUM_REQUIRED (VERSION 4.0)
project(Yoggie)
set(EXPORT_COMPILE_COMMANDS_JSON ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4099")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wclass-struct-conversion")
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
add_compile_definitions(GLFW_STATIC)
add_subdirectory(Editor)
add_subdirectory(SandboxApp)
include(libraries.cmake)
add_subdirectory(YoggieEngine)

1
Editor/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**.dll

Binary file not shown.

17
Editor/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB HEADER_FILES "src/*.h")
add_executable(Editor ${SOURCE_FILES} "../libs/glad/src/glad.c" ${HEADER_FILES})
target_include_directories(Editor PRIVATE
"../YoggieEngine/src"
"../libs/guizmo"
)
target_link_directories(Editor PRIVATE
"../libs/ImGui/build/Release"
"../libs/guizmo/build/Release" )
target_link_libraries(Editor
thirdparty_tools
YoggieEngine
ImGui
ImGuizmo
)

View File

@ -1,46 +0,0 @@
project "Editor"
kind "ConsoleApp"
buildmessage "Building editor ..."
links{
"YoggieEngine",
"ImGuizmo",
"yaml-cpp",
"nfd.lib"
}
includedirs{
"../YoggieEngine/build/Debug",
-- I'd prefer if didn't need these..
-- We'll figure that out some time later
"../libs/physx/physx/include",
"../libs/physx/pxshared/include",
incfolder["lua"],
incfolder["spdlog"],
incfolder["glm"],
incfolder["assimp"],
incfolder["glad"],
incfolder["glfw"],
incfolder["imgui"],
incfolder["imguizmo"],
incfolder["entt"],
incfolder["yamlcpp"],
incfolder["nativefiledialog"],
}
libdirs {
staticlib["yoggie"],
staticlib["nativefiledialog"]
}
files {
"../libs/glad/src/glad.c",
"./src/**.h",
"./src/**.cpp"
}

BIN
Editor/rsc/Yoggie.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Editor/rsc/Yoggie2.jpeg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,46 +0,0 @@
#pragma once
#include <filesystem>
#include <string>
#include "../../YoggieEngine/src/YoggieEngine.h"
enum class ASSET_TYPE {
Unknown = -1,
Mesh,
Texture,
Material
};
class Asset {
public:
Asset(const char* name): name(name) {}
virtual ASSET_TYPE GetType() { return ASSET_TYPE::Unknown; }
const char* GetName() const { return name.c_str(); }
bool isFolder = false ;
protected:
std::string name;
};
class MeshAsset : Asset {
public:
MeshAsset(YoggieEngine::Mesh mesh) : Asset("New MeshAsset"), mesh(mesh) {}
ASSET_TYPE GetType() override { return ASSET_TYPE::Mesh; }
private:
YoggieEngine::Mesh& mesh;
};
class TextureAsset : Asset {
public:
TextureAsset (YoggieEngine::Texture texture): Asset("New TextureAsset"), texture(texture) {}
ASSET_TYPE GetType() override { return ASSET_TYPE::Texture; }
private:
YoggieEngine::Texture& texture;
};
class MaterialAsset : Asset {
public:
MaterialAsset () : Asset("New MaterialAsset"){}
ASSET_TYPE GetType() override { return ASSET_TYPE::Material; }
private:
};

View File

@ -1,150 +0,0 @@
#include "AssetManager.h"
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include <iostream>
#include <fstream>
#include <spdlog/spdlog.h>
std::vector<Asset> AssetManager::assets;
std::filesystem::path AssetManager::currentPath;
void AssetManager::Init()
{
assets = std::vector<Asset>();
currentPath = std::filesystem::path(".");
}
void AssetManager::BuildAssetView()
{
if (currentPath.empty()) {
return;
}
for (auto& dir_entry : std::filesystem::directory_iterator(currentPath))
{
auto asset = Asset(dir_entry.path().filename().string().c_str());
if (dir_entry.is_directory()) {
asset.isFolder = true;
}
assets.push_back(asset);
}
}
void AssetManager::setAssetPath(std::filesystem::path path)
{
currentPath = path;
}
YoggieEngine::Mesh* AssetManager::LoadFromAssetFile(const std::filesystem::path assetPath)
{
YoggieEngine::Mesh* imported = nullptr;
std::ifstream AssetFile;
AssetFile.open(assetPath, std::ios::binary);
if (AssetFile.is_open()) {
char* Header = (char*)malloc(8);
unsigned long long Vsize = 0;
uint32_t Vnum = 0;
uint32_t Enum = 0;
// Read header
AssetFile.read(Header, 8);
AssetFile.read((char*)&Vsize, sizeof(unsigned long long));
AssetFile.read((char*)&Vnum, sizeof(uint32_t));
AssetFile.read((char*)&Enum, sizeof(uint32_t));
// print Header info
std::cout << "File has header: " << Header << std::endl;
std::cout << "Vertex size: " << Vsize << std::endl;
std::cout << "Number of Vertices: " << Vnum << std::endl;
std::cout << "Number of Elements: " << Enum << std::endl;
free(Header);
imported = new YoggieEngine::Mesh();
// Load Vertices (Vertex + UV )
imported->vertices = std::vector < YoggieEngine::Vertex>();
for (int i = 0; i < Vnum; i++)
{
YoggieEngine::Vertex data = YoggieEngine::Vertex();
AssetFile.read((char*)&data, Vsize);
imported->vertices.push_back(data);
}
// skip x bytes
AssetFile.ignore(sizeof(char) * 3);
// Load Elements
imported->elements = std::vector<unsigned int>();
for (int i = 0; i < Enum; i++) {
unsigned int data = 0;
AssetFile.read((char*)&data, sizeof(unsigned int));
imported->elements.push_back(data);
}
}
else {
std::cout << "Failed ot open mesh " << std::endl;
}
return imported;
}
YoggieEngine::Renderable* AssetManager::LoadFromSource(const std::filesystem::path srcPath, const std::filesystem::path assetFolder)
{
auto model = (YoggieEngine::ModelImporter()).Import(srcPath.string());
YoggieEngine::Mesh* exportMesh = model->renderable->mesh;
std::filesystem::path MeshFileName = assetFolder / srcPath.filename().replace_extension(".mesh");
std::cout << "Save path: " << MeshFileName << std::endl;
std::ofstream meshAsset;
meshAsset.open(MeshFileName, std::ios::binary);
if (meshAsset.is_open()) {
// write a header
static const char* HEADER = "MESH";
meshAsset.write(HEADER, sizeof(HEADER));
auto Vsize = sizeof(YoggieEngine::Vertex);
std::cout << "size of vertex: " << Vsize << std::endl;
std::cout << "Addr of vSize: " << &Vsize << std::endl;
auto Vnum = exportMesh->vertices.size();
auto Enum = exportMesh->elements.size();
meshAsset.write((char*)&Vsize, sizeof(unsigned long long));
meshAsset.write((char*)&Vnum, sizeof(uint32_t));
meshAsset.write((char*)&Enum, sizeof(uint32_t));
// write all vertices
for (auto& vertice : exportMesh->vertices)
{
meshAsset.write((char*)&vertice, sizeof(vertice));
}
// write 3 x 0 byte
meshAsset.write((const char*)"\0\0\0", sizeof(char) * 3);
// write all indices
for (auto index : exportMesh->elements) {
meshAsset.write((char*)&index, sizeof(index));
}
meshAsset.close();
}
else {
spdlog::error("Failed to create/open mesh file.");
}
return model->renderable;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include <vector>
#include "Asset.h"
class AssetManager {
public:
static void Init();
static void BuildAssetView();
static void setAssetPath(std::filesystem::path path);
static YoggieEngine::Mesh* LoadFromAssetFile(const std::filesystem::path assetPath);
static YoggieEngine::Renderable* LoadFromSource(const std::filesystem::path srcPath, const std::filesystem::path assetFolder);
static std::vector<Asset> assets ;
private:
static std::filesystem::path currentPath;
};

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;
@ -31,9 +31,9 @@ public:
location = std::string(path);
break;
case(NFD_CANCEL):
std::cout << "NFD_CANCEL" << std::endl;
spdlog::info("NFD_CANCEL" );
case (NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
spdlog::error("NFD_Error: {0}" , NFD_GetError() );
break;
};

19
Editor/src/EditorCamera.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
class EditorCamera : public YoggieEngine::Camera {
public:
EditorCamera () : Camera(){
Front = glm::vec3(0.0f, 0.0f, 1.0f);
Right = glm::vec3(-1.0f, 0.0f, 0.0f);
Up = glm::vec3(0.0f, 1.0f, 0.0f);
}
private:
glm::vec3 Front;
glm::vec3 Right;
glm::vec3 Up;
};

517
Editor/src/EditorLayer.h Normal file
View File

@ -0,0 +1,517 @@
#pragma once
#include <iostream>
#include <mini/ini.h>
#include <nfd.h>
#include <ImGuizmo.h>
#include <memory>
#include "Inspector.h"
#include "Console.h"
#include "IconsMaterialDesign.h"
#include "Project.h"
#include "EditorCamera.h"
using namespace YoggieEngine;
class EditorLayer : public Layer {
public:
EditorLayer() : Layer()
{
Logo.Load("rsc/Yoggie.png");
Selected = YoggieEngine::Entity{ (entt::entity)-1, (scene.get()) };
}
void OnStartup() override {
std::string path = (std::filesystem::current_path()).string();
scene = std::make_unique<Scene>();
project = std::make_unique<Project>();
project.get()->setProjectDirectory(path);
LoadLastOrEmptyProject();
//Console console = Console();
}
void OnUpdate() override {
scene.get()->Update();
renderer.get()->Render(*scene, *camera);
}
void OnUI() override {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { ImGui::GetWindowWidth(), 7 });
ImGui::BeginMainMenuBar();
int scaleFactor = 30;
ImGui::Image((ImTextureID)Logo.GetID(), { Logo.getSize().x / scaleFactor , Logo.getSize().y / scaleFactor });
ImGui::PopStyleVar();
if (ImGui::BeginMenu("App")) {
if (ImGui::MenuItem("Load Project"))
{
nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
//Project::LoadProject(path, project);
//AssetRegistry::setAssetPath(project.GetProjectDirectory());
//AssetRegistry::BuildAssetView();
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
spdlog::error("NFD_Error: {0}", NFD_GetError());
break;
}
}
if (ImGui::MenuItem("Save project as...")) {
nfdresult_t result = NFD_SaveDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
spdlog::info("Save as: {0}", path);
//Project::SaveProject(path, project);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
spdlog::error("NFD_Error: {0}", NFD_GetError());
break;
}
}
ImGui::EndMenu();
}
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);
//project.AddScene(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
/*
AssetRegistry::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):
{
}
break;
case(NFD_CANCEL):
spdlog::debug("User cancelled action");
break;
case(NFD_ERROR):
spdlog::warn("Something went wrong!");
break;
}
}
ImGui::EndMenu();
}
ImGui::SameLine(ImGui::GetWindowWidth() / 4 * 3);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.3f, 0.3f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::Button(ICON_MD_ROCKET_LAUNCH "Project");
ImGui::SameLine(ImGui::GetWindowWidth() - 120);
ImGui::PopStyleColor(1);
ImGui::PopStyleVar();
ImGui::EndMainMenuBar();
ImGui::Begin("RuntimeControls");
ImGui::BeginGroup();
ImGui::SameLine();
ImGui::Text(ICON_MD_TRANSFORM);
auto spacing = 10;
float buttonWidth = 75.0f;
float buttonHeight = 30;
float ColorIntensity = 0.5f;
float ColorIntensityHovered = 0.75;
float ColorIntensityActive = 0.85;
float yPadding = 6.f;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{0, yPadding });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.0f,ColorIntensity ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.0f,ColorIntensityHovered ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.0f,ColorIntensityActive ,0.0f ,1.0f });
ImGui::SameLine(0, spacing);
if (ImGui::Button("Translate", { buttonWidth,buttonHeight }))
activeOperation = ImGuizmo::OPERATION::TRANSLATE;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 0, yPadding });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ ColorIntensity, 0.0f ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ ColorIntensityHovered, 0.0f ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ ColorIntensityActive, 0.0f ,0.0f ,1.0f });
ImGui::SameLine(0, spacing);
if (ImGui::Button("Rotate", { buttonWidth,buttonHeight }))
activeOperation = ImGuizmo::OPERATION::ROTATE;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 0, yPadding });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.0f, 0.0f ,ColorIntensity ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.0f, 0.0f ,ColorIntensityHovered ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.0f, 0.0f ,ColorIntensityActive ,1.0f });
ImGui::SameLine(0, spacing);
if (ImGui::Button("Scale", { buttonWidth,buttonHeight }))
activeOperation = ImGuizmo::OPERATION::SCALE;
ImGui::PopStyleColor(9);
ImGui::PopStyleVar(3);
ImGui::EndGroup();
ImGui::SameLine((ImGui::GetWindowContentRegionMax().x / 2) - (90));
auto color = ImVec4{ 0.001 * 12 , 0.001 * 201 , 0.001 * 69, 1.0f };
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(ICON_MD_PLAY_ARROW, { 90,25 })) {
// Play game
}
ImGui::PopStyleColor(2);
ImGui::SameLine();
color = ImVec4{ 0.001 * 14, 0.001 * 157, 0.001 * 201, 1.0f };
ImGui::PushStyleColor(ImGuiCol_Button, color);
ImGui::PushStyleColor(
ImGuiCol_ButtonHovered,
ImVec4{
color.x * strengthIncrease,
color.y * strengthIncrease,
color.z * strengthIncrease,
color.w
}
);
if (ImGui::Button(ICON_MD_ELECTRIC_BOLT, { 90,25 })) {
// Simulate physics
}
ImGui::PopStyleColor(2);
ImGui::End();
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoDecoration
| ImGuiWindowFlags_NoScrollbar
| ImGuiWindowFlags_NoMove
| ImGuiWindowFlags_NoCollapse;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0,0 });
ImGui::Begin("SceneView",nullptr,viewportWindowFlags);
// spdlog::info("{0}x{1}", ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
SceneisFocused = ImGui::IsWindowFocused() || ImGui::IsWindowHovered();
ImGui::Image((ImTextureID)(intptr_t)renderer.get()->getCurrentFrameBuffer().GetColourAttachment(),
ImVec2{(float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight()});
//ImGuizmo::ViewManipulate(glm::value_ptr(cameraView), 1, ImGui::GetWindowPos(), { 90,90 }, 0x22CCCCCCC);
if(Selected.isValid()){
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
const auto& ProjMatrix = camera->getProjection(ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
const glm::mat4& viewMatrix = glm::inverse(camera->getTransform());
auto& tc = Selected.GetComponent<YoggieEngine::TransformComponent>();
auto transform = tc.GetTransform();
ImGuizmo::Manipulate(
glm::value_ptr(viewMatrix),
glm::value_ptr(ProjMatrix),
activeOperation, ImGuizmo::LOCAL, glm::value_ptr(transform));
if (ImGuizmo::IsUsing())
{
tc.Decompose(transform);
}
}
ImGui::End();
ImGui::PopStyleVar();
ImGui::Begin("EditorCamera");
ImGui::SliderFloat3("position", glm::value_ptr(camera->Position), -50, 50);
ImGui::End();
ImGui::Begin(ICON_MD_MENU "SceneExplorer",nullptr);
scene.get()->getReg().each([&](entt::entity enttNumber) {
YoggieEngine::Entity entity = YoggieEngine::Entity(enttNumber, &*scene.get());
auto id = entity.GetComponent<YoggieEngine::IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), entity == Selected)) {
Selected = YoggieEngine::Entity(enttNumber, &*scene);
}
});
ImGui::End();
{
ImGui::Begin("Asset", nullptr);
const char* hidden_extensions[]{
".exe",
".pdb",
".idb",
".dll",
".ini"
};
std::vector <Asset> files = std::vector<Asset>();
int iconSize = 60;
int maxColumns = 3;
YoggieEngine::Texture folderIcon;
YoggieEngine::Texture assetIcon;
//assetIcon = YoggieEngine::Texture("rsc/AssetIcon.png");
ImGui::DragInt("IconSize", &iconSize, 1, 30, 90);
ImGui::DragInt("Max. Columns", &maxColumns, 1, 1, 6);
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 : files) {
if (column % 3 == 0) {
ImGui::TableNextRow();
column = 0;
row++;
}
ImGui::TableSetColumnIndex(column);
ImGui::ImageButton(
(ImTextureID)assetIcon.GetID(),
ImVec2{ (float)iconSize, (float)iconSize });
ImGui::Text(asset.Handle.String().c_str(), row);
column++;
}
ImGui::PopStyleColor(3);
ImGui::EndTable();
}
ImGui::End();
}
ImGui::ShowDemoWindow();
//ImGui::ShowMetricsWindow();
}
void OnCreate() override {
spdlog::info(" Layer Create!" );
}
void OnDestroy() override {
spdlog::info( " Layer Destroy!" );
}
bool OnKey(int key, int mode) override {
float movement_speed = 0.10f;
if (SceneisFocused) {
if (key == YOGGIE_KEY_UP)
camera->Rotation.x += movement_speed;
if (key == YOGGIE_KEY_DOWN)
camera->Rotation.x -= movement_speed;
if (key == YOGGIE_KEY_LEFT)
camera->Rotation.y += movement_speed;
if (key == YOGGIE_KEY_RIGHT)
camera->Rotation.y -= movement_speed;
if (key == YOGGIE_KEY_A)
camera->Position += glm::vec3(1.0f, 0.0f, 0.0f) * movement_speed;
if (key == YOGGIE_KEY_S)
camera->Position += glm::vec3(0.0f, 0.0f, -1.0f) * movement_speed;
if (key == YOGGIE_KEY_D)
camera->Position -= glm::vec3(1.0f, 0.0f, 0.0f) * movement_speed;
if (key == GLFW_KEY_W)
camera->Position -= glm::vec3(0.0f, 0.0f, -1.0f) * movement_speed;
}
return true;
}
private:
std::unique_ptr<Inspector> inspector = std::make_unique<Inspector>(Selected);
std::unique_ptr<Renderer> renderer = std::make_unique<Renderer>();
std::unique_ptr<EditorCamera> camera = std::make_unique<EditorCamera>();
std::unique_ptr<Project> project;
std::unique_ptr<Scene> scene;
Texture Logo;
bool SimulatePhysics = true;
bool SceneisFocused = false;
YoggieEngine::Entity Selected;
ImGuizmo::OPERATION activeOperation = ImGuizmo::OPERATION::TRANSLATE;
char* path = nullptr;
void LoadLastOrEmptyProject() {
// Check if there is a last known loaded project and
// load that one .
// Otherwise load no project..
// OR
// Load an empty project.
mINI::INIStructure ini;
if (std::filesystem::exists("build\\Debug\\Editor.ini"))
{
mINI::INIFile file("build\\Debug\\Editor.ini");
file.read(ini);
}
else
{
spdlog::debug("Could not find an `Editor.ini` file.");
}
if (ini["editor"]["openlastproject"] == "TRUE")
{
Project::LoadProject(ini["cache"]["project"], *project);
///LoadScene(ini["cache"]["scene"], scene);
}
else
{
spdlog::debug("Starting without a project. Please create one.");
}
}
};

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

@ -0,0 +1,27 @@
#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(), nullptr, flags);
Draw();
ImGui::End();
}
~EditorWindow() = default;
protected:
std::string name;
private:
ImGuiWindowFlags_ flags;
virtual void Draw() = 0;
};

File diff suppressed because it is too large Load Diff

197
Editor/src/Inspector.cpp Normal file
View File

@ -0,0 +1,197 @@
#include "Inspector.h"
#include "TransformVec3.h"
#include "IconsMaterialDesign.h"
void Inspector::Draw()
{
if (selected.isValid()) {
AddComponentDropDown();
ShowComponents();
}
}
void AddComponent(YoggieEngine::Entity selected , int i) {
switch (i) {
case 0:
selected.AddComponent<YoggieEngine::ScriptComponent>();
break;
case 1:
selected.AddComponent<YoggieEngine::CameraComponent>();
break;
case 2:
selected.AddComponent<YoggieEngine::LightComponent>();
break;
case 3:
selected.AddComponent<YoggieEngine::Render3DComponent>();
default:
break;
}
}
void Inspector::AddComponentDropDown()
{
static char* names[] = { "Script Component", "Camera Component", "Light Component", "Render3D"};
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]))
AddComponent(selected, i);
}
ImGui::EndPopup();
}
ImGui::NewLine();
}
void Inspector::ShowComponents()
{
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::PushStyleColor(ImGuiCol_Button, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
ImGui::SetCursorPosX(ImGui::GetContentRegionMax().x - 20);
ImGui::Button(ICON_MD_SETTINGS, { 20,20 });
ImGui::OpenPopupOnItemClick("##myContext", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopupContextWindow("##myContext")) {
if (ImGui::MenuItem("Reset")) {
spdlog::info("Reset component");
}
if (ImGui::MenuItem("Copy Component")) {
spdlog::info("Copy component");
}
ImGui::EndPopup();
}
ImGui::PopStyleColor(3);
/*
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);
*/
auto something = glm::value_ptr(transform.Position);
ImGuiExtension::TransformVec3("Position", transform.Position);
ImGuiExtension::TransformVec3("Rotation", transform.Rotation);
ImGuiExtension::TransformVec3("Scale", transform.Scale);
}
if (selected.HasComponent<YoggieEngine::RelationComponent>()) {
ImGui::Text("Has relation");
}
}
if (selected.HasComponent<YoggieEngine::Render3DComponent>()) {
auto& render3d = selected.GetComponent<YoggieEngine::Render3DComponent>();
const char* AssetNames[]{ "Asset1" , "Asset2" };
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
if (ImGui::Button("Select Renderable Asset"))
ImGui::OpenPopup("Renderable_list_popup");
ImGui::SameLine();
ImGui::TextUnformatted(render3d.mesh.elements.empty() ? "<None>" : "ASSET_GUID_OR_ID");
if (ImGui::BeginPopup("Renderable_list_popup")) {
ImGui::Text("None");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(AssetNames); i++) {
if(ImGui::Selectable(AssetNames[i]))
{ }
}
ImGui::EndPopup();
}
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>()) {
const char* AssetNames[]{ "Script 1" , "Script 2" };
if (ImGui::CollapsingHeader("Script", ImGuiTreeNodeFlags_Leaf)) {
if (ImGui::Button("Select Renderable Asset"))
ImGui::OpenPopup("Scripts_list_popup");
if (ImGui::BeginPopup("Scripts_list_popup")) {
ImGui::Text("None");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(AssetNames); i++) {
if (ImGui::Selectable(AssetNames[i]))
{
}
}
ImGui::EndPopup();
}
ImGui::SameLine();
std::string scriptAssetId = "<Random_GUID>";
ImGui::InputText("asset", scriptAssetId.data(), scriptAssetId.length(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll);
}
}
}
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();
}

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

@ -0,0 +1,22 @@
#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( YoggieEngine::Entity& selected ) : EditorWindow("Inspector"), selected(selected){}
void Draw()override;
private:
void AddComponentDropDown();
void ShowComponents();
YoggieEngine::Entity& selected;
};

View File

@ -13,6 +13,15 @@ void Project::SaveProject(std::filesystem::path path, Project& project)
projectYAML << YAML::Key << "Project" << YAML::Value << project.Name;
projectYAML << YAML::Key << "Directory" << YAML::Value << path.parent_path().u8string();
projectYAML << YAML::EndMap;
projectYAML << YAML::BeginMap;
projectYAML << YAML::Key << "Scenes" << YAML::Value << YAML::BeginSeq;
for (auto scene : project.Scenes) {
projectYAML << scene->name;
}
projectYAML << YAML::EndSeq;
std::ofstream projectFile;
projectFile.open(path.u8string());
@ -20,8 +29,13 @@ 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)
{
if (!std::filesystem::exists(path)) {
throw std::runtime_error("Couldn't find project file!");
}
std::string YAMLProject;
std::stringstream sstream;
std::ifstream projectFile;
@ -36,10 +50,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;
spdlog::info("loaded project {0}", project.Name);
@ -55,12 +68,19 @@ namespace YAML {
{
if (!node.IsMap())
return false;
rhs.setName(node["Project"].as<std::string>());
rhs.setProjectDirectory(node["Directory"].as<std::string>());
std::string projectName = node["Project"].as<std::string>();
rhs.setName(projectName);
std::string projectDirectory = node["Directory"].as<std::string>();
rhs.setProjectDirectory(projectDirectory);
return true;
}
};
}

View File

@ -1,11 +1,15 @@
#pragma once
#include <filesystem>
#include <iostream>
#include "../../YoggieEngine/src/YoggieEngine.h"
#include <yaml-cpp/yaml.h>
class Project {
public:
Project() = default;
Project(const std::string& name): Name(name){}
~Project() { std::cout << "Unloading project..." << Name << std::endl; }
~Project() { spdlog::info("Unloading project {0}...", Name);}
void setName(std::string& name) { Name = name; }
const std::string& GetName()const { return Name; }
@ -13,10 +17,21 @@ public:
void setProjectDirectory(std::string& path) { ProjectDirectory = std::filesystem::path(path); }
const std::filesystem::path GetProjectDirectory() { return ProjectDirectory; }
void AddScene(YoggieEngine::Scene& scene)
{
Scenes.push_back(&scene);
}
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;
std::vector<YoggieEngine::Scene*> Scenes;
friend class YAML::convert<Project>;
};

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

@ -0,0 +1,59 @@
#pragma once
#include <imgui_widgets.cpp>
#include <glm/glm.hpp>
namespace ImGuiExtension {
void TransformVec3(const char* label, glm::vec3& vector) {
ImGui::PushID(label);
ImGui::Columns(2);
ImGui::SetColumnWidth(0, 100.0f);
ImGui::Text(label);
ImGui::NextColumn();
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.9f,0.2f,0.2f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.8f,0.1f,0.15f, 1.0f });
if (ImGui::Button("X"))
vector.x = 0;
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::DragFloat("##X", &glm::value_ptr(vector)[0], 0.1f, 0.0f, 0.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.3f,0.8f,0.3f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.2f,0.7f,0.2f, 1.0f });
if (ImGui::Button("Y"))
vector.y = 0;
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::DragFloat("##Y", &glm::value_ptr(vector)[1], 0.1f, 0.0f, 0.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.2f,0.35f,0.9f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.1f,0.25f,0.8f, 1.0f });
if (ImGui::Button("Z"))
vector.z = 0;
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::DragFloat("##Z", &glm::value_ptr(vector)[2], 0.1f, 0.0f, 0.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::PopStyleVar();
ImGui::Columns(1);
ImGui::PopID();
}
}

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,14 +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,71 +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,361 +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>();
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));
}
}
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::ViewManipulate(glm::value_ptr(transposed_view), 1, { ScreenSpaceMin.x,ScreenSpaceMin.y }, { 90,90 }, 0x22CCCCCC);
ImGuizmo::DrawGrid(glm::value_ptr(cam.ViewMatrix), glm::value_ptr(cam.ProjectionMatrix), glm::value_ptr(worldOrigin), 100.0f);
// Matrix is the model matrix we would want to manipulate
//ImGuizmo::Manipulate(glm::value_ptr(cam.ViewMatrix), glm::value_ptr(cam.ProjectionMatrix), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(cam.ViewMatrix));
}
};
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

@ -1,227 +1,17 @@
#include "../../YoggieEngine/src/EntryPoint.h"
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include "../../YoggieEngine/src/Physics/Physics.h"
#include "EditorLayer.h"
#include "EntryPoint.h"
#include <stack>
#include <nfd.h>
using namespace YoggieEngine;
#include <glm/glm.hpp>
#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/AssetManager.h"
#include "UI/MainMenuBar.h"
const unsigned int MS_PER_UPDATE = 2;
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(12.0f, 1.0f, 0.0f), glm::vec3(45.0f, 0.0f, 0.0f), 90);
class Editor : public Application {
public:
Editor()
: Application("Editor"),
AppWindow(1200,700),
framebuffer(new Framebuffer(1200,700)),
viewportRenderer(EditorSceneRendererConfig),
EditorGUIRenderer(AppWindow),
Selected((entt::entity)-1)
{
viewportRenderer.setCurrentFrameBuffer(*framebuffer);
}
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
{
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());
}
{
RuntimeControls rc = RuntimeControls();
}
{
SceneExplorer explorer(Selected, ActiveScene);
}
{
Inspector inspector = Inspector();
if (ActiveScene.getReg().valid(Selected)) {
Entity SelectedEntity = Entity(Selected, &ActiveScene);
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();
double previous = glfwGetTime();
double lag = 0.0;
while (!AppWindow.WindowShouldClose())
{
double current = glfwGetTime();
double elapsed = current - previous;
previous = current;
lag += elapsed;
AppWindow.Poll();
if (SimulatePhysics)
{
Physics.Step(1.0f / 60.0f);
}
while (lag >= MS_PER_UPDATE)
{
ActiveScene.Update();
lag -= MS_PER_UPDATE;
}
RenderScene();
RenderEditorGUI();
AppWindow.SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
}
delete framebuffer;
ActiveScene.Stop();
}
private:
NativeWindow AppWindow;
Framebuffer* framebuffer;
Renderer viewportRenderer;
GUIRenderer EditorGUIRenderer;
// Editor State
bool SimulatePhysics = false;
entt::entity Selected;
std::unique_ptr<Project> CurrentProject;
Scene ActiveScene;
Editor() : Application("Editor") {}
void Run() override {
PushLayer(new EditorLayer());
Application::Run();
}
};
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);
}
YoggieEngine::Application *CreateApplication() { return new Editor(); }

View File

@ -1,18 +0,0 @@
project "ImGui"
kind "StaticLib"
includedirs {
"../libs/glfw/include",
"../libs/ImGui"
}
files {
"../libs/ImGui/*.cpp",
"../libs/ImGui/backends/imgui_impl_glfw.cpp",
"../libs/ImGui/backends/imgui_impl_Opengl3.cpp",
}
libdirs{
"../libs/ImGui",
"../libs/glad"
}

View File

@ -1,19 +0,0 @@
project "ImGuizmo"
kind "StaticLib"
includedirs {
"../libs/glfw/include",
"../libs/ImGui",
"../libs/guizmo"
}
files {
"../libs/guizmo/*.cpp",
}
libdirs{
"../libs/ImGui",
"../libs/glad"
}
include("../ImGui")

View File

@ -1,39 +0,0 @@
project "Runtime"
kind "ConsoleApp"
buildmessage "Building the runtime ..."
links{
"YoggieEngine"
}
includedirs{
"./../YoggieEngine/src",
-- I'd prefer if didn't need these..
-- We'll figure that out some time later
"./../libs/lua/include",
"./../libs/spdlog/include",
"./../libs/glm",
"./../libs/GorillaAudio/include",
"./../libs/assimp/include",
"./../libs/glad/include",
"./../libs/glfw/include",
"./../libs/tinygltf",
"./../libs/glew/include",
"./../libs/glm",
"./../libs/ImGui",
"./include"
}
libdirs {
'./../YoggieEngine/build/Debug'
}
files {
"./src/*.h",
"./src/*.cpp"
}

View File

@ -1,6 +0,0 @@
#include <iostream>
int main()
{
std::cout << "Welcome to the runtime!" << std::endl;
}

View File

@ -0,0 +1,6 @@
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB HEADER_FILES "src/*.h")
add_executable(SandboxApp ${SOURCE_FILES} ${HEADER_FILES} )
target_link_directories(SandboxApp PRIVATE "../build/YoggieEngine/Debug")
target_link_libraries(SandboxApp YoggieEngine)
target_include_directories(SandboxApp PRIVATE "../YoggieEngine/src")

View File

@ -1,40 +0,0 @@
project "SandboxApp"
kind "ConsoleApp"
buildmessage "Building SandboxApp ..."
links{
"YoggieEngine"
}
includedirs{
"./../YoggieEngine/Include",
-- I'd prefer if didn't need these..
-- We'll figure that out some time later
"./../libs/lua/include",
"./../libs/spdlog/include",
"./../libs/glm",
"./../libs/GorillaAudio/include",
"./../libs/assimp/include",
"./../libs/glad/include",
"./../libs/glfw/include",
"./../libs/tinygltf",
"./../libs/glew/include",
"./../libs/glm",
"./../libs/ImGui",
"../libs/entt/src",
}
libdirs {
'./../YoggieEngine/build/Debug'
}
files {
"./src/*.h",
"./src/*.cpp"
}

View File

@ -1,11 +1,10 @@
#pragma once
#include "YoggieEngine.h"
#include "imgui.h"
#include "../../YoggieEngine/src/BarinkEngine.h"
#include "../../YoggieEngine/src/Graphics/Memory/Framebuffer.h"
void CameraTool();
void ScriptingTool(char* code);
///void transformWindow(Transform& transform, std::string PanelName);
void materialWindow(Material& material, std::string PanelName);
void SceneExplorer(const std::string& PanelName);
void SceneView(Framebuffer& framebuffer);
void ScriptingTool(char *code);
/// void transformWindow(Transform& transform, std::string PanelName);
void materialWindow(Material &material, std::string PanelName);
void SceneExplorer(const std::string &PanelName);
void SceneView(Framebuffer &framebuffer);

View File

@ -1,123 +1,102 @@
#include <imgui.h>
#include "GUI.h"
#include "Util.h"
#include <entt/entt.hpp>
#include <imgui.h>
#include "../../YoggieEngine/src/BarinkEngine.h"
#include "../../YoggieEngine/src/Scene/Components.h"
#include "../../YoggieEngine/src/Scene/Scene.h"
#include "../../YoggieEngine/src/Scene/Entity.h"
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include "../../YoggieEngine/src/PerfCounter.h"
#include "YoggieEngine.h"
/*
* Define globals
*/
* Define globals
*/
Scene scene;
BarinkEngine::Renderable* renderable;
BarinkEngine::SceneObject* object;
BarinkEngine::Renderable *renderable;
BarinkEngine::SceneObject *object;
Entity cube;
/*
* Runs once at startup
* - USe to initialize the game/sandbox/demo
*/
* Runs once at startup
* - USe to initialize the game/sandbox/demo
*/
void Start() {
auto importer = BarinkEngine::ModelImporter();
auto importer = BarinkEngine::ModelImporter();
// Load in asset(S)
object = importer.Import("build/Debug/Models/Cube.obj");
renderable = object->renderable;
// Load in asset(S)
object = importer.Import("build/Debug/Models/Cube.obj");
renderable = object->renderable;
// Add Entities to the scene
cube = scene.AddEntity("cube");
auto &render3DComponent =
cube.AddComponent<BarinkEngine::Render3DComponent>();
render3DComponent.mesh = *renderable->mesh;
cube.GetComponent<BarinkEngine::TransformComponent>().transform =
glm::rotate(glm::mat4(1.0f), 32.0f, glm::vec3(0.5f, 1.0f, 0.0f));
// Add Entities to the scene
cube = scene.AddEntity("cube");
auto& render3DComponent = cube.AddComponent<BarinkEngine::Render3DComponent>();
render3DComponent.mesh = *renderable->mesh;
cube.GetComponent<BarinkEngine::TransformComponent>()
.transform = glm::rotate(glm::mat4(1.0f), 32.0f, glm::vec3(0.5f,1.0f,0.0f));
// Create a second cube
auto cube2 = scene.AddEntity("Cube2");
auto &cube2Render = cube2.AddComponent<BarinkEngine::Render3DComponent>();
cube2Render.mesh = *renderable->mesh;
cube2Render.color = glm::vec3(0.0f, 1.0f, 0.0f);
auto &cube2Trans = cube2.GetComponent<BarinkEngine::TransformComponent>();
cube2Trans.transform =
glm::translate(glm::mat4(1.0f), glm::vec3(1.0f, 0.0f, 5.0f));
// Create a second cube
auto cube2 = scene.AddEntity("Cube2");
auto& cube2Render = cube2.AddComponent<BarinkEngine::Render3DComponent>();
cube2Render.mesh = *renderable->mesh;
cube2Render.color = glm::vec3(0.0f, 1.0f, 0.0f);
auto& cube2Trans = cube2.GetComponent<BarinkEngine::TransformComponent>();
cube2Trans.transform = glm::translate( glm::mat4(1.0f), glm::vec3(1.0f,0.0f, 5.0f));
// Create a light
auto AmbientLight = scene.AddEntity("AmbientLight");
AmbientLight.AddComponent<BarinkEngine::LightComponent>();
renderer.Prepare(scene);
}
/*
* Runs every frame
* - Use to draw Immediate mode graphics (Not meant for HUD's )
*/
void ImmediateGraphicsDraw()
{
// Show internal BarinkEngine stats
EngineInstrumentation::ShowStats();
ImGui::Begin("Scene view");
auto group = scene.getReg().view<BarinkEngine::IdentifierComponent>();
group.each([](auto entity, BarinkEngine::IdentifierComponent& identifier) {
ImGui::Text("%s", identifier.name.c_str());
});
ImGui::End();
ImGui::ShowMetricsWindow();
ImGui::Begin("Settings");
auto& a = cube.GetComponent<BarinkEngine::Render3DComponent>();
auto& b = cube.GetComponent<BarinkEngine::TransformComponent>();
ImGui::DragFloat3("Color", &a.color[0], 0.01f, 0.0f, 1.0f);
ImGui::DragFloat3("Position", &b.transform[3][0], 0.01f, 0.0f, 16.0f);
auto l = scene.getReg().view<BarinkEngine::LightComponent>();
l.each([](auto entity, BarinkEngine::LightComponent& light) {
ImGui::Text("Lighting");
ImGui::SliderFloat("Intensity", &light.Strength, 0.0f, 1.0f);
ImGui::SliderFloat3("l-Color", &light.Color[0], 0.0f, 1.0f);
});
ImGui::End();
// Create a light
auto AmbientLight = scene.AddEntity("AmbientLight");
AmbientLight.AddComponent<BarinkEngine::LightComponent>();
renderer.Prepare(scene);
}
/*
* Runs every frame
* - Meant for game logic ( non-physics related)
*/
void Update()
{
}
* Runs every frame
* - Use to draw Immediate mode graphics (Not meant for HUD's )
*/
void ImmediateGraphicsDraw() {
// Show internal BarinkEngine stats
EngineInstrumentation::ShowStats();
void Render()
{
renderer.Render(scene);
ImGui::Begin("Scene view");
auto group = scene.getReg().view<BarinkEngine::IdentifierComponent>();
group.each([](auto entity, BarinkEngine::IdentifierComponent &identifier) {
ImGui::Text("%s", identifier.name.c_str());
});
ImGui::End();
ImGui::ShowMetricsWindow();
ImGui::Begin("Settings");
auto &a = cube.GetComponent<BarinkEngine::Render3DComponent>();
auto &b = cube.GetComponent<BarinkEngine::TransformComponent>();
ImGui::DragFloat3("Color", &a.color[0], 0.01f, 0.0f, 1.0f);
ImGui::DragFloat3("Position", &b.transform[3][0], 0.01f, 0.0f, 16.0f);
auto l = scene.getReg().view<BarinkEngine::LightComponent>();
l.each([](auto entity, BarinkEngine::LightComponent &light) {
ImGui::Text("Lighting");
ImGui::SliderFloat("Intensity", &light.Strength, 0.0f, 1.0f);
ImGui::SliderFloat3("l-Color", &light.Color[0], 0.0f, 1.0f);
});
ImGui::End();
}
/*
* Runs at the end of the program
* - Meant for cleanup
*/
void Stop()
{
}
* Runs every frame
* - Meant for game logic ( non-physics related)
*/
void Update() {}
void Render() { renderer.Render(scene); }
/*
* Runs at the end of the program
* - Meant for cleanup
*/
void Stop() {}

View File

@ -1,6 +1,6 @@
#pragma once
#include "../../YoggieEngine/src/BarinkEngine.h"
#include "YoggieEngine.h"
//void PrintSceneTree(Node& node, int depth);
// void PrintSceneTree(Node& node, int depth);
//glm::mat4 CalculateModelMat(Transform& transform);
// glm::mat4 CalculateModelMat(Transform& transform);

View File

@ -0,0 +1,22 @@
file(GLOB SOURCE_FILES src/*.cpp)
add_library(YoggieEngine ${SOURCE_FILES} )
#target_precompile_headers(YoggieEngine PUBLIC src/YoggieEngine.h )
target_link_directories(YoggieEngine PUBLIC
"../libs/physx/physx/bin/win.x86_64.vc142.md/debug"
)
target_link_libraries(YoggieEngine
thirdparty_tools
PhysX_64
PhysXCooking_64
PhysXCommon_64
PhysXFoundation_64
PhysXPvdSDK_static_64
PhysXExtensions_static_64
)
target_include_directories(YoggieEngine PUBLIC
"../libs/physx/pxshared/include"
"../libs/physx/physx/include"
)

View File

@ -1,83 +0,0 @@
project "YoggieEngine"
kind "StaticLib"
pchheader "YoggieEngine.h"
pchsource "src/YoggieEngine.cpp"
buildmessage "Building Yoggie Engine"
disablewarnings{
"4099" -- Ignore the missing debug signals for GLFW warning
}
includedirs {
"./src",
"../libs/spdlog/include",
"../libs/glm",
"../libs/glfw/include",
"../libs/glew/include",
"../libs/glad/include",
"../libs/assimp/include",
"../libs/entt/src",
"../libs/physx/pxshared/include",
"../libs/physx/physx/include",
"../libs/lua/include",
"../libs/GorillaAudio/include",
"../libs/steam-audio/include",
"../libs/ImGui",
}
links {
-- This needs to fall under the filter as the names can differ on different platforms
"phonon",
"lua54",
"spdlog",
"assimp-vc143-mtd",
"glfw3",
"ImGui",
"PhysX_64",
"PhysXCooking_64",
"PhysXCommon_64",
"PhysXFoundation_64",
"PhysXPvdSDK_static_64",
"PhysXExtensions_static_64"
}
libdirs {
"../libs/steam-audio/lib/windows-x64",
"../libs/lua",
"../libs/spdlog/build/Release",
"../libs/assimp/lib/Debug",
"../libs/glfw/build/src/Debug",
"../libs/physx/physx/bin/win.x86_64.vc142.md/debug"
}
files {
"./src/**.cpp",
"./src/**.h"
}
prebuildcommands
{
ok,err = os.copyfile("YoggieEngine/src/Graphics/shaders/*" ,"SandboxApp/build/Debug/")
}
postbuildcommands
{
ok,err = os.copyfile("YoggieEngine/build/Debug/intermediates/YoggieEngine.pch", "YoggieEngine/build/Debug/YoggieEngine.pch")
}

View File

@ -1,20 +1,161 @@
#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"
#include "../../Editor/src/IconsMaterialDesign.h"
namespace YoggieEngine {
Application::Application(const std::string& name)
: m_AppName(name)
{
appWindow = CreateNativeWindow(1200, 700, m_AppName.c_str());
// 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);
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 18.0f;
static const ImWchar icon_ranges[] = { ICON_MIN_MD , ICON_MAX_MD, 0 };
io.Fonts->AddFontFromFileTTF("build/Debug/Fonts/MaterialIcons-Regular.ttf", 24, &config, icon_ranges);
ImGui::StyleColorsDark();
/*
ImGuiStyle* style = &ImGui::GetStyle();
ImVec4* colors = style->Colors;
colors[ImGuiCol_TitleBg] = ImVec4(0.72f, 0.24f, 0.87f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.72f, 0.24f, 0.87f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.53f, 0.09f, 0.67f, 1.00f);
*/
ImGui_ImplGlfw_InitForOpenGL((GLFWwindow*)appWindow->GetHandle(), true);
ImGui_ImplOpenGL3_Init("#version 450");
ImGuizmo::SetImGuiContext(ImGui::GetCurrentContext());
//ImGuizmo::SetOrthographic(true);
//init_inputSystem(appWindow);
glfwSetWindowUserPointer((GLFWwindow*)this->appWindow->GetHandle(), this);
glfwSetKeyCallback((GLFWwindow*)this->appWindow->GetHandle(), HandleKey);
}
void Application::HandleKey(GLFWwindow* window, int key, int scancode, int action, int mods) {
auto app = (Application*)glfwGetWindowUserPointer(window);
for (auto i = app->AppLayerstack.begin(); i < app->AppLayerstack.end(); i++) {
if ((*i)->OnKey(key, action)) {
break;
}
}
}
void Application::Run() {
std::cout << "No run function implemented!";
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnStartup();
}
double previous = glfwGetTime();
double lag = 0.0;
while (!appWindow->WindowShouldClose()) {
PollEvents();
double now = glfwGetTime();
double elapsed = now - previous;
previous = now;
lag += elapsed;
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnUpdate();
}
GuiBegin();
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnUI();
}
GuiEnd();
SwapBuffers();
}
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnDestroy();
}
}
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);
}
}
void Application::PushLayer(Layer* layer)
{
AppLayerstack.PushLayer(layer);
layer->OnAttach();
}
Application::~Application() {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
delete appWindow;
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "YoggieEngine.h"
#include "LayerStack.h"
namespace YoggieEngine {
@ -10,10 +11,28 @@ namespace YoggieEngine {
~Application();
virtual void Run();
void PollEvents();
void SwapBuffers();
void GuiBegin();
void GuiEnd();
void PushLayer(Layer* layer);
static Application& Get() { return *Application::instance; }
static void HandleKey(GLFWwindow* window, int key, int scancode, int action, int mods);
static void HandleMouseButton(GLFWwindow* window, int button, int action, int mods);
static void HandleScroll(GLFWwindow* window, double xoffset, double yoffset);
protected:
std::string m_AppName;
friend class ApplicationRuntime;
NativeWindow* appWindow;
LayerStack AppLayerstack;
Layer* guiLayer;
static Application* instance ;
friend class ImGuiLayer;
};
};

View File

@ -1,102 +0,0 @@
#include <YoggieEngine.h>
#include "ModelImporter.h"
namespace YoggieEngine {
SceneObject* ModelImporter::Import(const std::string path)
{
SceneObject* root = new SceneObject(std::string(path), nullptr);
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
aiNode* currentNode = scene->mRootNode;
std::vector<Mesh> meshes = processNode(currentNode, scene);
std::cout << "[DEBUG]: Loaded " << meshes.size() << " meshes!" << std::endl;
// create a renderable (per mesh ?? )
root->renderable = new Renderable();
root->renderable->mesh = new Mesh(meshes[0]);
return root;
}
std::vector<Mesh> ModelImporter::processNode(aiNode* node, const aiScene* scene)
{
std::vector<Mesh> meshes;
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
auto m2 = processNode(node->mChildren[i], scene);
for (auto m : m2) {
meshes.push_back(m);
}
}
return meshes;
}
Mesh ModelImporter::processMesh(aiMesh* mesh, const aiScene* scene) {
std::vector<unsigned int> indices;
std::vector<Vertex> vertices;
ProcessVertices(mesh, vertices);
ProcessIndices(mesh, indices);
Mesh result;
result.vertices = vertices;
result.elements = indices;
return result;
}
void ProcessVertices(aiMesh* mesh, std::vector<Vertex>& out_vertices) {
// Process vertices
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vertex v{};
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
v.vertices = vector;
if (mesh->mTextureCoords[0]) {
glm::vec2 texCoord;
texCoord.x = mesh->mTextureCoords[0][i].x;
texCoord.y = mesh->mTextureCoords[0][i].y;
v.uv = texCoord;
}
out_vertices.push_back(v);
}
}
void ProcessIndices(aiMesh* mesh, std::vector<unsigned int>& out_indices) {
// Process Indices
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
if (face.mNumIndices < 3)
continue;
for (unsigned int j = 0; j < face.mNumIndices; j++) {
out_indices.push_back(face.mIndices[j]);
}
}
}
}

View File

@ -1,31 +0,0 @@
#pragma once
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "../Graphics/Primitives/Mesh.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <string>
#include "../Scene/TransformTree/SceneNodeTypes.h"
namespace YoggieEngine {
void ProcessVertices(aiMesh* mesh, std::vector<Vertex>& out_vertices);
void ProcessIndices(aiMesh* mesh, std::vector<unsigned int>& out_indices);
class ModelImporter {
public:
SceneObject* Import(const std::string path);
private:
static Mesh ModelImporter::processMesh(aiMesh* mesh, const aiScene* scene);
static std::vector<Mesh> ModelImporter::processNode(aiNode* node, const aiScene* scene);
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "uuid.h"
typedef uuid::v4::UUID AssetHandle;
enum class AssetType {
Unknown = -1,
Mesh,
Texture,
Material,
Shader
};
struct Asset {
AssetHandle Handle;
template<class T >
static AssetType GetType(T t) { return t.GetType(); }
virtual AssetType GetType() { return AssetType::Unknown; }
};

View File

@ -0,0 +1,143 @@
#include <YoggieEngine.h>
#include "AssetImporter.h"
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
namespace YoggieEngine {
void ProcessVertices(aiMesh* mesh, std::vector<YoggieEngine::Vertex>& out_vertices) {
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
YoggieEngine::Vertex v{};
glm::vec3 vector{};
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
v.vertices = vector;
if (mesh->mTextureCoords[0]) {
glm::vec2 texCoord{};
texCoord.x = mesh->mTextureCoords[0][i].x;
texCoord.y = mesh->mTextureCoords[0][i].y;
v.uv = texCoord;
}
out_vertices.push_back(v);
}
}
void ProcessIndices(aiMesh* mesh, std::vector<unsigned int>& out_indices) {
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
if (face.mNumIndices < 3)
continue;
for (unsigned int j = 0; j < face.mNumIndices; j++) {
out_indices.push_back(face.mIndices[j]);
}
}
}
YoggieEngine::Mesh processMesh(aiMesh* mesh, const aiScene* scene) {
std::vector<unsigned int> indices;
std::vector<YoggieEngine::Vertex> vertices;
ProcessVertices(mesh, vertices);
ProcessIndices(mesh, indices);
YoggieEngine::Mesh result;
result.vertices = vertices;
result.elements = indices;
return result;
}
std::vector<YoggieEngine::Mesh> processNode(aiNode* node, const aiScene* scene) {
std::vector<YoggieEngine::Mesh> meshes = std::vector<YoggieEngine::Mesh>();
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
auto m2 = processNode(node->mChildren[i], scene);
for (auto m : m2) {
meshes.push_back(m);
}
}
return meshes;
}
void LoadModelFile(std::filesystem::path path) {
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path.string(), aiProcess_Triangulate | aiProcess_FlipUVs);
aiNode* currentNode = scene->mRootNode;
auto meshes = processNode(currentNode, scene);
}
bool IsSupportedImageFormat(const std::string& extension) {
static std::vector<std::string> supported_image_extensions = { "jpeg", "jpg", "png","bmp","hdr","psd","tga","gif","pic","psd","pgm","ppm" };
for (auto support_extension : supported_image_extensions) {
if (extension == support_extension)
return true;
}
return false;
}
Asset AssetImporter::ImportAsset(AssetMetadata& metadata) {
static Asset emptyAsset;
// Check file extension so we can choose our loader
if (metadata.filepath.has_extension() == true)
{
spdlog::error("Asset file has no extension!");
}
const auto extension = metadata.filepath.extension().string();
// Handle as Model file
bool IsSupportedModelFile = importer.IsExtensionSupported(extension);
if (IsSupportedModelFile) {
LoadModelFile(metadata.filepath);
return emptyAsset;
}
// Handle as Texture
if (IsSupportedImageFormat(extension))
{
Texture texture;
texture.Load(metadata.filepath.string());
return texture;
}
// Handle as shader
if (extension == "glsl" || extension == "vert" || extension == "frag") {
//Shader shader;
//shader.
return emptyAsset;
}
return emptyAsset;
}
};

View File

@ -0,0 +1,12 @@
#pragma once
#include "AssetMetadata.h"
#include <assimp/Importer.hpp>
namespace YoggieEngine{
class AssetImporter {
public:
static Asset ImportAsset(AssetMetadata& metadata);
private:
static Assimp::Importer importer;
};
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <map>
#include "AssetMetaData.h"
typedef std::map<AssetHandle, AssetMetadata> AssetRegistry;
class AssetManager {
public:
virtual Asset& GetAsset(AssetHandle handle) = 0;
protected:
AssetRegistry Assets;
std::map<AssetHandle, Asset> LoadedAssets;
};

View File

@ -0,0 +1,41 @@
#include "YoggieEngine.h"
#include "AssetManagerEditor.h"
#include "AssetImporter.h"
using namespace YoggieEngine;
Asset& AssetManagerEditor::GetAsset(AssetHandle handle)
{
static Asset EmptyAsset{};
// 1. Check if handle is valid
if (IsAssetHandleValid(handle) == false)
return EmptyAsset;
// 2. check if asset needs loading
Asset asset;
if (IsAssetLoaded(handle)) {
asset = LoadedAssets.at(handle);
}
else {
// Load asset
// Get MetaData
//auto& metadata = Assets[handle];
// Load Asset
//asset = AssetImporter::ImportAsset(metadata);
}
// 3. return asset.
return asset;
}
bool AssetManagerEditor::IsAssetHandleValid(AssetHandle handle)
{
return Assets.find(handle) != Assets.end();
}
bool AssetManagerEditor::IsAssetLoaded(AssetHandle handle ) {
return LoadedAssets.find(handle) != LoadedAssets.end();
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "AssetManager.h"
class AssetManagerEditor : public AssetManager {
public:
Asset& GetAsset(AssetHandle handle) override;
private:
bool IsAssetHandleValid(AssetHandle handle);
bool IsAssetLoaded(AssetHandle handle);
};

View File

@ -0,0 +1,7 @@
#pragma once
#include <filesystem>
#include "Asset.h"
struct AssetMetadata{
AssetHandle handle;
std::filesystem::path filepath;
};

View File

@ -0,0 +1,72 @@
/*
*
* SOURCE: https://github.com/rkg82/uuid-v4/blob/main/uuid/v4/uuid.h
*
*/
#ifndef __UUID__
#define __UUID__
#include <random>
#include <string>
namespace uuid::v4
{
// Encaasulate the genaeration of a Version 4 UUID object
// A Version 4 UUID is a universally unique identifier that is generated using random numbers.
class UUID
{
public:
UUID() {}
// I need a better UUID class that will work as a key in std::map
// because this won't properly work
bool operator() (const UUID& lhs, const UUID& rhs) const {
return 1==1;
}
bool operator< (const UUID& rhs)const {
return false;
}
// method for creating UUID object.
void generate ()
{
std::random_device rd;
std::mt19937 engine{ rd() };
std::uniform_int_distribution<int> dist{ 0, 256 }; //Limits of the interval
for (int index = 0; index < 16; ++index)
{
_data[index] = (unsigned char)dist(engine);
}
_data[6] = ((_data[6] & 0x0f) | 0x40); // Version 4
_data[8] = ((_data[8] & 0x3f) | 0x80); // Variant is 10
}
// Returns UUID as formatted string
std::string String()
{
// Formats to "0065e7d7-418c-4da4-b4d6-b54b6cf7466a"
char buffer[256] = { 0 };
std::snprintf(buffer, 255,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
_data[0], _data[1], _data[2], _data[3],
_data[4], _data[5],
_data[6], _data[7],
_data[8], _data[9],
_data[10], _data[11], _data[12], _data[13], _data[14], _data[15]);
std::string uuid = buffer;
return uuid;
}
private:
unsigned char _data[16] = { 0 };
};
};
#endif // #ifndef __UUID__

View File

@ -15,8 +15,7 @@ namespace YoggieEngine
}
}
int main(int argc, char** argv) {
int main(int argc, char** argv)
{
return YoggieEngine::entryPoint();
}

View File

@ -1,12 +0,0 @@
#pragma once
namespace YoggieEngine {
struct Event
{
public:
std::string name;
int argc;
void** argv;
};
}

View File

@ -1,28 +0,0 @@
#include <YoggieEngine.h>
#include "EventEmitter.h"
namespace YoggieEngine {
void EventEmitter::Subscribe(EventListener& subscriber)
{
subscribers.push_back(&subscriber);
}
void EventEmitter::Unsubscribe(EventListener& subscriber)
{
subscribers.remove(&subscriber);
}
void EventEmitter::EmitEvent(Event& incident)
{
// Notify all subscribers an event has taken place
for (auto it = subscribers.begin(); it != subscribers.end(); ++it)
{
(*it)->ReceiveEvent(incident);
}
}
EventEmitter::EventEmitter() {
subscribers = std::list<EventListener*>{};
}
}

View File

@ -1,16 +0,0 @@
#pragma once
namespace YoggieEngine{
class EventEmitter {
public:
void Subscribe(EventListener& subscriber);
void Unsubscribe(EventListener& subscriber);
protected:
std::list<EventListener*> subscribers;
void EmitEvent(Event& incident);
EventEmitter();
};
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "Event.h"
namespace YoggieEngine {
class EventListener {
public:
virtual void ReceiveEvent(Event& incident) = 0;
};
}

View File

@ -0,0 +1,42 @@
#pragma once
#include <glm/gtx/quaternion.hpp>
namespace YoggieEngine {
class Camera {
public:
Camera() {
projection = glm::perspective(glm::radians(90.0f), 800.0f / 600.0f, 0.001f, 1000.0f);
//projection[3][1] *= -1;
}
glm::mat4 getTransform() const {
auto transform = glm::translate(glm::mat4(1.0f), Position)
* glm::toMat4(glm::quat(Rotation))
* glm::scale(glm::mat4(1.0f), glm::vec3(1.0f));
return glm::inverse(transform);
}
glm::mat4& getProjection(float width, float height) {
//projection[3][1] *= -1;
return projection;
}
glm::vec3 Position = glm::vec3(0.0f);
glm::vec3 Rotation = glm::vec3(0.0f);
private:
glm::mat4 view;
glm::mat4 projection;
};
}

View File

@ -1,8 +1,5 @@
#include <YoggieEngine.h>
#include "CubeMap.h"
#define STB_IMAGE_IMPLEMENTATION
#include "../stb_image.h"
YoggieEngine::CubeMap::CubeMap()
{

View File

@ -2,12 +2,14 @@
#include "Scene/Components.h"
namespace YoggieEngine {
struct DrawCommand {
bool isDynamic;
unsigned int VAO_identifier;
unsigned int num_elements;
unsigned int IBO_identifier;
TransformComponent& transform;
Shader& shader;
glm::vec3& color;
// Material
};
};

View File

@ -0,0 +1,60 @@
#include <YoggieEngine.h>
#include "OpenglAPI.h"
namespace YoggieEngine {
GLenum glCheckError_(const char* file, int line) {
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR) {
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break;
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
};
spdlog::error("{0} | {1} ({2})", error, file, line);
}
return errorCode;
}
#ifdef DEBUG
#define glCheckError() glCheckError_(__FILE__, __LINE__)
#else
#define glCheckError()
#endif
void OpenGLApi::DrawTriangles(Render3DComponent rc) {
glBindVertexArray(rc.VAO);
glCheckError();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rc.IBO);
glCheckError();
glDrawElements(GL_TRIANGLES, static_cast<unsigned int> (rc.mesh.elements.size()), GL_UNSIGNED_INT, 0);
glCheckError();
glBindVertexArray(0);
}
void OpenGLApi::DrawCubeMap(unsigned int VertexAttributeObject, CubeMap CubeTexture) {
glDepthMask(GL_FALSE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, CubeTexture.getID());
//glCheckError(); // INVALID ENUM FOR SOME REASON
glBindVertexArray(VertexAttributeObject);
glDrawArrays(GL_TRIANGLES, 0, 36);
//glCheckError();
glBindVertexArray(0);
glDepthMask(GL_TRUE);
}
}

View File

@ -0,0 +1,9 @@
#pragma once
namespace YoggieEngine {
class OpenGLApi {
public:
static void DrawTriangles(Render3DComponent rc);
static void DrawCubeMap(unsigned int VertexAttributeObject, CubeMap CubeTexture);
};
};

View File

@ -1,36 +0,0 @@
#include <YoggieEngine.h>
#include "Camera.h"
namespace YoggieEngine {
Camera::Camera(const Camera& other)
: Position(other.Position), Rotation(other.Rotation), Zoom(other.Zoom)
{
}
Camera::Camera(glm::vec3 position, glm::vec3 rotation, float zoom)
: Position(position), Rotation( rotation)
{
Front = glm::vec3(-1.0f, 0.0f, 0.0f);
Right = glm::vec3(0.0f, 0.0f, 1.0f);
Up = glm::vec3(0.0f, 1.0f, 0.0f);
Zoom = zoom;
ViewMatrix = glm::lookAt(
Position,
Position + Front,
Up);
ProjectionMatrix = glm::perspective(glm::radians(Zoom), (800.0f / 600.0f), 0.001f, 100.0f);
}
Camera::~Camera() {
}
void Camera::Update() {
ViewMatrix = glm::lookAt(Position,Position + Front,Up);
}
}

View File

@ -1,27 +0,0 @@
#pragma once
namespace YoggieEngine {
class Camera {
public:
Camera(const Camera& other);
Camera(glm::vec3 position, glm::vec3 rotation, float zoom);
~Camera();
void Update();
glm::vec3 Position;
glm::vec3 Rotation;
float Zoom;
glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;
private:
glm::vec3 Front;
glm::vec3 Right;
glm::vec3 Up;
};
}

View File

@ -1,13 +0,0 @@
#pragma once
namespace YoggieEngine {
class Texture {
public:
Texture(const std::string texturePath);
void Bind();
void Unbind();
const unsigned int GetID() const { return Id; }
private:
unsigned int Id;
};
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "../Graphics/Memory/Buffer.h"
#include "../Graphics/Memory/VertexArray.h"
#include "../Graphics/Buffer.h"
#include "../Graphics/VertexArray.h"
namespace YoggieEngine {

View File

@ -1,9 +0,0 @@
#pragma once
namespace YoggieEngine {
struct Renderable {
Mesh* mesh;
Material* material;
Texture* texture;
};
}

View File

@ -2,16 +2,27 @@
#include "Renderer.h"
#include "../Scene/Components.h"
#include "../Graphics/Memory/Buffer.h"
#include "../Graphics/Memory/VertexArray.h"
#include "../Graphics/Primitives/DrawCommand.h"
#include "../Graphics/Buffer.h"
#include "../Graphics/VertexArray.h"
#include "Framebuffer.h"
#include "../Scene/Components.h"
#include"../Scene/Scene.h"
#include "Camera.h"
#include "OpenglAPI.h"
extern YoggieEngine::Camera cam;
namespace YoggieEngine {
unsigned int quadVAO = 0;
unsigned int quadVBO = 0;
// vegetation test
std::vector<glm::vec3> vegetation = {
glm::vec3(-1.5f, 0.0f, -0.48f),
glm::vec3(1.5f, 0.0f, 0.51f),
glm::vec3(0.0f, 0.0f, 0.7f),
glm::vec3(-0.3f, 0.0f, -2.3f)
};
unsigned int transparentVAO, transparentVBO;
Texture grassTexture;
float skyboxVertices[]{
// positions
@ -58,22 +69,41 @@ float skyboxVertices[]{
1.0f, -1.0f, 1.0f
};
Renderer::Renderer(RendererConfig& config)
: m_framebuffer(Framebuffer(config.ScreenWidth, config.ScreenHeight)),
Renderer::Renderer() :
m_framebuffer(800, 600),
gBufferShader("build/Debug/Shaders/deferred/geometry.vert", "build/Debug/Shaders/deferred/geometry.frag"),
lightingPassShader("build/Debug/Shaders/deferred/lightPass.vert", "build/Debug/Shaders/deferred/lightPass.frag"),
SkyboxShader("build/Debug/Shaders/Cubemaps/Skybox.vert", "build/Debug/Shaders/Cubemaps/Skybox.frag")
{
width = config.ScreenWidth;
height = config.ScreenHeight;
SkyboxShader("build/Debug/Shaders/Cubemaps/Skybox.vert", "build/Debug/Shaders/Cubemaps/Skybox.frag"),
BlendingShader("build/Debug/Shaders/forward/Blending.vert", "build/Debug/Shaders/forward/Blending.frag"),
forwardShader("build/Debug/Shaders/forward/geometry.vert", "build/Debug/Shaders/forward/geometry.frag"),
postProcessingShader("build/Debug/Shaders/forward/postprocessing.vert", "build/Debug/Shaders/forward/postprocessing.frag")
{
width = 800;
height = 600;
glEnable(GL_DEPTH_TEST);
CreateGBuffer();
std::vector<std::string> faces{
"build/Debug/skybox/Open_Water/right.jpg",
"build/Debug/skybox/Open_Water/left.jpg",
"build/Debug/skybox/Open_Water/top.jpg",
"build/Debug/skybox/Open_Water/bottom.jpg",
"build/Debug/skybox/Open_Water/front.jpg",
"build/Debug/skybox/Open_Water/back.jpg"
};
skybox = CubeMap(faces);
grassTexture.Load("build/Debug/Texture/grass.png");
}
void Renderer::CreateGBuffer() {
// Deferred Rendering
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
// - Position Color Buffer ;
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
@ -113,170 +143,105 @@ Renderer::Renderer(RendererConfig& config)
spdlog::critical("Framebuffer not complete {}{}", __FILE__, __LINE__);
}
std::vector<std::string> faces{
"build/Debug/skybox/Open_Water/right.jpg",
"build/Debug/skybox/Open_Water/left.jpg",
"build/Debug/skybox/Open_Water/top.jpg",
"build/Debug/skybox/Open_Water/bottom.jpg",
"build/Debug/skybox/Open_Water/front.jpg",
"build/Debug/skybox/Open_Water/back.jpg"
};
sky = CubeMap(faces);
// Create a skybox vao
unsigned int VBO;
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &VBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
}
Renderer::~Renderer(){}
Camera& Renderer::getCamera() {
return cam;
}
void Renderer::Submit( Render3DComponent& renderComponent, TransformComponent& transform) {
if (renderComponent.VAO == 0 || renderComponent.IBO == 0)
{
if (renderComponent.VAO != 0)
glDeleteVertexArrays(1, &(renderComponent.VAO));
if (renderComponent.IBO != 0)
glDeleteBuffers(1, &(renderComponent.IBO));
VertexArray va = VertexArray();
Buffer vertexBuffer = Buffer();
Buffer elementBuffer = Buffer();
va.Create();
va.Bind();
vertexBuffer.createBuffer();
vertexBuffer.Bind(false);
vertexBuffer.setBufferData((void*)&renderComponent.mesh.vertices[0], renderComponent.mesh.vertices.size() * sizeof(Vertex), false);
elementBuffer.createBuffer();
elementBuffer.Bind(true);
elementBuffer.setBufferData((void*)&renderComponent.mesh.elements[0], renderComponent.mesh.elements.size() * sizeof(unsigned int), true);
va.AttachAttribute(0, 3, sizeof(Vertex));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
va.Unbind();
vertexBuffer.Unbind(false);
elementBuffer.Unbind(true);
renderComponent.VAO = va.getID();
renderComponent.IBO = elementBuffer.getBufferID();
}
DrawCommand dc = { renderComponent.VAO, renderComponent.mesh.elements.size(), renderComponent.IBO, transform, renderComponent.shader, renderComponent.color };
commands.push_back(dc);
}
void Renderer::GeometryPass() {
// 1.0 Geometry pass
gBufferShader.Use();
for (const DrawCommand& command : commands)
{
glBindVertexArray(command.VAO_identifier);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.IBO_identifier);
gBufferShader.setUniformVec3("Color", command.color);
gBufferShader.setUniformMat4("Model", command.transform.LocalTransform);
gBufferShader.setUniformMat4("View", cam.ViewMatrix);
gBufferShader.setUniformMat4("Projection", cam.ProjectionMatrix);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(command.num_elements),
GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Renderer::SkyboxPass() {
// Render skybox
glDepthMask(GL_FALSE);
void Renderer::Render(Scene& scene , Camera MainCamera){
int oldviewport[4];
glGetIntegerv(GL_VIEWPORT, oldviewport);
glViewport(0, 0, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render skybox if the scene has one
SkyboxShader.Use();
SkyboxShader.setUniformMat4("projection", cam.ProjectionMatrix);
SkyboxShader.setUniformMat4("view", glm::mat4(glm::mat3(cam.ViewMatrix))); // remove rotation from the view matrix
glBindVertexArray(skyboxVAO);
glBindTexture(GL_TEXTURE_CUBE_MAP, sky.getID());
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthMask(GL_TRUE);
}
SkyboxShader.setUniformMat4("projection", MainCamera.getProjection(width, height));
SkyboxShader.setUniformMat4("view", glm::inverse(glm::mat4(glm::mat3(MainCamera.getTransform()))));
void Renderer::lightingPass(Scene& scene){
if (!skyboxVAO) {
unsigned int VBO;
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &VBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
// 2.0 Lighting Pass
}
// configure shader
OpenGLApi::DrawCubeMap(skyboxVAO, skybox);
auto renderables = scene.getReg().view<TransformComponent, Render3DComponent>();
gBufferShader.Use();
for (auto renderable : renderables) {
auto entity = Entity(renderable, &scene);
auto& renderComponent = entity.GetComponent<Render3DComponent>();
auto& transform = entity.GetComponent<TransformComponent>();
// Geometry pass
gBufferShader.setUniformVec3("Color", renderComponent.color);
gBufferShader.setUniformMat4("Model", transform.GetTransform());
gBufferShader.setUniformMat4("View", glm::inverse(MainCamera.getTransform()));
gBufferShader.setUniformMat4("Projection", MainCamera.getProjection(width, height));
OpenGLApi::DrawTriangles(renderComponent);
}
// Light pass
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
lightingPassShader.Use();
lightingPassShader.setUniformInt("gPosition", 0);
lightingPassShader.setUniformInt("gNormal", 1);
lightingPassShader.setUniformInt("gColorSpec", 2);
// Bind all Gbuffer textures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gColorSpec);
// send relevant Lighting Uniforms
auto lights = scene.getReg().view<LightComponent, TransformComponent>();
unsigned int lightnr = 0;
lights.each([&](auto entity, LightComponent& light, TransformComponent& transform) {
lightingPassShader.setUniformVec3("lights[" + std::to_string(lightnr) + "].Position", transform.Position);
lightingPassShader.setUniformVec3("lights[" + std::to_string(lightnr) + "].Color", light.Color);
for (auto light : lights) {
auto lightComponent = Entity(light, &scene).GetComponent<LightComponent>();
auto transformComponent = Entity(light, &scene).GetComponent<TransformComponent>();
auto name = "lights[" + std::to_string(lightnr) + "]";
lightingPassShader.setUniformVec3(name + ".Position", transformComponent.Position);
lightingPassShader.setUniformVec3(name + ".Color", lightComponent.Color);
// Attenuation
const float linear = 0.7f;
const float quadratic = 1.8f;
lightingPassShader.setUniformFloat("lights[" + std::to_string(lightnr) + "].Linear", linear);
lightingPassShader.setUniformFloat("lights[" + std::to_string(lightnr) + "].Quadratic", quadratic);
lightingPassShader.setUniformFloat(name + ".Linear", linear);
lightingPassShader.setUniformFloat(name + ".Quadratic", quadratic);
lightnr++;
});
lightingPassShader.setUniformVec3("viewPos", getCamera().Position);
}
// render to quad
if (quadVAO == 0)
{
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, -1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
};
unsigned int quadVBO;
// setup plane VAO ;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
@ -289,69 +254,80 @@ void Renderer::lightingPass(Scene& scene){
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
}
void Renderer::Render(Scene& scene)
{
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SkyboxPass();
GeometryPass();
lightingPass(scene);
// Copy GBuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer.GetId());
glBindFramebuffer(GL_DRAW_BUFFER, m_framebuffer.GetId());
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
// Forward rendering approach
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
for (const DrawCommand& command : commands)
{
glBindVertexArray(command.VAO_identifier);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.IBO_identifier);
if (transparentVAO == 0) {
unsigned int transparentVBO;
float transparentVertices[] = {
// positions // texture Coords
0.0f, 0.5f, 0.0f, 0.0f, 1.0f,
0.0f, -0.5f, 0.0f, 0.0f, 0.0f,
1.0f, -0.5f, 0.0f, 1.0f, 0.0f,
command.shader.Use();
command.shader.setUniformVec3("Color", command.color);
command.shader.setUniformMat4("M", command.transform.LocalTransform);
command.shader.setUniformMat4("V", cam.ViewMatrix);
command.shader.setUniformMat4("P", cam.ProjectionMatrix);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(command.num_elements),
GL_UNSIGNED_INT, NULL);
0.0f, 0.5f, 0.0f, 0.0f, 1.0f,
1.0f, -0.5f, 0.0f, 1.0f, 0.0f,
1.0f, 0.5f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &transparentVAO);
glGenBuffers(1, &transparentVBO);
glBindVertexArray(transparentVAO);
glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glBindVertexArray(0);
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
BlendingShader.Use();
glBindVertexArray(transparentVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, grassTexture.GetID());
BlendingShader.setUniformMat4("V", glm::inverse(MainCamera.getTransform()));
BlendingShader.setUniformMat4("P", MainCamera.getProjection(width, height));
for (unsigned int i = 0; i < vegetation.size(); i++) {
auto translation = glm::translate(glm::mat4(1.0f), vegetation[i]);
BlendingShader.setUniformMat4("M", translation);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glBindVertexArray(0);
glDisable(GL_BLEND);
// Lighting pass
/*
auto lights = scene.getReg().view<LightComponent>();
lights.each([&](auto entity, LightComponent& light) {
renderComponent.shader.setUniformVec3("lighting.color", light.Color);
renderComponent.shader.setUniformFloat("lighting.strength", light.Strength);
});
*/
commands.clear();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(oldviewport[0], oldviewport[1], oldviewport[2], oldviewport[3]);
}
Renderer::~Renderer(){}
void Renderer::setCurrentFrameBuffer(const Framebuffer& fb)
{
m_framebuffer = fb;

View File

@ -2,12 +2,8 @@
#include "GLFW/glfw3.h"
#include <vector>
#include "../PerfCounter.h"
#include "Renderable.h"
#include "Memory/Framebuffer.h"
#include "../Scene/Components.h"
#include"../Scene/Scene.h"
#include "Graphics/Primitives/DrawCommand.h"
#include "../Scene/Scene.h"
#include "Framebuffer.h"
namespace YoggieEngine {
@ -19,40 +15,99 @@ namespace YoggieEngine {
class Renderer {
public:
Renderer(RendererConfig& config);
Renderer();
~Renderer();
void Submit(Render3DComponent& renderComponent, TransformComponent& transform); // Collects DrawCommands
void Render(Scene&); // Draw to screen (using drawCall structs)
// Forward pass
/*
forwardShader.Use();
forwardShader.setUniformVec3("Color", renderComponent.color);
forwardShader.setUniformMat4("M", transform.LocalTransform);
forwardShader.setUniformMat4("V", MainCamera.view);
forwardShader.setUniformMat4("P", MainCamera.projection);
OpenGLApi::DrawTriangles(renderComponent);
*/
void Render(Scene& scene, Camera MainCamera);
void setCurrentFrameBuffer(const Framebuffer& fb);
void setClearColor(const glm::vec3& ClearColor);
Camera& getCamera();
private:
void GeometryPass();
void SkyboxPass();
void lightingPass(Scene& scene);
Framebuffer& getCurrentFrameBuffer() { return m_framebuffer; }
private:
Framebuffer m_framebuffer;
int width, height;
glm::vec3 m_clearColor;
bool m_depthTest;
std::vector<DrawCommand> commands;
void CreateGBuffer();
unsigned int skyboxVAO = 0;
CubeMap sky;
Shader forwardShader;
// deferred rending parameters
unsigned int gBuffer, gPosition, gNormal, gColorSpec, gDepth;
Shader lightingPassShader;
Shader gBufferShader;
Shader SkyboxShader;
Shader postProcessingShader;
// blending
Shader BlendingShader;
CubeMap skybox;
Texture grassTexture;
unsigned int transparentVAO = 0;
unsigned int skyboxVAO = 0;
unsigned int quadVAO = 0;
float skyboxVertices[36*3]{
// positions
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
std::vector<glm::vec3> vegetation = {
glm::vec3(-1.5f, 0.0f, -0.48f),
glm::vec3(1.5f, 0.0f, 0.51f),
glm::vec3(0.0f, 0.0f, 0.7f),
glm::vec3(-0.3f, 0.0f, -2.3f)
};
};
}

View File

@ -1,12 +1,17 @@
#pragma once
#include "Assets/Asset.h"
namespace YoggieEngine {
class Shader {
class Shader : public Asset{
private:
char* readFile(const char* filePath);
AssetType GetType() override{ return AssetType::Shader; }
public:
Shader(const std::string vertexShaderPath, const std::string fragmentShaderPath);
void Use() const;
void setUniformMat4(std::string uniformName, const glm::mat4& matrix4)const;
void setUniformVec4(std::string uniformName, const glm::vec4& vector4)const;

View File

@ -1,32 +1,36 @@
#include <YoggieEngine.h>
#include "Texture.h"
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include "../stb_image.h"
namespace YoggieEngine {
Texture::Texture(const std::string texturePath) {
int width, height, channels;
void Texture::Load(const std::string texturePath, bool Transparency) {
int channels;
unsigned char* data = stbi_load(texturePath.c_str(), &width, &height, &channels, 0);
if (data) {
glGenTextures(1, &Id);
glBindTexture(GL_TEXTURE_2D, Id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if (Transparency) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else {
spdlog::error("Failed to load image (%s)", texturePath);
std::cout << "Failed to load image!" << std::endl;
spdlog::error("Failed to load image ({0})", texturePath);
}
stbi_image_free(data);
}
void Texture::Bind() {

View File

@ -0,0 +1,22 @@
#pragma once
#include "Assets/Asset.h"
namespace YoggieEngine {
class Texture : public Asset {
public:
Texture() = default;
void Load(const std::string texturePath, bool Transparency = false);
void Bind();
void Unbind();
const unsigned int GetID() const { return Id; }
const ImVec2 getSize() { return {(float)width, (float)height}; }
AssetType GetType() override { return AssetType::Texture; }
private:
unsigned int Id;
int width;
int height;
};
}

View File

@ -0,0 +1,4 @@
#include <YoggieEngine.h>
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"

View File

@ -1,115 +1,98 @@
#include <YoggieEngine.h>
#include "InputManager.h"
namespace YoggieEngine {
InputManager InputSystem;
void InputManager::PollEvents()
{
for (auto it = windows.begin(); it != windows.end(); ++it) {
auto window = *it;
window->Poll();
namespace YoggieEngine {
double cursor_pos_x;
double cursor_pos_y;
int key_status[YOGGIE_KEY_LAST];
int mouseButton_status[7];
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void cursorPos_callback(GLFWwindow* window, double xpos, double ypos);
void cursorEnter_callback(GLFWwindow* window, int entered);
void mouseButton_callback(GLFWwindow* window, int button, int action, int mods);
void init_inputSystem(NativeWindow* window) {
cursor_pos_x = 0;
cursor_pos_y = 0;
glfwSetKeyCallback((GLFWwindow*) window->GetHandle(), key_callback);
glfwSetMouseButtonCallback((GLFWwindow*)window->GetHandle(), mouseButton_callback);
glfwSetCursorPosCallback((GLFWwindow*)window->GetHandle(), cursorPos_callback);
glfwSetCursorEnterCallback((GLFWwindow*)window->GetHandle(), cursorEnter_callback);
}
void InputManager::KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
void ReceiveInput() {
glfwPollEvents();
}
bool keyIsPressed(int key)
{
return (key_status[key] == GLFW_PRESS) || (key_status[key] == GLFW_REPEAT);
}
Event KeyEvent{};
KeyEvent.name = "KEY";
InputSystem.EmitEvent(KeyEvent);
bool MouseButtonPressed(int key)
{
return (mouseButton_status[key] == GLFW_PRESS ) || (mouseButton_status[key] == GLFW_REPEAT);
}
if (key == GLFW_KEY_A && action == GLFW_PRESS)
{
double getCursorPosX(NativeWindow* window)
{
glfwGetCursorPos((GLFWwindow*)window->GetHandle(), &cursor_pos_x, nullptr);
return cursor_pos_x;
}
double getCursorPosY(NativeWindow* window)
{
glfwGetCursorPos((GLFWwindow*)window->GetHandle(), nullptr, &cursor_pos_y);
return cursor_pos_y;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
key_status[key] = action;
}
void mouseButton_callback(GLFWwindow* window, int button, int action, int mods)
{
auto& io = ImGui::GetIO();
io.AddMouseButtonEvent(button , action == GLFW_PRESS);
std::cout << "'a' key was pressed" << std::endl;
}
mouseButton_status[button] = action;
}
void InputManager::CursorPositionCallback(GLFWwindow* window, double x, double y)
void cursorPos_callback(GLFWwindow* window, double xpos, double ypos)
{
//std::cout << "Cursor Position x: " << x << ", y: " << y << std::endl;
Event CursorPosUpdate{};
CursorPosUpdate.name = "UPDATE::CURSOR:POSITION";
InputSystem.EmitEvent(CursorPosUpdate);
//std::cout << "Cursor moved!" << std::endl;
}
void InputManager::CursorEnterCallback(GLFWwindow* window, int entered)
void cursorEnter_callback(GLFWwindow* window, int entered)
{
if (entered) {
Event mouseEntered {};
mouseEntered.name = "Mouse Entered Window's confines!";
mouseEntered.argc = 0;
InputSystem.EmitEvent(mouseEntered);
// window is in focus
//std::cout << "Cursor Entered!" << std::endl;
}
else {
Event mouseLeft{};
mouseLeft.name = "Mouse Left Window's confines!";
mouseLeft.argc = 0;
InputSystem.EmitEvent(mouseLeft);
// window is not in focus
//std::cout << "Cursor Left!" << std::endl;
}
}
void InputManager::MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
Event MouseButtonEvent{};
MouseButtonEvent.name = "MOUSEBUTTON";
InputSystem.EmitEvent(MouseButtonEvent);
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) {
std::cout << "Right mouse button was pressed!" << std::endl;
}
}
void InputManager::ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
std::cout << "Scroll: x: " << xoffset << ", y: " << yoffset << std::endl;
Event ScrollEvent{};
ScrollEvent.name = "SCROLL";
InputSystem.EmitEvent(ScrollEvent);
}
void InputManager::attach(BarinkWindow* window)
{
windows.push_back(window);
// Attach callbacks
glfwSetKeyCallback(window->windowptr(), KeyCallback);
glfwSetCursorPosCallback(window->windowptr(), CursorPositionCallback);
glfwSetCursorEnterCallback(window->windowptr(), CursorEnterCallback);
glfwSetMouseButtonCallback(window->windowptr(), MouseButtonCallback);
glfwSetScrollCallback(window->windowptr(), ScrollCallback);
this->Subscribe( (EventListener&)(*window));
}
InputManager::InputManager() : EventEmitter ()
{
windows = std::vector<BarinkWindow*>();
}
}

View File

@ -1,23 +1,15 @@
#pragma once
namespace YoggieEngine {
// Lets just take the dumb approach for now
class InputManager : EventEmitter {
public:
InputManager();
void init_inputSystem(NativeWindow* window);
void ReceiveInput();
bool keyIsPressed(int key);
bool MouseButtonPressed(int key);
void PollEvents();
void attach(BarinkWindow* window);
double getCursorPosX(NativeWindow* window);
double getCursorPosY(NativeWindow* window);
// GLFW Handlers
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void CursorPositionCallback(GLFWwindow* window, double x, double y);
static void CursorEnterCallback(GLFWwindow* window, int entered);
static void MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
private:
std::vector<BarinkWindow*> windows;
};
extern InputManager InputSystem;
}
}

View File

@ -0,0 +1,170 @@
#pragma once
namespace YoggieEngine{
/*
* Based on GLFW
*/
/* The unknown key */
#define YOGGIE_KEY_UNKNOWN -1
/* Printable keys */
#define YOGGIE_KEY_SPACE 32
#define YOGGIE_KEY_APOSTROPHE 39 /* ' */
#define YOGGIE_KEY_COMMA 44 /* , */
#define YOGGIE_KEY_MINUS 45 /* - */
#define YOGGIE_KEY_PERIOD 46 /* . */
#define YOGGIE_KEY_SLASH 47 /* / */
#define YOGGIE_KEY_0 48
#define YOGGIE_KEY_1 49
#define YOGGIE_KEY_2 50
#define YOGGIE_KEY_3 51
#define YOGGIE_KEY_4 52
#define YOGGIE_KEY_5 53
#define YOGGIE_KEY_6 54
#define YOGGIE_KEY_7 55
#define YOGGIE_KEY_8 56
#define YOGGIE_KEY_9 57
#define YOGGIE_KEY_SEMICOLON 59 /* ; */
#define YOGGIE_KEY_EQUAL 61 /* = */
#define YOGGIE_KEY_A 65
#define YOGGIE_KEY_B 66
#define YOGGIE_KEY_C 67
#define YOGGIE_KEY_D 68
#define YOGGIE_KEY_E 69
#define YOGGIE_KEY_F 70
#define YOGGIE_KEY_G 71
#define YOGGIE_KEY_H 72
#define YOGGIE_KEY_I 73
#define YOGGIE_KEY_J 74
#define YOGGIE_KEY_K 75
#define YOGGIE_KEY_L 76
#define YOGGIE_KEY_M 77
#define YOGGIE_KEY_N 78
#define YOGGIE_KEY_O 79
#define YOGGIE_KEY_P 80
#define YOGGIE_KEY_Q 81
#define YOGGIE_KEY_R 82
#define YOGGIE_KEY_S 83
#define YOGGIE_KEY_T 84
#define YOGGIE_KEY_U 85
#define YOGGIE_KEY_V 86
#define YOGGIE_KEY_W 87
#define YOGGIE_KEY_X 88
#define YOGGIE_KEY_Y 89
#define YOGGIE_KEY_Z 90
#define YOGGIE_KEY_LEFT_BRACKET 91 /* [ */
#define YOGGIE_KEY_BACKSLASH 92 /* \ */
#define YOGGIE_KEY_RIGHT_BRACKET 93 /* ] */
#define YOGGIE_KEY_GRAVE_ACCENT 96 /* ` */
#define YOGGIE_KEY_WORLD_1 161 /* non-US #1 */
#define YOGGIE_KEY_WORLD_2 162 /* non-US #2 */
/* Function keys */
#define YOGGIE_KEY_ESCAPE 256
#define YOGGIE_KEY_ENTER 257
#define YOGGIE_KEY_TAB 258
#define YOGGIE_KEY_BACKSPACE 259
#define YOGGIE_KEY_INSERT 260
#define YOGGIE_KEY_DELETE 261
#define YOGGIE_KEY_RIGHT 262
#define YOGGIE_KEY_LEFT 263
#define YOGGIE_KEY_DOWN 264
#define YOGGIE_KEY_UP 265
#define YOGGIE_KEY_PAGE_UP 266
#define YOGGIE_KEY_PAGE_DOWN 267
#define YOGGIE_KEY_HOME 268
#define YOGGIE_KEY_END 269
#define YOGGIE_KEY_CAPS_LOCK 280
#define YOGGIE_KEY_SCROLL_LOCK 281
#define YOGGIE_KEY_NUM_LOCK 282
#define YOGGIE_KEY_PRINT_SCREEN 283
#define YOGGIE_KEY_PAUSE 284
#define YOGGIE_KEY_F1 290
#define YOGGIE_KEY_F2 291
#define YOGGIE_KEY_F3 292
#define YOGGIE_KEY_F4 293
#define YOGGIE_KEY_F5 294
#define YOGGIE_KEY_F6 295
#define YOGGIE_KEY_F7 296
#define YOGGIE_KEY_F8 297
#define YOGGIE_KEY_F9 298
#define YOGGIE_KEY_F10 299
#define YOGGIE_KEY_F11 300
#define YOGGIE_KEY_F12 301
#define YOGGIE_KEY_F13 302
#define YOGGIE_KEY_F14 303
#define YOGGIE_KEY_F15 304
#define YOGGIE_KEY_F16 305
#define YOGGIE_KEY_F17 306
#define YOGGIE_KEY_F18 307
#define YOGGIE_KEY_F19 308
#define YOGGIE_KEY_F20 309
#define YOGGIE_KEY_F21 310
#define YOGGIE_KEY_F22 311
#define YOGGIE_KEY_F23 312
#define YOGGIE_KEY_F24 313
#define YOGGIE_KEY_F25 314
#define YOGGIE_KEY_KP_0 320
#define YOGGIE_KEY_KP_1 321
#define YOGGIE_KEY_KP_2 322
#define YOGGIE_KEY_KP_3 323
#define YOGGIE_KEY_KP_4 324
#define YOGGIE_KEY_KP_5 325
#define YOGGIE_KEY_KP_6 326
#define YOGGIE_KEY_KP_7 327
#define YOGGIE_KEY_KP_8 328
#define YOGGIE_KEY_KP_9 329
#define YOGGIE_KEY_KP_DECIMAL 330
#define YOGGIE_KEY_KP_DIVIDE 331
#define YOGGIE_KEY_KP_MULTIPLY 332
#define YOGGIE_KEY_KP_SUBTRACT 333
#define YOGGIE_KEY_KP_ADD 334
#define YOGGIE_KEY_KP_ENTER 335
#define YOGGIE_KEY_KP_EQUAL 336
#define YOGGIE_KEY_LEFT_SHIFT 340
#define YOGGIE_KEY_LEFT_CONTROL 341
#define YOGGIE_KEY_LEFT_ALT 342
#define YOGGIE_KEY_LEFT_SUPER 343
#define YOGGIE_KEY_RIGHT_SHIFT 344
#define YOGGIE_KEY_RIGHT_CONTROL 345
#define YOGGIE_KEY_RIGHT_ALT 346
#define YOGGIE_KEY_RIGHT_SUPER 347
#define YOGGIE_KEY_MENU 348
#define YOGGIE_KEY_LAST YOGGIE_KEY_MENU
/*
* Modifier keys
*/
// If set one or more Shift keys were held down.
#define YOGGIE_MOD_SHIFT 0x0001
//If set one or more Control keys were held down.
#define YOGGIE_MOD_CONTROL 0x0002
// If set one or more Alt keys were held down.
#define YOGGIE_MOD_ALT 0x0004
// SuperKey(s) (if set, One or more superkeys is held down)
#define YOGGIE_MOD_SUPER 0x0008
// Capslock (if set, Capslock is enabeld)
#define YOGGIE_MOD_CAPS_LOCK 0x0010
// Numlock (if set, numlock is enabled)
#define YOGGIE_MOD_NUM_LOCK 0x0020
/*
* Mouse Keys
*/
#define YOGGIE_MOUSE_BUTTON_1 0
#define YOGGIE_MOUSE_BUTTON_2 1
#define YOGGIE_MOUSE_BUTTON_3 2
#define YOGGIE_MOUSE_BUTTON_4 3
#define YOGGIE_MOUSE_BUTTON_5 4
#define YOGGIE_MOUSE_BUTTON_6 5
#define YOGGIE_MOUSE_BUTTON_7 6
#define YOGGIE_MOUSE_BUTTON_8 7
#define YOGGIE_MOUSE_BUTTON_LAST YOGGIE_MOUSE_BUTTON_8
#define YOGGIE_MOUSE_BUTTON_LEFT YOGGIE_MOUSE_BUTTON_1
#define YOGGIE_MOUSE_BUTTON_RIGHT YOGGIE_MOUSE_BUTTON_2
#define YOGGIE_MOUSE_BUTTON_MIDDLE YOGGIE_MOUSE_BUTTON_3
}

34
YoggieEngine/src/Layer.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <spdlog/spdlog.h>
class Layer {
public:
~Layer() { OnDestroy(); }
Layer() { OnCreate(); }
virtual void OnUpdate(){}
virtual void OnUI(){}
virtual bool OnKey(int key , int status ) {
spdlog::info( "Key {0} , {1}", key, status);
return false;
}
virtual bool OnMouseButton(int button, int action) {
return false;
}
virtual bool OnScroll(int xoffset, int yoffset) {
return false;
}
virtual void OnStartup(){}
virtual void OnAttach() {}
virtual void OnDetach() {}
virtual void OnCreate() {}
virtual void OnDestroy(){}
};

View File

@ -0,0 +1,27 @@
#include "YoggieEngine.h"
#include "LayerStack.h"
LayerStack::~LayerStack()
{
for (Layer* layer : layers) {
layer->OnDetach();
delete layer;
}
}
void LayerStack::PushLayer(Layer* layer) {
layers.emplace(layers.begin() + insertion_index, layer);
insertion_index++;
}
void LayerStack::PopLayer(Layer* layer) {
auto it = std::find(layers.begin(), layers.begin() + insertion_index, layer);
if (it != layers.begin() + insertion_index) {
layer->OnDetach();
layers.erase(it);
insertion_index--;
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "Layer.h"
#include <vector>
class LayerStack{
public:
LayerStack() = default;
~LayerStack();
void PushLayer(Layer* layer);
void PopLayer(Layer* layer);
std::vector<Layer*>::iterator begin() { return layers.begin(); }
std::vector<Layer*>::iterator end() { return layers.end(); }
std::vector<Layer*>::reverse_iterator rbegin() { return layers.rbegin(); }
std::vector<Layer*>::reverse_iterator rend() { return layers.rend(); }
private:
std::vector<Layer*> layers;
int insertion_index = 0;
};

View File

@ -1,70 +1,67 @@
#include <YoggieEngine.h>
#include "PerfCounter.h"
#include <YoggieEngine.h>
namespace YoggieEngine {
uint64_t EngineInstrumentation::GetPrecisionTime() {
using namespace std::chrono; // REMINDER: This is kinda ugly but safes line width
return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
}
void EngineInstrumentation::PerfomanceSamplerInit() {
//ES.frames = 0;
//EngineInstrumentation::lastSampleTime = GetPrecisionTime();
}
void EngineInstrumentation::Update() {
/*
uint64_t MilliSecondsPast = GetPrecisionTime() - EngineInstrumentation::lastSampleTime;
if (MilliSecondsPast >= 1000) {
ES.frameTime = (float)1000 / ES.frames;
ES.FPS = ES.frames;
ES.frames = 0;
//EngineInstrumentation::lastSampleTime = GetPrecisionTime();
}
*/
}
void EngineInstrumentation::ShowStats() {
ImGui::Begin("Statistics", false, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize);
ImGui::Text("Currently not available");
/* ImGui::Text("FPS: %i", ES.FPS);
ImGui::Text("Frame Time: %f", ES.frameTime);
ImGui::Text("Verts: %i", ES.verts);
ImGui::Text("Draw Calls: %i", ES.DC);
*/
ImGui::End();
}
PerfSampler::PerfSampler(const std::string& name)
: name(name)
{
using namespace std::chrono;
startTime = high_resolution_clock::now();
}
PerfSampler::~PerfSampler()
{
Stop();
}
void PerfSampler::Stop()
{
using namespace std::chrono;
auto end = high_resolution_clock::now();
auto durationInuSeconds =
duration_cast<nanoseconds>(end.time_since_epoch()).count() -
duration_cast<nanoseconds>(startTime.time_since_epoch()).count();
auto ms = durationInuSeconds * 0.001f;
// std::cout << "[" << name << "]" << "Took: " << durationInuSeconds << " us (" << ms << " ms)" << std::endl;
}
uint64_t EngineInstrumentation::GetPrecisionTime() {
using namespace std::chrono; // REMINDER: This is kinda ugly but safes line
// width
return duration_cast<milliseconds>(
high_resolution_clock::now().time_since_epoch())
.count();
}
void EngineInstrumentation::PerfomanceSamplerInit() {
spdlog::info("Initialize perf sampler");
/*EngineInstrumentation::frames = 0;
EngineInstrumentation::lastSampleTime = GetPrecisionTime();*/
}
void EngineInstrumentation::Update() {
/* uint64_t MilliSecondsPast = GetPrecisionTime() -
EngineInstrumentation::lastSampleTime;
if (MilliSecondsPast >= 1000) {
EngineInstrumentation::frameTime = (float)1000 /
EngineInstrumentation::frames; EngineInstrumentation::FPS = frames;
EngineInstrumentation::frames = 0;
EngineInstrumentation::lastSampleTime =
GetPrecisionTime();
}*/
}
void EngineInstrumentation::ShowStats() {
// ImGui::Begin("Statistics", false, ImGuiWindowFlags_NoCollapse |
//ImGuiWindowFlags_NoResize);
// ImGui::Text("Currently not available");
/* ImGui::Text("FPS: %i", ES.FPS);
ImGui::Text("Frame Time: %f", ES.frameTime);
ImGui::Text("Verts: %i", ES.verts);
ImGui::Text("Draw Calls: %i", ES.DC);
*/
// ImGui::End();
}
PerfSampler::PerfSampler(const std::string &name) : name(name) {
using namespace std::chrono;
startTime = high_resolution_clock::now();
}
PerfSampler::~PerfSampler() { Stop(); }
void PerfSampler::Stop() {
using namespace std::chrono;
auto end = high_resolution_clock::now();
auto durationInuSeconds =
duration_cast<nanoseconds>(end.time_since_epoch()).count() -
duration_cast<nanoseconds>(startTime.time_since_epoch()).count();
auto ms = durationInuSeconds * 0.001f;
// std::cout << "[" << name << "]" << "Took: " << durationInuSeconds << "
//us (" << ms << " ms)" << std::endl;
}
} // namespace YoggieEngine

View File

@ -1,20 +1,11 @@
#pragma once
#include "YoggieEngine.h"
namespace YoggieEngine {
struct EngineStatistics {
float frameTime;
uint32_t verts;
uint32_t DC;
int64_t frames;
int64_t FPS;
};
class EngineInstrumentation {
public:
//static int64_t lastSampleTime;
static int64_t lastSampleTime;
static uint64_t GetPrecisionTime();
static void PerfomanceSamplerInit();
@ -22,6 +13,15 @@ namespace YoggieEngine {
static void Update();
static void ShowStats();
private:
static float frameTime;
static uint32_t verts;
static uint32_t DC;
static int64_t frames;
static int64_t FPS;
};
class PerfSampler {

View File

@ -1,4 +1,5 @@
#include <YoggieEngine.h>
#include <glm/gtc/type_precision.hpp>
#include "Physics.h"
namespace YoggieEngine {
@ -27,7 +28,6 @@ namespace YoggieEngine {
gMaterial = nullptr;
mScene = nullptr;
}
Physics::~Physics()
@ -58,21 +58,75 @@ namespace YoggieEngine {
void Physics::Step(float dt)
{
mScene->simulate(dt);
mScene->simulate(1.0f/60.0f);
mScene->fetchResults(true);
}
void Physics::Demo()
{
createScene();
SetupPvdDebug();
createGroundPlane();
createStack(PxTransform(PxVec3(0, 0, stackZ -= 10.0f)), 10, 2.0f);
}
void Physics::EnableDebugVisuals() {
mScene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 1.0f);
mScene->setVisualizationParameter(PxVisualizationParameter::eACTOR_AXES, 2.0f);
}
static unsigned int VisualizationVAO, VBO;
static unsigned int numLines;
void Physics::SubmitMesh() {
const PxRenderBuffer& rb = mScene->getRenderBuffer();
std::vector<PxVec3> lines= std::vector<PxVec3>();
numLines = rb.getNbLines();
for (unsigned int i = 0; i < numLines; i++) {
auto line = rb.getLines()[i];
lines.push_back(line.pos0);
lines.push_back(line.pos1);
}
glGenVertexArrays(1, &VisualizationVAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VisualizationVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, lines.size() * sizeof(PxVec3), &lines, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Physics::DebugRender(Framebuffer& framebuffer) {
glDepthMask(GL_FALSE);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.GetId());
debugDraw.Use();
glBindVertexArray(VisualizationVAO);
glDrawArrays(GL_LINES, 0, numLines );
glBindVertexArray(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDepthMask(GL_TRUE);
}
PxRigidDynamic* Physics::createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity = PxVec3(0)) {
PxRigidDynamic* dynamic = PxCreateDynamic(*mPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
@ -98,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

@ -26,16 +26,27 @@ namespace YoggieEngine {
void Demo();
void EnableDebugVisuals();
void SubmitMesh();
private:
void DebugRender(Framebuffer& framebuffer);
void addRigidBody(glm::mat4& transform);
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();
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);
// Memory Management
bool recordMemoryAllocations = true;

Some files were not shown because too many files have changed in this diff Show More