1 #include "FixedText.hpp"
2 #include "MessageBox.hpp"
3 #include "Progress.hpp"
5 #include "TextInput.hpp"
7 #include "../graphics/Font.hpp"
8 #include "../graphics/Viewport.hpp"
19 MessageBox::MessageBox(const Font &f)
24 , adv(0.0f, font.LineSkip(), 0.0f)
25 , bg(1.0f, 1.0f, 1.0f, 0.0f)
26 , fg(1.0f, 1.0f, 1.0f, 1.0f)
27 , grav(Gravity::NORTH_WEST)
32 void MessageBox::Position(const glm::vec3 &p, Gravity g) noexcept {
35 if (get_y(g) == Align::END) {
36 adv.y = -font.LineSkip();
38 adv.y = font.LineSkip();
40 for (Text &txt : lines) {
46 void MessageBox::PushLine(const char *text) {
47 lines.emplace_front();
48 Text &txt = lines.front();
52 while (lines.size() > max_lines) {
60 PrimitiveMesh::Buffer bg_buf;
64 void MessageBox::Recalc() {
65 size = glm::vec2(0.0f, 0.0f);
66 for (const Text &line : lines) {
67 size.x = max(size.x, line.Size().x);
68 size.y += line.Size().y;
70 bg_buf.FillRect(size.x, size.y, bg, align(grav, size));
71 bg_mesh.Update(bg_buf);
76 void MessageBox::Render(Viewport &viewport) noexcept {
77 viewport.SetCursor(pos, grav);
78 if (bg.a > numeric_limits<float>::epsilon()) {
82 PlainColor &prog = viewport.HUDColorProgram();
83 prog.SetM(viewport.Cursor());
84 bg_mesh.DrawTriangles();
85 viewport.MoveCursor(glm::vec3(0.0f, 0.0f, -1.0f));
87 BlendedSprite &prog = viewport.SpriteProgram();
88 prog.SetBG(glm::vec4(0.0f));
89 prog.SetFG(glm::vec4(fg) * (1.0f / 255.0f));
90 for (Text &txt : lines) {
91 prog.SetM(viewport.Cursor());
93 viewport.MoveCursor(adv);
98 Progress::Progress(Font &font) noexcept
101 , tpl("%d/%d (%d%%)") {
107 char buf[128] = { '\0' };
111 void Progress::Update(int current, int total) {
112 snprintf(buf, sizeof(buf), tpl, current, total, current * 100 / total);
116 void Progress::Render(Viewport &viewport) noexcept {
117 text.Render(viewport);
121 Text::Text() noexcept
125 , pivot(Gravity::NORTH_WEST)
130 FixedText::FixedText() noexcept
132 , bg(1.0f, 1.0f, 1.0f, 0.0f)
133 , fg(1.0f, 1.0f, 1.0f, 1.0f)
135 , grav(Gravity::NORTH_WEST)
140 void Text::Set(const Font &font, const char *text) {
141 font.Render(text, tex);
142 size = font.TextSize(text);
148 SpriteMesh::Buffer sprite_buf;
152 void Text::Update() {
153 sprite_buf.LoadRect(size.x, size.y, align(pivot, size));
154 sprite.Update(sprite_buf);
158 void FixedText::Render(Viewport &viewport) noexcept {
159 BlendedSprite &prog = viewport.SpriteProgram();
160 viewport.SetCursor(pos, grav);
161 prog.SetM(viewport.Cursor());
164 Text::Render(viewport);
167 void Text::Render(Viewport &viewport) noexcept {
171 BlendedSprite &prog = viewport.SpriteProgram();
172 prog.SetTexture(tex);
177 TextInput::TextInput(const Font &font)
184 , bg(1.0f, 1.0f, 1.0f, 0.0f)
185 , fg(1.0f, 1.0f, 1.0f, 1.0f)
187 , size(font.LineSkip())
188 , gravity(Gravity::NORTH_WEST)
196 void TextInput::Focus(Viewport &viewport) noexcept {
197 SDL_StartTextInput();
200 glm::vec2 p(viewport.GetPosition(glm::vec2(position), gravity));
206 SDL_SetTextInputRect(&rect);
209 void TextInput::Blur() noexcept {
214 void TextInput::Clear() noexcept {
220 void TextInput::Backspace() noexcept {
221 string::size_type previous(cursor);
223 input.erase(cursor, previous - cursor);
227 void TextInput::Delete() noexcept {
228 string::size_type previous(cursor);
230 input.erase(previous, cursor - previous);
235 void TextInput::MoveBegin() noexcept {
239 void TextInput::MoveBackward() noexcept {
240 if (AtBegin()) return;
242 while (cursor > 0 && (input[cursor] & 0xC0) == 0x80) {
247 void TextInput::MoveForward() noexcept {
250 while (cursor <= input.size() && (input[cursor] & 0xC0) == 0x80) {
255 void TextInput::MoveEnd() noexcept {
256 cursor = input.size();
259 void TextInput::Insert(const char *str) {
260 size_t len = strlen(str);
261 input.insert(cursor, str, len);
266 bool TextInput::AtBegin() const noexcept {
270 bool TextInput::AtEnd() const noexcept {
271 return cursor == input.size();
274 void TextInput::Position(const glm::vec3 &p, Gravity g, Gravity pv) noexcept {
281 void TextInput::Width(float w) noexcept {
286 void TextInput::Handle(const SDL_TextInputEvent &e) {
290 void TextInput::Handle(const SDL_TextEditingEvent &) {
294 void TextInput::Refresh() {
296 bg_buf.FillRect(size.x, size.y, bg, align(gravity, size));
297 bg_mesh.Update(bg_buf);
302 bg_buf.Reserve(2, 2);
303 bg_buf.vertices.emplace_back(0.0f, 0.0f, 0.0f);
304 bg_buf.vertices.emplace_back(0.0f, float(font.LineSkip()), 0.0f);
305 bg_buf.colors.resize(2, fg);
306 bg_buf.indices.push_back(0);
307 bg_buf.indices.push_back(1);
308 cursor_mesh.Update(bg_buf);
310 dirty_cursor = false;
313 if (!input.empty()) {
314 text.Set(font, input.c_str());
320 void TextInput::Render(Viewport &viewport) {
322 viewport.SetCursor(position, gravity);
323 if (bg.a > numeric_limits<float>::epsilon()) {
324 viewport.EnableAlphaBlending();
325 PlainColor &prog = viewport.HUDColorProgram();
326 prog.SetM(viewport.Cursor());
327 bg_mesh.DrawTriangles();
328 viewport.MoveCursor(glm::vec3(0.0f, 0.0f, -1.0f));
330 if (!input.empty()) {
331 BlendedSprite &prog = viewport.SpriteProgram();
332 prog.SetBG(glm::vec4(0.0f));
333 prog.SetFG(glm::vec4(fg) * (1.0f / 255.0f));
334 prog.SetM(viewport.Cursor());
335 text.Render(viewport);
338 glm::vec2 offset(0.0f);
339 if (input.empty() || AtBegin()) {
341 offset = -align(text.Pivot(), glm::vec2(0.0f, font.LineSkip()));
342 } else if (AtEnd()) {
343 offset = -align(text.Pivot(), text.Size(), glm::vec2(-text.Size().x, 0.0f));
345 offset = -align(text.Pivot(), text.Size(), glm::vec2(-font.TextSize(input.substr(0, cursor).c_str()).x, 0.0f));
347 viewport.MoveCursor(glm::vec3(offset, -1.0f));
348 PlainColor &prog = viewport.HUDColorProgram();
349 prog.SetM(viewport.Cursor());
350 cursor_mesh.DrawLines();