44 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
fe7e168e21 Adding a relationship component
The relationship component enables us to define a hierarchy through the ECS. This creates a pathway towards Inverse Kinematics
2022-12-31 02:42:27 +01:00
3722e63495 Updated Markdown Documents
- Added new screenshot
- Removed two unnecessary screenshots
- Moved screenshots to a separate showcase markdown file
- Updated the Todo list
- Removed the features markdown file and added it to the README
- Moved development instructions to a separate Development markdown file
2022-12-28 23:49:55 +01:00
3a9c07aff9 Mixing Deferred and Forward rendering
- TODO: fix Skybox affected by lighting pass
2022-12-28 23:17:55 +01:00
2dcc3f1803 Deferred rendering mode + Skybox
- Added deferred rendering mode to the renderer
- Added a skybox to the forward rendering mode
- moved default imported assets directory (temporary fix)
2022-12-28 22:35:23 +01:00
2a5c7811e7 Importing mesh asset now functioning
- Added debug logging for all user actions regarding FileDialog
- Importing a Meshasset wil now Create a propery entity for the asset.
2022-12-27 21:16:56 +01:00
147 changed files with 5784 additions and 2624 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)

23
DEVELOPMENT.md Normal file
View File

@ -0,0 +1,23 @@
## Requirements
*_NOTE:_ Right now the build proces of some third party libraries have not been converted and may need special tooling*
#### Software
* Premake
* Git
* C++ Compiler
## Windows development workflow
User premake to generate project files for the approperiate build method.
On Windows I assume you'll build with visual studio
```bash
User:~$ premake vs2022
```
## Linux development workflow
Use premake to generate project files for the approperiate build method.
On Linux I assume you'll build with something like make.
```bash
User@Machine:~$ premake gmake2
```

1
Editor/.gitignore vendored Normal file
View File

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

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,149 +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;
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);
// 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 nullptr;
}
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.c_str(), 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,139 +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 << "strength";
emitter << YAML::Value << entity.GetComponent<LightComponent>().Strength;
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.Strength = entity["Light"]["strength"].as<float>();
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,172 +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,
project.get()->GetProjectDirectory() / "Assets"
);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Import MeshAsset (temp)"))
{
auto result = NFD_OpenDialog("mesh", NULL, &path);
switch (result) {
case(NFD_OKAY):
AssetManager::LoadFromAssetFile(path);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
break;
}
}
ImGui::EndMenu();
}
}
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,362 +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);
auto projection = glm::perspective(45.0f, 0.89f, 0.001f, 1.0f);
auto view = 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" };
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));
}
}
if (selected.HasComponent<LightComponent>()) {
auto& light = selected.GetComponent<LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat("Strength", &light.Strength, 0.001f);
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
}
}
if (selected.HasComponent <CameraComponent>()) {
auto& camera = selected.GetComponent<CameraComponent>();
static float Zoom = 90;
static glm::vec3 Position, Rotation = glm::vec3(0.0f);
ComponentView("Camera", [] {
ImGui::SliderFloat("Zoom", &Zoom, 10, 190);
ImGui::InputFloat3("Position:", &Position[0]);
ImGui::InputFloat3("Rotation:", &Rotation[0]);
});
}
if (selected.HasComponent<ScriptComponent>()) {
ComponentView("Scripting", [] {
ImGui::LabelText("##--", "Hello scripting");
});
}
}
};
class SceneExplorer : EditorWindow {
public:
SceneExplorer(entt::entity& selected , Scene& scene) : EditorWindow("SceneExplorer") {
scene.getReg().each([&](entt::entity enttNumber) {
Entity entity = Entity(enttNumber, &scene);
auto id = entity.GetComponent<IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), enttNumber == selected)) {
selected = enttNumber;
}
});
}
};
class Viewport : EditorWindow {
public:
Viewport (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);
ImGuizmo::ViewManipulate(glm::value_ptr(cam.ViewMatrix), 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(matrix));
}
};
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,218 +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>
#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
};
using namespace YoggieEngine;
class Editor : public Application {
public:
Editor()
: Application("Editor"),
AppWindow(1200,700),
framebuffer(new Framebuffer(1200,700)),
viewportRenderer(EditorSceneRendererConfig),
EditorGUIRenderer(AppWindow),
Selected((entt::entity)-1)
{
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);
});
viewportRenderer.Render();
}
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 a cube
auto model = importer.Import("build/Debug/Models/Cube.obj");
auto cube = scene.AddEntity("Cube");
auto& render3DComponent = cube.AddComponent<Render3DComponent>();
render3DComponent.mesh = *(model->renderable->mesh);
cube.GetComponent<TransformComponent>().Position = glm::vec3(1.0f, 0.0f, 5.0f);
auto cube2 = scene.AddEntity("Cube1");
auto& rendercube2 = cube2.AddComponent<Render3DComponent>();
rendercube2.mesh = *(model->renderable->mesh);
// create an ambient light source
auto AmbientLight = scene.AddEntity("AmbientLight");
auto light = AmbientLight.AddComponent<LightComponent>();
light.Color = glm::vec3(1.0f);
light.Strength = 1.0f;
}
YoggieEngine::Application *CreateApplication() { return new Editor(); }

