image.monkey2 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. Namespace mojo.graphics
  2. #rem monkeydoc The Image class.
  3. An image is a rectangular array of pixels that can be drawn using one of the [[Canvas.DrawImage]] methods.
  4. You can load an image from a file using the [[Load]].
  5. #end
  6. Class Image
  7. #rem monkeydoc @hidden
  8. #end
  9. Field OnDiscarded:Void()
  10. #rem monkeydoc Creates a new image.
  11. New( pixmap,... ) allows you to create a new image from an existing pixmap.
  12. New( width,height,... ) allows you to create a new image that can be rendered to using a canvas. For images that will be frequently updated, use `TextureFlags.Filter|TextureFlags.Dynamic' for the best performance.
  13. New( image,rect,... ) allows you to create an image from within an 'atlas' image.
  14. @example
  15. Namespace myapp
  16. #Import "<std>"
  17. #Import "<mojo>"
  18. Using std..
  19. Using mojo..
  20. Class MyWindow Extends Window
  21. Field image1:Image
  22. Field image2:Image
  23. Field image3:Image
  24. Method New()
  25. 'Create an image from a pixmap
  26. Local pixmap:=New Pixmap( 16,16 )
  27. pixmap.Clear( Color.Red )
  28. image1=New Image( pixmap )
  29. 'Create an image and render something to it
  30. image2=New Image( 16,16 )
  31. Local icanvas:=New Canvas( image2 )
  32. icanvas.Color=Color.Yellow
  33. icanvas.DrawRect( 0,0,8,8 )
  34. icanvas.DrawRect( 8,8,8,8 )
  35. icanvas.Color=Color.LightGrey
  36. icanvas.DrawRect( 8,0,8,8 )
  37. icanvas.DrawRect( 0,8,8,8 )
  38. icanvas.Flush() 'Important!
  39. 'Create a image from an atlas image
  40. image3=New Image( image2,New Recti( 4,4,12,12 ) )
  41. End
  42. Method OnRender( canvas:Canvas ) Override
  43. canvas.DrawText( "Image1",0,0 )
  44. canvas.DrawImage( image1,0,16 )
  45. canvas.DrawText( "Image2",0,40 )
  46. canvas.DrawImage( image2,0,56 )
  47. canvas.DrawText( "Image3",0,80 )
  48. canvas.DrawImage( image3,0,96 )
  49. End
  50. End
  51. Function Main()
  52. New AppInstance
  53. New MyWindow
  54. App.Run()
  55. End
  56. @end
  57. #end
  58. Method New( pixmap:Pixmap,textureFlags:TextureFlags=TextureFlags.Filter|TextureFlags.Mipmap,shader:Shader=Null )
  59. Local texture:=New Texture( pixmap,textureFlags )
  60. Init( Null,texture,texture.Rect,shader )
  61. OnDiscarded+=Lambda()
  62. texture.Discard()
  63. End
  64. End
  65. Method New( width:Int,height:Int,textureFlags:TextureFlags=TextureFlags.Filter|TextureFlags.Mipmap,shader:Shader=Null )
  66. Local textureFormat:PixelFormat=PixelFormat.RGBA32
  67. Local texture:=New Texture( width,height,textureFormat,textureFlags )
  68. Init( Null,texture,texture.Rect,shader )
  69. OnDiscarded+=Lambda()
  70. texture.Discard()
  71. End
  72. End
  73. Method New( image:Image,rect:Recti )
  74. Init( image._material,image._texture,rect,Null )
  75. End
  76. #rem monkeydoc @hidden
  77. #end
  78. Method New( texture:Texture,shader:Shader=Null )
  79. Init( Null,texture,texture.Rect,shader )
  80. End
  81. #rem monkeydoc @hidden
  82. #end
  83. Method New( material:Material,texture:Texture,rect:Recti )
  84. Init( material,texture,rect,Null )
  85. End
  86. #rem monkeydoc @hidden
  87. #end
  88. Property Material:Material()
  89. Return _material
  90. End
  91. #rem monkeydoc @hidden
  92. #end
  93. Property Texture:Texture()
  94. Return _texture
  95. End
  96. #rem monkeydoc @hidden The image's rect within its texture.
  97. #end
  98. Property Rect:Recti()
  99. Return _rect
  100. End
  101. #rem monkeydoc The width of the image's rect within its texture.
  102. #end
  103. Property Width:Int()
  104. Return _rect.Width
  105. End
  106. #rem monkeydoc The height of the image's rect within its texture.
  107. #end
  108. Property Height:Int()
  109. Return _rect.Height
  110. End
  111. #rem monkeydoc The image handle.
  112. Image handle values are fractional, where 0,0 is the top-left of the image and 1,1 is the bottom-right.
  113. #end
  114. Property Handle:Vec2f()
  115. Return _handle
  116. Setter( handle:Vec2f )
  117. _handle=handle
  118. UpdateVertices()
  119. End
  120. #rem monkeydoc The image scale.
  121. The scale property provides a simple way to 'pre-scale' an image.
  122. Scaling an image this way is faster than using one of the 'scale' parameters of [[Canvas.DrawImage]].
  123. #end
  124. Property Scale:Vec2f()
  125. Return _scale
  126. Setter( scale:Vec2f )
  127. _scale=scale
  128. UpdateVertices()
  129. End
  130. #rem monkeydoc The image bounds.
  131. The bounds rect represents the actual image vertices used when the image is drawn.
  132. Image bounds are affected by [[Scale]] and [[Handle]], and can be used for simple collision detection.
  133. #end
  134. Property Bounds:Rectf()
  135. Return _bounds
  136. End
  137. #rem monkeydoc Image radius.
  138. The radius property returns the radius of the [[Bounds]] rect.
  139. Image bounds are affected by [[Scale]] and [[Handle]], and can be used for simple collision detection.
  140. #end
  141. Property Radius:Float()
  142. Return _radius
  143. End
  144. #rem monkeydoc @hidden
  145. #end
  146. Property Vertices:Rectf()
  147. Return _vertices
  148. End
  149. #rem monkeydoc @hidden
  150. #end
  151. Property TexCoords:Rectf()
  152. Return _texCoords
  153. End
  154. #rem monkeydoc Releases the image and any resource it uses.
  155. #end
  156. Method Discard()
  157. If _discarded Return
  158. _discarded=True
  159. OnDiscarded()
  160. End
  161. #rem monkeydoc Loads an image from a file.
  162. #end
  163. Function Load:Image( path:String,textureFlags:TextureFlags=TextureFlags.Filter|TextureFlags.Mipmap,shader:Shader=Null )
  164. Local diffuse:=mojo.graphics.Texture.Load( path,textureFlags )
  165. If Not diffuse Return Null
  166. Local file:=StripExt( path )
  167. Local ext:=ExtractExt( path )
  168. Local specular:=mojo.graphics.Texture.Load( file+"_SPECULAR"+ext,textureFlags )
  169. Local normal:=mojo.graphics.Texture.Load( file+"_NORMALS"+ext,textureFlags )
  170. If specular Or normal
  171. If Not specular specular=mojo.graphics.Texture.ColorTexture( Color.Black )
  172. If Not normal normal=mojo.graphics.Texture.ColorTexture( New Color( .5,.5,.5 ) )
  173. Endif
  174. If Not shader
  175. If specular Or normal
  176. shader=Shader.GetShader( "phong" )
  177. Else
  178. shader=Shader.GetShader( "sprite" )
  179. Endif
  180. Endif
  181. Local material:=New Material( shader )
  182. If diffuse material.SetTexture( "DiffuseTexture",diffuse )
  183. If specular material.SetTexture( "SpecularTexture",specular )
  184. If normal material.SetTexture( "NormalTexture",normal )
  185. Local image:=New Image( material,diffuse,diffuse.Rect )
  186. image.OnDiscarded+=Lambda()
  187. If diffuse diffuse.Discard()
  188. If specular specular.Discard()
  189. If normal normal.Discard()
  190. End
  191. Return image
  192. End
  193. Private
  194. Field _material:Material
  195. Field _texture:Texture
  196. Field _rect:Recti
  197. Field _discarded:Bool
  198. Field _handle:=New Vec2f( 0,0 )
  199. Field _scale:=New Vec2f( 1,1 )
  200. Field _vertices:Rectf
  201. Field _texCoords:Rectf
  202. Field _bounds:Rectf
  203. Field _radius:Float
  204. Method Init( material:Material,texture:Texture,rect:Recti,shader:Shader )
  205. If Not material
  206. If Not shader shader=Shader.GetShader( "sprite" )
  207. material=New Material( shader )
  208. material.SetTexture( "DiffuseTexture",texture )
  209. Endif
  210. _material=material
  211. _texture=texture
  212. _rect=rect
  213. UpdateVertices()
  214. UpdateTexCoords()
  215. End
  216. Method UpdateVertices()
  217. _vertices.min.x=Float(_rect.Width)*(0-_handle.x)*_scale.x
  218. _vertices.min.y=Float(_rect.Height)*(0-_handle.y)*_scale.y
  219. _vertices.max.x=Float(_rect.Width)*(1-_handle.x)*_scale.x
  220. _vertices.max.y=Float(_rect.Height)*(1-_handle.y)*_scale.y
  221. _bounds.min.x=Min( _vertices.min.x,_vertices.max.x )
  222. _bounds.max.x=Max( _vertices.min.x,_vertices.max.x )
  223. _bounds.min.y=Min( _vertices.min.y,_vertices.max.y )
  224. _bounds.max.y=Max( _vertices.min.y,_vertices.max.y )
  225. _radius=_bounds.min.x*_bounds.min.x+_bounds.min.y*_bounds.min.y
  226. _radius=Max( _radius,_bounds.max.x*_bounds.max.x+_bounds.min.y*_bounds.min.y )
  227. _radius=Max( _radius,_bounds.max.x*_bounds.max.x+_bounds.max.y*_bounds.max.y )
  228. _radius=Max( _radius,_bounds.min.x*_bounds.min.x+_bounds.max.y*_bounds.max.y )
  229. _radius=Sqrt( _radius )
  230. End
  231. Method UpdateTexCoords()
  232. _texCoords.min.x=Float(_rect.min.x)/_texture.Width
  233. _texCoords.min.y=Float(_rect.min.y)/_texture.Height
  234. _texCoords.max.x=Float(_rect.max.x)/_texture.Width
  235. _texCoords.max.y=Float(_rect.max.y)/_texture.Height
  236. End
  237. End