97 lines
2.9 KiB
C++
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;
|
|
}
|
|
|
|
}
|