View File

@ -1,26 +0,0 @@
# Yoggie Engine features
## Features
**NOTE** __Not in any particular order__
- Rendering
- OpenGL
- Vulkan
- Logging
- Different for debug and release
- Different per OS
- Physics
- PhysX
- Alternative for non-nvidia stuff?!
- Basic Entity Component system
- Graphical scripting ??
- Scripting support ( idk what language)
- LUA
- Configuration options
- JSON
- LUA
- YAML

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,40 +1,34 @@
# Yoggie Engine
<img src="Screenshots/Yoggie.webp" width="400" ></img>
<img src="Screenshots/Yoggie.webp" width="160" ></img>
## Goal
Must support building a full game in 48 hours.
The goal is to build a mature enough engine to be capable of using during game jams.
## Screenshots
## Features
*_NOTE:_ Just because it is listed as a feature here does not imply it has been nor guarantees it ever will be implemented*
- Rendering
- OpenGL
- Vulkan
- Metal (Possibly)
- Logging
- Different for debug and release
- Physics
- PhysX
- Jolt Physics
- Entity Component system
- Graphical scripting (Possibly)
- Scripting support
- LUA
- C# (for object orientated approaches to gamedev)
- Configuration options
- JSON
- YAML
- INI
<img src="Screenshots/screen1.png" width="300"></img> \
<img src="Screenshots/screen2.png" width="300"></img> \
<img src="Screenshots/YoggieEditor.png" width="300"></img> \
<img src="Screenshots/YoggieEditor_workingGuizmo.png" width="300"></img> \
<img src="Screenshots/YoggieEditorV0.2.png" width="300"></img>
## Planning
see [TODO](docs/TODO.md) \
see [Features](Features.md)
_NOTE:_
The planning is moving away from markdown in favor
of gitea Projects. New planning will be visible on [this page](https://git.barink.dev/Nigel/MyGameEngine/projects).
## Requirements
#### Software
* Premake
* Git
* C++ Compiler
## Windows development workflow
User premake to generate project files for the approperiate build method.
On Windows I assume you'll build with visual studio
```bash
User:~$ premake vs2022
```
## Linux development workflow
Use premake to generate project files for the approperiate build method.
On Linux I assume you'll build with something like make.
```bash
User@Machine:~$ premake gmake2
```
## More docs
[Todo list](TODO.md) \
[Planning](https://git.barink.dev/Nigel/MyGameEngine/projects)\
[Development](DEVELOPMENT.md)\
[Show case](SHOWCASE.md)

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;
}

17
SHOWCASE.md Normal file
View File

@ -0,0 +1,17 @@
## The engine development in pictures
__Testing OpenGl with ImGui as a concept__
<img src="Screenshots/OpenGLAndImGuiTest.png" width="300"></img>
__Working on docking with different windows using ImGui__
<img src="Screenshots/YoggieEditor_workingGuizmo.png" width="300"></img>
__A first more complete look of the engine__
<img src="Screenshots/YoggieEditorV0.2.png" width="300"></img>
__Mixing deferred and forward rendering and adding a skybox__
<img src="Screenshots/ImprovedRendering.png" width="300"></img>

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);

BIN
Screenshots/ImprovedRendering.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Screenshots/YoggieEditor.png (Stored with Git LFS)

Binary file not shown.

BIN
Screenshots/screen2.png (Stored with Git LFS)

Binary file not shown.

37
TODO.md
View File

