Brought the lel-guecs tests over.

master
Zed A. Shaw 5 days ago
parent 29ec390478
commit 204490c1d9
  1. 46
      src/guecs/sfml/config.cpp
  2. 24
      src/guecs/sfml/config.hpp
  3. 77
      src/guecs/sfml/shaders.cpp
  4. 27
      src/guecs/sfml/shaders.hpp
  5. 81
      src/guecs/sfml/sound.cpp
  6. 26
      src/guecs/sfml/sound.hpp
  7. 62
      src/guecs/sfml/textures.cpp
  8. 28
      src/guecs/sfml/textures.hpp
  9. 20
      tests/guecs.cpp
  10. 72
      tests/lel.cpp
  11. 10
      tests/main.cpp
  12. 6
      tests/meson.build
  13. 36
      tests/shaders.cpp
  14. 24
      tests/sound.cpp
  15. 25
      tests/textures.cpp

@ -1,46 +0,0 @@
#include "guecs/sfml/config.hpp"
#include <fmt/core.h>
using nlohmann::json;
using fmt::format;
std::filesystem::path Config::BASE_DIR{"."};
Config::Config(const std::string src_path) : $src_path(src_path) {
std::ifstream infile(Config::path_to($src_path));
$config = json::parse(infile);
}
json &Config::operator[](const std::string &key) {
assert($config.contains(key) &&
"ERROR in config, key doesn't exist.");
return $config[key];
}
std::wstring Config::wstring(const std::string main_key, const std::string sub_key) {
assert($config.contains(main_key) && "ERROR wstring main/key in config, main_key doesn't exist.");
assert($config[main_key].contains(sub_key) && "ERROR wstring in config, main_key/key doesn't exist.");
const std::string& str_val = $config[main_key][sub_key];
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
return $converter.from_bytes(str_val);
}
std::vector<std::string> Config::keys() {
std::vector<std::string> the_fucking_keys;
for(auto& [key, value] : $config.items()) {
the_fucking_keys.push_back(key);
}
return the_fucking_keys;
}
void Config::set_base_dir(const char *optarg) {
Config::BASE_DIR.assign(optarg);
}
std::filesystem::path Config::path_to(const std::string& path) {
return Config::BASE_DIR / path;
}

@ -1,24 +0,0 @@
#pragma once
#include <nlohmann/json.hpp>
#include <fstream>
#include <codecvt>
#include <filesystem>
struct Config {
static std::filesystem::path BASE_DIR;
nlohmann::json $config;
std::string $src_path;
Config(const std::string src_path);
Config(nlohmann::json config, std::string src_path)
: $config(config), $src_path(src_path) {}
nlohmann::json &operator[](const std::string &key);
nlohmann::json &json() { return $config; };
std::wstring wstring(const std::string main_key, const std::string sub_key);
std::vector<std::string> keys();
static void set_base_dir(const char *optarg);
static std::filesystem::path path_to(const std::string& path);
};

@ -1,77 +0,0 @@
#include "guecs/sfml/shaders.hpp"
#include "guecs/sfml/config.hpp"
#include <SFML/Graphics/Image.hpp>
#include <fmt/core.h>
#include <memory>
namespace shaders {
using std::shared_ptr, std::make_shared;
static ShaderManager SMGR;
static bool INITIALIZED = false;
static int VERSION = 0;
inline void configure_shader_defaults(std::shared_ptr<sf::Shader> ptr) {
ptr->setUniform("source", sf::Shader::CurrentTexture);
}
bool load_shader(std::string name, nlohmann::json& settings) {
auto file_name = settings["file_name"];
auto file_path = Config::path_to(file_name);
auto ptr = std::make_shared<sf::Shader>();
bool good = ptr->loadFromFile(file_path, sf::Shader::Type::Fragment);
if(good) {
configure_shader_defaults(ptr);
SMGR.shaders.try_emplace(name, name, file_name, ptr);
}
return good;
}
void init() {
if(!INITIALIZED) {
assert(sf::Shader::isAvailable() && "no shaders?!");
INITIALIZED = true;
Config config("assets/shaders.json");
bool good = load_shader("ERROR", config["ERROR"]);
assert(good && "Failed to load ERROR shader. Look in assets/shaders.json");
for(auto& [name, settings] : config.json().items()) {
if(name == "ERROR") continue;
assert(!SMGR.shaders.contains(name) &&
"shader name duplicated in assets/shaders.json");
good = load_shader(name, settings);
if(!good) {
fmt::println("[SOUND] failed to load shader {}", name);
SMGR.shaders.insert_or_assign(name, SMGR.shaders.at("ERROR"));
}
}
}
}
std::shared_ptr<sf::Shader> get(const std::string& name) {
assert(INITIALIZED && "you forgot to shaders::init()");
assert(SMGR.shaders.contains(name) &&
"shader name not in assets/shaders.json");
auto& rec = SMGR.shaders.at(name);
return rec.ptr;
}
int reload() {
VERSION++;
INITIALIZED = false;
SMGR.shaders.clear();
init();
return VERSION;
}
bool updated(int my_version) {
return my_version != VERSION;
}
int version() {
return VERSION;
}
};

@ -1,27 +0,0 @@
#pragma once
#include <cstdint>
#include <vector>
#include <string>
#include <SFML/Graphics.hpp>
#include <unordered_map>
#include <memory>
#include <nlohmann/json.hpp>
namespace shaders {
struct Record {
std::string name;
std::string file_name;
std::shared_ptr<sf::Shader> ptr = nullptr;
};
struct ShaderManager {
std::unordered_map<std::string, Record> shaders;
};
std::shared_ptr<sf::Shader> get(const std::string& name);
void init();
bool load_shader(std::string& name, nlohmann::json& settings);
bool updated(int my_version);
int reload();
int version();
}

@ -1,81 +0,0 @@
#include "guecs/sfml/sound.hpp"
#include "guecs/sfml/config.hpp"
#include <fmt/core.h>
#include <cassert>
namespace sound {
static SoundManager SMGR;
static bool initialized = false;
static bool muted = false;
using namespace fmt;
using std::make_shared;
namespace fs = std::filesystem;
SoundPair& get_sound_pair(const std::string& name) {
assert(initialized && "You need to call sound::init() first");
if(SMGR.sounds.contains(name)) {
// get the sound from the sound map
return SMGR.sounds.at(name);
} else {
fmt::println("[SOUND] Attempted to stop {} sound but not available.", name);
return SMGR.sounds.at("blank");
}
}
void init() {
if(!initialized) {
Config assets("assets/config.json");
for(auto& el : assets["sounds"].items()) {
load(el.key(), Config::path_to(el.value()));
}
initialized = true;
}
}
void load(const std::string& name, const std::filesystem::path& sound_path) {
assert(fs::exists(sound_path) && "sound file does not exist");
// create the buffer and keep in the buffer map
auto buffer = make_shared<sf::SoundBuffer>(sound_path);
// set it on the sound and keep in the sound map
auto sound = make_shared<sf::Sound>(*buffer);
sound->setRelativeToListener(false);
sound->setPosition({0.0f, 0.0f, 1.0f});
SMGR.sounds.try_emplace(name, buffer, sound);
}
void play(const std::string& name, bool loop) {
if(muted) return;
auto& pair = get_sound_pair(name);
pair.sound->setLooping(loop);
// play it
pair.sound->play();
}
void stop(const std::string& name) {
auto& pair = get_sound_pair(name);
pair.sound->stop();
}
bool playing(const std::string& name) {
auto& pair = get_sound_pair(name);
auto status = pair.sound->getStatus();
return status == sf::SoundSource::Status::Playing;
}
void play_at(const std::string& name, float x, float y, float z) {
auto& pair = get_sound_pair(name);
pair.sound->setPosition({x, y, z});
pair.sound->play();
}
void mute(bool setting) {
muted = setting;
}
}

@ -1,26 +0,0 @@
#pragma once
#include <string>
#include <filesystem>
#include <memory>
#include <unordered_map>
#include <SFML/Audio.hpp>
namespace sound {
struct SoundPair {
std::shared_ptr<sf::SoundBuffer> buffer;
std::shared_ptr<sf::Sound> sound;
};
struct SoundManager {
std::unordered_map<std::string, SoundPair> sounds;
};
void init();
void load(const std::string& name, const std::filesystem::path& path);
void play(const std::string& name, bool loop=false);
void play_at(const std::string& name, float x, float y, float z);
void stop(const std::string& name);
void mute(bool setting);
bool playing(const std::string& name);
SoundPair& get_sound_pair(const std::string& name);
}

@ -1,62 +0,0 @@
#include "guecs/sfml/textures.hpp"
#include "guecs/sfml/config.hpp"
#include <SFML/Graphics/Image.hpp>
#include <fmt/core.h>
#include <memory>
namespace textures {
using std::shared_ptr, std::make_shared;
static TextureManager TMGR;
static bool initialized = false;
void load_sprites() {
Config assets("assets/config.json");
for(auto& [name, settings] : assets["sprites"].items()) {
auto file_name = settings["path"];
auto file_path = Config::path_to(file_name);
auto texture = make_shared<sf::Texture>(file_path);
texture->setSmooth(assets["graphics"]["smooth_textures"]);
auto sprite = make_shared<sf::Sprite>(*texture);
int width = settings["frame_width"];
int height = settings["frame_height"];
sf::Vector2i frame_size{width, height};
sprite->setTextureRect({{0,0}, frame_size});
TMGR.sprite_textures.try_emplace(name, sprite, texture, frame_size);
}
}
void init() {
if(!initialized) {
load_sprites();
initialized = true;
}
}
SpriteTexture get(const std::string& name) {
assert(initialized && "you forgot to call textures::init()");
assert(TMGR.sprite_textures.contains(name) &&
"!!!!! texture pack does not contain sprite");
auto result = TMGR.sprite_textures.at(name);
assert(result.sprite != nullptr &&
"bad sprite from textures::get named can't be null");
assert(result.texture != nullptr &&
"bad texture from textures::get named can't be null");
return result;
}
sf::Image load_image(const std::string& filename) {
sf::Image texture;
auto file_path = Config::path_to(filename);
bool good = texture.loadFromFile(file_path);
assert(good && "failed to load image file");
return texture;
}
};

@ -1,28 +0,0 @@
#pragma once
#include <cstdint>
#include <vector>
#include <string>
#include <SFML/Graphics.hpp>
#include <unordered_map>
#include <memory>
namespace textures {
struct SpriteTexture {
std::shared_ptr<sf::Sprite> sprite = nullptr;
std::shared_ptr<sf::Texture> texture = nullptr;
sf::Vector2i frame_size;
};
struct TextureManager {
std::vector<sf::Image> surfaces;
std::unordered_map<std::string, SpriteTexture> sprite_textures;
std::unordered_map<wchar_t, int> char_to_texture;
};
void init();
SpriteTexture get(const std::string& name);
sf::Image load_image(const std::string& filename);
}

@ -0,0 +1,20 @@
#include <fmt/core.h>
#include "guecs/ui.hpp"
#include <fmt/xchar.h>
#include <fuc2/testing.hpp>
using namespace guecs;
using namespace fuc2;
namespace guecs_tests {
void test_prototype() {
// accidentally gutted, will recover later
}
fuc2::Set TESTS{
.name="guecs",
.tests={
TEST(test_prototype),
}
};
}

@ -0,0 +1,72 @@
#include "guecs/lel.hpp"
#include <fmt/core.h>
#include <string>
#include <fuc2/testing.hpp>
using namespace fuc2;
namespace lel_tests {
void test_basic_ops() {
lel::Parser parser(0, 0, 500, 500);
bool good = parser.parse(
"[ label_1 | label3 | test1]"
"[ *(300,300)text1 | %(150)people | ^test2]"
"[ >label2 | _ | .test3]"
"[ =message | buttons | test4]");
CHECK(good);
for(size_t rowcount = 0; rowcount < parser.grid.size(); rowcount++) {
auto& row = parser.grid[rowcount];
for(size_t colcount = 0; colcount < row.size(); colcount++) {
auto &name = row[colcount];
if(name == "_") {
CHECK(!parser.cells.contains(name));
} else if(name == "_MAIN") {
// it's the main cell which covers the whole area
auto &cell = parser.cells.at(name);
CHECK(cell.row == 0);
CHECK(cell.col == 0);
CHECK(cell.x == parser.grid_x);
CHECK(cell.y == parser.grid_y);
CHECK(cell.w == parser.grid_w);
CHECK(cell.h == parser.grid_h);
} else {
auto &cell = parser.cells.at(name);
CHECK(cell.row == int(rowcount));
CHECK(cell.col == int(colcount));
}
}
}
CHECK(parser.cells.size() == 11);
CHECK(parser.cells.at("label2").right == true);
CHECK(parser.cells.at("text1").expand == true);
CHECK(parser.cells.at("text1").w == 300);
CHECK(parser.cells.at("text1").h == 300);
CHECK(parser.cells.at("people").expand == false);
CHECK(parser.cells.at("message").expand == false);
CHECK(parser.cells.at("message").center == true);
for(auto& [name, cell] : parser.cells) {
CHECK(cell.w > 0);
CHECK(cell.h > 0);
}
auto hit = parser.hit(10, 10);
CHECK(*hit == "label_1");
auto nohit = parser.hit(1000, 1000);
CHECK(!nohit);
CHECK(nohit == std::nullopt);
}
fuc2::Set TESTS{
.name="lel",
.tests={
TEST(test_basic_ops),
}
};
}

