From e86d474c7c415e9c33a6c452e500530f1f1e4707 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 30 Nov 2024 10:43:25 -0500 Subject: [PATCH] Now have more test for the base functionality but need to push render tests and find a way to test the GUI. I've also brought in sol2 for lua integration but not sure what to do with it. --- meson.build | 19 +++++++++-- panel.cpp | 2 ++ panel.hpp | 2 +- scratchpad/luatest.cpp | 17 ++++++++++ status.txt | 1 + systems.cpp | 2 +- tests/ansi_parser.cpp | 3 -- tests/collider.cpp | 2 ++ tests/map.cpp | 6 ++++ tests/panel.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++ tests/render.cpp | 38 +++++++++++++++++++++ tests/save.cpp | 4 +++ wraps/lua.wrap | 14 ++++++++ wraps/sol2.wrap | 11 +++++++ 14 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 scratchpad/luatest.cpp create mode 100644 tests/panel.cpp create mode 100644 tests/render.cpp create mode 100644 wraps/lua.wrap create mode 100644 wraps/sol2.wrap diff --git a/meson.build b/meson.build index 75ab421..0b52c9b 100644 --- a/meson.build +++ b/meson.build @@ -8,10 +8,15 @@ ftxui_screen = dependency('ftxui-screen') ftxui_dom = dependency('ftxui-dom') ftxui_component = dependency('ftxui-component') sfml = dependency('sfml') +lua = dependency('lua') +sol2 = dependency('sol2') -dependencies = [catch2, fmt, - ftxui_screen, ftxui_dom, ftxui_component, - json, sfml] +dependencies = [ + catch2, fmt, + ftxui_screen, ftxui_dom, + ftxui_component, json, + sfml, lua, sol2 +] runtests = executable('runtests', [ 'dbc.cpp', @@ -24,6 +29,7 @@ runtests = executable('runtests', [ 'config.cpp', 'save.cpp', 'panel.cpp', + 'render.cpp', 'tests/fsm.cpp', 'tests/dbc.cpp', 'tests/map.cpp', @@ -34,6 +40,8 @@ runtests = executable('runtests', [ 'tests/ansi_parser.cpp', 'tests/config.cpp', 'tests/save.cpp', + 'tests/render.cpp', + 'tests/panel.cpp', ], dependencies: dependencies) @@ -64,4 +72,9 @@ img2ansi = executable('img2ansi', [ ], dependencies: dependencies) +luatest = executable('luatest', [ + 'scratchpad/luatest.cpp' + ], +dependencies: dependencies) + test('tests', runtests) diff --git a/panel.cpp b/panel.cpp index fa822c6..30b9ec8 100644 --- a/panel.cpp +++ b/panel.cpp @@ -1,4 +1,5 @@ #include "panel.hpp" +#include "dbc.hpp" void Panel::resize(int w, int h) { $dirty = true; @@ -13,6 +14,7 @@ void Panel::set_renderer(Component renderer) { } void Panel::add(Component child) { + dbc::pre("must set_renderer first", $component != nullptr); $dirty = true; $component->Add(child); } diff --git a/panel.hpp b/panel.hpp index e2e427a..e6d5bd8 100644 --- a/panel.hpp +++ b/panel.hpp @@ -29,7 +29,7 @@ struct Panel { int border_px = UI_PANEL_BORDER_PX; bool $dirty = true; - Component $component; + Component $component = nullptr; Screen $screen; std::wstring_convert> $converter; std::wstring $screenout; diff --git a/scratchpad/luatest.cpp b/scratchpad/luatest.cpp new file mode 100644 index 0000000..1924a20 --- /dev/null +++ b/scratchpad/luatest.cpp @@ -0,0 +1,17 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include + +int main(int, char*[]) { + std::cout << "=== opening a state ===" << std::endl; + + sol::state lua; + // open some common libraries + lua.open_libraries(sol::lib::base, sol::lib::package); + lua.script("print('bark bark bark!')"); + + std::cout << std::endl; + + return 0; +} diff --git a/status.txt b/status.txt index 64babc6..d91ab3f 100644 --- a/status.txt +++ b/status.txt @@ -5,6 +5,7 @@ TODAY'S GOAL: * Better tests and more coverage. * Clean up and document as much code as possible. * Doxygen? Other docs tool? +* Add a method to render.cpp that sets terminal true color. TODO: * I can do headless windows in renderer for testing. diff --git a/systems.cpp b/systems.cpp index f139eca..445e893 100644 --- a/systems.cpp +++ b/systems.cpp @@ -149,7 +149,7 @@ void System::collision(DinkyECS::World &world, Player &player) { } void System::draw_entities(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y) { - auto &lighting = game_map.lighting(); + const auto &lighting = game_map.lighting(); world.query([&](const auto &ent, auto &pos, auto &tile) { if(pos.location.x >= cam_orig.x && pos.location.x <= cam_orig.x + view_x diff --git a/tests/ansi_parser.cpp b/tests/ansi_parser.cpp index 509eb6e..adaa1a4 100644 --- a/tests/ansi_parser.cpp +++ b/tests/ansi_parser.cpp @@ -60,9 +60,6 @@ TEST_CASE("test out ragel parser", "[gui]") { std::string colors = generate_colors(); std::wstring colors_utf = $converter.from_bytes(colors); - std::cout << colors; - - bool good = ansi.parse(colors_utf, [&](sf::Color color, sf::Color bgcolor){ // ignore color diff --git a/tests/collider.cpp b/tests/collider.cpp index 9a6dc1d..2bea07c 100644 --- a/tests/collider.cpp +++ b/tests/collider.cpp @@ -58,6 +58,8 @@ TEST_CASE("confirm basic collision operations", "[collision]") { REQUIRE(collider.occupied({12,12})); REQUIRE(collider.occupied({21,21})); REQUIRE(!collider.occupied({1,10})); + + REQUIRE(collider.get({12,12}) == player); } diff --git a/tests/map.cpp b/tests/map.cpp index f04747d..35327f9 100644 --- a/tests/map.cpp +++ b/tests/map.cpp @@ -68,6 +68,12 @@ TEST_CASE("lighting test", "[map]") { map.clear_light_target(light1); map.clear_light_target(light2); + + const auto &lighting = map.lighting(); + + // confirm light is set at least at and around the two points + REQUIRE(lighting[light1.y][light1.x] == lighting::LEVELS[source1.strength]); + REQUIRE(lighting[light2.y][light2.x] == lighting::LEVELS[source2.strength]); } TEST_CASE("camera control", "[map]") { diff --git a/tests/panel.cpp b/tests/panel.cpp new file mode 100644 index 0000000..6e28bfe --- /dev/null +++ b/tests/panel.cpp @@ -0,0 +1,75 @@ +#include +#include +#include // for ColorSupport, Color, Palette16, Palette256, TrueColor +#include // for hflow, paragraph, separator, hbox, vbox, filler, operator|, border, Element +#include "panel.hpp" +#include "ansi_parser.hpp" + +using namespace ftxui; +using namespace fmt; +using std::string; + +void test_ansi_parsing(Panel &panel) { + sf::Color default_fg(0,0,0); + sf::Color default_bg(100,100,100); + // this sets the Truecolor so need to do it first + ANSIParser ansi(default_fg, default_bg); + + bool good = ansi.parse(panel.to_string(), + [&](sf::Color color, sf::Color bgcolor){ + // ignore color + }, + [&](wchar_t ch) { + // ignore char + }); + + REQUIRE(good == true); +} + +TEST_CASE("can render a simple text panel", "[panel]") { + ftxui::Terminal::SetColorSupport(ftxui::Terminal::Color::TrueColor); + + Panel text_panel(0, 0, 20, 5); + + bool show_modal = false; + + auto buttons = Container::Horizontal({ + Button("OK", [&]{ show_modal = false; }), + Button("CANCEL", [&]{ show_modal = false; }), + }); + + auto text_box = Renderer([buttons]{ + return hbox({ + hflow( + vbox(text("I AM TEXT")), + buttons->Render() + )}); + }); + + text_panel.set_renderer(text_box); + text_panel.add(buttons); + + text_panel.resize(10,10); + text_panel.render(); + test_ansi_parsing(text_panel); + + const Screen &screen = text_panel.screen(); + REQUIRE(screen.dimx() == 10); + REQUIRE(screen.dimx() == 10); +} + +TEST_CASE("can render a simple grid panel", "[panel]") { + Terminal::SetColorSupport(Terminal::Color::TrueColor); + + Panel grid_panel(20, 20, 20, 5, true); + + auto text_box = Renderer([]{ + return hbox({ + hflow(vbox(text("I AM TEXT")))}); + }); + + grid_panel.set_renderer(text_box); + grid_panel.resize(10,10); + grid_panel.render(); + test_ansi_parsing(grid_panel); +} diff --git a/tests/render.cpp b/tests/render.cpp new file mode 100644 index 0000000..e6b7ad5 --- /dev/null +++ b/tests/render.cpp @@ -0,0 +1,38 @@ +#include +#include +#include "render.hpp" +#include "panel.hpp" + +using namespace ftxui; +using namespace fmt; +using std::string; + +void run_renderer(SFMLRender &renderer, Panel &panel) { + panel.render(); + renderer.display(); + REQUIRE(renderer.is_open() == true); + renderer.clear(); + renderer.draw(panel); +} + +TEST_CASE("can render a text or grid panel", "[render]") { + SFMLRender renderer; + + Panel panel(0, 0, 20, 5); + Panel grid(200, 200, 20, 5, true); + + auto text_box = Renderer([]{ + return hbox({ + hflow( + vbox(text("I AM TEXT")) + )}); + }); + + panel.set_renderer(text_box); + grid.set_renderer(text_box); + + run_renderer(renderer, panel); + run_renderer(renderer, grid); + + renderer.close(); +} diff --git a/tests/save.cpp b/tests/save.cpp index 83725ae..5ec7e45 100644 --- a/tests/save.cpp +++ b/tests/save.cpp @@ -66,6 +66,7 @@ TEST_CASE("basic save a world", "[save]") { world.set(player.entity, {0, 0}); world.set(player.entity, {100, 10}); world.set(player.entity, {"@"}); + world.set(player.entity, {102}); save::to_file("./savetest.world", world, map); @@ -95,4 +96,7 @@ TEST_CASE("basic save a world", "[save]") { REQUIRE(map.height() == in_map.height()); REQUIRE(map.$walls == in_map.$walls); REQUIRE(map.$input_map == in_map.$input_map); + + Inventory &inv = world.get(player.entity); + REQUIRE(inv.gold == 102); } diff --git a/wraps/lua.wrap b/wraps/lua.wrap new file mode 100644 index 0000000..9749598 --- /dev/null +++ b/wraps/lua.wrap @@ -0,0 +1,14 @@ +[wrap-file] +directory = lua-5.4.6 +source_url = https://www.lua.org/ftp/lua-5.4.6.tar.gz +source_filename = lua-5.4.6.tar.gz +source_hash = 7d5ea1b9cb6aa0b59ca3dde1c6adcb57ef83a1ba8e5432c0ecd06bf439b3ad88 +patch_filename = lua_5.4.6-5_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.6-5/get_patch +patch_hash = 755ec591b6b4739650ba6bb11b4feca2d221ab7f80f024dd625f50c8932ad76f +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/lua_5.4.6-5/lua-5.4.6.tar.gz +wrapdb_version = 5.4.6-5 + +[provide] +lua-5.4 = lua_dep +lua = lua_dep diff --git a/wraps/sol2.wrap b/wraps/sol2.wrap new file mode 100644 index 0000000..6bf0517 --- /dev/null +++ b/wraps/sol2.wrap @@ -0,0 +1,11 @@ +[wrap-git] +url = https://github.com/ThePhD/sol2.git +revision = v3.3.1 +depth = 1 +method = meson +# patch_filename = +# patch_hash = + + +[provide] +sol2 = sol2_dep