#include "textures.hpp" #include #include "../GUI/exceptions.hpp" namespace ougge::Resources { Texture::Texture(const Resource& r, SDL_Renderer* renderer) : Texture(*r.openStream(), r.size, renderer) {} Texture::Texture(std::istream& s, size_t size, SDL_Renderer* renderer) : renderer(renderer), texture(nullptr), w(0), h(0) { SDL_RWops* sdl_stream = SDL_RWFromIStream(s, size); if(!sdl_stream) throw SDLException(); texture = std::shared_ptr(IMG_LoadTexture_RW(renderer, sdl_stream, 1), SDL_DestroyTexture); if(!texture) throw IMGException(); SDL_TRY(SDL_QueryTexture(texture.get(), nullptr, nullptr, &w, &h)); } SDL_RenderCopyExF_Params::SDL_RenderCopyExF_Params() : rotation_angle(0), flip(SDL_FLIP_NONE) {} void Texture::render(const SDL_FRect& target_section){ SDL_TRY( SDL_RenderCopyF(renderer, texture.get(), nullptr, &target_section) ); } void Texture::render(const SDL_FRect& target_section, const SDL_Rect& texture_section){ SDL_TRY( SDL_RenderCopyF(renderer, texture.get(), &texture_section, &target_section) ); } void Texture::render(const SDL_RenderCopyExF_Params& p){ SDL_TRY( SDL_RenderCopyExF(renderer, texture.get(), optional_value_ptr_or_null(p.texture_section), optional_value_ptr_or_null(p.target_section), -1.0f * angleToDegree(normalizeAngle(p.rotation_angle)), optional_value_ptr_or_null(p.rotation_center), p.flip ) ) } static Sint64 istream_size(SDL_RWops* context){ return (Sint64)(size_t)context->hidden.unknown.data2; } static Sint64 istream_seek(SDL_RWops* context, Sint64 offset, int whence){ std::istream* stream = (std::istream*)context->hidden.unknown.data1; switch(whence){ case SEEK_SET: stream->seekg(offset, std::ios::beg); break; case SEEK_CUR: stream->seekg(offset, std::ios::cur); break; case SEEK_END: stream->seekg(offset, std::ios::end); break; default: break; } return stream->fail() ? -1 : (Sint64)stream->tellg(); } static size_t istream_read(SDL_RWops* context, void *ptr, size_t size, size_t maxnum){ if(size == 0) return -1; std::istream* stream = (std::istream*)context->hidden.unknown.data1; stream->read((char*)ptr, size * maxnum); return stream->bad() ? -1 : stream->gcount() / size; } static int istream_close(SDL_RWops* context){ if (context) SDL_FreeRW(context); return 0; } SDL_RWops* SDL_RWFromIStream(std::istream& stream, size_t size){ SDL_RWops* rwops = SDL_AllocRW(); if(rwops) { rwops->size = istream_size; rwops->seek = istream_seek; rwops->read = istream_read; rwops->write = nullptr; rwops->close = istream_close; rwops->hidden.unknown.data1 = &stream; rwops->hidden.unknown.data2 = (void*)size; rwops->type = SDL_RWOPS_UNKNOWN; } return rwops; } }