#include #include "graphic.hpp" #include "coordinates.hpp" #include "font.hpp" #include "start_size.hpp" #include "control.hpp" struct dialog_border { static constexpr uint8_t corner_top_left = 105; static constexpr uint8_t corner_top_right = 106; static constexpr uint8_t corner_bot_left = 107; static constexpr uint8_t corner_bottom_right = 108; static constexpr uint8_t vertical_end_cap = 109; static constexpr uint8_t vertical = 110; static constexpr uint8_t horizontal = 111; }; struct battle_border { static constexpr uint8_t horizontal = 96; static constexpr uint8_t corner_bottom_right = 97; static constexpr uint8_t arrow_right = 98; static constexpr uint8_t vertical = 99; static constexpr uint8_t corner_bot_left = 100; static constexpr uint8_t three_dots = 101; static constexpr uint8_t vertical_end_cap = 102; static constexpr uint8_t level = 103; static constexpr uint8_t arrow_left = 104; }; #define S reinterpret_cast void draw_text(const uint32_t base_pattern, const uint8_t * text, const uint32_t x, const uint32_t y) { uint8_t i = 0, x_o = 0; uint8_t c; auto draw_ligature = [&](const uint8_t * l_text) { uint8_t j = 0; uint8_t d; while ((d = l_text[j++]) != 0) put_char(base_pattern, x + x_o++, y, ascii_to_font(d)); }; while ((c = text[i++]) != 0) { switch (c) { case ligatures_t::pkmn: { static const uint8_t * pkmn = S("\xb2\xb3"); draw_ligature(pkmn); } break; case ligatures_t::poke: { static const uint8_t * poke = S("POK\xe9"); draw_ligature(poke); } break; case ligatures_t::trainer: { static const uint8_t * trainer = S("TRAINER"); draw_ligature(trainer); } break; default: put_char(base_pattern, x + x_o++, y, ascii_to_font(c)); break; } } } #undef S void draw_box_border(const uint32_t base_pattern, const screen_cell_t& top_left, const screen_cell_t& bottom_right) { // place corners put_char(base_pattern, top_left.x, top_left.y, dialog_border::corner_top_left); put_char(base_pattern, bottom_right.x, top_left.y, dialog_border::corner_top_right); put_char(base_pattern, bottom_right.x, bottom_right.y, dialog_border::corner_bottom_right); put_char(base_pattern, top_left.x, bottom_right.y, dialog_border::corner_bot_left); for (uint32_t y = top_left.y + 1; y < bottom_right.y; y++) { // left vertical bar put_char(base_pattern, top_left.x, y, dialog_border::vertical); // right vertical bar put_char(base_pattern, bottom_right.x, y, dialog_border::vertical); } for (uint32_t x = top_left.x + 1; x < bottom_right.x; x++) { // top horizontal bar put_char(base_pattern, x, top_left.y, dialog_border::horizontal); // bottom horizontal bar put_char(base_pattern, x, bottom_right.y, dialog_border::horizontal); } } void draw_box_background(const uint32_t base_pattern, const screen_cell_t& top_left, const screen_cell_t& bottom_right) { for (uint32_t x = top_left.x + 1; x < bottom_right.x; x++) { for (uint32_t y = top_left.y + 1; y < bottom_right.y; y++) { put_char(base_pattern, x, y, ascii_to_font(' ')); } } } void dialog_t::draw(const uint32_t base_pattern, const start_size_t& text) { draw_box_border(base_pattern, top_left, bottom_right); draw_box_background(base_pattern, top_left, bottom_right); uint32_t ix = 0; uint32_t x = top_left.x + 1; uint32_t y = top_left.y + 2; // ignore C-string null terminator while (ix < (text.size - 1)) { const uint8_t c = text.start[ix]; switch (c) { case control_t::text: break; case control_t::done: break; case control_t::prompt: break; case control_t::page: break; case control_t::next: [[fallthrough]]; case control_t::line: while (x < bottom_right.x) { put_char(base_pattern, x, y, ascii_to_font(' ')); x++; } x = top_left.x + 1; y += 2; break; case control_t::para: [[fallthrough]]; case control_t::cont: // fixme: ix = text.size; break; default: put_char(base_pattern, x, y, ascii_to_font(c)); x += 1; break; } ix++; } }