canvas.monkey2 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945
  1. Namespace mojo.graphics
  2. #rem monkeydoc Outline modes.
  3. Outline modes are used with the [[Canvas.OutlineMode]] property and control the style
  4. of outline drawn.
  5. | OutlineMode | Description
  6. |:--------------|:-----------
  7. | None | Outlines disabled.
  8. | Solid | Solid outlines.
  9. | Smooth | Smooth outlines.
  10. #end
  11. Enum OutlineMode
  12. None=0
  13. Solid=1
  14. Smooth=2
  15. End
  16. #rem monkeydoc The Canvas class.
  17. Canvas objects are used to perform rendering to either a mojo [[View]] or an 'off screen' [[Image]].
  18. To draw to a canvas, use one of the 'Draw' methods. Drawing is affected by a number of draw states, including:
  19. * [[Color]] - the current drawing color. This is combined with the current alpha to produce the final rendering color and alpha values.
  20. * [[Alpha]] - the current drawing alpha level.
  21. * [[Matrix]] - the current drawing matrix. All drawing coordinates are multiplied by this matrix before rendering.
  22. * [[BlendMode]] - the blending mode for drawing, eg: opaque, alpha, additive, multiply.
  23. * [[Viewport]] - the current viewport. All drawing coordinates are relative to the top-left of the viewport.
  24. * [[Scissor]] - the current scissor rect. All rendering is clipped to the union of the viewport and the scissor rect.
  25. * [[Font]] - The current font to use when drawing text with [[DrawText]].
  26. Drawing does not occur immediately. Drawing commands are 'buffered' to reduce the overhead of sending lots of draw calls to the lower level graphics API. You can force all drawing commands in the buffer to actually render using [[Flush]].
  27. #end
  28. Class Canvas
  29. #rem monkeydoc Creates a canvas that renders to an image
  30. #end
  31. Method New( image:Image )
  32. Local rtarget:=New RenderTarget( New Texture[]( image.Texture ),Null )
  33. Init( rtarget,New GraphicsDevice )
  34. BeginRender( New Recti( 0,0,image.Rect.Size ),AffineMat3f.Translation( image.Rect.Origin ) )
  35. End
  36. #rem monkeydoc @hidden Creates a canvas that renders to the backbuffer.
  37. #end
  38. Method New( width:Int,height:Int )
  39. Init( Null,New GraphicsDevice( width,height ) )
  40. End
  41. #rem monkeydoc @hidden Resizes a canvas that renders to the backbuffer.
  42. #end
  43. Method Resize( size:Vec2i )
  44. _device.Resize( size )
  45. End
  46. #rem monkeydoc @hidden
  47. #end
  48. Method BeginRender( bounds:Recti,matrix:AffineMat3f )
  49. Flush()
  50. _rmatrixStack.Push( _rmatrix )
  51. _rboundsStack.Push( _rbounds )
  52. _rmatrix*=matrix
  53. _rbounds&=TransformRecti( bounds,_rmatrix )
  54. Viewport=bounds
  55. Scissor=New Recti( 0,0,bounds.Size )
  56. AmbientLight=Color.Black
  57. BlendMode=BlendMode.Alpha
  58. PointSize=0
  59. LineWidth=0
  60. LineSmoothing=False
  61. TextureFilteringEnabled=true
  62. OutlineMode=OutlineMode.None
  63. OutlineColor=Color.Yellow
  64. OutlineWidth=0
  65. ClearMatrix()
  66. End
  67. #rem monkeydoc @hidden
  68. #end
  69. Method EndRender()
  70. If _lighting EndLighting()
  71. Flush()
  72. _rbounds=_rboundsStack.Pop()
  73. _rmatrix=_rmatrixStack.Pop()
  74. End
  75. #rem monkeydoc The current render target.
  76. #end
  77. Property RenderTarget:RenderTarget()
  78. Return _rtarget
  79. End
  80. #rem monkeydoc The current viewport.
  81. The viewport describes the rect within the render target that rendering occurs in.
  82. All rendering is relative to the top-left of the viewport, and is clipped to the intersection of the viewport and scissor rects.
  83. This property must not be modified if the canvas is in lighting mode.
  84. #end
  85. Property Viewport:Recti()
  86. Return _viewport
  87. Setter( viewport:Recti )
  88. DebugAssert( Not _lighting,"Canvas.Viewport property cannot be modified while lighting" )
  89. If _lighting return
  90. Flush()
  91. _viewport=viewport
  92. _dirty|=Dirty.Viewport|Dirty.Scissor
  93. End
  94. #rem monkeydoc The current scissor rect.
  95. The scissor rect is a rect within the viewport that can be used for additional clipping.
  96. Scissor rect coordinates are relative to the current viewport rect, but are not affected by the current drawing matrix.
  97. This property must not be modified if the canvas is in lighting mode.
  98. #end
  99. Property Scissor:Recti()
  100. Return _scissor
  101. Setter( scissor:Recti )
  102. DebugAssert( Not _lighting,"Canvas.Scissor property cannot be modified while lighting" )
  103. If _lighting return
  104. Flush()
  105. _scissor=scissor
  106. _dirty|=Dirty.Scissor
  107. End
  108. #rem monkeydoc Ambient light color for lighting mode.
  109. Sets the ambient light color for lighting.
  110. This property cannot be modified if the canvas is already in lighting mode.
  111. #end
  112. Property AmbientLight:Color()
  113. Return _ambientLight
  114. Setter( ambient:Color )
  115. DebugAssert( Not _lighting,"Canvas.AmbientLight property cannot be modified while lighting" )
  116. If _lighting return
  117. _ambientLight=ambient
  118. End
  119. #rem monkeydoc The current drawing blend mode.
  120. #end
  121. Property BlendMode:BlendMode()
  122. Return _blendMode
  123. Setter( blendMode:BlendMode )
  124. _blendMode=blendMode
  125. End
  126. #rem monkeydoc TODO! Texture filtering enabled state.
  127. Set to true for normal behavior.
  128. Set to false for a groovy retro effect.
  129. #end
  130. Property TextureFilteringEnabled:Bool()
  131. Return Not _device.RetroMode
  132. Setter( enabled:Bool )
  133. DebugAssert( Not _lighting,"Canvas.TextureFilteringEnabled property cannot be modified while lighting" )
  134. If _lighting Return
  135. Local rmode:=Not enabled
  136. If rmode=_device.RetroMode Return
  137. Flush()
  138. _device.RetroMode=rmode
  139. End
  140. #rem monkeydoc The current point size for use with DrawPoint.
  141. #end
  142. Property PointSize:Float()
  143. Return _pointSize
  144. Setter( pointSize:Float )
  145. _pointSize=pointSize
  146. End
  147. #rem monkeydoc The current line width for use with DrawLine.
  148. #end
  149. Property LineWidth:Float()
  150. Return _lineWidth
  151. Setter( lineWidth:Float )
  152. _lineWidth=lineWidth
  153. End
  154. #rem monkeydoc Smoothing enabled for DrawLine.
  155. #end
  156. Property LineSmoothing:Bool()
  157. Return _lineSmoothing
  158. Setter( smoothing:Bool )
  159. _lineSmoothing=smoothing
  160. End
  161. #rem monkeydoc The current font for use with DrawText.
  162. Set font to null to use the default mojo font.
  163. #end
  164. Property Font:Font()
  165. Return _font
  166. Setter( font:Font )
  167. If Not font font=_defaultFont
  168. _font=font
  169. End
  170. #rem monkeydoc The current drawing alpha level.
  171. Note that [[Alpha]] and the alpha component of [[Color]] are multiplied together to produce the final alpha value for rendering.
  172. This allows you to use [[Alpha]] as a 'master' alpha level.
  173. #end
  174. Property Alpha:Float()
  175. Return _alpha
  176. Setter( alpha:Float )
  177. _alpha=alpha
  178. Local a:=_color.a * _alpha * 255.0
  179. _pmcolor=UInt(a) Shl 24 | UInt(_color.b*a) Shl 16 | UInt(_color.g*a) Shl 8 | UInt(_color.r*a)
  180. End
  181. #rem monkeydoc The current drawing color.
  182. Note that [[Alpha]] and the alpha component of [[Color]] are multiplied together to produce the final alpha value for rendering.
  183. This allows you to use [[Alpha]] as a 'master' alpha level.
  184. #end
  185. Property Color:Color()
  186. Return _color
  187. Setter( color:Color )
  188. _color=color
  189. Local a:=_color.a * _alpha * 255.0
  190. _pmcolor=UInt(a) Shl 24 | UInt(_color.b*a) Shl 16 | UInt(_color.g*a) Shl 8 | UInt(_color.r*a)
  191. End
  192. #rem monkeydoc The current drawing matrix.
  193. All coordinates passed to draw methods are multiplied by this matrix for rendering.
  194. #end
  195. Property Matrix:AffineMat3f()
  196. Return _matrix
  197. Setter( matrix:AffineMat3f )
  198. _matrix=matrix
  199. _tanvec=_matrix.i.Normalize()
  200. End
  201. #rem monkeydoc The current outline mode.
  202. Outline modes control the style of outlines drawn.
  203. See the [[OutlineMode]] enum for a list of possible values.
  204. #end
  205. Property OutlineMode:OutlineMode()
  206. Return _outlineMode
  207. Setter( mode:OutlineMode )
  208. _outlineMode=mode
  209. End
  210. #rem monkeydoc The current outline color.
  211. #end
  212. Property OutlineColor:Color()
  213. Return _outlineColor
  214. Setter( color:Color )
  215. _outlineColor=color
  216. Local a:=_outlineColor.a * 255.0
  217. _outlinepmcolor=UInt(a) Shl 24 | UInt(_outlineColor.b*a) Shl 16 | UInt(_outlineColor.g*a) Shl 8 | UInt(_outlineColor.r*a)
  218. End
  219. #rem monkeydoc The current outline width.
  220. #end
  221. Property OutlineWidth:Float()
  222. Return _outlineWidth
  223. Setter( width:Float )
  224. _outlineWidth=width
  225. End
  226. #rem monkeydoc Pushes the drawing matrix onto the internal matrix stack.
  227. #end
  228. Method PushMatrix()
  229. _matrixStack.Push( _matrix )
  230. End
  231. #rem monkeydoc Pops the drawing matrix off the internal matrix stack.
  232. #end
  233. Method PopMatrix()
  234. _matrix=_matrixStack.Pop()
  235. End
  236. #rem monkeydoc Clears the internal matrix stack and sets the drawing matrix to the identitity matrix.
  237. #end
  238. Method ClearMatrix()
  239. _matrixStack.Clear()
  240. _matrix=New AffineMat3f
  241. End
  242. #rem monkeydoc Translates the drawing matrix.
  243. Translates the drawing matrix. This has the effect of translating all drawing coordinates by `tx` and `ty`.
  244. @param tx X translation.
  245. @param ty Y translation.
  246. @param tv X/Y translation.
  247. #end
  248. Method Translate( tx:Float,ty:Float )
  249. Matrix=Matrix.Translate( tx,ty )
  250. End
  251. Method Translate( tv:Vec2f )
  252. Matrix=Matrix.Translate( tv )
  253. End
  254. #rem monkeydoc Rotates the drawing matrix.
  255. Rotates the drawing matrix. This has the effect of rotating all drawing coordinates by the angle `rz'.
  256. @param rz Rotation angle in radians.
  257. #end
  258. Method Rotate( rz:Float )
  259. Matrix=Matrix.Rotate( rz )
  260. End
  261. #rem monkeydoc Scales the drawing matrix.
  262. Scales the drawing matrix. This has the effect of scaling all drawing coordinates by `sx` and `sy`.
  263. @param sx X scale factor.
  264. @param sy Y scale factor.
  265. @param sv X/Y scale factor.
  266. #end
  267. Method Scale( sx:Float,sy:Float )
  268. Matrix=Matrix.Scale( sx,sy )
  269. End
  270. Method Scale( sv:Vec2f )
  271. Matrix=Matrix.Scale( sv )
  272. End
  273. #rem monkeydoc Draws a point.
  274. Draws a point in the current [[Color]] using the current [[BlendMode]].
  275. The point coordinates are transformed by the current [[Matrix]] and clipped to the current [[Viewport]] and [[Scissor]].
  276. @param x Point x coordinate.
  277. @param y Point y coordinate.
  278. @param v Point coordinates.
  279. #end
  280. Method DrawPoint( x:Float,y:Float )
  281. If _pointSize<=0
  282. AddDrawOp( _shader,_material,_blendMode,1,1 )
  283. AddPointVertex( x,y,0,0 )
  284. Return
  285. Endif
  286. Local d:=_pointSize/2
  287. AddDrawOp( _shader,_material,_blendMode,4,1 )
  288. AddVertex( x-d,y-d,0,0 )
  289. AddVertex( x+d,y-d,1,0 )
  290. AddVertex( x+d,y+d,1,1 )
  291. AddVertex( x-d,y+d,0,1 )
  292. End
  293. Method DrawPoint( v:Vec2f )
  294. DrawPoint( v.x,v.y )
  295. End
  296. Private
  297. Method DrawOutlineLine( x0:Float,y0:Float,x1:Float,y1:Float )
  298. ' x0+=.5;y0+=.5;x1+=.5;y1+=.5
  299. Local blendMode:=_outlineMode=OutlineMode.Smooth ? BlendMode.Alpha Else BlendMode.Opaque
  300. Local pmcolor:=_pmcolor
  301. _pmcolor=_outlinepmcolor
  302. If _outlineWidth<=0
  303. AddDrawOp( _shader,_material,blendMode,2,1 )
  304. AddPointVertex( x0,y0,0,0 )
  305. AddPointVertex( x1,y1,1,1 )
  306. _pmcolor=pmcolor
  307. Return
  308. Endif
  309. Local dx:=y0-y1,dy:=x1-x0
  310. Local sc:=0.5/Sqrt( dx*dx+dy*dy )*_outlineWidth
  311. dx*=sc;dy*=sc
  312. If _outlineMode=OutlineMode.Solid
  313. AddDrawOp( _shader,_material,_blendMode,4,1 )
  314. ' AddPointVertex( x0-dx-dy,y0-dy+dx,0,0 )
  315. ' AddPointVertex( x0+dx-dy,y0+dy+dx,0,0 )
  316. ' AddPointVertex( x1+dx+dy,y1+dy-dx,0,0 )
  317. ' AddPointVertex( x1-dx+dy,y1-dy-dx,0,0 )
  318. AddPointVertex( x0-dx,y0-dy,0,0 )
  319. AddPointVertex( x0+dx,y0+dy,0,0 )
  320. AddPointVertex( x1+dx,y1+dy,0,0 )
  321. AddPointVertex( x1-dx,y1-dy,0,0 )
  322. _pmcolor=pmcolor
  323. Return
  324. End
  325. AddDrawOp( _shader,_material,blendMode,4,2 )
  326. AddPointVertex( x0,y0,0,0 )
  327. AddPointVertex( x1,y1,0,0 )
  328. _pmcolor=0
  329. AddPointVertex( x1-dx,y1-dy,0,0 )
  330. AddPointVertex( x0-dx,y0-dy,0,0 )
  331. AddPointVertex( x0+dx,y0+dy,0,0 )
  332. AddPointVertex( x1+dx,y1+dy,0,0 )
  333. _pmcolor=_outlinepmcolor
  334. AddPointVertex( x1,y1,0,0 )
  335. AddPointVertex( x0,y0,0,0 )
  336. _pmcolor=pmcolor
  337. End
  338. Method DrawOutlineLine( v0:Vec2f,v1:Vec2f )
  339. DrawOutlineLine( v0.x,v0.y,v1.x,v1.y )
  340. End
  341. Method DrawOutline( rect:Rectf )
  342. DrawOutlineLine( rect.min.x,rect.min.y,rect.max.x,rect.min.y )
  343. DrawOutlineLine( rect.max.x,rect.min.y,rect.max.x,rect.max.y )
  344. DrawOutlineLine( rect.max.x,rect.max.y,rect.min.x,rect.max.y )
  345. DrawOutlineLine( rect.min.x,rect.max.y,rect.min.x,rect.min.y )
  346. End
  347. Public
  348. #rem monkeydoc Draws a line.
  349. Draws a line in the current [[Color]] using the current [[BlendMode]].
  350. The line coordinates are transformed by the current [[Matrix]] and clipped to the current [[Viewport]] and [[Scissor]].
  351. @param x0 X coordinate of first endpoint of the line.
  352. @param y0 Y coordinate of first endpoint of the line.
  353. @param x1 X coordinate of first endpoint of the line.
  354. @param y1 Y coordinate of first endpoint of the line.
  355. @param v0 First endpoint of the line.
  356. @param v1 Second endpoint of the line.
  357. #end
  358. Method DrawLine( x0:Float,y0:Float,x1:Float,y1:Float )
  359. If _lineWidth<=0
  360. AddDrawOp( _shader,_material,_blendMode,2,1 )
  361. AddPointVertex( x0,y0,0,0 )
  362. AddPointVertex( x1,y1,1,1 )
  363. Return
  364. Endif
  365. ' x0+=.5;y0+=.5;x1+=.5;y1+=.5
  366. Local dx:=y0-y1,dy:=x1-x0
  367. Local sc:=0.5/Sqrt( dx*dx+dy*dy )*_lineWidth
  368. dx*=sc;dy*=sc
  369. If Not _lineSmoothing
  370. AddDrawOp( _shader,_material,_blendMode,4,1 )
  371. AddPointVertex( x0-dx,y0-dy,0,0 )
  372. AddPointVertex( x0+dx,y0+dy,0,0 )
  373. AddPointVertex( x1+dx,y1+dy,0,0 )
  374. AddPointVertex( x1-dx,y1-dy,0,0 )
  375. Return
  376. End
  377. Local pmcolor:=_pmcolor
  378. AddDrawOp( _shader,_material,_blendMode,4,2 )
  379. AddPointVertex( x0,y0,0,0 )
  380. AddPointVertex( x1,y1,0,0 )
  381. _pmcolor=0
  382. AddPointVertex( x1-dx,y1-dy,0,0 )
  383. AddPointVertex( x0-dx,y0-dy,0,0 )
  384. AddPointVertex( x0+dx,y0+dy,0,0 )
  385. AddPointVertex( x1+dx,y1+dy,0,0 )
  386. _pmcolor=pmcolor
  387. AddPointVertex( x1,y1,0,0 )
  388. AddPointVertex( x0,y0,0,0 )
  389. End
  390. Method DrawLine( v0:Vec2f,v1:Vec2f )
  391. DrawLine( v0.x,v0.y,v1.x,v1.y )
  392. End
  393. #rem monkeydoc Draws a triangle.
  394. Draws a triangle in the current [[Color]] using the current [[BlendMode]].
  395. The triangle vertex coordinates are also transform by the current [[Matrix]].
  396. #End
  397. Method DrawTriangle( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float )
  398. AddDrawOp( _shader,_material,_blendMode,3,1 )
  399. AddVertex( x0,y0,0,0 )
  400. AddVertex( x1,y1,1,0 )
  401. AddVertex( x2,y2,1,1 )
  402. If _outlineMode=OutlineMode.None Return
  403. DrawOutlineLine( x0,y0,x1,y1 )
  404. DrawOutlineLine( x1,y1,x2,y2 )
  405. DrawOutlineLine( x2,y2,x0,y0 )
  406. End
  407. Method DrawTriangle( v0:Vec2f,v1:Vec2f,v2:Vec2f )
  408. DrawTriangle( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y )
  409. End
  410. #rem monkeydoc Draws a quad.
  411. Draws a quad in the current [[Color]] using the current [[BlendMode]].
  412. The quad vertex coordinates are also transform by the current [[Matrix]].
  413. #end
  414. Method DrawQuad( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float,x3:Float,y3:Float )
  415. AddDrawOp( _shader,_material,_blendMode,4,1 )
  416. AddVertex( x0,y0,0,0 )
  417. AddVertex( x1,y1,1,0 )
  418. AddVertex( x2,y2,1,1 )
  419. AddVertex( x3,y3,0,1 )
  420. If _outlineMode=OutlineMode.None Return
  421. DrawOutlineLine( x0,y0,x1,y1 )
  422. DrawOutlineLine( x1,y1,x2,y2 )
  423. DrawOutlineLine( x2,y2,x3,y3 )
  424. DrawOutlineLine( x3,y3,x0,y0 )
  425. End
  426. Method DrawQuad( v0:Vec2f,v1:Vec2f,v2:Vec2f,v3:Vec2f )
  427. DrawQuad( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y,v3.x,v3.y )
  428. End
  429. #rem monkeydoc Draws a rectangle.
  430. Draws a rectangle in the current [[Color]] using the current [[BlendMode]].
  431. The rectangle vertex coordinates are also transform by the current [[Matrix]].
  432. #end
  433. Method DrawRect( x:Float,y:Float,w:Float,h:Float )
  434. DrawQuad( x,y,x+w,y,x+w,y+h,x,y+h )
  435. #rem
  436. Local x0:=x,y0:=y,x1:=x+w,y1:=y+h
  437. AddDrawOp( _shader,_material,_blendMode,4,1 )
  438. AddVertex( x0,y0,0,0 )
  439. AddVertex( x1,y0,1,0 )
  440. AddVertex( x1,y1,1,1 )
  441. AddVertex( x0,y1,0,1 )
  442. #end
  443. End
  444. Method DrawRect( rect:Rectf )
  445. DrawRect( rect.X,rect.Y,rect.Width,rect.Height )
  446. End
  447. Method DrawRect( rect:Rectf,srcImage:Image )
  448. Local tc:=srcImage.TexCoords
  449. AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,4,1 )
  450. AddVertex( rect.min.x,rect.min.y,tc.min.x,tc.min.y )
  451. AddVertex( rect.max.x,rect.min.y,tc.max.x,tc.min.y )
  452. AddVertex( rect.max.x,rect.max.y,tc.max.x,tc.max.y )
  453. AddVertex( rect.min.x,rect.max.y,tc.min.x,tc.max.y )
  454. If _outlineMode=OutlineMode.None Return
  455. DrawOutline( rect )
  456. End
  457. Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image )
  458. DrawRect( New Rectf( x,y,x+width,y+height ),srcImage )
  459. End
  460. Method DrawRect( rect:Rectf,srcImage:Image,srcRect:Recti )
  461. Local s0:=Float(srcImage.Rect.min.x+srcRect.min.x)/srcImage.Texture.Width
  462. Local t0:=Float(srcImage.Rect.min.y+srcRect.min.y)/srcImage.Texture.Height
  463. Local s1:=Float(srcImage.Rect.min.x+srcRect.max.x)/srcImage.Texture.Width
  464. Local t1:=Float(srcImage.Rect.min.y+srcRect.max.y)/srcImage.Texture.Height
  465. AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,4,1 )
  466. AddVertex( rect.min.x,rect.min.y,s0,t0 )
  467. AddVertex( rect.max.x,rect.min.y,s1,t0 )
  468. AddVertex( rect.max.x,rect.max.y,s1,t1 )
  469. AddVertex( rect.min.x,rect.max.y,s0,t1 )
  470. If _outlineMode=OutlineMode.None Return
  471. DrawOutline( rect )
  472. End
  473. Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int )
  474. DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+width,srcY+height ) )
  475. End
  476. Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int,srcWidth:Int,srcHeight:Int )
  477. DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+srcWidth,srcY+srcHeight ) )
  478. End
  479. #rem monkeydoc Draws an oval.
  480. Draws an oval in the current [[Color]] using the current [[BlendMode]].
  481. The oval vertex coordinates are also transform by the current [[Matrix]].
  482. @param x Top left x coordinate for the oval.
  483. @param y Top left y coordinate for the oval.
  484. @param width Width of the oval.
  485. @param height Height of the oval.
  486. #end
  487. Method DrawOval( x:Float,y:Float,width:Float,height:Float )
  488. Local xr:=width/2,yr:=height/2
  489. Local dx_x:=xr*_matrix.i.x
  490. Local dx_y:=xr*_matrix.i.y
  491. Local dy_x:=yr*_matrix.j.x
  492. Local dy_y:=yr*_matrix.j.y
  493. Local dx:=Sqrt( dx_x*dx_x+dx_y*dx_y )
  494. Local dy:=Sqrt( dy_x*dy_x+dy_y*dy_y )
  495. Local n:=Max( Int( dx+dy ),12 ) & ~3
  496. Local x0:=x+xr,y0:=y+yr
  497. AddDrawOp( _shader,_material,_blendMode,n,1 )
  498. For Local i:=0 Until n
  499. Local th:=(i+.5)*Pi*2/n
  500. Local px:=x0+Cos( th ) * xr
  501. Local py:=y0+Sin( th ) * yr
  502. AddPointVertex( px,py,0,0 )
  503. Next
  504. If _outlineMode=OutlineMode.None Return
  505. For Local i:=0 until n
  506. Local th0:=(i+.5)*TwoPi/n
  507. Local px0:=x0+Cos( th0 ) * xr
  508. Local py0:=y0+Sin( th0 ) * yr
  509. Local th1:=(i+1.5)*TwoPi/n
  510. Local px1:=x0+Cos( th1 ) * xr
  511. Local py1:=y0+Sin( th1 ) * yr
  512. DrawOutlineLine( px0,py0,px1,py1 )
  513. Next
  514. End
  515. #rem monkeydoc Draws an ellipse.
  516. Draws an ellipse in the current [[Color]] using the current [[BlendMode]].
  517. The ellipse is also transformed by the current [[Matrix]].
  518. @param x Center x coordinate for the ellipse.
  519. @param y Center y coordinate for the ellipse.
  520. @param xRadius X axis radius for the ellipse.
  521. @param yRadius Y axis radius for the ellipse.
  522. #end
  523. Method DrawEllipse( x:Float,y:Float,xRadius:Float,yRadius:Float )
  524. DrawOval( x-xRadius,y-yRadius,xRadius*2,yRadius*2 )
  525. End
  526. #rem monkeydoc Draws a circle.
  527. Draws a circle in the current [[Color]] using the current [[BlendMode]] and transformed by the current [[Matrix]].
  528. @param x Center x coordinate for the circle.
  529. @param y Center y coordinate for the circle.
  530. @param radius The circle radius.
  531. #end
  532. Method DrawCircle( x:Float,y:Float,radius:Float )
  533. DrawOval( x-radius,y-radius,radius*2,radius*2 )
  534. End
  535. #rem monkeydoc Draws a polygon.
  536. Draws a polygon using the current [[Color]], [[BlendMode]] and [[Matrix]].
  537. The `vertices` array must be at least 2 elements long
  538. @param vertices Array of x/y vertex coordinate pairs.
  539. #end
  540. Method DrawPoly( vertices:Float[] )
  541. Local order:=vertices.Length/2
  542. DebugAssert( order>=1,"Invalid polygon" )
  543. AddDrawOp( _shader,_material,_blendMode,order,1 )
  544. For Local i:=0 Until order*2 Step 2
  545. AddVertex( vertices[i],vertices[i+1],0,0 )
  546. Next
  547. If _outlineMode=OutlineMode.None Or order<3 Return
  548. For Local i:=0 Until order-1
  549. Local k:=i*2
  550. DrawOutlineLine( vertices[k],vertices[k+1],vertices[k+2],vertices[k+3] )
  551. Next
  552. Local kn:=(order-1)*2
  553. DrawOutlineLine( vertices[kn],vertices[kn+1],vertices[0],vertices[1] )
  554. End
  555. #rem monkeydoc Draws a sequence of polygons.
  556. Draws a sequence of polygons using the current [[Color]], [[BlendMode]] and [[Matrix]].
  557. @param order The type of polygon: 3=triangles, 4=quads, >4=n-gons.
  558. @param count The number of polygons.
  559. @param vertices Array of x/y vertex coordinate pairs.
  560. #end
  561. Method DrawPolys( order:Int,count:Int,vertices:Float[] )
  562. DebugAssert( order>=1 And count>0 And order*count<=vertices.Length,"Invalid polyon" )
  563. AddDrawOp( _shader,_material,_blendMode,order,count )
  564. For Local i:=0 Until order*count*2 Step 2
  565. AddVertex( vertices[i],vertices[i+1],0,0 )
  566. Next
  567. If _outlineMode=OutlineMode.None Or order<3 Return
  568. For Local i:=0 Until count
  569. For Local j:=0 Until order-1
  570. Local k:=(i*order+j)*2
  571. DrawOutlineLine( vertices[k],vertices[k+1],vertices[k+2],vertices[k+3] )
  572. Next
  573. Local k0:=i*order*2,kn:=(i*order+order-1)*2
  574. DrawOutlineLine( vertices[kn],vertices[kn+1],vertices[k0],vertices[k0+1] )
  575. Next
  576. End
  577. #rem monkeydoc Draws a sequence of primtives.
  578. Draws a sequence of convex primtives using the current [[Color]], [[BlendMode]] and [[Matrix]].
  579. @param order The type of primitive: 1=points, 2=lines, 3=triangles, 4=quads, >4=n-gons.
  580. @param count The number of primitives to draw.
  581. @param vertices Pointer to the first vertex x,y pair.
  582. @param verticesPitch Number of bytes from one vertex x,y pair to the next. Set to 8 for 'tightly packed' vertices.
  583. @param texCoords Pointer to the first texCoord s,t pair. This can be null.
  584. @param texCoordsPitch Number of bytes from one texCoord s,y to the next. Set to 8 for 'tightly packed' texCoords.
  585. @param colors Pointer to the first RGBA uint color value. This can be null.
  586. @param colorsPitch Number of bytes from one RGBA color to the next. Set to 4 for 'tightly packed' colors.
  587. @param image Source image for rendering. This can be null.
  588. @param indices Pointer to sequence of integer indices for indexed drawing. This can by null for non-indexed drawing.
  589. #end
  590. Method DrawPrimitives( order:Int,count:Int,vertices:Float Ptr,verticesPitch:Int,texCoords:Float Ptr,texCoordsPitch:Int,colors:UInt Ptr,colorsPitch:Int,image:Image,indices:Int Ptr )
  591. DebugAssert( order>0 And count>0,"Illegal primitive" )
  592. If image
  593. AddDrawOp( image.Shader,image.Material,image.BlendMode,order,count )
  594. Else
  595. AddDrawOp( _shader,_material,_blendMode,order,count )
  596. Endif
  597. Local n:=order*count
  598. If indices
  599. If texCoords And colors
  600. For Local i:=0 Until n
  601. Local j:=indices[i]
  602. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  603. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+j*texCoordsPitch )
  604. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( colors )+j*colorsPitch )
  605. AddVertex( vp[0],vp[1],tp[0],tp[1],cp[0] )
  606. Next
  607. Else If texCoords
  608. For Local i:=0 Until n
  609. Local j:=indices[i]
  610. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  611. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+j*texCoordsPitch )
  612. AddVertex( vp[0],vp[1],tp[0],tp[1] )
  613. Next
  614. Else If colors
  615. For Local i:=0 Until n
  616. Local j:=indices[i]
  617. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  618. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( colors )+j*colorsPitch )
  619. AddVertex( vp[0],vp[1],0,0,cp[0] )
  620. Next
  621. Else
  622. For Local i:=0 Until n
  623. Local j:=indices[i]
  624. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  625. AddVertex( vp[0],vp[1],0,0 )
  626. Next
  627. Endif
  628. Else
  629. If texCoords And colors
  630. For Local i:=0 Until n
  631. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  632. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+i*texCoordsPitch )
  633. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( colors )+i*colorsPitch )
  634. AddVertex( vp[0],vp[1],tp[0],tp[1],cp[0] )
  635. Next
  636. Else If texCoords
  637. For Local i:=0 Until n
  638. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  639. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+i*texCoordsPitch )
  640. AddVertex( vp[0],vp[1],tp[0],tp[1] )
  641. Next
  642. Else If colors
  643. For Local i:=0 Until n
  644. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  645. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( colors )+i*colorsPitch )
  646. AddVertex( vp[0],vp[1],0,0,cp[0] )
  647. Next
  648. Else
  649. For Local i:=0 Until n
  650. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  651. AddVertex( vp[0],vp[1],0,0 )
  652. Next
  653. Endif
  654. Endif
  655. End
  656. #rem monkeydoc Draws an image.
  657. Draws an image using the current [[Color]], [[BlendMode]] and [[Matrix]].
  658. @param tx X coordinate to draw image at.
  659. @param ty Y coordinate to draw image at.
  660. @param tv X/Y coordinates to draw image at.
  661. @param rz Rotation angle, in radians, for drawing.
  662. @param sx X axis scale factor for drawing.
  663. @param sy Y axis scale factor for drawing.
  664. @param sv X/Y scale factor for drawing.
  665. #end
  666. Method DrawImage( image:Image,tx:Float,ty:Float )
  667. Local vs:=image.Vertices
  668. Local ts:=image.TexCoords
  669. AddDrawOp( image.Shader,image.Material,image.BlendMode,4,1 )
  670. AddVertex( vs.min.x+tx,vs.min.y+ty,ts.min.x,ts.min.y )
  671. AddVertex( vs.max.x+tx,vs.min.y+ty,ts.max.x,ts.min.y )
  672. AddVertex( vs.max.x+tx,vs.max.y+ty,ts.max.x,ts.max.y )
  673. AddVertex( vs.min.x+tx,vs.max.y+ty,ts.min.x,ts.max.y )
  674. If _lighting And image.ShadowCaster
  675. AddShadowCaster( image.ShadowCaster,tx,ty )
  676. Endif
  677. End
  678. Method DrawImage( image:Image,tx:Float,ty:Float,rz:Float )
  679. Local matrix:=Matrix
  680. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  681. DrawImage( image,0,0 )
  682. Matrix=matrix
  683. End
  684. Method DrawImage( image:Image,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  685. Local matrix:=Matrix
  686. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  687. DrawImage( image,0,0 )
  688. Matrix=matrix
  689. End
  690. Method DrawImage( image:Image,tv:Vec2f )
  691. DrawImage( image,tv.x,tv.y )
  692. End
  693. Method DrawImage( image:Image,tv:Vec2f,rz:Float )
  694. DrawImage( image,tv.x,tv.y,rz )
  695. End
  696. Method DrawImage( image:Image,tv:Vec2f,rz:Float,sv:Vec2f )
  697. DrawImage( image,tv.x,tv.y,rz,sv.x,sv.y )
  698. End
  699. #rem monkeydoc Draws text.
  700. Draws text using the current [[Color]], [[BlendMode]] and [[Matrix]].
  701. @param text The text to draw.
  702. @param tx X coordinate to draw text at.
  703. @param ty Y coordinate to draw text at.
  704. @param handleX X handle for drawing.
  705. @param handleY Y handle for drawing.
  706. #end
  707. Method DrawText( text:String,tx:Float,ty:Float,handleX:Float=0,handleY:Float=0 )
  708. If Not text.Length Return
  709. tx-=_font.TextWidth( text ) * handleX
  710. ty-=_font.Height * handleY
  711. Local gpage:=_font.GetGlyphPage( text[0] )
  712. If Not gpage gpage=_font.GetGlyphPage( 0 )
  713. Local sx:Float,sy:Float
  714. Local tw:Float,th:Float
  715. Local i0:=0,lastChar:=0
  716. while i0<text.Length
  717. Local i1:=i0+1
  718. Local page:Image
  719. While i1<text.Length
  720. page=_font.GetGlyphPage( text[i1] )
  721. If page And page<>gpage Exit
  722. i1+=1
  723. Wend
  724. Local image:=gpage
  725. sx=image.Rect.min.x;sy=image.Rect.min.y
  726. tw=image.Texture.Width;th=image.Texture.Height
  727. AddDrawOp( image.Shader,image.Material,image.BlendMode,4,i1-i0 )
  728. For Local i:=i0 Until i1
  729. Local char:=text[i]
  730. tx+=_font.GetKerning( lastChar,char ) 'add kerning before render
  731. Local g:=_font.GetGlyph( char )
  732. Local s0:=Float(g.rect.min.x+sx)/tw
  733. Local t0:=Float(g.rect.min.y+sy)/th
  734. Local s1:=Float(g.rect.max.x+sx)/tw
  735. Local t1:=Float(g.rect.max.y+sy)/th
  736. Local x0:=Round( tx+g.offset.x )
  737. Local y0:=Round( ty+g.offset.y )
  738. Local x1:=x0+g.rect.Width
  739. Local y1:=y0+g.rect.Height
  740. AddVertex( x0,y0,s0,t0 )
  741. AddVertex( x1,y0,s1,t0 )
  742. AddVertex( x1,y1,s1,t1 )
  743. AddVertex( x0,y1,s0,t1 )
  744. tx+=g.advance 'add advance after render
  745. lastChar=char
  746. Next
  747. gpage=page
  748. i0=i1
  749. Wend
  750. End
  751. #rem monkeydoc Adds a light to the canvas.
  752. This method must only be called while the canvas is in lighting mode, ie: between calls to [[BeginLighting]] and [[EndLighting]].
  753. #end
  754. Method AddLight( light:Image,tx:Float,ty:Float )
  755. DebugAssert( _lighting,"Canvas.AddLight() can only be used while lighting" )
  756. If Not _lighting Return
  757. If _lightNV+4>_lightVB.Length Return
  758. Local lx:=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  759. Local ly:=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  760. Local op:=New LightOp
  761. op.light=light
  762. op.lightPos=New Vec2f( lx,ly )
  763. op.primOffset=_lightNV
  764. _lightOps.Push( op )
  765. _vp=_lightVP0+_lightNV
  766. _lightNV+=4
  767. Local vs:=light.Vertices
  768. Local ts:=light.TexCoords
  769. AddVertex( vs.min.x+tx,vs.min.y+ty,ts.min.x,ts.min.y,lx,ly,_pmcolor )
  770. AddVertex( vs.max.x+tx,vs.min.y+ty,ts.max.x,ts.min.y,lx,ly,_pmcolor )
  771. AddVertex( vs.max.x+tx,vs.max.y+ty,ts.max.x,ts.max.y,lx,ly,_pmcolor )
  772. AddVertex( vs.min.x+tx,vs.max.y+ty,ts.min.x,ts.max.y,lx,ly,_pmcolor )
  773. End
  774. Method AddLight( light:Image,tx:Float,ty:Float,rz:Float )
  775. Local matrix:=Matrix
  776. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  777. AddLight( light,0,0 )
  778. Matrix=matrix
  779. End
  780. Method AddLight( light:Image,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  781. Local matrix:=Matrix
  782. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  783. AddLight( light,0,0 )
  784. Matrix=matrix
  785. End
  786. Method AddLight( light:Image,tv:Vec2f )
  787. AddLight( light,tv.x,tv.y )
  788. End
  789. Method AddLight( light:Image,tv:Vec2f,rz:Float )
  790. AddLight( light,tv.x,tv.y,rz )
  791. End
  792. Method AddLight( light:Image,tv:Vec2f,rz:Float,sv:Vec2f )
  793. AddLight( light,tv.x,tv.y,rz,sv.x,sv.y )
  794. End
  795. #rem monkeydoc Adds a shadow caster to the canvas.
  796. This method must only be called while the canvas is in lighting mode, ie: between calls to [[BeginLighting]] and [[EndLighting]].
  797. #end
  798. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float )
  799. DebugAssert( _lighting,"Canvas.AddShadowCaster() can only be used while lighting" )
  800. If Not _lighting Return
  801. Local op:=New ShadowOp
  802. op.caster=caster
  803. op.firstVert=_shadowVerts.Length
  804. _shadowOps.Push( op )
  805. Local tv:=New Vec2f( tx,ty )
  806. For Local sv:=Eachin caster.Vertices
  807. sv+=tv
  808. Local lv:=New Vec2f(
  809. _matrix.i.x * sv.x + _matrix.j.x * sv.y + _matrix.t.x,
  810. _matrix.i.y * sv.x + _matrix.j.y * sv.y + _matrix.t.y )
  811. _shadowVerts.Push( lv )
  812. Next
  813. End
  814. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float,rz:float )
  815. Local matrix:=Matrix
  816. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  817. AddShadowCaster( caster,0,0 )
  818. Matrix=matrix
  819. End
  820. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  821. Local matrix:=Matrix
  822. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  823. AddShadowCaster( caster,0,0 )
  824. Matrix=matrix
  825. End
  826. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f )
  827. AddShadowCaster( caster,tv.x,tv.y )
  828. End
  829. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f,rz:Float )
  830. AddShadowCaster( caster,tv.x,tv.y,rz )
  831. End
  832. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f,rz:Float,sv:Vec2f )
  833. AddShadowCaster( caster,tv.x,tv.y,rz,sv.x,sv.y )
  834. End
  835. #rem monkeydoc Copies a pixmap from the rendertarget.
  836. This method must not be called while the canvas is in lighting mode.
  837. @param rect The rect to copy.
  838. #end
  839. Method CopyPixmap:Pixmap( rect:Recti )
  840. DebugAssert( Not _lighting,"Canvas.CopyPixmap() cannot be used while lighting" )
  841. If _lighting Return Null
  842. Local pixmap:=New Pixmap( rect.Width,rect.Height,PixelFormat.RGBA32 )
  843. CopyPixels( rect,pixmap )
  844. Return pixmap
  845. End
  846. #rem monkeydoc Copies a rectangular region of pixels to a pixmap.
  847. #end
  848. Method CopyPixels( rect:Recti,pixmap:Pixmap,dstx:Int=0,dsty:Int=0 )
  849. DebugAssert( Not _lighting,"Canvas.CopyPixels() cannot be used while lighting" )
  850. If _lighting Return
  851. Flush()
  852. rect=TransformRecti( rect,_rmatrix ) & _rbounds
  853. _device.CopyPixels( rect,pixmap,dstx,dsty )
  854. End
  855. #rem monkeydoc Gets a pixel color.
  856. Returns the color of the pixel at the given coordinates.
  857. #end
  858. Method GetPixel:Color( x:Int,y:Int )
  859. Flush()
  860. CopyPixels( New Recti( x,y,x+1,y+1 ),_tmpPixmap1x1 )
  861. Return _tmpPixmap1x1.GetPixel( 0,0 )
  862. End
  863. #rem monkeydoc Gets a pixel color.
  864. Returns the ARGB color of the pixel at the given coordinates.
  865. #end
  866. Method GetPixelARGB:UInt( x:Int,y:Int )
  867. Flush()
  868. CopyPixels( New Recti( x,y,x+1,y+1 ),_tmpPixmap1x1 )
  869. Return _tmpPixmap1x1.GetPixelARGB( 0,0 )
  870. End
  871. #rem monkeydoc Clears the viewport.
  872. Clears the current viewport to `color`.
  873. This method must not be called while the canvas is in lighting mode.
  874. @param color Color to clear the viewport to.
  875. #end
  876. Method Clear( color:Color )
  877. DebugAssert( Not _lighting,"Canvas.Clear() cannot be used while lighting" )
  878. If _lighting Return
  879. Validate()
  880. _device.Clear( color )
  881. _drawNV=0
  882. _drawOps.Clear()
  883. _drawOp=New DrawOp
  884. End
  885. #rem monkeydoc Flushes drawing commands.
  886. Flushes any outstanding drawing commands in the draw buffer.
  887. This is only generally necessary if you are drawing to an image.
  888. #end
  889. Method Flush()
  890. If _drawOps.Empty
  891. _device.FlushTarget()
  892. Return
  893. Endif
  894. Validate()
  895. _drawVB.Invalidate( 0,_drawNV )
  896. _drawVB.Unlock()
  897. 'Render ambient
  898. '
  899. RenderDrawOps( 0 )
  900. If _lighting
  901. 'render diffuse gbuffer
  902. '
  903. _device.RenderTarget=_gbrtargets[0]
  904. RenderDrawOps( 1 )
  905. 'render normal gbuffer
  906. '
  907. _device.RenderTarget=_gbrtargets[1]
  908. RenderDrawOps( 2 )
  909. 'back to rendertarget
  910. '
  911. _device.RenderTarget=_rtarget
  912. Endif
  913. _device.FlushTarget()
  914. _drawVP0=Cast<Vertex2f Ptr>( _drawVB.Lock() )
  915. _drawNV=0
  916. _drawOps.Clear()
  917. _drawOp=New DrawOp
  918. End
  919. #rem monkeydoc True if canvas is in lighting mode.
  920. #end
  921. Property IsLighting:Bool()
  922. Return _lighting
  923. End
  924. #rem monkeydoc Puts the canvas into lighting mode.
  925. While in lighting mode, you can add lights and shadow casters to the cavas using [[AddLight]] and [[AddShadowCaster]]. Lights and shadows
  926. are later rendered by calling [[EndLighting]].
  927. Each call to BeginLighting must be matched with a corresponding call to EndLighting.
  928. The following properties must not be modified while in lighting mode: [[Viewport]], [[Scissor]], [[AmbientLight]]. Attempting to
  929. modify these properties while in lighting mode will result in a runtime error in debug builds.
  930. The following methods must not be called in lighting mode: [[Clear]], [[BeginLighting]]. Attepting to call these methods while in
  931. lighting mode will result in a runtime error in debug builds.
  932. #end
  933. Method BeginLighting()
  934. DebugAssert( Not _lighting,"Already lighting" )
  935. If _lighting Return
  936. _lighting=True
  937. Local gbufferSize:=_device.RenderTargetSize
  938. gbufferSize.x=Max( gbufferSize.x,1920 )
  939. gbufferSize.y=Max( gbufferSize.y,1080 )
  940. If Not _gbuffers[0] Or gbufferSize.x>_gbuffers[0].Width Or gbufferSize.y>_gbuffers[0].Height
  941. For Local i:=0 Until 2
  942. If _gbuffers[i] _gbuffers[i].Discard()
  943. If _gbrtargets[i] _gbrtargets[i].Discard()
  944. _gbuffers[i]=New Texture( gbufferSize.x,gbufferSize.y,PixelFormat.RGBA32,TextureFlags.Dynamic )
  945. _gbrtargets[i]=New RenderTarget( New Texture[]( _gbuffers[i] ),Null )
  946. Next
  947. Local gbufferScale:=New Vec2f( 1 )/Cast<Vec2f>( gbufferSize )
  948. _uniforms.SetVec2f( "GBufferScale",gbufferScale )
  949. _uniforms.SetTexture( "GBuffer0",_gbuffers[0] )
  950. _uniforms.SetTexture( "GBuffer1",_gbuffers[1] )
  951. Endif
  952. Validate()
  953. _uniforms.SetVec4f( "AmbientLight",_ambientLight )
  954. _device.RenderTarget=_gbrtargets[0]
  955. _device.Clear( Color.Black )
  956. _device.RenderTarget=_gbrtargets[1]
  957. _device.Clear( New Color( .5,.5,0 ) )
  958. _device.RenderTarget=_rtarget
  959. End
  960. #rem monkeydoc Renders lighting and ends lighting mode.
  961. Renders any lights and shadows casters added to the canvas through calls to [[AddLight]] and [[AddShadowCaster]] and ends lighting mode.
  962. Any lights and shadow casters added to the canvas are also removed and must be added again later if you want to render them again.
  963. This method must be called while the canvas is in lighting mode.
  964. #end
  965. Method EndLighting()
  966. DebugAssert( _lighting,"Not lighting" )
  967. If Not _lighting Return
  968. Flush()
  969. _lightVB.Invalidate( 0,_lightNV )
  970. _lightVB.Unlock()
  971. RenderLighting()
  972. _lightVP0=Cast<Vertex2f Ptr>( _lightVB.Lock() )
  973. _lightNV=0
  974. _lightOps.Clear()
  975. _shadowOps.Clear()
  976. _shadowVerts.Clear()
  977. _lighting=False
  978. End
  979. '***** INTERNAL *****
  980. #rem monkeydoc @hidden
  981. #end
  982. Property GraphicsDevice:GraphicsDevice()
  983. If _lighting Return Null
  984. Flush()
  985. Return _device
  986. End
  987. #rem monkeydoc @hidden
  988. #end
  989. Property RenderMatrix:AffineMat3f()
  990. Return _rmatrix
  991. End
  992. #rem monkeydoc @hidden
  993. #end
  994. Property RenderBounds:Recti()
  995. Return _rbounds
  996. End
  997. Private
  998. Enum Dirty
  999. GBuffer=1
  1000. Viewport=2
  1001. Scissor=4
  1002. End
  1003. Class DrawOp
  1004. Field shader:Shader
  1005. Field material:UniformBlock
  1006. Field blendMode:BlendMode
  1007. Field primOrder:Int
  1008. Field primCount:Int
  1009. Field primOffset:Int
  1010. End
  1011. Class LightOp
  1012. Field light:Image
  1013. Field lightPos:Vec2f
  1014. Field primOrder:Int
  1015. Field primOffset:Int
  1016. End
  1017. Class ShadowOp
  1018. Field caster:ShadowCaster
  1019. Field firstVert:Int
  1020. End
  1021. Global _tmpPixmap1x1:Pixmap
  1022. Global _quadIndices:IndexBuffer
  1023. Global _shadowVB:VertexBuffer
  1024. Global _defaultFont:Font
  1025. Global _lighting:Bool=False
  1026. Global _gbuffers:=New Texture[2]
  1027. Global _gbrtargets:=New RenderTarget[2]
  1028. Field _rtarget:RenderTarget
  1029. Field _device:GraphicsDevice
  1030. Field _uniforms:UniformBlock
  1031. Field _shader:Shader
  1032. Field _material:UniformBlock
  1033. Field _viewport:Recti
  1034. Field _scissor:Recti
  1035. Field _ambientLight:Color
  1036. Field _retroMode:Bool
  1037. Field _blendMode:BlendMode
  1038. Field _font:Font
  1039. Field _alpha:Float
  1040. Field _color:Color
  1041. Field _pmcolor:UInt=~0
  1042. Field _pointSize:Float=1
  1043. Field _lineWidth:Float=1
  1044. Field _lineSmoothing:Bool
  1045. Field _matrix:=New AffineMat3f
  1046. Field _tanvec:Vec2f=New Vec2f( 1,0 )
  1047. Field _matrixStack:=New Stack<AffineMat3f>
  1048. Field _outlineMode:OutlineMode
  1049. Field _outlineColor:Color
  1050. Field _outlinepmcolor:UInt
  1051. Field _outlineSmoothing:Bool
  1052. Field _outlineWidth:Float
  1053. Field _rmatrix:=New AffineMat3f
  1054. Field _rbounds:=New Recti( 0,0,$40000000,$40000000 )
  1055. Field _rmatrixStack:=New Stack<AffineMat3f>
  1056. Field _rboundsStack:=New Stack<Recti>
  1057. Field _dirty:Dirty
  1058. Field _projMatrix:Mat4f
  1059. Field _rviewport:Recti
  1060. Field _rviewportClip:Vec2i
  1061. Field _rscissor:Recti
  1062. Field _vp:Vertex2f Ptr
  1063. Field _drawVB:VertexBuffer
  1064. Field _drawVP0:Vertex2f Ptr
  1065. Field _drawNV:Int
  1066. Field _drawOps:=New Stack<DrawOp>
  1067. Field _drawOp:=New DrawOp
  1068. Field _lightVB:VertexBuffer
  1069. Field _lightVP0:Vertex2f Ptr
  1070. Field _lightNV:Int
  1071. Field _lightOps:=New Stack<LightOp>
  1072. Field _shadowOps:=New Stack<ShadowOp>
  1073. Field _shadowVerts:=New Stack<Vec2f>
  1074. Const MaxVertices:=65536
  1075. Const MaxShadowVertices:=16384
  1076. Const MaxLights:=1024
  1077. Function Init2()
  1078. Global inited:=False
  1079. If inited Return
  1080. inited=True
  1081. _tmpPixmap1x1=New Pixmap( 1,1,PixelFormat.RGBA8 )
  1082. Local nquads:=MaxVertices/4
  1083. _quadIndices=New IndexBuffer( IndexFormat.UINT16,nquads*6 )
  1084. Local ip:=Cast<UShort Ptr>( _quadIndices.Lock() )
  1085. For Local i:=0 Until nquads*4 Step 4
  1086. ip[0]=i
  1087. ip[1]=i+1
  1088. ip[2]=i+2
  1089. ip[3]=i
  1090. ip[4]=i+2
  1091. ip[5]=i+3
  1092. ip+=6
  1093. Next
  1094. _quadIndices.Invalidate( 0,nquads*6 )
  1095. _quadIndices.Unlock()
  1096. _shadowVB=New VertexBuffer( Vertex2f.Format,MaxShadowVertices )
  1097. _defaultFont=mojo.graphics.Font.Load( "font::DejaVuSans.ttf",16 )
  1098. End
  1099. Method Init( rtarget:RenderTarget,device:GraphicsDevice )
  1100. Init2()
  1101. _rtarget=rtarget
  1102. _device=device
  1103. _device.RenderTarget=_rtarget
  1104. _device.CullMode=CullMode.None
  1105. _device.DepthFunc=DepthFunc.Always
  1106. _device.DepthMask=False
  1107. _uniforms=New UniformBlock( 1 )
  1108. _device.BindUniformBlock( _uniforms )
  1109. _drawVB=New VertexBuffer( Vertex2f.Format,MaxVertices )
  1110. _drawVP0=Cast<Vertex2f Ptr>( _drawVB.Lock() )
  1111. _drawNV=0
  1112. _lightVB=New VertexBuffer( Vertex2f.Format,MaxLights*4 )
  1113. _lightVP0=Cast<Vertex2f Ptr>( _lightVB.Lock() )
  1114. _lightNV=0
  1115. ' _shadowVB=New VertexBuffer( Vertex2f.Format,65536 )
  1116. _device.IndexBuffer=_quadIndices
  1117. _shader=Shader.GetShader( "null" )
  1118. _material=New UniformBlock( 2 )
  1119. _viewport=New Recti( 0,0,640,480 )
  1120. _ambientLight=Color.Black
  1121. _blendMode=BlendMode.Alpha
  1122. _font=_defaultFont
  1123. _alpha=1
  1124. _color=Color.White
  1125. _pmcolor=$ffffffff
  1126. _outlineMode=OutlineMode.None
  1127. _outlineColor=Color.Yellow
  1128. _outlinepmcolor=$ffffffff
  1129. _outlineWidth=0
  1130. _matrix=New AffineMat3f
  1131. End
  1132. 'Vertices
  1133. '
  1134. #rem
  1135. Method AddVertex( x:Float,y:Float,s0:Float,t0:Float,s1:Float,t1:Float,color:UInt )
  1136. _vp->position.x=x
  1137. _vp->position.y=y
  1138. _vp->texCoord0.x=s0
  1139. _vp->texCoord0.y=t0
  1140. _vp->texCoord1.x=s1
  1141. _vp->texCoord1.y=t1
  1142. _vp->color=color
  1143. _vp+=1
  1144. End
  1145. #end
  1146. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float,s1:Float,t1:Float,color:UInt )
  1147. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  1148. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  1149. _vp->texCoord0.x=s0
  1150. _vp->texCoord0.y=t0
  1151. _vp->texCoord1.x=s1
  1152. _vp->texCoord1.y=t1
  1153. _vp->color=color
  1154. _vp+=1
  1155. End
  1156. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float,color:UInt )
  1157. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  1158. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  1159. _vp->texCoord0.x=s0
  1160. _vp->texCoord0.y=t0
  1161. _vp->texCoord1.x=_tanvec.x
  1162. _vp->texCoord1.y=_tanvec.y
  1163. _vp->color=color
  1164. _vp+=1
  1165. End
  1166. Method AddPointVertex( tx:Float,ty:Float,s0:Float,t0:Float )
  1167. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x + .5
  1168. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y + .5
  1169. _vp->texCoord0.x=s0
  1170. _vp->texCoord0.y=t0
  1171. _vp->color=_pmcolor
  1172. _vp+=1
  1173. End
  1174. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float )
  1175. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  1176. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  1177. _vp->texCoord0.x=s0
  1178. _vp->texCoord0.y=t0
  1179. _vp->texCoord1.x=_tanvec.x
  1180. _vp->texCoord1.y=_tanvec.y
  1181. _vp->color=_pmcolor
  1182. _vp+=1
  1183. End
  1184. 'Drawing
  1185. '
  1186. Method AddDrawOp( shader:Shader,material:UniformBlock,blendMode:BlendMode,primOrder:int,primCount:Int )
  1187. If _drawNV+primCount*primOrder>_drawVB.Length
  1188. Flush()
  1189. Endif
  1190. If blendMode=BlendMode.None blendMode=_blendMode
  1191. If shader<>_drawOp.shader Or material<>_drawOp.material Or blendMode<>_drawOp.blendMode Or primOrder<>_drawOp.primOrder
  1192. 'pad quads so primOffset always on a 4 vert boundary
  1193. If primOrder=4 And _drawNV & 3
  1194. _drawNV+=4-(_drawNV&3)
  1195. Endif
  1196. _drawOp=New DrawOp
  1197. _drawOp.shader=shader
  1198. _drawOp.material=material
  1199. _drawOp.blendMode=blendMode
  1200. _drawOp.primOrder=primOrder
  1201. _drawOp.primCount=primCount
  1202. _drawOp.primOffset=_drawNV
  1203. _drawOps.Push( _drawOp )
  1204. Else
  1205. _drawOp.primCount+=primCount
  1206. Endif
  1207. _vp=_drawVP0+_drawNV
  1208. _drawNV+=primCount*primOrder
  1209. End
  1210. Method Validate()
  1211. If _dirty & Dirty.Viewport
  1212. Local tviewport:=TransformRecti( _viewport,_rmatrix )
  1213. _rviewport=tviewport & _rbounds
  1214. _rviewportClip=tviewport.Origin-_rviewport.Origin
  1215. Local rmatrix:=New Mat4f
  1216. rmatrix.i.x=_rmatrix.i.x
  1217. rmatrix.j.y=_rmatrix.j.y
  1218. rmatrix.t.x=_rviewportClip.x
  1219. rmatrix.t.y=_rviewportClip.y
  1220. If _rtarget
  1221. _projMatrix=Mat4f.Ortho( 0,_rviewport.Width,0,_rviewport.Height,-1,1 ) * rmatrix
  1222. Else
  1223. _projMatrix=Mat4f.Ortho( 0,_rviewport.Width,_rviewport.Height,0,-1,1 ) * rmatrix
  1224. Endif
  1225. _uniforms.SetMat4f( "ModelViewProjectionMatrix",_projMatrix )
  1226. _uniforms.SetVec2f( "ViewportOrigin",_rviewport.Origin )
  1227. _uniforms.SetVec2f( "ViewportSize",_rviewport.Size )
  1228. _uniforms.SetVec2f( "ViewportClip",_rviewportClip )
  1229. _device.Viewport=_rviewport
  1230. Endif
  1231. If _dirty & Dirty.Scissor
  1232. _rscissor=TransformRecti( _scissor+_viewport.Origin,_rmatrix ) & _rviewport
  1233. _device.Scissor=_rscissor
  1234. Endif
  1235. _dirty=Null
  1236. End
  1237. Method RenderDrawOps( rpass:Int )
  1238. _device.RenderPass=rpass
  1239. _device.VertexBuffer=_drawVB
  1240. Local rpassMask:=1 Shl rpass
  1241. For Local op:=Eachin _drawOps
  1242. Local shader:=op.shader
  1243. If Not (shader.RenderPassMask & rpassMask) Continue
  1244. _device.Shader=shader
  1245. _device.BlendMode=op.blendMode
  1246. _device.BindUniformBlock( op.material )
  1247. Select op.primOrder
  1248. Case 4
  1249. _device.RenderIndexed( 3,op.primCount*2,op.primOffset/4*6 )
  1250. Default
  1251. _device.Render( op.primOrder,op.primCount,op.primOffset )
  1252. End
  1253. ' _device.Render( op.primOrder,op.primCount,op.primOffset )
  1254. Next
  1255. End
  1256. 'Shadows
  1257. '
  1258. Method DrawShadows:Int( lightOp:LightOp )
  1259. Const EXTRUDE:=1024.0
  1260. Local lv:=lightOp.lightPos
  1261. Local vp0:=Cast<Vertex2f Ptr>( _shadowVB.Lock() ),n:=0
  1262. For Local op:=Eachin _shadowOps
  1263. Local vert0:=op.firstVert
  1264. Local nverts:=op.caster.Vertices.Length
  1265. Local tv:=_shadowVerts[vert0+nverts-1]
  1266. For Local iv:=0 Until nverts
  1267. Local pv:=tv
  1268. tv=_shadowVerts[vert0+iv]
  1269. Local dv:=tv-pv
  1270. Local nv:=dv.Normal.Normalize()
  1271. Local pd:=-pv.Dot( nv )
  1272. Local d:=lv.Dot( nv )+pd
  1273. If d<0 Continue
  1274. If n+9>_shadowVB.Length Exit
  1275. Local tp:=vp0+n
  1276. n+=9
  1277. Local hv:=(pv+tv)/2
  1278. Local pv2:=pv + (pv-lv).Normalize() * EXTRUDE
  1279. Local tv2:=tv + (tv-lv).Normalize() * EXTRUDE
  1280. Local hv2:=hv + (hv-lv).Normalize() * EXTRUDE
  1281. tp[0].position=tv;tp[1].position=tv2;tp[2].position=hv2
  1282. tp[3].position=tv;tp[4].position=hv2;tp[5].position=pv
  1283. tp[6].position=hv2;tp[7].position=pv2;tp[8].position=pv
  1284. Next
  1285. Next
  1286. _shadowVB.Invalidate( 0,n )
  1287. _shadowVB.Unlock()
  1288. Return n
  1289. End
  1290. 'Lighting
  1291. '
  1292. Method RenderLighting()
  1293. _device.BlendMode=BlendMode.Additive
  1294. _device.VertexBuffer=_lightVB
  1295. For Local op:=Eachin _lightOps
  1296. Local n:=DrawShadows( op )
  1297. If n
  1298. _device.RenderPass=4
  1299. _device.RenderTarget=_gbrtargets[0]
  1300. _device.BlendMode=BlendMode.Opaque
  1301. _device.ColorMask=ColorMask.Alpha
  1302. _device.VertexBuffer=_shadowVB
  1303. _device.Shader=Shader.GetShader( "shadow" )
  1304. _device.Clear( Color.White )
  1305. _device.Render( 3,n/3,0 )
  1306. _device.RenderPass=5
  1307. _device.RenderTarget=_rtarget
  1308. _device.BlendMode=BlendMode.Additive
  1309. _device.ColorMask=ColorMask.All
  1310. _device.VertexBuffer=_lightVB
  1311. Else
  1312. _device.RenderPass=4
  1313. Endif
  1314. Local light:=op.light
  1315. _device.Shader=light.Shader
  1316. _device.BindUniformBlock( light.Material )
  1317. _device.Render( 4,1,op.primOffset )
  1318. Next
  1319. End
  1320. End