ougge/src/Resources/textures.cpp
2024-08-16 19:32:36 +03:00

97 lines
2.9 KiB
C++

#include "textures.hpp"
#include <SDL_image.h>
#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<SDL_Texture>(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;
}
}