srb2::Draw::TextElement: add parse method

- Parse and translate special characters
- Currently supported:
  - Button codes
    - <up>
    - <down>
    - <right>
    - <left>
    - <r>
    - <l>
    - <start>
    - <a>
    - <b>
    - <c>
    - <x>
    - <y>
    - <z>
  - All button codes can be suffixed with '_pressed' or
    '_animated'
    - E.g. <b_pressed> or <start_animated>
This commit is contained in:
James R 2024-01-16 06:21:13 -08:00
parent 0d765d9fd1
commit bfa6e4f401
2 changed files with 84 additions and 0 deletions

View file

@ -7,6 +7,8 @@
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#include <unordered_map>
#include "doomdef.h" // skincolornum_t
#include "doomtype.h"
#include "hu_stuff.h"
@ -27,6 +29,79 @@ int Draw::TextElement::width() const
return font_ ? font_width(*font_, default_font_flags(*font_) | flags_.value_or(0), string_.c_str()) / FRACUNIT : 0;
}
Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
{
static const std::unordered_map<std::string_view, char> translation = {
#define BUTTON(str, lower_bits) \
{str, 0xB0 | lower_bits},\
{str "_animated", 0xA0 | lower_bits},\
{str "_pressed", 0x90 | lower_bits}
BUTTON("up", 0x00),
BUTTON("down", 0x01),
BUTTON("right", 0x02),
BUTTON("left", 0x03),
BUTTON("r", 0x07),
BUTTON("l", 0x08),
BUTTON("start", 0x09),
BUTTON("a", 0x0A),
BUTTON("b", 0x0B),
BUTTON("c", 0x0C),
BUTTON("x", 0x0D),
BUTTON("y", 0x0E),
BUTTON("z", 0x0F),
#undef BUTTON
};
string_.clear();
string_.reserve(raw.size());
using std::size_t;
using std::string_view;
for (;;)
{
size_t p = raw.find('<');
// Copy characters until the start tag
string_.append(raw.substr(0, p));
if (p == raw.npos)
{
break; // end of string
}
raw.remove_prefix(p);
// Find end tag
p = raw.find('>');
if (p == raw.npos)
{
break; // no end tag
}
string_view code = raw.substr(1, p - 1);
if (auto it = translation.find(code); it != translation.end())
{
string_.push_back(it->second); // replace with character code
}
else
{
string_.append(raw.substr(0, p + 1)); // code not found, leave text verbatim
}
raw.remove_prefix(p + 1); // past end of tag
}
return *this;
}
void Chain::patch(patch_t* patch) const
{
const auto _ = Clipper(*this);

View file

@ -11,6 +11,7 @@
#define __V_DRAW_HPP__
#include <string>
#include <string_view>
#include <optional>
#include <utility>
@ -97,6 +98,14 @@ public:
return *this;
}
TextElement& parse(std::string_view string);
template <class... Args>
TextElement& parse(fmt::format_string<Args...> format, Args&&... args)
{
return parse(fmt::format(format, args...));
}
TextElement& font(Font font)
{
font_ = font;