]> git.localhorst.tv Git - blobs.git/commitdiff
basic info box
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 19 Nov 2017 20:56:30 +0000 (21:56 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 19 Nov 2017 20:56:30 +0000 (21:56 +0100)
well, not much info in there, but at least the guy has a name now

21 files changed:
src/app/Assets.hpp
src/app/MasterState.hpp
src/app/app.cpp
src/app/states.cpp
src/blobs.cpp
src/graphics/AlphaSprite.hpp [new file with mode: 0644]
src/graphics/CreatureSkin.hpp
src/graphics/Font.hpp
src/graphics/PlainColor.hpp [new file with mode: 0644]
src/graphics/PlanetSurface.hpp
src/graphics/SimpleVAO.hpp
src/graphics/SunSurface.hpp
src/graphics/Texture.hpp
src/graphics/Viewport.hpp
src/graphics/render.cpp
src/graphics/shader.cpp
src/graphics/viewport.cpp
src/ui/CreaturePanel.hpp [new file with mode: 0644]
src/ui/Label.hpp [new file with mode: 0644]
src/ui/align.hpp [new file with mode: 0644]
src/ui/ui.cpp [new file with mode: 0644]

index 3cfc1334371f7e2e491d3053113c6c0dd672a396..d4ab683f8d8bacb8df9be2dd0ba5ce28172dba37 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef BLOBS_APP_ASSETS_HPP_
 #define BLOBS_APP_ASSETS_HPP_
 
+#include "../graphics/AlphaSprite.hpp"
 #include "../graphics/ArrayTexture.hpp"
 #include "../graphics/CreatureSkin.hpp"
+#include "../graphics/Font.hpp"
+#include "../graphics/PlainColor.hpp"
 #include "../graphics/PlanetSurface.hpp"
 #include "../graphics/SunSurface.hpp"
 #include "../world/Resource.hpp"
@@ -22,6 +25,7 @@ struct Assets {
 
        std::string path;
        std::string data_path;
+       std::string font_path;
        std::string skin_path;
        std::string tile_path;
 
@@ -30,12 +34,20 @@ struct Assets {
                world::Set<world::TileType> tiles;
        } data;
 
+       struct {
+               graphics::Font large;
+               graphics::Font medium;
+               graphics::Font small;
+       } fonts;
+
        struct {
                graphics::ArrayTexture tiles;
                graphics::ArrayTexture skins;
        } textures;
 
        struct {
+               graphics::AlphaSprite alpha_sprite;
+               graphics::PlainColor plain_color;
                graphics::PlanetSurface planet_surface;
                graphics::SunSurface sun_surface;
                graphics::CreatureSkin creature_skin;
index d2072ee326c27a30683a18558ff2d6c3de7194d1..959af6269c7cfd805f854f108ec67cf1c6a00e1a 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "Assets.hpp"
 #include "../graphics/Camera.hpp"
+#include "../ui/CreaturePanel.hpp"
 
 
 namespace blobs {
@@ -31,6 +32,9 @@ public:
        graphics::Camera &GetCamera() noexcept { return cam; }
        const graphics::Camera &GetCamera() const noexcept { return cam; }
 
+       ui::CreaturePanel &GetCreaturePanel() noexcept { return cp; }
+       const ui::CreaturePanel &GetCreaturePanel() const noexcept { return cp; }
+
 private:
        void OnResize(int w, int h) override;
 
@@ -47,6 +51,7 @@ private:
        world::Simulation &sim;
 
        graphics::Camera cam;
+       ui::CreaturePanel cp;
 
        int remain;
        int thirds;
index b3ae4780ec6c5147a315d227fb11aa66e0b89d5c..0ec22b02c16607d189cda86107140d14ccde643f 100644 (file)
@@ -173,8 +173,14 @@ void State::OnQuit() {
 Assets::Assets()
 : path("assets/")
 , data_path(path + "data/")
+, font_path(path + "fonts/")
 , skin_path(path + "skins/")
-, tile_path(path + "tiles/") {
+, tile_path(path + "tiles/")
+, fonts{
+       graphics::Font(font_path + "DejaVuSans.ttf", 32),
+       graphics::Font(font_path + "DejaVuSans.ttf", 24),
+       graphics::Font(font_path + "DejaVuSans.ttf", 16)
+} {
        {
                std::ifstream resource_file(data_path + "resources");
                io::TokenStreamReader resource_reader(resource_file);
@@ -187,6 +193,7 @@ Assets::Assets()
                ReadTileTypes(tile_reader);
        }
 
+
        graphics::Format format;
        textures.tiles.Bind();
        textures.tiles.Reserve(256, 256, 14, format);
index d344e875ae413824e22ba71b9812a536b0dc89db..862d4184e60238331aa36e3ffd6dae2cf791c0c4 100644 (file)
@@ -1,6 +1,7 @@
 #include "MasterState.hpp"
 
 #include "../creature/Creature.hpp"
+#include "../graphics/Viewport.hpp"
 #include "../world/Body.hpp"
 #include "../world/Planet.hpp"
 #include "../world/Simulation.hpp"
@@ -17,6 +18,7 @@ MasterState::MasterState(Assets &assets, world::Simulation &sim) noexcept
 , assets(assets)
 , sim(sim)
 , cam(sim.Root())
+, cp(assets)
 , remain(0)
 , thirds(0)
 , paused(false) {
@@ -27,7 +29,18 @@ MasterState::~MasterState() noexcept {
 
 
 void MasterState::OnResize(int w, int h) {
+       assets.shaders.plain_color.Activate();
+       assets.shaders.plain_color.SetVP(glm::mat4(1.0f), glm::ortho(0.0f, float(w), float(h), 0.0f, 1.0e4f, -1.0e4f));
+       assets.shaders.alpha_sprite.Activate();
+       assets.shaders.alpha_sprite.SetVP(glm::mat4(1.0f), glm::ortho(0.0f, float(w), float(h), 0.0f, 1.0e4f, -1.0e4f));
+
        cam.Aspect(float(w), float(h));
+       assets.shaders.planet_surface.Activate();
+       assets.shaders.planet_surface.SetVP(cam.View(), cam.Projection());
+       assets.shaders.sun_surface.Activate();
+       assets.shaders.sun_surface.SetVP(cam.View(), cam.Projection());
+       assets.shaders.creature_skin.Activate();
+       assets.shaders.creature_skin.SetVP(cam.View(), cam.Projection());
 }
 
 void MasterState::OnUpdate(int dt) {
@@ -57,7 +70,6 @@ void MasterState::OnKeyDown(const SDL_KeyboardEvent &e) {
 }
 
 void MasterState::OnRender(graphics::Viewport &viewport) {
-
        int num_lights = 0;
        for (auto sun : sim.Suns()) {
                // TODO: source sun's light color and strength
@@ -95,16 +107,15 @@ void MasterState::OnRender(graphics::Viewport &viewport) {
        assets.shaders.planet_surface.Activate();
        assets.shaders.planet_surface.SetTexture(assets.textures.tiles);
        for (auto planet : sim.Planets()) {
-               assets.shaders.planet_surface.SetMVP(cam.Model(*planet), cam.View(), cam.Projection());
+               assets.shaders.planet_surface.SetM(cam.Model(*planet));
                planet->Draw(assets, viewport);
        }
 
        assets.shaders.sun_surface.Activate();
        for (auto sun : sim.Suns()) {
                double sun_radius = sun->Radius();
-               assets.shaders.sun_surface.SetMVP(
-                       cam.Model(*sun) * glm::scale(glm::vec3(sun_radius, sun_radius, sun_radius)),
-                       cam.View(), cam.Projection());
+               assets.shaders.sun_surface.SetM(
+                       cam.Model(*sun) * glm::scale(glm::vec3(sun_radius, sun_radius, sun_radius)));
                assets.shaders.sun_surface.SetLight(glm::vec3(1.0f, 1.0f, 1.0f), 1.0e6f);
                assets.shaders.sun_surface.Draw();
        }
@@ -113,9 +124,12 @@ void MasterState::OnRender(graphics::Viewport &viewport) {
        assets.shaders.creature_skin.SetTexture(assets.textures.skins);
        // TODO: extend to nearby bodies as well
        for (auto c : cam.Reference().Creatures()) {
-               assets.shaders.creature_skin.SetMVP(cam.Model(c->GetBody()) * glm::mat4(c->LocalTransform()), cam.View(), cam.Projection());
+               assets.shaders.creature_skin.SetM(cam.Model(c->GetBody()) * glm::mat4(c->LocalTransform()));
                c->Draw(assets, viewport);
        }
+
+       viewport.ClearDepth();
+       cp.Draw(assets, viewport);
 }
 
 }
index 49813d585ce04c90c051b97fec5a6c104afe93f3..56475029097c8f061ca5ec971d994aac68674200 100644 (file)
@@ -68,8 +68,9 @@ int main(int argc, char *argv[]) {
        std::cout << "moon cycles per year: " << (planet.OrbitalPeriod() / moon.OrbitalPeriod()) << std::endl;
 
        auto blob = new creature::Creature;
-       blob->BuildVAO();
        Spawn(*blob, planet, assets);
+       blob->BuildVAO();
+       blob->Name("Blob");
 
        app::MasterState state(assets, sim);
        state.GetCamera()
@@ -88,6 +89,7 @@ int main(int argc, char *argv[]) {
        //      .Reference(sun)
        //      .Orbital(glm::vec3(-500.0f, 500.0f, 500.0f))
        //;
+       state.GetCreaturePanel().Show(*blob);
 
        app::Application app(init.window, init.viewport);
        app.PushState(&state);
diff --git a/src/graphics/AlphaSprite.hpp b/src/graphics/AlphaSprite.hpp
new file mode 100644 (file)
index 0000000..3cc6a83
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef BLOBS_GRAPHICS_ALPHASPRITE_HPP_
+#define BLOBS_GRAPHICS_ALPHASPRITE_HPP_
+
+#include "Program.hpp"
+#include "SimpleVAO.hpp"
+
+#include "glm.hpp"
+
+#include <cstdint>
+
+
+namespace blobs {
+namespace graphics {
+
+class Texture;
+
+class AlphaSprite {
+
+public:
+       AlphaSprite();
+       ~AlphaSprite();
+
+       AlphaSprite(const AlphaSprite &) = delete;
+       AlphaSprite &operator =(const AlphaSprite &) = delete;
+
+       AlphaSprite(AlphaSprite &&) = delete;
+       AlphaSprite &operator =(AlphaSprite &&) = delete;
+
+public:
+       void Activate() noexcept;
+
+       void SetM(const glm::mat4 &m) noexcept;
+       void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
+       void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
+       void SetTexture(Texture &) noexcept;
+       void SetFgColor(const glm::vec4 &) noexcept;
+       void SetBgColor(const glm::vec4 &) noexcept;
+
+       const glm::mat4 &M() const noexcept { return m; }
+       const glm::mat4 &V() const noexcept { return v; }
+       const glm::mat4 &P() const noexcept { return p; }
+       const glm::mat4 &MV() const noexcept { return mv; }
+       const glm::mat4 &MVP() const noexcept { return mvp; }
+
+       void DrawRect() const noexcept;
+
+private:
+       struct Attributes {
+               glm::vec3 position;
+               glm::vec2 texture;
+       };
+       SimpleVAO<Attributes, std::uint8_t> vao;
+       Program prog;
+
+       glm::mat4 m;
+       glm::mat4 v;
+       glm::mat4 p;
+       glm::mat4 mv;
+       glm::mat4 mvp;
+
+       GLuint m_handle;
+       GLuint mv_handle;
+       GLuint mvp_handle;
+
+       GLuint sampler_handle;
+       GLuint fg_color_handle;
+       GLuint bg_color_handle;
+
+};
+
+}
+}
+
+#endif
index 78cf658d3c48e8b3e4b7885bddc1732ffcae9292..0d83563b2e4f35c8575389fdeadf6b6c2509a7cf 100644 (file)
@@ -29,6 +29,8 @@ public:
 public:
        void Activate() noexcept;
 
+       void SetM(const glm::mat4 &m) noexcept;
+       void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetTexture(ArrayTexture &) noexcept;
        void SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept;
index ce9cfd9248cbe4c03a56e3428c67d6dc4817f568..6088d95b70a96f609899596ff2a8d6e84e5dd9cc 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "glm.hpp"
 
+#include <string>
 #include <SDL_ttf.h>
 
 
@@ -29,6 +30,7 @@ public:
        };
 
 public:
+       Font(const std::string &src, int size, long index = 0);
        Font(const char *src, int size, long index = 0);
        ~Font();
 
@@ -60,9 +62,12 @@ public:
        bool HasGlyph(Uint16) const noexcept;
 
        glm::ivec2 TextSize(const char *) const;
+       glm::ivec2 TextSize(const std::string &) const;
 
        Texture Render(const char *) const;
+       Texture Render(const std::string &) const;
        void Render(const char *, Texture &) const;
+       void Render(const std::string &, Texture &) const;
 
 private:
        TTF_Font *handle;
diff --git a/src/graphics/PlainColor.hpp b/src/graphics/PlainColor.hpp
new file mode 100644 (file)
index 0000000..660ca93
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef BLOBS_GRAPHICS_PLAINCOLOR_HPP_
+#define BLOBS_GRAPHICS_PLAINCOLOR_HPP_
+
+#include "Program.hpp"
+#include "SimpleVAO.hpp"
+
+#include "glm.hpp"
+
+#include <cstdint>
+
+
+namespace blobs {
+namespace graphics {
+
+class PlainColor {
+
+public:
+       PlainColor();
+       ~PlainColor();
+
+       PlainColor(const PlainColor &) = delete;
+       PlainColor &operator =(const PlainColor &) = delete;
+
+       PlainColor(PlainColor &&) = delete;
+       PlainColor &operator =(PlainColor &&) = delete;
+
+public:
+       void Activate() noexcept;
+
+       void SetM(const glm::mat4 &m) noexcept;
+       void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
+       void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
+       void SetColor(const glm::vec3 &color) noexcept;
+
+       const glm::mat4 &M() const noexcept { return m; }
+       const glm::mat4 &V() const noexcept { return v; }
+       const glm::mat4 &P() const noexcept { return p; }
+       const glm::mat4 &MV() const noexcept { return mv; }
+       const glm::mat4 &MVP() const noexcept { return mvp; }
+
+       void DrawRect() const noexcept;
+       void OutlineRect() const noexcept;
+
+private:
+       struct Attributes {
+               glm::vec3 position;
+       };
+       SimpleVAO<Attributes, std::uint8_t> vao;
+       Program prog;
+
+       glm::mat4 m;
+       glm::mat4 v;
+       glm::mat4 p;
+       glm::mat4 mv;
+       glm::mat4 mvp;
+
+       GLuint m_handle;
+       GLuint mv_handle;
+       GLuint mvp_handle;
+
+       GLuint fg_color_handle;
+
+};
+
+}
+}
+
+#endif
index 8e98875851d70c0d859b0386aaae604396bab070..178fcabac98123ad6914a8e01b45e9079f3cac4b 100644 (file)
@@ -29,6 +29,8 @@ public:
 public:
        void Activate() noexcept;
 
+       void SetM(const glm::mat4 &m) noexcept;
+       void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetNormal(const glm::vec3 &) noexcept;
        void SetTexture(ArrayTexture &) noexcept;
index 963c0157ae3e608c59023eaa636fce1c088fa363..c809f7fb72ff4b1863f295d5191037abaa3865cc 100644 (file)
@@ -72,8 +72,17 @@ public:
        MappedBuffer<Element> MapElements(GLenum access) {
                return MappedBuffer<Element>(GL_ELEMENT_ARRAY_BUFFER, access);
        }
+       void Draw(GLenum mode, std::size_t size, std::size_t offset = 0) const noexcept {
+               glDrawElements(mode, size, gl_traits<Element>::type, ((Element *) nullptr) + offset);
+       }
        void DrawTriangles(std::size_t size, std::size_t offset = 0) const noexcept {
-               glDrawElements(GL_TRIANGLES, size, gl_traits<Element>::type, ((Element *) nullptr) + offset);
+               Draw(GL_TRIANGLES, size, offset);
+       }
+       void DrawTriangleStrip(std::size_t size, std::size_t offset = 0) const noexcept {
+               Draw(GL_TRIANGLE_STRIP, size, offset);
+       }
+       void DrawLineLoop(std::size_t size, std::size_t offset = 0) const noexcept {
+               Draw(GL_LINE_LOOP, size, offset);
        }
 
 private:
index 5ce91b12cdf11f123605c0582842d2becad4620e..b5a056be3fe14dec0e69be7bc03d02ccbe207477 100644 (file)
@@ -29,6 +29,8 @@ public:
 public:
        void Activate() noexcept;
 
+       void SetM(const glm::mat4 &m) noexcept;
+       void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetLight(const glm::vec3 &color, float strength) noexcept;
 
index 6ad7eb995448287efadd4a258efa3cb01a8e2ed5..107d259b81d595e83a82e64385a478ee497612d0 100644 (file)
@@ -29,6 +29,7 @@ public:
 public:
        GLsizei Width() const noexcept { return width; }
        GLsizei Height() const noexcept { return height; }
+       glm::vec2 Size() const noexcept { return glm::vec2(width, height); }
 
        void Data(const SDL_Surface &, bool pad2 = true) noexcept;
        void Data(GLsizei w, GLsizei h, const Format &, GLvoid *data) noexcept;
index 78178a620655df08b714c8fa1b8c09c3cd7e4fa5..eab642bae94ff76cf4facadb4e7d4a13c16c0b42 100644 (file)
@@ -27,6 +27,7 @@ public:
        void Resize(int w, int h);
 
        void Clear();
+       void ClearDepth();
 
 private:
        int width;
index 5a0e492cd1d0343ba915fefba30bd957c1d7ff74..96bcb12bf7cde601f972c82072aa87d9042c3ffe 100644 (file)
 namespace blobs {
 namespace graphics {
 
+Font::Font(const std::string &src, int size, long index)
+: Font(src.c_str(), size, index) {
+}
+
 Font::Font(const char *src, int size, long index)
 : handle(TTF_OpenFontIndex(src, size, index)) {
        if (!handle) {
@@ -115,12 +119,20 @@ glm::ivec2 Font::TextSize(const char *text) const {
        return size;
 }
 
+glm::ivec2 Font::TextSize(const std::string &text) const {
+       return TextSize(text.c_str());
+}
+
 Texture Font::Render(const char *text) const {
        Texture tex;
        Render(text, tex);
        return tex;
 }
 
+Texture Font::Render(const std::string &text) const {
+       return Render(text.c_str());
+}
+
 void Font::Render(const char *text, Texture &tex) const {
        SDL_Surface *srf = TTF_RenderUTF8_Blended(handle, text, { 0xFF, 0xFF, 0xFF, 0xFF });
        if (!srf) {
@@ -132,6 +144,10 @@ void Font::Render(const char *text, Texture &tex) const {
        SDL_FreeSurface(srf);
 }
 
+void Font::Render(const std::string &text, Texture &tex) const {
+       Render(text.c_str(), tex);
+}
+
 Format::Format() noexcept
 : format(GL_BGRA)
 , type(GL_UNSIGNED_INT_8_8_8_8_REV)
index c7b5fdd326e58bcd26651aaf0e925206daf877ef..0a31360e7adc4877836660177166563dab237676 100644 (file)
@@ -1,10 +1,13 @@
+#include "AlphaSprite.hpp"
 #include "CreatureSkin.hpp"
+#include "PlainColor.hpp"
 #include "PlanetSurface.hpp"
 #include "Program.hpp"
 #include "Shader.hpp"
 #include "SunSurface.hpp"
 
 #include "ArrayTexture.hpp"
+#include "Texture.hpp"
 #include "../app/init.hpp"
 
 #include <algorithm>
@@ -269,6 +272,24 @@ void PlanetSurface::Activate() noexcept {
        glDisable(GL_BLEND);
 }
 
+void PlanetSurface::SetM(const glm::mat4 &mm) noexcept {
+       m = mm;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void PlanetSurface::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
 void PlanetSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
        m = mm;
        v = vv;
@@ -427,6 +448,24 @@ void SunSurface::Activate() noexcept {
        glDisable(GL_BLEND);
 }
 
+void SunSurface::SetM(const glm::mat4 &mm) noexcept {
+       m = mm;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void SunSurface::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
 void SunSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
        m = mm;
        v = vv;
@@ -543,6 +582,24 @@ void CreatureSkin::Activate() noexcept {
        glDisable(GL_BLEND);
 }
 
+void CreatureSkin::SetM(const glm::mat4 &mm) noexcept {
+       m = mm;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void CreatureSkin::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
 void CreatureSkin::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
        m = mm;
        v = vv;
@@ -570,5 +627,266 @@ void CreatureSkin::SetNumLights(int n) noexcept {
        prog.Uniform(num_lights_handle, std::min(MAX_LIGHTS, n));
 }
 
+
+PlainColor::PlainColor()
+: prog() {
+       prog.LoadShader(
+               GL_VERTEX_SHADER,
+               "#version 330 core\n"
+
+               "layout(location = 0) in vec3 vtx_position;\n"
+
+               "uniform mat4 M;\n"
+               "uniform mat4 MV;\n"
+               "uniform mat4 MVP;\n"
+
+               "void main() {\n"
+                       "gl_Position = MVP * vec4(vtx_position, 1);\n"
+               "}\n"
+       );
+       prog.LoadShader(
+               GL_FRAGMENT_SHADER,
+               "#version 330 core\n"
+
+               "uniform vec3 fg_color;\n"
+
+               "out vec3 color;\n"
+
+               "void main() {\n"
+                       "color = fg_color;\n"
+               "}\n"
+       );
+       prog.Link();
+       if (!prog.Linked()) {
+               prog.Log(std::cerr);
+               throw std::runtime_error("link program");
+       }
+       m_handle = prog.UniformLocation("M");
+       mv_handle = prog.UniformLocation("MV");
+       mvp_handle = prog.UniformLocation("MVP");
+       fg_color_handle = prog.UniformLocation("fg_color");
+
+       vao.Bind();
+       vao.BindAttributes();
+       vao.EnableAttribute(0);
+       vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
+       vao.ReserveAttributes(4, GL_STATIC_DRAW);
+       {
+               auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
+               attrib[0].position = glm::vec3(-1.0f, -1.0f, 0.0f);
+               attrib[1].position = glm::vec3(-1.0f,  1.0f, 0.0f);
+               attrib[2].position = glm::vec3( 1.0f, -1.0f, 0.0f);
+               attrib[3].position = glm::vec3( 1.0f,  1.0f, 0.0f);
+       }
+       vao.BindElements();
+       vao.ReserveElements(7, GL_STATIC_DRAW);
+       {
+               auto element = vao.MapElements(GL_WRITE_ONLY);
+               element[ 0] = 0;
+               element[ 1] = 3;
+               element[ 2] = 2;
+               element[ 3] = 0;
+               element[ 4] = 1;
+               element[ 5] = 3;
+               element[ 6] = 2;
+       }
+       vao.Unbind();
+}
+
+PlainColor::~PlainColor() {
+}
+
+void PlainColor::Activate() noexcept {
+       prog.Use();
+       glEnable(GL_DEPTH_TEST);
+       glDepthFunc(GL_LESS);
+       glEnable(GL_CULL_FACE);
+       glDisable(GL_BLEND);
+}
+
+void PlainColor::SetM(const glm::mat4 &mm) noexcept {
+       m = mm;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void PlainColor::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void PlainColor::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       m = mm;
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void PlainColor::SetColor(const glm::vec3 &color) noexcept {
+       prog.Uniform(fg_color_handle, color);
+}
+
+void PlainColor::DrawRect() const noexcept {
+       vao.Bind();
+       vao.DrawTriangles(6);
+}
+
+void PlainColor::OutlineRect() const noexcept {
+       vao.Bind();
+       vao.DrawLineLoop(4, 3);
+}
+
+
+AlphaSprite::AlphaSprite()
+: prog() {
+       prog.LoadShader(
+               GL_VERTEX_SHADER,
+               "#version 330 core\n"
+
+               "layout(location = 0) in vec3 vtx_position;\n"
+               "layout(location = 1) in vec2 vtx_texture;\n"
+
+               "uniform mat4 M;\n"
+               "uniform mat4 MV;\n"
+               "uniform mat4 MVP;\n"
+
+               "out vec2 frag_tex_uv;\n"
+
+               "void main() {\n"
+                       "gl_Position = MVP * vec4(vtx_position, 1);\n"
+                       "frag_tex_uv = vtx_texture;\n"
+               "}\n"
+       );
+       prog.LoadShader(
+               GL_FRAGMENT_SHADER,
+               "#version 330 core\n"
+
+               "in vec2 frag_tex_uv;\n"
+
+               "uniform sampler2D tex_sampler;\n"
+               "uniform vec4 fg_color;\n"
+               "uniform vec4 bg_color;\n"
+
+               "out vec4 color;\n"
+
+               "void main() {\n"
+                       "vec4 tex_color = texture(tex_sampler, frag_tex_uv);\n"
+                       "vec4 factor = mix(bg_color, fg_color, tex_color.a);\n"
+                       "color = vec4((tex_color * factor).rgb, factor.a);\n"
+               "}\n"
+       );
+       prog.Link();
+       if (!prog.Linked()) {
+               prog.Log(std::cerr);
+               throw std::runtime_error("link program");
+       }
+       m_handle = prog.UniformLocation("M");
+       mv_handle = prog.UniformLocation("MV");
+       mvp_handle = prog.UniformLocation("MVP");
+       sampler_handle = prog.UniformLocation("tex_sampler");
+       fg_color_handle = prog.UniformLocation("fg_color");
+       bg_color_handle = prog.UniformLocation("bg_color");
+
+       vao.Bind();
+       vao.BindAttributes();
+       vao.EnableAttribute(0);
+       vao.EnableAttribute(1);
+       vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
+       vao.AttributePointer<glm::vec2>(1, false, offsetof(Attributes, texture));
+       vao.ReserveAttributes(4, GL_STATIC_DRAW);
+       {
+               auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
+               attrib[0].position = glm::vec3(-1.0f, -1.0f, 0.0f);
+               attrib[0].texture = glm::vec2(0.0f, 0.0f);
+               attrib[1].position = glm::vec3(-1.0f,  1.0f, 0.0f);
+               attrib[1].texture = glm::vec2(0.0f, 1.0f);
+               attrib[2].position = glm::vec3( 1.0f, -1.0f, 0.0f);
+               attrib[2].texture = glm::vec2(1.0f, 0.0f);
+               attrib[3].position = glm::vec3( 1.0f,  1.0f, 0.0f);
+               attrib[3].texture = glm::vec2(1.0f, 1.0f);
+       }
+       vao.BindElements();
+       vao.ReserveElements(7, GL_STATIC_DRAW);
+       {
+               auto element = vao.MapElements(GL_WRITE_ONLY);
+               element[ 0] = 0;
+               element[ 1] = 1;
+               element[ 2] = 2;
+               element[ 3] = 3;
+       }
+       vao.Unbind();
+}
+
+AlphaSprite::~AlphaSprite() {
+}
+
+void AlphaSprite::Activate() noexcept {
+       prog.Use();
+       glEnable(GL_DEPTH_TEST);
+       glDepthFunc(GL_LESS);
+       glEnable(GL_CULL_FACE);
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void AlphaSprite::SetM(const glm::mat4 &mm) noexcept {
+       m = mm;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void AlphaSprite::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void AlphaSprite::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       m = mm;
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
+       prog.Uniform(m_handle, m);
+       prog.Uniform(mv_handle, mv);
+       prog.Uniform(mvp_handle, mvp);
+}
+
+void AlphaSprite::SetTexture(Texture &tex) noexcept {
+       glActiveTexture(GL_TEXTURE0);
+       tex.Bind();
+       prog.Uniform(sampler_handle, GLint(0));
+}
+
+void AlphaSprite::SetFgColor(const glm::vec4 &color) noexcept {
+       prog.Uniform(fg_color_handle, color);
+}
+
+void AlphaSprite::SetBgColor(const glm::vec4 &color) noexcept {
+       prog.Uniform(bg_color_handle, color);
+}
+
+void AlphaSprite::DrawRect() const noexcept {
+       vao.Bind();
+       vao.DrawTriangleStrip(4);
+}
+
 }
 }
index 9e22a260eeb12072eb75ea5931be9b666009d0c1..636f3c35c1015f9cc9612ef9d62c4f592d740692 100644 (file)
@@ -152,5 +152,9 @@ void Viewport::Clear() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
+void Viewport::ClearDepth() {
+       glClear(GL_DEPTH_BUFFER_BIT);
+}
+
 }
 }
diff --git a/src/ui/CreaturePanel.hpp b/src/ui/CreaturePanel.hpp
new file mode 100644 (file)
index 0000000..b9888b2
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef BLOBS_UI_CREATUREPANEL_HPP_
+#define BLOBS_UI_CREATUREPANEL_HPP_
+
+#include "Label.hpp"
+
+
+namespace blobs {
+namespace app {
+       struct Assets;
+}
+namespace creature {
+       class Creature;
+}
+namespace graphics {
+       class Viewport;
+}
+namespace ui {
+
+class CreaturePanel {
+
+public:
+       explicit CreaturePanel(const app::Assets &);
+       ~CreaturePanel();
+
+       CreaturePanel(const CreaturePanel &) = delete;
+       CreaturePanel &operator =(const CreaturePanel &) = delete;
+
+       CreaturePanel(CreaturePanel &&) = delete;
+       CreaturePanel &operator =(CreaturePanel &&) = delete;
+
+public:
+       void Show(creature::Creature &);
+       void Hide() noexcept;
+
+       void Draw(app::Assets &, graphics::Viewport &) noexcept;
+
+private:
+       creature::Creature *c;
+
+       Label name;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/ui/Label.hpp b/src/ui/Label.hpp
new file mode 100644 (file)
index 0000000..0b9e0ca
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef BLOBS_UI_LABEL_HPP_
+#define BLOBS_UI_LABEL_HPP_
+
+#include "align.hpp"
+#include "../graphics/Texture.hpp"
+
+#include <string>
+
+
+namespace blobs {
+namespace app {
+       struct Assets;
+}
+namespace graphics {
+       class Font;
+       class Viewport;
+}
+namespace ui {
+
+class Label {
+
+public:
+       explicit Label(const graphics::Font &);
+       ~Label();
+
+       Label(const Label &) = delete;
+       Label &operator =(const Label &) = delete;
+
+       Label(Label &&) = delete;
+       Label &operator =(Label &&) = delete;
+
+public:
+       Label &Text(const std::string &);
+       Label &Font(const graphics::Font &);
+       Label &Foreground(const glm::vec4 &);
+       Label &Background(const glm::vec4 &);
+
+       Label &Position(const glm::vec3 &p) noexcept { pos = p; return *this; }
+       const glm::vec3 &Position() const noexcept { return pos; }
+
+       Label &Origin(Gravity o) noexcept { origin = o; return *this; }
+       Gravity Origin() const noexcept { return origin; }
+
+       glm::vec2 Size();
+       void Draw(app::Assets &, graphics::Viewport &) noexcept;
+
+private:
+       void Update();
+
+private:
+       const graphics::Font *font;
+       std::string text;
+       graphics::Texture tex;
+       glm::vec4 fg_color;
+       glm::vec4 bg_color;
+       glm::vec3 pos;
+       Gravity origin;
+       bool dirty;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/ui/align.hpp b/src/ui/align.hpp
new file mode 100644 (file)
index 0000000..15dce20
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef BLOBS_UI_ALIGN_HPP_
+#define BLOBS_UI_ALIGN_HPP_
+
+#include "../graphics/glm.hpp"
+
+
+namespace blobs {
+namespace ui {
+
+enum class Align {
+       BEGIN,
+       MIDDLE,
+       END,
+};
+
+enum class Gravity {
+       NORTH_WEST,
+       NORTH,
+       NORTH_EAST,
+       WEST,
+       CENTER,
+       EAST,
+       SOUTH_WEST,
+       SOUTH,
+       SOUTH_EAST,
+};
+
+inline Align get_x(Gravity g) noexcept {
+       return Align(int(g) % 3);
+}
+
+inline Align get_y(Gravity g) noexcept {
+       return Align(int(g) / 3);
+}
+
+inline Gravity get_gravity(Align x, Align y) noexcept {
+       return Gravity(int(y) * 3 + int(x));
+}
+
+inline glm::vec2 align(
+       Gravity g,
+       const glm::vec2 &size,
+       const glm::vec2 &offset = glm::vec2(0.0f, 0.0f)
+) {
+       return glm::vec2(
+               size.x * 0.5f * (1 - int(get_x(g))) + offset.x,
+               size.y * 0.5f * (1 - int(get_y(g))) + offset.y
+       );
+}
+
+inline glm::vec3 align(
+       Gravity g,
+       const glm::vec2 &size,
+       const glm::vec3 &offset
+) {
+       return glm::vec3(
+               size.x * 0.5f * (1 - int(get_x(g))) + offset.x,
+               size.y * 0.5f * (1 - int(get_y(g))) + offset.y,
+               offset.z
+       );
+}
+
+}
+}
+
+#endif
diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp
new file mode 100644 (file)
index 0000000..f7a102e
--- /dev/null
@@ -0,0 +1,126 @@
+#include "CreaturePanel.hpp"
+
+#include "../app/Assets.hpp"
+#include "../creature/Creature.hpp"
+#include "../graphics/Viewport.hpp"
+
+#include <glm/gtx/transform.hpp>
+
+#include <iostream>
+#include <glm/gtx/io.hpp>
+
+
+namespace blobs {
+namespace ui {
+
+CreaturePanel::CreaturePanel(const app::Assets &assets)
+: c(nullptr)
+, name(assets.fonts.large) {
+       name.Origin(Gravity::NORTH_EAST);
+}
+
+CreaturePanel::~CreaturePanel() {
+}
+
+
+void CreaturePanel::Show(creature::Creature &cr) {
+       c = &cr;
+       name.Text(c->Name());
+}
+
+void CreaturePanel::Hide() noexcept {
+       c = nullptr;
+}
+
+void CreaturePanel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
+       if (!c) return;
+
+       const glm::vec2 margin(20.0f);
+       const glm::vec2 padding(10.0f);
+
+       const glm::vec2 size(name.Size() + 2.0f * padding);
+       const glm::vec2 half_size = size * 0.5f;
+
+       const glm::vec3 top_right(viewport.Width() - margin.x, margin.y, 0.0f);
+       name.Position(top_right - glm::vec3(padding.x, -padding.y, 1.0f));
+
+       assets.shaders.plain_color.Activate();
+       assets.shaders.plain_color.SetM(
+               glm::translate(glm::vec3(top_right.x - half_size.x, top_right.y + half_size.y, 0.0f))
+               * glm::scale(glm::vec3(half_size.x, half_size.y, 1.0f)));
+       assets.shaders.plain_color.SetColor(glm::vec3(0.7f, 0.7f, 0.7f));
+       assets.shaders.plain_color.DrawRect();
+
+       name.Draw(assets, viewport);
+}
+
+
+Label::Label(const graphics::Font &f)
+: font(&f)
+, text()
+, tex()
+, fg_color(0.0f, 0.0f, 0.0f, 1.0f)
+, bg_color(0.0f, 0.0f, 0.0f, 0.0f)
+, pos(0.0f, 0.0f, 0.0f)
+, origin(Gravity::CENTER)
+, dirty(true) {
+}
+
+Label::~Label() {
+}
+
+Label &Label::Text(const std::string &t) {
+       if (text != t) {
+               dirty = true;
+       }
+       text = t;
+       return *this;
+}
+
+Label &Label::Font(const graphics::Font &f) {
+       if (font != &f) {
+               dirty = true;
+       }
+       font = &f;
+       return *this;
+}
+
+Label &Label::Foreground(const glm::vec4 &c) {
+       fg_color = c;
+       return *this;
+}
+
+Label &Label::Background(const glm::vec4 &c) {
+       bg_color = c;
+       return *this;
+}
+
+glm::vec2 Label::Size() {
+       Update();
+       return tex.Size();
+}
+
+void Label::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
+       Update();
+       glm::vec2 size = Size();
+       glm::vec3 position = align(origin, size, pos);
+
+       std::cout << "pos: " << pos << ", size: " << size << ", position: " << position << std::endl;
+
+       assets.shaders.alpha_sprite.Activate();
+       assets.shaders.alpha_sprite.SetM(glm::translate(position)
+               * glm::scale(glm::vec3(size.x * 0.5f, size.y * 0.5f, 1.0f)));
+       assets.shaders.alpha_sprite.SetTexture(tex);
+       assets.shaders.alpha_sprite.SetFgColor(fg_color);
+       assets.shaders.alpha_sprite.SetBgColor(bg_color);
+       assets.shaders.alpha_sprite.DrawRect();
+}
+
+void Label::Update() {
+       if (!dirty) return;
+       font->Render(text, tex);
+       dirty = false;
+}
+
+}
+}