Rewrote the ansi parser to exactly callback on color setting, so now just need to clean this all up and fix a few little bugs.
This commit is contained in:
parent
96ee16e598
commit
89a70f398a
9 changed files with 274 additions and 126 deletions
127
render.cpp
127
render.cpp
|
@ -4,6 +4,7 @@
|
|||
#include <fmt/core.h>
|
||||
#include <array>
|
||||
#include "map.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace fmt;
|
||||
|
||||
|
@ -104,45 +105,113 @@ inline void configure_tile(const sf::Sprite &sprite, sf::FloatRect &sp_bounds,
|
|||
height_delta = bg_bounds.height > sp_bounds.width ? (bg_bounds.height - sp_bounds.height) / 2 : 0;
|
||||
}
|
||||
|
||||
void SFMLRender::render_text(const std::wstring &text, float x, float y) {
|
||||
void SFMLRender::render_grid(const std::wstring &text, float x, float y) {
|
||||
wchar_t last_tile = '#';
|
||||
sf::FloatRect sp_bounds;
|
||||
float width_delta = 0;
|
||||
float height_delta = 0;
|
||||
sf::Sprite &sprite = get_text_sprite(last_tile);
|
||||
const float start_x = x;
|
||||
sf::Color cur_fg = $default_fg;
|
||||
|
||||
// make a copy so we don't modify the cached one
|
||||
$ansi.parse(text, [&](sf::Color bg, sf::Color fg, wchar_t tile) {
|
||||
if(tile == '\n') {
|
||||
// don't bother processing newlines, just skip
|
||||
y += $line_spacing;
|
||||
x = start_x;
|
||||
} else if(tile == L'\r') {
|
||||
return; // skip these, just windows junk
|
||||
} else {
|
||||
$bg_sprite.setPosition({x, y});
|
||||
$ansi.parse(text, [&](sf::Color fg, sf::Color bg) {
|
||||
cur_fg = fg;
|
||||
$bg_sprite.setColor(bg);
|
||||
},
|
||||
|
||||
// only get a new sprite if the tile changed
|
||||
if(last_tile != tile) {
|
||||
last_tile = tile; // update last tile seen
|
||||
sprite = get_text_sprite(tile);
|
||||
configure_tile(sprite, sp_bounds, $bg_bounds, width_delta, height_delta);
|
||||
[&](wchar_t tile) {
|
||||
if(tile == '\n') {
|
||||
// don't bother processing newlines, just skip
|
||||
y += $line_spacing;
|
||||
x = start_x;
|
||||
} else if(tile == L'\r') {
|
||||
return; // skip these, just windows junk
|
||||
} else {
|
||||
$bg_sprite.setPosition({x, y});
|
||||
|
||||
// only get a new sprite if the tile changed
|
||||
if(last_tile != tile) {
|
||||
last_tile = tile; // update last tile seen
|
||||
sprite = get_text_sprite(tile);
|
||||
configure_tile(sprite, sp_bounds, $bg_bounds, width_delta, height_delta);
|
||||
}
|
||||
|
||||
sprite.setPosition({x+width_delta, y+height_delta});
|
||||
sprite.setColor(cur_fg);
|
||||
|
||||
$window.draw($bg_sprite);
|
||||
$window.draw(sprite);
|
||||
// next cell
|
||||
x += $base_glyph.advance;
|
||||
}
|
||||
|
||||
sprite.setPosition({x+width_delta, y+height_delta});
|
||||
sprite.setColor(fg);
|
||||
|
||||
$window.draw($bg_sprite);
|
||||
$window.draw(sprite);
|
||||
// next cell
|
||||
x += $base_glyph.advance;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SFMLRender::draw_text_ui(Panel &panel, bool with_border) {
|
||||
inline sf::FloatRect draw_chunk(sf::RenderWindow& window, sf::Text& text, float x, float y, std::wstring &out) {
|
||||
text.setString(out);
|
||||
text.setPosition(x, y);
|
||||
sf::FloatRect bounds = text.getLocalBounds();
|
||||
// need left,top,width,height for box to be accurate
|
||||
window.draw(text);
|
||||
out.clear();
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void SFMLRender::render_text(const std::wstring &text, float start_x, float start_y) {
|
||||
std::wstring out;
|
||||
float x = start_x;
|
||||
float y = start_y;
|
||||
enum State { START=1, BUILDING=2 };
|
||||
enum Event { NL=1, CHAR=3, SKIP=5 };
|
||||
State state = START;
|
||||
Event event = CHAR;
|
||||
|
||||
// start with the default_fg until it's changed
|
||||
$ui_text.setFillColor($default_fg);
|
||||
|
||||
$ansi.parse(text,
|
||||
[&](sf::Color fg, sf::Color bg){
|
||||
if(out.size() > 0 ) {
|
||||
auto bounds = draw_chunk($window, $ui_text, x, y, out);
|
||||
x += bounds.width;
|
||||
}
|
||||
$ui_text.setFillColor(fg);
|
||||
},
|
||||
[&](wchar_t tile) {
|
||||
if(tile == '\r') event = SKIP;
|
||||
else if(tile == '\n') event = NL;
|
||||
else event = CHAR;
|
||||
|
||||
switch(event) {
|
||||
case SKIP: break; // ignore it
|
||||
case NL: {
|
||||
if(state == START) {
|
||||
state = BUILDING;
|
||||
} else if(state == BUILDING) {
|
||||
sf::FloatRect bounds;
|
||||
|
||||
if(out.size() > 0) {
|
||||
bounds = draw_chunk($window, $ui_text, x, y, out);
|
||||
} else {
|
||||
bounds = $ui_text.getLocalBounds();
|
||||
}
|
||||
|
||||
y += bounds.height;
|
||||
x = start_x; // reset to the original position
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHAR:
|
||||
state = BUILDING;
|
||||
out += tile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void SFMLRender::draw_text(Panel &panel, bool with_border) {
|
||||
sf::RectangleShape backing(
|
||||
sf::Vector2f($ui_bounds.width * panel.width,
|
||||
$ui_bounds.height * panel.height));
|
||||
|
@ -159,13 +228,11 @@ void SFMLRender::draw_text_ui(Panel &panel, bool with_border) {
|
|||
|
||||
panel.render();
|
||||
const std::wstring &panelout = panel.to_string();
|
||||
$ui_text.setPosition(panel.x, panel.y);
|
||||
$ui_text.setString(panelout);
|
||||
$window.draw($ui_text);
|
||||
render_text(panelout, panel.x, panel.y);
|
||||
}
|
||||
|
||||
void SFMLRender::draw_screen(Panel &panel, float x, float y) {
|
||||
void SFMLRender::draw_grid(Panel &panel, float x, float y) {
|
||||
panel.render();
|
||||
const std::wstring &panelout = panel.to_string();
|
||||
render_text(panelout, panel.x + x, panel.y + y);
|
||||
render_grid(panelout, panel.x + x, panel.y + y);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue