From 55dbd6b35a39888f245e247d2e140f141f918178 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Wed, 22 Jul 2015 12:28:25 +0200 Subject: [PATCH 1/1] set and display block type labels --- .gitmodules | 3 ++ Makefile | 15 +++++-- TODO | 5 +++ assets | 1 + src/app/Application.hpp | 8 ++++ src/app/Assets.hpp | 25 +++++++++++ src/app/{Application.cpp => app.cpp} | 67 +++++++++++++++++++++------- src/graphics/Font.hpp | 26 +++++++++++ src/graphics/render.cpp | 41 ++++++++++++++++- src/ui/HUD.hpp | 15 ++++++- src/ui/Interface.hpp | 8 +++- src/ui/ui.cpp | 58 +++++++++++++++++------- src/world/BlockType.hpp | 3 ++ src/world/World.cpp | 13 ++++++ src/world/block.cpp | 1 + 15 files changed, 246 insertions(+), 43 deletions(-) create mode 100644 .gitmodules create mode 160000 assets create mode 100644 src/app/Assets.hpp rename src/app/{Application.cpp => app.cpp} (73%) diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..bde19f5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "assets"] + path = assets + url = http://git.localhorst.tv/repo/blank-assets.git diff --git a/Makefile b/Makefile index cfe9a2c..2a355cd 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,9 @@ RELEASE_DIR := build/release TEST_DIR := build/test DIR := $(RELEASE_DIR) $(DEBUG_DIR) $(PROFILE_DIR) $(TEST_DIR) build +ASSET_DIR := assets +ASSET_DEP := $(ASSET_DIR)/.git + LIB_SRC := $(wildcard $(SOURCE_DIR)/*/*.cpp) BIN_SRC := $(wildcard $(SOURCE_DIR)/*.cpp) SRC := $(LIB_SRC) $(BIN_SRC) @@ -58,16 +61,16 @@ profile: $(PROFILE_BIN) tests: $(TEST_BIN) -run: blank +run: $(ASSET_DEP) blank ./blank -gdb: blank.debug +gdb: $(ASSET_DEP) blank.debug gdb ./blank.debug -cachegrind: blank.profile +cachegrind: $(ASSET_DEP) blank.profile valgrind ./blank.profile -callgrind: blank.profile +callgrind: $(ASSET_DEP) blank.profile valgrind --tool=callgrind \ --branch-sim=yes --cacheuse=yes --cache-sim=yes \ --collect-bus=yes --collect-systime=yes --collect-jumps=yes \ @@ -103,6 +106,10 @@ $(TEST_BIN): $(TEST_OBJ) @echo link: $@ @$(LDXX) -o $@ $(CXXFLAGS) $(LDXXFLAGS) $(TESTLIBS) $(TEST_FLAGS) $^ +$(ASSET_DEP): .git/$(shell git symbolic-ref HEAD) + @git submodule update --init >/dev/null + @touch $@ + $(RELEASE_DIR)/%.o: $(SOURCE_DIR)/%.cpp | $(RELEASE_DIR) @mkdir -p "$(@D)" @echo compile: $@ diff --git a/TODO b/TODO index e7b2f8f..9d43155 100644 --- a/TODO +++ b/TODO @@ -12,6 +12,11 @@ textures do I need to say anything? :) +font colours + + set font fg and bg colour as either uniform or vertex attribute + and lerp between them based on the texture's alpha component + command line usefull for development and later on world administration diff --git a/assets b/assets new file mode 160000 index 0000000..7ac546c --- /dev/null +++ b/assets @@ -0,0 +1 @@ +Subproject commit 7ac546c3310a3f147a889077dffa6919fad94be7 diff --git a/src/app/Application.hpp b/src/app/Application.hpp index a3c6276..ea74211 100644 --- a/src/app/Application.hpp +++ b/src/app/Application.hpp @@ -1,14 +1,18 @@ #ifndef BLANK_APP_APPLICATION_HPP_ #define BLANK_APP_APPLICATION_HPP_ +#include "Assets.hpp" #include "init.hpp" #include "RandomWalk.hpp" +#include "../graphics/BlendedSprite.hpp" #include "../graphics/BlockLighting.hpp" #include "../graphics/Camera.hpp" #include "../graphics/DirectionalLighting.hpp" #include "../ui/Interface.hpp" #include "../world/World.hpp" +#include + namespace blank { @@ -43,6 +47,7 @@ public: /// process all events in SDL's queue void HandleEvents(); + void Handle(const SDL_WindowEvent &); /// integrate to the next step with dt milliseconds passed void Update(int dt); /// push the current state to display @@ -58,8 +63,11 @@ private: Window window; GLContext ctx; InitGLEW init_glew; + Assets assets; + BlockLighting chunk_prog; DirectionalLighting entity_prog; + BlendedSprite sprite_prog; Camera cam; World world; diff --git a/src/app/Assets.hpp b/src/app/Assets.hpp new file mode 100644 index 0000000..d9ab3d4 --- /dev/null +++ b/src/app/Assets.hpp @@ -0,0 +1,25 @@ +#ifndef BLANK_APP_ASSETS_HPP_ +#define BLANK_APP_ASSETS_HPP_ + +#include + + +namespace blank { + +class Font; + +class Assets { + +public: + explicit Assets(const std::string &base); + + Font LoadFont(const std::string &name, int size) const; + +private: + std::string fonts; + +}; + +} + +#endif diff --git a/src/app/Application.cpp b/src/app/app.cpp similarity index 73% rename from src/app/Application.cpp rename to src/app/app.cpp index 80dee36..9e83cd4 100644 --- a/src/app/Application.cpp +++ b/src/app/app.cpp @@ -1,11 +1,27 @@ #include "Application.hpp" +#include "Assets.hpp" +#include "../graphics/Font.hpp" #include "../world/BlockType.hpp" #include "../world/Entity.hpp" #include #include +using std::string; + + +namespace { + +string get_asset_path() { + char *base = SDL_GetBasePath(); + string assets(base); + assets += "assets/"; + SDL_free(base); + return assets; +} + +} namespace blank { @@ -17,11 +33,13 @@ Application::Application(const Config &config) , window() , ctx(window.CreateContext()) , init_glew() +, assets(get_asset_path()) , chunk_prog() , entity_prog() +, sprite_prog() , cam() , world(config.world) -, interface(config.interface, world) +, interface(config.interface, assets, world) , test_controller(MakeTestEntity(world)) , running(false) { if (config.vsync) { @@ -116,21 +134,7 @@ void Application::HandleEvents() { running = false; break; case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_WINDOWEVENT_FOCUS_GAINED: - window.GrabMouse(); - break; - case SDL_WINDOWEVENT_FOCUS_LOST: - window.ReleaseMouse(); - break; - case SDL_WINDOWEVENT_RESIZED: - cam.Viewport(event.window.data1, event.window.data2); - interface.Handle(event.window); - break; - default: - interface.Handle(event.window); - break; - } + Handle(event.window); break; default: break; @@ -138,6 +142,24 @@ void Application::HandleEvents() { } } +void Application::Handle(const SDL_WindowEvent &event) { + switch (event.event) { + case SDL_WINDOWEVENT_FOCUS_GAINED: + window.GrabMouse(); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + window.ReleaseMouse(); + break; + case SDL_WINDOWEVENT_RESIZED: + cam.Viewport(event.data1, event.data2); + interface.Handle(event); + break; + default: + interface.Handle(event); + break; + } +} + void Application::Update(int dt) { interface.Update(dt); test_controller.Update(dt); @@ -152,9 +174,20 @@ void Application::Render() { world.Render(chunk_prog, entity_prog); - interface.Render(entity_prog); + interface.Render(entity_prog, sprite_prog); window.Flip(); } + +Assets::Assets(const string &base) +: fonts(base + "fonts/") { + +} + +Font Assets::LoadFont(const string &name, int size) const { + string full = fonts + name + ".ttf"; + return Font(full.c_str(), size); +} + } diff --git a/src/graphics/Font.hpp b/src/graphics/Font.hpp index 2219452..1d4ff17 100644 --- a/src/graphics/Font.hpp +++ b/src/graphics/Font.hpp @@ -11,6 +11,21 @@ class Texture; class Font { +public: + enum FontStyle { + STYLE_NORMAL = TTF_STYLE_NORMAL, + STYLE_BOLD = TTF_STYLE_BOLD, + STYLE_ITALIC = TTF_STYLE_ITALIC, + STYLE_UNDERLINE = TTF_STYLE_UNDERLINE, + STYLE_STRIKE = TTF_STYLE_STRIKETHROUGH, + }; + enum FontHinting { + HINT_NORMAL = TTF_HINTING_NORMAL, + HINT_LIGHT = TTF_HINTING_LIGHT, + HINT_MONO = TTF_HINTING_MONO, + HINT_NONE = TTF_HINTING_NONE, + }; + public: Font(const char *src, int size, long index = 0); ~Font(); @@ -22,6 +37,13 @@ public: Font &operator =(const Font &) = delete; public: + int Style() const noexcept; + void Style(int) const noexcept; + int Outline() const noexcept; + void Outline(int) noexcept; + + int Hinting() const noexcept; + void Hinting(int) const noexcept; bool Kerning() const noexcept; void Kerning(bool) noexcept; @@ -30,11 +52,15 @@ public: int Descent() const noexcept; int LineSkip() const noexcept; + const char *FamilyName() const noexcept; + const char *StyleName() const noexcept; + bool HasGlyph(Uint16) const noexcept; glm::tvec2 TextSize(const char *) const; Texture Render(const char *, SDL_Color) const; + void Render(const char *, SDL_Color, Texture &) const; private: TTF_Font *handle; diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 3d0bbd4..7e04840 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -34,6 +34,31 @@ Font &Font::operator =(Font &&other) noexcept { } +int Font::Style() const noexcept { + return TTF_GetFontStyle(handle); +} + +void Font::Style(int s) const noexcept { + TTF_SetFontStyle(handle, s); +} + +int Font::Outline() const noexcept { + return TTF_GetFontOutline(handle); +} + +void Font::Outline(int px) noexcept { + TTF_SetFontOutline(handle, px); +} + + +int Font::Hinting() const noexcept { + return TTF_GetFontHinting(handle); +} + +void Font::Hinting(int h) const noexcept { + TTF_SetFontHinting(handle, h); +} + bool Font::Kerning() const noexcept { return TTF_GetFontKerning(handle); } @@ -60,6 +85,15 @@ int Font::LineSkip() const noexcept { } +const char *Font::FamilyName() const noexcept { + return TTF_FontFaceFamilyName(handle); +} + +const char *Font::StyleName() const noexcept { + return TTF_FontFaceStyleName(handle); +} + + bool Font::HasGlyph(Uint16 c) const noexcept { return TTF_GlyphIsProvided(handle, c); } @@ -74,16 +108,19 @@ glm::tvec2 Font::TextSize(const char *text) const { } Texture Font::Render(const char *text, SDL_Color color) const { + Texture tex; + return tex; +} + +void Font::Render(const char *text, SDL_Color color, Texture &tex) const { SDL_Surface *srf = TTF_RenderUTF8_Blended(handle, text, color); if (!srf) { throw std::runtime_error(TTF_GetError()); } - Texture tex; tex.Bind(); tex.Data(*srf, false); tex.FilterLinear(); SDL_FreeSurface(srf); - return tex; } diff --git a/src/ui/HUD.hpp b/src/ui/HUD.hpp index ca6b754..245d886 100644 --- a/src/ui/HUD.hpp +++ b/src/ui/HUD.hpp @@ -1,22 +1,26 @@ #ifndef BLANK_UI_HUD_H_ #define BLANK_UI_HUD_H_ +#include "../graphics/Texture.hpp" #include "../model/Model.hpp" #include "../model/OutlineModel.hpp" +#include "../model/SpriteModel.hpp" #include namespace blank { +class BlendedSprite; class Block; class BlockTypeRegistry; class DirectionalLighting; +class Font; class HUD { public: - explicit HUD(const BlockTypeRegistry &); + HUD(const BlockTypeRegistry &, const Font &); HUD(const HUD &) = delete; HUD &operator =(const HUD &) = delete; @@ -26,14 +30,21 @@ public: void Display(const Block &); - void Render(DirectionalLighting &) noexcept; + void Render(DirectionalLighting &, BlendedSprite &) noexcept; private: const BlockTypeRegistry &types; + const Font &font; Model block; Model::Buffer block_buf; glm::mat4 block_transform; + + Texture block_label; + SpriteModel label_sprite; + glm::mat4 label_transform; + SDL_Color label_color; + bool block_visible; OutlineModel crosshair; diff --git a/src/ui/Interface.hpp b/src/ui/Interface.hpp index a08a0bf..88637c6 100644 --- a/src/ui/Interface.hpp +++ b/src/ui/Interface.hpp @@ -4,6 +4,7 @@ #include "HUD.hpp" #include "../app/FPSController.hpp" #include "../app/IntervalTimer.hpp" +#include "../graphics/Font.hpp" #include "../model/geometry.hpp" #include "../model/OutlineModel.hpp" #include "../world/Block.hpp" @@ -15,7 +16,9 @@ namespace blank { class Chunk; +class BlendedSprite; class DirectionalLighting; +class Assets; class World; class Interface { @@ -31,7 +34,7 @@ public: bool visual_disabled = false; }; - Interface(const Config &, World &); + Interface(const Config &, const Assets &, World &); void HandlePress(const SDL_KeyboardEvent &); void HandleRelease(const SDL_KeyboardEvent &); @@ -61,7 +64,7 @@ public: void Update(int dt); - void Render(DirectionalLighting &) noexcept; + void Render(DirectionalLighting &, BlendedSprite &) noexcept; private: void CheckAim(); @@ -69,6 +72,7 @@ private: private: World &world; FPSController ctrl; + Font font; HUD hud; Ray aim; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 8ddd40c..8e48f14 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -1,11 +1,16 @@ #include "HUD.hpp" #include "Interface.hpp" +#include "../app/Assets.hpp" #include "../app/init.hpp" +#include "../graphics/BlendedSprite.hpp" #include "../graphics/DirectionalLighting.hpp" +#include "../graphics/Font.hpp" #include "../model/shapes.hpp" #include "../world/World.hpp" +#include +#include #include #include #include @@ -13,18 +18,23 @@ namespace blank { -HUD::HUD(const BlockTypeRegistry &types) +HUD::HUD(const BlockTypeRegistry &types, const Font &font) : types(types) +, font(font) , block() , block_buf() , block_transform(1.0f) +, block_label() +, label_sprite() +, label_transform(1.0f) +, label_color{0xFF, 0xFF, 0xFF, 0xFF} , block_visible(false) , crosshair() , crosshair_transform(1.0f) , near(100.0f) , far(-100.0f) , projection(glm::ortho(0.0f, 1.0f, 1.0f, 0.0f, near, far)) -, view(glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0))) { +, view(1.0f) { block_transform = glm::translate(block_transform, glm::vec3(50.0f, 50.0f, 0.0f)); block_transform = glm::scale(block_transform, glm::vec3(50.0f)); block_transform = glm::rotate(block_transform, 3.5f, glm::vec3(1.0f, 0.0f, 0.0f)); @@ -48,7 +58,7 @@ void HUD::Viewport(float width, float height) noexcept { void HUD::Viewport(float x, float y, float width, float height) noexcept { projection = glm::ortho(x, width, height, y, near, far); - crosshair_transform = glm::translate(glm::mat4(1.0f), glm::vec3(width * 0.5f, height * 0.5f, 0.0f)); + crosshair_transform = glm::translate(glm::vec3(width * 0.5f, height * 0.5f, 0.0f)); } @@ -58,32 +68,47 @@ void HUD::Display(const Block &b) { block_buf.Clear(); type.FillModel(block_buf, b.Transform()); block.Update(block_buf); + + font.Render(type.label.c_str(), label_color, block_label); + glm::vec2 size(font.TextSize(type.label.c_str())); + label_sprite.LoadRect(size.x, size.y); + label_transform = glm::translate(glm::vec3( + std::max(5.0f, 50.0f - std::round(size.x * 0.5f)), + 70.0f + size.y, + 0.75f + )); + block_visible = type.visible; } -void HUD::Render(DirectionalLighting &program) noexcept { - program.SetLightDirection({ 1.0f, 3.0f, 5.0f }); +void HUD::Render(DirectionalLighting &world_prog, BlendedSprite &sprite_prog) noexcept { + world_prog.Activate(); + world_prog.SetLightDirection({ 1.0f, 3.0f, 5.0f }); // disable distance fog - program.SetFogDensity(0.0f); + world_prog.SetFogDensity(0.0f); GLContext::ClearDepthBuffer(); - program.SetVP(view, projection); + world_prog.SetMVP(crosshair_transform, view, projection); + crosshair.Draw(); if (block_visible) { - program.SetM(block_transform); + world_prog.SetM(block_transform); block.Draw(); - } - program.SetM(crosshair_transform); - crosshair.Draw(); + sprite_prog.Activate(); + sprite_prog.SetMVP(label_transform, view, projection); + sprite_prog.SetTexture(block_label); + label_sprite.Draw(); + } } -Interface::Interface(const Config &config, World &world) +Interface::Interface(const Config &config, const Assets &assets, World &world) : world(world) , ctrl(world.Player()) -, hud(world.BlockTypes()) +, font(assets.LoadFont("DejaVuSans", 16)) +, hud(world.BlockTypes(), font) , aim{{ 0, 0, 0 }, { 0, 0, -1 }} , aim_chunk(nullptr) , aim_block(0) @@ -381,15 +406,16 @@ void Interface::CheckAim() { } -void Interface::Render(DirectionalLighting &program) noexcept { +void Interface::Render(DirectionalLighting &world_prog, BlendedSprite &sprite_prog) noexcept { if (config.visual_disabled) return; if (aim_chunk) { - program.SetM(outline_transform); + world_prog.Activate(); + world_prog.SetM(outline_transform); outline.Draw(); } - hud.Render(program); + hud.Render(world_prog, sprite_prog); } } diff --git a/src/world/BlockType.hpp b/src/world/BlockType.hpp index 28f814b..caccb8f 100644 --- a/src/world/BlockType.hpp +++ b/src/world/BlockType.hpp @@ -20,6 +20,9 @@ struct BlockType { glm::vec3 color; glm::vec3 outline_color; + // a string to display to the user + std::string label; + Block::Type id; // light level that blocks of this type emit diff --git a/src/world/World.cpp b/src/world/World.cpp index d51520e..94cd092 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -29,6 +29,7 @@ World::World(const Config &config) { // white block BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape); + type.label = "White Block"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -37,6 +38,7 @@ World::World(const Config &config) } { // white slab BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape); + type.label = "White Slab"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -45,6 +47,7 @@ World::World(const Config &config) } { // white stair BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape); + type.label = "White Stair"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -54,6 +57,7 @@ World::World(const Config &config) { // red block BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape); + type.label = "Red Block"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -62,6 +66,7 @@ World::World(const Config &config) } { // red slab BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape); + type.label = "Red Slab"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -70,6 +75,7 @@ World::World(const Config &config) } { // red stair BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape); + type.label = "Red Stair"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -79,6 +85,7 @@ World::World(const Config &config) { // green block BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape); + type.label = "Green Block"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -87,6 +94,7 @@ World::World(const Config &config) } { // green slab BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape); + type.label = "Green Slab"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -95,6 +103,7 @@ World::World(const Config &config) } { // green stair BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape); + type.label = "Green Stair"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -104,6 +113,7 @@ World::World(const Config &config) { // blue block BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape); + type.label = "Blue Block"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -112,6 +122,7 @@ World::World(const Config &config) } { // blue slab BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape); + type.label = "Blue Slab"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -120,6 +131,7 @@ World::World(const Config &config) } { // blue stair BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape); + type.label = "Blue Stair"; type.block_light = true; type.collision = true; type.collide_block = true; @@ -129,6 +141,7 @@ World::World(const Config &config) { // glowing yellow block BlockType type(true, { 1.0f, 1.0f, 0.0f }, &blockShape); + type.label = "Light"; type.luminosity = 15; type.block_light = true; type.collision = true; diff --git a/src/world/block.cpp b/src/world/block.cpp index 78aa9d8..510771a 100644 --- a/src/world/block.cpp +++ b/src/world/block.cpp @@ -77,6 +77,7 @@ BlockType::BlockType(bool v, const glm::vec3 &col, const Shape *s) noexcept : shape(s) , color(col) , outline_color(-1, -1, -1) +, label("some block") , id(0) , luminosity(0) , visible(v) -- 2.39.2