anyway to change the title? easy question
apptitle
BlitzMax Forums/BlitzMax Programming/apptitle if you get create a function that exports the hwnd from the bglcreatecontext c file then you can do it on windows with the WinAPI function SetWindowText_( hwnd, title ).
didn't find any internal function as windowed support isn't really in. actually it is only meant for debugging from what the doc / source says
didn't find any internal function as windowed support isn't really in. actually it is only meant for debugging from what the doc / source says
Nice idea but shouldn't we all be creating cross-platform software now?
Yepp
But windowed isn't in so far. I think when it is really in we will have this functions provided as well :)
But windowed isn't in so far. I think when it is really in we will have this functions provided as well :)
is there a function to set the window title before the window is created? because without this function the user will see the default title for a small time.
I wrote a little module with some commands including SetAppTitle here: http://www.blitzbasic.com/Community/posts.php?topic=43341
it works for Mac and Windows currently (look near the bottom of the thread for the latest version).
it works for Mac and Windows currently (look near the bottom of the thread for the latest version).
thank you, Perturbatio, but if I run the following code the user can still see the default title ("BlitzGLWimdow") for a small time.
If I call the SetAppTitle-function before I call the Graphics-command the window title is all the time "BlitzGLWindow".
Strict Import Pert.AppFuncs Graphics 200 , 200 , 0 'At this program step the title of the window is "BlitzGLWindow" SetAppTitle "MyApp" 'here the title is "MyApp" While Not KeyHit ( KEY_ESCAPE ) PollSystem Wend
If I call the SetAppTitle-function before I call the Graphics-command the window title is all the time "BlitzGLWindow".
I notice there's no AppTitle in the final Windows release, so are we still not to use windowed mode for releases?
The only way to change it before the window shows is to either:
Hack the C source that contains the Graphics command
OR
Create your own OpenGL window
Hack the C source that contains the Graphics command
OR
Create your own OpenGL window
I notice there's no AppTitle in the final Windows release, so are we still not to use windowed mode for releases?
From the docs:
A depth value of 0 enables 'windowed mode'. This special mode is currently intended for debugging purposes only and should not be used for release builds. Improved support for windowed modes will be added shortly.
thank you, Perturbatio, I've changed some files and it works!
(I added 4 lines from your code so that the function works as well as the AppTitle-function in Blitz3D(that means it works before and while the window is opened))
here is the code:
/mod/brl.mod/blitzgl.mod/blitzgl.win32.c:
/mod/brl.mod/blitzgl.mod/blitzgl.bmx:
/mod/brl.mod/max2d.mod/max2d.bmx:
thanks a lot, it helps me very much!!
(I added 4 lines from your code so that the function works as well as the AppTitle-function in Blitz3D(that means it works before and while the window is opened))
here is the code:
/mod/brl.mod/blitzgl.mod/blitzgl.win32.c:
#include <windows.h> #include <gl/gl.h> enum{ BGL_FULLSCREEN=1, BGL_BACKBUFFER=2, BGL_ALPHABUFFER=4, BGL_DEPTHBUFFER=8, BGL_STENCILBUFFER=16, BGL_ACCUMBUFFER=32 }; static const char *CLASS_NAME="BlitzGL Window Class"; static HDC context_hdc; static HWND context_hwnd; static HGLRC context_hglrc; static int fullScreen; static const char*windowname="BlitzGLWindow"; static DEVMODE devmode; static int active,started,font_lists; typedef BOOL (APIENTRY * WGLSWAPINTERVALEXT) (int); static WGLSWAPINTERVALEXT wglSwapIntervalEXT; void bglDeleteContext( int context ); static void bglExit(){ bglDeleteContext(0); } static void poll(){ MSG msg; while( PeekMessage( &msg,0,0,0,PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } } _stdcall long wndProc( HWND hwnd,UINT msg,WPARAM wp,LPARAM lp ){ switch( msg ){ case WM_CLOSE: return 0; case WM_PAINT: ValidateRect( hwnd,0 ); return 0; case WM_SETFOCUS: if( devmode.dmSize && !fullScreen ){ if( ChangeDisplaySettings( &devmode,CDS_FULLSCREEN )==DISP_CHANGE_SUCCESSFUL ){ fullScreen=1; }else if( devmode.dmFields&DM_DISPLAYFREQUENCY ){ devmode.dmDisplayFrequency=0; devmode.dmFields&=~DM_DISPLAYFREQUENCY; if( ChangeDisplaySettings( &devmode,CDS_FULLSCREEN )==DISP_CHANGE_SUCCESSFUL ){ fullScreen=1; } } } return 0; case WM_KILLFOCUS: if( devmode.dmSize && fullScreen ){ ChangeDisplaySettings( 0,CDS_FULLSCREEN ); ShowWindow( hwnd,SW_MINIMIZE ); fullScreen=0; } return 0; } return DefWindowProc( hwnd,msg,wp,lp ); } void bglDeleteContext( context ){ if( !active ) return; wglDeleteContext( context_hglrc ); ChangeDisplaySettings( 0,CDS_FULLSCREEN ); DestroyWindow( context_hwnd ); active=0; } int bglDisplayModes( int *modes,int size ){ int count=size/16; int *end=modes+count*4,i=0,n=0; while( modes!=end ){ DEVMODE mode; mode.dmSize=sizeof(DEVMODE); mode.dmDriverExtra=0; if( !EnumDisplaySettings(0,i++,&mode) ) break; if( mode.dmBitsPerPel<16 ) continue; *modes++=mode.dmPelsWidth; *modes++=mode.dmPelsHeight; *modes++=mode.dmBitsPerPel; *modes++=mode.dmDisplayFrequency; ++n; } return n; } static void setPfd( PIXELFORMATDESCRIPTOR *pfd,int flags ){ memset( pfd,0,sizeof(*pfd) ); pfd->nSize=sizeof(pfd); pfd->nVersion=1; pfd->cColorBits=1; pfd->iPixelType=PFD_TYPE_RGBA; pfd->iLayerType=PFD_MAIN_PLANE; pfd->dwFlags=PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL; pfd->dwFlags|=(flags & BGL_BACKBUFFER) ? PFD_DOUBLEBUFFER : 0; pfd->cAlphaBits=(flags & BGL_ALPHABUFFER) ? 1 : 0; pfd->cDepthBits=(flags & BGL_DEPTHBUFFER) ? 1 : 0; pfd->cStencilBits=(flags & BGL_STENCILBUFFER) ? 1 : 0; pfd->cAccumBits=(flags & BGL_ACCUMBUFFER) ? 1 : 0; } static void createWindowedContext( int width,int height,int flags ){ long pf; PIXELFORMATDESCRIPTOR pfd; RECT rect={0,0,width,height}; int ex_style=0,style=WS_VISIBLE|WS_CAPTION; devmode.dmSize=0; AdjustWindowRectEx( &rect,style,0,ex_style ); context_hwnd=CreateWindowEx( ex_style,CLASS_NAME,windowname, style,CW_USEDEFAULT,CW_USEDEFAULT, rect.right-rect.left,rect.bottom-rect.top, 0,0,GetModuleHandle(0),0 ); setPfd( &pfd,flags ); context_hdc=GetDC( context_hwnd ); pf=ChoosePixelFormat( context_hdc,&pfd ); if( !pf ){ DestroyWindow( context_hwnd ); return; } SetPixelFormat( context_hdc,pf,&pfd ); context_hglrc=wglCreateContext( context_hdc ); wglMakeCurrent( context_hdc,context_hglrc ); active=1; } static void createFullscreenContext( int width,int height,int depth,int hertz,int flags ){ long pf; PIXELFORMATDESCRIPTOR pfd; devmode.dmSize=sizeof(devmode); devmode.dmPelsWidth=width; devmode.dmPelsHeight=height; devmode.dmBitsPerPel=depth; devmode.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL; if( hertz ){ devmode.dmDisplayFrequency=hertz; devmode.dmFields|=DM_DISPLAYFREQUENCY; } context_hwnd=CreateWindowEx( WS_EX_TOPMOST,CLASS_NAME,windowname, WS_VISIBLE|WS_POPUP|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,0,0,width,height,0,0,GetModuleHandle(0),0 ); setPfd( &pfd,flags ); context_hdc=GetDC( context_hwnd ); pf=ChoosePixelFormat( context_hdc,&pfd ); if( !pf ){ DestroyWindow( context_hwnd ); return; } SetPixelFormat( context_hdc,pf,&pfd ); context_hglrc=wglCreateContext( context_hdc ); wglMakeCurrent( context_hdc,context_hglrc ); active=1; } int bglCreateContext( int width,int height,int depth,int hertz,int flags ){ bglDeleteContext( 0 ); if( !started ){ WNDCLASS wc={0}; wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC; wc.lpfnWndProc=(WNDPROC)wndProc; wc.hInstance=GetModuleHandle(0); wc.lpszClassName=CLASS_NAME; wc.hCursor=(HCURSOR)LoadCursor( 0,IDC_ARROW ); wc.hbrBackground=0;//(HBRUSH)GetStockObject(BLACK_BRUSH); if( !RegisterClass( &wc ) ) exit(-1); atexit( bglExit ); started=1; } if( flags & BGL_FULLSCREEN ){ createFullscreenContext( width,height,depth,hertz,flags ); }else{ createWindowedContext( width,height,flags ); } if( !active ) return 0; wglSwapIntervalEXT=(WGLSWAPINTERVALEXT)wglGetProcAddress("wglSwapIntervalEXT"); bglSetSwapInterval( 0 ); return 1; } int bglSetSwapInterval( int n ){ return wglSwapIntervalEXT && wglSwapIntervalEXT(n); } void bglSwapBuffers(){ if( !active ) return; SwapBuffers( context_hdc ); } void bglSetMouseVisible( int visible ){ int n; if( !active ) return; n=ShowCursor( visible ); if( n<-1 || n>0 ) ShowCursor(!visible); } int bglFixedFontBitmaps(){ HFONT hfont,t_font; HDC hdc; if( !active ) return 0; if( font_lists ) return font_lists; hfont=CreateFont( 14,0,0,0, FW_REGULAR,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"fixedsys" ); hdc=CreateCompatibleDC(0); t_font=(HFONT)SelectObject( hdc,hfont ); font_lists=glGenLists( 256 ); wglUseFontBitmaps( hdc,0,255,font_lists ); SelectObject( hdc,t_font ); DeleteDC( hdc ); DeleteObject( hfont ); return font_lists; }
/mod/brl.mod/blitzgl.mod/blitzgl.bmx:
Strict Rem bbdoc: BlitzGL end rem Module BRL.BlitzGL ModuleInfo "Version: 1.05" ModuleInfo "Author: Mark Sibly" ModuleInfo "License: Blitz Shared Source Code" ModuleInfo "Copyright: Blitz Research Ltd" ModuleInfo "Modserver: BRL" ModuleInfo "History: 1.05 Release" ModuleInfo "History: 1.04 Release" ModuleInfo "History: Fixed C Compiler warnings" Import Pub.OpenGL Import BRL.Pixmap ?MacOS Import "blitzgl.macosx.m" ?Win32 Import "blitzgl.win32.c" ?Linux Import "blitzgl.linux.c" ? Extern Const BGL_FULLSCREEN=1 Const BGL_BACKBUFFER=2 Const BGL_ALPHABUFFER=4 Const BGL_DEPTHBUFFER=8 Const BGL_STENCILBUFFER=16 Const BGL_ACCUMBUFFER=32 Rem bbdoc: Get available display modes returns: Number of available display modes about: The region of memory pointed to by @buf is filled with a series of 16 byte [width:Int,height:Int,depth:Int,hertz:Int] structures. No more than @size bytes are written to @buf. End Rem Function bglDisplayModes( buf:Int Ptr,size ) ?win32 Rem bbdoc: Name of the next created context about: this variable contains the title of the next context created with #bglCreateContext EndRem Global bglAppTitle:Byte Ptr = "windowtitle" ? Rem bbdoc: Create GL context returns: True if successful about: @flags can be any combination of:<br> <br> <table> <tr><th>Flag value</th><th>Effect</th></tr> <tr><td><font class=token>BGL_FULLSCREEN</font></td><td>Create a full screen context</td></tr> <tr><td><font class=token>BGL_BACKBUFFER</font></td><td>Create a context with a backbuffer</td></tr> <tr><td><font class=token>BGL_ALPHABUFFER</font></td><td>Create a context with an alpha buffer</td></tr> <tr><td><font class=token>BGL_DEPTHBUFFER</font></td><td>Create a context with a depth buffer</td></tr> <tr><td><font class=token>BGL_STENCILBUFFER</font></td><td>Create a context with a stencil buffer</td></tr> <tr><td><font class=token>BGL_ACCUMBUFFER</font></td><td>Create a context with an accumulation buffer</td></tr> </table> <br> To combine multiple flags, use the <font class=token>|</font> operator. End Rem Function bglCreateContext( width,height,depth=16,hertz=0,flags=BGL_FULLSCREEN|BGL_BACKBUFFER|BGL_DEPTHBUFFER ) Rem bbdoc: Delete GL context about: By default, deletes current context. End Rem Function bglDeleteContext( context=0 ) Rem bbdoc: Set GL swap interval returns: True if successful, else false. Not all OpenGL drivers may support this function. End Rem Function bglSetSwapInterval( interval ) Rem bbdoc: Swap GL buffers about: The current OpenGL context must have been created with the BGL_BACKBUFFER flag. End Rem Function bglSwapBuffers() Rem bbdoc: Show or hide GL mouse pointer End Rem Function bglSetMouseVisible( visible ) Rem bbdoc: Create GL font bitmaps returns: Base display list name containing first glyph End Rem Function bglFixedFontBitmaps() End Extern '----- Helper Functions ----- Rem bbdoc: Helper function to calculate nearest valid texture size about: This functions rounds @width and @height up to the nearest valid texture size end rem Function bglAdjustTexSize( width Var,height Var ) Function Pow2Size( n ) Local t=1 While t<n t:*2 Wend Return t End Function width=Pow2Size( width ) height=Pow2Size( height ) Repeat Local t glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t If t Return If width=1 And height=1 RuntimeError "Unable to calculate tex size" If width>1 width:/2 If height>1 height:/2 Forever End Function Rem bbdoc: Helper function to create a texture from a pixmap returns: Integer GL Texture name about: @pixmap is resized to a valid texture size before conversion. end rem Function bglTexFromPixmap( pixmap:TPixmap,mipmap=True ) If pixmap.format<>PF_RGBA8888 pixmap=pixmap.Convert( PF_RGBA8888 ) Local width=pixmap.width,height=pixmap.height bglAdjustTexSize width,height If width<>pixmap.width Or height<>pixmap.height pixmap=ResizePixmap( pixmap,width,height ) Local old_name,old_row_len glGetIntegerv GL_TEXTURE_BINDING_2D,Varptr old_name glGetIntegerv GL_UNPACK_ROW_LENGTH,Varptr old_row_len Local name glGenTextures 1,Varptr name glBindtexture GL_TEXTURE_2D,name Local mip_level Repeat glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format] glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels If Not mipmap Exit If width=1 And height=1 Exit If width>1 width:/2 If height>1 height:/2 pixmap=ResizePixmap( pixmap,width,height ) mip_level:+1 Forever glBindTexture GL_TEXTURE_2D,old_name glPixelStorei GL_UNPACK_ROW_LENGTH,old_row_len Return name End Function Rem bbdoc: Helper function to output some simple 8x16 font text about: Draws text relative to top-left of current viewport.<br> <br> This function is intended for debugging purposes only - performance is unlikely to be stellar. end rem Function bglDrawText( text$,x,y ) Local mvMatrix![16],pjMatrix![16],matMode[1],vp[4] glGetIntegerv GL_VIEWPORT,vp glGetIntegerv GL_MATRIX_MODE,matMode glGetDoublev GL_MODELVIEW_MATRIX,mvMatrix glGetDoublev GL_PROJECTION_MATRIX,pjMatrix glMatrixMode GL_MODELVIEW glLoadIdentity glMatrixMode GL_PROJECTION glLoadIdentity y=vp[3]-y-16 x=x-vp[2]/2+vp[0] y=y-vp[3]/2+vp[1] Local h,lists=bglFixedFontBitmaps() glRasterPos2i 0,0 glBitmap 0,0,0,0,x,y,Null For Local k=0 Until Len(text) Local n=text[k] If n>=0 And n<=255 glCallList lists+n Next glMatrixMode GL_PROJECTION glLoadMatrixd pjMatrix glMatrixMode GL_MODELVIEW glLoadMatrixd mvMatrix glMatrixMode matMode[0] End Function
/mod/brl.mod/max2d.mod/max2d.bmx:
Strict Rem bbdoc: Max2D End Rem Module BRL.Max2D ModuleInfo "Version: 1.08" ModuleInfo "Author: Mark Sibly, Simon Armstrong" ModuleInfo "License: Blitz Shared Source Code" ModuleInfo "Copyright: Blitz Research Ltd" ModuleInfo "Modserver: BRL" ModuleInfo "History: 1.08 Release" ModuleInfo "History: Graphics now does an EndGraphics first" ModuleInfo "History: 1.07 Release" ModuleInfo "History: 1.06 Release" ModuleInfo "History: Added GetLineWidth#()" ModuleInfo "History: Added GetClsColor( red Var,green Var,blue Var )" ModuleInfo "History: Fixed Object reference bug in Collision system" ModuleInfo "History: 1.05 Release" ModuleInfo "History: Fixed AnimImage collisions" ModuleInfo "History: Fixed ImagesCollide/ImagesCollide2 parameter types" Import BRL.System Import "image.bmx" Import "driver.bmx" Import "imagefont.bmx" Private Global graphics_active Global graphics_width,graphics_height Global graphics_depth,graphics_hertz Global color_red,color_blue,color_green Global color_alpha# Global clscolor_red,clscolor_green,clscolor_blue Global line_width# Global mask_red,mask_green,mask_blue Global tform_rot#,tform_scale_x#,tform_scale_y# Global tform_ix#,tform_iy#,tform_jx#,tform_jy# Global viewport_x,viewport_y,viewport_w,viewport_h Global origin_x#,origin_y# Global handle_x#,handle_y# Global image_font:TImageFont,default_font:TImageFont Global blend_mode Global auto_midhandle Global auto_imageflags; Function UpdateTransform() Local s#=Sin(tform_rot) Local c#=Cos(tform_rot) tform_ix= c*tform_scale_x tform_iy=-s*tform_scale_y tform_jx= s*tform_scale_x tform_jy= c*tform_scale_y blitz2d_driver.SetTransform tform_ix,tform_iy,tform_jx,tform_jy SetCollisions2DTransform tform_ix,tform_iy,tform_jx,tform_jy End Function ?win32 Extern "Win32" Function _SetWindowText(hwnd:Int, lpString:Byte Ptr) = "SetWindowTextA@8" Function _GetActiveWindow() = "GetActiveWindow@0" EndExtern ? Public ?win32 Rem bbdoc: Set applications title about: Use this function to set the name of the application. The application name is the window title in windowed mode and shown in taskbar when the program is in fullscreen mode and the user switched to another application( with ALT+TAB ). EndRem Function SetAppTitle ( title$ ) bglAppTitle = title.ToCString ( ) Local _CurrentWinHandle = _GetActiveWindow() _SetWindowText(_CurrentWinHandle, title.toCString()) EndFunction ? Rem bbdoc: Get number of available graphics modes returns: Number of available graphics modes about: Use #GetGraphicsMode to obtain information about an individual graphics mode End Rem Function CountGraphicsModes() Return GraphicsModes.length End Function Rem bbdoc: Get information about a graphics mode about: #GetGraphicsMode returns information about a specific graphics mode. @mode should be in the range 0 (inclusive) to the value returned by #CountGraphicsModes (exclusive). end rem Function GetGraphicsMode( mode,width Var,height Var,depth Var,hertz Var ) Local gmode:TGraphicsMode=GraphicsModes[mode] width=gmode.width height=gmode.height depth=gmode.depth hertz=gmode.hertz End Function Rem bbdoc: Determine if a graphics mode exists returns: True if a matching graphics mode is found about: A value of 0 for any of @width, @height, @depth or @hertz will cause that parameter to be ignored. end rem Function GraphicsModeExists( width,height,depth=0,hertz=0 ) For Local mode=0 Until GraphicsModes.length Local gmode:TGraphicsMode=GraphicsModes[mode] If width And width<>gmode.width Continue If height And height<>gmode.height Continue If depth And depth<>gmode.depth Continue If hertz And hertz<>gmode.hertz Continue Return True Next Return False End Function Rem bbdoc: Set Graphics mode about: Sets the current Max2D graphics mode. This command must be executed before any other Max2D commands. @width and @height specify the size, in pixels, of the graphics mode, @depth specifies the bit depth and @hertz specifies the refresh rate.<br> <br> A @depth value of 0 enables 'windowed mode'. This special mode is currently intended for debugging purposes only and should not be used for release builds. Improved support for windowed modes will be added shortly.<br> <br> Changing graphics modes will automatically invalidate all images and image fonts. These must be reloaded or recreated if you wish to use them again in another graphics mode. End Rem Function Graphics( width,height,depth=16,hertz=60 ) If depth And Not GraphicsModeExists( width,height,0,0 ) RuntimeError "Graphics mode does not exist" EndIf EndGraphics blitz2d_driver.Graphics width,height,depth,hertz graphics_width=width graphics_height=height graphics_depth=depth graphics_hertz=hertz SetBlend MASKBLEND SetColor 255,255,255 SetClsColor 0,0,0 SetMaskColor 0,0,0 SetAlpha 1 SetOrigin 0,0 SetHandle 0,0 SetViewport 0,0,width,height SetTransform 0,1,1 AutoMidHandle False AutoImageFlags MASKEDIMAGE|FILTEREDIMAGE default_font=TImageFont.CreateDefault() image_font=default_font graphics_active=True End Function Rem bbdoc: End Graphics mode about: EndGraphics closes the current full screen 2D graphics display created with the #Graphics command.<br> <br> Changing graphics modes will automatically invalidate all images and image fonts. These must be reloaded or recreated if you wish to use them again in another graphics mode. end rem Function EndGraphics() If Not graphics_active Return blitz2d_driver.EndGraphics graphics_width=0 graphics_height=0 image_font=Null default_font=Null graphics_active=False End Function Rem bbdoc: Get width of Graphics mode. returns: The width, in pixels, of the current Graphics mode. End Rem Function GraphicsWidth() Return graphics_width End Function Rem bbdoc: Get height of Graphics mode. returns: The height, in pixels, of the current Graphics mode. End Rem Function GraphicsHeight() Return graphics_height End Function Rem bbdoc: Get width, height, depth and hertz of current Graphics mode. returns: The width and height in pixels, the depth in bits and the frequency in hertz of the current Graphics mode. End Rem Function GetGraphics( width Var,height Var,depth Var,hertz Var ) width=graphics_width height=graphics_height depth=graphics_depth hertz=graphics_hertz End Function Rem bbdoc: Swap front and back buffers about: Flip can only be used after a call to #Graphics and must be executed to show the results of any drawing commands.<p> BlitzMax uses a double buffered graphics system where all drawing is done to a <i>Back Buffer</i> and what is shown on the screen is known as the <i>Front Buffer</i>. #Flip causes the buffers to be swapped allowing for fast flicker free graphics animation. End Rem Function Flip() blitz2d_driver.Flip End Function Rem bbdoc: Clear back buffer about: Clears the back buffer to the current #SetClsColor. The default ClsColor is Black.<p> After a #Flip command the contents of the back buffer is undefined, most often containing the contents of the last <i>Front Buffer</i> making a call to Cls() essential before calling any drawing commands in order to create the next frame of graphics for display. End Rem Function Cls() blitz2d_driver.Cls End Function Rem bbdoc: Set current #Cls color about: The @red, @green and @blue parameters should be in the range of 0 to 255. End Rem Function SetClsColor( red,green,blue ) clscolor_red=red clscolor_green=green clscolor_blue=blue blitz2d_driver.SetClsColor red,green,blue End Function Rem bbdoc: Get red, green and blue component of current cls color. returns: Red, green and blue values in the range 0..255 in the variables supplied. End Rem Function GetClsColor( red Var,green Var,blue Var ) red=clscolor_red green=clscolor_green blue=clscolor_blue End Function Rem bbdoc: Plot a pixel about: Sets the color of a single pixel on the back buffer to the current drawing color defined with the #SetColor command. Other commands that affect the operation of #Plot include #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha. End Rem Function Plot( x#,y# ) blitz2d_driver.Plot x+origin_x,y+origin_y End Function Rem bbdoc: Draw a rectangle about: Sets the color of a rectangular area of pixels using the current drawing color defined with the #SetColor command.<p> Other commands that affect the operation of #DrawRect include #SetHandle, #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha. End Rem Function DrawRect( x#,y#,width#,height# ) blitz2d_driver.DrawRect handle_x,handle_y,handle_x+width,handle_y+height,x+origin_x,y+origin_y End Function Rem bbdoc: Draw a line about: #DrawLine draws a line from @x,@y to @x2,@y2 with the current drawing color.<p> BlitzMax commands that affect the drawing of lines include #SetLineWidth, #SetColor, #SetHandle, #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha. The optional @draw_last_pixel parameter can be used to control whether the last pixel of the line is drawn or not. Not drawing the last pixel can be useful if you are using certain blending modes. End Rem Function DrawLine( x#,y#,x2#,y2#,draw_last_pixel=True ) blitz2d_driver.DrawLine handle_x,handle_y,handle_x+x2-x,handle_y+y2-y,x+origin_x,y+origin_y If Not draw_last_pixel Return Local px#=handle_x+x2-x,py#=handle_y+y2-y blitz2d_driver.Plot px*tform_ix+py*tform_iy+x+origin_x,px*tform_jx+py*tform_jy+y+origin_y End Function Rem bbdoc: Draw an oval about: #DrawOval draws an oval that fits in the rectangular area defined by @x, @y, @width and @height parameters.<p> BlitzMax commands that affect the drawing of ovals include #SetColor, #SetHandle, #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha. End Rem Function DrawOval( x#,y#,width#,height# ) blitz2d_driver.DrawOval handle_x,handle_y,handle_x+width,handle_y+height,x+origin_x,y+origin_y End Function Rem bbdoc: Draw a polygon about: #DrawPoly draws a polygon with corners defined by an array of x#,y# coordinate pairs.<p> BlitzMax commands that affect the drawing of polygons include #SetColor, #SetHandle, #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha. End Rem Function DrawPoly( xy#[] ) blitz2d_driver.DrawPoly xy,handle_x,handle_y,origin_x,origin_y End Function Rem bbdoc: Draw text about: #DrawText prints strings at position @x,@y of the graphics display using the current image font specified by the #SetImageFont command.<p> Other commands that affect #DrawText include #SetColor, #SetHandle, #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha. End Rem Function DrawText( t$,x#,y# ) image_font.Draw t,.. x+origin_x+handle_x*tform_ix+handle_y*tform_iy,.. y+origin_y+handle_x*tform_jx+handle_y*tform_jy,.. tform_ix,tform_iy,tform_jx,tform_jy End Function Rem bbdoc: Draw an image to the back buffer about: Drawing is affected by the current blend mode, color, scale and rotation.<br> <br> If the blend mode is ALPHABLEND, then the image is also affected by the current alpha value. End Rem Function DrawImage( image:TImage,x#,y#,frame=0 ) Local x0#=-image.handle_x,x1#=x0+image.width Local y0#=-image.handle_y,y1#=y0+image.height image.frames[frame].Draw x0,y0,x1,y1,x+origin_x,y+origin_y End Function Rem bbdoc: Draw an image to a rectangular area of the back buffer about: Drawing is affected by the current blend mode, color, scale and rotation.<br> <br> If the blend mode is ALPHABLEND, then the image is also affected by the current alpha value. End Rem Function DrawImageRect( image:TImage,x#,y#,w#,h#,frame=0 ) Local x0#=-image.handle_x,x1#=x0+w Local y0#=-image.handle_y,y1#=y0+h image.frames[frame].Draw x0,y0,x1,y1,x+origin_x,y+origin_y End Function Rem bbdoc: Draw an image in a tiled pattern about: #TileImage draws an image in a repeating, tiled pattern, filling the current viewport. End Rem Function TileImage( image:TImage,x#=0#,y#=0#,frame=0 ) blitz2d_driver.SetTransform 1,0,0,1 Local w=image.width Local h=image.height Local ox=viewport_x-w+1 Local oy=viewport_y-h+1 Local px#=x+origin_x-image.handle_x Local py#=y+origin_y-image.handle_y Local fx#=px-Floor(px) Local fy#=py-Floor(py) Local tx=Floor(px)-ox Local ty=Floor(py)-oy If tx>=0 tx=tx Mod w + ox Else tx=w - -tx Mod w + ox If ty>=0 ty=ty Mod h + oy Else ty=h - -ty Mod h + oy Local vr=viewport_x+viewport_w,vb=viewport_y+viewport_h Local iy=ty While iy<vb Local ix=tx While ix<vr image.frames[frame].Draw 0,0,w,h,ix+fx,iy+fy ix=ix+w Wend iy=iy+h Wend UpdateTransform End Function Rem bbdoc: Set current color about: The #SetColor command affects the color of #Plot, #DrawRect, #DrawLine, #DrawText and #DrawPoly.<p> The @red, @green and @blue parameters should be in the range of 0 to 255. End Rem Function SetColor( red,green,blue ) color_red=red color_green=green color_blue=blue blitz2d_driver.SetColor red,green,blue End Function Rem bbdoc: Get red, green and blue component of current color. returns: Red, green and blue values in the range 0..255 in the variables supplied. End Rem Function GetColor( red Var,green Var,blue Var ) red=color_red green=color_green blue=color_blue End Function Rem bbdoc: Set current blend mode about: SetBlend controls how pixels are combined with existing pixels in the back buffer when drawing commands are used in BlitzMax.<p> @blend should be one of: <table> <tr><th>Blend mode</th><th>Effect</th></tr> <tr><td>SOLIDBLEND</td><td>Pixels overwrite existing backbuffer pixels</td></tr> <tr><td>MASKBLEND</td><td>Pixels are drawn only if their alpha component is greater than .5</td></tr> <tr><td>ALPHABLEND</td><td>Pixels are alpha blended with existing backbuffer pixels</td></tr> <tr><td>LIGHTBLEND</td><td>Pixel colors are added to backbuffer pixel colors, giving a 'lighting' effect</td></tr> <tr><td>SHADEBLEND</td><td>Pixel colors are multiplied with backbuffer pixel colors, giving a 'shading' effect</td></tr> </table> End Rem Function SetBlend( blend ) blend_mode=blend blitz2d_driver.SetBlend blend End Function Rem bbdoc: Get current blendmode setting returns: 0 (SOLIDBLEND), 1 (MASKBLEND) ,2 (ALPHABLEND), 3 (LIGHTBLEND) or 4 (SHADEBLEND). End Rem Function GetBlend() Return blend_mode End Function Rem bbdoc: Set current alpha level about: @alpha should be in the range 0 to 1.<p> @alpha controls the transparancy level when the ALPHABLEND blend mode is in effect. The range from 0.0 to 1.0 allows a range of transparancy from completely transparent to completely solid. End Rem Function SetAlpha( alpha# ) color_alpha=alpha blitz2d_driver.SetAlpha alpha End Function Rem bbdoc: Get current alpha setting. returns: the current alpha value in the range 0..1.0 End Rem Function GetAlpha#() Return color_alpha End Function Rem bbdoc: Sets pixel width of lines drawn with the #DrawLine command End Rem Function SetLineWidth( width# ) line_width=width blitz2d_driver.SetLineWidth width End Function Rem bbdoc: Get line width returns: Current line width, in pixels End Rem Function GetLineWidth#() Return line_width End Function Rem bbdoc: Set current mask color about: The current mask color is used to build an alpha mask when images are loaded or modified. The @red, @green and @blue parameters should be in the range of 0 to 255. End Rem Function SetMaskColor( red,green,blue ) mask_red=red mask_green=green mask_blue=blue End Function Rem bbdoc: Get red, green and blue component of current mask color returns: Red, green and blue values in the range 0..255 End Rem Function GetMaskColor( red Var,green Var,blue Var ) red=color_red green=color_green blue=color_blue End Function Rem bbdoc: Set drawing viewport about: The current ViewPort defines an area within the back buffer that all drawing is clipped to. Any regions of a DrawCommand that fall outside the current ViewPort are not drawn. End Rem Function SetViewport( x,y,width,height ) viewport_x=x viewport_y=y viewport_w=width viewport_h=height blitz2d_driver.SetViewport x,y,width,height End Function Rem bbdoc: Get dimensions of current Viewport. returns: The horizontal, vertical, width and height values of the current Viewport in the variables supplied. End Rem Function GetViewport( x Var,y Var,width Var,height Var ) x=viewport_x y=viewport_y width=viewport_w height=viewport_h End Function Rem bbdoc: Set drawing origin about: The current Origin is an x,y coordinate added to all drawing x,y coordinates after any rotation or scaling. End Rem Function SetOrigin( x#,y# ) origin_x=x origin_y=y End Function Rem bbdoc: Get current origin position. returns: The horizontal and vertical position of the current origin. End Rem Function GetOrigin( x# Var,y# Var ) x=origin_x y=origin_y End Function Rem bbdoc: Set drawing handle about: The drawing handle is a 2D offset added to the x,y location of all drawing commands. Unlike #SetOrigin, the drawing handle is added before rotation and scale are applied providing a <i>local</i> origin. end rem Function SetHandle( x#,y# ) handle_x=-x handle_y=-y End Function Rem bbdoc: Get current drawing handle. returns: The horizontal and vertical position of the current drawing handle. End Rem Function GetHandle( x# Var,y# Var ) x=handle_x y=handle_y End Function Rem bbdoc: Set current rotation about: @rotation is given in degrees and should be in the range 0 to 360. End Rem Function SetRotation( rotation# ) tform_rot=rotation UpdateTransform End Function Rem bbdoc: Get current Max2D rotation setting. returns: The rotation in degrees. End Rem Function GetRotation#() Return tform_rot End Function Rem bbdoc: Set current scale about: @scale_x and @scale_y multiply the width and height of drawing commands where 0.5 will half the size of the drawing and 2.0 is equivalent to doubling the size. End Rem Function SetScale( scale_x#,scale_y# ) tform_scale_x=scale_x tform_scale_y=scale_y UpdateTransform End Function Rem bbdoc: Get current Max2D scale settings. returns: The current x and y scale values in the variables supplied. End Rem Function GetScale( scale_x# Var,scale_y# Var ) scale_x=tform_scale_x scale_y=tform_scale_y End Function Rem bbdoc: Set current rotation and scale about: SetTransform is a shortcut for setting both the rotation and scale parameters in Max2D with a single function call. End Rem Function SetTransform( rotation#=0,scale_x#=1,scale_y#=1 ) tform_rot=rotation tform_scale_x=scale_x tform_scale_y=scale_y UpdateTransform End Function Rem bbdoc: Make the mouse pointer visible End Rem Function ShowMouse() blitz2d_driver.SetMouseVisible True End Function Rem bbdoc: Make the mouse pointer invisible End Rem Function HideMouse() blitz2d_driver.SetMouseVisible False End Function Rem bbdoc: Load an image font returns: An image font object end rem Function LoadImageFont:TImageFont( url:Object,size,style=SMOOTHFONT ) Return TImageFont.Load( url,size,style ) End Function Rem bbdoc: Set current image font about: In order to #DrawText in fonts other than the default system font use the #SetImageFont command with a font handle returned by the #LoadImageFont command.<br> <br> Use <font class=token>SetImageFont Null</font> to select the default, built-in font. End Rem Function SetImageFont( font:TImageFont ) If Not font font=default_font image_font=font End Function Rem bbdoc: Get current image font. returns: The current image font. End Rem Function GetImageFont:TImageFont() Return image_font End Function Rem bbdoc: Get width of text about: This command is useful for calculating horizontal alignment of text when using the #DrawText command. returns: The width, in pixels, of @text based on the current image font. End Rem Function TextWidth( text$ ) Local width=0 For Local n=0 Until text.length Local c=text[n]-image_font.BaseChar() If c<0 Or c>=image_font.CountGlyphs() Continue width:+image_font.Glyph(c).Advance() Next Return width End Function Rem bbdoc: Get height of text about: This command is useful for calculating vertical alignment of text when using the #DrawText command. returns: The width, in pixels, of @text based on the current image font. End Rem Function TextHeight( text$ ) Local height=0 For Local n=0 Until text.length Local c=text[n]-image_font.BaseChar() If c<0 Or c>=image_font.CountGlyphs() Continue Local x,y,w,h image_font.Glyph(c).GetRect( x,y,w,h ) height=Max(height,h) Next Return height End Function Rem bbdoc: Load an image returns: A new image object about: @url can be either a string or an existing pixmap.<br> <br> @flags can be 0, -1, or any combination of:<br> <br> <table> <tr><th>Flags value</th><th>Effect</th></tr> <tr><td><font class=token>FILTEREDIMAGE</font></td><td>The image is smoothed when scaled or rotated</td></tr> <tr><td><font class=token>DYNAMICIMAGE</font></td><td>The image can be modified using #LockImage or #GrabImage </td></tr> <tr><td><font class=token>MASKEDIMAGE</font></td><td>The image is masked with the current mask color</td></tr> </table><br> <br> If flags is -1, the default auto image flags are used: See @AutoImageFlags<br> <br> To combine flags, use the <font class=token>|</font> (Boolean OR) operator. End Rem Function LoadImage:TImage( url:Object,flags=-1 ) If flags=-1 flags=auto_imageflags Local image:TImage=TImage.Load( url,mask_red,mask_green,mask_blue,flags ) If Not image Return If auto_midhandle MidHandleImage image Return image End Function Rem bbdoc: Load a multi-frame image returns: An image object about: #LoadAnimImage extracts multiple image frames from a single, larger image. @url can be either a string or an existing pixmap.<br> <br> See #LoadImage for valid @flags values. End Rem Function LoadAnimImage:TImage( url:Object,cell_width,cell_height,first_cell,cell_count,flags=-1 ) If flags=-1 flags=auto_imageflags Local image:TImage=TImage.LoadAnim( url,cell_width,cell_height,first_cell,cell_count,mask_red,mask_green,mask_blue,flags ) If Not image Return If auto_midhandle MidHandleImage image Return image End Function Rem bbdoc: Set an image's handle to an arbitrary point End Rem Function SetImageHandle( image:TImage,x#,y# ) image.handle_x=x image.handle_y=y End Function Rem bbdoc: Enable or disable auto midhandle mode about: When auto midhandle mode is enabled, all images are automatically 'midhandled' (see #MidHandleImage) when they are created. If auto midhandle mode is disabled, images are handled by their top left corner. End Rem Function AutoMidHandle( enable ) auto_midhandle=enable End Function Rem bbdoc: Set auto image flags about: The auto image flags are used by #LoadImage when no image flags are specified. See #LoadImage for a full list of valid image flags. end rem Function AutoImageFlags( flags ) If flags=-1 Return auto_imageflags=flags End Function Rem bbdoc: Set an image's handle to its center End Rem Function MidHandleImage( image:TImage ) image.handle_x=image.width*.5 image.handle_y=image.height*.5 End Function Rem bbdoc: Get width of an image returns: The width, in pixels, of @image End Rem Function ImageWidth( image:TImage ) Return image.width End Function Rem bbdoc: Get height of an image returns: The height, in pixels, of @image End Rem Function ImageHeight( image:TImage ) Return image.height End Function Rem bbdoc: Create an empty image returns: A new image object about: #CreateImage creates an 'empty' image, which should be initialized using either #GrabImage or #LockImage before being drawn.<br> <br> Please refer to #LoadImage for valid @flags values. The @flags value is always combined with DYNAMICIMAGE. End Rem Function CreateImage:TImage( width,height,frames=1,flags=-1 ) If flags=-1 flags=auto_imageflags Local image:TImage=TImage.Create( width,height,frames,flags|DYNAMICIMAGE ) If auto_midhandle MidHandleImage image Return image End Function Rem bbdoc: Lock an image for direct access returns: A pixmap representing the image contents about: Locking an image allows you to directly access an image's pixels.<br> <br> Only images created with the DYNAMICIMAGE flag can be locked.<br> <br> Locked images must eventually be unlocked with #UnlockImage before they can be drawn. end rem Function LockImage:TPixmap( image:TImage,frame=0,read_lock=True,write_lock=True ) Return image.frames[frame].Lock( read_lock,write_lock ) End Function Rem bbdoc: Unlock an image about: Unlocks an image previously locked with #LockImage. end rem Function UnlockImage( image:TImage,frame=0 ) image.frames[frame].Unlock End Function Rem bbdoc: Grab an image from the back buffer about: Copies pixels from the back buffer to an image frame.<br> <br> Only images created with the DYNAMICIMAGE flag can be grabbed. End Rem Function GrabImage( image:TImage,x,y,frame=0 ) Local pixmap:TPixmap=blitz2d_driver.GrabPixmap( x,y,image.width,image.height ) If image.flags&MASKEDIMAGE pixmap=MaskPixmap( pixmap,mask_red,mask_green,mask_blue ) image.frames[frame]=blitz2d_driver.CreateFrameFromPixmap( pixmap,image.flags ) image.masks[frame]=pixmap End Function Rem bbdoc: Draw pixmap end rem Function DrawPixmap( pixmap:TPixmap,x,y ) blitz2d_driver.DrawPixmap pixmap,x,y End Function Rem bbdoc: Grab pixmap end rem Function GrabPixmap:TPixmap( x,y,width,height ) Return blitz2d_driver.GrabPixmap( x,y,width,height ) End Function Const COLLISION_LAYER_ALL=0 Const COLLISION_LAYER_1=$0001 Const COLLISION_LAYER_2=$0002 Const COLLISION_LAYER_3=$0004 Const COLLISION_LAYER_4=$0008 Const COLLISION_LAYER_5=$0010 Const COLLISION_LAYER_6=$0020 Const COLLISION_LAYER_7=$0040 Const COLLISION_LAYER_8=$0080 Const COLLISION_LAYER_9=$0100 Const COLLISION_LAYER_10=$0200 Const COLLISION_LAYER_11=$0400 Const COLLISION_LAYER_12=$0800 Const COLLISION_LAYER_13=$1000 Const COLLISION_LAYER_14=$2000 Const COLLISION_LAYER_15=$4000 Const COLLISION_LAYER_16=$8000 Const COLLISION_LAYER_17=$00010000 Const COLLISION_LAYER_18=$00020000 Const COLLISION_LAYER_19=$00040000 Const COLLISION_LAYER_20=$00080000 Const COLLISION_LAYER_21=$00100000 Const COLLISION_LAYER_22=$00200000 Const COLLISION_LAYER_23=$00400000 Const COLLISION_LAYER_24=$00800000 Const COLLISION_LAYER_25=$01000000 Const COLLISION_LAYER_26=$02000000 Const COLLISION_LAYER_27=$04000000 Const COLLISION_LAYER_28=$08000000 Const COLLISION_LAYER_29=$10000000 Const COLLISION_LAYER_30=$20000000 Const COLLISION_LAYER_31=$40000000 Const COLLISION_LAYER_32=$80000000 Rem bbdoc: Tests if two images collide returns: True if any pixels of the two images specified at the given location overlap. about: #ImagesCollide uses the current Rotation and Scale factors from the most previous call to #SetScale and #SetRotation to calculate at a pixel level if the two images collide. End Rem Function ImagesCollide(image1:TImage,x1,y1,frame1,image2:TImage,x2,y2,frame2) ResetCollisions COLLISION_LAYER_32 CollideImage image1,x1,y1,frame1,0,COLLISION_LAYER_32 If CollideImage(image2,x2,y2,frame2,COLLISION_LAYER_32,0) Return True End Function Rem bbdoc: Tests if two images with arbitrary Rotation and Scales collide returns: True if any pixels of the two images specified at the given location overlap. about: #ImagesCollide2 uses the specified Rotation and Scale paramteters to calculate at a pixel level if the two images collide (overlap). End Rem Function ImagesCollide2(image1:TImage,x1,y1,frame1,rot1#,scalex1#,scaley1#,image2:TImage,x2,y2,frame2,rot2#,scalex2#,scaley2#) Local _scalex#,_scaley#,_rot#,res _rot=GetRotation() GetScale _scalex,_scaley ResetCollisions COLLISION_LAYER_32 SetRotation rot1 SetScale scalex1,scaley1 CollideImage image1,x1,y1,frame1,0,COLLISION_LAYER_32 SetRotation rot2 SetScale scalex2,scaley2 If CollideImage(image2,x2,y2,frame2,COLLISION_LAYER_32,0) res=True SetRotation _rot SetScale _scalex,_scaley Return res End Function Rem bbdoc: Clears collision layers specified by the value of @mask, mask=0 for all layers. about: The BlitzMax 2D collision system manages 32 layers, the @mask parameter can be a combination of the following values or the special value COLLISION_LAYER_ALL in order to perform collision operations on multiple layers.<br> Note: @COLLISION_LAYER_32 is used by the ImagesCollide and ImagesCollide2 commands. <table> <tr><th>Layer</th><th>MaskValue</th></tr> <tr><td>COLLISION_LAYER_ALL</td><td>0</td></tr> <tr><td>COLLISION_LAYER_1</td><td>$0001</td></tr> <tr><td>COLLISION_LAYER_2</td><td>$0002</td></tr> <tr><td>COLLISION_LAYER_3</td><td>$0004</td></tr> <tr><td>COLLISION_LAYER_4</td><td>$0008</td></tr> <tr><td>COLLISION_LAYER_5</td><td>$0010</td></tr> <tr><td>COLLISION_LAYER_6</td><td>$0020</td></tr> <tr><td>COLLISION_LAYER_7</td><td>$0040</td></tr> <tr><td>COLLISION_LAYER_8</td><td>$0080</td></tr> <tr><td>COLLISION_LAYER_9</td><td>$0100</td></tr> <tr><td>COLLISION_LAYER_10</td><td>$0200</td></tr> <tr><td>COLLISION_LAYER_11</td><td>$0400</td></tr> <tr><td>COLLISION_LAYER_12</td><td>$0800</td></tr> <tr><td>COLLISION_LAYER_13</td><td>$1000</td></tr> <tr><td>COLLISION_LAYER_14</td><td>$2000</td></tr> <tr><td>COLLISION_LAYER_15</td><td>$4000</td></tr> <tr><td>COLLISION_LAYER_16</td><td>$8000</td></tr> </table> EndRem Function ResetCollisions(mask%=0) Local i,q:TQuad For i=0 To 31 If mask=0 Or mask&(1 Shl i) q=quadlayer[i] If q While q.link q=q.link Wend q.link=freequads q=quadlayer[i] freequads=q quadlayer[i]=Null EndIf EndIf Next End Function Rem bbdoc: Pixel accurate collision testing between transformed Images. about: The @collidemask specifies any layers to test for collision with. The @writemask specifies which if any collision layers the @image is added to in it's currently transformed state. The id specifies an object to be returned to future #CollideImage calls when collisions occur. EndRem Function CollideImage:Object[](image:TImage,x,y,frame,collidemask%,writemask%,id:Object=Null) Local q:TQuad q=CreateQuad(image,frame,x,y,image.width,image.height,id) Return CollideQuad(q,collidemask,writemask) End Function Rem bbdoc: Pixel accurate collision testing between image layers about: The @collidemask specifies any layers to test for collision with.<br> The @writemask specifies which if any collision layers the @image is added to in it's currently transformed state.<br> The @id specifies an object to be returned to future #CollideImage calls when collisions occur.<br> EndRem Function CollideRect:Object[](x,y,w,h,collidemask%,writemask%,id:Object=Null) Local q:TQuad q=CreateQuad(Null,0,x,y,w,h,id) Return CollideQuad(q,collidemask,writemask) End Function Private Global cix#,ciy#,cjx#,cjy# Function SetCollisions2DTransform(ix#,iy#,jx#,jy#) 'callback from module Blitz2D cix=ix ciy=iy cjx=jx cjy=jy End Function Global TextureMaps:TPixmap[] Global LineBuffer[] Global quadlayer:TQuad[32] Global freequads:TQuad Const POLYX=0 Const POLYY=1 Const POLYU=2 Const POLYV=3 Function DotProduct(x0#,y0#,x1#,y1#,x2#,y2#) Return (((x2-x1)*(y1-y0))-((x1-x0)*(y2-y1))) End Function Function ClockwisePoly(data#[],channels) 'flips order if anticlockwise Local count,clk,i,j Local r0,r1,r2 Local t# count=Len(data)/channels ' clock wise test r0=0 r1=channels clk=2 For i=2 To count-1 r2=r1+channels If DotProduct(data[r0+POLYX],data[r0+POLYY],data[r1+POLYX],data[r1+POLYY],data[r2+POLYX],data[r2+POLYY])>=0 clk:+1 r1=r2 Next If clk<count Return ' flip order for anti@#!*wise r0=0 r1=(count-1)*channels While r0<r1 For j=0 To channels-1 t=data[r0+j] data[r0+j]=data[r1+j] data[r1+j]=t Next r0:+channels r1:-channels Wend End Function Type rpoly 'Extends TNode Field texture:TPixmap Field data#[] Field channels,count,size Field ldat#[],ladd#[] Field rdat#[],radd#[] Field Left,Right,top Field state End Type Function RenderPolys(vdata#[][],channels[],textures:TPixmap[],renderspans(polys:TList,count,ypos)) Local polys:rpoly[],p:rpoly,pcount Local active:TList Local top,bot Local n,y,h,i,j,res Local data#[] bot=$80000000 top=$7fffffff n=Len(vdata) ' create polys an array of poly renderers polys=New rpoly[n] For i=0 Until n p=New rpoly polys[i]=p p.texture=textures[i] p.data=vdata[i] p.channels=channels[i] p.count=Len(p.data)/p.channels p.size=p.count*p.channels ClockwisePoly(p.data,p.channels) 'flips order if anticlockwise ' find top verticies p.Left=0 j=0 p.top=$7fffffff While j<p.size y=p.data[j+POLYY] 'float to int conversion If y<p.top p.top=y;p.Left=j If y<top top=y If y>bot bot=y j:+p.channels Wend p.Right=p.Left Next active=New TList pcount=0 ' draw top to bottom For y=top To bot-1 ' get left gradient For p=EachIn polys If p.state=2 Continue If p.state=0 And y<p.top Continue data=p.data If y>=Int(data[p.Left+POLYY]) j=p.Left i=(p.Left-p.channels) If i<0 i:+p.size While i<>p.Left If Int(data[i+POLYY])>y Exit j=i i=(i-p.channels) If i<0 i:+p.size Wend h=Int(data[i+POLYY])-Int(data[j+POLYY]) If i=p.Left Or h<=0 active.remove p ' p.remove pcount:-1 p.state=2 Continue EndIf p.ldat=data[j..j+p.channels] p.ladd=data[i..i+p.channels] For j=0 To p.channels-1 p.ladd[j]=(p.ladd[j]-p.ldat[j])/h p.ldat[j]:+p.ladd[j]*0.5 Next p.Left=i If p.state=0 p.state=1 active.AddLast p pcount:+1 EndIf EndIf ' get right gradient If y>=Int(data[p.Right+POLYY]) i=(p.Right+p.channels) Mod p.size j=p.Right While i<>p.Right If Int(data[i+POLYY])>y Exit j=i i=(i+p.channels)Mod p.size Wend h=Int(data[i+POLYY])-Int(data[j+POLYY]) If i=p.Right Or h<=0 active.remove p pcount:-1 p.state=2 Continue EndIf p.rdat=data[j..j+p.channels] p.radd=data[i..i+p.channels] For j=0 To p.channels-1 p.radd[j]=(p.radd[j]-p.rdat[j])/h p.rdat[j]:+p.radd[j]*0.5 Next p.Right=i If p.state=0 p.state=1 active.AddLast p pcount:+1 EndIf EndIf Next ' call renderer If pcount res=renderspans(active,pcount,y) If res<0 Return res EndIf ' increment spans For p=EachIn active For j=0 To p.channels-1 p.ldat[j]:+p.ladd[j] p.rdat[j]:+p.radd[j] Next Next Next Return res End Function Function CollideSpans(polys:TList,count,y) Local p:rpoly Local startx,endx Local x0,x1,w,x Local u#,v#,ui#,vi# Local pix Ptr Local src:TPixmap Local tw,th,tp,argb Local width,skip# startx=$7fffffff endx=$80000000 If count<2 Return 0 p=rpoly(polys.ValueAtIndex(0)) startx=p.ldat[POLYX] endx=p.rdat[POLYX] p=rpoly(polys.ValueAtIndex(1)) x0=p.ldat[POLYX] x1=p.rdat[POLYX] If x0>=endx Return 0 If x1<=startx Return 0 If x0>startx startx=x0 If x1<endx endx=x1 width=endx-startx If width<=0 Return 0 If width>Len(LineBuffer) LineBuffer=New Int[width] MemClear LineBuffer,width*4 For p=EachIn polys src=p.texture If src x0=p.ldat[POLYX] x1=p.rdat[POLYX] w=x1-x0 If w<=0 Continue u=p.ldat[POLYU] v=p.ldat[POLYV] ui=(p.rdat[POLYU]-u)/w vi=(p.rdat[POLYV]-v)/w skip=(startx-x0)+0.5 u=u+ui*skip v=v+vi*skip pix=Int Ptr(src.pixels) tw=src.width th=src.height tp=src.pitch/4 For x=0 Until width If u<0.0 u=0.0 If v<0.0 v=0.0 If u>1.0 u=1.0 If v>1.0 v=1.0 ?BigEndian argb=$00000080 & pix[(Int(v*th))*tp+(Int(u*tw))] ?LittleEndian argb=$80000000 & pix[(Int(v*th))*tp+(Int(u*tw))] ? If (argb) If LineBuffer[x] Return -1 LineBuffer[x]=argb EndIf u:+ui v:+vi Next Else For x=0 Until width If LineBuffer[x] Return -1 LineBuffer[x]=-1 Next EndIf Next Return 0 End Function Type TQuad Field link:TQuad Field id:Object Field mask:TPixmap Field frame Field minx#,miny#,maxx#,maxy# Field xyuv#[16] Method SetCoords(tx0#,ty0#,tx1#,ty1#,tx2#,ty2#,tx3#,ty3#) xyuv[0]=tx0 xyuv[1]=ty0 xyuv[2]=0.0 xyuv[3]=0.0 xyuv[4]=tx1 xyuv[5]=ty1 xyuv[6]=1.0 xyuv[7]=0.0 xyuv[8]=tx2 xyuv[9]=ty2 xyuv[10]=1.0 xyuv[11]=1.0 xyuv[12]=tx3 xyuv[13]=ty3 xyuv[14]=0.0 xyuv[15]=1.0 minx=tx0 miny=ty0 maxx=tx0 maxy=ty0 If tx1<minx minx=tx1 If ty1<miny miny=ty1 If tx1>maxx maxx=tx1 If ty1>maxy maxy=ty1 If tx2<minx minx=tx2 If ty2<miny miny=ty2 If tx2>maxx maxx=tx2 If ty2>maxy maxy=ty2 If tx3<minx minx=tx3 If ty3<miny miny=ty3 If tx3>maxx maxx=tx3 If ty3>maxy maxy=ty3 End Method End Type Function QuadsCollide(p:TQuad,q:TQuad) Local vertlist#[][2] Local textures:TPixmap[2] Local channels[2] If p.maxx<q.minx Or p.maxy<q.miny Or p.minx>q.maxx Or p.miny>q.maxy Return False vertlist[0]=p.xyuv vertlist[1]=q.xyuv textures[0]=p.mask textures[1]=q.mask channels[0]=4 channels[1]=4 Return RenderPolys(vertlist,channels,textures,CollideSpans) End Function Function CreateQuad:TQuad(image:TImage,frame,x#,y#,w#,h#,id:Object) Local x0#,y0#,x1#,y1#,tx#,ty# Local tx0#,ty0#,tx1#,ty1#,tx2#,ty2#,tx3#,ty3# Local minx#,miny#,maxx#,maxy# Local q:TQuad Local f:TImageFrame If image x0=-image.handle_x y0=-image.handle_y EndIf x1=x0+w y1=y0+h tx=x+origin_x ty=y+origin_y tx0=x0*cix+y0*ciy+tx ty0=x0*cjx+y0*cjy+ty tx1=x1*cix+y0*ciy+tx ty1=x1*cjx+y0*cjy+ty tx2=x1*cix+y1*ciy+tx ty2=x1*cjx+y1*cjy+ty tx3=x0*cix+y1*ciy+tx ty3=x0*cjx+y1*cjy+ty If freequads q=freequads freequads=q.link Else q=New TQuad EndIf q.link=Null q.id=id If image q.mask=image.masks[frame] f=image.frames[frame] EndIf q.setcoords(tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3) Return q End Function Function CollideQuad:Object[](pquad:TQuad,collidemask%,writemask%) Local result:Object[] Local p:TQuad,q:TQuad Local i,j,count p=pquad 'CreateImageQuad(image,frame,x,y) ' check for collisions For i=0 To 31 If collidemask & (1 Shl i) q=quadlayer[i] While q If QuadsCollide(p,q) If count=Len(result) result=result[..((count+4)*1.2)] result[count]=q.id count:+1 EndIf q=q.link Wend EndIf Next ' write to layers For i=0 To 31 If writemask & (1 Shl i) If freequads q=freequads freequads=q.link Else q=New TQuad EndIf q.id=p.id; 'TODO:optimize with memcpy? q.mask=p.mask; q.frame=p.frame MemCopy q.xyuv,p.xyuv,64 q.minx=p.minx;q.miny=p.miny;q.maxx=p.maxx;q.maxy=p.maxy; q.link=quadlayer[i] quadlayer[i]=q EndIf Next ' return result Return result[..count] End Function
thanks a lot, it helps me very much!!
After the last call to SyncMods I've seen the "AppTitle$"-Variable in the brl.blitz-mod.
This is exactly what I was asking for.
Thanks a lot, Mark!
This is exactly what I was asking for.
Thanks a lot, Mark!