@ -1,24 +1,23 @@
# Project Planning
**NOTE:** __Fairly detailed planning__
<input type="checkbox" checked></input> Setup build system \
<input type="checkbox" checked></input> Link with GLFW \
<input type="checkbox" checked></input> Basic Window \
<input type="checkbox" checked></input> Basic Triangle rendering \
<input type="checkbox" checked></input> Basic IMGui \
<input type="checkbox"></input> Basic Textures \
<input type="checkbox" checked></input> Link GLEW or GLAD \
<input type="checkbox" checked></input> Work on basic logging \
<input type="checkbox" checked></input> Input handling \
<input type="checkbox"></input> More shader work \
<input type="checkbox" checked></input> Load FBX model files \
<input type="checkbox"></input> Basic Physics \
<input type="checkbox" checked> Running LUA \
<input type="checkbox"> Lua Scripting \
<input type="checkbox"></input> To far in the future
<input type="checkbox" checked> Setup build system</input>\
<input type="checkbox" checked>Link with GLFW</input>\
<input type="checkbox" checked>Link GLEW or GLAD</input>\
<input type="checkbox" checked>Basic Window</input>\
<input type="checkbox" checked>Work on basic logging</input>\
<input type="checkbox" checked>Running LUA</input>\
<input type="checkbox" checked>Basic triangle rendering</input>\
<input type="checkbox" checked>Load model files</input>\
<input type="checkbox" checked>Basic ImGui </input>\
<input type="checkbox" checked>Skybox support</input>\
<input type="checkbox">Basic Textures <i>(Soon)</i></input>\
<input type="checkbox">More shader work <i>(Hopefully coming in January)</i></input> \
<input type="checkbox">Input handling <i>(Soon)</i></input>\
<input type="checkbox">Basic Physics <i>(Almost implemented)</i></input>\
<input type="checkbox">Lua Scripting <i>(Soon)</i> </input>\
<input type="checkbox">Basic Sound system</input>
### What's next?
I am not sure what's going to be added next
## Resources
https://renderdoc.org/ \

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

