more work on asset registry and importing process

This commit is contained in:
2026-05-17 19:12:27 -05:00
parent b3b7688f76
commit e02e92db10
13 changed files with 221 additions and 148 deletions

View File

@@ -23,15 +23,13 @@ file(GLOB_RECURSE HEADERS ${CMAKE_SOURCE_DIR}/src/*.h)
add_subdirectory(_ThirdParty/entt)
add_subdirectory(_ThirdParty/fmt)
add_subdirectory(_ThirdParty/spdlog)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(_ThirdParty/json)
add_subdirectory(_ThirdParty/uuid)
add_subdirectory(_ThirdParty/nfd)
set (ASSIMP_INSTALL OFF)
add_subdirectory(_ThirdParty/assimp)
if(UNIX)
find_path(UNZIP_PATH unzip.h PATHS
/usr/include
@@ -40,11 +38,11 @@ if(UNIX)
if(NOT UNZIP_PATH)
include_directories(/usr/include/minizip)
endif()
endif()
add_subdirectory(_ThirdParty/assimp)
target_compile_options(assimp PRIVATE
-Wno-unused-but-set-variable
)
endif()
add_executable(${PROJECT_NAME}
${IMGUI_SOURCES}
@@ -54,13 +52,6 @@ add_executable(${PROJECT_NAME}
src/ProjectManifestFile.cpp
src/ProjectManifestFile.h)
add_custom_target(copy_resources
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/resources"
"${CMAKE_CURRENT_BINARY_DIR}/resources"
COMMENT "Copying resources..."
)
target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm EnTT fmt nfd uuid)
target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE _ThirdParty/json/single_include)

View File

@@ -1 +1,5 @@
# b_engine
### if on linux and using wayland:
```cd _ThirdParty/nfd```
```git submodule update --init```

View File

@@ -3,13 +3,58 @@
//
#include "AssetRegistry.h"
#include "AssetRecord.h"
#include <filesystem>
#include <fstream>
#include <unordered_set>
#include "ModelManager.h"
#include "TextureManager.h"
#include "uuid.h"
#include "nlohmann/json.hpp"
#include "spdlog/spdlog.h"
std::unordered_map<uuids::uuid, std::unique_ptr<AssetRegistry>> AssetRegistry::_registry;
using json = nlohmann::json;
std::unordered_map<uuids::uuid, std::unique_ptr<AssetRecord>> AssetRegistry::_registry;
const std::unordered_set<std::string> TextureExtensions = {
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff"
};
const std::unordered_set<std::string> ModelExtensions = {
".obj", ".fbx", ".gltf", ".glb"
};
const std::unordered_set<std::string> ShaderExtensions = {
".vert", ".frag", ".glsl"
};
AssetType check_asset_type(const Path& path)
{
if (!path.has_extension()) {
return AssetType::UNKNOWN;
}
if (fs::is_directory(path)) {
return AssetType::DIRECTORY;
}
if (TextureExtensions.contains(path.extension().string())) {
return AssetType::TEXTURE;
}
if (ModelExtensions.contains(path.extension().string())) {
return AssetType::MODEL;
}
if (ShaderExtensions.contains(path.extension().string())) {
return AssetType::SHADER;
}
return AssetType::UNKNOWN;
}
uuids::uuid generate_uuid()
{
@@ -33,27 +78,40 @@ uuids::uuid generate_uuid()
return gen();
}
void AssetRegistry::read_source_folder(const std::string_view _folder) {
if (_folder.empty()) {
return;
void AssetRegistry::read_directory(const Path& path) {
fs::recursive_directory_iterator directory{path};
std::vector<fs::directory_entry> entries;
for (const auto& entry : directory) {
if (entry.exists()) {
entries.push_back(entry);
}
}
const Path path {_folder};
Directory directory {path};
for (const auto entry : directory) {
if (!entry.exists()) {
for (const auto& entry : entries) {
if (entry.path().extension() == ".meta") {
continue;
}
if (!generate_meta_file(entry.path())) {
spdlog::error("Failed to generate meta file for {}", entry.path().string());
continue;
}
std::optional<AssetRecord> record = read_meta_file(entry.path());
if (!record)
{
continue;
}
_registry[record->uuid] = std::make_unique<AssetRecord>(*record);
AssetRecord* asset = _registry[record->uuid].get();
load_asset(asset);
if (entry.is_directory()) {
read_source_folder(entry.path().c_str());
continue;
read_directory(entry.path());
}
uuid_t uuid;
generate_meta_file(entry.path());
}
}
@@ -63,18 +121,79 @@ bool AssetRegistry::does_meta_exist(const Path& path) {
return fs::exists(meta);
}
void AssetRegistry::generate_meta_file(const Path &path) {
std::optional<AssetRecord> AssetRegistry::read_meta_file(const Path &path) {
Path meta = path;
meta += ".meta";
if (fs::exists(meta)) {
return;
}
AssetRecord record;
record.uuid = generate_uuid();
record.sourcePath = path.c_str();
std::ofstream file {meta};
file.close();
if (!fs::exists(meta) && !generate_meta_file(path)) {
return std::optional<AssetRecord>{};
}
std::stringstream ss;
try {
std::ifstream file {meta};
ss << file.rdbuf();
file.close();
} catch (const std::exception& e) {
spdlog::error("Failed to read meta file: {}", e.what());
return std::optional<AssetRecord>{};
}
std::string metaContent = ss.str();
json metaJson = json::parse(metaContent);
auto uuidString = metaJson["uuid"].get<std::string>();
std::optional<uuids::uuid> uuid = uuids::uuid::from_string(uuidString);
if (!uuid)
{
return std::optional<AssetRecord>{};
}
record.uuid = *uuid;
record.sourcePath = metaJson["sourcePath"].get<std::string>();
record.assetType = static_cast<AssetType>(metaJson["assetType"].get<int>());
return std::optional{record};
}
bool AssetRegistry::generate_meta_file(const Path& path)
{
Path meta = path;
meta += ".meta";
if (fs::exists(meta)) return true;
nlohmann::json j;
j["uuid"] = uuids::to_string(generate_uuid());
j["sourcePath"] = path.string();
j["assetType"] = check_asset_type(path);
try {
std::ofstream file {meta};
std::stringstream ss;
ss << j.dump();
file << ss.str();
file.close();
} catch (const std::exception& e) {
spdlog::error("File exception while generating meta file: {}", e.what());
return false;
}
return true;
}
void AssetRegistry::load_asset(AssetRecord* asset) {
switch (asset->assetType) {
case AssetType::SHADER:
break;
case AssetType::TEXTURE:
TextureManager::textures[asset->uuid] = TextureManager::load_from_file(asset->sourcePath);
break;
case AssetType::MODEL:
ModelManager::models[asset->uuid] = ModelManager::load_from_file(asset->sourcePath);
break;
default:
break;
}
}

View File

@@ -6,14 +6,12 @@
#define B_ENGINE_ASSETREGISTRY_H
#include <unordered_map>
#include <uuid/uuid.h>
#include <memory>
#include <vector>
#include <string_view>
#include <filesystem>
#include "AssetRecord.h"
#include "uuid.h"
namespace fs = std::filesystem;
@@ -23,15 +21,17 @@ using Path = fs::path;
class AssetRegistry {
public:
static void read_source_folder(std::string_view _folder);
static void read_directory(const Path& path);
static std::vector<AssetRegistry*> get_records();
static AssetRegistry* get_record(uuid_t uuid);
static std::vector<AssetRecord*> get_records();
static AssetRecord* get_record(uuids::uuid uuid);
private:
static std::unordered_map<uuids::uuid, std::unique_ptr<AssetRegistry>> _registry;
static std::unordered_map<uuids::uuid, std::unique_ptr<AssetRecord>> _registry;
static bool does_meta_exist(const Path& path);
static void generate_meta_file(const Path& path);
static std::optional<AssetRecord> read_meta_file(const Path& path);
static bool generate_meta_file(const Path& path);
static void load_asset(AssetRecord* asset);
};

View File

@@ -15,15 +15,14 @@
#include "TextureManager.h"
#include "glm/ext/matrix_transform.hpp"
std::unordered_map<std::string, std::shared_ptr<Model>> ModelManager::models;
std::unordered_map<uuids::uuid, std::unique_ptr<Model>> ModelManager::models;
void process_ai_node(aiNode* node, const aiScene* scene, glm::mat4 transform, ModelNode& model);
void process_ai_mesh(const aiMesh* aiMesh, Mesh& mesh);
void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory);
/*void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory);
void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);
void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);
void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);*/
auto zUpMatrix = glm::mat4(
1.0f, 0.0f, 0.0f, 0.0f, // Column 0
@@ -32,7 +31,7 @@ auto zUpMatrix = glm::mat4(
0.0f, 0.0f, 0.0f, 1.0f // Column 3
);
std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool zUp)
std::unique_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool zUp)
{
Assimp::Importer importer;
@@ -47,10 +46,10 @@ std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool
return nullptr;
}
auto model = std::make_shared<Model>();
auto model = std::make_unique<Model>();
const std::filesystem::path modelPath = {_path};
for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
/*for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
aiMaterial* aiMat = scene->mMaterials[i];
aiString matName;
if (aiMat->Get(AI_MATKEY_NAME, matName) && strcmp(matName.data, "DefaultMaterial") == 0) {
@@ -59,7 +58,7 @@ std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool
Material mat{};
process_ai_material(aiMat, mat, modelPath.parent_path());
model->materials.push_back(std::make_shared<Material>(mat));
}
}*/
for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
aiMesh* aiMesh = scene->mMeshes[i];
@@ -148,7 +147,7 @@ void process_ai_mesh(const aiMesh* aiMesh, Mesh& mesh)
mesh = {positions, uvs, normals, indices};
}
void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
/*void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
aiString matName;
aiReturn ret = aiMat->Get(AI_MATKEY_NAME, matName);
if (ret != AI_SUCCESS) {
@@ -193,9 +192,9 @@ void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::file
mat.phong.diffuse = glm::vec3{diffuseColor.r, diffuseColor.g, diffuseColor.b};
mat.phong.specular = glm::vec3{specularColor.r, specularColor.g, specularColor.b};
mat.phong.shininess = shininess;
}
}*/
void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
/*void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
aiString aiTextureName;
aiMat->GetTexture(aiTextureType_DIFFUSE, 0, &aiTextureName);
std::string textureName = aiTextureName.C_Str();
@@ -259,4 +258,4 @@ void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const
} else {
mat.specular = TextureManager::textures["default_specular"];
}
}
}*/

