|  |  |  | #include "render.hpp"
 | 
					
						
							|  |  |  | #include "ansi_parser.hpp"
 | 
					
						
							|  |  |  | #include <cmath>
 | 
					
						
							|  |  |  | #include <fmt/core.h>
 | 
					
						
							|  |  |  | #include <array>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::array<sf::Color, 10> VALUES{
 | 
					
						
							|  |  |  |   sf::Color{1, 4, 2},  // black
 | 
					
						
							|  |  |  |   sf::Color{9, 29, 16}, // dark dark
 | 
					
						
							|  |  |  |   sf::Color{14, 50, 26}, // dark mid
 | 
					
						
							|  |  |  |   sf::Color{0, 109, 44}, // dark light
 | 
					
						
							|  |  |  |   sf::Color{63, 171, 92}, // mid
 | 
					
						
							|  |  |  |   sf::Color{161, 217, 155}, // light dark
 | 
					
						
							|  |  |  |   sf::Color{199, 233, 192}, // light mid
 | 
					
						
							|  |  |  |   sf::Color{229, 245, 224}, // light light
 | 
					
						
							|  |  |  |   sf::Color{255, 255, 255}, // white
 | 
					
						
							|  |  |  |   sf::Color::Transparent, // white
 | 
					
						
							|  |  |  | };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sf::Color SFMLRender::color(int val) {
 | 
					
						
							|  |  |  |   return VALUES[size_t(val)];
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sf::Color SFMLRender::color(Value val) {
 | 
					
						
							|  |  |  |   return VALUES[size_t(val)];
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SFMLRender::SFMLRender(Canvas &canvas, Screen &map_screen, Screen &screen) :
 | 
					
						
							|  |  |  |   $window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"),
 | 
					
						
							|  |  |  |   $map_font_size(BASE_MAP_FONT_SIZE),
 | 
					
						
							|  |  |  |   $line_spacing(0),
 | 
					
						
							|  |  |  |   $canvas(canvas),
 | 
					
						
							|  |  |  |   $map_screen(map_screen),
 | 
					
						
							|  |  |  |   $screen(screen),
 | 
					
						
							|  |  |  |   $default_fg(color(Value::LIGHT_MID)),
 | 
					
						
							|  |  |  |   $default_bg(color(Value::BLACK)),
 | 
					
						
							|  |  |  |   $ansi($default_fg, $default_bg)
 | 
					
						
							|  |  |  | {
 | 
					
						
							|  |  |  |   // force true color, but maybe I want to support different color sets
 | 
					
						
							|  |  |  |   $font.loadFromFile("./assets/text.otf");
 | 
					
						
							|  |  |  |   $ui_text.setFont($font);
 | 
					
						
							|  |  |  |   $ui_text.setPosition(0,0);
 | 
					
						
							|  |  |  |   $ui_text.setCharacterSize(UI_FONT_SIZE);
 | 
					
						
							|  |  |  |   $ui_text.setFillColor(color(Value::LIGHT_LIGHT));
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sf::Sprite &SFMLRender::get_text_sprite(wchar_t tile) {
 | 
					
						
							|  |  |  |   if(!$sprites.contains(tile)) {
 | 
					
						
							|  |  |  |     sf::Glyph glyph = $font.getGlyph(tile, $map_font_size, false);
 | 
					
						
							|  |  |  |     // WARNING! we actually have to do this here because SFML caches
 | 
					
						
							|  |  |  |     // the glyphs on the font texture, so this gets loaded each time
 | 
					
						
							|  |  |  |     // we get a new glyph from the font.
 | 
					
						
							|  |  |  |     $font_texture = $font.getTexture($map_font_size);
 | 
					
						
							|  |  |  |     sf::Sprite sprite($font_texture);
 | 
					
						
							|  |  |  |     sprite.setTextureRect(glyph.textureRect);
 | 
					
						
							|  |  |  |     $sprites[tile] = sprite;
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return $sprites[tile];
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool SFMLRender::resize_map(int new_size) {
 | 
					
						
							|  |  |  |   if(MIN_FONT_SIZE < new_size && new_size < MAX_FONT_SIZE) {
 | 
					
						
							|  |  |  |     $sprites.clear(); // need to reset the sprites for the new size
 | 
					
						
							|  |  |  |     $map_font_size = new_size;
 | 
					
						
							|  |  |  |     $base_glyph = $font.getGlyph(BG_TILE, $map_font_size, false);
 | 
					
						
							|  |  |  |     $line_spacing = $font.getLineSpacing($map_font_size);
 | 
					
						
							|  |  |  |     $bg_sprite = get_text_sprite(BG_TILE);
 | 
					
						
							|  |  |  |     $bg_bounds = $bg_sprite.getLocalBounds();
 | 
					
						
							|  |  |  |     return true;
 | 
					
						
							|  |  |  |   } else {
 | 
					
						
							|  |  |  |     // something else here
 | 
					
						
							|  |  |  |     return false;
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SFMLRender::draw_main_ui() {
 | 
					
						
							|  |  |  |   std::string screenout = $screen.ToString();
 | 
					
						
							|  |  |  |   std::wstring main_screen_utf8 = $converter.from_bytes(screenout);
 | 
					
						
							|  |  |  |   $ui_text.setString(main_screen_utf8);
 | 
					
						
							|  |  |  |   $window.draw($ui_text);
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SFMLRender::render_text(std::string &text, float x, float y) {
 | 
					
						
							|  |  |  |   // 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 = GAME_MAP_POS;
 | 
					
						
							|  |  |  |     } else if(tile == L'\r') {
 | 
					
						
							|  |  |  |         return; // skip these, just windows junk
 | 
					
						
							|  |  |  |     } else {
 | 
					
						
							|  |  |  |       $bg_sprite.setPosition({x, y});
 | 
					
						
							|  |  |  |       sf::Sprite &sprite = get_text_sprite(tile);
 | 
					
						
							|  |  |  |       $bg_sprite.setColor(bg);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // should look into caching all this instead of calcing it each time
 | 
					
						
							|  |  |  |       auto sp_bounds = sprite.getLocalBounds();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // calculate where to center the sprite, but only if it's smaller
 | 
					
						
							|  |  |  |       auto width_delta = $bg_bounds.width > sp_bounds.width ? ($bg_bounds.width - sp_bounds.width) / 2 : 0;
 | 
					
						
							|  |  |  |       auto height_delta = $bg_bounds.height > sp_bounds.width ? ($bg_bounds.height - sp_bounds.height) / 2 : 0;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       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_screen(bool clear, float map_off_x, float map_off_y) {
 | 
					
						
							|  |  |  |   if(clear) $window.clear();
 | 
					
						
							|  |  |  |   draw_main_ui();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   std::string map_screenout = $map_screen.ToString();
 | 
					
						
							|  |  |  |   render_text(map_screenout, GAME_MAP_POS+map_off_x, map_off_y);
 | 
					
						
							|  |  |  |   $window.display();
 | 
					
						
							|  |  |  | }
 |