diff --git a/demo/main.cpp b/demo/main.cpp index e2481d8a894d89e4c4881ef26357604daa16876b..c54a40a8383bc6fff2b3d09eaaadcd549868c1d1 100644 --- a/demo/main.cpp +++ b/demo/main.cpp @@ -332,12 +332,21 @@ public: void update() override { process_camera(m_world, m_inputs); + + if ( m_inputs->keyboard.pressed(glfwGetKeyScancode(GLFW_KEY_F10)) ) { + auto dbgui = fggl::util::ServiceLocator::instance().providePtr<fggl::debug::DebugUI>(); + dbgui->visible( !dbgui->visible() ); + } } void render() override { + + } + + // entity inspector + void debugInspector(bool* visible) { auto types = m_world.types(); - // ECS3 inspector ImGui::Begin("Entities"); auto entityItr = m_world.all(); for (auto& entity : entityItr) { @@ -352,112 +361,111 @@ public: } } ImGui::End(); + }; + +private: + fggl::ecs3::World& m_world; + InputManager m_inputs; +}; - // imgui gamepad debug - if ( m_gamepadWindow ) { - auto &gamepads = m_inputs->gamepads; - ImGui::Begin("GamePad", &m_gamepadWindow); - for (int i = 0; i < 16; i++) { - std::string title = gamepads.name(i); - - bool present = gamepads.present(i); - if (ImGui::TreeNode(title.c_str())) { - ImGui::Text("present: %s", present ? "yes" : "no"); - - if (present) { - - if (ImGui::TreeNode("buttons##2")) { - for (auto &btn: fggl::input::GamepadButtonsMicrosoft) { - ImGui::Text("%s: %i %i %i", btn.name, - gamepads.button(i, btn.id), - gamepads.buttonPressed(i, btn.id), - gamepads.buttonReleased(i, btn.id) - ); - } - ImGui::TreePop(); +void gamepadDebug(bool* visible) { + auto inputs = fggl::util::ServiceLocator::instance().providePtr<fggl::input::Input>(); + auto &gamepads = inputs->gamepads; + ImGui::Begin("GamePad", visible); + for (int i = 0; i < 16; i++) { + std::string title = gamepads.name(i); + + bool present = gamepads.present(i); + if (ImGui::TreeNode(title.c_str())) { + ImGui::Text("present: %s", present ? "yes" : "no"); + + if (present) { + + if (ImGui::TreeNode("buttons##2")) { + for (auto &btn: fggl::input::GamepadButtonsMicrosoft) { + ImGui::Text("%s: %i %i %i", btn.name, + gamepads.button(i, btn.id), + gamepads.buttonPressed(i, btn.id), + gamepads.buttonReleased(i, btn.id) + ); } + ImGui::TreePop(); + } - if (ImGui::TreeNode("axes##2")) { - for (auto &axis: fggl::input::GamepadAxes) { - ImGui::Text("%s: %f %f", axis.name, - gamepads.axis(i, axis.id), - gamepads.axisDelta(i, axis.id) - ); + if (ImGui::TreeNode("axes##2")) { + for (auto &axis: fggl::input::GamepadAxes) { + ImGui::Text("%s: %f %f", axis.name, + gamepads.axis(i, axis.id), + gamepads.axisDelta(i, axis.id) + ); - } - ImGui::TreePop(); } - + ImGui::TreePop(); } - ImGui::TreePop(); - ImGui::Separator(); } + ImGui::TreePop(); + ImGui::Separator(); } - ImGui::End(); - } - } -private: - fggl::ecs3::World& m_world; - InputManager m_inputs; - bool m_gamepadWindow = false; -}; + } + ImGui::End(); +} int main(int argc, char* argv[]) { auto& locator = fggl::util::ServiceLocator::instance(); - // setup ECS + // setup ECS Types fggl::ecs3::TypeRegistry types; types.make<fggl::math::Transform>(); fggl::ecs3::ModuleManager modules(types); + // setup ECS fggl::ecs3::World ecs(types); // input management auto inputs = std::make_shared<fggl::input::Input>(); locator.supply<fggl::input::Input>(inputs); - auto glfwModule = modules.load<fggl::gfx::ecsGlfwModule>(inputs); - // window - fggl::gfx::Window win{}; - win.title("FGGL Demo"); - win.fullscreen( true ); + auto glfwModule = modules.load<fggl::gfx::ecsGlfwModule>(inputs); + auto window = glfwModule->createWindow("Demo Game"); + window->fullscreen( true ); // storage API - fggl::data::Storage storage; + auto storage = std::make_shared<fggl::data::Storage>(); + locator.supply<fggl::data::Storage>(storage); //discover( storage.resolvePath(fggl::data::Data, "../../packs") ); // Opengl APIs - auto glModule = modules.load<fggl::gfx::ecsOpenGLModule>(win, storage); - + auto glModule = modules.load<fggl::gfx::ecsOpenGLModule>(window, storage); fggl::gfx::loadPipeline(glModule, "unlit", false); fggl::gfx::loadPipeline(glModule, "phong", false); fggl::gfx::loadPipeline(glModule, "normals", false); // debug layer - fggl::debug::DebugUI debug(win); - debug.visible(true); - - // Create scene manager + std::shared_ptr<fggl::debug::DebugUI> debug = std::make_shared<fggl::debug::DebugUI>(window); + locator.supply<fggl::debug::DebugUI>(debug); + debug->addWindow("gamepad", gamepadDebug); + debug->addWindow("imgui-demo", ImGui::ShowDemoWindow); + debug->addWindow("imgui-about", ImGui::ShowAboutWindow); + debug->addWindow("imgui-help", [](bool* val) { ImGui::ShowUserGuide(); } ); + debug->visible(true); + + // Scene management auto scenes = std::make_shared<fggl::scenes::SceneManager>(); locator.supply<fggl::scenes::SceneManager>(scenes); - scenes->create("main_menu", std::make_shared<MenuScene>(inputs)); scenes->create("game", std::make_shared<GameScene>(ecs, inputs)); - - // activate the main menu scenes->activate("main_menu"); - // create ECS - + // Main game/event loop fggl::util::Timer time{}; time.frequency( glfwGetTimerFrequency() ); time.setup( glfwGetTimerValue() ); - while( !win.closeRequested() ) { + while( !window->closeRequested() ) { // // Setup setup // @@ -465,7 +473,7 @@ int main(int argc, char* argv[]) { inputs->frame( time.delta() ); glfwModule->context.pollEvents(); - debug.frameStart(); + debug->frameStart(); // // update step @@ -473,15 +481,15 @@ int main(int argc, char* argv[]) { scenes->update(); // render the scene - win.activate(); + window->activate(); glModule->ogl.clear(); // allow the scene to do stuff, then actually render scenes->render(); fggl::gfx::renderMeshes(glModule, ecs, time.delta()); - debug.draw(); - win.swap(); + debug->draw(); + window->swap(); } return 0; diff --git a/fggl/debug/debug.cpp b/fggl/debug/debug.cpp index 399fa2410ab879ebff89b24bf21d8af0573812c9..9e825fdb51d01721fd078d31d93328e415b76df1 100644 --- a/fggl/debug/debug.cpp +++ b/fggl/debug/debug.cpp @@ -7,14 +7,14 @@ using fggl::gfx::Window; using fggl::debug::DebugUI; -DebugUI::DebugUI(Window& win) : m_visible(false) { +DebugUI::DebugUI(std::shared_ptr<Window> win) : m_visible(false) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - io.IniFilename = NULL; + io.IniFilename = nullptr; - ImGui_ImplGlfw_InitForOpenGL(win.handle(), true); + ImGui_ImplGlfw_InitForOpenGL(win->handle(), true); ImGui_ImplOpenGL3_Init("#version 130"); } @@ -32,11 +32,13 @@ void DebugUI::frameStart() { } void DebugUI::draw() { + for ( auto& [name, data] : m_windows) { + if ( data.m_visible ) { + data.m_callback( &data.m_visible ); + } + } + ImGui::Render(); if ( m_visible ) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } - -void DebugUI::showDemo() { - ImGui::ShowDemoWindow(); -} diff --git a/fggl/debug/debug.h b/fggl/debug/debug.h index 6b1e162c845544d449454fc1a62e49f8f9a35cb7..cdfb29899cbf4fbe26105febd2b55cf2ce829318 100644 --- a/fggl/debug/debug.h +++ b/fggl/debug/debug.h @@ -1,27 +1,47 @@ #ifndef FGGL_DEBUG_H #define FGGL_DEBUG_H +#include <utility> +#include <functional> +#include <unordered_map> + #include <fggl/gfx/window.hpp> namespace fggl::debug { + using DebugUIDraw = std::function<void(bool*)>; + + struct DebugWindow { + bool m_visible; + DebugUIDraw m_callback; + }; + class DebugUI { public: - DebugUI(gfx::Window& window); + explicit DebugUI(std::shared_ptr<gfx::Window> window); ~DebugUI(); void frameStart(); void draw(); - void showDemo(); + inline void addWindow(const std::string& name, DebugUIDraw window){ + m_windows[name] = DebugWindow{ + .m_visible = true, + .m_callback = std::move(window) + }; + } inline void visible(bool state) { m_visible = state; } + inline bool visible() const { + return m_visible; + } + private: bool m_visible; - + std::unordered_map<std::string, DebugWindow> m_windows; }; } diff --git a/fggl/gfx/compat.hpp b/fggl/gfx/compat.hpp index 089ac569e0becc1d9568e6dfca3ee5dbce60baca..b7933526ed94f0a3f02c74853c989beda24a51df 100644 --- a/fggl/gfx/compat.hpp +++ b/fggl/gfx/compat.hpp @@ -28,6 +28,13 @@ namespace fggl::gfx { ecsGlfwModule(std::shared_ptr<fggl::input::Input> inputs) : context(std::move(inputs) ) { } + inline + std::shared_ptr<Window> createWindow(const std::string& title) { + auto window = std::make_shared<Window>(); + window->title(title); + return window; + } + [[nodiscard]] std::string name() const override { return "gfx::glfw"; diff --git a/fggl/gfx/ogl/backend.cpp b/fggl/gfx/ogl/backend.cpp index 4aa000c669528b8722d81c772e74c08ac32d9326..3a864ade4bab0200eefb2f9a8b660eaaaa0eb4f2 100644 --- a/fggl/gfx/ogl/backend.cpp +++ b/fggl/gfx/ogl/backend.cpp @@ -4,9 +4,9 @@ using namespace fggl::gfx; -GlGraphics::GlGraphics(Window& window) : m_window(window) { +GlGraphics::GlGraphics(const std::shared_ptr<Window> window) : m_window(window) { std::cerr << "[OGL] attaching window context" << std::endl; - window.activate(); + window->activate(); GLenum err = glewInit(); if ( GLEW_OK != err ) { throw std::runtime_error("couldn't init glew"); @@ -21,7 +21,7 @@ GlGraphics::~GlGraphics() { } void GlGraphics::clear() { - m_window.activate(); + m_window->activate(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); diff --git a/fggl/gfx/ogl/backend.hpp b/fggl/gfx/ogl/backend.hpp index 13075a1b78d1cf84c6ce03400638b1bca5fe4d55..96b863e0d410f1505d0e87249fc0f4f0bf8bf45b 100644 --- a/fggl/gfx/ogl/backend.hpp +++ b/fggl/gfx/ogl/backend.hpp @@ -14,13 +14,13 @@ namespace fggl::gfx { class GlGraphics { public: - GlGraphics(Window& window); + GlGraphics(const std::shared_ptr<Window> window); ~GlGraphics(); void clear(); private: - Window& m_window; + std::shared_ptr<Window> m_window; }; class Shader { diff --git a/fggl/gfx/ogl/compat.hpp b/fggl/gfx/ogl/compat.hpp index fd761c62bf38044fc31ab4b82c22ca4780694405..a29b7357072a368300861c7ad964d927405e525d 100644 --- a/fggl/gfx/ogl/compat.hpp +++ b/fggl/gfx/ogl/compat.hpp @@ -18,6 +18,7 @@ #include <fggl/gfx/common.hpp> #include <fggl/gfx/camera.hpp> #include <fggl/ecs/ecs.hpp> +#include <utility> namespace fggl::gfx { @@ -29,8 +30,8 @@ namespace fggl::gfx { fggl::gfx::MeshRenderer renderer; fggl::gfx::ShaderCache cache; - ecsOpenGLModule(Window& window, fggl::data::Storage& storage) : - ogl(window), renderer(), cache(storage) { } + ecsOpenGLModule(std::shared_ptr<Window> window, std::shared_ptr<fggl::data::Storage> storage) : + ogl(std::move(window)), renderer(), cache(std::move(storage)) { } std::string name() const override { return "gfx::opengl"; diff --git a/fggl/gfx/ogl/shader.cpp b/fggl/gfx/ogl/shader.cpp index c3558de127c555dd03b1a231b3cb83d6abcc65cb..d9c0da50d4373e5e724d270d6ef32d2055765606 100644 --- a/fggl/gfx/ogl/shader.cpp +++ b/fggl/gfx/ogl/shader.cpp @@ -8,7 +8,7 @@ using namespace fggl::gfx; bool ShaderCache::compileShader(const std::string& fname, GLuint sid) { std::string source; - bool result = m_storage.load(fggl::data::Data, fname, &source); + bool result = m_storage->load(fggl::data::Data, fname, &source); if ( !result ) { std::cerr << ">> Error loading file: " << fname << std::endl; return false; @@ -40,7 +40,7 @@ bool ShaderCache::compileShader(const std::string& fname, GLuint sid) { return true; } -ShaderCache::ShaderCache(fggl::data::Storage& storage) : m_storage(storage), m_shaders(), m_binary(true) { +ShaderCache::ShaderCache(std::shared_ptr<fggl::data::Storage> storage) : m_storage(storage), m_shaders(), m_binary(true) { if ( !GLEW_ARB_get_program_binary ) { std::cerr << "shader caching disabled, no card support" << std::endl; @@ -53,7 +53,7 @@ bool ShaderCache::loadFromDisk(GLuint pid, const ShaderConfig& config) { BinaryCache cache; auto fname = "shader_" + config.name + ".bin"; - bool status = m_storage.load( fggl::data::Cache, fname, &cache ); + bool status = m_storage->load( fggl::data::Cache, fname, &cache ); if ( !status ) { std::cerr << "loading shader from disk failed" << std::endl; @@ -71,7 +71,7 @@ void ShaderCache::saveToDisk(GLuint pid, const ShaderConfig& config) { cacheSave(pid, &cache); auto fname = "shader_" + config.name + ".bin"; - m_storage.save( fggl::data::Cache, fname, &cache); + m_storage->save( fggl::data::Cache, fname, &cache); } GLuint ShaderCache::getOrLoad(const ShaderConfig& config) { diff --git a/fggl/gfx/ogl/shader.hpp b/fggl/gfx/ogl/shader.hpp index 4e06dbd41399b6d79ac4ba1b2e3820f2acd07675..b7e0d48bb1a6b70e25323e3bb95aed323451362f 100644 --- a/fggl/gfx/ogl/shader.hpp +++ b/fggl/gfx/ogl/shader.hpp @@ -30,7 +30,7 @@ namespace fggl::gfx { class ShaderCache { public: - ShaderCache(fggl::data::Storage& storage); + ShaderCache(std::shared_ptr<fggl::data::Storage> storage); ~ShaderCache() = default; GLuint load(const ShaderConfig& config); @@ -39,7 +39,7 @@ namespace fggl::gfx { GLuint get(const std::string& name); private: - fggl::data::Storage& m_storage; + std::shared_ptr<fggl::data::Storage> m_storage; std::unordered_map<std::string, GLuint> m_shaders; // opengl operations