View File

@@ -9,13 +9,14 @@
#include <string_view>
#include "Model.h"
#include "uuid.h"
class ModelManager
{
public:
static std::unordered_map<std::string, std::shared_ptr<Model>> models;
static std::unordered_map<uuids::uuid, std::unique_ptr<Model>> models;
static std::shared_ptr<Model> load_from_file(std::string_view _path, bool zUp = false);
static std::unique_ptr<Model> load_from_file(std::string_view _path, bool zUp = false);
};

View File

@@ -6,11 +6,14 @@
#define B_ENGINE_PROJECTMANIFEST_H
#include <string>
#include <filesystem>
typedef struct
{
std::string name;
std::string assetFolder;
std::filesystem::path projectDirectory;
} ProjectManifest;
#endif //B_ENGINE_PROJECTMANIFEST_H

View File

@@ -14,9 +14,9 @@
void log_shader_compile_errors(GLuint shader, std::string_view shaderType);
void log_program_compile_errors(GLuint program);
std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> ShaderManager::shaders;
std::unordered_map<uuids::uuid, std::unique_ptr<ShaderProgram>> ShaderManager::shaders;
std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath, std::string_view fragmentPath)
std::unique_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath, std::string_view fragmentPath)
{
std::string vertexSource;
std::string fragmentSource;
@@ -24,8 +24,7 @@ std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath,
std::ifstream vertexFile {};
std::ifstream fragmentFile {};
try
{
try {
vertexFile.open(vertexPath.data());
fragmentFile.open(fragmentPath.data());
@@ -39,8 +38,8 @@ std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath,
vertexFile.close();
fragmentFile.close();
} catch (std::ifstream::failure& e) {
spdlog::error("Failed to load shader program {}, {}: {}", vertexPath, fragmentPath, std::string(e.what()).c_str());
} catch (std::fstream::failure& e) {
spdlog::error("Failed to load shader program {}, {}: {}", vertexPath, fragmentPath, e.what());
return nullptr;
}

View File

@@ -10,12 +10,13 @@
#include <memory>
#include "ShaderProgram.h"
#include "uuid.h"
class ShaderManager {
public:
static std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> shaders;
static std::unordered_map<uuids::uuid, std::unique_ptr<ShaderProgram>> shaders;
static std::unique_ptr<ShaderProgram> load(std::string_view vertexPath, std::string_view fragmentPath);
static std::shared_ptr<ShaderProgram> load(std::string_view vertexPath, std::string_view fragmentPath);
};
#endif //B_ENGINE_SHADERMANAGER_H

View File

@@ -5,14 +5,15 @@
#include "TextureManager.h"
#include "stb_image.h"
#include "uuid.h"
#include "spdlog/spdlog.h"
#include "glad/gl.h"
std::unordered_map<std::string, std::shared_ptr<Texture>> TextureManager::textures;
std::unordered_map<uuids::uuid, std::unique_ptr<Texture>> TextureManager::textures;
std::shared_ptr<Texture> TextureManager::load_from_file(std::string_view filePath)
std::unique_ptr<Texture> TextureManager::load_from_file(const std::string_view filePath)
{
int width, height, channels;
unsigned char *data = stbi_load(filePath.data(), &width, &height, &channels, 0);
@@ -38,10 +39,10 @@ std::shared_ptr<Texture> TextureManager::load_from_file(std::string_view filePat
stbi_image_free(data);
return std::make_shared<Texture>(textureID, filePath, width, height, channels);
return std::make_unique<Texture>(textureID, filePath, width, height, channels);
}
std::shared_ptr<Texture> TextureManager::load_from_data(unsigned char* data, int width, int height, int channels)
std::unique_ptr<Texture> TextureManager::load_from_data(unsigned char* data, int width, int height, int channels)
{
unsigned int textureID = 0;
glGenTextures(1, &textureID);
@@ -57,5 +58,5 @@ std::shared_ptr<Texture> TextureManager::load_from_data(unsigned char* data, int
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
return std::make_shared<Texture>(textureID, "memory", width, height, channels);
return std::make_unique<Texture>(textureID, "memory", width, height, channels);
}

View File

@@ -5,17 +5,19 @@
#ifndef B_ENGINE_TEXTUREMANAGER_H
#define B_ENGINE_TEXTUREMANAGER_H
#include <filesystem>
#include <memory>
#include <unordered_map>
#include "Texture.h"
#include "uuid.h"
class TextureManager {
public:
static std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
static std::unordered_map<uuids::uuid, std::unique_ptr<Texture>> textures;
static std::shared_ptr<Texture> load_from_file(std::string_view filePath);
static std::shared_ptr<Texture> load_from_data(unsigned char* data, int width, int height, int channels);
static std::unique_ptr<Texture> load_from_file(std::string_view filePath);
static std::unique_ptr<Texture> load_from_data(unsigned char* data, int width, int height, int channels);
};
#endif //B_ENGINE_TEXTUREMANAGER_H

View File

@@ -6,9 +6,11 @@
#define B_ENGINE_TYPES_H
enum class AssetType {
SHADER = 0,
TEXTURE = 1,
MODEL = 2
UNKNOWN = 0,
DIRECTORY = 1,
SHADER = 2,
TEXTURE = 3,
MODEL = 4
};
#endif //B_ENGINE_TYPES_H

View File

@@ -7,6 +7,7 @@
#include "glm/ext/matrix_clip_space.hpp"
#define STB_IMAGE_IMPLEMENTATION
#include "AssetRegistry.h"
#include "stb_image.h"
#include "Camera.h"
@@ -28,6 +29,8 @@
#include "ui/UISceneGraph.h"
#include "ui/UISceneViewer.h"
#include <filesystem>
const char* B_ENGINE_VERSION = "v0.0.3";
GLFWwindow* gWindow = nullptr;
@@ -43,10 +46,11 @@ float gMouseSensitivity = 0.1f;
std::unique_ptr<ProjectManifest> gCurrentProject {nullptr};
Camera gCamera {};
Scene gScene{};
EditorContext gEditorCtx{};
FreeCameraController gCameraController{};
Camera gCamera {};
FreeCameraController gEditorCameraController{};
void glfw_error_callback(int error, const char* description);
void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
@@ -55,12 +59,8 @@ void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height);
void init_glfw();
void create_main_window();
void load_gl();
void init_camera();
void init_scene();
void load_default_textures();
void load_shaders();
void load_inputs();
void load_default_models();
void init_editor_camera();
void loop();
void create_entity(entt::entity parent);
@@ -81,14 +81,8 @@ int main() {
stbi_set_flip_vertically_on_load(true);
load_default_textures();
load_shaders();
load_inputs();
load_default_models();
UIManager::init(gWindow);
auto* menuBar = UIManager::add_ui_panel<UIMenuBar>("menu_bar");
menuBar->create_entity = create_entity;
@@ -97,14 +91,11 @@ int main() {
UIManager::add_ui_panel<UISceneGraph>("scene_graph");
UIManager::add_ui_panel<UIEntityInspector>("entity_inspector");
init_camera();
init_scene();
gCameraController.set_camera(gCamera);
gCameraController.look_sensitivity = 0.2;
gCameraController.movement_speed = 0.2;
gEditorCameraController.set_camera(gCamera);
gEditorCameraController.look_sensitivity = 0.2;
gEditorCameraController.movement_speed = 0.2;
InputManager::add_mouse_listener([](float xoff, float yoff) {
gCameraController.on_mouse_delta(xoff, yoff);
gEditorCameraController.on_mouse_delta(xoff, yoff);
});
gEditorCtx.scene = &gScene;
@@ -133,8 +124,7 @@ void glfw_framebuffer_size_callback(GLFWwindow *window, int width, int height) {
gCamera.update_aspect_ratio(gAspectRatio);
}
void init_glfw()
{
void init_glfw() {
if (!glfwInit()) {
spdlog::error("could not initialize glfw");
std::exit(1);
@@ -163,10 +153,6 @@ void create_main_window()
glfwSetCursorPosCallback(gWindow, InputManager::mouse_pos_callback);
glfwSetFramebufferSizeCallback(gWindow, glfw_framebuffer_size_callback);
#ifndef GLFW_CONTEXT_DEBUG
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
}
void load_gl()
@@ -187,45 +173,12 @@ void load_gl()
glEnable(GL_MULTISAMPLE);
}
void init_camera() {
void init_editor_camera() {
gCamera = {{10.f, 10.f, 10.f}, 0, 0, gAspectRatio};
gCamera.rotate_yaw(-135.f);
gCamera.rotate_pitch(-35.f);
}
void init_scene() {
gScene.set_active_camera(&gCamera);
const auto defaultLight = gScene.create_game_object();
auto& [name] = gScene.fetch_component<Components::Tag>(defaultLight);
name = "Directional Light";
auto& [direction, ambient, diffuse, specular] = gScene.attach_component<Components::DirectionalLight>(defaultLight);
direction = glm::vec3(-1, -1, -1);
ambient = glm::vec3(0.3);
diffuse = glm::vec3(0.7);
specular = glm::vec3(1.0);
}
void load_default_textures() {
spdlog::info("creating default textures");
unsigned char defaultDiffuseData[4] = {static_cast<unsigned char>(255), 255, 255, 255};
TextureManager::textures["default_diffuse"] = TextureManager::load_from_data(reinterpret_cast<unsigned char*>(&defaultDiffuseData), 1, 1, 4);
unsigned char defaultSpecularData[4] = {static_cast<unsigned char>(64), 64, 64, 255};
TextureManager::textures["default_specular"] = TextureManager::load_from_data(reinterpret_cast<unsigned char*>(&defaultSpecularData), 1, 1, 4);
}
void load_shaders() {
spdlog::info("compiling shaders");
ShaderManager::shaders["phong_shader"] = ShaderManager::load("./resources/standard.vert", "./resources/standard.frag");
if (ShaderManager::shaders["phong_shader"] == nullptr)
{
spdlog::error("failed to compile phong shader");
std::exit(1);
}
}
void load_inputs() {
InputManager::generate_input_action("move_forward", {{GLFW_KEY_W, KEY_DOWN}});
InputManager::generate_input_action("move_backward", {{GLFW_KEY_S, KEY_DOWN}});
@@ -235,13 +188,6 @@ void load_inputs() {
InputManager::generate_input_action("move_down", {{GLFW_KEY_LEFT_SHIFT, KEY_DOWN}});
}
void load_default_models() {
spdlog::info("loading default models");
ModelManager::models["cube"] = ModelManager::load_from_file("./resources/cube.obj");
ModelManager::models["vette"] = ModelManager::load_from_file("./resources/c4/C4Fixed.obj");
ModelManager::models["male"] = ModelManager::load_from_file("./resources/male.obj");
}
void loop() {
while (!glfwWindowShouldClose(gWindow)) {
// input
@@ -249,7 +195,7 @@ void loop() {
// update
UIManager::update(gEditorCtx);
gCameraController.update(gEditorCtx);
gEditorCameraController.update(gEditorCtx);
if (gCamera.aspect_ratio() != gEditorCtx.viewportAspectRatio) {
gCamera.update_aspect_ratio(gEditorCtx.viewportAspectRatio);
@@ -266,8 +212,8 @@ void loop() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const auto shader = ShaderManager::shaders["phong_shader"];
gScene.draw_scene(shader.get());
// const auto shader = ShaderManager::shaders["phong_shader"];
// gScene.draw_scene(shader.get());
glBindVertexArray(0);
ShaderProgram::unbind();
@@ -285,7 +231,12 @@ void create_entity(entt::entity parent) {
}
void open_project(std::string_view _path) {
const std::filesystem::path projectFilePath {_path};
gCurrentProject = ProjectManifestFile::load(_path);
gCurrentProject->projectDirectory = projectFilePath.parent_path();
std::filesystem::path assetPath = gCurrentProject->projectDirectory.append(gCurrentProject->assetFolder);
AssetRegistry::read_directory(assetPath);
const std::string title = fmt::format("project \"{}\" | b_engine {}", gCurrentProject->name, B_ENGINE_VERSION);
glfwSetWindowTitle(gWindow, title.c_str());