font rendering
- should combine all that's needed to render a text into some struct
- also, with background nw being a thing, a padding might be nice
- or could separate bg from fg rendering
+ with background now being a thing, a padding might be nice
+ that or maybe separate bg from fg rendering
it may also be feasible to get rid of SDL_ttf and use freetype
directly to eliminate the unneccessary surface creation
break;
case SDL_WINDOWEVENT_RESIZED:
viewport.Resize(event.data1, event.data2);
- interface.Resize(viewport);
break;
default:
break;
--- /dev/null
+#ifndef BLANK_GRAPHICS_TEXT_HPP_
+#define BLANK_GRAPHICS_TEXT_HPP_
+
+#include "align.hpp"
+#include "Texture.hpp"
+#include "../model/SpriteModel.hpp"
+
+#include <string>
+#include <glm/glm.hpp>
+
+
+namespace blank {
+
+class Font;
+class Viewport;
+
+class Text {
+
+public:
+ Text() noexcept;
+
+ void Set(const Font &, const char *);
+ void Set(const Font &f, const std::string &s) {
+ Set(f, s.c_str());
+ }
+
+ void Position(const glm::vec3 &p) noexcept {
+ pos = p;
+ }
+ void Position(
+ const glm::vec3 &p,
+ Gravity g
+ ) noexcept {
+ pos = p;
+ grav = g;
+ pivot = g;
+ dirty = true;
+ }
+ void Position(
+ const glm::vec3 &p,
+ Gravity g,
+ Gravity pv
+ ) noexcept {
+ pos = p;
+ grav = g;
+ pivot = pv;
+ dirty = true;
+ }
+
+ void Foreground(const glm::vec4 &col) noexcept { fg = col; }
+ void Background(const glm::vec4 &col) noexcept { bg = col; }
+
+ void Render(Viewport &) noexcept;
+
+ void Show() noexcept { visible = true; }
+ void Hide() noexcept { visible = false; }
+ void Toggle() noexcept { visible = !visible; }
+ bool Visible() const noexcept { return visible; }
+
+private:
+ void Update();
+
+private:
+ Texture tex;
+ SpriteModel sprite;
+ glm::vec4 bg;
+ glm::vec4 fg;
+ glm::vec2 size;
+ glm::vec3 pos;
+ Gravity grav;
+ Gravity pivot;
+ bool dirty;
+ bool visible;
+
+};
+
+}
+
+#endif
#ifndef BLANK_GRAPHICS_VIEWPORT_HPP_
#define BLANK_GRAPHICS_VIEWPORT_HPP_
+#include "align.hpp"
#include "BlendedSprite.hpp"
#include "BlockLighting.hpp"
#include "Camera.hpp"
#include "DirectionalLighting.hpp"
#include <glm/glm.hpp>
-#include <SDL.h>
namespace blank {
void Clear() noexcept;
void ClearDepth() noexcept;
+ void SetCursor(const glm::vec3 &);
+ void SetCursor(const glm::vec3 &, Gravity = Gravity::NORTH_WEST);
+ void MoveCursor(const glm::vec3 &);
+ const glm::mat4 &Cursor() const noexcept { return cursor; }
+
BlockLighting &ChunkProgram() noexcept;
DirectionalLighting &EntityProgram() noexcept;
DirectionalLighting &HUDProgram() noexcept;
const glm::mat4 &Perspective() const noexcept { return cam.Projection(); }
const glm::mat4 &Ortho() const noexcept { return canv.Projection(); }
- const glm::mat4 &CenterTransform() const noexcept { return center; }
private:
- SDL_GLContext ctx;
Camera cam;
Canvas canv;
- glm::mat4 center;
+ glm::mat4 cursor;
BlockLighting chunk_prog;
DirectionalLighting entity_prog;
--- /dev/null
+#ifndef BLANK_GRAPHICS_ALIGN_HPP_
+#define BLANK_GRAPHICS_ALIGN_HPP_
+
+#include <glm/glm.hpp>
+
+
+namespace blank {
+
+enum class Align {
+ LEFT,
+ CENTER,
+ RIGHT,
+};
+
+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.5 * int(get_x(g)) + offset.x,
+ size.y * 0.5 * int(get_y(g)) + offset.y
+ );
+}
+
+}
+
+#endif
+#include "BlendedSprite.hpp"
#include "Font.hpp"
#include "Format.hpp"
+#include "Text.hpp"
#include "Texture.hpp"
+#include "Viewport.hpp"
#include <algorithm>
#include <cstring>
}
+Text::Text() noexcept
+: tex()
+, sprite()
+, bg(1.0f, 1.0f, 1.0f, 0.0f)
+, fg(1.0f, 1.0f, 1.0f, 1.0f)
+, size(0.0f)
+, pos(0.0f)
+, grav(Gravity::NORTH_WEST)
+, pivot(Gravity::NORTH_WEST)
+, dirty(false)
+, visible(false) {
+
+}
+
+void Text::Set(const Font &font, const char *text) {
+ font.Render(text, tex);
+ size = font.TextSize(text);
+ dirty = true;
+}
+
+void Text::Update() {
+ sprite.LoadRect(size.x, size.y, align(pivot, size));
+ dirty = false;
+}
+
+void Text::Render(Viewport &viewport) noexcept {
+ if (dirty) {
+ Update();
+ }
+ BlendedSprite &prog = viewport.SpriteProgram();
+ viewport.SetCursor(pos, grav);
+ prog.SetM(viewport.Cursor());
+ prog.SetTexture(tex);
+ prog.SetBG(bg);
+ prog.SetFG(fg);
+ sprite.Draw();
+}
+
+
Texture::Texture()
: handle(0)
, width(0)
Viewport::Viewport()
: cam()
, canv()
-, center(1.0f)
+, cursor(1.0f)
, chunk_prog()
, entity_prog()
, sprite_prog()
cam.Aspect(fw, fh);
canv.Resize(fw, fh);
- center = glm::translate(glm::vec3(fw * 0.5f, fh * 0.5f, 0.0f));
-
chunk_prog.SetProjection(Perspective());
if (active_prog == HUD) {
entity_prog.SetProjection(Ortho());
}
+void Viewport::SetCursor(const glm::vec3 &pos) {
+ cursor[3].x = pos.x;
+ cursor[3].y = pos.y;
+ cursor[3].z = pos.z;
+}
+
+void Viewport::SetCursor(const glm::vec3 &pos, Gravity grav) {
+ glm::vec2 p(align(grav, canv.Size(), glm::vec2(pos) + canv.Offset()));
+ cursor[3].x = p.x;
+ cursor[3].y = p.y;
+ cursor[3].z = pos.z;
+}
+
+void Viewport::MoveCursor(const glm::vec3 &d) {
+ cursor[3].x += d.x;
+ cursor[3].y += d.y;
+ cursor[3].z += d.z;
+}
+
+
BlockLighting &Viewport::ChunkProgram() noexcept {
if (active_prog != CHUNK) {
chunk_prog.Activate();
#ifndef BLANK_UI_HUD_H_
#define BLANK_UI_HUD_H_
-#include "../graphics/Texture.hpp"
+#include "../graphics/Text.hpp"
#include "../model/Model.hpp"
#include "../model/OutlineModel.hpp"
-#include "../model/SpriteModel.hpp"
#include <glm/glm.hpp>
Model::Buffer block_buf;
glm::mat4 block_transform;
- Texture block_label;
- SpriteModel label_sprite;
- glm::mat4 label_transform;
+ Text block_label;
bool block_visible;
#include "../app/FPSController.hpp"
#include "../app/IntervalTimer.hpp"
#include "../graphics/Font.hpp"
+#include "../graphics/Text.hpp"
#include "../model/geometry.hpp"
#include "../model/OutlineModel.hpp"
#include "../world/Block.hpp"
void HandleRelease(const SDL_MouseButtonEvent &);
void Handle(const SDL_MouseWheelEvent &);
- void Resize(const Viewport &);
-
void FaceBlock();
void TurnBlock();
OutlineModel outline;
glm::mat4 outline_transform;
- bool show_counter;
- Texture counter_tex;
- SpriteModel counter_sprite;
- glm::mat4 counter_transform;
- float counter_x;
+ Text counter_text;
Config config;
, block_buf()
, block_transform(1.0f)
, block_label()
-, label_sprite()
-, label_transform(1.0f)
, block_visible(false)
, crosshair() {
block_transform = glm::translate(block_transform, glm::vec3(50.0f, 50.0f, 0.0f));
});
crosshair.colors.resize(4, { 10.0f, 10.0f, 10.0f });
crosshair.Invalidate();
+
+ block_label.Position(
+ glm::vec3(50.0f, 85.0f, 0.0f),
+ Gravity::NORTH_WEST,
+ Gravity::NORTH
+ );
+ block_label.Foreground(glm::vec4(1.0f));
+ block_label.Background(glm::vec4(0.5f));
}
type.FillModel(block_buf, b.Transform());
block.Update(block_buf);
- font.Render(type.label.c_str(), 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_label.Set(font, type.label);
block_visible = type.visible;
}
world_prog.SetFogDensity(0.0f);
viewport.EnableInvertBlending();
- world_prog.SetM(viewport.CenterTransform());
+ viewport.SetCursor(glm::vec3(0.0f), Gravity::CENTER);
+ world_prog.SetM(viewport.Cursor());
crosshair.Draw();
if (block_visible) {
viewport.DisableBlending();
world_prog.SetM(block_transform);
block.Draw();
-
- BlendedSprite &sprite_prog = viewport.SpriteProgram();
- sprite_prog.SetM(label_transform);
- sprite_prog.SetTexture(block_label);
- sprite_prog.SetFG(glm::vec4(1.0f));
- sprite_prog.SetBG(glm::vec4(0.5f));
- label_sprite.Draw();
+ block_label.Render(viewport);
}
}
, aim_normal()
, outline()
, outline_transform(1.0f)
-, show_counter(false)
-, counter_tex()
-, counter_sprite()
-, counter_transform(1.0f)
-, counter_x(935.0f)
+, counter_text()
, config(config)
, place_timer(256)
, remove_timer(256)
, selection(1)
, fwd(0)
, rev(0) {
+ counter_text.Hide();
+ counter_text.Position(glm::vec3(-25.0f, 25.0f, 0.0f), Gravity::NORTH_EAST);
+ counter_text.Foreground(glm::vec4(1.0f));
+ counter_text.Background(glm::vec4(0.5f));
hud.Display(selection);
}
}
void Interface::ToggleCounter() {
- if ((show_counter = !show_counter)) {
+ counter_text.Toggle();
+ if (counter_text.Visible()) {
UpdateCounter();
}
}
std::stringstream s;
s << std::setprecision(3) << counter.AvgRunning() << "ms";
std::string text = s.str();
- font.Render(text.c_str(), counter_tex);
- glm::vec2 size(font.TextSize(text.c_str()));
- counter_sprite.LoadRect(size.x, size.y);
- counter_transform = glm::translate(glm::vec3(
- counter_x - size.x,
- 25.0f,
- 0.75f
- ));
+ counter_text.Set(font, text);
}
}
-void Interface::Resize(const Viewport &viewport) {
- counter_x = viewport.Width() - 25.0f;
-}
-
-
void Interface::Update(int dt) {
ctrl.Velocity(glm::vec3(fwd - rev) * config.move_velocity);
ctrl.Update(dt);
CheckAim();
}
- if (show_counter && counter.Changed()) {
+ if (counter_text.Visible() && counter.Changed()) {
UpdateCounter();
}
}
outline.Draw();
}
- if (show_counter) {
- BlendedSprite &sprite_prog = viewport.SpriteProgram();
- sprite_prog.SetM(counter_transform);
- sprite_prog.SetTexture(counter_tex);
- counter_sprite.Draw();
+ if (counter_text.Visible()) {
+ counter_text.Render(viewport);
}
hud.Render(viewport);