165 lines
3.8 KiB
C++
165 lines
3.8 KiB
C++
|
|
#include "std.h"
|
|
#include "cachedtexture.h"
|
|
|
|
int active_texs;
|
|
|
|
extern gxRuntime *gx_runtime;
|
|
extern gxGraphics *gx_graphics;
|
|
|
|
set<CachedTexture::Rep*> CachedTexture::rep_set;
|
|
|
|
static string path;
|
|
|
|
struct CachedTexture::Rep{
|
|
int ref_cnt;
|
|
string file;
|
|
int flags,w,h,first;
|
|
vector<gxCanvas*> frames;
|
|
|
|
Rep( int w,int h,int flags,int cnt ):
|
|
ref_cnt(1),flags(flags),w(w),h(h),first(0){
|
|
++active_texs;
|
|
while( cnt-->0 ){
|
|
if( gxCanvas *t=gx_graphics->createCanvas( w,h,flags ) ){
|
|
frames.push_back( t );
|
|
}else break;
|
|
}
|
|
}
|
|
|
|
Rep( const string &f,int flags,int w,int h,int first,int cnt ):
|
|
ref_cnt(1),file(f),flags(flags),w(w),h(h),first(first){
|
|
++active_texs;
|
|
if( !(flags & gxCanvas::CANVAS_TEX_CUBE) ){
|
|
if( w<=0 || h<=0 || first<0 || cnt<=0 ){
|
|
w=h=first=0;
|
|
if( gxCanvas *t=gx_graphics->loadCanvas( f,flags ) ){
|
|
frames.push_back( t );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
int t_flags=flags & (
|
|
gxCanvas::CANVAS_TEX_RGB|
|
|
gxCanvas::CANVAS_TEX_ALPHA|
|
|
gxCanvas::CANVAS_TEX_MASK|
|
|
gxCanvas::CANVAS_TEX_HICOLOR ) | gxCanvas::CANVAS_NONDISPLAY;
|
|
|
|
gxCanvas *t=gx_graphics->loadCanvas( f,t_flags );
|
|
if( !t ) return;
|
|
if( !t->getDepth() ){
|
|
gx_graphics->freeCanvas( t );
|
|
return;
|
|
}
|
|
|
|
if( flags & gxCanvas::CANVAS_TEX_CUBE ){
|
|
int w=t->getWidth()/6;
|
|
if( w*6!=t->getWidth() ) return;
|
|
int h=t->getHeight();
|
|
|
|
gxCanvas *tex=gx_graphics->createCanvas( w,h,flags );
|
|
if( tex ){
|
|
frames.push_back( tex );
|
|
|
|
for( int face=0;face<6;++face ){
|
|
tex->setCubeFace(face);
|
|
gx_graphics->copy( tex,0,0,tex->getWidth(),tex->getHeight(),t,face*w,0,w,h );
|
|
}
|
|
tex->setCubeFace(1);
|
|
}
|
|
}else{
|
|
int x_tiles=t->getWidth()/w;
|
|
int y_tiles=t->getHeight()/h;
|
|
if( first+cnt>x_tiles*y_tiles ){
|
|
gx_graphics->freeCanvas( t );
|
|
return;
|
|
}
|
|
int x=(first%x_tiles)*w;
|
|
int y=(first/x_tiles)*h;
|
|
while( cnt-- ){
|
|
gxCanvas *p=gx_graphics->createCanvas( w,h,flags );
|
|
gx_graphics->copy( p,0,0,p->getWidth(),p->getHeight(),t,x,y,w,h );
|
|
frames.push_back(p);
|
|
x=x+w;if( x+w>t->getWidth() ){ x=0;y=y+h; }
|
|
}
|
|
}
|
|
gx_graphics->freeCanvas( t );
|
|
}
|
|
|
|
~Rep(){
|
|
--active_texs;
|
|
for( int k=0;k<frames.size();++k ) gx_graphics->freeCanvas( frames[k] );
|
|
}
|
|
};
|
|
|
|
CachedTexture::Rep *CachedTexture::findRep( const string &f,int flags,int w,int h,int first,int cnt ){
|
|
set<Rep*>::const_iterator it;
|
|
for( it=rep_set.begin();it!=rep_set.end();++it ){
|
|
Rep *rep=*it;
|
|
if( rep->file==f && rep->flags==flags && rep->w==w && rep->h==h && rep->first==first && rep->frames.size()==cnt ){
|
|
++rep->ref_cnt;return rep;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
CachedTexture::CachedTexture( int w,int h,int flags,int cnt ):
|
|
rep(d_new Rep(w,h,flags,cnt)){
|
|
}
|
|
|
|
CachedTexture::CachedTexture( const string &f_,int flags,int w,int h,int first,int cnt ){
|
|
string f=f_;
|
|
if( f.substr(0,2)==".\\" ) f=f.substr(2);
|
|
if( path.size() ){
|
|
string t=path+tolower( filenamefile( f ) );
|
|
if( rep=findRep( t,flags,w,h,first,cnt ) ) return;
|
|
rep=d_new Rep( t,flags,w,h,first,cnt );
|
|
if( rep->frames.size() ){
|
|
rep_set.insert( rep );
|
|
return;
|
|
}
|
|
delete rep;
|
|
}
|
|
string t=tolower( fullfilename( f ) );
|
|
if( rep=findRep( t,flags,w,h,first,cnt ) ) return;
|
|
rep=d_new Rep( t,flags,w,h,first,cnt );
|
|
rep_set.insert( rep );
|
|
}
|
|
|
|
CachedTexture::CachedTexture( const CachedTexture &t ):
|
|
rep(t.rep){
|
|
++rep->ref_cnt;
|
|
}
|
|
|
|
CachedTexture::~CachedTexture(){
|
|
if( !--rep->ref_cnt ){
|
|
rep_set.erase( rep );
|
|
delete rep;
|
|
}
|
|
}
|
|
|
|
CachedTexture &CachedTexture::operator=( const CachedTexture &t ){
|
|
++t.rep->ref_cnt;
|
|
if( !--rep->ref_cnt ){
|
|
rep_set.erase( rep );
|
|
delete rep;
|
|
}
|
|
rep=t.rep;
|
|
return *this;
|
|
}
|
|
|
|
string CachedTexture::getName()const{
|
|
return rep->file;
|
|
}
|
|
|
|
const vector<gxCanvas*> &CachedTexture::getFrames()const{
|
|
return rep->frames;
|
|
}
|
|
|
|
void CachedTexture::setPath( const string &t ){
|
|
path=tolower(t);
|
|
if( int sz=path.size() ){
|
|
if( path[sz-1]!='/' && path[sz-1]!='\\' ) path+='\\';
|
|
}
|
|
} |