#include "glad/gl.h" #include "GLFW/glfw3.h" #include "spdlog/spdlog.h" #include "glm/glm.hpp" #include "glm/ext/matrix_clip_space.hpp" #define STB_IMAGE_IMPLEMENTATION #include "AssetRegistry.h" #include "stb_image.h" #include "Camera.h" #include "Components.h" #include "EditorContext.h" #include "FreeCameraController.h" #include "InputManager.h" #include "ModelManager.h" #include "ProjectManifest.h" #include "ProjectManifestFile.h" #include "Scene.h" #include "ShaderManager.h" #include "ShaderProgram.h" #include "TextureManager.h" #include "UIManager.h" #include "ui/UIEntityInspector.h" #include "ui/UIMenuBar.h" #include "ui/UISceneGraph.h" #include "ui/UISceneViewer.h" #include const char* B_ENGINE_VERSION = "v0.0.3"; GLFWwindow* gWindow = nullptr; int gWindowWidth = 1920; int gWindowHeight = 1080; int glVersionMajor = 0; int glVersionMinor = 0; float gAspectRatio = 0.f; float gMouseSensitivity = 0.1f; std::unique_ptr gCurrentProject {nullptr}; Scene gScene{}; EditorContext gEditorCtx{}; 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); void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height); void init_glfw(); void create_main_window(); void load_gl(); void load_inputs(); void init_editor_camera(); 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 {} start", B_ENGINE_VERSION); init_glfw(); create_main_window(); load_gl(); stbi_set_flip_vertically_on_load(true); load_inputs(); UIManager::init(gWindow); 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"); gEditorCameraController.set_camera(gCamera); gEditorCameraController.look_sensitivity = 0.2; gEditorCameraController.movement_speed = 0.2; InputManager::add_mouse_listener([](float xoff, float yoff) { gEditorCameraController.on_mouse_delta(xoff, yoff); }); gEditorCtx.scene = &gScene; gEditorCtx.window = gWindow; gEditorCtx.selectedEntity = entt::null; loop(); ShaderManager::shaders.clear(); TextureManager::textures.clear(); ModelManager::models.clear(); glfwDestroyWindow(gWindow); glfwTerminate(); return 0; } void glfw_error_callback(int error, const char* description) { spdlog::error("glfw error: {}", description); } void glfw_framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); gAspectRatio = (float)width / (float)height; gCamera.update_aspect_ratio(gAspectRatio); } void init_glfw() { if (!glfwInit()) { spdlog::error("could not initialize glfw"); std::exit(1); } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_SAMPLES, 4); glfwSetErrorCallback(glfw_error_callback); } void create_main_window() { 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); } glfwMakeContextCurrent(gWindow); glfwSetKeyCallback(gWindow, InputManager::key_callback); glfwSetCursorPosCallback(gWindow, InputManager::mouse_pos_callback); glfwSetFramebufferSizeCallback(gWindow, glfw_framebuffer_size_callback); } void load_gl() { int version = gladLoadGL(glfwGetProcAddress); glVersionMajor = GLAD_VERSION_MAJOR(version); glVersionMinor = GLAD_VERSION_MINOR(version); spdlog::info("gl version {}.{}", glVersionMajor, glVersionMinor); if (gWindow) { int fbWidth, fbHeight; glfwGetFramebufferSize(gWindow, &fbWidth, &fbHeight); gAspectRatio = (float)fbWidth / (float)fbHeight; } glEnable(GL_DEPTH_TEST); glEnable(GL_MULTISAMPLE); } 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 load_inputs() { InputManager::generate_input_action("move_forward", {{GLFW_KEY_W, KEY_DOWN}}); InputManager::generate_input_action("move_backward", {{GLFW_KEY_S, KEY_DOWN}}); InputManager::generate_input_action("move_right", {{GLFW_KEY_D, KEY_DOWN}}); InputManager::generate_input_action("move_left", {{GLFW_KEY_A, KEY_DOWN}}); InputManager::generate_input_action("move_up", {{GLFW_KEY_SPACE, KEY_DOWN}}); InputManager::generate_input_action("move_down", {{GLFW_KEY_LEFT_SHIFT, KEY_DOWN}}); } void loop() { while (!glfwWindowShouldClose(gWindow)) { // input glfwPollEvents(); // update UIManager::update(gEditorCtx); gEditorCameraController.update(gEditorCtx); if (gCamera.aspect_ratio() != gEditorCtx.viewportAspectRatio) { gCamera.update_aspect_ratio(gEditorCtx.viewportAspectRatio); } gScene.update_transforms(); const auto* uiScenePanel = dynamic_cast(UIManager::get_ui_panel("scene_viewer").get()); if (uiScenePanel) { uiScenePanel->bind_fbo(); } // draw 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()); glBindVertexArray(0); ShaderProgram::unbind(); glBindFramebuffer(GL_FRAMEBUFFER, 0); UIManager::draw(); // end frame glfwSwapBuffers(gWindow); } } void create_entity(entt::entity parent) { gScene.create_game_object(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()); }