Textures and palette moved to graphics.
This commit is contained in:
parent
b91e9ffaf6
commit
229ad2dd95
30 changed files with 31 additions and 31 deletions
72
src/graphics/palette.cpp
Normal file
72
src/graphics/palette.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#include <fmt/core.h>
|
||||
#include "graphics/palette.hpp"
|
||||
#include "config.hpp"
|
||||
#include "dbc.hpp"
|
||||
|
||||
namespace palette {
|
||||
using std::string;
|
||||
using nlohmann::json;
|
||||
|
||||
struct PaletteMgr {
|
||||
std::unordered_map<string, sf::Color> palettes;
|
||||
std::string config;
|
||||
std::unordered_map<string, string> pending_refs;
|
||||
bool initialized = false;
|
||||
};
|
||||
|
||||
static PaletteMgr COLOR;
|
||||
|
||||
bool initialized() {
|
||||
return COLOR.initialized;
|
||||
}
|
||||
|
||||
void init(const string &json_file) {
|
||||
if(!COLOR.initialized) {
|
||||
COLOR.initialized = true;
|
||||
|
||||
COLOR.config = json_file;
|
||||
auto config = settings::get(json_file);
|
||||
json& colors = config.json();
|
||||
|
||||
for(auto [key, value_specs] : colors.items()) {
|
||||
const string& base_key = key;
|
||||
|
||||
for(auto [value, rgba] : value_specs.items()) {
|
||||
auto color_path = base_key + ":" + value;
|
||||
dbc::check(!COLOR.palettes.contains(color_path),
|
||||
fmt::format("PALLETES config {} already has a color path {}", COLOR.config, color_path));
|
||||
|
||||
if(rgba.type() == json::value_t::string) {
|
||||
COLOR.pending_refs.try_emplace(color_path, rgba);
|
||||
} else {
|
||||
uint8_t alpha = rgba.size() == 3 ? 255 : (uint8_t)rgba[3];
|
||||
sf::Color color{rgba[0], rgba[1], rgba[2], alpha};
|
||||
COLOR.palettes.try_emplace(color_path, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto [color_path, ref] : COLOR.pending_refs) {
|
||||
dbc::check(COLOR.palettes.contains(ref),
|
||||
fmt::format("In {} you have {} referring to {} but {} doesn't exist.",
|
||||
COLOR.config, color_path, ref, ref));
|
||||
dbc::check(!COLOR.palettes.contains(color_path),
|
||||
fmt::format("Color {} with ref {} is duplicated.", color_path, ref));
|
||||
|
||||
auto color = COLOR.palettes.at(ref);
|
||||
|
||||
COLOR.palettes.try_emplace(color_path, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sf::Color get(const string& key) {
|
||||
dbc::check(COLOR.palettes.contains(key),
|
||||
fmt::format("COLOR {} is missing from {}", key, COLOR.config));
|
||||
return COLOR.palettes.at(key);
|
||||
}
|
||||
|
||||
sf::Color get(const string& key, const string& value) {
|
||||
return get(key + ":" + value);
|
||||
}
|
||||
}
|
||||
13
src/graphics/palette.hpp
Normal file
13
src/graphics/palette.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include <string>
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
|
||||
namespace palette {
|
||||
using std::string;
|
||||
|
||||
bool initialized();
|
||||
void init(const std::string &config="palette");
|
||||
|
||||
sf::Color get(const string &key);
|
||||
|
||||
sf::Color get(const string &key, const string &value);
|
||||
}
|
||||
203
src/graphics/textures.cpp
Normal file
203
src/graphics/textures.cpp
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
#include "graphics/textures.hpp"
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include "dbc.hpp"
|
||||
#include <fmt/core.h>
|
||||
#include "config.hpp"
|
||||
#include "constants.hpp"
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
|
||||
namespace textures {
|
||||
using std::shared_ptr, std::make_shared, nlohmann::json, std::string;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static TextureManager TMGR;
|
||||
static bool initialized = false;
|
||||
static bool failure = false;
|
||||
|
||||
void load_sprite_textures(SpriteTextureMap &mapping, json &config, bool smooth) {
|
||||
for(auto& [name, settings] : config.items()) {
|
||||
const string& path = settings["path"];
|
||||
dbc::check(fs::exists(path), fmt::format("texture at {} doesn't exist", path));
|
||||
auto texture = make_shared<sf::Texture>(path);
|
||||
|
||||
texture->setSmooth(smooth);
|
||||
auto sprite = make_shared<sf::Sprite>(*texture);
|
||||
|
||||
int width = settings["frame_width"];
|
||||
int height = settings["frame_height"];
|
||||
|
||||
dbc::check(width % 2 == 0 && height % 2 == 0,
|
||||
fmt::format("sprite {}:{} has invalid frame size {}:{}",
|
||||
path, name, width, height));
|
||||
|
||||
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() {
|
||||
auto sprites = settings::get("config");
|
||||
bool smooth = sprites["graphics"]["smooth_textures"];
|
||||
|
||||
load_sprite_textures(TMGR.sprite_textures, sprites["sprites"], smooth);
|
||||
|
||||
auto icons = settings::get("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() {
|
||||
auto assets = settings::get("tiles");
|
||||
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() {
|
||||
auto config = settings::get("map_tiles");
|
||||
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() {
|
||||
dbc::check(!failure, "YOU HAD A CATASTROPHIC TEXTURES FAILURE, FIX IT");
|
||||
|
||||
try {
|
||||
if(!initialized) {
|
||||
load_tiles();
|
||||
load_sprites();
|
||||
load_map_tiles();
|
||||
initialized = true;
|
||||
}
|
||||
} catch(...) {
|
||||
failure = true;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
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, bool duped) {
|
||||
auto& st = get(name, TMGR.sprite_textures);
|
||||
|
||||
if(duped) {
|
||||
st.sprite = make_shared<sf::Sprite>(*st.sprite);
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
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<int>& get_ambient_light() {
|
||||
return TMGR.ambient_light;
|
||||
}
|
||||
|
||||
std::vector<wchar_t>& 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);
|
||||
}
|
||||
};
|
||||
54
src/graphics/textures.hpp
Normal file
54
src/graphics/textures.hpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include "algos/matrix.hpp"
|
||||
|
||||
namespace textures {
|
||||
|
||||
struct SpriteTexture {
|
||||
std::shared_ptr<sf::Sprite> sprite = nullptr;
|
||||
std::shared_ptr<sf::Texture> texture = nullptr;
|
||||
sf::Vector2i frame_size;
|
||||
};
|
||||
|
||||
using SpriteTextureMap = std::unordered_map<std::string, SpriteTexture>;
|
||||
|
||||
struct TextureManager {
|
||||
std::vector<sf::Image> surfaces;
|
||||
std::vector<size_t> ceilings;
|
||||
std::vector<wchar_t> map_tile_set;
|
||||
std::vector<int> ambient_light;
|
||||
SpriteTextureMap sprite_textures;
|
||||
SpriteTextureMap icon_textures;
|
||||
std::unordered_map<std::string, size_t> name_to_id;
|
||||
std::unordered_map<wchar_t, sf::Sprite> map_sprites;
|
||||
sf::Texture map_sprite_sheet{"./assets/map_tiles.png"};
|
||||
};
|
||||
|
||||
void init();
|
||||
|
||||
SpriteTexture get_sprite(const std::string& name, bool duped=false);
|
||||
SpriteTexture get_icon(const std::string& name);
|
||||
|
||||
sf::Image load_image(const std::string& filename);
|
||||
|
||||
std::vector<int>& get_ambient_light();
|
||||
|
||||
std::vector<wchar_t>& get_map_tile_set();
|
||||
|
||||
const uint32_t* get_surface(size_t num);
|
||||
|
||||
sf::Image& get_surface_img(size_t num);
|
||||
|
||||
const uint32_t* get_ceiling(size_t num);
|
||||
|
||||
sf::Sprite& get_map_sprite(wchar_t display);
|
||||
|
||||
size_t get_id(const std::string& name);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue