196 lines
4.8 KiB
C++
196 lines
4.8 KiB
C++
|
|
#include "std.h"
|
|
#include "geom.h"
|
|
#include "texture.h"
|
|
#include "cachedtexture.h"
|
|
|
|
#include "../gxruntime/gxgraphics.h"
|
|
|
|
extern gxScene *gx_scene;
|
|
extern gxGraphics *gx_graphics;
|
|
|
|
struct Filter {
|
|
string t;
|
|
int flags;
|
|
Filter(const string &t, int flags) :t(t), flags(flags) {
|
|
}
|
|
};
|
|
|
|
static vector<Filter> filters;
|
|
|
|
static int filterFile(const string &t, int flags) {
|
|
//check filters...
|
|
string l = tolower(t);
|
|
for (int k = 0; k < filters.size(); ++k) {
|
|
if (l.find(filters[k].t) != string::npos) {
|
|
flags |= filters[k].flags;
|
|
}
|
|
}
|
|
return flags;
|
|
}
|
|
|
|
struct Texture::Rep {
|
|
|
|
int ref_cnt;
|
|
CachedTexture cached_tex;
|
|
vector<gxCanvas*> tex_frames;
|
|
|
|
int tex_blend, tex_flags;
|
|
bool transparent;
|
|
|
|
float sx, sy, tx, ty, rot;
|
|
bool mat_used, mat_valid;
|
|
gxScene::Matrix matrix;
|
|
|
|
Rep(int w, int h, int flags, int cnt) :
|
|
ref_cnt(1), cached_tex(w, h, flags, cnt),
|
|
tex_blend(gxScene::BLEND_MULTIPLY), tex_flags(0),
|
|
sx(1), sy(1), tx(0), ty(0), rot(0), mat_used(false) {
|
|
tex_frames = cached_tex.getFrames();
|
|
transparent =
|
|
(flags & gxCanvas::CANVAS_TEX_ALPHA) &&
|
|
!(flags & gxCanvas::CANVAS_TEX_MASK);
|
|
memset(&matrix, 0, sizeof(matrix));
|
|
}
|
|
|
|
Rep(const string &f, int flags, int w, int h, int first, int cnt) :
|
|
ref_cnt(1), cached_tex(f, flags, w, h, first, cnt),
|
|
tex_blend(gxScene::BLEND_MULTIPLY), tex_flags(0),
|
|
sx(1), sy(1), tx(0), ty(0), rot(0), mat_used(false) {
|
|
tex_frames = cached_tex.getFrames();
|
|
transparent =
|
|
(flags & gxCanvas::CANVAS_TEX_ALPHA) &&
|
|
!(flags & gxCanvas::CANVAS_TEX_MASK);
|
|
memset(&matrix, 0, sizeof(matrix));
|
|
}
|
|
|
|
Rep(const Rep &t) :
|
|
ref_cnt(1), cached_tex(t.cached_tex), tex_frames(t.tex_frames),
|
|
tex_blend(t.tex_blend), tex_flags(t.tex_flags),
|
|
sx(t.sx), sy(t.sy), tx(t.tx), ty(t.ty), rot(t.rot),
|
|
mat_used(t.mat_used), mat_valid(t.mat_valid), matrix(t.matrix),
|
|
transparent(t.transparent) {
|
|
}
|
|
};
|
|
|
|
Texture::Texture() :rep(0) {
|
|
}
|
|
|
|
Texture::Texture(const string &f, int flags) {
|
|
flags = filterFile(f, flags) | gxCanvas::CANVAS_TEXTURE;
|
|
if (flags & gxCanvas::CANVAS_TEX_MASK) flags |= gxCanvas::CANVAS_TEX_RGB | gxCanvas::CANVAS_TEX_ALPHA;
|
|
rep = d_new Rep(f, flags, 0, 0, 0, 1);
|
|
}
|
|
|
|
Texture::Texture(const string &f, int flags, int w, int h, int first, int cnt) {
|
|
flags = filterFile(f, flags) | gxCanvas::CANVAS_TEXTURE;
|
|
if (flags & gxCanvas::CANVAS_TEX_MASK) flags |= gxCanvas::CANVAS_TEX_RGB | gxCanvas::CANVAS_TEX_ALPHA;
|
|
rep = d_new Rep(f, flags, w, h, first, cnt);
|
|
}
|
|
|
|
Texture::Texture(int w, int h, int flags, int cnt) {
|
|
flags |= gxCanvas::CANVAS_TEXTURE;
|
|
if (flags & gxCanvas::CANVAS_TEX_MASK) flags |= gxCanvas::CANVAS_TEX_RGB | gxCanvas::CANVAS_TEX_ALPHA;
|
|
rep = d_new Rep(w, h, flags, cnt);
|
|
}
|
|
|
|
Texture::Texture(const Texture &t) :
|
|
rep(t.rep) {
|
|
if (rep) ++rep->ref_cnt;
|
|
}
|
|
|
|
Texture::~Texture() {
|
|
if (rep && !--rep->ref_cnt) delete rep;
|
|
}
|
|
|
|
Texture &Texture::operator=(const Texture &t) {
|
|
if (t.rep) ++t.rep->ref_cnt;
|
|
if (rep && !--rep->ref_cnt) delete rep;
|
|
rep = t.rep;
|
|
return *this;
|
|
}
|
|
|
|
void Texture::setScale(float u_scale, float v_scale) {
|
|
if (!rep) return;
|
|
rep->sx = u_scale; rep->sy = v_scale;
|
|
rep->mat_valid = false;
|
|
rep->mat_used = true;
|
|
}
|
|
|
|
void Texture::setRotation(float angle) {
|
|
if (!rep) return;
|
|
rep->rot = angle;
|
|
rep->mat_valid = false;
|
|
rep->mat_used = true;
|
|
}
|
|
|
|
void Texture::setPosition(float u_pos, float v_pos) {
|
|
if (!rep) return;
|
|
rep->tx = u_pos;
|
|
rep->ty = v_pos;
|
|
rep->mat_valid = false;
|
|
rep->mat_used = true;
|
|
}
|
|
|
|
void Texture::setBlend(int blend) {
|
|
if (!rep) return;
|
|
rep->tex_blend = blend;
|
|
}
|
|
|
|
void Texture::setFlags(int flags) {
|
|
if (!rep) return;
|
|
rep->tex_flags = flags;
|
|
}
|
|
|
|
bool Texture::isTransparent()const {
|
|
return rep ? rep->transparent : false;
|
|
}
|
|
|
|
gxCanvas *Texture::getCanvas(int n)const {
|
|
return rep && n >= 0 && n < rep->tex_frames.size() ? rep->tex_frames[n] : 0;
|
|
}
|
|
|
|
int Texture::getCanvasFlags()const {
|
|
return rep && rep->tex_frames.size() ? rep->tex_frames[0]->getFlags() : 0;
|
|
}
|
|
|
|
CachedTexture *Texture::getCachedTexture()const {
|
|
return rep ? &rep->cached_tex : 0;
|
|
}
|
|
|
|
int Texture::getBlend()const {
|
|
return rep ? rep->tex_blend : 0;
|
|
}
|
|
|
|
int Texture::getFlags()const {
|
|
return rep ? rep->tex_flags : 0;
|
|
}
|
|
|
|
const gxScene::Matrix *Texture::getMatrix()const {
|
|
if (!rep || !rep->mat_used) return 0;
|
|
if (!rep->mat_valid) {
|
|
float c = cos(rep->rot), s = sin(rep->rot);
|
|
rep->matrix.elements[0][0] = c*rep->sx;
|
|
rep->matrix.elements[1][0] = s*rep->sx;
|
|
rep->matrix.elements[0][1] = -s*rep->sy;
|
|
rep->matrix.elements[1][1] = c*rep->sy;
|
|
rep->matrix.elements[2][0] = rep->tx;
|
|
rep->matrix.elements[2][1] = rep->ty;
|
|
rep->mat_valid = true;
|
|
}
|
|
return &rep->matrix;
|
|
}
|
|
|
|
bool Texture::operator<(const Texture &t)const {
|
|
if (rep && t.rep) return rep->cached_tex < t.rep->cached_tex;
|
|
return rep < t.rep;
|
|
}
|
|
|
|
void Texture::clearFilters() {
|
|
filters.clear();
|
|
}
|
|
|
|
void Texture::addFilter(const string &t, int flags) {
|
|
filters.push_back(Filter(tolower(t), flags));
|
|
}
|