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