assets-related refactor
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -12,12 +13,18 @@ class Texture;
|
|||||||
class Shader;
|
class Shader;
|
||||||
class Font;
|
class Font;
|
||||||
class Atlas;
|
class Atlas;
|
||||||
|
class Assets;
|
||||||
class UiDocument;
|
class UiDocument;
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
class Sound;
|
class Sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace assetload {
|
||||||
|
/// @brief final work to do in the main thread
|
||||||
|
using postfunc = std::function<void(Assets*)>;
|
||||||
|
}
|
||||||
|
|
||||||
class Assets {
|
class Assets {
|
||||||
std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
|
std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
|
||||||
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
|
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
|
||||||
|
|||||||
@@ -49,9 +49,16 @@ bool AssetsLoader::loadNext() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aloader_func loader = found->second;
|
aloader_func loader = found->second;
|
||||||
bool status = loader(*this, assets, paths, entry.filename, entry.alias, entry.config);
|
try {
|
||||||
entries.pop();
|
auto postfunc = loader(*this, assets, paths, entry.filename, entry.alias, entry.config);
|
||||||
return status;
|
postfunc(assets);
|
||||||
|
entries.pop();
|
||||||
|
return true;
|
||||||
|
} catch (std::runtime_error& err) {
|
||||||
|
logger.error() << err.what();
|
||||||
|
entries.pop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLayouts(int env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) {
|
void addLayouts(int env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef ASSETS_ASSETS_LOADER_H
|
#ifndef ASSETS_ASSETS_LOADER_H
|
||||||
#define ASSETS_ASSETS_LOADER_H
|
#define ASSETS_ASSETS_LOADER_H
|
||||||
|
|
||||||
|
#include "Assets.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@@ -23,7 +25,6 @@ enum class AssetType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class ResPaths;
|
class ResPaths;
|
||||||
class Assets;
|
|
||||||
class AssetsLoader;
|
class AssetsLoader;
|
||||||
class Content;
|
class Content;
|
||||||
|
|
||||||
@@ -43,7 +44,14 @@ struct SoundCfg : AssetCfg {
|
|||||||
SoundCfg(bool keepPCM) : keepPCM(keepPCM) {}
|
SoundCfg(bool keepPCM) : keepPCM(keepPCM) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
using aloader_func = std::function<bool(AssetsLoader&, Assets*, const ResPaths*, const std::string&, const std::string&, std::shared_ptr<AssetCfg>)>;
|
using aloader_func = std::function<assetload::postfunc(
|
||||||
|
AssetsLoader&,
|
||||||
|
Assets*,
|
||||||
|
const ResPaths*,
|
||||||
|
const std::string&,
|
||||||
|
const std::string&,
|
||||||
|
std::shared_ptr<AssetCfg>)
|
||||||
|
>;
|
||||||
|
|
||||||
struct aloader_entry {
|
struct aloader_entry {
|
||||||
AssetType tag;
|
AssetType tag;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "assetload_funcs.h"
|
#include "assetload_funcs.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include "Assets.h"
|
#include "Assets.h"
|
||||||
#include "AssetsLoader.h"
|
#include "AssetsLoader.h"
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include "../files/engine_paths.h"
|
#include "../files/engine_paths.h"
|
||||||
#include "../coders/png.h"
|
#include "../coders/png.h"
|
||||||
#include "../coders/json.h"
|
#include "../coders/json.h"
|
||||||
|
#include "../coders/GLSLExtension.h"
|
||||||
#include "../graphics/core/Shader.h"
|
#include "../graphics/core/Shader.h"
|
||||||
#include "../graphics/core/Texture.h"
|
#include "../graphics/core/Texture.h"
|
||||||
#include "../graphics/core/ImageData.h"
|
#include "../graphics/core/ImageData.h"
|
||||||
@@ -28,7 +30,7 @@ static bool animation(
|
|||||||
Atlas* dstAtlas
|
Atlas* dstAtlas
|
||||||
);
|
);
|
||||||
|
|
||||||
bool assetload::texture(
|
assetload::postfunc assetload::texture(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -36,18 +38,15 @@ bool assetload::texture(
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg>
|
std::shared_ptr<AssetCfg>
|
||||||
) {
|
) {
|
||||||
std::unique_ptr<Texture> texture(
|
std::shared_ptr<ImageData> image (
|
||||||
png::load_texture(paths->find(filename+".png").u8string())
|
png::load_image(paths->find(filename+".png").u8string())
|
||||||
);
|
);
|
||||||
if (texture == nullptr) {
|
return [name, image](auto assets) {
|
||||||
std::cerr << "failed to load texture '" << name << "'" << std::endl;
|
assets->store(Texture::from(image.get()), name);
|
||||||
return false;
|
};
|
||||||
}
|
|
||||||
assets->store(texture.release(), name);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::shader(
|
assetload::postfunc assetload::shader(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -61,18 +60,16 @@ bool assetload::shader(
|
|||||||
std::string vertexSource = files::read_string(vertexFile);
|
std::string vertexSource = files::read_string(vertexFile);
|
||||||
std::string fragmentSource = files::read_string(fragmentFile);
|
std::string fragmentSource = files::read_string(fragmentFile);
|
||||||
|
|
||||||
Shader* shader = Shader::create(
|
vertexSource = Shader::preprocessor->process(vertexFile, vertexSource);
|
||||||
vertexFile.string(),
|
fragmentSource = Shader::preprocessor->process(fragmentFile, fragmentSource);
|
||||||
fragmentFile.string(),
|
|
||||||
vertexSource, fragmentSource
|
|
||||||
);
|
|
||||||
|
|
||||||
if (shader == nullptr) {
|
return [=](auto assets) {
|
||||||
std::cerr << "failed to load shader '" << name << "'" << std::endl;
|
assets->store(Shader::create(
|
||||||
return false;
|
vertexFile.u8string(),
|
||||||
}
|
fragmentFile.u8string(),
|
||||||
assets->store(shader, name);
|
vertexSource, fragmentSource
|
||||||
return true;
|
), name);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
|
static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
|
||||||
@@ -85,17 +82,13 @@ static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::unique_ptr<ImageData> image(png::load_image(file.string()));
|
std::unique_ptr<ImageData> image(png::load_image(file.string()));
|
||||||
if (image == nullptr) {
|
|
||||||
std::cerr << "could not to load " << file.string() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
image->fixAlphaColor();
|
image->fixAlphaColor();
|
||||||
atlas.add(name, image.release());
|
atlas.add(name, image.release());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::atlas(
|
assetload::postfunc assetload::atlas(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -105,17 +98,23 @@ bool assetload::atlas(
|
|||||||
) {
|
) {
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
for (const auto& file : paths->listdir(directory)) {
|
for (const auto& file : paths->listdir(directory)) {
|
||||||
if (!appendAtlas(builder, file)) continue;
|
if (!appendAtlas(builder, file))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
std::set<std::string> names = builder.getNames();
|
||||||
Atlas* atlas = builder.build(2);
|
Atlas* atlas = builder.build(2);
|
||||||
assets->store(atlas, name);
|
return [=](auto assets) {
|
||||||
for (const auto& file : builder.getNames()) {
|
atlas->prepare();
|
||||||
animation(assets, paths, "textures", file, atlas);
|
assets->store(atlas, name);
|
||||||
}
|
|
||||||
return true;
|
// FIXME
|
||||||
|
for (const auto& file : names) {
|
||||||
|
animation(assets, paths, "textures", file, atlas);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::font(
|
assetload::postfunc assetload::font(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -123,25 +122,24 @@ bool assetload::font(
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg>
|
std::shared_ptr<AssetCfg>
|
||||||
) {
|
) {
|
||||||
std::vector<std::unique_ptr<Texture>> pages;
|
auto pages = std::make_shared<std::vector<std::unique_ptr<ImageData>>>();
|
||||||
for (size_t i = 0; i <= 4; i++) {
|
for (size_t i = 0; i <= 4; i++) {
|
||||||
std::string name = filename + "_" + std::to_string(i) + ".png";
|
std::string name = filename + "_" + std::to_string(i) + ".png";
|
||||||
name = paths->find(name).string();
|
name = paths->find(name).string();
|
||||||
std::unique_ptr<Texture> texture (png::load_texture(name));
|
std::unique_ptr<ImageData> image (png::load_image(name));
|
||||||
if (texture == nullptr) {
|
pages->push_back(std::move(image));
|
||||||
std::cerr << "failed to load bitmap font '" << name;
|
|
||||||
std::cerr << "' (missing page " << std::to_string(i) << ")";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pages.push_back(std::move(texture));
|
|
||||||
}
|
}
|
||||||
int res = pages[0]->getHeight() / 16;
|
return [=](auto assets) {
|
||||||
assets->store(new Font(std::move(pages), res, 4), name);
|
int res = pages->at(0)->getHeight() / 16;
|
||||||
return true;
|
std::vector<std::unique_ptr<Texture>> textures;
|
||||||
|
for (auto& page : *pages) {
|
||||||
|
textures.emplace_back(Texture::from(page.get()));
|
||||||
|
}
|
||||||
|
assets->store(new Font(std::move(textures), res, 4), name);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::layout(
|
assetload::postfunc assetload::layout(
|
||||||
AssetsLoader& loader,
|
AssetsLoader& loader,
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -149,18 +147,19 @@ bool assetload::layout(
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> config
|
std::shared_ptr<AssetCfg> config
|
||||||
) {
|
) {
|
||||||
try {
|
return [=](auto assets) {
|
||||||
auto cfg = dynamic_cast<LayoutCfg*>(config.get());
|
try {
|
||||||
auto document = UiDocument::read(cfg->env, name, file);
|
auto cfg = dynamic_cast<LayoutCfg*>(config.get());
|
||||||
assets->store(document.release(), name);
|
auto document = UiDocument::read(cfg->env, name, file);
|
||||||
return true;
|
assets->store(document.release(), name);
|
||||||
} catch (const parsing_error& err) {
|
} catch (const parsing_error& err) {
|
||||||
std::cerr << "failed to parse layout XML '" << file << "'" << std::endl;
|
throw std::runtime_error(
|
||||||
std::cerr << err.errorLog() << std::endl;
|
"failed to parse layout XML '"+file+"':\n"+err.errorLog()
|
||||||
return false;
|
);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
bool assetload::sound(
|
assetload::postfunc assetload::sound(
|
||||||
AssetsLoader& loader,
|
AssetsLoader& loader,
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -172,37 +171,35 @@ bool assetload::sound(
|
|||||||
bool keepPCM = cfg ? cfg->keepPCM : false;
|
bool keepPCM = cfg ? cfg->keepPCM : false;
|
||||||
|
|
||||||
std::string extension = ".ogg";
|
std::string extension = ".ogg";
|
||||||
try {
|
std::unique_ptr<audio::Sound> baseSound = nullptr;
|
||||||
std::unique_ptr<audio::Sound> baseSound = nullptr;
|
|
||||||
|
|
||||||
// looking for 'sound_name' as base sound
|
// looking for 'sound_name' as base sound
|
||||||
auto soundFile = paths->find(file+extension);
|
auto soundFile = paths->find(file+extension);
|
||||||
if (fs::exists(soundFile)) {
|
if (fs::exists(soundFile)) {
|
||||||
baseSound.reset(audio::load_sound(soundFile, keepPCM));
|
baseSound.reset(audio::load_sound(soundFile, keepPCM));
|
||||||
}
|
|
||||||
// looking for 'sound_name_0' as base sound
|
|
||||||
auto variantFile = paths->find(file+"_0"+extension);
|
|
||||||
if (fs::exists(variantFile)) {
|
|
||||||
baseSound.reset(audio::load_sound(variantFile, keepPCM));
|
|
||||||
}
|
|
||||||
|
|
||||||
// loading sound variants
|
|
||||||
for (uint i = 1; ; i++) {
|
|
||||||
auto variantFile = paths->find(file+"_"+std::to_string(i)+extension);
|
|
||||||
if (!fs::exists(variantFile)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
|
|
||||||
}
|
|
||||||
assets->store(baseSound.release(), name);
|
|
||||||
}
|
|
||||||
catch (std::runtime_error& err) {
|
|
||||||
std::cerr << err.what() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
// looking for 'sound_name_0' as base sound
|
||||||
|
auto variantFile = paths->find(file+"_0"+extension);
|
||||||
|
if (fs::exists(variantFile)) {
|
||||||
|
baseSound.reset(audio::load_sound(variantFile, keepPCM));
|
||||||
|
}
|
||||||
|
|
||||||
|
// loading sound variants
|
||||||
|
for (uint i = 1; ; i++) {
|
||||||
|
auto variantFile = paths->find(file+"_"+std::to_string(i)+extension);
|
||||||
|
if (!fs::exists(variantFile)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sound = baseSound.release();
|
||||||
|
return [=](auto assets) {
|
||||||
|
assets->store(sound, name);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: integrate
|
||||||
static bool animation(
|
static bool animation(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -256,10 +253,12 @@ static bool animation(
|
|||||||
}
|
}
|
||||||
if (!contains) continue;
|
if (!contains) continue;
|
||||||
}
|
}
|
||||||
if (!appendAtlas(builder, file)) continue;
|
if (!appendAtlas(builder, file))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Atlas> srcAtlas (builder.build(2));
|
std::unique_ptr<Atlas> srcAtlas (builder.build(2));
|
||||||
|
srcAtlas->prepare();
|
||||||
|
|
||||||
Texture* srcTex = srcAtlas->getTexture();
|
Texture* srcTex = srcAtlas->getTexture();
|
||||||
Texture* dstTex = dstAtlas->getTexture();
|
Texture* dstTex = dstAtlas->getTexture();
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef ASSETS_ASSET_LOADERS_H_
|
#ifndef ASSETS_ASSET_LOADERS_H_
|
||||||
#define ASSETS_ASSET_LOADERS_H_
|
#define ASSETS_ASSET_LOADERS_H_
|
||||||
|
|
||||||
|
#include "Assets.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -12,7 +14,7 @@ struct AssetCfg;
|
|||||||
|
|
||||||
/// @brief see AssetsLoader.h: aloader_func
|
/// @brief see AssetsLoader.h: aloader_func
|
||||||
namespace assetload {
|
namespace assetload {
|
||||||
bool texture(
|
postfunc texture(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets*,
|
Assets*,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -20,7 +22,7 @@ namespace assetload {
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool shader(
|
postfunc shader(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets*,
|
Assets*,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -28,7 +30,7 @@ namespace assetload {
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool atlas(
|
postfunc atlas(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets*,
|
Assets*,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -36,7 +38,7 @@ namespace assetload {
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool font(
|
postfunc font(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets*,
|
Assets*,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -44,7 +46,7 @@ namespace assetload {
|
|||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool layout(
|
postfunc layout(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets*,
|
Assets*,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
@@ -53,7 +55,7 @@ namespace assetload {
|
|||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
|
|
||||||
bool sound(
|
postfunc sound(
|
||||||
AssetsLoader&,
|
AssetsLoader&,
|
||||||
Assets*,
|
Assets*,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ inline void source_line(std::stringstream& ss, uint linenum) {
|
|||||||
ss << "#line " << linenum << "\n";
|
ss << "#line " << linenum << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string GLSLExtension::process(const fs::path file, const std::string& source) {
|
const std::string GLSLExtension::process(const fs::path& file, const std::string& source) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
uint linenum = 1;
|
uint linenum = 1;
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ public:
|
|||||||
bool hasHeader(const std::string& name) const;
|
bool hasHeader(const std::string& name) const;
|
||||||
bool hasDefine(const std::string& name) const;
|
bool hasDefine(const std::string& name) const;
|
||||||
|
|
||||||
const std::string process(const std::filesystem::path file, const std::string& source);
|
const std::string process(
|
||||||
|
const std::filesystem::path& file,
|
||||||
|
const std::string& source
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CODERS_GLSL_EXTESION_H_
|
#endif // CODERS_GLSL_EXTESION_H_
|
||||||
|
|||||||
+3
-8
@@ -343,18 +343,13 @@ ImageData* _png_load(const char* file){
|
|||||||
ImageData* png::load_image(std::string filename) {
|
ImageData* png::load_image(std::string filename) {
|
||||||
ImageData* image (_png_load(filename.c_str()));
|
ImageData* image (_png_load(filename.c_str()));
|
||||||
if (image == nullptr) {
|
if (image == nullptr) {
|
||||||
std::cerr << "Could not load image " << filename << std::endl;
|
throw std::runtime_error("could not load image "+filename);
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* png::load_texture(std::string filename) {
|
Texture* png::load_texture(std::string filename) {
|
||||||
std::unique_ptr<ImageData> image (_png_load(filename.c_str()));
|
std::unique_ptr<ImageData> image (load_image(filename));
|
||||||
if (image == nullptr){
|
|
||||||
std::cerr << "Could not load texture " << filename << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto texture = Texture::from(image.get());
|
auto texture = Texture::from(image.get());
|
||||||
texture->setNearestFilter();
|
texture->setNearestFilter();
|
||||||
return texture;
|
return texture;
|
||||||
@@ -362,4 +357,4 @@ Texture* png::load_texture(std::string filename) {
|
|||||||
|
|
||||||
void png::write_image(std::string filename, const ImageData* image) {
|
void png::write_image(std::string filename, const ImageData* image) {
|
||||||
_png_write(filename.c_str(), image->getWidth(), image->getHeight(), (const ubyte*)image->getData(), image->getFormat() == ImageFormat::rgba8888);
|
_png_write(filename.c_str(), image->getWidth(), image->getHeight(), (const ubyte*)image->getData(), image->getFormat() == ImageFormat::rgba8888);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,12 @@ void menus::create_new_world_panel(Engine* engine) {
|
|||||||
auto seedInput = std::make_shared<TextBox>(seedstr, glm::vec4(6.0f));
|
auto seedInput = std::make_shared<TextBox>(seedstr, glm::vec4(6.0f));
|
||||||
panel->add(seedInput);
|
panel->add(seedInput);
|
||||||
|
|
||||||
generatorTypeButton = guiutil::gotoButton(langs::get(L"World generator", L"world") + (L": ") + util::str2wstr_utf8(translate_generator_id(menus::generatorID)), "world_generators", engine->getGUI()->getMenu());
|
generatorTypeButton = guiutil::gotoButton(
|
||||||
|
langs::get(L"World generator", L"world") + L": " +
|
||||||
|
util::str2wstr_utf8(translate_generator_id(menus::generatorID)),
|
||||||
|
"world_generators",
|
||||||
|
engine->getGUI()->getMenu()
|
||||||
|
);
|
||||||
panel->add(generatorTypeButton);
|
panel->add(generatorTypeButton);
|
||||||
|
|
||||||
panel->add(menus::create_button(L"Create World", glm::vec4(10), glm::vec4(1, 20, 1, 1),
|
panel->add(menus::create_button(L"Create World", glm::vec4(10), glm::vec4(1, 20, 1, 1),
|
||||||
@@ -153,7 +158,7 @@ void menus::create_new_world_panel(Engine* engine) {
|
|||||||
engine->getContent(),
|
engine->getContent(),
|
||||||
engine->getContentPacks()
|
engine->getContentPacks()
|
||||||
);
|
);
|
||||||
level->world->wfile->createDirectories();
|
level->getWorld()->wfile->createDirectories();
|
||||||
menus::generatorID = WorldGenerators::getDefaultGeneratorID();
|
menus::generatorID = WorldGenerators::getDefaultGeneratorID();
|
||||||
engine->setScreen(std::make_shared<LevelScreen>(engine, level));
|
engine->setScreen(std::make_shared<LevelScreen>(engine, level));
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "ImageData.h"
|
#include "ImageData.h"
|
||||||
|
|
||||||
Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions)
|
Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions)
|
||||||
: texture(Texture::from(image)),
|
: texture(nullptr),
|
||||||
image(image),
|
image(image),
|
||||||
regions(regions) {
|
regions(regions) {
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,10 @@ Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions
|
|||||||
Atlas::~Atlas() {
|
Atlas::~Atlas() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Atlas::prepare() {
|
||||||
|
texture.reset(Texture::from(image.get()));
|
||||||
|
}
|
||||||
|
|
||||||
bool Atlas::has(const std::string& name) const {
|
bool Atlas::has(const std::string& name) const {
|
||||||
return regions.find(name) != regions.end();
|
return regions.find(name) != regions.end();
|
||||||
}
|
}
|
||||||
@@ -80,8 +84,9 @@ Atlas* AtlasBuilder::build(uint extrusion, uint maxResolution) {
|
|||||||
}
|
}
|
||||||
float unitX = 1.0f / width;
|
float unitX = 1.0f / width;
|
||||||
float unitY = 1.0f / height;
|
float unitY = 1.0f / height;
|
||||||
regions[entry.name] = UVRegion(unitX * x, unitY * y,
|
regions[entry.name] = UVRegion(
|
||||||
unitX * (x + w), unitY * (y + h));
|
unitX * x, unitY * y, unitX * (x + w), unitY * (y + h)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return new Atlas(canvas.release(), regions);
|
return new Atlas(canvas.release(), regions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public:
|
|||||||
Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions);
|
Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions);
|
||||||
~Atlas();
|
~Atlas();
|
||||||
|
|
||||||
|
void prepare();
|
||||||
|
|
||||||
bool has(const std::string& name) const;
|
bool has(const std::string& name) const;
|
||||||
const UVRegion& get(const std::string& name) const;
|
const UVRegion& get(const std::string& name) const;
|
||||||
|
|
||||||
@@ -27,7 +29,6 @@ public:
|
|||||||
ImageData* getImage() const;
|
ImageData* getImage() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct atlasentry {
|
struct atlasentry {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::shared_ptr<ImageData> image;
|
std::shared_ptr<ImageData> image;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
GLSLExtension* Shader::preprocessor = new GLSLExtension();
|
GLSLExtension* Shader::preprocessor = new GLSLExtension();
|
||||||
|
|
||||||
Shader::Shader(unsigned int id) : id(id){
|
Shader::Shader(uint id) : id(id){
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::~Shader(){
|
Shader::~Shader(){
|
||||||
@@ -28,106 +28,101 @@ void Shader::use(){
|
|||||||
glUseProgram(id);
|
glUseProgram(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniformMatrix(std::string name, glm::mat4 matrix){
|
uint Shader::getUniformLocation(const std::string& name) {
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
auto found = uniformLocations.find(name);
|
||||||
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(matrix));
|
if (found == uniformLocations.end()) {
|
||||||
|
uint location = glGetUniformLocation(id, name.c_str());
|
||||||
|
uniformLocations.emplace(name, location);
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform1i(std::string name, int x){
|
void Shader::uniformMatrix(const std::string& name, glm::mat4 matrix){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix));
|
||||||
glUniform1i(transformLoc, x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform1f(std::string name, float x){
|
void Shader::uniform1i(const std::string& name, int x){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniform1i(getUniformLocation(name), x);
|
||||||
glUniform1f(transformLoc, x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform2f(std::string name, float x, float y){
|
void Shader::uniform1f(const std::string& name, float x){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniform1f(getUniformLocation(name), x);
|
||||||
glUniform2f(transformLoc, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform2f(std::string name, glm::vec2 xy){
|
void Shader::uniform2f(const std::string& name, float x, float y){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniform2f(getUniformLocation(name), x, y);
|
||||||
glUniform2f(transformLoc, xy.x, xy.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform2i(std::string name, glm::ivec2 xy){
|
void Shader::uniform2f(const std::string& name, glm::vec2 xy){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniform2f(getUniformLocation(name), xy.x, xy.y);
|
||||||
glUniform2i(transformLoc, xy.x, xy.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform3f(std::string name, float x, float y, float z){
|
void Shader::uniform2i(const std::string& name, glm::ivec2 xy){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniform2i(getUniformLocation(name), xy.x, xy.y);
|
||||||
glUniform3f(transformLoc, x,y,z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform3f(std::string name, glm::vec3 xyz){
|
void Shader::uniform3f(const std::string& name, float x, float y, float z){
|
||||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
glUniform3f(getUniformLocation(name), x,y,z);
|
||||||
glUniform3f(transformLoc, xyz.x, xyz.y, xyz.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::uniform3f(const std::string& name, glm::vec3 xyz){
|
||||||
|
glUniform3f(getUniformLocation(name), xyz.x, xyz.y, xyz.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline auto shader_deleter = [](GLuint* shader) {
|
||||||
|
glDeleteShader(*shader);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const uint GL_LOG_LEN = 512;
|
||||||
|
|
||||||
|
// shader should be deleted after shader program linking
|
||||||
|
using glshader = std::unique_ptr<GLuint, decltype(shader_deleter)>;
|
||||||
|
|
||||||
|
glshader compile_shader(GLenum type, const GLchar* source, const std::string& file) {
|
||||||
|
GLint success;
|
||||||
|
GLuint shader = glCreateShader(type);
|
||||||
|
glShaderSource(shader, 1, &source, nullptr);
|
||||||
|
glCompileShader(shader);
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success){
|
||||||
|
GLchar infoLog[GL_LOG_LEN];
|
||||||
|
glGetShaderInfoLog(shader, GL_LOG_LEN, nullptr, infoLog);
|
||||||
|
glDeleteShader(shader);
|
||||||
|
throw std::runtime_error(
|
||||||
|
"vertex shader compilation failed ("+file+"):\n"+std::string(infoLog)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return glshader(new GLuint(shader), shader_deleter);
|
||||||
|
}
|
||||||
|
|
||||||
Shader* Shader::create(
|
Shader* Shader::create(
|
||||||
std::string vertexFile,
|
const std::string& vertexFile,
|
||||||
std::string fragmentFile,
|
const std::string& fragmentFile,
|
||||||
std::string vertexCode,
|
const std::string& vertexCode,
|
||||||
std::string fragmentCode
|
const std::string& fragmentCode
|
||||||
) {
|
) {
|
||||||
vertexCode = preprocessor->process(fs::path(vertexFile), vertexCode);
|
const GLchar* vCode = vertexCode.c_str();
|
||||||
fragmentCode = preprocessor->process(fs::path(fragmentFile), fragmentCode);
|
const GLchar* fCode = fragmentCode.c_str();
|
||||||
|
|
||||||
const GLchar* vShaderCode = vertexCode.c_str();
|
glshader vertex = compile_shader(GL_VERTEX_SHADER, vCode, vertexFile);
|
||||||
const GLchar* fShaderCode = fragmentCode.c_str();
|
glshader fragment = compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentFile);
|
||||||
|
|
||||||
GLuint vertex, fragment;
|
|
||||||
GLint success;
|
|
||||||
GLchar infoLog[512];
|
|
||||||
|
|
||||||
// Vertex Shader
|
|
||||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
glShaderSource(vertex, 1, &vShaderCode, nullptr);
|
|
||||||
glCompileShader(vertex);
|
|
||||||
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success){
|
|
||||||
glGetShaderInfoLog(vertex, 512, nullptr, infoLog);
|
|
||||||
std::cerr << "SHADER::VERTEX: compilation failed: " << vertexFile << std::endl;
|
|
||||||
std::cerr << infoLog << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fragment Shader
|
|
||||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(fragment, 1, &fShaderCode, nullptr);
|
|
||||||
glCompileShader(fragment);
|
|
||||||
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success){
|
|
||||||
glGetShaderInfoLog(fragment, 512, nullptr, infoLog);
|
|
||||||
std::cerr << "SHADER::FRAGMENT: compilation failed: " << vertexFile << std::endl;
|
|
||||||
std::cerr << infoLog << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shader Program
|
// Shader Program
|
||||||
|
GLint success;
|
||||||
GLuint id = glCreateProgram();
|
GLuint id = glCreateProgram();
|
||||||
glAttachShader(id, vertex);
|
glAttachShader(id, *vertex);
|
||||||
glAttachShader(id, fragment);
|
glAttachShader(id, *fragment);
|
||||||
glLinkProgram(id);
|
glLinkProgram(id);
|
||||||
|
|
||||||
glGetProgramiv(id, GL_LINK_STATUS, &success);
|
glGetProgramiv(id, GL_LINK_STATUS, &success);
|
||||||
if (!success){
|
if (!success){
|
||||||
glGetProgramInfoLog(id, 512, nullptr, infoLog);
|
GLchar infoLog[GL_LOG_LEN];
|
||||||
std::cerr << "SHADER::PROGRAM: linking failed" << std::endl;
|
glGetProgramInfoLog(id, GL_LOG_LEN, nullptr, infoLog);
|
||||||
std::cerr << infoLog << std::endl;
|
throw std::runtime_error(
|
||||||
|
"shader program linking failed:\n"+std::string(infoLog)
|
||||||
glDeleteShader(vertex);
|
);
|
||||||
glDeleteShader(fragment);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteShader(vertex);
|
|
||||||
glDeleteShader(fragment);
|
|
||||||
|
|
||||||
return new Shader(id);
|
return new Shader(id);
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-15
@@ -1,35 +1,46 @@
|
|||||||
#ifndef GRAPHICS_CORE_SHADER_H_
|
#ifndef GRAPHICS_CORE_SHADER_H_
|
||||||
#define GRAPHICS_CORE_SHADER_H_
|
#define GRAPHICS_CORE_SHADER_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include "../../typedefs.h"
|
#include "../../typedefs.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class GLSLExtension;
|
class GLSLExtension;
|
||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
uint id;
|
uint id;
|
||||||
|
std::unordered_map<std::string, uint> uniformLocations;
|
||||||
|
|
||||||
|
uint getUniformLocation(const std::string& name);
|
||||||
public:
|
public:
|
||||||
static GLSLExtension* preprocessor;
|
static GLSLExtension* preprocessor;
|
||||||
|
|
||||||
Shader(unsigned int id);
|
Shader(uint id);
|
||||||
~Shader();
|
~Shader();
|
||||||
|
|
||||||
void use();
|
void use();
|
||||||
void uniformMatrix(std::string name, glm::mat4 matrix);
|
void uniformMatrix(const std::string&, glm::mat4 matrix);
|
||||||
void uniform1i(std::string name, int x);
|
void uniform1i(const std::string& name, int x);
|
||||||
void uniform1f(std::string name, float x);
|
void uniform1f(const std::string& name, float x);
|
||||||
void uniform2f(std::string name, float x, float y);
|
void uniform2f(const std::string& name, float x, float y);
|
||||||
void uniform2f(std::string name, glm::vec2 xy);
|
void uniform2f(const std::string& name, glm::vec2 xy);
|
||||||
void uniform2i(std::string name, glm::ivec2 xy);
|
void uniform2i(const std::string& name, glm::ivec2 xy);
|
||||||
void uniform3f(std::string name, float x, float y, float z);
|
void uniform3f(const std::string& name, float x, float y, float z);
|
||||||
void uniform3f(std::string name, glm::vec3 xyz);
|
void uniform3f(const std::string& name, glm::vec3 xyz);
|
||||||
|
|
||||||
|
/// @brief Create shader program using vertex and fragment shaders source.
|
||||||
|
/// @param vertexFile vertex shader file name
|
||||||
|
/// @param fragmentFile fragment shader file name
|
||||||
|
/// @param vertexSource vertex shader source code
|
||||||
|
/// @param fragmentSource fragment shader source code
|
||||||
|
/// @return linked shader program containing vertex and fragment shaders
|
||||||
static Shader* create(
|
static Shader* create(
|
||||||
std::string vertexFile,
|
const std::string& vertexFile,
|
||||||
std::string fragmentFile,
|
const std::string& fragmentFile,
|
||||||
std::string vertexSource,
|
const std::string& vertexSource,
|
||||||
std::string fragmentSource
|
const std::string& fragmentSource
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -142,5 +142,7 @@ std::unique_ptr<Atlas> BlocksPreview::build(
|
|||||||
fbo.unbind();
|
fbo.unbind();
|
||||||
|
|
||||||
Window::viewport(0, 0, Window::width, Window::height);
|
Window::viewport(0, 0, Window::width, Window::height);
|
||||||
return std::unique_ptr<Atlas>(builder.build(2));
|
auto newAtlas = std::unique_ptr<Atlas>(builder.build(2));
|
||||||
|
newAtlas->prepare();
|
||||||
|
return newAtlas;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user