max2d.bmx 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566
  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 Int(x/gc.vres_mousexscale),Int(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. Function GetAutoImageFlags:Int()
  812. Return gc.auto_imageflags
  813. End Function
  814. Rem
  815. bbdoc: Set an image's handle to its center
  816. End Rem
  817. Function MidHandleImage( image:TImage )
  818. image.handle_x=image.width*.5
  819. image.handle_y=image.height*.5
  820. End Function
  821. Rem
  822. bbdoc: Get width of an image
  823. returns: The width, in pixels, of @image
  824. End Rem
  825. Function ImageWidth( image:TImage )
  826. Return image.width
  827. End Function
  828. Rem
  829. bbdoc: Get height of an image
  830. returns: The height, in pixels, of @image
  831. End Rem
  832. Function ImageHeight( image:TImage )
  833. Return image.height
  834. End Function
  835. Rem
  836. bbdoc: Create an empty image
  837. returns: A new image object
  838. about:
  839. #CreateImage creates an 'empty' image, which should be initialized using either #GrabImage or #LockImage
  840. before being drawn.
  841. Please refer to #LoadImage for valid @flags values. The @flags value is always combined with DYNAMICIMAGE.
  842. End Rem
  843. Function CreateImage:TImage( width,height,frames=1,flags=-1 )
  844. If flags=-1 flags=gc.auto_imageflags
  845. Local image:TImage=TImage.Create( width,height,frames,flags|DYNAMICIMAGE,gc.mask_red,gc.mask_green,gc.mask_blue )
  846. If gc.auto_midhandle MidHandleImage image
  847. Return image
  848. End Function
  849. Rem
  850. bbdoc: Lock an image for direct access
  851. returns: A pixmap representing the image contents
  852. about:
  853. Locking an image allows you to directly access an image's pixels.
  854. Only images created with the DYNAMICIMAGE flag can be locked.
  855. Locked images must eventually be unlocked with #UnlockImage before they can be drawn.
  856. End Rem
  857. Function LockImage:TPixmap( image:TImage,frame=0,read_lock=True,write_lock=True )
  858. Return image.Lock( frame,read_lock,write_lock )
  859. End Function
  860. Rem
  861. bbdoc: Unlock an image
  862. about:
  863. Unlocks an image previously locked with #LockImage.
  864. end rem
  865. Function UnlockImage( image:TImage,frame=0 )
  866. End Function
  867. Rem
  868. bbdoc: Grab an image from the back buffer
  869. about:
  870. Copies pixels from the back buffer to an image frame.
  871. Only images created with the DYNAMICIMAGE flag can be grabbed.
  872. End Rem
  873. Function GrabImage( image:TImage,x,y,frame=0 )
  874. Local pixmap:TPixmap=_max2dDriver.GrabPixmap( x,y,image.width,image.height )
  875. If image.flags&MASKEDIMAGE
  876. pixmap=MaskPixmap( pixmap,gc.mask_red,gc.mask_green,gc.mask_blue )
  877. EndIf
  878. image.SetPixmap frame,pixmap
  879. End Function
  880. Rem
  881. bbdoc: Draw pixmap
  882. end rem
  883. Function DrawPixmap( pixmap:TPixmap,x,y )
  884. _max2dDriver.DrawPixmap pixmap,x,y
  885. End Function
  886. Rem
  887. bbdoc: Grab pixmap
  888. end rem
  889. Function GrabPixmap:TPixmap( x,y,width,height )
  890. Return _max2dDriver.GrabPixmap( x,y,width,height )
  891. End Function
  892. Const COLLISION_LAYER_ALL=0
  893. Const COLLISION_LAYER_1=$0001
  894. Const COLLISION_LAYER_2=$0002
  895. Const COLLISION_LAYER_3=$0004
  896. Const COLLISION_LAYER_4=$0008
  897. Const COLLISION_LAYER_5=$0010
  898. Const COLLISION_LAYER_6=$0020
  899. Const COLLISION_LAYER_7=$0040
  900. Const COLLISION_LAYER_8=$0080
  901. Const COLLISION_LAYER_9=$0100
  902. Const COLLISION_LAYER_10=$0200
  903. Const COLLISION_LAYER_11=$0400
  904. Const COLLISION_LAYER_12=$0800
  905. Const COLLISION_LAYER_13=$1000
  906. Const COLLISION_LAYER_14=$2000
  907. Const COLLISION_LAYER_15=$4000
  908. Const COLLISION_LAYER_16=$8000
  909. Const COLLISION_LAYER_17=$00010000
  910. Const COLLISION_LAYER_18=$00020000
  911. Const COLLISION_LAYER_19=$00040000
  912. Const COLLISION_LAYER_20=$00080000
  913. Const COLLISION_LAYER_21=$00100000
  914. Const COLLISION_LAYER_22=$00200000
  915. Const COLLISION_LAYER_23=$00400000
  916. Const COLLISION_LAYER_24=$00800000
  917. Const COLLISION_LAYER_25=$01000000
  918. Const COLLISION_LAYER_26=$02000000
  919. Const COLLISION_LAYER_27=$04000000
  920. Const COLLISION_LAYER_28=$08000000
  921. Const COLLISION_LAYER_29=$10000000
  922. Const COLLISION_LAYER_30=$20000000
  923. Const COLLISION_LAYER_31=$40000000
  924. Const COLLISION_LAYER_32=$80000000
  925. Rem
  926. bbdoc: Tests if two images collide
  927. returns: True if any pixels of the two images specified at the given location overlap.
  928. about:
  929. #ImagesCollide uses the current Rotation and Scale factors from the most previous
  930. call to #SetScale and #SetRotation to calculate at a pixel level if the two images collide.
  931. End Rem
  932. Function ImagesCollide(image1:TImage,x1,y1,frame1,image2:TImage,x2,y2,frame2)
  933. ResetCollisions COLLISION_LAYER_32
  934. CollideImage image1,x1,y1,frame1,0,COLLISION_LAYER_32
  935. If CollideImage(image2,x2,y2,frame2,COLLISION_LAYER_32,0) Return True
  936. End Function
  937. Rem
  938. bbdoc: Tests if two images with arbitrary Rotation and Scales collide
  939. returns: True if any pixels of the two images specified at the given location overlap.
  940. about:
  941. #ImagesCollide2 uses the specified Rotation and Scale paramteters
  942. to calculate at a pixel level if the two images collide (overlap).
  943. End Rem
  944. Function ImagesCollide2(image1:TImage,x1,y1,frame1,rot1#,scalex1#,scaley1#,image2:TImage,x2,y2,frame2,rot2#,scalex2#,scaley2#)
  945. Local _scalex#,_scaley#,_rot#,res
  946. _rot=GetRotation()
  947. GetScale _scalex,_scaley
  948. ResetCollisions COLLISION_LAYER_32
  949. SetRotation rot1
  950. SetScale scalex1,scaley1
  951. CollideImage image1,x1,y1,frame1,0,COLLISION_LAYER_32
  952. SetRotation rot2
  953. SetScale scalex2,scaley2
  954. If CollideImage(image2,x2,y2,frame2,COLLISION_LAYER_32,0) res=True
  955. SetRotation _rot
  956. SetScale _scalex,_scaley
  957. Return res
  958. End Function
  959. Rem
  960. bbdoc: Clears collision layers specified by the value of @mask, mask=0 for all layers.
  961. about:
  962. The BlitzMax 2D collision system manages 32 layers, the @mask parameter can
  963. be a combination of the following values or the special value COLLISION_LAYER_ALL in order
  964. to perform collision operations on multiple layers.
  965. Note: COLLISION_LAYER_32 is used by the #ImagesCollide and #ImagesCollide2 commands.
  966. [ @Layer | @{Mask value}
  967. * COLLISION_LAYER_ALL | 0
  968. * COLLISION_LAYER_1 | $0001
  969. * COLLISION_LAYER_2 | $0002
  970. * COLLISION_LAYER_3 | $0004
  971. * COLLISION_LAYER_4 | $0008
  972. * COLLISION_LAYER_5 | $0010
  973. * COLLISION_LAYER_6 | $0020
  974. * COLLISION_LAYER_7 | $0040
  975. * COLLISION_LAYER_8 | $0080
  976. * COLLISION_LAYER_9 | $0100
  977. * COLLISION_LAYER_10 | $0200
  978. * COLLISION_LAYER_11 | $0400
  979. * COLLISION_LAYER_12 | $0800
  980. * COLLISION_LAYER_13 | $1000
  981. * COLLISION_LAYER_14 | $2000
  982. * COLLISION_LAYER_15 | $4000
  983. * COLLISION_LAYER_16 | $8000
  984. ]
  985. EndRem
  986. Function ResetCollisions(mask%=0)
  987. Local i,q:TQuad
  988. For i=0 To 31
  989. If mask=0 Or mask&(1 Shl i)
  990. q=quadlayer[i]
  991. If q
  992. q.mask=Null
  993. q.id=Null
  994. While q.link
  995. q=q.link
  996. q.mask=Null
  997. q.id=Null
  998. Wend
  999. q.link=freequads
  1000. q=quadlayer[i]
  1001. freequads=q
  1002. quadlayer[i]=Null
  1003. EndIf
  1004. EndIf
  1005. Next
  1006. End Function
  1007. Rem
  1008. bbdoc: Pixel accurate collision testing between transformed Images.
  1009. about:
  1010. The @collidemask specifies any layers to test for collision with.
  1011. The @writemask specifies which if any collision layers the @image is added to in it's currently transformed state.
  1012. The id specifies an object to be returned to future #CollideImage calls when collisions occur.
  1013. EndRem
  1014. Function CollideImage:Object[](image:TImage,x,y,frame,collidemask%,writemask%,id:Object=Null)
  1015. Local q:TQuad
  1016. q=CreateQuad(image,frame,x,y,image.width,image.height,id)
  1017. Return CollideQuad(q,collidemask,writemask)
  1018. End Function
  1019. Rem
  1020. bbdoc: Pixel accurate collision testing between image layers
  1021. about:
  1022. The @collidemask specifies any layers to test for collision with.
  1023. The @writemask specifies which if any collision layers the @image is added to in it's currently transformed state.
  1024. The @id specifies an object to be returned to future #CollideImage calls when collisions occur.
  1025. EndRem
  1026. Function CollideRect:Object[](x,y,w,h,collidemask%,writemask%,id:Object=Null)
  1027. Local q:TQuad
  1028. q=CreateQuad(Null,0,x,y,w,h,id)
  1029. Return CollideQuad(q,collidemask,writemask)
  1030. End Function
  1031. Private
  1032. Global cix#,ciy#,cjx#,cjy#
  1033. Function SetCollisions2DTransform(ix#,iy#,jx#,jy#) 'callback from module Blitz2D
  1034. cix=ix
  1035. ciy=iy
  1036. cjx=jx
  1037. cjy=jy
  1038. End Function
  1039. Global TextureMaps:TPixmap[]
  1040. Global LineBuffer[]
  1041. Global quadlayer:TQuad[32]
  1042. Global freequads:TQuad
  1043. Const POLYX=0
  1044. Const POLYY=1
  1045. Const POLYU=2
  1046. Const POLYV=3
  1047. Function DotProduct(x0#,y0#,x1#,y1#,x2#,y2#)
  1048. Return (((x2-x1)*(y1-y0))-((x1-x0)*(y2-y1)))
  1049. End Function
  1050. Function ClockwisePoly(data#[],channels) 'flips order if anticlockwise
  1051. Local count,clk,i,j
  1052. Local r0,r1,r2
  1053. Local t#
  1054. count=Len(data)/channels
  1055. ' clock wise test
  1056. r0=0
  1057. r1=channels
  1058. clk=2
  1059. For i=2 To count-1
  1060. r2=r1+channels
  1061. If DotProduct(data[r0+POLYX],data[r0+POLYY],data[r1+POLYX],data[r1+POLYY],data[r2+POLYX],data[r2+POLYY])>=0 clk:+1
  1062. r1=r2
  1063. Next
  1064. If clk<count Return
  1065. ' flip order for anticockwise
  1066. r0=0
  1067. r1=(count-1)*channels
  1068. While r0<r1
  1069. For j=0 To channels-1
  1070. t=data[r0+j]
  1071. data[r0+j]=data[r1+j]
  1072. data[r1+j]=t
  1073. Next
  1074. r0:+channels
  1075. r1:-channels
  1076. Wend
  1077. End Function
  1078. Type rpoly
  1079. Field texture:TPixmap
  1080. Field data#[]
  1081. Field channels,count,size
  1082. Field ldat#[],ladd#[]
  1083. Field rdat#[],radd#[]
  1084. Field Left,Right,top
  1085. Field state
  1086. End Type
  1087. Function RenderPolys(vdata#[][],channels[],textures:TPixmap[],renderspans(polys:TList,count,ypos))
  1088. Local polys:rpoly[],p:rpoly,pcount
  1089. Local active:TList
  1090. Local top,bot
  1091. Local n,y,h,i,j,res
  1092. Local data#[]
  1093. bot=$80000000
  1094. top=$7fffffff
  1095. n=Len(vdata)
  1096. ' create polys an array of poly renderers
  1097. polys=New rpoly[n]
  1098. For i=0 Until n
  1099. p=New rpoly
  1100. polys[i]=p
  1101. p.texture=textures[i]
  1102. p.data=vdata[i]
  1103. p.channels=channels[i]
  1104. p.count=Len(p.data)/p.channels
  1105. p.size=p.count*p.channels
  1106. ClockwisePoly(p.data,p.channels) 'flips order if anticlockwise
  1107. ' find top verticies
  1108. p.Left=0
  1109. j=0
  1110. p.top=$7fffffff
  1111. While j<p.size
  1112. y=p.data[j+POLYY] 'float to int conversion
  1113. If y<p.top p.top=y;p.Left=j
  1114. If y<top top=y
  1115. If y>bot bot=y
  1116. j:+p.channels
  1117. Wend
  1118. p.Right=p.Left
  1119. Next
  1120. active=New TList
  1121. pcount=0
  1122. ' draw top to bottom
  1123. For y=top To bot-1
  1124. ' get left gradient
  1125. For p=EachIn polys
  1126. If p.state=2 Continue
  1127. If p.state=0 And y<p.top Continue
  1128. data=p.data
  1129. If y>=Int(data[p.Left+POLYY])
  1130. j=p.Left
  1131. i=(p.Left-p.channels)
  1132. If i<0 i:+p.size
  1133. While i<>p.Left
  1134. If Int(data[i+POLYY])>y Exit
  1135. j=i
  1136. i=(i-p.channels)
  1137. If i<0 i:+p.size
  1138. Wend
  1139. h=Int(data[i+POLYY])-Int(data[j+POLYY])
  1140. If i=p.Left Or h<=0
  1141. active.remove p
  1142. ' p.remove
  1143. pcount:-1
  1144. p.state=2
  1145. Continue
  1146. EndIf
  1147. p.ldat=data[j..j+p.channels]
  1148. p.ladd=data[i..i+p.channels]
  1149. For j=0 To p.channels-1
  1150. p.ladd[j]=(p.ladd[j]-p.ldat[j])/h
  1151. p.ldat[j]:+p.ladd[j]*0.5
  1152. Next
  1153. p.Left=i
  1154. If p.state=0
  1155. p.state=1
  1156. active.AddLast p
  1157. pcount:+1
  1158. EndIf
  1159. EndIf
  1160. ' get right gradient
  1161. If y>=Int(data[p.Right+POLYY])
  1162. i=(p.Right+p.channels) Mod p.size
  1163. j=p.Right
  1164. While i<>p.Right
  1165. If Int(data[i+POLYY])>y Exit
  1166. j=i
  1167. i=(i+p.channels)Mod p.size
  1168. Wend
  1169. h=Int(data[i+POLYY])-Int(data[j+POLYY])
  1170. If i=p.Right Or h<=0
  1171. active.remove p
  1172. pcount:-1
  1173. p.state=2
  1174. Continue
  1175. EndIf
  1176. p.rdat=data[j..j+p.channels]
  1177. p.radd=data[i..i+p.channels]
  1178. For j=0 To p.channels-1
  1179. p.radd[j]=(p.radd[j]-p.rdat[j])/h
  1180. p.rdat[j]:+p.radd[j]*0.5
  1181. Next
  1182. p.Right=i
  1183. If p.state=0
  1184. p.state=1
  1185. active.AddLast p
  1186. pcount:+1
  1187. EndIf
  1188. EndIf
  1189. Next
  1190. ' call renderer
  1191. If pcount
  1192. res=renderspans(active,pcount,y)
  1193. If res<0 Return res
  1194. EndIf
  1195. ' increment spans
  1196. For p=EachIn active
  1197. For j=0 To p.channels-1
  1198. p.ldat[j]:+p.ladd[j]
  1199. p.rdat[j]:+p.radd[j]
  1200. Next
  1201. Next
  1202. Next
  1203. Return res
  1204. End Function
  1205. Function CollideSpans(polys:TList,count,y)
  1206. Local p:rpoly
  1207. Local startx,endx
  1208. Local x0,x1,w,x
  1209. Local u#,v#,ui#,vi#
  1210. Local pix Ptr
  1211. Local src:TPixmap
  1212. Local tw,th,tp,argb
  1213. Local width,skip#
  1214. startx=$7fffffff
  1215. endx=$80000000
  1216. If count<2 Return 0
  1217. p=rpoly(polys.ValueAtIndex(0))
  1218. startx=p.ldat[POLYX]
  1219. endx=p.rdat[POLYX]
  1220. p=rpoly(polys.ValueAtIndex(1))
  1221. x0=p.ldat[POLYX]
  1222. x1=p.rdat[POLYX]
  1223. If x0>=endx Return 0
  1224. If x1<=startx Return 0
  1225. If x0>startx startx=x0
  1226. If x1<endx endx=x1
  1227. width=endx-startx
  1228. If width<=0 Return 0
  1229. If width>Len(LineBuffer) LineBuffer=New Int[width]
  1230. MemClear LineBuffer,Size_T(width*4)
  1231. For p=EachIn polys
  1232. src=p.texture
  1233. If src
  1234. x0=p.ldat[POLYX]
  1235. x1=p.rdat[POLYX]
  1236. w=x1-x0
  1237. If w<=0 Continue
  1238. u=p.ldat[POLYU]
  1239. v=p.ldat[POLYV]
  1240. ui=(p.rdat[POLYU]-u)/w
  1241. vi=(p.rdat[POLYV]-v)/w
  1242. skip=(startx-x0)+0.5
  1243. u=u+ui*skip
  1244. v=v+vi*skip
  1245. pix=Int Ptr(src.pixels)
  1246. tw=src.width
  1247. th=src.height
  1248. tp=src.pitch/4
  1249. For x=0 Until width
  1250. If u<0.0 u=0.0
  1251. If v<0.0 v=0.0
  1252. If u>1.0 u=1.0
  1253. If v>1.0 v=1.0
  1254. ?BigEndian
  1255. argb=$00000080 & pix[(Int(v*th))*tp+(Int(u*tw))]
  1256. ?LittleEndian
  1257. argb=$80000000 & pix[(Int(v*th))*tp+(Int(u*tw))]
  1258. ?
  1259. If (argb)
  1260. If LineBuffer[x] Return -1
  1261. LineBuffer[x]=argb
  1262. EndIf
  1263. u:+ui
  1264. v:+vi
  1265. Next
  1266. Else
  1267. For x=0 Until width
  1268. If LineBuffer[x] Return -1
  1269. LineBuffer[x]=-1
  1270. Next
  1271. EndIf
  1272. Next
  1273. Return 0
  1274. End Function
  1275. Type TQuad
  1276. Field link:TQuad
  1277. Field id:Object
  1278. Field mask:TPixmap
  1279. Field frame
  1280. Field minx#,miny#,maxx#,maxy#
  1281. Field xyuv#[16]
  1282. Method SetCoords(tx0#,ty0#,tx1#,ty1#,tx2#,ty2#,tx3#,ty3#)
  1283. xyuv[0]=tx0
  1284. xyuv[1]=ty0
  1285. xyuv[2]=0.0
  1286. xyuv[3]=0.0
  1287. xyuv[4]=tx1
  1288. xyuv[5]=ty1
  1289. xyuv[6]=1.0
  1290. xyuv[7]=0.0
  1291. xyuv[8]=tx2
  1292. xyuv[9]=ty2
  1293. xyuv[10]=1.0
  1294. xyuv[11]=1.0
  1295. xyuv[12]=tx3
  1296. xyuv[13]=ty3
  1297. xyuv[14]=0.0
  1298. xyuv[15]=1.0
  1299. minx=Min(Min(Min(tx0,tx1),tx2),tx3)
  1300. miny=Min(Min(Min(ty0,ty1),ty2),ty3)
  1301. maxx=Max(Max(Max(tx0,tx1),tx2),tx3)
  1302. maxy=Max(Max(Max(ty0,ty1),ty2),ty3)
  1303. End Method
  1304. End Type
  1305. Function QuadsCollide(p:TQuad,q:TQuad)
  1306. If p.maxx<q.minx Or p.maxy<q.miny Or p.minx>q.maxx Or p.miny>q.maxy Return False
  1307. Local vertlist#[][2]
  1308. Local textures:TPixmap[2]
  1309. Local channels[2]
  1310. vertlist[0]=p.xyuv
  1311. vertlist[1]=q.xyuv
  1312. textures[0]=p.mask
  1313. textures[1]=q.mask
  1314. channels[0]=4
  1315. channels[1]=4
  1316. Return RenderPolys(vertlist,channels,textures,CollideSpans)
  1317. End Function
  1318. Function CreateQuad:TQuad(image:TImage,frame,x#,y#,w#,h#,id:Object)
  1319. Local x0#,y0#,x1#,y1#,tx#,ty#
  1320. Local tx0#,ty0#,tx1#,ty1#,tx2#,ty2#,tx3#,ty3#
  1321. Local minx#,miny#,maxx#,maxy#
  1322. Local q:TQuad
  1323. Local pix:TPixmap
  1324. If image
  1325. x0=-image.handle_x
  1326. y0=-image.handle_y
  1327. EndIf
  1328. x1=x0+w
  1329. y1=y0+h
  1330. tx=x+gc.origin_x
  1331. ty=y+gc.origin_y
  1332. tx0=x0*cix+y0*ciy+tx
  1333. ty0=x0*cjx+y0*cjy+ty
  1334. tx1=x1*cix+y0*ciy+tx
  1335. ty1=x1*cjx+y0*cjy+ty
  1336. tx2=x1*cix+y1*ciy+tx
  1337. ty2=x1*cjx+y1*cjy+ty
  1338. tx3=x0*cix+y1*ciy+tx
  1339. ty3=x0*cjx+y1*cjy+ty
  1340. If freequads
  1341. q=freequads
  1342. freequads=q.link
  1343. q.link=Null
  1344. Else
  1345. q=New TQuad
  1346. EndIf
  1347. q.id=id
  1348. If image
  1349. pix=image.Lock( frame,True,False )
  1350. If AlphaBitsPerPixel[pix.format] q.mask=pix
  1351. EndIf
  1352. q.setcoords(tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3)
  1353. Return q
  1354. End Function
  1355. Function CollideQuad:Object[](pquad:TQuad,collidemask%,writemask%)
  1356. Local result:Object[]
  1357. Local p:TQuad,q:TQuad
  1358. Local i,j,count
  1359. p=pquad 'CreateImageQuad(image,frame,x,y)
  1360. ' check for collisions
  1361. For i=0 To 31
  1362. If collidemask & (1 Shl i)
  1363. q=quadlayer[i]
  1364. While q
  1365. If QuadsCollide(p,q)
  1366. If count=Len(result) result=result[..((count+4)*1.2)]
  1367. result[count]=q.id
  1368. count:+1
  1369. EndIf
  1370. q=q.link
  1371. Wend
  1372. EndIf
  1373. Next
  1374. ' write to layers
  1375. For i=0 To 31
  1376. If writemask & (1 Shl i)
  1377. If freequads
  1378. q=freequads
  1379. freequads=q.link
  1380. Else
  1381. q=New TQuad
  1382. EndIf
  1383. q.id=p.id; 'TODO:optimize with memcpy?
  1384. q.mask=p.mask;
  1385. q.frame=p.frame
  1386. MemCopy q.xyuv,p.xyuv,64
  1387. q.minx=p.minx;q.miny=p.miny;q.maxx=p.maxx;q.maxy=p.maxy;
  1388. q.link=quadlayer[i]
  1389. quadlayer[i]=q
  1390. EndIf
  1391. Next
  1392. ' return result
  1393. If count Return result[..count]
  1394. End Function