max2d.bmx 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562
  1. Strict
  2. Rem
  3. bbdoc: Graphics/Max2D
  4. End Rem
  5. Module BRL.Max2D
  6. ModuleInfo "Version: 1.22"
  7. ModuleInfo "Author: Mark Sibly, Simon Armstrong"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.22 Release"
  12. ModuleInfo "History: fixed ResetCollision not resetting recycled collision quads"
  13. ModuleInfo "History: 1.21 Release"
  14. ModuleInfo "History: makecurrent now does validate before initial cls"
  15. ModuleInfo "History: 1.20 Release"
  16. ModuleInfo "History: Fixed TImageFont.Draw so it uses float translation"
  17. ModuleInfo "History: 1.19 Release"
  18. ModuleInfo "History: Fixed collision bug with non alpha/masked images"
  19. ModuleInfo "History: 1.18 Release"
  20. ModuleInfo "History: Add Flip Hook and polledinput"
  21. ModuleInfo "History: 1.17 Release"
  22. ModuleInfo "History: Added MIPMAPPEDIMAGE to smooth fonts"
  23. ModuleInfo "History: Fixed ImageFont TImage.Load parameters in wrong order!"
  24. ModuleInfo "History: 1.16 Release"
  25. ModuleInfo "History: Improved ImageFont unicode support"
  26. ModuleInfo "History: 1.15 Release"
  27. ModuleInfo "History: Added OnEnd EndGraphics"
  28. ModuleInfo "History: 1.14 Release"
  29. ModuleInfo "History: CreateImage/LockImage now always returns RGBA8888 pixmap"
  30. ModuleInfo "History: Fixed multiple Graphics calls crashing due to using Flip before DetectSync"
  31. ModuleInfo "History: 1.13 Release"
  32. ModuleInfo "History: LoadImageFont generates filteredimage images only for smoothfont fonts"
  33. ModuleInfo "History: 1.12 Release"
  34. ModuleInfo "History: Added MIPMAPPEDIMAGE flag"
  35. ModuleInfo "History: 1.11 Release"
  36. ModuleInfo "History: Fixed Garbage at graphics startup"
  37. ModuleInfo "History: 1.10 Release"
  38. ModuleInfo "History: Fixed LockImage bug"
  39. ModuleInfo "History: 1.09 Release"
  40. ModuleInfo "History: Integrated with new graphics system"
  41. ModuleInfo "History: ImageFrames now lazily evaluated"
  42. ModuleInfo "History: Fixed GetMaskColor"
  43. ModuleInfo "History: 1.08 Release"
  44. ModuleInfo "History: Collision system optimized"
  45. ModuleInfo "History: Graphics now does an EndGraphics first"
  46. ModuleInfo "History: 1.07 Release"
  47. ModuleInfo "History: 1.06 Release"
  48. ModuleInfo "History: Added GetLineWidth#()"
  49. ModuleInfo "History: Added GetClsColor( red Var,green Var,blue Var )"
  50. ModuleInfo "History: Fixed Object reference bug in Collision system"
  51. ModuleInfo "History: 1.05 Release"
  52. ModuleInfo "History: Fixed AnimImage collisions"
  53. ModuleInfo "History: Fixed ImagesCollide/ImagesCollide2 parameter types"
  54. Import BRL.PolledInput
  55. Import BRL.LinkedList
  56. Import BRL.Hook
  57. Import "image.bmx"
  58. Import "driver.bmx"
  59. Import "imagefont.bmx"
  60. Private
  61. Global gc:TMax2DGraphics
  62. Function UpdateTransform()
  63. Local s#=Sin(gc.tform_rot)
  64. Local c#=Cos(gc.tform_rot)
  65. gc.tform_ix= c*gc.tform_scale_x
  66. gc.tform_iy=-s*gc.tform_scale_y
  67. gc.tform_jx= s*gc.tform_scale_x
  68. gc.tform_jy= c*gc.tform_scale_y
  69. _max2dDriver.SetTransform gc.tform_ix,gc.tform_iy,gc.tform_jx,gc.tform_jy
  70. SetCollisions2DTransform gc.tform_ix,gc.tform_iy,gc.tform_jx,gc.tform_jy
  71. End Function
  72. Public
  73. Type TMax2DGraphics Extends TGraphics
  74. Field color_red,color_green,color_blue
  75. Field color_alpha#
  76. Field clscolor_red,clscolor_green,clscolor_blue
  77. Field line_width#
  78. Field tform_rot#,tform_scale_x#,tform_scale_y#
  79. Field tform_ix#,tform_iy#,tform_jx#,tform_jy#
  80. Field viewport_x,viewport_y,viewport_w,viewport_h
  81. Field origin_x#,origin_y#
  82. Field handle_x#,handle_y#
  83. Field image_font:TImageFont
  84. Field blend_mode
  85. Field vres_width#,vres_height#
  86. Field vres_mousexscale#,vres_mouseyscale#
  87. Field g_width,g_height
  88. Global default_font:TImageFont
  89. Global mask_red,mask_green,mask_blue
  90. Global auto_midhandle
  91. Global auto_imageflags=MASKEDIMAGE|FILTEREDIMAGE
  92. Field _graphics:TGraphics,_driver:TMax2DDriver,_setup
  93. Method Driver:TMax2DDriver()
  94. Return _driver
  95. End Method
  96. Method GetSettings( width Var,height Var,depth Var,hertz Var,flags Var )
  97. Local w,h,d,r,f
  98. _graphics.GetSettings w,h,d,r,f
  99. width=w
  100. height=h
  101. depth=d
  102. hertz=r
  103. flags=f
  104. End Method
  105. Method Close()
  106. If Not _graphics Return
  107. _graphics.Close
  108. _graphics=Null
  109. _driver=Null
  110. End Method
  111. Method Validate()
  112. Local w,h,d,r,f
  113. _graphics.GetSettings w,h,d,r,f
  114. If w<>g_width Or h<>g_height
  115. g_width=w
  116. g_height=h
  117. vres_width=w
  118. vres_height=h
  119. vres_mousexscale=1
  120. vres_mouseyscale=1
  121. EndIf
  122. SetVirtualResolution vres_width,vres_height
  123. SetBlend blend_mode
  124. SetColor color_red,color_green,color_blue
  125. SetAlpha color_alpha
  126. SetClsColor clscolor_red,clscolor_green,clscolor_blue
  127. SetLineWidth line_width
  128. SetRotation tform_rot
  129. SetScale tform_scale_x,tform_scale_y
  130. SetViewport viewport_x,viewport_y,viewport_w,viewport_h
  131. SetOrigin origin_x,origin_y
  132. SetHandle -handle_x,-handle_y
  133. SetImageFont image_font
  134. End Method
  135. Method MakeCurrent()
  136. gc=Self
  137. _max2dDriver=TMax2DDriver( Driver() )
  138. Assert _max2dDriver
  139. Validate
  140. If _setup Return
  141. Cls
  142. Flip 0
  143. Cls
  144. Flip 0
  145. _setup=True
  146. End Method
  147. Function ClearCurrent()
  148. gc=Null
  149. _max2dDriver=Null
  150. End Function
  151. Function Current:TMax2DGraphics()
  152. Return gc
  153. End Function
  154. Function Create:TMax2DGraphics( g:TGraphics,d:TMax2DDriver )
  155. Local gw,gh,gd,gr,gf
  156. g.GetSettings gw,gh,gd,gr,gf
  157. If Not default_font default_font=TImageFont.CreateDefault()
  158. Local t:TMax2DGraphics=New TMax2DGraphics
  159. t.g_width=gw
  160. t.g_height=gh
  161. t.blend_mode=MASKBLEND
  162. t.color_red=255
  163. t.color_green=255
  164. t.color_blue=255
  165. t.color_alpha=1
  166. t.clscolor_red=0
  167. t.clscolor_green=0
  168. t.clscolor_blue=0
  169. t.line_width=1
  170. t.tform_rot=0
  171. t.tform_scale_x=1
  172. t.tform_scale_y=1
  173. t.tform_ix=1
  174. t.tform_iy=0
  175. t.tform_jx=1
  176. t.tform_jy=0
  177. t.viewport_x=0
  178. t.viewport_y=0
  179. t.viewport_w=gw
  180. t.viewport_h=gh
  181. t.origin_x=0
  182. t.origin_y=0
  183. t.handle_x=0
  184. t.handle_y=0
  185. t.image_font=default_font
  186. t.vres_width=gw
  187. t.vres_height=gh
  188. t.vres_mousexscale=1
  189. t.vres_mouseyscale=1
  190. t._graphics=g
  191. t._driver=d
  192. t._setup=False
  193. Return t
  194. End Function
  195. End Type
  196. Rem
  197. bbdoc: Clear graphics buffer
  198. about:
  199. Clears the graphics buffer to the current cls color as determined by #SetClsColor.
  200. End Rem
  201. Function Cls()
  202. _max2dDriver.Cls
  203. End Function
  204. Rem
  205. bbdoc: Set current #Cls color
  206. about:
  207. The @red, @green and @blue parameters should be in the range of 0 to 255.
  208. The default cls color is black.
  209. End Rem
  210. Function SetClsColor( red,green,blue )
  211. gc.clscolor_red=red
  212. gc.clscolor_green=green
  213. gc.clscolor_blue=blue
  214. _max2dDriver.SetClsColor red,green,blue
  215. End Function
  216. Rem
  217. bbdoc: Get red, green and blue component of current cls color.
  218. returns: Red, green and blue values in the range 0..255 in the variables supplied.
  219. End Rem
  220. Function GetClsColor( red Var,green Var,blue Var )
  221. red=gc.clscolor_red
  222. green=gc.clscolor_green
  223. blue=gc.clscolor_blue
  224. End Function
  225. Rem
  226. bbdoc: Plot a pixel
  227. about:
  228. Sets the color of a single pixel on the back buffer to the current drawing color
  229. defined with the #SetColor command. Other commands that affect the operation of
  230. #Plot include #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
  231. End Rem
  232. Function Plot( x#,y# )
  233. _max2dDriver.Plot x+gc.origin_x,y+gc.origin_y
  234. End Function
  235. Rem
  236. bbdoc: Draw a rectangle
  237. about:
  238. Sets the color of a rectangular area of pixels using the current drawing color
  239. defined with the #SetColor command.
  240. Other commands that affect the operation of #DrawRect include #SetHandle, #SetScale,
  241. #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
  242. End Rem
  243. Function DrawRect( x#,y#,width#,height# )
  244. _max2dDriver.DrawRect..
  245. gc.handle_x,gc.handle_y,..
  246. gc.handle_x+width,gc.handle_y+height,..
  247. x+gc.origin_x,y+gc.origin_y
  248. End Function
  249. Rem
  250. bbdoc: Draw a line
  251. about:
  252. #DrawLine draws a line from @x, @y to @x2, @y2 with the current drawing color.
  253. BlitzMax commands that affect the drawing of lines include #SetLineWidth, #SetColor, #SetHandle,
  254. #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
  255. The optional @draw_last_pixel parameter can be used to control whether the last pixel of the line is drawn or not.
  256. Not drawing the last pixel can be useful if you are using certain blending modes.
  257. End Rem
  258. Function DrawLine( x#,y#,x2#,y2#,draw_last_pixel=True )
  259. _max2dDriver.DrawLine..
  260. gc.handle_x,gc.handle_y,..
  261. gc.handle_x+x2-x,gc.handle_y+y2-y,..
  262. x+gc.origin_x,y+gc.origin_y
  263. If Not draw_last_pixel Return
  264. Local px#=gc.handle_x+x2-x,py#=gc.handle_y+y2-y
  265. _max2dDriver.Plot..
  266. px*gc.tform_ix+py*gc.tform_iy+x+gc.origin_x,px*gc.tform_jx+py*gc.tform_jy+y+gc.origin_y
  267. End Function
  268. Rem
  269. bbdoc: Draw an oval
  270. about:
  271. #DrawOval draws an oval that fits in the rectangular area defined by @x, @y, @width
  272. and @height parameters.
  273. BlitzMax commands that affect the drawing of ovals include #SetColor, #SetHandle,
  274. #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
  275. End Rem
  276. Function DrawOval( x#,y#,width#,height# )
  277. _max2dDriver.DrawOval..
  278. gc.handle_x,gc.handle_y,..
  279. gc.handle_x+width,gc.handle_y+height,..
  280. x+gc.origin_x,y+gc.origin_y
  281. End Function
  282. Rem
  283. bbdoc: Draw a polygon
  284. about:
  285. #DrawPoly draws a polygon with corners defined by an array of x#,y# coordinate pairs.
  286. BlitzMax commands that affect the drawing of polygons include #SetColor, #SetHandle,
  287. #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
  288. End Rem
  289. Function DrawPoly( xy#[] )
  290. _max2dDriver.DrawPoly xy,..
  291. gc.handle_x,gc.handle_y,..
  292. gc.origin_x,gc.origin_y
  293. End Function
  294. Rem
  295. bbdoc: Draw text
  296. about:
  297. #DrawText prints strings at position @x,@y of the graphics display using
  298. the current image font specified by the #SetImageFont command.
  299. Other commands that affect #DrawText include #SetColor, #SetHandle,
  300. #SetScale, #SetRotation, #SetOrigin, #SetViewPort, #SetBlend and #SetAlpha.
  301. It is recomended that the blend mode be set to ALPHABLEND using the #SetBlend
  302. command for non jagged antialiased text. Text that will be drawn at a smaller
  303. size using the #SetScale command should use fonts loaded with the SMOOTHFONT
  304. style to benefit from mip-mapped filtering, see #LoadImageFont for more information.
  305. End Rem
  306. Function DrawText( t$,x#,y# )
  307. gc.image_font.Draw t,..
  308. x+gc.origin_x+gc.handle_x*gc.tform_ix+gc.handle_y*gc.tform_iy,..
  309. y+gc.origin_y+gc.handle_x*gc.tform_jx+gc.handle_y*gc.tform_jy,..
  310. gc.tform_ix,gc.tform_iy,gc.tform_jx,gc.tform_jy
  311. End Function
  312. Rem
  313. bbdoc: Draw an image to the back buffer
  314. about:
  315. Drawing is affected by the current blend mode, color, scale and rotation.
  316. If the blend mode is ALPHABLEND the image is affected by the current alpha value
  317. and images with alpha channels are blended correctly with the background.
  318. End Rem
  319. Function DrawImage( image:TImage,x#,y#,frame=0 )
  320. Local x0#=-image.handle_x,x1#=x0+image.width
  321. Local y0#=-image.handle_y,y1#=y0+image.height
  322. Local iframe:TImageFrame=image.Frame(frame)
  323. If iframe iframe.Draw x0,y0,x1,y1,x+gc.origin_x,y+gc.origin_y,0,0,image.width,image.height
  324. End Function
  325. Rem
  326. bbdoc: Draw an image to a rectangular area of the back buffer
  327. about:
  328. @x, @y, @w and @h specify the destination rectangle to draw to.
  329. @frame is the image frame to draw.
  330. Drawing is affected by the current blend mode, color, scale and rotation.
  331. If the blend mode is ALPHABLEND, then the image is also affected by the current alpha value.
  332. End Rem
  333. Function DrawImageRect( image:TImage,x#,y#,w#,h#,frame=0 )
  334. Local x0#=-image.handle_x,x1#=x0+w
  335. Local y0#=-image.handle_y,y1#=y0+h
  336. Local iframe:TImageFrame=image.Frame(frame)
  337. If iframe iframe.Draw x0,y0,x1,y1,x+gc.origin_x,y+gc.origin_y,0,0,image.width,image.height
  338. End Function
  339. Rem
  340. bbdoc: Draw a sub rectangle of an image to a rectangular area of the back buffer
  341. about:
  342. @x, @y, @w and @h specify the destination rectangle to draw to.
  343. @sx, @sy, @sw and @sh specify the source rectangle within the image to draw from.
  344. @hx and @hy specify a handle offset within the source rectangle.
  345. @frame is the image frame to draw.
  346. Drawing is affected by the current blend mode, color, scale and rotation.
  347. If the blend mode is ALPHABLEND, then the image is also affected by the current alpha value.
  348. End Rem
  349. Function DrawSubImageRect( image:TImage,x#,y#,w#,h#,sx#,sy#,sw#,sh#,hx#=0,hy#=0,frame=0 )
  350. Local x0#=-hx*w/sw,x1#=x0+w
  351. Local y0#=-hy*h/sh,y1#=y0+h
  352. Local iframe:TImageFrame=image.Frame(frame)
  353. If iframe iframe.Draw x0,y0,x1,y1,x+gc.origin_x,y+gc.origin_y,sx,sy,sw,sh
  354. End Function
  355. Rem
  356. bbdoc: Draw an image in a tiled pattern
  357. about:
  358. #TileImage draws an image in a repeating, tiled pattern, filling the current viewport.
  359. End Rem
  360. Function TileImage( image:TImage,x#=0#,y#=0#,frame=0 )
  361. Local iframe:TImageFrame=image.Frame(frame)
  362. If Not iframe Return
  363. _max2dDriver.SetTransform 1,0,0,1
  364. Local w=image.width
  365. Local h=image.height
  366. Local ox=gc.viewport_x-w+1
  367. Local oy=gc.viewport_y-h+1
  368. Local px#=x+gc.origin_x-image.handle_x
  369. Local py#=y+gc.origin_y-image.handle_y
  370. Local fx#=px-Floor(px)
  371. Local fy#=py-Floor(py)
  372. Local tx=Floor(px)-ox
  373. Local ty=Floor(py)-oy
  374. If tx>=0 tx=tx Mod w + ox Else tx=w - -tx Mod w + ox
  375. If ty>=0 ty=ty Mod h + oy Else ty=h - -ty Mod h + oy
  376. Local vr=gc.viewport_x+gc.viewport_w,vb=gc.viewport_y+gc.viewport_h
  377. Local iy=ty
  378. While iy<vb
  379. Local ix=tx
  380. While ix<vr
  381. iframe.Draw 0,0,w,h,ix+fx,iy+fy,0,0,w,h
  382. ix=ix+w
  383. Wend
  384. iy=iy+h
  385. Wend
  386. UpdateTransform
  387. End Function
  388. Rem
  389. bbdoc: Set current color
  390. about:
  391. The #SetColor command affects the color of #Plot, #DrawRect, #DrawLine, #DrawText,
  392. #DrawImage and #DrawPoly.
  393. The @red, @green and @blue parameters should be in the range of 0 to 255.
  394. End Rem
  395. Function SetColor( red,green,blue )
  396. gc.color_red=red
  397. gc.color_green=green
  398. gc.color_blue=blue
  399. _max2dDriver.SetColor red,green,blue
  400. End Function
  401. Rem
  402. bbdoc: Get red, green and blue component of current color.
  403. returns: Red, green and blue values in the range 0..255 in the variables supplied.
  404. End Rem
  405. Function GetColor( red Var,green Var,blue Var )
  406. red=gc.color_red
  407. green=gc.color_green
  408. blue=gc.color_blue
  409. End Function
  410. Rem
  411. bbdoc: Set current blend mode
  412. about:
  413. SetBlend controls how pixels are combined with existing pixels in the back buffer when drawing
  414. commands are used in BlitzMax.
  415. @blend should be one of:
  416. [ @{Blend mode} | @Effect
  417. * MASKBLEND | Pixels are drawn only if their alpha component is greater than .5
  418. * SOLIDBLEND | Pixels overwrite existing backbuffer pixels
  419. * ALPHABLEND | Pixels are alpha blended with existing backbuffer pixels
  420. * LIGHTBLEND | Pixel colors are added to backbuffer pixel colors, giving a 'lighting' effect
  421. * SHADEBLEND | Pixel colors are multiplied with backbuffer pixel colors, giving a 'shading' effect
  422. ]
  423. End Rem
  424. Function SetBlend( blend )
  425. gc.blend_mode=blend
  426. _max2dDriver.SetBlend blend
  427. End Function
  428. Rem
  429. bbdoc: Get current blend mode
  430. returns: The current blend mode.
  431. About:
  432. See #SetBlend for possible return values.
  433. End Rem
  434. Function GetBlend()
  435. Return gc.blend_mode
  436. End Function
  437. Rem
  438. bbdoc: Set current alpha level
  439. about:
  440. @alpha should be in the range 0 to 1.
  441. @alpha controls the transparancy level when the ALPHABLEND blend mode is in effect.
  442. The range from 0.0 to 1.0 allows a range of transparancy from completely transparent
  443. to completely solid.
  444. End Rem
  445. Function SetAlpha( alpha# )
  446. gc.color_alpha=alpha
  447. _max2dDriver.SetAlpha alpha
  448. End Function
  449. Rem
  450. bbdoc: Get current alpha setting.
  451. returns: the current alpha value in the range 0..1.0
  452. End Rem
  453. Function GetAlpha#()
  454. Return gc.color_alpha
  455. End Function
  456. Rem
  457. bbdoc: Sets pixel width of lines drawn with the #DrawLine command
  458. End Rem
  459. Function SetLineWidth( width# )
  460. gc.line_width=width
  461. _max2dDriver.SetLineWidth width
  462. End Function
  463. Rem
  464. bbdoc: Get line width
  465. returns: Current line width, in pixels
  466. End Rem
  467. Function GetLineWidth#()
  468. Return gc.line_width
  469. End Function
  470. Rem
  471. bbdoc: Set current mask color
  472. about:
  473. The current mask color is used to build an alpha mask when images are loaded or modified.
  474. The @red, @green and @blue parameters should be in the range of 0 to 255.
  475. End Rem
  476. Function SetMaskColor( red,green,blue )
  477. gc.mask_red=red
  478. gc.mask_green=green
  479. gc.mask_blue=blue
  480. End Function
  481. Rem
  482. bbdoc: Get red, green and blue component of current mask color
  483. returns: Red, green and blue values in the range 0..255
  484. End Rem
  485. Function GetMaskColor( red Var,green Var,blue Var )
  486. red=gc.mask_red
  487. green=gc.mask_green
  488. blue=gc.mask_blue
  489. End Function
  490. Rem
  491. bbdoc: Set virtual graphics resolution
  492. about:
  493. SetResolution allows you to set a 'virtual' resolution independent of the graphics resolution.
  494. This allows you to design an application to work at a fixed resolution, say 640 by 480, and run it
  495. at any graphics resolution.
  496. End Rem
  497. Function SetVirtualResolution( width#,height# )
  498. gc.vres_width=width
  499. gc.vres_height=height
  500. gc.vres_mousexscale=width/GraphicsWidth()
  501. gc.vres_mouseyscale=height/GraphicsHeight()
  502. _max2dDriver.SetResolution width,height
  503. End Function
  504. Rem
  505. bbdoc: Get virtual graphics resolution width
  506. End Rem
  507. Function VirtualResolutionWidth#()
  508. Return gc.vres_width
  509. End Function
  510. Rem
  511. bbdoc: Get virtual graphics resolution height
  512. End Rem
  513. Function VirtualResolutionHeight#()
  514. Return gc.vres_height
  515. End Function
  516. Rem
  517. bbdoc: Get virtual mouse X coordinate
  518. End Rem
  519. Function VirtualMouseX#()
  520. Return MouseX() * gc.vres_mousexscale
  521. End Function
  522. Rem
  523. bbdoc: Get virtual mouse Y coordinate
  524. End Rem
  525. Function VirtualMouseY#()
  526. Return MouseY() * gc.vres_mouseyscale
  527. End Function
  528. Rem
  529. bbdoc: Get virtual mouse X speed
  530. End Rem
  531. Function VirtualMouseXSpeed#()
  532. Return MouseXSpeed() * gc.vres_mousexscale
  533. End Function
  534. Rem
  535. bbdoc: Get virtual mouse Y speed
  536. End Rem
  537. Function VirtualMouseYSpeed#()
  538. Return MouseYSpeed() * gc.vres_mouseyscale
  539. End Function
  540. Rem
  541. bbdoc: Move virtual mouse
  542. End Rem
  543. Function MoveVirtualMouse( x#,y# )
  544. MoveMouse x/gc.vres_mousexscale,y/gc.vres_mouseyscale
  545. End Function
  546. Rem
  547. bbdoc: Set drawing viewport
  548. about:
  549. The current ViewPort defines an area within the back buffer that all drawing is clipped to. Any
  550. regions of a DrawCommand that fall outside the current ViewPort are not drawn.
  551. End Rem
  552. Function SetViewport( x,y,width,height )
  553. gc.viewport_x=x
  554. gc.viewport_y=y
  555. gc.viewport_w=width
  556. gc.viewport_h=height
  557. Local x0=Floor( x / gc.vres_mousexscale )
  558. Local y0=Floor( y / gc.vres_mouseyscale )
  559. Local x1=Floor( (x+width) / gc.vres_mousexscale )
  560. Local y1=Floor( (y+height) / gc.vres_mouseyscale )
  561. _max2dDriver.SetViewport x0,y0,(x1-x0),(y1-y0)
  562. End Function
  563. Rem
  564. bbdoc: Get dimensions of current Viewport.
  565. returns: The horizontal, vertical, width and height values of the current Viewport in the variables supplied.
  566. End Rem
  567. Function GetViewport( x Var,y Var,width Var,height Var )
  568. x=gc.viewport_x
  569. y=gc.viewport_y
  570. width=gc.viewport_w
  571. height=gc.viewport_h
  572. End Function
  573. Rem
  574. bbdoc: Set drawing origin
  575. about:
  576. The current Origin is an x,y coordinate added to all drawing x,y coordinates after any rotation or scaling.
  577. End Rem
  578. Function SetOrigin( x#,y# )
  579. gc.origin_x=x
  580. gc.origin_y=y
  581. End Function
  582. Rem
  583. bbdoc: Get current origin position.
  584. returns: The horizontal and vertical position of the current origin.
  585. End Rem
  586. Function GetOrigin( x# Var,y# Var )
  587. x=gc.origin_x
  588. y=gc.origin_y
  589. End Function
  590. Rem
  591. bbdoc: Set drawing handle
  592. about:
  593. The drawing handle is a 2D offset subtracted from the x,y location of all
  594. drawing commands except #DrawImage as Images have their own unique handles.
  595. Unlike #SetOrigin the drawing handle is subtracted before rotation and scale
  596. are applied providing a 'local' origin.
  597. End Rem
  598. Function SetHandle( x#,y# )
  599. gc.handle_x=-x
  600. gc.handle_y=-y
  601. End Function
  602. Rem
  603. bbdoc: Get current drawing handle.
  604. returns: The horizontal and vertical position of the current drawing handle.
  605. End Rem
  606. Function GetHandle( x# Var,y# Var )
  607. x=-gc.handle_x
  608. y=-gc.handle_y
  609. End Function
  610. Rem
  611. bbdoc: Set current rotation
  612. about:
  613. @rotation is given in degrees and should be in the range 0 to 360.
  614. End Rem
  615. Function SetRotation( rotation# )
  616. gc.tform_rot=rotation
  617. UpdateTransform
  618. End Function
  619. Rem
  620. bbdoc: Get current Max2D rotation setting.
  621. returns: The rotation in degrees.
  622. End Rem
  623. Function GetRotation#()
  624. Return gc.tform_rot
  625. End Function
  626. Rem
  627. bbdoc: Set current scale
  628. about:
  629. @scale_x and @scale_y multiply the width and height of drawing
  630. commands where 0.5 will half the size of the drawing and 2.0 is equivalent
  631. to doubling the size.
  632. End Rem
  633. Function SetScale( scale_x#,scale_y# )
  634. gc.tform_scale_x=scale_x
  635. gc.tform_scale_y=scale_y
  636. UpdateTransform
  637. End Function
  638. Rem
  639. bbdoc: Get current Max2D scale settings.
  640. returns: The current x and y scale values in the variables supplied.
  641. End Rem
  642. Function GetScale( scale_x# Var,scale_y# Var )
  643. scale_x=gc.tform_scale_x
  644. scale_y=gc.tform_scale_y
  645. End Function
  646. Rem
  647. bbdoc: Set current rotation and scale
  648. about:
  649. SetTransform is a shortcut for setting both the rotation and
  650. scale parameters in Max2D with a single function call.
  651. End Rem
  652. Function SetTransform( rotation#=0,scale_x#=1,scale_y#=1 )
  653. gc.tform_rot=rotation
  654. gc.tform_scale_x=scale_x
  655. gc.tform_scale_y=scale_y
  656. UpdateTransform
  657. End Function
  658. Rem
  659. bbdoc: Make the mouse pointer visible
  660. End Rem
  661. Rem
  662. Function ShowMouse()
  663. _max2dDriver.SetMouseVisible True
  664. End Function
  665. End Rem
  666. Rem
  667. bbdoc: Make the mouse pointer invisible
  668. End Rem
  669. Rem
  670. Function HideMouse()
  671. _max2dDriver.SetMouseVisible False
  672. End Function
  673. End Rem
  674. Rem
  675. bbdoc: Load an image font
  676. returns: An image font object
  677. about:
  678. @style can be a combination of BOLDFONT, ITALICFONT and SMOOTHFONT
  679. flags. Use the SMOOTHFONT flag for improved filtering if the font is to be rotated or
  680. scaled.
  681. End Rem
  682. Function LoadImageFont:TImageFont( url:Object,size,style=SMOOTHFONT )
  683. Return TImageFont.Load( url,size,style )
  684. End Function
  685. Rem
  686. bbdoc: Set current image font
  687. about:
  688. In order to #DrawText in fonts other than the default system font use the #SetImageFont
  689. command with a font handle returned by the #LoadImageFont command.
  690. Use &{SetImageFont Null} to select the default, built-in font.
  691. End Rem
  692. Function SetImageFont( font:TImageFont )
  693. If Not font font=gc.default_font
  694. gc.image_font=font
  695. End Function
  696. Rem
  697. bbdoc: Get current image font.
  698. returns: The current image font.
  699. End Rem
  700. Function GetImageFont:TImageFont()
  701. Return gc.image_font
  702. End Function
  703. Rem
  704. bbdoc: Get width of text
  705. returns: the width, in pixels, of @text based on the current image font.
  706. about:
  707. This command is useful for calculating horizontal alignment of text when using
  708. the #DrawText command.
  709. End Rem
  710. Function TextWidth( text$ )
  711. Local width=0
  712. For Local n=0 Until text.length
  713. Local i=gc.image_font.CharToGlyph( text[n] )
  714. If i<0 Continue
  715. width:+gc.image_font.LoadGlyph(i).Advance()
  716. Next
  717. Return width
  718. End Function
  719. Rem
  720. bbdoc: Get height of text
  721. returns: the height, in pixels, of @text based on the current image font.
  722. about:
  723. This command is useful for calculating vertical alignment of text when using
  724. the #DrawText command.
  725. End Rem
  726. Function TextHeight( text$ )
  727. Return gc.image_font.Height()
  728. Rem
  729. Local height=0
  730. For Local n=0 Until text.length
  731. Local c=text[n]-image_font.BaseChar()
  732. If c<0 Or c>=image_font.CountGlyphs() Continue
  733. Local x,y,w,h
  734. image_font.Glyph(c).GetRect( x,y,w,h )
  735. height=Max(height,h)
  736. Next
  737. Return height
  738. End Rem
  739. End Function
  740. Rem
  741. bbdoc: Load an image
  742. returns: A new image object
  743. about:
  744. @url can be either a string or an existing pixmap.
  745. @flags can be 0, -1 or any combination of:
  746. [ @{Flags value} | @{Effect}
  747. * MASKEDIMAGE | The image is masked with the current mask color.
  748. * FILTEREDIMAGE | The image is smoothed when scaled up to greater than its original
  749. size, when rotated, or when drawn at fractional pixel coordinates.
  750. * MIPMAPPEDIMAGE | The image is smoothed when scaled down to less than its original size.
  751. * DYNAMICIMAGE | The image can be modified using #LockImage or #GrabImage.
  752. ]
  753. Note MIPMAPPEDIMAGE images consume extra video memory, so this flag should only be used
  754. when really necessary.
  755. If flags is -1, the auto image flags are used: See #AutoImageFlags.
  756. To combine flags, use the | (boolean OR) operator.
  757. End Rem
  758. Function LoadImage:TImage( url:Object,flags=-1 )
  759. If flags=-1 flags=gc.auto_imageflags
  760. Local image:TImage=TImage.Load( url,flags,gc.mask_red,gc.mask_green,gc.mask_blue )
  761. If Not image Return
  762. If gc.auto_midhandle MidHandleImage image
  763. Return image
  764. End Function
  765. Rem
  766. bbdoc: Load a multi-frame image
  767. returns: An image object
  768. about:
  769. #LoadAnimImage extracts multiple image frames from a single, larger image. @url can be either a string or an
  770. existing pixmap.
  771. See #LoadImage for valid @flags values.
  772. End Rem
  773. Function LoadAnimImage:TImage( url:Object,cell_width,cell_height,first_cell,cell_count,flags=-1 )
  774. If flags=-1 flags=gc.auto_imageflags
  775. Local image:TImage=TImage.LoadAnim( url,cell_width,cell_height,first_cell,cell_count,flags,gc.mask_red,gc.mask_green,gc.mask_blue )
  776. If Not image Return
  777. If gc.auto_midhandle MidHandleImage image
  778. Return image
  779. End Function
  780. Rem
  781. bbdoc: Set an image's handle to an arbitrary point
  782. about:
  783. An image's handle is subtracted from the coordinates of #DrawImage before
  784. rotation and scale are applied.
  785. End Rem
  786. Function SetImageHandle( image:TImage,x#,y# )
  787. image.handle_x=x
  788. image.handle_y=y
  789. End Function
  790. Rem
  791. bbdoc: Enable or disable auto midhandle mode
  792. about:
  793. When auto midhandle mode is enabled, all images are automatically 'midhandled' (see #MidHandleImage)
  794. when they are created. If auto midhandle mode is disabled, images are handled by their top left corner.
  795. AutoMidHandle defaults to False after calling #Graphics.
  796. End Rem
  797. Function AutoMidHandle( enable )
  798. gc.auto_midhandle=enable
  799. End Function
  800. Rem
  801. bbdoc: Set auto image flags
  802. about:
  803. The auto image flags are used by #LoadImage and #CreateImage when no image
  804. flags are specified. See #LoadImage for a full list of valid image flags.
  805. AutoImageFlags defaults to MASKEDIMAGE | FILTEREDIMAGE.
  806. End Rem
  807. Function AutoImageFlags( flags )
  808. If flags=-1 Return
  809. gc.auto_imageflags=flags
  810. End Function
  811. Rem
  812. bbdoc: Set an image's handle to its center
  813. End Rem
  814. Function MidHandleImage( image:TImage )
  815. image.handle_x=image.width*.5
  816. image.handle_y=image.height*.5
  817. End Function
  818. Rem
  819. bbdoc: Get width of an image
  820. returns: The width, in pixels, of @image
  821. End Rem
  822. Function ImageWidth( image:TImage )
  823. Return image.width
  824. End Function
  825. Rem
  826. bbdoc: Get height of an image
  827. returns: The height, in pixels, of @image
  828. End Rem
  829. Function ImageHeight( image:TImage )
  830. Return image.height
  831. End Function
  832. Rem
  833. bbdoc: Create an empty image
  834. returns: A new image object
  835. about:
  836. #CreateImage creates an 'empty' image, which should be initialized using either #GrabImage or #LockImage
  837. before being drawn.
  838. Please refer to #LoadImage for valid @flags values. The @flags value is always combined with DYNAMICIMAGE.
  839. End Rem
  840. Function CreateImage:TImage( width,height,frames=1,flags=-1 )
  841. If flags=-1 flags=gc.auto_imageflags
  842. Local image:TImage=TImage.Create( width,height,frames,flags|DYNAMICIMAGE,gc.mask_red,gc.mask_green,gc.mask_blue )
  843. If gc.auto_midhandle MidHandleImage image
  844. Return image
  845. End Function
  846. Rem
  847. bbdoc: Lock an image for direct access
  848. returns: A pixmap representing the image contents
  849. about:
  850. Locking an image allows you to directly access an image's pixels.
  851. Only images created with the DYNAMICIMAGE flag can be locked.
  852. Locked images must eventually be unlocked with #UnlockImage before they can be drawn.
  853. End Rem
  854. Function LockImage:TPixmap( image:TImage,frame=0,read_lock=True,write_lock=True )
  855. Return image.Lock( frame,read_lock,write_lock )
  856. End Function
  857. Rem
  858. bbdoc: Unlock an image
  859. about:
  860. Unlocks an image previously locked with #LockImage.
  861. end rem
  862. Function UnlockImage( image:TImage,frame=0 )
  863. End Function
  864. Rem
  865. bbdoc: Grab an image from the back buffer
  866. about:
  867. Copies pixels from the back buffer to an image frame.
  868. Only images created with the DYNAMICIMAGE flag can be grabbed.
  869. End Rem
  870. Function GrabImage( image:TImage,x,y,frame=0 )
  871. Local pixmap:TPixmap=_max2dDriver.GrabPixmap( x,y,image.width,image.height )
  872. If image.flags&MASKEDIMAGE
  873. pixmap=MaskPixmap( pixmap,gc.mask_red,gc.mask_green,gc.mask_blue )
  874. EndIf
  875. image.SetPixmap frame,pixmap
  876. End Function
  877. Rem
  878. bbdoc: Draw pixmap
  879. end rem
  880. Function DrawPixmap( pixmap:TPixmap,x,y )
  881. _max2dDriver.DrawPixmap pixmap,x,y
  882. End Function
  883. Rem
  884. bbdoc: Grab pixmap
  885. end rem
  886. Function GrabPixmap:TPixmap( x,y,width,height )
  887. Return _max2dDriver.GrabPixmap( x,y,width,height )
  888. End Function
  889. Const COLLISION_LAYER_ALL=0
  890. Const COLLISION_LAYER_1=$0001
  891. Const COLLISION_LAYER_2=$0002
  892. Const COLLISION_LAYER_3=$0004
  893. Const COLLISION_LAYER_4=$0008
  894. Const COLLISION_LAYER_5=$0010
  895. Const COLLISION_LAYER_6=$0020
  896. Const COLLISION_LAYER_7=$0040
  897. Const COLLISION_LAYER_8=$0080
  898. Const COLLISION_LAYER_9=$0100
  899. Const COLLISION_LAYER_10=$0200
  900. Const COLLISION_LAYER_11=$0400
  901. Const COLLISION_LAYER_12=$0800
  902. Const COLLISION_LAYER_13=$1000
  903. Const COLLISION_LAYER_14=$2000
  904. Const COLLISION_LAYER_15=$4000
  905. Const COLLISION_LAYER_16=$8000
  906. Const COLLISION_LAYER_17=$00010000
  907. Const COLLISION_LAYER_18=$00020000
  908. Const COLLISION_LAYER_19=$00040000
  909. Const COLLISION_LAYER_20=$00080000
  910. Const COLLISION_LAYER_21=$00100000
  911. Const COLLISION_LAYER_22=$00200000
  912. Const COLLISION_LAYER_23=$00400000
  913. Const COLLISION_LAYER_24=$00800000
  914. Const COLLISION_LAYER_25=$01000000
  915. Const COLLISION_LAYER_26=$02000000
  916. Const COLLISION_LAYER_27=$04000000
  917. Const COLLISION_LAYER_28=$08000000
  918. Const COLLISION_LAYER_29=$10000000
  919. Const COLLISION_LAYER_30=$20000000
  920. Const COLLISION_LAYER_31=$40000000
  921. Const COLLISION_LAYER_32=$80000000
  922. Rem
  923. bbdoc: Tests if two images collide
  924. returns: True if any pixels of the two images specified at the given location overlap.
  925. about:
  926. #ImagesCollide uses the current Rotation and Scale factors from the most previous
  927. call to #SetScale and #SetRotation to calculate at a pixel level if the two images collide.
  928. End Rem
  929. Function ImagesCollide(image1:TImage,x1,y1,frame1,image2:TImage,x2,y2,frame2)
  930. ResetCollisions COLLISION_LAYER_32
  931. CollideImage image1,x1,y1,frame1,0,COLLISION_LAYER_32
  932. If CollideImage(image2,x2,y2,frame2,COLLISION_LAYER_32,0) Return True
  933. End Function
  934. Rem
  935. bbdoc: Tests if two images with arbitrary Rotation and Scales collide
  936. returns: True if any pixels of the two images specified at the given location overlap.
  937. about:
  938. #ImagesCollide2 uses the specified Rotation and Scale paramteters
  939. to calculate at a pixel level if the two images collide (overlap).
  940. End Rem
  941. Function ImagesCollide2(image1:TImage,x1,y1,frame1,rot1#,scalex1#,scaley1#,image2:TImage,x2,y2,frame2,rot2#,scalex2#,scaley2#)
  942. Local _scalex#,_scaley#,_rot#,res
  943. _rot=GetRotation()
  944. GetScale _scalex,_scaley
  945. ResetCollisions COLLISION_LAYER_32
  946. SetRotation rot1
  947. SetScale scalex1,scaley1
  948. CollideImage image1,x1,y1,frame1,0,COLLISION_LAYER_32
  949. SetRotation rot2
  950. SetScale scalex2,scaley2
  951. If CollideImage(image2,x2,y2,frame2,COLLISION_LAYER_32,0) res=True
  952. SetRotation _rot
  953. SetScale _scalex,_scaley
  954. Return res
  955. End Function
  956. Rem
  957. bbdoc: Clears collision layers specified by the value of @mask, mask=0 for all layers.
  958. about:
  959. The BlitzMax 2D collision system manages 32 layers, the @mask parameter can
  960. be a combination of the following values or the special value COLLISION_LAYER_ALL in order
  961. to perform collision operations on multiple layers.
  962. Note: COLLISION_LAYER_32 is used by the #ImagesCollide and #ImagesCollide2 commands.
  963. [ @Layer | @{Mask value}
  964. * COLLISION_LAYER_ALL | 0
  965. * COLLISION_LAYER_1 | $0001
  966. * COLLISION_LAYER_2 | $0002
  967. * COLLISION_LAYER_3 | $0004
  968. * COLLISION_LAYER_4 | $0008
  969. * COLLISION_LAYER_5 | $0010
  970. * COLLISION_LAYER_6 | $0020
  971. * COLLISION_LAYER_7 | $0040
  972. * COLLISION_LAYER_8 | $0080
  973. * COLLISION_LAYER_9 | $0100
  974. * COLLISION_LAYER_10 | $0200
  975. * COLLISION_LAYER_11 | $0400
  976. * COLLISION_LAYER_12 | $0800
  977. * COLLISION_LAYER_13 | $1000
  978. * COLLISION_LAYER_14 | $2000
  979. * COLLISION_LAYER_15 | $4000
  980. * COLLISION_LAYER_16 | $8000
  981. ]
  982. EndRem
  983. Function ResetCollisions(mask%=0)
  984. Local i,q:TQuad
  985. For i=0 To 31
  986. If mask=0 Or mask&(1 Shl i)
  987. q=quadlayer[i]
  988. If q
  989. q.mask=Null
  990. q.id=Null
  991. While q.link
  992. q=q.link
  993. q.mask=Null
  994. q.id=Null
  995. Wend
  996. q.link=freequads
  997. q=quadlayer[i]
  998. freequads=q
  999. quadlayer[i]=Null
  1000. EndIf
  1001. EndIf
  1002. Next
  1003. End Function
  1004. Rem
  1005. bbdoc: Pixel accurate collision testing between transformed Images.
  1006. about:
  1007. The @collidemask specifies any layers to test for collision with.
  1008. The @writemask specifies which if any collision layers the @image is added to in it's currently transformed state.
  1009. The id specifies an object to be returned to future #CollideImage calls when collisions occur.
  1010. EndRem
  1011. Function CollideImage:Object[](image:TImage,x,y,frame,collidemask%,writemask%,id:Object=Null)
  1012. Local q:TQuad
  1013. q=CreateQuad(image,frame,x,y,image.width,image.height,id)
  1014. Return CollideQuad(q,collidemask,writemask)
  1015. End Function
  1016. Rem
  1017. bbdoc: Pixel accurate collision testing between image layers
  1018. about:
  1019. The @collidemask specifies any layers to test for collision with.
  1020. The @writemask specifies which if any collision layers the @image is added to in it's currently transformed state.
  1021. The @id specifies an object to be returned to future #CollideImage calls when collisions occur.
  1022. EndRem
  1023. Function CollideRect:Object[](x,y,w,h,collidemask%,writemask%,id:Object=Null)
  1024. Local q:TQuad
  1025. q=CreateQuad(Null,0,x,y,w,h,id)
  1026. Return CollideQuad(q,collidemask,writemask)
  1027. End Function
  1028. Private
  1029. Global cix#,ciy#,cjx#,cjy#
  1030. Function SetCollisions2DTransform(ix#,iy#,jx#,jy#) 'callback from module Blitz2D
  1031. cix=ix
  1032. ciy=iy
  1033. cjx=jx
  1034. cjy=jy
  1035. End Function
  1036. Global TextureMaps:TPixmap[]
  1037. Global LineBuffer[]
  1038. Global quadlayer:TQuad[32]
  1039. Global freequads:TQuad
  1040. Const POLYX=0
  1041. Const POLYY=1
  1042. Const POLYU=2
  1043. Const POLYV=3
  1044. Function DotProduct(x0#,y0#,x1#,y1#,x2#,y2#)
  1045. Return (((x2-x1)*(y1-y0))-((x1-x0)*(y2-y1)))
  1046. End Function
  1047. Function ClockwisePoly(data#[],channels) 'flips order if anticlockwise
  1048. Local count,clk,i,j
  1049. Local r0,r1,r2
  1050. Local t#
  1051. count=Len(data)/channels
  1052. ' clock wise test
  1053. r0=0
  1054. r1=channels
  1055. clk=2
  1056. For i=2 To count-1
  1057. r2=r1+channels
  1058. If DotProduct(data[r0+POLYX],data[r0+POLYY],data[r1+POLYX],data[r1+POLYY],data[r2+POLYX],data[r2+POLYY])>=0 clk:+1
  1059. r1=r2
  1060. Next
  1061. If clk<count Return
  1062. ' flip order for anticockwise
  1063. r0=0
  1064. r1=(count-1)*channels
  1065. While r0<r1
  1066. For j=0 To channels-1
  1067. t=data[r0+j]
  1068. data[r0+j]=data[r1+j]
  1069. data[r1+j]=t
  1070. Next
  1071. r0:+channels
  1072. r1:-channels
  1073. Wend
  1074. End Function
  1075. Type rpoly
  1076. Field texture:TPixmap
  1077. Field data#[]
  1078. Field channels,count,size
  1079. Field ldat#[],ladd#[]
  1080. Field rdat#[],radd#[]
  1081. Field Left,Right,top
  1082. Field state
  1083. End Type
  1084. Function RenderPolys(vdata#[][],channels[],textures:TPixmap[],renderspans(polys:TList,count,ypos))
  1085. Local polys:rpoly[],p:rpoly,pcount
  1086. Local active:TList
  1087. Local top,bot
  1088. Local n,y,h,i,j,res
  1089. Local data#[]
  1090. bot=$80000000
  1091. top=$7fffffff
  1092. n=Len(vdata)
  1093. ' create polys an array of poly renderers
  1094. polys=New rpoly[n]
  1095. For i=0 Until n
  1096. p=New rpoly
  1097. polys[i]=p
  1098. p.texture=textures[i]
  1099. p.data=vdata[i]
  1100. p.channels=channels[i]
  1101. p.count=Len(p.data)/p.channels
  1102. p.size=p.count*p.channels
  1103. ClockwisePoly(p.data,p.channels) 'flips order if anticlockwise
  1104. ' find top verticies
  1105. p.Left=0
  1106. j=0
  1107. p.top=$7fffffff
  1108. While j<p.size
  1109. y=p.data[j+POLYY] 'float to int conversion
  1110. If y<p.top p.top=y;p.Left=j
  1111. If y<top top=y
  1112. If y>bot bot=y
  1113. j:+p.channels
  1114. Wend
  1115. p.Right=p.Left
  1116. Next
  1117. active=New TList
  1118. pcount=0
  1119. ' draw top to bottom
  1120. For y=top To bot-1
  1121. ' get left gradient
  1122. For p=EachIn polys
  1123. If p.state=2 Continue
  1124. If p.state=0 And y<p.top Continue
  1125. data=p.data
  1126. If y>=Int(data[p.Left+POLYY])
  1127. j=p.Left
  1128. i=(p.Left-p.channels)
  1129. If i<0 i:+p.size
  1130. While i<>p.Left
  1131. If Int(data[i+POLYY])>y Exit
  1132. j=i
  1133. i=(i-p.channels)
  1134. If i<0 i:+p.size
  1135. Wend
  1136. h=Int(data[i+POLYY])-Int(data[j+POLYY])
  1137. If i=p.Left Or h<=0
  1138. active.remove p
  1139. ' p.remove
  1140. pcount:-1
  1141. p.state=2
  1142. Continue
  1143. EndIf
  1144. p.ldat=data[j..j+p.channels]
  1145. p.ladd=data[i..i+p.channels]
  1146. For j=0 To p.channels-1
  1147. p.ladd[j]=(p.ladd[j]-p.ldat[j])/h
  1148. p.ldat[j]:+p.ladd[j]*0.5
  1149. Next
  1150. p.Left=i
  1151. If p.state=0
  1152. p.state=1
  1153. active.AddLast p
  1154. pcount:+1
  1155. EndIf
  1156. EndIf
  1157. ' get right gradient
  1158. If y>=Int(data[p.Right+POLYY])
  1159. i=(p.Right+p.channels) Mod p.size
  1160. j=p.Right
  1161. While i<>p.Right
  1162. If Int(data[i+POLYY])>y Exit
  1163. j=i
  1164. i=(i+p.channels)Mod p.size
  1165. Wend
  1166. h=Int(data[i+POLYY])-Int(data[j+POLYY])
  1167. If i=p.Right Or h<=0
  1168. active.remove p
  1169. pcount:-1
  1170. p.state=2
  1171. Continue
  1172. EndIf
  1173. p.rdat=data[j..j+p.channels]
  1174. p.radd=data[i..i+p.channels]
  1175. For j=0 To p.channels-1
  1176. p.radd[j]=(p.radd[j]-p.rdat[j])/h
  1177. p.rdat[j]:+p.radd[j]*0.5
  1178. Next
  1179. p.Right=i
  1180. If p.state=0
  1181. p.state=1
  1182. active.AddLast p
  1183. pcount:+1
  1184. EndIf
  1185. EndIf
  1186. Next
  1187. ' call renderer
  1188. If pcount
  1189. res=renderspans(active,pcount,y)
  1190. If res<0 Return res
  1191. EndIf
  1192. ' increment spans
  1193. For p=EachIn active
  1194. For j=0 To p.channels-1
  1195. p.ldat[j]:+p.ladd[j]
  1196. p.rdat[j]:+p.radd[j]
  1197. Next
  1198. Next
  1199. Next
  1200. Return res
  1201. End Function
  1202. Function CollideSpans(polys:TList,count,y)
  1203. Local p:rpoly
  1204. Local startx,endx
  1205. Local x0,x1,w,x
  1206. Local u#,v#,ui#,vi#
  1207. Local pix Ptr
  1208. Local src:TPixmap
  1209. Local tw,th,tp,argb
  1210. Local width,skip#
  1211. startx=$7fffffff
  1212. endx=$80000000
  1213. If count<2 Return 0
  1214. p=rpoly(polys.ValueAtIndex(0))
  1215. startx=p.ldat[POLYX]
  1216. endx=p.rdat[POLYX]
  1217. p=rpoly(polys.ValueAtIndex(1))
  1218. x0=p.ldat[POLYX]
  1219. x1=p.rdat[POLYX]
  1220. If x0>=endx Return 0
  1221. If x1<=startx Return 0
  1222. If x0>startx startx=x0
  1223. If x1<endx endx=x1
  1224. width=endx-startx
  1225. If width<=0 Return 0
  1226. If width>Len(LineBuffer) LineBuffer=New Int[width]
  1227. MemClear LineBuffer,width*4
  1228. For p=EachIn polys
  1229. src=p.texture
  1230. If src
  1231. x0=p.ldat[POLYX]
  1232. x1=p.rdat[POLYX]
  1233. w=x1-x0
  1234. If w<=0 Continue
  1235. u=p.ldat[POLYU]
  1236. v=p.ldat[POLYV]
  1237. ui=(p.rdat[POLYU]-u)/w
  1238. vi=(p.rdat[POLYV]-v)/w
  1239. skip=(startx-x0)+0.5
  1240. u=u+ui*skip
  1241. v=v+vi*skip
  1242. pix=Int Ptr(src.pixels)
  1243. tw=src.width
  1244. th=src.height
  1245. tp=src.pitch/4
  1246. For x=0 Until width
  1247. If u<0.0 u=0.0
  1248. If v<0.0 v=0.0
  1249. If u>1.0 u=1.0
  1250. If v>1.0 v=1.0
  1251. ?BigEndian
  1252. argb=$00000080 & pix[(Int(v*th))*tp+(Int(u*tw))]
  1253. ?LittleEndian
  1254. argb=$80000000 & pix[(Int(v*th))*tp+(Int(u*tw))]
  1255. ?
  1256. If (argb)
  1257. If LineBuffer[x] Return -1
  1258. LineBuffer[x]=argb
  1259. EndIf
  1260. u:+ui
  1261. v:+vi
  1262. Next
  1263. Else
  1264. For x=0 Until width
  1265. If LineBuffer[x] Return -1
  1266. LineBuffer[x]=-1
  1267. Next
  1268. EndIf
  1269. Next
  1270. Return 0
  1271. End Function
  1272. Type TQuad
  1273. Field link:TQuad
  1274. Field id:Object
  1275. Field mask:TPixmap
  1276. Field frame
  1277. Field minx#,miny#,maxx#,maxy#
  1278. Field xyuv#[16]
  1279. Method SetCoords(tx0#,ty0#,tx1#,ty1#,tx2#,ty2#,tx3#,ty3#)
  1280. xyuv[0]=tx0
  1281. xyuv[1]=ty0
  1282. xyuv[2]=0.0
  1283. xyuv[3]=0.0
  1284. xyuv[4]=tx1
  1285. xyuv[5]=ty1
  1286. xyuv[6]=1.0
  1287. xyuv[7]=0.0
  1288. xyuv[8]=tx2
  1289. xyuv[9]=ty2
  1290. xyuv[10]=1.0
  1291. xyuv[11]=1.0
  1292. xyuv[12]=tx3
  1293. xyuv[13]=ty3
  1294. xyuv[14]=0.0
  1295. xyuv[15]=1.0
  1296. minx=Min(Min(Min(tx0,tx1),tx2),tx3)
  1297. miny=Min(Min(Min(ty0,ty1),ty2),ty3)
  1298. maxx=Max(Max(Max(tx0,tx1),tx2),tx3)
  1299. maxy=Max(Max(Max(ty0,ty1),ty2),ty3)
  1300. End Method
  1301. End Type
  1302. Function QuadsCollide(p:TQuad,q:TQuad)
  1303. If p.maxx<q.minx Or p.maxy<q.miny Or p.minx>q.maxx Or p.miny>q.maxy Return False
  1304. Local vertlist#[][2]
  1305. Local textures:TPixmap[2]
  1306. Local channels[2]
  1307. vertlist[0]=p.xyuv
  1308. vertlist[1]=q.xyuv
  1309. textures[0]=p.mask
  1310. textures[1]=q.mask
  1311. channels[0]=4
  1312. channels[1]=4
  1313. Return RenderPolys(vertlist,channels,textures,CollideSpans)
  1314. End Function
  1315. Function CreateQuad:TQuad(image:TImage,frame,x#,y#,w#,h#,id:Object)
  1316. Local x0#,y0#,x1#,y1#,tx#,ty#
  1317. Local tx0#,ty0#,tx1#,ty1#,tx2#,ty2#,tx3#,ty3#
  1318. Local minx#,miny#,maxx#,maxy#
  1319. Local q:TQuad
  1320. Local pix:TPixmap
  1321. If image
  1322. x0=-image.handle_x
  1323. y0=-image.handle_y
  1324. EndIf
  1325. x1=x0+w
  1326. y1=y0+h
  1327. tx=x+gc.origin_x
  1328. ty=y+gc.origin_y
  1329. tx0=x0*cix+y0*ciy+tx
  1330. ty0=x0*cjx+y0*cjy+ty
  1331. tx1=x1*cix+y0*ciy+tx
  1332. ty1=x1*cjx+y0*cjy+ty
  1333. tx2=x1*cix+y1*ciy+tx
  1334. ty2=x1*cjx+y1*cjy+ty
  1335. tx3=x0*cix+y1*ciy+tx
  1336. ty3=x0*cjx+y1*cjy+ty
  1337. If freequads
  1338. q=freequads
  1339. freequads=q.link
  1340. q.link=Null
  1341. Else
  1342. q=New TQuad
  1343. EndIf
  1344. q.id=id
  1345. If image
  1346. pix=image.Lock( frame,True,False )
  1347. If AlphaBitsPerPixel[pix.format] q.mask=pix
  1348. EndIf
  1349. q.setcoords(tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3)
  1350. Return q
  1351. End Function
  1352. Function CollideQuad:Object[](pquad:TQuad,collidemask%,writemask%)
  1353. Local result:Object[]
  1354. Local p:TQuad,q:TQuad
  1355. Local i,j,count
  1356. p=pquad 'CreateImageQuad(image,frame,x,y)
  1357. ' check for collisions
  1358. For i=0 To 31
  1359. If collidemask & (1 Shl i)
  1360. q=quadlayer[i]
  1361. While q
  1362. If QuadsCollide(p,q)
  1363. If count=Len(result) result=result[..((count+4)*1.2)]
  1364. result[count]=q.id
  1365. count:+1
  1366. EndIf
  1367. q=q.link
  1368. Wend
  1369. EndIf
  1370. Next
  1371. ' write to layers
  1372. For i=0 To 31
  1373. If writemask & (1 Shl i)
  1374. If freequads
  1375. q=freequads
  1376. freequads=q.link
  1377. Else
  1378. q=New TQuad
  1379. EndIf
  1380. q.id=p.id; 'TODO:optimize with memcpy?
  1381. q.mask=p.mask;
  1382. q.frame=p.frame
  1383. MemCopy q.xyuv,p.xyuv,64
  1384. q.minx=p.minx;q.miny=p.miny;q.maxx=p.maxx;q.maxy=p.maxy;
  1385. q.link=quadlayer[i]
  1386. quadlayer[i]=q
  1387. EndIf
  1388. Next
  1389. ' return result
  1390. If count Return result[..count]
  1391. End Function