@ -0,0 +1,42 @@
#include <YoggieEngine.h>
#include "CubeMap.h"
YoggieEngine::CubeMap::CubeMap()
{
}
YoggieEngine::CubeMap::CubeMap(std::vector<std::string>& texture_faces)
{
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
stbi_set_flip_vertically_on_load(false);
int width, height, nrChannels;
unsigned char* data;
for (unsigned int i = 0; i < texture_faces.size(); i++)
{
data = stbi_load(texture_faces[i].c_str(), &width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
else {
spdlog::debug("Loading image {} failed!", texture_faces[i]);
stbi_image_free(data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
stbi_set_flip_vertically_on_load(true);
}
YoggieEngine::CubeMap::~CubeMap()
{
}

View File

@ -0,0 +1,19 @@
#pragma once
namespace YoggieEngine {
class CubeMap {
public:
CubeMap();
CubeMap(std::vector<std::string>& texture_faces);
~CubeMap();
unsigned int getID() { return textureID; }
private:
unsigned int textureID;
};
};

View File

@ -2,11 +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

@ -23,29 +23,12 @@ namespace YoggieEngine {
// Create a depth buffer
glGenTextures(1, &DepthAttachment);
glBindTexture(GL_TEXTURE_2D, DepthAttachment);
glGenRenderbuffers(1, &DepthAttachment);
glBindRenderbuffer(GL_RENDERBUFFER, DepthAttachment);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, DepthAttachment, 0);
/*
* // Render buffer
glGenRenderbuffers(1, &DepthAttachment);
glBindRenderbuffer(GL_RENDERBUFFER, DepthAttachment);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_RENDERBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthAttachment);
*/
if (!glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
{

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(glm::vec3 position, glm::vec3 rotation, float zoom)
: Position(position), Rotation(rotation), Zoom(zoom) {
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);
auto rotated_position = glm::rotate(glm::mat4(1.0f), Rotation.x, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::vec4(Position, 1.0f);
ViewMatrix = glm::lookAt(
Position,
glm::vec3{ rotated_position.x, rotated_position.y , rotated_position.z } + 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,25 +0,0 @@
#pragma once
namespace YoggieEngine {
class Camera {
public:
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

@ -2,7 +2,7 @@
#include "RenderSurface.h"
namespace YoggieEngine {
RenderSurface::RenderSurface() {
shader = new Shader("build/SandboxAppliction/Debug/renderSuface.vs", "build/SandboxApplication/Debug/renderSurface.fs");
shader = new Shader("build/SandboxAppliction/Debug/Shaders/forward/geometry.vert", "build/SandboxApplication/Debug/Shaders/forward/geometry.frag");
verts = std::vector<glm::vec3>{
{-0.5f, 0.5f, 0.0f}, // 0

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,123 +2,331 @@
#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"
namespace YoggieEngine {
Camera cam = Camera(glm::vec3(12.0f, 0.0f, 0.0f), glm::vec3(45.0f, 0.0f, 0.0f), 90.0f);
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)
};
Renderer::Renderer(RendererConfig& config)
: m_framebuffer(Framebuffer(config.ScreenWidth, config.ScreenHeight))
{
}
unsigned int transparentVAO, transparentVBO;
Texture grassTexture;
Renderer::~Renderer(){}
float skyboxVertices[]{
// 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
};
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 };
commands.push_back(dc);
}
void Renderer::Render()
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"),
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")
{
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
width = 800;
height = 600;
glEnable(GL_DEPTH_TEST);
CreateGBuffer();
if (m_depthTest) {
glEnable(GL_DEPTH_TEST);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
// - normal color buffer ;
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
// - Color + Specular buffer ;
glGenTextures(1, &gColorSpec);
glBindTexture(GL_TEXTURE_2D, gColorSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0);
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
// Create and attach a depth buffer
glGenRenderbuffers(1, &gDepth);
glBindRenderbuffer(GL_RENDERBUFFER, gDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gDepth);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
spdlog::critical("Framebuffer not complete {}{}", __FILE__, __LINE__);
}
glClearColor(m_clearColor.r, m_clearColor.g, m_clearColor.b, 1.0f);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
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);
for (const DrawCommand& command : commands)
// Render skybox if the scene has one
SkyboxShader.Use();
SkyboxShader.setUniformMat4("projection", MainCamera.getProjection(width, height));
SkyboxShader.setUniformMat4("view", glm::inverse(glm::mat4(glm::mat3(MainCamera.getTransform()))));
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);
}
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);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gColorSpec);
auto lights = scene.getReg().view<LightComponent, TransformComponent>();
unsigned int lightnr = 0;
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);
const float linear = 0.7f;
const float quadratic = 1.8f;
lightingPassShader.setUniformFloat(name + ".Linear", linear);
lightingPassShader.setUniformFloat(name + ".Quadratic", quadratic);
lightnr++;
}
if (quadVAO == 0)
{
glBindVertexArray(command.VAO_identifier);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.IBO_identifier);
float quadVertices[] = {
-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, 0.0f,
};
unsigned int quadVBO;
// setup plane VAO ;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, 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)));
}
command.shader.Use();
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), command.transform.Rotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
rotation *= glm::rotate(glm::mat4(1.0f), command.transform.Rotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
rotation *= glm::rotate(glm::mat4(1.0f), command.transform.Rotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), command.transform.Position) * glm::scale(glm::mat4(1.0f), command.transform.Scale) * rotation;
// Copy GBuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
glBindFramebuffer(GL_DRAW_BUFFER, m_framebuffer.GetId());
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
command.shader.setUniformVec3("Color", glm::vec3(0.3f, 0.3f, 0.3f));
command.shader.setUniformMat4("M", modelMatrix);
command.shader.setUniformMat4("V", cam.ViewMatrix);
command.shader.setUniformMat4("P", cam.ProjectionMatrix);
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,
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)
{
@ -130,5 +338,4 @@ void Renderer::setClearColor(const glm::vec3& ClearColor)
m_clearColor = ClearColor;
}
}

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,22 +15,99 @@ namespace YoggieEngine {
class Renderer {
public:
Renderer(RendererConfig& config);
Renderer();
~Renderer();
void Submit(Render3DComponent& renderComponent, TransformComponent& transform); // Collects DrawCommands
void Render(); // 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();
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();
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

@ -109,7 +109,7 @@ namespace YoggieEngine {
{
glUniform4fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector4));
}
void Shader::setUniformVec3(std::string uniformName, const glm::vec3& vector3) const
void Shader::setUniformVec3(std::string uniformName, const glm::vec3& vector3) const
{
glUniform3fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector3));
}

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*>();
}
}

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