diff --git a/demo/main.cpp b/demo/main.cpp index f17d9fe2fffa7cfd8d9c1afb6b21312349590275..9bc3aaee0d188f0b4c9375e2aac4928edcc4e270 100644 --- a/demo/main.cpp +++ b/demo/main.cpp @@ -13,6 +13,7 @@ #include "fggl/gfx/ogl/renderer.hpp" #include "fggl/gfx/ogl/compat.hpp" #include "fggl/gfx/compat.hpp" +#include "fggl/gui/containers.hpp" #include <fggl/data/heightmap.h> #include <fggl/data/procedural.hpp> @@ -124,6 +125,8 @@ public: } void setup() { + m_canvas.size( fggl::math::vec2(0,0), fggl::math::vec2(100, 100)); + auto types = m_world->types(); // create camera using strings @@ -250,14 +253,21 @@ public: } } - void render(fggl::gfx::Paint& paint) override { - //debugInspector(); - //fggl::gfx::renderMeshes(glModule, *m_world, m_sceneTime->delta()); - } + void render(fggl::gfx::Graphics& gfx) override { + // render the 3D scene + if ( m_world != nullptr ) { + gfx.drawScene( *m_world ); + } - fggl::ecs3::World* world() override { - return m_world.get(); - } + const fggl::math::vec2 panelSize { 250.0F, 250.0F }; + const auto canvasY = gfx.canvasBounds().bottom - panelSize.y; + m_canvas.size( {0.0F, canvasY}, panelSize); + + // now the 2D scene + fggl::gfx::Paint paint; + m_canvas.render(paint); + gfx.draw2D(paint); + } // entity inspector void debugInspector() { @@ -283,6 +293,7 @@ private: std::unique_ptr<fggl::ecs3::World> m_world; std::unique_ptr<fggl::util::Timer> m_sceneTime; InputManager m_inputs; + fggl::gui::Panel m_canvas; }; void gamepadDebug(bool* visible) { diff --git a/fggl/app.cpp b/fggl/app.cpp index 5ca623b73d3db732cd8d9d3a6938916b83193989..134999398f2d15ea0c230c4a6ebefc43d670fe3e 100644 --- a/fggl/app.cpp +++ b/fggl/app.cpp @@ -41,17 +41,9 @@ namespace fggl { m_window->frameStart(); // get draw instructions - fggl::gfx::Paint paint; - state.render(paint); + auto& graphics = m_window->graphics(); + state.render(graphics); - // execute draw instructions - auto& graphics = m_window->graphics(); - graphics.draw2D( paint ); - - ecs3::World* world = state.world(); - if ( world != nullptr ) { - graphics.drawScene(*world); - } m_window->frameEnd(); m_modules->onFrameEnd(); diff --git a/fggl/gfx/ogl4/canvas.cpp b/fggl/gfx/ogl4/canvas.cpp index 729dbfedfa3fd31be0af0a528db0476d077b5c79..c106c02e1d7e34b78b562ba185c9c3c1df2c9347 100644 --- a/fggl/gfx/ogl4/canvas.cpp +++ b/fggl/gfx/ogl4/canvas.cpp @@ -29,6 +29,7 @@ #include "fggl/util/service.h" #include "fggl/gui/fonts.hpp" +#include "fggl/gfx/windowing.hpp" #define FGGL_OPENGL_CORRECTNESS @@ -90,7 +91,9 @@ namespace fggl::gfx::ogl4 { } } - CanvasRenderer::CanvasRenderer() : m_fontTex(ogl::TextureType::Tex2D) { + CanvasRenderer::CanvasRenderer() : + m_bounds({0.0F, 1920.F, 1080.0F, 0.0F}), + m_fontTex(ogl::TextureType::Tex2D) { m_vao.bind(); #ifdef FGGL_GL_I_BOUND @@ -133,10 +136,12 @@ namespace fggl::gfx::ogl4 { m_indexList.replace(mesh.indexList.size(), mesh.indexList.data()); // draw + glDisable( GL_DEPTH_TEST ); + glDisable( GL_CULL_FACE ); // FIXME: this should be abstracted into the shader class glUseProgram( shader ); - auto projMat = glm::ortho(0.0f, 1920.0f, 1080.0f, 0.f); + auto projMat = glm::ortho(m_bounds.left, m_bounds.right, m_bounds.bottom, m_bounds.top); glUniformMatrix4fv(glGetUniformLocation( shader, "projection"), 1, GL_FALSE, glm::value_ptr(projMat)); @@ -150,6 +155,7 @@ namespace fggl::gfx::ogl4 { return; } + // get the expected font auto fontFactory = util::ServiceLocator::instance().get<gui::FontLibrary>(); std::shared_ptr<gui::FontFace> face = fontFactory->getFont("LiberationSans-Regular.ttf"); @@ -167,8 +173,12 @@ namespace fggl::gfx::ogl4 { // bind the vbo we'll use for writing m_vao.bind(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // setup the openGL state we expect for rendering + glDisable( GL_DEPTH_TEST ); + glDisable( GL_CULL_FACE ); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // for each text string, attempt to render it for ( const auto& textCmd : paint.textCmds() ) { @@ -219,6 +229,7 @@ namespace fggl::gfx::ogl4 { } glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); } /* diff --git a/fggl/gui/containers.cpp b/fggl/gui/containers.cpp index ed36f1ad1c7b7cb03ac34fcc4485358af53282f2..60056ec60d76bf95cf2837aab47e6ed27d419e99 100644 --- a/fggl/gui/containers.cpp +++ b/fggl/gui/containers.cpp @@ -1,4 +1,5 @@ #include <fggl/gui/containers.hpp> +#include <spdlog/spdlog.h> namespace fggl::gui { @@ -52,4 +53,16 @@ namespace fggl::gui { setSize(biggestCross, lineSum); }*/ + void Panel::render(gfx::Paint &paint) { + spdlog::info("Imma render mah panel! {}, {}", bottomRight().x, bottomRight().y ); + + // background painting time + gfx::Path2D background(topLeft()); + background.colour(math::vec3(1.0F, 1.0F, 0.0F)); + draw_box(background, topLeft(), bottomRight()); + paint.fill(background); + + // call parent's render method for child objects + Container::render(paint); + } }; diff --git a/fggl/gui/widget.cpp b/fggl/gui/widget.cpp index 837a42c63683ad88fea86e5eddb72619844dd90c..9aa8fe8de9969988aeaf819abefd9336c76795d3 100644 --- a/fggl/gui/widget.cpp +++ b/fggl/gui/widget.cpp @@ -26,7 +26,7 @@ namespace fggl::gui { path.pathTo( { innerTop.x, innerTop.y } ); } - void makeBox( gfx::Path2D& path, glm::vec2 topLeft, glm::vec2 bottomRight ) { + void draw_box( gfx::Path2D& path, glm::vec2 topLeft, glm::vec2 bottomRight ) { path.moveTo( { topLeft.x, topLeft.y } ); path.pathTo( { bottomRight.x, topLeft.y } ); path.pathTo( { bottomRight.x, bottomRight.y } ); @@ -39,7 +39,7 @@ namespace fggl::gui { // background path.colour( {0.5f, 0.5f, 0.5f} ); - makeBox( path, topLeft, bottomRight ); + draw_box( path, topLeft, bottomRight ); // fill math::vec2 innerTop { topLeft.x + 5, topLeft.y + 5 }; @@ -52,14 +52,13 @@ namespace fggl::gui { // draw the bar path.colour( {0.8f, 0.0f, 0.0f} ); - makeBox( path, innerTop, innerBottom ); + draw_box( path, innerTop, innerBottom ); // part of the bar that's not filled in math::vec2 emptyTop { innerBottom.x, innerTop.y }; math::vec2 emptyBottom { trueBottom, innerBottom.y }; path.colour( {0.4f, 0.0f, 0.0f} ); - makeBox( path, emptyTop, emptyBottom ); - + draw_box( path, emptyTop, emptyBottom ); } void draw_slider( gfx::Path2D& path, glm::vec2 topLeft, glm::vec2 size, float value ) { @@ -78,7 +77,7 @@ namespace fggl::gui { math::vec2 selectorTop { innerTop.x + selectorValue - ( selectorWidth/2), topLeft.y }; math::vec2 selectorBottom { selectorTop.x + selectorWidth, bottomRight.y }; path.colour( {1.0f, 1.0f, 1.0f} ); - makeBox( path, selectorTop, selectorBottom ); + draw_box( path, selectorTop, selectorBottom ); } void draw_button( gfx::Path2D& path, glm::vec2 pos, glm::vec2 size, bool active, bool pressed) { @@ -141,6 +140,6 @@ namespace fggl::gui { // inner box path.colour( baseColour ); - makeBox( path, innerTop, innerBottom ); + draw_box( path, innerTop, innerBottom ); } } \ No newline at end of file diff --git a/fggl/scenes/menu.cpp b/fggl/scenes/menu.cpp index c1629e2932e0f0fdf84c867aa228aa53830c23fa..712056f42e05963d0c738d1c758f48aa5b16c16a 100644 --- a/fggl/scenes/menu.cpp +++ b/fggl/scenes/menu.cpp @@ -54,8 +54,11 @@ namespace fggl::scenes { } } - void BasicMenu::render(gfx::Paint& paint) { + void BasicMenu::render(gfx::Graphics& gfx) { + // render the 2D scene (we don't have a 3D scene to worry about in menus) + gfx::Paint paint; m_canvas.render( paint ); + gfx.draw2D(paint); } void BasicMenu::activate() { diff --git a/include/fggl/app.hpp b/include/fggl/app.hpp index a73989c137bc70e0a103cc204650ffe881731e8e..a83dece63bbebdb70e63806b02b22c547dd0b834 100644 --- a/include/fggl/app.hpp +++ b/include/fggl/app.hpp @@ -76,16 +76,12 @@ namespace fggl { * It is not safe to assume the render target will always be the same, as the scene may be * rendered in mutliple passes (eg, for VR requirements). */ - virtual void render(gfx::Paint &paint) = 0; + virtual void render(gfx::Graphics &paint) = 0; virtual void activate() {} virtual void deactivate() {} - inline virtual ecs3::World* world() { - return nullptr; - } - protected: App &m_owner; }; diff --git a/include/fggl/gfx/ogl/renderer.hpp b/include/fggl/gfx/ogl/renderer.hpp index a07cbaba16a59fe0e07f11103fed8af9f1cba288..97f621f0d3a05371ac92a471b3dce84acbaf0eec 100644 --- a/include/fggl/gfx/ogl/renderer.hpp +++ b/include/fggl/gfx/ogl/renderer.hpp @@ -59,6 +59,10 @@ namespace fggl::gfx { void draw2D(const Paint &paint) override; void drawScene(ecs3::World& world) override; + inline Bounds canvasBounds() override { + return m_canvasRenderer->bounds(); + } + private: std::unique_ptr<ogl4::StaticModelRenderer> m_modelRenderer; std::unique_ptr<ogl4::CanvasRenderer> m_canvasRenderer; diff --git a/include/fggl/gfx/ogl4/canvas.hpp b/include/fggl/gfx/ogl4/canvas.hpp index 6c90bff32cf512d8a33983bdbfe3a495c1527ac1..849d1af7e3fb9fab772bdbc7e7eac6edc850d1cd 100644 --- a/include/fggl/gfx/ogl4/canvas.hpp +++ b/include/fggl/gfx/ogl4/canvas.hpp @@ -7,6 +7,7 @@ #include "fggl/gfx/paint.hpp" #include "fggl/gfx/ogl/types.hpp" +#include "fggl/gfx/windowing.hpp" #include "fggl/gui/fonts.hpp" @@ -17,11 +18,15 @@ namespace fggl::gfx::ogl4 { CanvasRenderer(); void render(GLuint shader, const gfx::Paint& paint); + inline gfx::Bounds bounds() const { + return m_bounds; + } + private: + gfx::Bounds m_bounds; ogl::VertexArray m_vao; ogl::ArrayBuffer m_vertexList; ogl::ElementBuffer m_indexList; - gui::FontLibrary m_fonts; ogl::Texture m_fontTex; diff --git a/include/fggl/gfx/windowing.hpp b/include/fggl/gfx/windowing.hpp index 45866bc46edb4e8b867d9fbfe35e59cc1b6a7524..4a22fb5362d77469addd2929c23f6414718ac311 100644 --- a/include/fggl/gfx/windowing.hpp +++ b/include/fggl/gfx/windowing.hpp @@ -8,13 +8,22 @@ namespace fggl::gfx { + struct Bounds { + float top; + float right; + float bottom; + float left; + }; + class Graphics { public: virtual ~Graphics() = default; virtual void clear() = 0; virtual void resize(int width, int height) = 0; + virtual Bounds canvasBounds() = 0; virtual void draw2D(const Paint &paint) = 0; + virtual void drawScene(ecs3::World&) = 0; }; diff --git a/include/fggl/gui/containers.hpp b/include/fggl/gui/containers.hpp index d27d59d8a8678ad2e64de0c1f028535b7efc1375..676a60b20467deb3a021cc980f01edc318a71adc 100644 --- a/include/fggl/gui/containers.hpp +++ b/include/fggl/gui/containers.hpp @@ -28,6 +28,15 @@ namespace fggl::gui { std::vector<std::unique_ptr<Widget>> m_children; }; + class Panel : public Container { + public: + Panel() = default; + ~Panel() = default; + + void render(gfx::Paint& paint) override; + + }; + enum class LayoutAxis { LINE_AXIS, PAGE_AXIS diff --git a/include/fggl/gui/widget.hpp b/include/fggl/gui/widget.hpp index e74e496f11eda4b429f146e36af84b8d74b44cf3..f740bf1db71c38770819e7aba2831ab4cb3ac812 100644 --- a/include/fggl/gui/widget.hpp +++ b/include/fggl/gui/widget.hpp @@ -36,15 +36,20 @@ namespace fggl::gui { virtual ~Widget() = default; - inline math::vec2 topLeft() { + inline math::vec2 topLeft() const { return m_bounds.topLeft; }; - inline math::vec2 bottomRight() { + inline math::vec2 bottomRight() const { return m_bounds.topLeft + m_bounds.size; } - inline math::vec2 size() { + inline void size(math::vec2 pos, math::vec2 size) { + m_bounds.topLeft = pos; + m_bounds.size = size; + } + + inline math::vec2 size() const { return m_bounds.size; } diff --git a/include/fggl/scenes/menu.hpp b/include/fggl/scenes/menu.hpp index b7ce39d7bea349ad187af294cc6378eab9b7959f..3e1b977b4ef8cf542c3e8fa2d8c25b75811af42d 100644 --- a/include/fggl/scenes/menu.hpp +++ b/include/fggl/scenes/menu.hpp @@ -19,7 +19,7 @@ namespace fggl::scenes { explicit BasicMenu(App &owner); void update() override; - void render(gfx::Paint &paint) override; + void render(gfx::Graphics &paint) override; void activate() override; void deactivate() override;