184 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include <asset_parser/assets/text.hpp>
 | |
| #include <asset_parser/assets/texture.hpp>
 | |
| #include <filesystem>
 | |
| #include <logger/logger.hpp>
 | |
| #include <string_view>
 | |
| #include <unordered_set>
 | |
| 
 | |
| #define STB_IMAGE_IMPLEMENTATION
 | |
| #include <stb_image.h>
 | |
| 
 | |
| namespace lt {
 | |
| 
 | |
| class Loader
 | |
| {
 | |
| public:
 | |
| 	[[nodiscard]] virtual auto get_name() const -> std::string_view = 0;
 | |
| 
 | |
| 	Loader() = default;
 | |
| 
 | |
| 	Loader(Loader &&) = default;
 | |
| 
 | |
| 	Loader(const Loader &) = delete;
 | |
| 
 | |
| 	auto operator=(Loader &&) -> Loader & = default;
 | |
| 
 | |
| 	auto operator=(const Loader &) -> Loader & = delete;
 | |
| 
 | |
| 	virtual ~Loader() = default;
 | |
| 
 | |
| private:
 | |
| };
 | |
| 
 | |
| class TextureLoader: public Loader
 | |
| {
 | |
| public:
 | |
| 	TextureLoader() = default;
 | |
| 
 | |
| 	[[nodiscard]] virtual auto load(std::filesystem::path file_path) const
 | |
| 	    -> Assets::TextureAsset::PackageData
 | |
| 	    = 0;
 | |
| };
 | |
| 
 | |
| 
 | |
| class StbLoader: public TextureLoader
 | |
| {
 | |
| public:
 | |
| 	StbLoader() = default;
 | |
| 
 | |
| 	void load(std::filesystem::path path);
 | |
| 
 | |
| 	[[nodiscard]] static auto get_supported_extensions() -> std::unordered_set<std::string_view>
 | |
| 	{
 | |
| 		return { ".png" };
 | |
| 	}
 | |
| 
 | |
| 	[[nodiscard]] auto get_name() const -> std::string_view override
 | |
| 	{
 | |
| 		return "StbLoader";
 | |
| 	}
 | |
| 
 | |
| 	[[nodiscard]] auto load(std::filesystem::path file_path) const
 | |
| 	    -> Assets::TextureAsset::PackageData override
 | |
| 	{
 | |
| 		auto width = int {};
 | |
| 		auto height = int {};
 | |
| 		auto channels = int {};
 | |
| 
 | |
| 		auto *pixels = stbi_load(file_path.string().c_str(), &width, &height, &channels, 4);
 | |
| 		if (!pixels)
 | |
| 		{
 | |
| 			throw std::runtime_error {
 | |
| 				std::format("Failed to load image file at: {} using stbi_load", file_path.string()),
 | |
| 			};
 | |
| 		}
 | |
| 
 | |
| 		const auto metadata = Assets::Asset::Metadata {
 | |
| 			.type = Assets::Asset::Type::Texture,
 | |
| 		};
 | |
| 
 | |
| 		const auto texture_metadata = Assets::TextureAsset::Metadata {
 | |
|             .format = Assets::TextureAsset::Format::RGBA8,
 | |
|             .num_components = static_cast<uint32_t>(channels),
 | |
|             .pixel_size = {
 | |
|                 static_cast<uint32_t>(width),
 | |
|                 static_cast<uint32_t>(height),
 | |
|                 {},
 | |
|             },
 | |
|         };
 | |
| 
 | |
| 		auto pixels_blob = Assets::Blob {};
 | |
| 		pixels_blob.resize(static_cast<size_t>(width) * height * channels);
 | |
| 
 | |
| 		// TODO(Light): figure out if it's possible to directly populate a blob with stbi functions
 | |
| 		memcpy(pixels_blob.data(), pixels, pixels_blob.size());
 | |
| 		stbi_image_free(pixels);
 | |
| 
 | |
| 		return Assets::TextureAsset::PackageData {
 | |
| 			.metadata = metadata,
 | |
| 			.texture_metadata = texture_metadata,
 | |
| 			.pixels = std::move(pixels_blob),
 | |
| 		};
 | |
| 	}
 | |
| };
 | |
| 
 | |
| class TextureLoaderFactory
 | |
| {
 | |
| public:
 | |
| 	static auto create(std::string_view file_extension) -> std::unique_ptr<TextureLoader>
 | |
| 	{
 | |
| 		if (StbLoader::get_supported_extensions().contains(file_extension))
 | |
| 		{
 | |
| 			return std::make_unique<StbLoader>();
 | |
| 		}
 | |
| 
 | |
| 		return {};
 | |
| 	}
 | |
| };
 | |
| 
 | |
| class TextLoader: Loader
 | |
| {
 | |
| public:
 | |
| 	[[nodiscard]] static auto get_supported_extensions() -> std::unordered_set<std::string_view>
 | |
| 	{
 | |
| 		return { ".glsl", ".txt", ".hlsl" };
 | |
| 	}
 | |
| 
 | |
| 	[[nodiscard]] auto get_name() const -> std::string_view override
 | |
| 	{
 | |
| 		return "TextLoader";
 | |
| 	}
 | |
| 
 | |
| 	[[nodiscard]] auto load(const std::filesystem::path &file_path) const
 | |
| 	    -> Assets::TextAsset::PackageData
 | |
| 	{
 | |
| 		auto stream = std::ifstream { file_path, std::ios::binary };
 | |
| 		if (!stream.good())
 | |
| 		{
 | |
| 			throw std::runtime_error {
 | |
| 				std::format(
 | |
| 				    "Failed to open ifstream for text loading of file: {}",
 | |
| 				    file_path.string()
 | |
| 				),
 | |
| 			};
 | |
| 		}
 | |
| 
 | |
| 		auto file_size = std::filesystem::file_size(file_path);
 | |
| 
 | |
| 		auto text_blob = Assets::Blob(file_size);
 | |
| 
 | |
| 		stream.read((char *)(text_blob.data()), static_cast<long>(file_size)); // NOLINT
 | |
| 
 | |
| 		const auto metadata = Assets::Asset::Metadata {
 | |
| 			.type = Assets::Asset::Type::Text,
 | |
| 		};
 | |
| 
 | |
| 		const auto text_metadata = Assets::TextAsset::Metadata {
 | |
| 			.lines = {},
 | |
| 		};
 | |
| 
 | |
| 		return Assets::TextAsset::PackageData {
 | |
| 			.metadata = metadata,
 | |
| 			.text_metadata = {},
 | |
| 			.text_blob = std::move(text_blob),
 | |
| 		};
 | |
| 	}
 | |
| };
 | |
| 
 | |
| class TextLoaderFactory
 | |
| {
 | |
| public:
 | |
| 	static auto create(std::string_view file_extension) -> std::unique_ptr<TextLoader>
 | |
| 	{
 | |
| 		if (TextLoader::get_supported_extensions().contains(file_extension))
 | |
| 		{
 | |
| 			return std::make_unique<TextLoader>();
 | |
| 		}
 | |
| 
 | |
| 		return {};
 | |
| 	}
 | |
| };
 | |
| 
 | |
| } // namespace lt
 |