#include #include "SDL3/SDL_pixels.h" #include "Sprite.hpp" #include "physfs.h" #define STB_IMAGE_IMPLEMENTATION #include "../stb_image.h" namespace Slate { Sprite Sprite::FromFile(SDL_Renderer *renderer, std::string path) { Sprite sprite{}; SDL_Surface *surface = nullptr; if (!PHYSFS_exists(path.c_str())) { throw std::runtime_error(std::format("File not found: {}", path)); } PHYSFS_file *file = PHYSFS_openRead(path.c_str()); const PHYSFS_sint64 length = PHYSFS_fileLength(file); auto *buffer = new unsigned char[length]; PHYSFS_readBytes(file, buffer, length); PHYSFS_close(file); int width, height, channels; unsigned char *image = stbi_load_from_memory( buffer, static_cast(length), &width, &height, &channels, 4 ); if (!image) { delete[] buffer; throw std::runtime_error(std::format("Failed to parse image: {}", path)); } surface = SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_ABGR8888, image, width * channels); if (surface == nullptr) { throw std::runtime_error(std::format("Unable to load spritesheet file: {}", path)); } sprite.texture = SDL_CreateTextureFromSurface(renderer, surface); sprite.rect.w = static_cast(sprite.texture->w); sprite.rect.h = static_cast(sprite.texture->h); sprite.rect.x = sprite.rect.y = 0; SDL_SetTextureScaleMode(sprite.texture, SDL_SCALEMODE_NEAREST); SDL_DestroySurface(surface); return sprite; } Sprite Sprite::FromXML(SDL_Renderer *renderer, tinyxml2::XMLElement *element) { const char *path; element->QueryStringAttribute("texture", &path); Sprite sprite = FromFile(renderer, path); const auto *rect = element->FirstChildElement(); rect->QueryFloatAttribute("x", &sprite.rect.x); rect->QueryFloatAttribute("y", &sprite.rect.y); rect->QueryFloatAttribute("w", &sprite.rect.w); rect->QueryFloatAttribute("h", &sprite.rect.h); return sprite; } }