parent
6b3ce5eb3d
commit
0edd948101
@ -0,0 +1,262 @@ |
||||
#include <chrono> // for operator""s, chrono_literals |
||||
#include <thread> // for sleep_for |
||||
#include "dinkyecs.hpp" |
||||
#include "events.hpp" |
||||
#include "dbc.hpp" |
||||
#include "render.hpp" |
||||
#include "lights.hpp" |
||||
#include <filesystem> |
||||
#include <fcntl.h> |
||||
#include "constants.hpp" |
||||
#include "point.hpp" |
||||
#include <fmt/core.h> |
||||
#include <locale> |
||||
#include <codecvt> |
||||
#include <vector> |
||||
|
||||
using namespace fmt; |
||||
using namespace ftxui; |
||||
using namespace std::chrono_literals; |
||||
using lighting::LightSource, lighting::LightRender; |
||||
namespace fs = std::filesystem; |
||||
using std::string, std::wstring, std::vector; |
||||
|
||||
const Point GRID_SIZE={15,8}; |
||||
const int DEFAULT_FONT_SIZE=200; |
||||
|
||||
struct FontGrid { |
||||
size_t width; |
||||
size_t height; |
||||
vector<vector<string>> $chars; |
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter; |
||||
|
||||
FontGrid(size_t width, size_t height) : |
||||
width(width), height(height), |
||||
$chars(height, vector<string>(width, "")) |
||||
{ |
||||
} |
||||
|
||||
void render(wchar_t start_char, bool fill) { |
||||
wchar_t cur_char = start_char; |
||||
|
||||
for(size_t y = 0; y < height; ++y) { |
||||
for(size_t x = 0; x < width; ++x) { |
||||
if(!fill) { |
||||
cur_char += (x+1) * (y+1); |
||||
} |
||||
|
||||
wstring out_w{cur_char}; |
||||
$chars[y][x] = from_unicode(out_w); |
||||
} |
||||
} |
||||
} |
||||
|
||||
string from_unicode(wstring input) { |
||||
return $converter.to_bytes(input); |
||||
} |
||||
|
||||
wchar_t to_unicode_char(size_t x, size_t y) { |
||||
string input = $chars[y][x]; |
||||
return $converter.from_bytes(input)[0]; |
||||
} |
||||
|
||||
string at(size_t x, size_t y) { |
||||
return $chars[y][x]; |
||||
} |
||||
|
||||
unsigned int page_size() { |
||||
return width * height; |
||||
} |
||||
|
||||
}; |
||||
|
||||
struct WhatTheColor { |
||||
int h; |
||||
int s; |
||||
int v; |
||||
Component h_slider; |
||||
Component s_slider; |
||||
Component v_slider; |
||||
}; |
||||
|
||||
class GUI { |
||||
public: |
||||
DinkyECS::World& $world; |
||||
Panel $font_view; |
||||
Panel $status_ui; |
||||
Canvas $canvas; |
||||
SFMLRender $renderer; |
||||
FontGrid $font_grid; |
||||
wchar_t $start_char = L'\ua66b'; |
||||
wchar_t $fill_char = WCHAR_MIN; |
||||
WhatTheColor $fg_color; |
||||
WhatTheColor $bg_color; |
||||
Component $fg_settings; |
||||
Component $bg_settings; |
||||
|
||||
GUI(DinkyECS::World &world) : |
||||
$world(world), |
||||
$font_view(GAME_MAP_POS, 0, GRID_SIZE.x, GRID_SIZE.y, true), |
||||
$status_ui(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), |
||||
$font_grid(GRID_SIZE.x, GRID_SIZE.y), |
||||
$fg_color{.h=20, .s=50, .v=20}, |
||||
$bg_color{.h=100, .s=100, .v=100} |
||||
{ |
||||
resize_fonts(DEFAULT_FONT_SIZE); |
||||
$font_grid.render($start_char, false); |
||||
} |
||||
|
||||
void resize_fonts(int new_size) { |
||||
println("RESIZE MAP TO {}", new_size); |
||||
$renderer.resize_grid(new_size, $font_view); |
||||
// set canvas to best size
|
||||
$canvas = Canvas($font_view.width * 2, $font_view.height * 4); |
||||
} |
||||
|
||||
void draw_font_grid() { |
||||
for(size_t y = 0; y < $font_grid.height; y++) { |
||||
for(size_t x = 0; x < $font_grid.width; x++) { |
||||
$canvas.DrawText(x * 2, y * 4, $font_grid.at(x, y), [&](auto &pixel) { |
||||
pixel.foreground_color = Color::HSV($fg_color.h, $fg_color.s, $fg_color.v); |
||||
pixel.background_color = Color::HSV($bg_color.h, $bg_color.s, $bg_color.v); |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void create_renderer() { |
||||
$renderer.init_terminal(); |
||||
|
||||
$font_view.set_renderer(Renderer([&]{ |
||||
draw_font_grid(); |
||||
return canvas($canvas); |
||||
})); |
||||
|
||||
$fg_color.h_slider = Slider("FG H:", &$fg_color.h, 0, 255, 1); |
||||
$fg_color.s_slider = Slider("FG S:", &$fg_color.s, 0, 255, 1); |
||||
$fg_color.v_slider = Slider("FG V:", &$fg_color.v, 0, 255, 1); |
||||
$bg_color.h_slider = Slider("BG H:", &$bg_color.h, 0, 255, 1); |
||||
$bg_color.s_slider = Slider("BG S:", &$bg_color.s, 0, 255, 1); |
||||
$bg_color.v_slider = Slider("BG V:", &$bg_color.v, 0, 255, 1); |
||||
|
||||
$status_ui.set_renderer(Renderer([&]{ |
||||
return hbox({ |
||||
hflow( |
||||
vbox( |
||||
text(format("\\u{:x}", int($fill_char))) | border, |
||||
separator(), |
||||
text(format("FG H: {}, S: {}, V: {}", |
||||
$fg_color.h, $fg_color.s, $fg_color.v)) | border, |
||||
$fg_color.h_slider->Render(), |
||||
separator(), |
||||
$fg_color.s_slider->Render(), |
||||
separator(), |
||||
$fg_color.v_slider->Render(), |
||||
separator(), |
||||
text(format("BG H: {}, S: {}, V: {}", |
||||
$bg_color.h, $bg_color.s, $bg_color.v)) | border, |
||||
$bg_color.h_slider->Render(), |
||||
separator(), |
||||
$bg_color.s_slider->Render(), |
||||
separator(), |
||||
$bg_color.v_slider->Render() |
||||
) | flex_grow |
||||
), |
||||
separator(), |
||||
hbox(), |
||||
}); |
||||
})); |
||||
|
||||
$status_ui.add($fg_color.h_slider); |
||||
$status_ui.add($fg_color.s_slider); |
||||
$status_ui.add($fg_color.v_slider); |
||||
$status_ui.add($bg_color.h_slider); |
||||
$status_ui.add($bg_color.s_slider); |
||||
$status_ui.add($bg_color.v_slider); |
||||
} |
||||
|
||||
void shutdown() { |
||||
$renderer.close(); |
||||
} |
||||
|
||||
void select_cell(Point pos) { |
||||
$fill_char = $font_grid.to_unicode_char(pos.x, pos.y); |
||||
$font_grid.render($fill_char, true); |
||||
} |
||||
|
||||
void deselect_cell() { |
||||
$font_grid.render($start_char, false); |
||||
} |
||||
|
||||
bool handle_ui_events() { |
||||
bool event_happened; |
||||
using KB = sf::Keyboard; |
||||
using MOUSE = sf::Mouse; |
||||
sf::Event event; |
||||
int font_size = $renderer.font_size(); |
||||
|
||||
while($renderer.poll_event(event)) { |
||||
if(event.type == sf::Event::Closed) { |
||||
shutdown(); |
||||
return true; |
||||
} else if(event.type == sf::Event::KeyPressed) { |
||||
println("KEY PRESSED"); |
||||
if(KB::isKeyPressed(KB::Up)) { |
||||
$start_char = std::min(WCHAR_MAX, $start_char + $font_grid.page_size()); |
||||
$font_grid.render($start_char, false); |
||||
event_happened = true; |
||||
} else if(KB::isKeyPressed(KB::Down)) { |
||||
$start_char = std::max(WCHAR_MIN+1, $start_char - $font_grid.page_size()); |
||||
$font_grid.render($start_char, false); |
||||
} else if(KB::isKeyPressed(KB::Equal)) { |
||||
resize_fonts(font_size + 10); |
||||
} else if(KB::isKeyPressed(KB::Hyphen)) { |
||||
resize_fonts(font_size - 10); |
||||
event_happened = true; |
||||
} |
||||
} else if(MOUSE::isButtonPressed(MOUSE::Left)) { |
||||
Point pos; |
||||
if($renderer.mouse_position($font_view, pos)) { |
||||
select_cell(pos); |
||||
event_happened = true; |
||||
} else if($renderer.mouse_position($status_ui, pos)) { |
||||
$status_ui.mouse_click(Mouse::Button::Left, pos); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return event_happened; |
||||
} |
||||
|
||||
void render_scene() { |
||||
$renderer.clear(); |
||||
|
||||
$status_ui.render(); |
||||
$renderer.draw($status_ui); |
||||
|
||||
$font_view.render(); |
||||
$renderer.draw($font_view); |
||||
|
||||
$renderer.display(); |
||||
} |
||||
}; |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
DinkyECS::World world; |
||||
|
||||
GUI gui(world); |
||||
|
||||
gui.create_renderer(); |
||||
|
||||
do { |
||||
gui.render_scene(); |
||||
|
||||
if(gui.handle_ui_events()) { |
||||
println("THERE WERE EVENTS"); |
||||
} |
||||
|
||||
std::this_thread::sleep_for(10ms); |
||||
} while(gui.$renderer.is_open()); |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue