#include "textures.hpp" #include #include "dbc.hpp" #include #include "config.hpp" #include "constants.hpp" #include namespace textures { using std::shared_ptr, std::make_shared, nlohmann::json, std::string; static TextureManager TMGR; static bool initialized = false; void load_sprite_textures(SpriteTextureMap &mapping, json &config, bool smooth) { for(auto& [name, settings] : config.items()) { auto texture = make_shared(settings["path"]); texture->setSmooth(smooth); auto sprite = make_shared(*texture); int width = settings["frame_width"]; int height = settings["frame_height"]; dbc::check(width % 2 == 0, fmt::format("sprite {} has invalid frame size {}", name, width)); sf::Vector2i frame_size{width, height}; sprite->setTextureRect({{0,0}, frame_size}); dbc::check(!mapping.contains(name), fmt::format("duplicate sprite/icon name {}", (string)name)); mapping.try_emplace(name, sprite, texture, frame_size); } } void load_sprites() { Config sprites("assets/config.json"); bool smooth = sprites["graphics"]["smooth_textures"]; load_sprite_textures(TMGR.sprite_textures, sprites["sprites"], smooth); Config icons("assets/icons.json"); load_sprite_textures(TMGR.icon_textures, icons.json(), smooth); } inline void resize_shit(size_t size) { TMGR.surfaces.resize(size); TMGR.ceilings.resize(size); TMGR.map_tile_set.resize(size); TMGR.ambient_light.resize(size); } void load_tiles() { Config assets("assets/tiles.json"); auto &tiles = assets.json(); resize_shit(tiles.size()); for(auto &el : tiles.items()) { auto &config = el.value(); const string& texture_fname = config["texture"]; size_t surface_i = config["id"]; dbc::check(!TMGR.name_to_id.contains(el.key()), fmt::format("duplicate key in textures {}", (string)el.key())); TMGR.name_to_id.insert_or_assign(el.key(), surface_i); if(surface_i >= tiles.size()) { resize_shit(surface_i + 1); } TMGR.map_tile_set[surface_i] = config["display"]; TMGR.ambient_light[surface_i] = config["light"]; TMGR.surfaces[surface_i] = load_image(texture_fname); // NOTE: ceilings defaults to 0 which is floor texture so only need to update if(config.contains("ceiling")) { const string& name = config["ceiling"]; dbc::check(tiles.contains(name), fmt::format("invalid ceiling name {} in tile config {}", name, (string)el.key())); auto& ceiling = tiles[name]; TMGR.ceilings[surface_i] = ceiling["id"]; } } } void load_map_tiles() { Config config("./assets/map_tiles.json"); json& tiles = config.json(); for(auto tile : tiles) { sf::Vector2i coords{tile["x"], tile["y"]}; dbc::check(coords.x % ICONGEN_MAP_TILE_DIM == 0, "x coordinates wrong in map"); dbc::check(coords.y % ICONGEN_MAP_TILE_DIM == 0, "y coordinates wrong in map"); sf::IntRect square{coords, {ICONGEN_MAP_TILE_DIM, ICONGEN_MAP_TILE_DIM}}; sf::Sprite sprite{TMGR.map_sprite_sheet, square}; wchar_t display = tile["display"]; dbc::check(!TMGR.map_sprites.contains(display), fmt::format("duplicate tile display {} in map_tiles.json", int(display))); TMGR.map_sprites.try_emplace(display, sprite); } } void init() { if(!initialized) { load_tiles(); load_sprites(); load_map_tiles(); initialized = true; } } SpriteTexture& get(const string& name, SpriteTextureMap& mapping) { dbc::check(initialized, "you forgot to call textures::init()"); dbc::check(mapping.contains(name), fmt::format("!!!!! textures do not contain {} sprite", name)); auto& result = mapping.at(name); dbc::check(result.sprite != nullptr, fmt::format("bad sprite from textures::get named {}", name)); dbc::check(result.texture != nullptr, fmt::format("bad texture from textures::get named {}", name)); return result; } SpriteTexture get_sprite(const string& name) { return get(name, TMGR.sprite_textures); } SpriteTexture get_icon(const string& name) { return get(name, TMGR.icon_textures); } sf::Image load_image(const string& filename) { sf::Image texture; bool good = texture.loadFromFile(filename); dbc::check(good, fmt::format("failed to load {}", filename)); return texture; } std::vector& get_ambient_light() { return TMGR.ambient_light; } std::vector& get_map_tile_set() { return TMGR.map_tile_set; } const uint32_t* get_surface(size_t num) { return (const uint32_t *)TMGR.surfaces[num].getPixelsPtr(); } sf::Image& get_surface_img(size_t num) { return TMGR.surfaces[num]; } const uint32_t* get_ceiling(size_t num) { size_t ceiling_num = TMGR.ceilings[num]; return (const uint32_t *)TMGR.surfaces[ceiling_num].getPixelsPtr(); } size_t get_id(const string& name) { dbc::check(TMGR.name_to_id.contains(name), fmt::format("there is no texture named {} in tiles.json", name)); return TMGR.name_to_id.at(name); } sf::Sprite& get_map_sprite(wchar_t display) { dbc::check(TMGR.map_sprites.contains(display), fmt::format("map_sprites.json doesn't have {} sprite", int(display))); return TMGR.map_sprites.at(display); } };