#include "std.h" #include "bbgraphics.h" #include "bbinput.h" gxGraphics *gx_graphics; gxCanvas *gx_canvas; struct GfxMode{ int w,h,d,caps; }; class bbImage{ public: bbImage( const vector &f ):frames(f){ } ~bbImage(){ for( int k=0;kfreeCanvas( frames[k] ); } } const vector &getFrames()const{ return frames; } void replaceFrame( int n,gxCanvas *c ){ gx_graphics->freeCanvas( frames[n] ); frames[n]=c; } private: vector frames; }; //degrees to radians static const float dtor=0.0174532925199432957692369076848861f; static int gx_driver; //current graphics driver static bool filter; static bool auto_dirty; static bool auto_midhandle; static set image_set; static int curs_x,curs_y; static gxCanvas *p_canvas; static gxFont *curr_font; static unsigned curr_color; static unsigned curr_clsColor; static vector gfx_modes; static inline void debugImage( bbImage *i,int frame=0 ){ if( debug ){ if( !image_set.count(i) ) RTEX( "Image does not exist" ); if( frame>=i->getFrames().size() ) RTEX( "Image frame out of range" ); } } static inline void debugFont( gxFont *f ){ if( debug ){ if( !gx_graphics->verifyFont( f ) ) RTEX( "Font does not exist" ); } } static inline void debugCanvas( gxCanvas *c ){ if( debug ){ if( !gx_graphics->verifyCanvas( c ) ) RTEX( "Buffer does not exist" ); } } static inline void debugDriver( int n ){ if( debug ){ if( n<1 || n>gx_runtime->numGraphicsDrivers() ){ RTEX( "Illegal graphics driver index" ); } } } static inline void debugMode( int n ){ if( debug ){ if( n<1 || n>gfx_modes.size() ){ RTEX( "Illegal graphics mode index" ); } } } void bbFreeImage( bbImage *i ); static void freeGraphics(){ #ifdef PRO extern void blitz3d_close(); blitz3d_close(); #endif while( image_set.size() ) bbFreeImage( *image_set.begin() ); if( p_canvas ){ gx_graphics->freeCanvas( p_canvas ); p_canvas=0; } } #define RED(_X_) ( ((_X_)>>16) & 0xff ) #define GRN(_X_) ( ((_X_)>>8) & 0xff ) #define BLU(_X_) ( (_X_) & 0xff ) static int getPixel( gxCanvas *c,float x,float y ){ debugCanvas( c ); x-=.5f;y-=.5f; float fx=floor(x),fy=floor(y); int ix=fx,iy=fy;fx=x-fx;fy=y-fy; int tl=c->getPixel( ix,iy ); int tr=c->getPixel( ix+1,iy ); int br=c->getPixel( ix+1,iy+1 ); int bl=c->getPixel( ix,iy+1 ); float w1=(1-fx)*(1-fy),w2=fx*(1-fy),w3=(1-fx)*fy,w4=fx*fy; float r=RED(tl)*w1+RED(tr)*w2+RED(bl)*w3+RED(br)*w4; float g=GRN(tl)*w1+GRN(tr)*w2+GRN(bl)*w3+GRN(br)*w4; float b=BLU(tl)*w1+BLU(tr)*w2+BLU(bl)*w3+BLU(br)*w4; return (int(r+.5f)<<16)|(int(g+.5f)<<8)|int(b+.5f); } struct vec2{ float x,y; }; static vec2 vrot( float m[2][2],const vec2 &v ){ vec2 t;t.x=m[0][0]*v.x+m[0][1]*v.y;t.y=m[1][0]*v.x+m[1][1]*v.y; return t; } static float vmin( float a,float b,float c,float d ){ float t=a;if( bt ) t=b;if( c>t ) t=c;if( d>t ) t=d;return t; } static gxCanvas *tformCanvas( gxCanvas *c,float m[2][2],int x_handle,int y_handle ){ vec2 v,v0,v1,v2,v3; float i[2][2]; float dt=1.0f/(m[0][0]*m[1][1]-m[1][0]*m[0][1]); i[0][0]=dt*m[1][1];i[1][0]=-dt*m[1][0]; i[0][1]=-dt*m[0][1];i[1][1]=dt*m[0][0]; float ox=x_handle,oy=y_handle; v0.x=-ox;v0.y=-oy; //tl v1.x=c->getWidth()-ox;v1.y=-oy; //tr v2.x=c->getWidth()-ox;v2.y=c->getHeight()-oy; //br v3.x=-ox;v3.y=c->getHeight()-oy; //bl v0=vrot(m,v0);v1=vrot(m,v1);v2=vrot(m,v2);v3=vrot(m,v3); float minx=floor( vmin( v0.x,v1.x,v2.x,v3.x ) ); float miny=floor( vmin( v0.y,v1.y,v2.y,v3.y ) ); float maxx=ceil( vmax( v0.x,v1.x,v2.x,v3.x ) ); float maxy=ceil( vmax( v0.y,v1.y,v2.y,v3.y ) ); int iw=maxx-minx,ih=maxy-miny; gxCanvas *t=gx_graphics->createCanvas( iw,ih,0 ); t->setHandle( -minx,-miny ); t->setMask( c->getMask() ); c->lock(); t->lock(); v.y=miny+.5f; for( int y=0;ygetPixel( floor(q.x+ox),floor(q.y+oy) ); t->setPixel( x,y,rgb ); } } t->unlock(); c->unlock(); return t; } static bool saveCanvas( gxCanvas *c,const string &f ){ ofstream out( f.c_str(),ios::binary ); if( !out.good() ) return false; int tempsize=(c->getWidth()*3+3)&~3; BITMAPFILEHEADER bf; memset( &bf,0,sizeof(bf) ); bf.bfType='MB'; bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+tempsize*c->getHeight(); bf.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); BITMAPINFOHEADER bi;memset( &bi,0,sizeof(bi) ); bi.biSize=sizeof(bi); bi.biWidth=c->getWidth(); bi.biHeight=c->getHeight(); bi.biPlanes=1; bi.biBitCount=24; out.write( (char*)&bf,sizeof(bf) ); out.write( (char*)&bi,sizeof(bi) ); unsigned char *temp=d_new unsigned char[ tempsize ]; memset( temp,0,tempsize ); c->lock(); for( int y=c->getHeight()-1;y>=0;--y ){ unsigned char *dest=temp; for( int x=0;xgetWidth();++x ){ unsigned rgb=c->getPixelFast( x,y ); *dest++=rgb&0xff; *dest++=(rgb>>8)&0xff; *dest++=(rgb>>16)&0xff; } out.write( (char*)temp,tempsize ); } c->unlock(); delete [] temp; return out.good(); } int bbCountGfxDrivers(){ return gx_runtime->numGraphicsDrivers(); } BBStr * bbGfxDriverName( int n ){ debugDriver( n ); string t;int caps; gx_runtime->graphicsDriverInfo( n-1,&t,&caps ); return d_new BBStr( t ); } void bbSetGfxDriver( int n ){ debugDriver( n ); gfx_modes.clear(); gx_driver=n-1; } int bbCountGfxModes(){ gfx_modes.clear(); int n=gx_runtime->numGraphicsModes( gx_driver ); for( int k=0;kgraphicsModeInfo( gx_driver,k,&m.w,&m.h,&m.d,&m.caps ); gfx_modes.push_back( m ); } return gfx_modes.size(); } int bbGfxModeWidth( int n ){ debugMode( n ); return gfx_modes[n-1].w; } int bbGfxModeHeight( int n ){ debugMode( n ); return gfx_modes[n-1].h; } int bbGfxModeDepth( int n ){ debugMode( n ); return gfx_modes[n-1].d; } static int modeExists( int w,int h,int d,bool bb3d ){ int cnt=gx_runtime->numGraphicsModes( gx_driver ); for( int k=0;kgraphicsModeInfo( gx_driver,k,&tw,&th,&td,&tc ); if( bb3d && !(tc&gxRuntime::GFXMODECAPS_3D) ) continue; if( w==tw && h==th && d==td ) return 1; } return 0; } int bbGfxModeExists( int w,int h,int d ){ return modeExists( w,h,d,false ); } #ifdef PRO int bbGfxDriver3D( int n ){ debugDriver( n ); string t;int caps; gx_runtime->graphicsDriverInfo( n-1,&t,&caps ); return (caps & gxRuntime::GFXMODECAPS_3D) ? 1 : 0; } int bbCountGfxModes3D(){ gfx_modes.clear(); int n=gx_runtime->numGraphicsModes( gx_driver ); for( int k=0;kgraphicsModeInfo( gx_driver,k,&m.w,&m.h,&m.d,&m.caps ); if( m.caps & gxRuntime::GFXMODECAPS_3D) gfx_modes.push_back( m ); } return gfx_modes.size(); } int bbGfxMode3DExists( int w,int h,int d ){ return modeExists( w,h,d,true ); } int bbGfxMode3D( int n ){ debugMode( n ); return gfx_modes[n-1].caps & gxRuntime::GFXMODECAPS_3D ? 1 :0; } int bbWindowed3D(){ int tc; gx_runtime->windowedModeInfo( &tc ); return (tc & gxRuntime::GFXMODECAPS_3D) ? 1 : 0; } #endif int bbTotalVidMem(){ return gx_graphics->getTotalVidmem(); } int bbAvailVidMem(){ return gx_graphics->getAvailVidmem(); } void bbSetBuffer( gxCanvas *buff ){ debugCanvas( buff ); gx_canvas=buff; curs_x=curs_y=0; gx_canvas->setOrigin( 0,0 ); gx_canvas->setViewport( 0,0,gx_canvas->getWidth(),gx_canvas->getHeight() ); gx_canvas->setColor( curr_color ); gx_canvas->setClsColor( curr_clsColor ); gx_canvas->setFont( curr_font ); } gxCanvas *bbGraphicsBuffer(){ return gx_canvas; } int bbLoadBuffer( gxCanvas *c,BBStr *str ){ debugCanvas( c ); string s=*str;delete str; gxCanvas *t=gx_graphics->loadCanvas( s,0 ); if( !t ) return 0; float m[2][2]; m[0][0]=(float)c->getWidth()/(float)t->getWidth(); m[1][1]=(float)c->getHeight()/(float)t->getHeight(); m[1][0]=m[0][1]=0; gxCanvas *p=tformCanvas( t,m,0,0 ); gx_graphics->freeCanvas( t ); int ox,oy; c->getOrigin( &ox,&oy );c->setOrigin( 0,0 ); c->blit( 0,0,p,0,0,p->getWidth(),p->getHeight(),true ); gx_graphics->freeCanvas( p ); return 1; } int bbSaveBuffer( gxCanvas *c,BBStr *str ){ debugCanvas( c ); string t=*str;delete str; return saveCanvas( c,t ) ? 1 : 0; } void bbBufferDirty( gxCanvas *c ){ debugCanvas( c ); c->backup(); } static void graphics( int w,int h,int d,int flags ){ freeGraphics(); gx_runtime->closeGraphics( gx_graphics ); gx_graphics=gx_runtime->openGraphics( w,h,d,gx_driver,flags ); if( !gx_runtime->idle() ) RTEX( 0 ); if( !gx_graphics ){ RTEX( "Unable to set graphics mode" ); } curr_clsColor=0; curr_color=0xffffffff; curr_font=gx_graphics->getDefaultFont(); gxCanvas *buff=(flags & gxGraphics::GRAPHICS_3D) ? gx_graphics->getBackCanvas() : gx_graphics->getFrontCanvas(); bbSetBuffer( buff ); } void bbGraphics( int w,int h,int d,int mode ){ int flags=0; switch( mode ){ case 0:flags|=debug ? gxGraphics::GRAPHICS_WINDOWED : 0 ;break; case 1:break; case 2:flags|=gxGraphics::GRAPHICS_WINDOWED;break; case 3:flags|=gxGraphics::GRAPHICS_WINDOWED|gxGraphics::GRAPHICS_SCALED;break; case 6:flags|=gxGraphics::GRAPHICS_WINDOWED|gxGraphics::GRAPHICS_AUTOSUSPEND;break; case 7:flags|=gxGraphics::GRAPHICS_WINDOWED|gxGraphics::GRAPHICS_SCALED|gxGraphics::GRAPHICS_AUTOSUSPEND;break; default:RTEX( "Illegal Graphics mode" ); } graphics( w,h,d,flags ); } #ifdef PRO void bbGraphics3D( int w,int h,int d,int mode ){ int flags=gxGraphics::GRAPHICS_3D; switch( mode ){ case 0:flags|=(debug && bbWindowed3D()) ? gxGraphics::GRAPHICS_WINDOWED : 0 ;break; case 1:break; case 2:flags|=gxGraphics::GRAPHICS_WINDOWED;break; case 3:flags|=gxGraphics::GRAPHICS_WINDOWED|gxGraphics::GRAPHICS_SCALED;break; case 6:flags|=gxGraphics::GRAPHICS_WINDOWED|gxGraphics::GRAPHICS_AUTOSUSPEND;break; case 7:flags|=gxGraphics::GRAPHICS_WINDOWED|gxGraphics::GRAPHICS_SCALED|gxGraphics::GRAPHICS_AUTOSUSPEND;break; default:RTEX( "Illegal Graphics3D mode" ); } graphics( w,h,d,flags ); extern void blitz3d_open(); blitz3d_open(); } #endif void bbEndGraphics(){ freeGraphics(); gx_runtime->closeGraphics( gx_graphics ); gx_graphics=gx_runtime->openGraphics( 400,300,0,0,gxGraphics::GRAPHICS_WINDOWED ); if( !gx_runtime->idle() ) RTEX( 0 ); if( gx_graphics ){ curr_clsColor=0; curr_color=0xffffffff; curr_font=gx_graphics->getDefaultFont(); bbSetBuffer( gx_graphics->getFrontCanvas() ); return; } RTEX( "Unable to set graphics mode" ); } int bbGraphicsLost(){ return gx_runtime->graphicsLost(); } void bbSetGamma( int r,int g,int b,float dr,float dg,float db ){ if( dr<0 ) dr=0; else if( dr>255.0f ) dr=255.0f; if( dg<0 ) dg=0; else if( dg>255.0f ) dg=255.0f; if( db<0 ) db=0; else if( db>255.0f ) db=255.0f; gx_graphics->setGamma( r,g,b,dr,dg,db ); } void bbUpdateGamma( int calibrate ){ gx_graphics->updateGamma( !!calibrate ); } float bbGammaRed( int n ){ float dr,dg,db; gx_graphics->getGamma( n,n,n,&dr,&dg,&db ); return dr; } float bbGammaGreen( int n ){ float dr,dg,db; gx_graphics->getGamma( n,n,n,&dr,&dg,&db ); return dg; } float bbGammaBlue( int n ){ float dr,dg,db; gx_graphics->getGamma( n,n,n,&dr,&dg,&db ); return db; } gxCanvas *bbFrontBuffer(){ return gx_graphics->getFrontCanvas(); } gxCanvas *bbBackBuffer(){ return gx_graphics->getBackCanvas(); } void bbLockBuffer( gxCanvas *buff ){ if( buff ) debugCanvas( buff ); (buff ? buff : gx_canvas)->lock(); } void bbUnlockBuffer( gxCanvas *buff ){ if( buff ) debugCanvas( buff ); (buff ? buff : gx_canvas)->unlock(); } int bbReadPixel( int x,int y,gxCanvas *buff ){ if( buff ) debugCanvas( buff ); return (buff ? buff : gx_canvas)->getPixel( x,y ); } void bbWritePixel( int x,int y,int argb,gxCanvas *buff ){ if( buff ) debugCanvas( buff ); (buff ? buff : gx_canvas)->setPixel( x,y,argb ); } int bbReadPixelFast( int x,int y,gxCanvas *buff ){ return (buff ? buff : gx_canvas)->getPixelFast( x,y ); } void bbWritePixelFast( int x,int y,int argb,gxCanvas *buff ){ (buff ? buff : gx_canvas)->setPixelFast( x,y,argb ); } void bbCopyPixel( int src_x,int src_y,gxCanvas *src,int dest_x,int dest_y,gxCanvas *buff ){ (buff ? buff : gx_canvas)->copyPixel( dest_x,dest_y,src ? src : gx_canvas,src_x,src_y ); } void bbCopyPixelFast( int src_x,int src_y,gxCanvas *src,int dest_x,int dest_y,gxCanvas *buff ){ (buff ? buff : gx_canvas)->copyPixelFast( dest_x,dest_y,src ? src : gx_canvas,src_x,src_y ); } int bbScanLine(){ return gx_graphics->getScanLine(); } void bbVWait( int n ){ gx_graphics->vwait(); if( !gx_runtime->idle() ) RTEX( 0 ); } void bbFlip( int vwait ){ gx_graphics->flip( vwait ? true : false ); if( !gx_runtime->idle() ) RTEX( 0 ); } int bbGraphicsWidth(){ return gx_graphics->getWidth(); } int bbGraphicsHeight(){ return gx_graphics->getHeight(); } int bbGraphicsDepth(){ return gx_graphics->getDepth(); } void bbOrigin( int x,int y ){ gx_canvas->setOrigin( x,y ); } void bbViewport( int x,int y,int w,int h ){ gx_canvas->setViewport( x,y,w,h ); } void bbColor( int r,int g,int b ){ gx_canvas->setColor( curr_color=(r<<16)|(g<<8)|b ); } void bbGetColor( int x,int y ){ gx_canvas->setColor( curr_color=gx_canvas->getPixel( x,y ) ); } int bbColorRed(){ return (gx_canvas->getColor()>>16)&0xff; } int bbColorGreen(){ return (gx_canvas->getColor()>>8)&0xff; } int bbColorBlue(){ return gx_canvas->getColor()&0xff; } void bbClsColor( int r,int g,int b ){ gx_canvas->setClsColor( curr_clsColor=(r<<16)|(g<<8)|b ); } void bbSetFont( gxFont *f ){ debugFont( f ); gx_canvas->setFont( curr_font=f ); } void bbCls(){ gx_canvas->cls(); } void bbPlot( int x,int y ){ gx_canvas->plot( x,y ); } void bbLine( int x1,int y1,int x2,int y2 ){ gx_canvas->line( x1,y1,x2,y2 ); } void bbRect( int x,int y,int w,int h,int solid ){ gx_canvas->rect( x,y,w,h,solid ? true : false ); } void bbOval( int x,int y,int w,int h,int solid ){ gx_canvas->oval( x,y,w,h,solid ? true : false ); } void bbText( int x,int y,BBStr *str,int centre_x,int centre_y ){ if( centre_x ) x-=curr_font->getWidth( *str )/2; if( centre_y ) y-=curr_font->getHeight()/2; gx_canvas->text( x,y,*str ); delete str; } void bbCopyRect( int sx,int sy,int w,int h,int dx,int dy,gxCanvas *src,gxCanvas *dest ){ if( src ) debugCanvas( src ); else src=gx_canvas; if( dest ) debugCanvas( dest ); else dest=gx_canvas; dest->blit( dx,dy,src,sx,sy,w,h,true ); } gxFont *bbLoadFont( BBStr *name,int height,int bold,int italic,int underline ){ int flags= (bold ? gxFont::FONT_BOLD : 0 ) | (italic ? gxFont::FONT_ITALIC : 0 ) | (underline ? gxFont::FONT_UNDERLINE : 0 ); gxFont *font=gx_graphics->loadFont( *name,height,flags ); delete name; return font; } void bbFreeFont( gxFont *f ){ debugFont( f ); if( f==curr_font ) bbSetFont( gx_graphics->getDefaultFont() ); gx_graphics->freeFont( f ); } int bbFontWidth(){ return curr_font->getWidth(); } int bbFontHeight(){ return curr_font->getHeight(); } int bbStringWidth( BBStr *str ){ string t=*str;delete str; return curr_font->getWidth( t ); } int bbStringHeight( BBStr *str ){ delete str; return curr_font->getHeight(); } gxMovie *bbOpenMovie( BBStr *s ){ gxMovie *movie=gx_graphics->openMovie( *s,0 );delete s; return movie; } int bbDrawMovie( gxMovie *movie,int x,int y,int w,int h ){ if( w<0 ) w=movie->getWidth(); if( h<0 ) h=movie->getHeight(); int playing=movie->draw( gx_canvas,x,y,w,h ); if( !gx_runtime->idle() ) RTEX( 0 ); return playing; } int bbMovieWidth( gxMovie *movie ){ return movie->getWidth(); } int bbMovieHeight( gxMovie *movie ){ return movie->getHeight(); } int bbMoviePlaying( gxMovie *movie ){ return movie->isPlaying(); } void bbCloseMovie( gxMovie *movie ){ gx_graphics->closeMovie( movie ); } bbImage *bbLoadImage( BBStr *s ){ string t=*s;delete s; gxCanvas *c=gx_graphics->loadCanvas( t,0 ); if( !c ) return 0; if( auto_dirty ) c->backup(); if( auto_midhandle ) c->setHandle( c->getWidth()/2,c->getHeight()/2 ); vector frames; frames.push_back( c ); bbImage *i=d_new bbImage( frames ); image_set.insert( i ); return i; } bbImage *bbLoadAnimImage( BBStr *s,int w,int h,int first,int cnt ){ string t=*s;delete s; if( cnt<1 ) RTEX( "Illegal frame count" ); if( first<0 ) RTEX( "Illegal first frame" ); gxCanvas *pic=gx_graphics->loadCanvas( t,gxCanvas::CANVAS_NONDISPLAY ); if( !pic ) return 0; //frames per row, per picture int fpr=pic->getWidth()/w; int fpp=pic->getHeight()/h*fpr; if( first+cnt>fpp ){ gx_graphics->freeCanvas( pic ); RTEX( "Not enough frames in bitmap" ); } //x,y of first frame... vector frames; int src_x=first%fpr*w,src_y=first/fpr*h; for( int k=0;kcreateCanvas( w,h,0 ); if( !c ){ for( --k;k>=0;--k ) gx_graphics->freeCanvas( frames[k] ); gx_graphics->freeCanvas( pic );return 0; } c->blit( 0,0,pic,src_x,src_y,w,h,true ); if( auto_dirty ) c->backup(); if( auto_midhandle ) c->setHandle( c->getWidth()/2,c->getHeight()/2 ); frames.push_back( c ); src_x+=w;if( src_x+w>pic->getWidth() ){ src_x=0;src_y+=h; } } gx_graphics->freeCanvas( pic ); bbImage *i=d_new bbImage( frames ); image_set.insert( i ); return i; } bbImage *bbCopyImage( bbImage *i ){ debugImage( i ); vector frames; const vector &f=i->getFrames(); for( int k=0;kcreateCanvas( t->getWidth(),t->getHeight(),0 ); if( !c ){ for( --k;k>=0;--k ) gx_graphics->freeCanvas( frames[k] ); return 0; } int x,y; t->getHandle( &x,&y ); t->setHandle( 0,0 ); c->blit( 0,0,t,0,0,t->getWidth(),t->getHeight(),true ); if( auto_dirty ) c->backup(); t->setHandle( x,y ); c->setHandle( x,y ); c->setMask( t->getMask() ); frames.push_back( c ); } bbImage *t=d_new bbImage( frames ); image_set.insert( t ); return t; } bbImage *bbCreateImage( int w,int h,int n ){ vector frames; for( int k=0;kcreateCanvas( w,h,0 ); if( !c ){ for( --k;k>=0;--k ) gx_graphics->freeCanvas( frames[k] ); return 0; } if( auto_dirty ) c->backup(); if( auto_midhandle ) c->setHandle( c->getWidth()/2,c->getHeight()/2 ); frames.push_back( c ); } bbImage *i=d_new bbImage( frames ); image_set.insert( i ); return i; } void bbFreeImage( bbImage *i ){ if( !image_set.erase(i) ) return; const vector &f=i->getFrames(); for( int k=0;kgetFrontCanvas() ); break; } } delete i; } int bbSaveImage( bbImage *i,BBStr *str,int n ){ debugImage( i,n ); string t=*str;delete str; gxCanvas *c=i->getFrames()[n]; return saveCanvas( c,t ) ? 1 : 0; } void bbGrabImage( bbImage *i,int x,int y,int n ){ debugImage( i,n ); gxCanvas *c=i->getFrames()[n]; int src_ox,src_oy,dst_hx,dst_hy; gx_canvas->getOrigin( &src_ox,&src_oy ); c->getHandle( &dst_hx,&dst_hy ); x+=src_ox-dst_hx;y+=src_oy-dst_hy; c->setViewport( 0,0,c->getWidth(),c->getHeight() ); c->blit( 0,0,gx_canvas,x,y,c->getWidth(),c->getHeight(),true ); if( auto_dirty ) c->backup(); } gxCanvas *bbImageBuffer( bbImage *i,int n ){ debugImage( i,n ); return i->getFrames()[n]; } void bbDrawImage( bbImage *i,int x,int y,int frame ){ debugImage( i,frame ); gxCanvas *c=i->getFrames()[frame]; gx_canvas->blit( x,y,c,0,0,c->getWidth(),c->getHeight(),false ); } void bbDrawBlock( bbImage *i,int x,int y,int frame ){ debugImage( i,frame ); gxCanvas *c=i->getFrames()[frame]; gx_canvas->blit( x,y,c,0,0,c->getWidth(),c->getHeight(),true ); } static void tile( bbImage *i,int x,int y,int frame,bool solid ){ gxCanvas *c=i->getFrames()[frame]; int hx,hy; c->getHandle( &hx,&hy ); int w=c->getWidth(),h=c->getHeight(); int ox,oy,vp_x,vp_y,vp_w,vp_h; gx_canvas->getOrigin( &ox,&oy ); gx_canvas->getViewport( &vp_x,&vp_y,&vp_w,&vp_h ); int dx=vp_x-ox+hx; int dy=vp_y-oy+hy; x-=dx; y-=dy; dx+=(x>=0?x%w:w-(-x%w)); dy+=(y>=0?y%h:h-(-y%h)); for( y=-h;yblit( x+dx,y+dy,c,0,0,w,h,solid ); } } } void bbTileImage( bbImage *i,int x,int y,int frame ){ debugImage( i,frame ); tile( i,x,y,frame,false ); } void bbTileBlock( bbImage *i,int x,int y,int frame ){ debugImage( i,frame ); tile( i,x,y,frame,true ); } void bbDrawImageRect( bbImage *i,int x,int y,int r_x,int r_y,int r_w,int r_h,int frame ){ debugImage( i,frame ); gxCanvas *c=i->getFrames()[frame]; gx_canvas->blit( x,y,c,r_x,r_y,r_w,r_h,false ); } void bbDrawBlockRect( bbImage *i,int x,int y,int r_x,int r_y,int r_w,int r_h,int frame ){ debugImage( i,frame ); gxCanvas *c=i->getFrames()[frame]; gx_canvas->blit( x,y,c,r_x,r_y,r_w,r_h,true ); } void bbMaskImage( bbImage *i,int r,int g,int b ){ debugImage( i ); unsigned argb=(r<<16)|(g<<8)|b; const vector &f=i->getFrames(); for( int k=0;ksetMask( argb ); } void bbHandleImage( bbImage *i,int x,int y ){ debugImage( i ); const vector &f=i->getFrames(); for( int k=0;ksetHandle( x,y ); } void bbMidHandle( bbImage *i ){ debugImage( i ); const vector &f=i->getFrames(); for( int k=0;ksetHandle( f[k]->getWidth()/2,f[k]->getHeight()/2 ); } void bbAutoMidHandle( int enable ){ auto_midhandle=enable ? true : false; } int bbImageWidth( bbImage *i ){ debugImage( i ); return i->getFrames()[0]->getWidth(); } int bbImageHeight( bbImage *i ){ debugImage( i ); return i->getFrames()[0]->getHeight(); } int bbImageXHandle( bbImage *i ){ debugImage( i ); int x,y; i->getFrames()[0]->getHandle( &x,&y ); return x; } int bbImageYHandle( bbImage *i ){ debugImage( i ); int x,y; i->getFrames()[0]->getHandle( &x,&y ); return y; } int bbImagesOverlap( bbImage *i1,int x1,int y1,bbImage *i2,int x2,int y2 ){ debugImage( i1 ); debugImage( i2 ); gxCanvas *c1=i1->getFrames()[0]; gxCanvas *c2=i2->getFrames()[0]; return c1->collide( x1,y1,c2,x2,y2,true ); } int bbImagesCollide( bbImage *i1,int x1,int y1,int f1,bbImage *i2,int x2,int y2,int f2 ){ debugImage( i1,f1 ); debugImage( i2,f2 ); gxCanvas *c1=i1->getFrames()[f1]; gxCanvas *c2=i2->getFrames()[f2]; return c1->collide( x1,y1,c2,x2,y2,false ); } int bbRectsOverlap( int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2 ){ if( x1+w1<=x2 || x1>=x2+w2 || y1+h1<=y2 || y1>=y2+h2 ) return 0; return 1; } int bbImageRectOverlap( bbImage *i,int x,int y,int x2,int y2,int w2,int h2 ){ debugImage( i ); gxCanvas *c=i->getFrames()[0]; return c->rect_collide( x,y,x2,y2,w2,h2,true ); } int bbImageRectCollide( bbImage *i,int x,int y,int f,int x2,int y2,int w2,int h2 ){ debugImage( i,f ); gxCanvas *c=i->getFrames()[f]; return c->rect_collide( x,y,x2,y2,w2,h2,false ); } void bbTFormImage( bbImage *i,float a,float b,float c,float d ){ debugImage( i ); const vector &f=i->getFrames(); int k; for( k=0;kgetFrontCanvas() ); break; } } float m[2][2]; m[0][0]=a;m[1][0]=b;m[0][1]=c;m[1][1]=d; for( k=0;kgetHandle( &hx,&hy ); gxCanvas *t=tformCanvas( c,m,hx,hy ); i->replaceFrame( k,t ); t->backup(); } } void bbScaleImage( bbImage *i,float w,float h ){ debugImage( i ); bbTFormImage( i,w,0,0,h ); } void bbResizeImage( bbImage *i,float w,float h ){ debugImage( i ); gxCanvas *c=i->getFrames()[0]; bbTFormImage( i,w/(float)c->getWidth(),0,0,h/(float)c->getHeight() ); } void bbRotateImage( bbImage *i,float d ){ debugImage( i ); d*=-dtor; bbTFormImage( i,cos(d),-sin(d),sin(d),cos(d) ); } void bbTFormFilter( int enable ){ filter=enable ? true : false; } static int p_ox,p_oy,p_hx,p_hy,p_vpx,p_vpy,p_vpw,p_vph; static gxCanvas *startPrinting(){ gxCanvas *c=gx_graphics->getFrontCanvas(); c->lock(); c->unlock(); c->getOrigin( &p_ox,&p_oy ); c->getHandle( &p_hx,&p_hy ); c->getViewport( &p_vpx,&p_vpy,&p_vpw,&p_vph ); c->setOrigin( 0,0 ); c->setHandle( 0,0 ); c->setViewport( 0,0,c->getWidth(),c->getHeight() ); if( c!=gx_canvas ){ c->setFont( curr_font ); c->setColor( curr_color ); } int dy=curs_y+curr_font->getHeight()-c->getHeight(); if( dy>0 ){ curs_y=c->getHeight()-curr_font->getHeight(); c->blit( 0,0,c,0,dy,c->getWidth(),c->getHeight()-dy,true ); c->setColor( curr_clsColor ); c->rect( 0,c->getHeight()-dy,c->getWidth(),dy,true ); c->setColor( curr_color ); } return c; } static void endPrinting( gxCanvas *c ){ c->setViewport( p_vpx,p_vpy,p_vpw,p_vph ); c->setHandle( p_hx,p_hy ); c->setOrigin( p_ox,p_oy ); if( c==gx_canvas ) c->setColor( curr_color ); if( !gx_runtime->idle() ) RTEX( 0 ); } void bbWrite( BBStr *str ){ gxCanvas *c=startPrinting(); c->text( curs_x,curs_y,*str ); curs_x+=curr_font->getWidth( *str ); endPrinting( c ); delete str; } void bbPrint( BBStr *str ){ gxCanvas *c=startPrinting(); c->text( curs_x,curs_y,*str ); curs_x=0; curs_y+=curr_font->getHeight(); endPrinting( c ); delete str; } BBStr *bbInput( BBStr *prompt ){ gxCanvas *c=startPrinting(); string t=*prompt;delete prompt; //get temp canvas if( !p_canvas || p_canvas->getWidth()getWidth() || p_canvas->getHeight()getHeight()*2 ){ if( p_canvas ) gx_graphics->freeCanvas( p_canvas ); p_canvas=gx_graphics->createCanvas( c->getWidth(),curr_font->getHeight()*2,0 ); if( !p_canvas ){ endPrinting(c); return d_new BBStr(); } } //draw prompt c->text( curs_x,curs_y,t ); curs_x+=curr_font->getWidth( t ); p_canvas->setFont( curr_font ); p_canvas->setColor( curr_color ); p_canvas->blit( 0,0,c,0,curs_y,c->getWidth(),curr_font->getHeight(),true ); string str; bool go=true; int curs=0,last_key=0,last_time,rep_delay; while( go ){ //render all text //calc curs x and width int cx=curs_x+curr_font->getWidth( str.substr( 0,curs ) ); int cw=curr_font->getWidth( cursgetMilliSecs(),tc=-1; while( gx_runtime->idle() ){ int t=gx_runtime->getMilliSecs(); int n=(t-st)/320; if( n!=tc ){ tc=n; if( !(tc&1) ){ //cursor ON c->setColor( curr_clsColor^0xffffff ); c->rect( cx,curs_y,cw,curr_font->getHeight(),true ); c->setColor( curr_clsColor ); }else{ //cursor OFF c->blit( cx,curs_y,p_canvas,cx,0,cw,curr_font->getHeight(),true ); c->setColor( curr_color ); } c->text( cx,curs_y,str.substr( curs,1 ) ); } if( key=gx_keyboard->getKey() ){ if( int asc=gx_input->toAscii( key ) ){ rep_delay=280; last_key=key; last_time=t; key=asc; break; } } if( last_key && gx_keyboard->keyDown( last_key ) ){ if( t-last_time>rep_delay ){ if( key=gx_input->toAscii( last_key ) ){ last_time+=rep_delay; rep_delay=40; break; } } }else last_key=0; gx_runtime->delay( 20 ); } //check the key switch( key ){ case 0: go=false; str=""; break; case 8: if( curs ){ str=str.substr( 0,curs-1 )+str.substr( curs ); --curs; } break; case 27: curs=0;str=""; break; case gxInput::ASC_DELETE: if( cursisPrintable( key ) ){ str=str.substr(0,curs)+char(key)+str.substr(curs); ++curs; } } //render text p_canvas->blit( 0,curr_font->getHeight(),p_canvas,0,0,c->getWidth(),curr_font->getHeight(),true ); p_canvas->text( curs_x,curr_font->getHeight(),str ); c->blit( 0,curs_y,p_canvas,0,curr_font->getHeight(),c->getWidth(),curr_font->getHeight(),true ); } curs_x=0; curs_y+=curr_font->getHeight(); endPrinting( c ); return d_new BBStr( str ); } void bbLocate( int x,int y ){ gxCanvas *c=gx_graphics->getFrontCanvas(); curs_x=x<0 ? 0 : (x > c->getWidth() ? c->getWidth() : x); curs_y=y<0 ? 0 : (y > c->getHeight() ? c->getHeight() : y); } void bbShowPointer(){ gx_runtime->setPointerVisible( true ); } void bbHidePointer(){ gx_runtime->setPointerVisible( false ); } bool graphics_create(){ p_canvas=0; filter=true; gx_driver=0; freeGraphics(); auto_dirty=true; auto_midhandle=false; gx_graphics=gx_runtime->openGraphics( 400,300,0,0,gxGraphics::GRAPHICS_WINDOWED ); if( gx_graphics ){ curr_clsColor=0; curr_color=0xffffffff; curr_font=gx_graphics->getDefaultFont(); bbSetBuffer( bbFrontBuffer() ); return true; } return false; } bool graphics_destroy(){ freeGraphics(); gfx_modes.clear(); if( gx_graphics ){ gx_runtime->closeGraphics( gx_graphics ); gx_graphics=0; } return true; } void graphics_link( void (*rtSym)( const char *sym,void *pc ) ){ //gfx driver info rtSym( "%CountGfxDrivers",bbCountGfxDrivers ); rtSym( "$GfxDriverName%driver",bbGfxDriverName ); rtSym( "SetGfxDriver%driver",bbSetGfxDriver ); //gfx mode info rtSym( "%CountGfxModes",bbCountGfxModes ); rtSym( "%GfxModeExists%width%height%depth",bbGfxModeExists ); rtSym( "%GfxModeWidth%mode",bbGfxModeWidth ); rtSym( "%GfxModeHeight%mode",bbGfxModeHeight ); rtSym( "%GfxModeDepth%mode",bbGfxModeDepth ); rtSym( "%AvailVidMem",bbAvailVidMem ); rtSym( "%TotalVidMem",bbTotalVidMem ); #ifdef PRO rtSym( "%GfxDriver3D%driver",bbGfxDriver3D ); rtSym( "%CountGfxModes3D",bbCountGfxModes3D ); rtSym( "%GfxMode3DExists%width%height%depth",bbGfxMode3DExists ); rtSym( "%GfxMode3D%mode",bbGfxMode3D ); rtSym( "%Windowed3D",bbWindowed3D ); #endif //display mode rtSym( "Graphics%width%height%depth=0%mode=0",bbGraphics ); #ifdef PRO rtSym( "Graphics3D%width%height%depth=0%mode=0",bbGraphics3D ); #endif rtSym( "EndGraphics",bbEndGraphics ); rtSym( "%GraphicsLost",bbGraphicsLost ); rtSym( "SetGamma%src_red%src_green%src_blue#dest_red#dest_green#dest_blue",bbSetGamma ); rtSym( "UpdateGamma%calibrate=0",bbUpdateGamma ); rtSym( "#GammaRed%red",bbGammaRed ); rtSym( "#GammaGreen%green",bbGammaGreen ); rtSym( "#GammaBlue%blue",bbGammaBlue ); rtSym( "%FrontBuffer",bbFrontBuffer ); rtSym( "%BackBuffer",bbBackBuffer ); rtSym( "%ScanLine",bbScanLine ); rtSym( "VWait%frames=1",bbVWait ); rtSym( "Flip%vwait=1",bbFlip ); rtSym( "%GraphicsWidth",bbGraphicsWidth ); rtSym( "%GraphicsHeight",bbGraphicsHeight ); rtSym( "%GraphicsDepth",bbGraphicsDepth ); //buffer management rtSym( "SetBuffer%buffer",bbSetBuffer ); rtSym( "%GraphicsBuffer",bbGraphicsBuffer ); rtSym( "%LoadBuffer%buffer$bmpfile",bbLoadBuffer ); rtSym( "%SaveBuffer%buffer$bmpfile",bbSaveBuffer ); rtSym( "BufferDirty%buffer",bbBufferDirty ); //fast pixel reads/write rtSym( "LockBuffer%buffer=0",bbLockBuffer ); rtSym( "UnlockBuffer%buffer=0",bbUnlockBuffer ); rtSym( "%ReadPixel%x%y%buffer=0",bbReadPixel ); rtSym( "WritePixel%x%y%argb%buffer=0",bbWritePixel ); rtSym( "%ReadPixelFast%x%y%buffer=0",bbReadPixelFast ); rtSym( "WritePixelFast%x%y%argb%buffer=0",bbWritePixelFast ); rtSym( "CopyPixel%src_x%src_y%src_buffer%dest_x%dest_y%dest_buffer=0",bbCopyPixel ); rtSym( "CopyPixelFast%src_x%src_y%src_buffer%dest_x%dest_y%dest_buffer=0",bbCopyPixelFast ); //rendering rtSym( "Origin%x%y",bbOrigin ); rtSym( "Viewport%x%y%width%height",bbViewport ); rtSym( "Color%red%green%blue",bbColor ); rtSym( "GetColor%x%y",bbGetColor ); rtSym( "%ColorRed",bbColorRed ); rtSym( "%ColorGreen",bbColorGreen ); rtSym( "%ColorBlue",bbColorBlue ); rtSym( "ClsColor%red%green%blue",bbClsColor ); rtSym( "SetFont%font",bbSetFont ); rtSym( "Cls",bbCls ); rtSym( "Plot%x%y",bbPlot ); rtSym( "Rect%x%y%width%height%solid=1",bbRect ); rtSym( "Oval%x%y%width%height%solid=1",bbOval ); rtSym( "Line%x1%y1%x2%y2",bbLine ); rtSym( "Text%x%y$text%centre_x=0%centre_y=0",bbText ); rtSym( "CopyRect%source_x%source_y%width%height%dest_x%dest_y%src_buffer=0%dest_buffer=0",bbCopyRect ); //fonts rtSym( "%LoadFont$fontname%height=12%bold=0%italic=0%underline=0",bbLoadFont ); rtSym( "FreeFont%font",bbFreeFont ); rtSym( "%FontWidth",bbFontWidth ); rtSym( "%FontHeight",bbFontHeight ); rtSym( "%StringWidth$string",bbStringWidth ); rtSym( "%StringHeight$string",bbStringHeight ); //movies rtSym( "%OpenMovie$file",bbOpenMovie ); rtSym( "%DrawMovie%movie%x=0%y=0%w=-1%h=-1",bbDrawMovie ); rtSym( "%MovieWidth%movie",bbMovieWidth ); rtSym( "%MovieHeight%movie",bbMovieHeight ); rtSym( "%MoviePlaying%movie",bbMoviePlaying ); rtSym( "CloseMovie%movie",bbCloseMovie ); rtSym( "%LoadImage$bmpfile",bbLoadImage ); rtSym( "%LoadAnimImage$bmpfile%cellwidth%cellheight%first%count",bbLoadAnimImage ); rtSym( "%CopyImage%image",bbCopyImage ); rtSym( "%CreateImage%width%height%frames=1",bbCreateImage ); rtSym( "FreeImage%image",bbFreeImage ); rtSym( "%SaveImage%image$bmpfile%frame=0",bbSaveImage ); rtSym( "GrabImage%image%x%y%frame=0",bbGrabImage ); rtSym( "%ImageBuffer%image%frame=0",bbImageBuffer ); rtSym( "DrawImage%image%x%y%frame=0",bbDrawImage ); rtSym( "DrawBlock%image%x%y%frame=0",bbDrawBlock ); rtSym( "TileImage%image%x=0%y=0%frame=0",bbTileImage ); rtSym( "TileBlock%image%x=0%y=0%frame=0",bbTileBlock ); rtSym( "DrawImageRect%image%x%y%rect_x%rect_y%rect_width%rect_height%frame=0",bbDrawImageRect ); rtSym( "DrawBlockRect%image%x%y%rect_x%rect_y%rect_width%rect_height%frame=0",bbDrawBlockRect ); rtSym( "MaskImage%image%red%green%blue",bbMaskImage ); rtSym( "HandleImage%image%x%y",bbHandleImage ); rtSym( "MidHandle%image",bbMidHandle ); rtSym( "AutoMidHandle%enable",bbAutoMidHandle ); rtSym( "%ImageWidth%image",bbImageWidth ); rtSym( "%ImageHeight%image",bbImageHeight ); rtSym( "%ImageXHandle%image",bbImageXHandle ); rtSym( "%ImageYHandle%image",bbImageYHandle ); rtSym( "ScaleImage%image#xscale#yscale",bbScaleImage ); rtSym( "ResizeImage%image#width#height",bbResizeImage ); rtSym( "RotateImage%image#angle",bbRotateImage ); rtSym( "TFormImage%image#a#b#c#d",bbTFormImage ); rtSym( "TFormFilter%enable",bbTFormFilter ); rtSym( "%ImagesOverlap%image1%x1%y1%image2%x2%y2",bbImagesOverlap ); rtSym( "%ImagesCollide%image1%x1%y1%frame1%image2%x2%y2%frame2",bbImagesCollide ); rtSym( "%RectsOverlap%x1%y1%width1%height1%x2%y2%width2%height2",bbRectsOverlap ); rtSym( "%ImageRectOverlap%image%x%y%rect_x%rect_y%rect_width%rect_height",bbImageRectOverlap ); rtSym( "%ImageRectCollide%image%x%y%frame%rect_x%rect_y%rect_width%rect_height",bbImageRectCollide ); rtSym( "Write$string",bbWrite ); rtSym( "Print$string=\"\"",bbPrint ); rtSym( "$Input$prompt=\"\"",bbInput ); rtSym( "Locate%x%y",bbLocate ); rtSym( "ShowPointer",bbShowPointer ); rtSym( "HidePointer",bbHidePointer ); }