12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- SuperStrict
- Rem
- bbdoc: Graphics/Max2D
- End Rem
- Module BRL.Max2D
- ModuleInfo "Version: 1.23"
- ModuleInfo "Author: Mark Sibly, Simon Armstrong"
- ModuleInfo "License: zlib/libpng"
- ModuleInfo "Copyright: Blitz Research Ltd"
- ModuleInfo "Modserver: BRL"
- ModuleInfo "History: 1.23"
- ModuleInfo "History: Changed to SuperStrict"
- ModuleInfo "History: Extended flags to Long"
- ModuleInfo "History: 1.22 Release"
- ModuleInfo "History: fixed ResetCollision not resetting recycled collision quads"
- ModuleInfo "History: 1.21 Release"
- ModuleInfo "History: makecurrent now does validate before initial cls"
- ModuleInfo "History: 1.20 Release"
- ModuleInfo "History: Fixed TImageFont.Draw so it uses float translation"
- ModuleInfo "History: 1.19 Release"
- ModuleInfo "History: Fixed collision bug with non alpha/masked images"
- ModuleInfo "History: 1.18 Release"
- ModuleInfo "History: Add Flip Hook and polledinput"
- ModuleInfo "History: 1.17 Release"
- ModuleInfo "History: Added MIPMAPPEDIMAGE to smooth fonts"
- ModuleInfo "History: Fixed ImageFont TImage.Load parameters in wrong order!"
- ModuleInfo "History: 1.16 Release"
- ModuleInfo "History: Improved ImageFont unicode support"
- ModuleInfo "History: 1.15 Release"
- ModuleInfo "History: Added OnEnd EndGraphics"
- ModuleInfo "History: 1.14 Release"
- ModuleInfo "History: CreateImage/LockImage now always returns RGBA8888 pixmap"
- ModuleInfo "History: Fixed multiple Graphics calls crashing due to using Flip before DetectSync"
- ModuleInfo "History: 1.13 Release"
- ModuleInfo "History: LoadImageFont generates filteredimage images only for smoothfont fonts"
- ModuleInfo "History: 1.12 Release"
- ModuleInfo "History: Added MIPMAPPEDIMAGE flag"
- ModuleInfo "History: 1.11 Release"
- ModuleInfo "History: Fixed Garbage at graphics startup"
- ModuleInfo "History: 1.10 Release"
- ModuleInfo "History: Fixed LockImage bug"
- ModuleInfo "History: 1.09 Release"
- ModuleInfo "History: Integrated with new graphics system"
- ModuleInfo "History: ImageFrames now lazily evaluated"
- ModuleInfo "History: Fixed GetMaskColor"
- ModuleInfo "History: 1.08 Release"
- ModuleInfo "History: Collision system optimized"
- ModuleInfo "History: Graphics now does an EndGraphics first"
- ModuleInfo "History: 1.07 Release"
- ModuleInfo "History: 1.06 Release"
- ModuleInfo "History: Added GetLineWidth:Float()"
- 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.PolledInput
- Import BRL.LinkedList
- Import BRL.Hook
- Import "image.bmx"
- Import "renderimage.bmx"
- Import "driver.bmx"
- Import "imagefont.bmx"
- Private
- Global gc:TMax2DGraphics
- Function UpdateTransform()
- Local s:Float=Sin(gc.tform_rot)
- Local c:Float=Cos(gc.tform_rot)
- gc.tform_ix= c*gc.tform_scale_x
- gc.tform_iy=-s*gc.tform_scale_y
- gc.tform_jx= s*gc.tform_scale_x
- gc.tform_jy= c*gc.tform_scale_y
- _max2dDriver.SetTransform gc.tform_ix,gc.tform_iy,gc.tform_jx,gc.tform_jy
- SetCollisions2DTransform gc.tform_ix,gc.tform_iy,gc.tform_jx,gc.tform_jy
- End Function
- Public
- Type TMax2DGraphics Extends TGraphics
- 'Field color_red,color_green,color_blue
- Field color:SColor8
- Field color_alpha:Float
- 'Field clscolor_red,clscolor_green,clscolor_blue
- Field clscolor:SColor8
- Field line_width:Float
- Field tform_rot:Float,tform_scale_x:Float,tform_scale_y:Float
- Field tform_ix:Float,tform_iy:Float,tform_jx:Float,tform_jy:Float
- Field viewport_x:Int,viewport_y:Int,viewport_w:Int,viewport_h:Int
- Field origin_x:Float,origin_y:Float
- Field handle_x:Float,handle_y:Float
- Field image_font:TImageFont
- Field blend_mode:Int
- Field vres_width:Float,vres_height:Float
- Field vres_mousexscale:Float,vres_mouseyscale:Float
- Field g_width:Int,g_height:Int
- Global default_font:TImageFont
- Global mask_red:Int,mask_green:Int,mask_blue:Int
- Global auto_midhandle:Int
- Global auto_imageflags:Int=MASKEDIMAGE|FILTEREDIMAGE
- Field _graphics:TGraphics,_driver:TMax2DDriver,_setup:Int
- Field _ric:TRenderImageContext
-
- Method Driver:TMax2DDriver() Override
- Return _driver
- End Method
-
- Method GetSettings( width:Int Var,height:Int Var,depth:Int Var,hertz:Int Var,flags:Long Var, x:Int Var, y:Int Var ) Override
- Local w:Int,h:Int,d:Int,r:Int,f:Long,xp:Int,yp:Int
- _graphics.GetSettings w,h,d,r,f,xp,yp
- width=w
- height=h
- depth=d
- hertz=r
- flags=f
- x=-1
- y=-1
- End Method
-
- Method Close() Override
- If Not _graphics Return
- _graphics.Close
- _graphics=Null
- _driver=Null
- End Method
-
- Method Validate()
- Local w:Int,h:Int,d:Int,r:Int,f:Long,xp:Int,yp:Int
- _graphics.GetSettings w,h,d,r,f,xp,yp
- If w<>g_width Or h<>g_height
- g_width=w
- g_height=h
- vres_width=w
- vres_height=h
- vres_mousexscale=1
- vres_mouseyscale=1
- EndIf
- SetVirtualResolution vres_width,vres_height
- SetBlend blend_mode
- SetColor color
- SetAlpha color_alpha
- SetClsColor clscolor
- SetLineWidth line_width
- SetRotation tform_rot
- SetScale tform_scale_x,tform_scale_y
- SetViewport viewport_x,viewport_y,viewport_w,viewport_h
- SetOrigin origin_x,origin_y
- SetHandle -handle_x,-handle_y
- SetImageFont image_font
- End Method
-
- Method MakeCurrent()
- gc=Self
- _max2dDriver=TMax2DDriver( Driver() )
- Assert _max2dDriver
- Validate
- If _setup Return
- Cls
- Flip 0
- Cls
- Flip 0
- _setup=True
- End Method
-
- Function ClearCurrent()
- gc=Null
- _max2dDriver=Null
- End Function
-
- Function Current:TMax2DGraphics()
- Return gc
- End Function
-
- Function Create:TMax2DGraphics( g:TGraphics,d:TMax2DDriver )
- Local gw:Int,gh:Int,gd:Int,gr:Int,gf:Long,gx:Int,gy:Int
- g.GetSettings gw,gh,gd,gr,gf,gx,gy
-
- If Not default_font default_font=TImageFont.CreateDefault()
- Local t:TMax2DGraphics=New TMax2DGraphics
-
- t.g_width=gw
- t.g_height=gh
- t.blend_mode=MASKBLEND
- t.color = New SColor8(255, 255, 255)
- t.color_alpha=1
- t.clscolor = New SColor8(0, 0, 0)
- t.line_width=1
- t.tform_rot=0
- t.tform_scale_x=1
- t.tform_scale_y=1
- t.tform_ix=1
- t.tform_iy=0
- t.tform_jx=1
- t.tform_jy=0
- t.viewport_x=0
- t.viewport_y=0
- t.viewport_w=gw
- t.viewport_h=gh
- t.origin_x=0
- t.origin_y=0
- t.handle_x=0
- t.handle_y=0
- t.image_font=default_font
- t.vres_width=gw
- t.vres_height=gh
- t.vres_mousexscale=1
- t.vres_mouseyscale=1
- t._graphics=g
- t._driver=d
- t._setup=False
- Return t
- End Function
-
- Method Resize(width:Int, height:Int) Override
- _graphics.Resize(width, height)
- End Method
-
- Method Position(x:Int, y:Int) Override
- _graphics.Position(x, y)
- End Method
- Method CreateRenderImage:TRenderImage(width:Int, height:Int, UseLinearFlitering:Int = True, max2DGraphics:TGraphics = Null)
- If Not max2DGraphics Then max2DGraphics = self
- Local max2D:TMax2DGraphics = TMax2DGraphics(max2DGraphics)
- If Not max2D Then Return Null 'only supporting Max2D graphics
-
- If _ric And _ric.GraphicsContext() <> max2D._graphics
- _ric.Destroy()
- _ric = Null
- EndIf
-
- If Not _ric
- _ric = TRenderImageContext(max2D._driver.CreateRenderImageContext(max2D._graphics))
- EndIf
-
- 'sanity check
- ?debug
- Assert _ric <> Null, "The code for the current TGraphics instance doesn't exist yet for rendering to a texture, feel free to write one."
- ?
- Return _ric.CreateRenderImage(width, height, UseLinearFlitering)
- End Method
-
- Method DestroyRenderImage(renderImage:TRenderImage)
- ' sanity check
- ?debug
- Assert _ric <> Null, "No TRenderImage instances have been created"
- ?
- _ric.DestroyRenderImage(renderImage)
- End Method
- Method SetRenderImage(renderimage:TRenderImage)
- ' sanity check
- ?debug
- Assert _ric <> Null, "No TRenderImage instances have been created"
- ?
- _ric.SetRenderImage(renderimage)
- End Method
- Method CreatePixmapFromRenderImage:TPixmap(renderimage:TRenderImage)
- ' sanity check
- ?debug
- Assert _ric <> Null, "No TRenderImage instances have been created"
- ?
- Return _ric.CreatePixmapFromRenderImage(renderimage)
- End Method
- Method SetRenderImageViewport(renderimage:TRenderimage, x:Int, y:Int, width:Int, height:Int)
- ' sanity check
- ?debug
- Assert _ric <> Null, "No TRenderImage instances have been created"
- ?
- renderimage.SetViewport(x, y, width, height)
- End Method
- Method ClearRenderImage(renderimage:TRenderimage, r:Int=0, g:Int=0, b:Int=0, a:Float=0.0)
- ' sanity check
- ?debug
- Assert _ric <> Null, "No TRenderImage instances have been created"
- ?
- renderimage.Clear(r,g,b,a)
- End Method
- Method CreateRenderImageFromPixmap:TRenderImage(Pixmap:TPixmap, UseLinearFlitering:Int = True, max2DGraphics:TGraphics = Null)
- If Not max2DGraphics then max2DGraphics = self
- Local max2d:TMax2DGraphics = TMax2DGraphics(max2DGraphics)
- If Not max2d Then Return Null ' only supports Max2D
-
- If _ric And _ric.GraphicsContext() <> max2d._graphics
- _ric.Destroy()
- _ric = Null
- EndIf
-
- If Not _ric
- _ric = TRenderImageContext(max2D._driver.CreateRenderImageContext(max2D._graphics))
- EndIf
-
- 'sanity check
- ?debug
- Assert _ric <> Null, "The code for the current TGraphics instance doesn't exist yet for rendering to a texture, feel free to write one."
- Assert Pixmap <> Null, "Invalid pixmap"
- Assert Pixmap.Width <> 0 And Pixmap.Height <> 0, "Invalid pixmap"
- ?
- Return _ric.CreateRenderImageFromPixmap(Pixmap, UseLinearFlitering)
- End Method
- End Type
- Rem
- bbdoc: Clear graphics buffer
- about:
- Clears the graphics buffer to the current cls color as determined by #SetClsColor.
- End Rem
- Function Cls()
- _max2dDriver.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.
- The default cls color is black.
- End Rem
- Function SetClsColor( red:Int,green:Int,blue:Int )
- gc.clscolor = New SColor8(red, green, blue)
- _max2dDriver.SetClsColor red,green,blue
- End Function
- Function SetClsColor( color:SColor8 )
- gc.clscolor = color
- _max2dDriver.SetClsColor color
- 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:Int Var,green:Int Var,blue:Int Var )
- red=gc.clscolor.r
- green=gc.clscolor.g
- blue=gc.clscolor.b
- 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:Float,y:Float )
- _max2dDriver.Plot x+gc.origin_x,y+gc.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.
- Other commands that affect the operation of #DrawRect include #SetHandle, #SetScale,
- #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
- End Rem
- Function DrawRect( x:Float,y:Float,width:Float,height:Float )
- _max2dDriver.DrawRect..
- gc.handle_x,gc.handle_y,..
- gc.handle_x+width,gc.handle_y+height,..
- x+gc.origin_x,y+gc.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.
- 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:Float,y:Float,x2:Float,y2:Float,draw_last_pixel:Int=True )
- _max2dDriver.DrawLine..
- gc.handle_x,gc.handle_y,..
- gc.handle_x+x2-x,gc.handle_y+y2-y,..
- x+gc.origin_x,y+gc.origin_y
- If Not draw_last_pixel Return
- Local px:Float=gc.handle_x+x2-x,py:Float=gc.handle_y+y2-y
- _max2dDriver.Plot..
- px*gc.tform_ix+py*gc.tform_iy+x+gc.origin_x,px*gc.tform_jx+py*gc.tform_jy+y+gc.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.
- BlitzMax commands that affect the drawing of ovals include #SetColor, #SetHandle,
- #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
- End Rem
- Function DrawOval( x:Float,y:Float,width:Float,height:Float )
- _max2dDriver.DrawOval..
- gc.handle_x,gc.handle_y,..
- gc.handle_x+width,gc.handle_y+height,..
- x+gc.origin_x,y+gc.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.
- BlitzMax commands that affect the drawing of polygons include #SetColor, #SetHandle,
- #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
- End Rem
- Function DrawPoly( xy:Float[], indices:Int[] = Null )
- _max2dDriver.DrawPoly xy,..
- gc.handle_x,gc.handle_y,..
- gc.origin_x,gc.origin_y, indices
- 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.
- Other commands that affect #DrawText include #SetColor, #SetHandle,
- #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
- It is recomended that the blend mode be set to ALPHABLEND using the #SetBlend
- command for non jagged antialiased text. Text that will be drawn at a smaller
- size using the #SetScale command should use fonts loaded with the SMOOTHFONT
- style to benefit from mip-mapped filtering, see #LoadImageFont for more information.
- End Rem
- Function DrawText( t:String,x:Float,y:Float )
- gc.image_font.Draw t,..
- x+gc.origin_x+gc.handle_x*gc.tform_ix+gc.handle_y*gc.tform_iy,..
- y+gc.origin_y+gc.handle_x*gc.tform_jx+gc.handle_y*gc.tform_jy,..
- gc.tform_ix,gc.tform_iy,gc.tform_jx,gc.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.
- If the blend mode is ALPHABLEND the image is affected by the current alpha value
- and images with alpha channels are blended correctly with the background.
- End Rem
- Function DrawImage( image:TImage,x:Float,y:Float,frame:Int=0 )
- Local x0:Float=-image.handle_x,x1:Float=x0+image.width
- Local y0:Float=-image.handle_y,y1:Float=y0+image.height
- Local iframe:TImageFrame=image.Frame(frame)
- If iframe iframe.Draw x0,y0,x1,y1,x+gc.origin_x,y+gc.origin_y,0,0,image.width,image.height
- End Function
- Rem
- bbdoc: Draw an image to a rectangular area of the back buffer
- about:
- @x, @y, @w and @h specify the destination rectangle to draw to.
- @frame is the image frame to draw.
- Drawing is affected by the current blend mode, color, scale and rotation.
- If the blend mode is ALPHABLEND, then the image is also affected by the current alpha value.
- End Rem
- Function DrawImageRect( image:TImage,x:Float,y:Float,w:Float,h:Float,frame:Int=0 )
- Local x0:Float=-image.handle_x,x1:Float=x0+w
- Local y0:Float=-image.handle_y,y1:Float=y0+h
- Local iframe:TImageFrame=image.Frame(frame)
- If iframe iframe.Draw x0,y0,x1,y1,x+gc.origin_x,y+gc.origin_y,0,0,image.width,image.height
- End Function
- Rem
- bbdoc: Draw a sub rectangle of an image to a rectangular area of the back buffer
- about:
- @x, @y, @w and @h specify the destination rectangle to draw to.
- @sx, @sy, @sw and @sh specify the source rectangle within the image to draw from.
- @hx and @hy specify a handle offset within the source rectangle.
- @frame is the image frame to draw.
- Drawing is affected by the current blend mode, color, scale and rotation.
- If the blend mode is ALPHABLEND, then the image is also affected by the current alpha value.
- End Rem
- Function DrawSubImageRect( image:TImage,x:Float,y:Float,w:Float,h:Float,sx:Float,sy:Float,sw:Float,sh:Float,hx:Float=0,hy:Float=0,frame:Int=0 )
- Local x0:Float=-hx*w/sw,x1:Float=x0+w
- Local y0:Float=-hy*h/sh,y1:Float=y0+h
- Local iframe:TImageFrame=image.Frame(frame)
- If iframe iframe.Draw x0,y0,x1,y1,x+gc.origin_x,y+gc.origin_y,sx,sy,sw,sh
- 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:Float=0:Float,y:Float=0:Float,frame:Int=0 )
- Local iframe:TImageFrame=image.Frame(frame)
- If Not iframe Return
-
- _max2dDriver.SetTransform 1,0,0,1
- Local w:Int=image.width
- Local h:Int=image.height
- Local ox:Int=gc.viewport_x-w+1
- Local oy:Int=gc.viewport_y-h+1
- Local px:Float=x+gc.origin_x-image.handle_x
- Local py:Float=y+gc.origin_y-image.handle_y
- Local fx:Float=px-Floor(px)
- Local fy:Float=py-Floor(py)
- Local tx:Int=Floor(px)-ox
- Local ty:Int=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:Int=gc.viewport_x+gc.viewport_w,vb:Int=gc.viewport_y+gc.viewport_h
- Local iy:Int=ty
- While iy<vb
- Local ix:Int=tx
- While ix<vr
- iframe.Draw 0,0,w,h,ix+fx,iy+fy,0,0,w,h
- 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,
- #DrawImage and #DrawPoly.
- The @red, @green and @blue parameters should be in the range of 0 to 255.
- End Rem
- Function SetColor( red:Int,green:Int,blue:Int )
- gc.color = New SColor8(red, green, blue)
- _max2dDriver.SetColor red,green,blue
- End Function
- Function SetColor( color:SColor8 )
- gc.color = color
- _max2dDriver.SetColor color
- 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:Int Var,green:Int Var,blue:Int Var )
- red=gc.color.r
- green=gc.color.g
- blue=gc.color.b
- End Function
- Function GetColor( color:SColor8 Var )
- color = gc.color
- 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.
- @blend should be one of:
- [ @{Blend mode} | @Effect
- * MASKBLEND | Pixels are drawn only if their alpha component is greater than .5
- * SOLIDBLEND | Pixels overwrite existing backbuffer pixels
- * ALPHABLEND | Pixels are alpha blended with existing backbuffer pixels
- * LIGHTBLEND | Pixel colors are added to backbuffer pixel colors, giving a 'lighting' effect
- * SHADEBLEND | Pixel colors are multiplied with backbuffer pixel colors, giving a 'shading' effect
- ]
- End Rem
- Function SetBlend( blend:Int )
- gc.blend_mode=blend
- _max2dDriver.SetBlend blend
- End Function
- Rem
- bbdoc: Get current blend mode
- returns: The current blend mode.
- About:
- See #SetBlend for possible return values.
- End Rem
- Function GetBlend:Int()
- Return gc.blend_mode
- End Function
- Rem
- bbdoc: Set current alpha level
- about:
- @alpha should be in the range 0 to 1.
- @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:Float )
- gc.color_alpha=alpha
- _max2dDriver.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:Float()
- Return gc.color_alpha
- End Function
- Rem
- bbdoc: Sets pixel width of lines drawn with the #DrawLine command
- End Rem
- Function SetLineWidth( width:Float )
- gc.line_width=width
- _max2dDriver.SetLineWidth width
- End Function
- Rem
- bbdoc: Get line width
- returns: Current line width, in pixels
- End Rem
- Function GetLineWidth:Float()
- Return gc.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:Int,green:Int,blue:Int )
- gc.mask_red=red
- gc.mask_green=green
- gc.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:Int Var,green:Int Var,blue:Int Var )
- red=gc.mask_red
- green=gc.mask_green
- blue=gc.mask_blue
- End Function
- Rem
- bbdoc: Set virtual graphics resolution
- about:
- SetResolution allows you to set a 'virtual' resolution independent of the graphics resolution.
- This allows you to design an application to work at a fixed resolution, say 640 by 480, and run it
- at any graphics resolution.
- End Rem
- Function SetVirtualResolution( width:Float,height:Float )
- gc.vres_width=width
- gc.vres_height=height
- gc.vres_mousexscale=width/GraphicsWidth()
- gc.vres_mouseyscale=height/GraphicsHeight()
- _max2dDriver.SetResolution width,height
- End Function
- Rem
- bbdoc: Get virtual graphics resolution width
- End Rem
- Function VirtualResolutionWidth:Float()
- Return gc.vres_width
- End Function
- Rem
- bbdoc: Get virtual graphics resolution height
- End Rem
- Function VirtualResolutionHeight:Float()
- Return gc.vres_height
- End Function
- Rem
- bbdoc: Get virtual mouse X coordinate
- End Rem
- Function VirtualMouseX:Float()
- Return MouseX() * gc.vres_mousexscale
- End Function
- Rem
- bbdoc: Get virtual mouse Y coordinate
- End Rem
- Function VirtualMouseY:Float()
- Return MouseY() * gc.vres_mouseyscale
- End Function
- Rem
- bbdoc: Get virtual mouse X speed
- End Rem
- Function VirtualMouseXSpeed:Float()
- Return MouseXSpeed() * gc.vres_mousexscale
- End Function
- Rem
- bbdoc: Get virtual mouse Y speed
- End Rem
- Function VirtualMouseYSpeed:Float()
- Return MouseYSpeed() * gc.vres_mouseyscale
- End Function
- Rem
- bbdoc: Move virtual mouse
- End Rem
- Function MoveVirtualMouse( x:Float,y:Float )
- MoveMouse Int(x/gc.vres_mousexscale),Int(y/gc.vres_mouseyscale)
- 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:Int,y:Int,width:Int,height:Int )
- gc.viewport_x=x
- gc.viewport_y=y
- gc.viewport_w=width
- gc.viewport_h=height
- Local x0:Int=Floor( x / gc.vres_mousexscale )
- Local y0:Int=Floor( y / gc.vres_mouseyscale )
- Local x1:Int=Floor( (x+width) / gc.vres_mousexscale )
- Local y1:Int=Floor( (y+height) / gc.vres_mouseyscale )
- _max2dDriver.SetViewport x0,y0,(x1-x0),(y1-y0)
- 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:Int Var,y:Int Var,width:Int Var,height:Int Var )
- x=gc.viewport_x
- y=gc.viewport_y
- width=gc.viewport_w
- height=gc.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:Float,y:Float )
- gc.origin_x=x
- gc.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:Float Var,y:Float Var )
- x=gc.origin_x
- y=gc.origin_y
- End Function
- Rem
- bbdoc: Set drawing handle
- about:
- The drawing handle is a 2D offset subtracted from the x,y location of all
- drawing commands except #DrawImage as Images have their own unique handles.
- Unlike #SetOrigin the drawing handle is subtracted before rotation and scale
- are applied providing a 'local' origin.
- End Rem
- Function SetHandle( x:Float,y:Float )
- gc.handle_x=-x
- gc.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:Float Var,y:Float Var )
- x=-gc.handle_x
- y=-gc.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:Float )
- gc.tform_rot=Rotation
- UpdateTransform
- End Function
- Rem
- bbdoc: Get current Max2D rotation setting.
- returns: The rotation in degrees.
- End Rem
- Function GetRotation:Float()
- Return gc.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:Float,scale_y:Float )
- gc.tform_scale_x=scale_x
- gc.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:Float Var,scale_y:Float Var )
- scale_x=gc.tform_scale_x
- scale_y=gc.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:Float=0,scale_x:Float=1,scale_y:Float=1 )
- gc.tform_rot=Rotation
- gc.tform_scale_x=scale_x
- gc.tform_scale_y=scale_y
- UpdateTransform
- End Function
- Rem
- bbdoc: Make the mouse pointer visible
- End Rem
- Rem
- Function ShowMouse()
- _max2dDriver.SetMouseVisible True
- End Function
- End Rem
- Rem
- bbdoc: Make the mouse pointer invisible
- End Rem
- Rem
- Function HideMouse()
- _max2dDriver.SetMouseVisible False
- End Function
- End Rem
- Rem
- bbdoc: Load an image font
- returns: An image font object
- about:
- @style can be a combination of BOLDFONT, ITALICFONT and SMOOTHFONT
- flags. Use the SMOOTHFONT flag for improved filtering if the font is to be rotated or
- scaled.
- End Rem
- Function LoadImageFont:TImageFont( url:Object,size:Int,style:Int=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.
- Use &{SetImageFont Null} to select the default, built-in font.
- End Rem
- Function SetImageFont( font:TImageFont )
- If Not font font=gc.default_font
- gc.image_font=font
- End Function
- Rem
- bbdoc: Get current image font.
- returns: The current image font.
- End Rem
- Function GetImageFont:TImageFont()
- Return gc.image_font
- End Function
- Rem
- bbdoc: Get width of text
- returns: the width, in pixels, of @text based on the current image font.
- about:
- This command is useful for calculating horizontal alignment of text when using
- the #DrawText command.
- End Rem
- Function TextWidth:Int( Text:String )
- Local width:Int=0
- For Local n:Int=0 Until Text.length
- Local i:Int=gc.image_font.CharToGlyph( Text[n] )
- If i<0 Continue
- width:+gc.image_font.LoadGlyph(i).Advance()
- Next
- Return width
- End Function
- Rem
- bbdoc: Get height of text
- returns: the height, in pixels, of @text based on the current image font.
- about:
- This command is useful for calculating vertical alignment of text when using
- the #DrawText command.
- End Rem
- Function TextHeight:Int( Text:String )
- Return gc.image_font.Height()
- Rem
- 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 Rem
- End Function
- Rem
- bbdoc: Load an image
- returns: A new image object
- about:
- @url can be either a string or an existing pixmap.
- @flags can be 0, -1 or any combination of:
- [ @{Flags value} | @{Effect}
- * MASKEDIMAGE | The image is masked with the current mask color.
- * FILTEREDIMAGE | The image is smoothed when scaled up to greater than its original
- size, when rotated, or when drawn at fractional pixel coordinates.
- * MIPMAPPEDIMAGE | The image is smoothed when scaled down to less than its original size.
- * DYNAMICIMAGE | The image can be modified using #LockImage or #GrabImage.
- ]
- Note MIPMAPPEDIMAGE images consume extra video memory, so this flag should only be used
- when really necessary.
- If flags is -1, the auto image flags are used: See #AutoImageFlags.
- To combine flags, use the | (boolean OR) operator.
- End Rem
- Function LoadImage:TImage( url:Object,flags:Int=-1 )
- If flags=-1 flags=gc.auto_imageflags
- Local image:TImage=TImage.Load( url,flags,gc.mask_red,gc.mask_green,gc.mask_blue )
- If Not image Return null
- If gc.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.
- See #LoadImage for valid @flags values.
- End Rem
- Function LoadAnimImage:TImage( url:Object,cell_width:Int,cell_height:Int,first_cell:Int,cell_count:Int,flags:Int=-1 )
- If flags=-1 flags=gc.auto_imageflags
- Local image:TImage=TImage.LoadAnim( url,cell_width,cell_height,first_cell,cell_count,flags,gc.mask_red,gc.mask_green,gc.mask_blue )
- If Not image Return null
- If gc.auto_midhandle MidHandleImage image
- Return image
- End Function
- Rem
- bbdoc: Set an image's handle to an arbitrary point
- about:
- An image's handle is subtracted from the coordinates of #DrawImage before
- rotation and scale are applied.
- End Rem
- Function SetImageHandle( image:TImage,x:Float,y:Float )
- 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.
- AutoMidHandle defaults to False after calling #Graphics.
- End Rem
- Function AutoMidHandle( enable:Int )
- gc.auto_midhandle=enable
- End Function
- Rem
- bbdoc: Set auto image flags
- about:
- The auto image flags are used by #LoadImage and #CreateImage when no image
- flags are specified. See #LoadImage for a full list of valid image flags.
- AutoImageFlags defaults to MASKEDIMAGE | FILTEREDIMAGE.
- End Rem
- Function AutoImageFlags( flags:Int )
- If flags=-1 Return
- gc.auto_imageflags=flags
- End Function
- Function GetAutoImageFlags:Int()
- Return gc.auto_imageflags
- 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:Int( 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:Int( 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.
- Please refer to #LoadImage for valid @flags values. The @flags value is always combined with DYNAMICIMAGE.
- End Rem
- Function CreateImage:TImage( width:Int,height:Int,frames:Int=1,flags:Int=-1 )
- If flags=-1 flags=gc.auto_imageflags
- Local image:TImage=TImage.Create( width,height,frames,flags|DYNAMICIMAGE,gc.mask_red,gc.mask_green,gc.mask_blue )
- If gc.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.
- Only images created with the DYNAMICIMAGE flag can be locked.
- Locked images must eventually be unlocked with #UnlockImage before they can be drawn.
- End Rem
- Function LockImage:TPixmap( image:TImage,frame:Int=0,read_lock:Int=True,write_lock:Int=True )
- Return image.Lock( frame,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:Int=0 )
- End Function
- Rem
- bbdoc: Grab an image from the back buffer
- about:
- Copies pixels from the back buffer to an image frame.
- Only images created with the DYNAMICIMAGE flag can be grabbed.
- End Rem
- Function GrabImage( image:TImage,x:Int,y:Int,frame:Int=0 )
- Local pixmap:TPixmap=_max2dDriver.GrabPixmap( x,y,image.width,image.height )
- If image.flags&MASKEDIMAGE
- pixmap=MaskPixmap( pixmap,gc.mask_red,gc.mask_green,gc.mask_blue )
- EndIf
- image.SetPixmap frame,pixmap
- End Function
- Rem
- bbdoc: Draw pixmap
- end rem
- Function DrawPixmap( pixmap:TPixmap,x:Int,y:Int )
- _max2dDriver.DrawPixmap pixmap,x,y
- End Function
- Rem
- bbdoc: Grab pixmap
- end rem
- Function GrabPixmap:TPixmap( x:Int,y:Int,width:Int,height:Int )
- Return _max2dDriver.GrabPixmap( x,y,width,height )
- End Function
- Rem
- bbdoc: Create a new render image
- about:
- @width, @height specify the dimensions of the render image.
- @useLinearFlitering defines the image flag to filter images when scaling.
- @max2DGraphics is an optional parameter to pass a custom Max2DGraphics context.
- returns: #TRenderImage with the given dimension
- End Rem
- Function CreateRenderImage:TRenderImage(width:Int, height:Int, useLinearFlitering:Int = True, max2DGraphics:TMax2DGraphics = Null)
- Return gc.CreateRenderImage(width, height, useLinearFlitering, max2DGraphics)
- End Function
- Rem
- bbdoc: Create a render image from a given #TPixmap
- about:
- @pixmap defines the #TPixmap to create a new #TRenderImage from.
- @useLinearFlitering defines the image flag to filter images when scaling.
- @max2DGraphics is an optional parameter to pass a custom Max2DGraphics context.
- returns: #TRenderImage with the content of the passed #TPixmap
- End Rem
- Function CreateRenderImageFromPixmap:TRenderImage(pixmap:TPixmap, useLinearFlitering:Int = True, max2DGraphics:TMax2DGraphics = Null)
- Return gc.CreateRenderImageFromPixmap(pixmap, useLinearFlitering, max2DGraphics)
- EndFunction
- Rem
- bbdoc: Destroy a no longer needed render image
- End Rem
- Function DestroyRenderImage(renderImage:TRenderImage)
- gc.DestroyRenderImage(renderImage)
- End Function
- Rem
- bbdoc: Set a render image as currently active render target
- about:
- @renderImage defines the render image to use as target. Set to Null to render on the default graphics buffer again.
- End Rem
- Function SetRenderImage(renderImage:TRenderImage)
- gc.SetRenderImage(renderImage)
- End Function
- Rem
- bbdoc: Clear content of the passed render image
- about:
- @renderImage defines the render image to clear.
- @r, @g, @b define the red, green and blue components of the clear color. Range is 0 - 255.
- @a defines the alpha value and is ranged 0.0 to 1.0.
- End Rem
- Function ClearRenderImage(renderImage:TRenderImage, r:Int=0, g:Int=0, b:Int=0, a:Float=0.0)
- gc.ClearRenderImage(renderImage, r,g,b,a)
- End Function
- Rem
- bbdoc: Create a #TPixmap from a render image
- about:
- @renderImage defines the render image from where the #TPixmap is to generate
- returns: #TPixmap of the render image
- End Rem
- Function CreatePixmapFromRenderImage:TPixmap(renderImage:TRenderImage)
- Return gc.CreatePixmapFromRenderImage(renderImage)
- End Function
- Rem
- bbdoc: Set the viewport of the given render image
- about:
- @renderImage defines the render image to set the viewport for
- @x, @y, @width, @height define the dimension of the viewport
- End Rem
- Function SetRenderImageViewport(renderImage:TRenderImage, x:Int, y:Int, width:Int, height:Int)
- gc.SetRenderImageViewport(renderImage, x, y, width, height)
- End Function
- Rem
- bbdoc: Backup the render image (from GPU to RAM)
- about:
- When a running application is suspended (eg user logs out from the OS or hibernation)
- then Direct3D-graphics loose their context ("D3DERR_DEVICELOST").
- To enable restoration an render image needs to "persist" as else after resume the texture
- will be blank.
- Use this for dynamically created render image content which you do not re-draw each frame.
- Also use #RenderImageValid() to check if content needs to be recreated.
- @renderImage defines the render image to backup
- End Rem
- Function PersistRenderImage:Int(renderImage:TRenderImage)
- If renderImage Then Return renderImage.Persist()
- Return False
- End Function
- Rem
- bbdoc: Check if render image content is still valid
- about:
- When a running application is suspended (eg user logs out from the OS or hibernation)
- then Direct3D-graphics loose their context ("D3DERR_DEVICELOST") and so the textures.
- If that happens, the render image is flagged to no longer be valid.
- @renderImage defines the render image to backup
- returns: False if content the render image needs to be recreated
- End Rem
- Function RenderImageValid:Int(renderImage:TRenderImage)
- If renderImage Then Return renderImage.Valid()
- Return False
- End Function
- Rem
- bbdoc: Mark a render image (in-)valid
- about:
- When a running application is suspended (eg user logs out from the OS or hibernation)
- then Direct3D-graphics loose their context ("D3DERR_DEVICELOST") and so the textures.
- Once you restored/recreated the content of your render image you can set it
- to be valid again.
- @renderImage defines the render image to backup
- @bool defines the new state of the valid flag (True or False)
- End Rem
- Function SetRenderImageValid(renderImage:TRenderImage, bool:Int = True)
- If renderImage Then renderImage.SetValid(bool)
- End Function
- Const COLLISION_LAYER_ALL:Int=0
- Const COLLISION_LAYER_1:Int=$0001
- Const COLLISION_LAYER_2:Int=$0002
- Const COLLISION_LAYER_3:Int=$0004
- Const COLLISION_LAYER_4:Int=$0008
- Const COLLISION_LAYER_5:Int=$0010
- Const COLLISION_LAYER_6:Int=$0020
- Const COLLISION_LAYER_7:Int=$0040
- Const COLLISION_LAYER_8:Int=$0080
- Const COLLISION_LAYER_9:Int=$0100
- Const COLLISION_LAYER_10:Int=$0200
- Const COLLISION_LAYER_11:Int=$0400
- Const COLLISION_LAYER_12:Int=$0800
- Const COLLISION_LAYER_13:Int=$1000
- Const COLLISION_LAYER_14:Int=$2000
- Const COLLISION_LAYER_15:Int=$4000
- Const COLLISION_LAYER_16:Int=$8000
- Const COLLISION_LAYER_17:Int=$00010000
- Const COLLISION_LAYER_18:Int=$00020000
- Const COLLISION_LAYER_19:Int=$00040000
- Const COLLISION_LAYER_20:Int=$00080000
- Const COLLISION_LAYER_21:Int=$00100000
- Const COLLISION_LAYER_22:Int=$00200000
- Const COLLISION_LAYER_23:Int=$00400000
- Const COLLISION_LAYER_24:Int=$00800000
- Const COLLISION_LAYER_25:Int=$01000000
- Const COLLISION_LAYER_26:Int=$02000000
- Const COLLISION_LAYER_27:Int=$04000000
- Const COLLISION_LAYER_28:Int=$08000000
- Const COLLISION_LAYER_29:Int=$10000000
- Const COLLISION_LAYER_30:Int=$20000000
- Const COLLISION_LAYER_31:Int=$40000000
- Const COLLISION_LAYER_32:Int=$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:Int(image1:TImage,x1:Int,y1:Int,frame1:Int,image2:TImage,x2:Int,y2:Int,frame2:Int)
- 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:Int(image1:TImage,x1:Int,y1:Int,frame1:Int,rot1:Float,scalex1:Float,scaley1:Float,image2:TImage,x2:Int,y2:Int,frame2:Int,rot2:Float,scalex2:Float,scaley2:Float)
- Local _scalex:Float,_scaley:Float,_rot:Float,res:Int
- _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.
- Note: COLLISION_LAYER_32 is used by the #ImagesCollide and #ImagesCollide2 commands.
- [ @Layer | @{Mask value}
- * COLLISION_LAYER_ALL | 0
- * COLLISION_LAYER_1 | $0001
- * COLLISION_LAYER_2 | $0002
- * COLLISION_LAYER_3 | $0004
- * COLLISION_LAYER_4 | $0008
- * COLLISION_LAYER_5 | $0010
- * COLLISION_LAYER_6 | $0020
- * COLLISION_LAYER_7 | $0040
- * COLLISION_LAYER_8 | $0080
- * COLLISION_LAYER_9 | $0100
- * COLLISION_LAYER_10 | $0200
- * COLLISION_LAYER_11 | $0400
- * COLLISION_LAYER_12 | $0800
- * COLLISION_LAYER_13 | $1000
- * COLLISION_LAYER_14 | $2000
- * COLLISION_LAYER_15 | $4000
- * COLLISION_LAYER_16 | $8000
- ]
- EndRem
- Function ResetCollisions(mask:Int=0)
- Local i:Int,q:TQuad
- For i=0 To 31
- If mask=0 Or mask&(1 Shl i)
- q=quadlayer[i]
- If q
- q.mask=Null
- q.id=Null
- While q.link
- q=q.link
- q.mask=Null
- q.id=Null
- 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:Int,y:Int,frame:Int,collidemask:Int,writemask:Int,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.
- 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 CollideRect:Object[](x:Int,y:Int,w:Int,h:Int,collidemask:Int,writemask:Int,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:Float,ciy:Float,cjx:Float,cjy:Float
- Function SetCollisions2DTransform(ix:Float,iy:Float,jx:Float,jy:Float) 'callback from module Blitz2D
- cix=ix
- ciy=iy
- cjx=jx
- cjy=jy
- End Function
- Global TextureMaps:TPixmap[]
- Global LineBuffer:Int[]
- Global quadlayer:TQuad[32]
- Global freequads:TQuad
- Const POLYX:Int=0
- Const POLYY:Int=1
- Const POLYU:Int=2
- Const POLYV:Int=3
- Function DotProduct:Int(x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float)
- Return (((x2-x1)*(y1-y0))-((x1-x0)*(y2-y1)))
- End Function
- Function ClockwisePoly(data:Float[],channels:Int) 'flips order if anticlockwise
- Local count:Int,clk:Int,i:Int,j:Int
- Local r0:Int,r1:Int,r2:Int
- Local t:Float
-
- 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 anticockwise
- 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
- Field texture:TPixmap
- Field data:Float[]
- Field channels:Int,count:Int,size:Int
- Field ldat:Float[],ladd:Float[]
- Field rdat:Float[],radd:Float[]
- Field Left:Int,Right:Int,top:Int
- Field state:Int
- End Type
- Function RenderPolys:Int(vdata:Float[][],channels:Int[],textures:TPixmap[],renderspans:Int(polys:TList,count:Int,ypos:Int))
- Local polys:rpoly[],p:rpoly,pcount:Int
- Local active:TList
- Local top:Int,bot:Int
- Local n:Int,y:Int,h:Int,i:Int,j:Int,res:Int
- Local data:Float[]
- 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:Int(polys:TList,count:Int,y:Int)
- Local p:rpoly
- Local startx:Int,endx:Int
- Local x0:Int,x1:Int,w:Int,x:Int
- Local u:Float,v:Float,ui:Float,vi:Float
- Local pix:Int Ptr
- Local src:TPixmap
- Local tw:Int,th:Int,tp:Int,argb:Int
- Local width:Int,skip:Float
-
- 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,Size_T(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:Int
- Field minx:Float,miny:Float,maxx:Float,maxy:Float
- Field xyuv:Float[16]
-
- Method SetCoords(tx0:Float,ty0:Float,tx1:Float,ty1:Float,tx2:Float,ty2:Float,tx3:Float,ty3:Float)
- 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=Min(Min(Min(tx0,tx1),tx2),tx3)
- miny=Min(Min(Min(ty0,ty1),ty2),ty3)
- maxx=Max(Max(Max(tx0,tx1),tx2),tx3)
- maxy=Max(Max(Max(ty0,ty1),ty2),ty3)
- End Method
- End Type
- Function QuadsCollide:Int(p:TQuad,q:TQuad)
- If p.maxx<q.minx Or p.maxy<q.miny Or p.minx>q.maxx Or p.miny>q.maxy Return False
- Local vertlist:Float[][2]
- Local textures:TPixmap[2]
- Local channels:Int[2]
- 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:Int,x:Float,y:Float,w:Float,h:Float,id:Object)
- Local x0:Float,y0:Float,x1:Float,y1:Float,tx:Float,ty:Float
- Local tx0:Float,ty0:Float,tx1:Float,ty1:Float,tx2:Float,ty2:Float,tx3:Float,ty3:Float
- Local minx:Float,miny:Float,maxx:Float,maxy:Float
- Local q:TQuad
- Local pix:TPixmap
-
- If image
- x0=-image.handle_x
- y0=-image.handle_y
- EndIf
- x1=x0+w
- y1=y0+h
- tx=x+gc.origin_x
- ty=y+gc.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
- q.link=Null
- Else
- q=New TQuad
- EndIf
- q.id=id
- If image
- pix=image.Lock( frame,True,False )
- If AlphaBitsPerPixel[pix.format] q.mask=pix
- EndIf
- q.setcoords(tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3)
- Return q
- End Function
- Function CollideQuad:Object[](pquad:TQuad,collidemask:Int,writemask:Int)
- Local result:Object[]
- Local p:TQuad,q:TQuad
- Local i:Int,j:Int,count:Int
- 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
- If count Return result[..count]
- End Function
|