@ -2,6 +2,11 @@
TEST_SET(sol2_tests); TEST_SET(sol2_tests);
TEST_SET(builder_tests); TEST_SET(builder_tests);
TEST_SET(lel_tests);
TEST_SET(guecs_tests);
TEST_SET(shader_tests);
TEST_SET(sound_tests);
TEST_SET(texture_tests);
using namespace fuc2; using namespace fuc2;
@ -9,6 +14,11 @@ int main(int argc, char* argv[]) {
std::vector<fuc2::Set> tests{ std::vector<fuc2::Set> tests{
sol2_tests::TESTS, sol2_tests::TESTS,
builder_tests::TESTS, builder_tests::TESTS,
lel_tests::TESTS,
guecs_tests::TESTS,
shader_tests::TESTS,
sound_tests::TESTS,
texture_tests::TESTS,
}; };
return run_tests(tests, argc, argv); return run_tests(tests, argc, argv);

@ -2,4 +2,10 @@ tests = [
'tests/main.cpp', 'tests/main.cpp',
'tests/sol2_test.cpp', 'tests/sol2_test.cpp',
'tests/builder_test.cpp', 'tests/builder_test.cpp',
'tests/guecs.cpp',
'tests/lel.cpp',
'tests/main.cpp',
'tests/shaders.cpp',
'tests/sound.cpp',
'tests/textures.cpp',
] ]

@ -0,0 +1,36 @@
#include <fmt/core.h>
#include <string>
#include <fuc2/testing.hpp>
using namespace fuc2;
using namespace fmt;
namespace shader_tests {
void test_shader_loading() {
/*
shaders::init();
int version = shaders::version();
std::shared_ptr<sf::Shader> ui_shader = shaders::get("ui_shader");
auto other_test = shaders::get("ui_shader");
CHECK(ui_shader != nullptr);
CHECK(ui_shader == other_test);
CHECK(shaders::updated(version) == false);
int new_version = shaders::reload();
CHECK(version != shaders::version());
CHECK(version != new_version);
CHECK(shaders::version() == new_version);
CHECK(shaders::updated(version) == true);
version = new_version;
*/
}
fuc2::Set TESTS{
.name="shader",
.tests={
TEST(test_shader_loading),
}
};
}

@ -0,0 +1,24 @@
#include <fmt/core.h>
#include <string>
#include <fuc2/testing.hpp>
using namespace fuc2;
namespace sound_tests {
void test_sound_manager() {
/*
sound::init();
sound::play("blank");
sound::play_at("blank", 0.1, 0.1, 0.1);
*/
}
fuc2::Set TESTS{
.name="sound",
.tests={
TEST(test_sound_manager),
}
};
}

@ -0,0 +1,25 @@
#include <fmt/core.h>
#include <string>
#include <fuc2/testing.hpp>
using namespace fuc2;
namespace texture_tests {
void test_texture_management() {
/*
textures::init();
auto spider = textures::get("textures_test");
CHECK(spider.sprite != nullptr);
CHECK(spider.texture != nullptr);
auto image = textures::load_image("assets/textures_test.png");
*/
}
fuc2::Set TESTS{
.name="texture",
.tests={
TEST(test_texture_management),
}
};
}
Loading…
Cancel
Save