diff --git a/.gitmodules b/.gitmodules index a56b36f..56c8f91 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,9 @@ [submodule "_ThirdParty/fmt"] path = _ThirdParty/fmt url = https://github.com/fmtlib/fmt.git +[submodule "_ThirdParty/json"] + path = _ThirdParty/json + url = https://github.com/nlohmann/json.git +[submodule "_ThirdParty/nfd"] + path = _ThirdParty/nfd + url = https://github.com/btzy/nativefiledialog-extended.git diff --git a/CMakeLists.txt b/CMakeLists.txt index e571e4f..f9e716d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,23 @@ set (GLFW_BUILD_TESTS OFF) set (GLFW_BUILD_DOCS OFF) add_subdirectory(_ThirdParty/glfw) +add_subdirectory(_ThirdParty/glm) + +include_directories(src/imgui) +file(GLOB_RECURSE IMGUI_SOURCES src/imgui/*.cpp) + +file(GLOB_RECURSE SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp) +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/nfd) + set (ASSIMP_INSTALL OFF) if(UNIX) find_path(UNZIP_PATH unzip.h PATHS @@ -26,26 +41,16 @@ if(UNIX) endif() add_subdirectory(_ThirdParty/assimp) target_compile_options(assimp PRIVATE - -Wno-unused-but-set-variable + -Wno-unused-but-set-variable ) -add_subdirectory(_ThirdParty/glm) - -add_subdirectory(_ThirdParty/entt) - -add_subdirectory(_ThirdParty/fmt) - -include_directories(src/imgui) -file(GLOB_RECURSE IMGUI_SOURCES src/imgui/*.cpp) - -file(GLOB_RECURSE SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp) -file(GLOB_RECURSE HEADERS ${CMAKE_SOURCE_DIR}/src/*.h) - add_executable(${PROJECT_NAME} ${IMGUI_SOURCES} ${GLAD_SOURCE_DIR}/gl.c ${SOURCES} - ${HEADERS}) + ${HEADERS} + src/ProjectManifestFile.cpp + src/ProjectManifestFile.h) add_custom_target(copy_resources COMMAND ${CMAKE_COMMAND} -E copy_directory @@ -54,6 +59,7 @@ add_custom_target(copy_resources COMMENT "Copying resources..." ) -target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm EnTT fmt) +target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm EnTT fmt nfd) target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR}) target_include_directories(${PROJECT_NAME} PRIVATE src) +target_include_directories(${PROJECT_NAME} PRIVATE _ThirdParty/json/single_include) diff --git a/_ThirdParty/json b/_ThirdParty/json new file mode 160000 index 0000000..630beae --- /dev/null +++ b/_ThirdParty/json @@ -0,0 +1 @@ +Subproject commit 630beaeb05473986400c2d933d67171b3fb2d15d diff --git a/_ThirdParty/nfd b/_ThirdParty/nfd new file mode 160000 index 0000000..c9cc7ba --- /dev/null +++ b/_ThirdParty/nfd @@ -0,0 +1 @@ +Subproject commit c9cc7baf287f969686561674a555af5be7ac82b1 diff --git a/src/ProjectManifest.h b/src/ProjectManifest.h index ae33c18..8a5e4e9 100644 --- a/src/ProjectManifest.h +++ b/src/ProjectManifest.h @@ -5,9 +5,12 @@ #ifndef B_ENGINE_PROJECTMANIFEST_H #define B_ENGINE_PROJECTMANIFEST_H -struct ProjectManifest -{ +#include -}; +typedef struct +{ + std::string name; + std::string assetFolder; +} ProjectManifest; #endif //B_ENGINE_PROJECTMANIFEST_H diff --git a/src/ProjectManifestFile.cpp b/src/ProjectManifestFile.cpp new file mode 100644 index 0000000..f1b36b5 --- /dev/null +++ b/src/ProjectManifestFile.cpp @@ -0,0 +1,38 @@ +// +// Created by slinky on 5/14/26. +// + +#include "ProjectManifestFile.h" + +#include + +#include "spdlog/spdlog.h" +#include "nlohmann/json.hpp" + +using json = nlohmann::json; + +std::unique_ptr ProjectManifestFile::load(std::string_view _path) { + std::ifstream file; + file.open(_path.data(), std::ios::in); + if (!file.is_open()) { + spdlog::error("failed to open project file {}", _path); + return nullptr; + } + + std::stringstream ss; + ss << file.rdbuf(); + + std::string fileData = ss.str(); + + auto data = json::parse(fileData); + + ProjectManifest manifest; + manifest.name = data.at("name").get(); + manifest.assetFolder = data.at("assetFolder").get(); + + return std::make_unique(manifest); +} + +bool ProjectManifestFile::save(std::string_view _path, ProjectManifest *_project) { + return true; +} diff --git a/src/ProjectManifestFile.h b/src/ProjectManifestFile.h new file mode 100644 index 0000000..02538ce --- /dev/null +++ b/src/ProjectManifestFile.h @@ -0,0 +1,19 @@ +// +// Created by slinky on 5/14/26. +// + +#ifndef B_ENGINE_PROJECTMANIFESTFILE_H +#define B_ENGINE_PROJECTMANIFESTFILE_H + +#include +#include + +#include "ProjectManifest.h" + +class ProjectManifestFile { +public: + static std::unique_ptr load(std::string_view _path); + static bool save(std::string_view _path, ProjectManifest* _project); +}; + +#endif //B_ENGINE_PROJECTMANIFESTFILE_H \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 910fca3..a9caeb1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,8 @@ #include "FreeCameraController.h" #include "InputManager.h" #include "ModelManager.h" +#include "ProjectManifest.h" +#include "ProjectManifestFile.h" #include "Scene.h" #include "ShaderManager.h" #include "ShaderProgram.h" @@ -26,6 +28,8 @@ #include "ui/UISceneGraph.h" #include "ui/UISceneViewer.h" +const char* B_ENGINE_VERSION = "v0.0.3"; + GLFWwindow* gWindow = nullptr; int gWindowWidth = 1920; int gWindowHeight = 1080; @@ -37,6 +41,8 @@ float gAspectRatio = 0.f; float gMouseSensitivity = 0.1f; +std::unique_ptr gCurrentProject {nullptr}; + Camera gCamera {}; Scene gScene{}; EditorContext gEditorCtx{}; @@ -58,13 +64,14 @@ void load_default_models(); void loop(); void create_entity(entt::entity parent); +void open_project(std::string_view _path); auto xAxis = glm::vec3{1.f, 0.f, 0.f}; auto yAxis = glm::vec3{0.f, 1.f, 0.f}; auto zAxis = glm::vec3{0.f, 0.f, 1.f}; int main() { - spdlog::info("b_engine v0.0.3 start"); + spdlog::info("b_engine {} start", B_ENGINE_VERSION); init_glfw(); @@ -83,8 +90,9 @@ int main() { load_default_models(); UIManager::init(gWindow); - UIMenuBar* menuBar = UIManager::add_ui_panel("menu_bar"); + auto* menuBar = UIManager::add_ui_panel("menu_bar"); menuBar->create_entity = create_entity; + menuBar->open_project = open_project; UIManager::add_ui_panel("scene_viewer"); UIManager::add_ui_panel("scene_graph"); UIManager::add_ui_panel("entity_inspector"); @@ -142,7 +150,8 @@ void init_glfw() void create_main_window() { - gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, "b_engine v0.0.3", nullptr, nullptr); + std::string title = fmt::format("b_engine {}", B_ENGINE_VERSION); + gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, title.c_str(), nullptr, nullptr); if (!gWindow) { spdlog::error("failed to create glfw window"); std::exit(1); @@ -272,10 +281,12 @@ void loop() { } void create_entity(entt::entity parent) { - auto entity = gScene.create_game_object(parent); - auto& drawable = gScene.attach_component(entity); - drawable.model = ModelManager::models["vette"]; - auto& transform = gScene.fetch_component(entity); - transform.scale = {0.1, 0.1, 0.1}; - transform.dirty = true; + gScene.create_game_object(parent); +} + +void open_project(std::string_view _path) { + gCurrentProject = ProjectManifestFile::load(_path); + + const std::string title = fmt::format("project \"{}\" | b_engine {}", gCurrentProject->name, B_ENGINE_VERSION); + glfwSetWindowTitle(gWindow, title.c_str()); } diff --git a/src/ui/UIMenuBar.cpp b/src/ui/UIMenuBar.cpp index f888d41..f48cc45 100644 --- a/src/ui/UIMenuBar.cpp +++ b/src/ui/UIMenuBar.cpp @@ -4,16 +4,34 @@ #include "UIMenuBar.h" #include "UIManager.h" +#include "UISceneGraph.h" #include "imgui.h" -#include "UISceneGraph.h" + +#include "nfd.h" void UIMenuBar::update(EditorContext &context) { if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("New Scene")) { + if (ImGui::MenuItem("New Project")) { } - if (ImGui::MenuItem("Open Scene")) { + if (ImGui::MenuItem("Open Project")) { + NFD_Init(); + + nfdu8char_t *outPath; + nfdu8filteritem_t filters[1] = { { "b_engine project files", "json" } }; + nfdopendialogu8args_t args = {0}; + args.filterList = filters; + args.filterCount = 1; + nfdresult_t result = NFD_OpenDialogU8_With(&outPath, &args); + + if (result == NFD_OKAY && open_project) + { + open_project(outPath); + NFD_FreePathU8(outPath); + } + + NFD_Quit(); } ImGui::Separator(); // Adds a visual line between sections if (ImGui::MenuItem("Save", "Ctrl+S")) { diff --git a/src/ui/UIMenuBar.h b/src/ui/UIMenuBar.h index f449e75..dcdb030 100644 --- a/src/ui/UIMenuBar.h +++ b/src/ui/UIMenuBar.h @@ -12,6 +12,7 @@ public: void update(EditorContext &context) override; std::function create_entity; + std::function open_project; };