152 lines
4.2 KiB
C++
152 lines
4.2 KiB
C++
#include <cstdint>
|
|
|
|
#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<const uint8_t *>
|
|
|
|
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++;
|
|
}
|
|
}
|