| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- Namespace mojo.graphics
- Using std.resource
- #rem monkeydoc The Image class.
- An image is a rectangular array of pixels that can be drawn using one of the [[Canvas.DrawImage]] methods.
- You can load an image from a file using one of the [[Load]], [[LoadBump]] or [[LoadLight]] functions.
- #end
- Class Image Extends Resource
- #rem monkeydoc Creates a new Image.
-
- New( pixmap,... ) Creates an image from an existing pixmap.
-
- New( width,height,... ) Creates an image that can be rendered to using a canvas.
-
- New( image,... ) Creates an image from within an 'atlas' image.
-
- Note: `textureFlags` should be null for static images or TextureFlags.Dynamic for dynamic images.
- @param pixmap Source image.
-
- @param textureFlags Image texture flags.
-
- @param shader Image shader.
-
- @param image Source pixmap.
-
- @param rect Source rect.
-
- @param x,y,width,height Source rect
-
- @param width,height Image size.
-
- #end
- Method New( pixmap:Pixmap,textureFlags:TextureFlags=Null,shader:Shader=Null )
-
- Local texture:=New Texture( pixmap,textureFlags )
-
- Init( texture,texture.Rect,shader )
-
- AddDependancy( texture )
- End
- Method New( width:Int,height:Int,textureFlags:TextureFlags=Null,shader:Shader=Null )
-
- Local texture:=New Texture( width,height,PixelFormat.RGBA32,textureFlags )
-
- Init( texture,texture.Rect,shader )
-
- AddDependancy( texture )
- End
- Method New( image:Image )
-
- Init( image._textures[0],image._rect,image._shader )
-
- image.AddDependancy( Self )
-
- For Local i:=1 Until 4
- SetTexture( i,image.GetTexture( i ) )
- Next
-
- BlendMode=image.BlendMode
- TextureFilter=image.TextureFilter
- LightDepth=image.LightDepth
- Handle=image.Handle
- Scale=image.Scale
- Color=image.Color
- End
-
- Method New( image:Image,rect:Recti )
-
- Init( image._textures[0],rect+image._rect.Origin,image._shader )
-
- image.AddDependancy( Self )
-
- For Local i:=1 Until 4
- SetTexture( i,image.GetTexture( i ) )
- Next
-
- BlendMode=image.BlendMode
- TextureFilter=image.TextureFilter
- LightDepth=image.LightDepth
- Handle=image.Handle
- Scale=image.Scale
- Color=image.Color
- End
-
- Method New( image:Image,x:Int,y:Int,width:Int,height:Int )
-
- Self.New( image,New Recti( x,y,x+width,y+height ) )
- End
-
- #rem monkeydoc @hidden
- #end
- Method New( texture:Texture,shader:Shader=Null )
- Init( texture,texture.Rect,shader )
- End
-
- #rem monkeydoc @hidden
- #end
- Method New( texture:Texture,rect:Recti,shader:Shader=Null )
- Init( texture,rect,shader )
- End
-
- #rem monkeydoc The image's primary texture.
- #end
- Property Texture:Texture()
-
- Return _textures[0]
-
- Setter( texture:Texture )
-
- SetTexture( 0,texture )
- End
- #rem monkeydoc The image's texture rect.
-
- Describes the rect the image occupies within its primary texture.
-
- #end
- Property Rect:Recti()
-
- Return _rect
- End
-
- #rem monkeydoc The image handle.
-
- Image handle values are fractional, where 0,0 is the top-left of the image and 1,1 is the bottom-right.
- #end
- Property Handle:Vec2f()
-
- Return _handle
-
- Setter( handle:Vec2f )
-
- _handle=handle
-
- UpdateVertices()
- End
- #rem monkeydoc The image scale.
-
- The scale property provides a simple way to 'pre-scale' an image.
-
- For images with a constant scale, Scaling an image this way is faster than using one of the 'scale' parameters of [[Canvas.DrawImage]].
-
- #end
- Property Scale:Vec2f()
-
- Return _scale
-
- Setter( scale:Vec2f )
-
- _scale=scale
-
- UpdateVertices()
- End
- #rem monkeydoc The image blend mode.
-
- The blend mode used to draw the image.
-
- If set to BlendMode.None, the canvas blend mode is used instead.
-
- Defaults to BlendMode.None.
-
- #end
- Property BlendMode:BlendMode()
-
- Return _blendMode
-
- Setter( blendMode:BlendMode )
-
- _blendMode=blendMode
- End
-
- #rem monkeydoc The image texture filter.
-
- The texture flags used to draw the image.
-
- If set to TextureFilter.None, the canvas texture filter is used instead.
-
- Defaults to TextureFilter.None
-
- #end
- Property TextureFilter:TextureFilter()
-
- Return _textureFilter
-
- Setter( filter:TextureFilter )
-
- _textureFilter=filter
- End
-
- #rem monkeydoc The image color.
-
- The color used to draw the image.
-
- Image color is multiplied by canvas color to achieve the final rendering color.
-
- Defaults to white.
-
- #end
- Property Color:Color()
-
- Return _color
-
- Setter( color:Color )
-
- _color=color
-
- _material.SetVector( "mx2_ImageColor",_color )
- End
- #rem monkeydoc The image light depth.
- #end
- Property LightDepth:Float()
-
- Return _lightDepth
-
- Setter( depth:Float )
-
- _lightDepth=depth
-
- _material.SetScalar( "mx2_LightDepth",_lightDepth )
- End
- #rem monkeydoc Shadow caster attached to image.
- #end
- Property ShadowCaster:ShadowCaster()
-
- Return _shadowCaster
-
- Setter( shadowCaster:ShadowCaster )
-
- _shadowCaster=shadowCaster
- End
- #rem monkeydoc The image bounds.
-
- The bounds rect represents the actual image vertices used when the image is drawn.
-
- Image bounds are affected by [[Scale]] and [[Handle]], and can be used for simple collision detection.
-
- #end
- Property Bounds:Rectf()
-
- Return _bounds
- End
- #rem monkeydoc Image bounds width.
- #end
- Property Width:Float()
-
- Return _bounds.Width
- End
-
- #rem monkeydoc Image bounds height.
- #end
- Property Height:Float()
-
- Return _bounds.Height
- End
- #rem monkeydoc Image bounds radius.
- #end
- Property Radius:Float()
-
- Return _radius
- End
- #rem monkeydoc Image shader.
- #end
- Property Shader:Shader()
-
- Return _shader
- End
-
- #rem monkeydoc Image material.
- #end
- Property Material:UniformBlock()
-
- Return _material
- End
- #rem monkeydoc @hidden Image vertices.
- #end
- Property Vertices:Rectf()
-
- Return _vertices
- End
-
- #rem monkeydoc @hidden Image texture coorinates.
- #end
- Property TexCoords:Rectf()
-
- Return _texCoords
- End
- #rem monkeydoc @hidden Sets an image texture.
- #end
- Method SetTexture( index:Int,texture:Texture )
-
- _textures[index]=texture
-
- _material.SetTexture( "mx2_ImageTexture"+index,texture )
- End
-
- #rem monkeydoc @hidden gets an image texture.
- #end
- Method GetTexture:Texture( index:Int )
-
- Return _textures[index]
- End
-
- #rem monkeydoc Loads an image from file.
- #end
- Function Load:Image( path:String,shader:Shader=Null )
-
- Local pixmap:=Pixmap.Load( path,Null,True )
- If Not pixmap Return Null
- If Not shader shader=mojo.graphics.Shader.GetShader( "sprite" )
-
- Local image:=New Image( pixmap,Null,shader )
-
- image.OnDiscarded+=Lambda()
- pixmap.Discard()
- End
-
- Return image
- End
-
- #rem monkeydoc Loads a bump image from file(s).
-
- `diffuse`, `normal` and `specular` are filepaths of the diffuse, normal and specular image files respectively.
-
- `specular` can be null, in which case `specularScale` is used for the specular component. Otherwise, `specularScale` is used to modulate the red component of the specular texture.
-
- #end
- Function LoadBump:Image( diffuse:String,normal:String,specular:String,specularScale:Float=1,flipNormalY:Bool=True,shader:Shader=Null )
-
- Local texture1:=graphics.Texture.LoadNormal( normal,Null,specular,specularScale,flipNormalY )
- If Not texture1 Return Null
-
- Local texture0:=graphics.Texture.Load( diffuse,Null )
-
- If Not texture0
- Local pdiff:=New Pixmap( texture1.Width,texture1.Height,PixelFormat.I8 )
- pdiff.Clear( std.graphics.Color.White )
- texture0=New graphics.Texture( pdiff,Null )
- Endif
-
- If Not shader shader=graphics.Shader.GetShader( "bump" )
-
- Local image:=New Image( texture0,texture0.Rect,shader )
- image.SetTexture( 1,texture1 )
-
- image.OnDiscarded+=Lambda()
- If texture0 texture0.Discard()
- If texture1 texture1.Discard()
- End
-
- Return image
- End
- #rem monkeydoc Loads a light image from file.
- #end
- Function LoadLight:Image( path:String,shader:Shader=Null )
-
- Local pixmap:=Pixmap.Load( path )
- If Not pixmap Return Null
-
- If Not shader shader=mojo.graphics.Shader.GetShader( "light" )
-
- Select pixmap.Format
- Case PixelFormat.IA16,PixelFormat.RGBA32
-
- pixmap.PremultiplyAlpha()
-
- Case PixelFormat.A8
- Local tpixmap:=pixmap
- pixmap=pixmap.Convert( PixelFormat.IA16 )
- tpixmap.Discard()
- 'Copy A->I
- For Local y:=0 Until pixmap.Height
- Local p:=pixmap.PixelPtr( 0,y )
- For Local x:=0 Until pixmap.Width
- p[0]=p[1]
- p+=2
- Next
- Next
- Case PixelFormat.I8
-
- Local tpixmap:=pixmap
- pixmap=pixmap.Convert( PixelFormat.IA16 )
- tpixmap.Discard()
-
- 'Copy I->A
- For Local y:=0 Until pixmap.Height
- Local p:=pixmap.PixelPtr( 0,y )
- For Local x:=0 Until pixmap.Width
- p[1]=p[0]
- p+=2
- Next
- Next
- Case PixelFormat.RGB24
-
- Local tpixmap:=pixmap
- pixmap=pixmap.Convert( PixelFormat.RGBA32 )
- tpixmap.Discard()
-
- 'Copy R->A
- For Local y:=0 Until pixmap.Height
- Local p:=pixmap.PixelPtr( 0,y )
- For Local x:=0 Until pixmap.Width
- p[3]=p[0]
- p+=4
- Next
- Next
-
- End
-
- Local texture:=New Texture( pixmap,Null )
-
- Local image:=New Image( texture,shader )
-
- image.OnDiscarded+=Lambda()
- pixmap.Discard()
- End
-
- Return image
- End
- Private
-
- Field _shader:Shader
- Field _material:UniformBlock
- Field _textures:=New Texture[4]
- Field _blendMode:BlendMode
- Field _textureFilter:TextureFilter
- Field _color:Color
- Field _lightDepth:Float
- Field _shadowCaster:ShadowCaster
-
- Field _rect:Recti
- Field _handle:Vec2f
- Field _scale:Vec2f
-
- Field _vertices:Rectf
- Field _texCoords:Rectf
- Field _bounds:Rectf
- Field _radius:Float
-
- Method Init( texture:Texture,rect:Recti,shader:Shader )
-
- If Not shader shader=Shader.GetShader( "sprite" )
-
- _rect=rect
- _shader=shader
- _material=New UniformBlock
-
- AddDependancy( _material )
-
- SetTexture( 0,texture )
-
- BlendMode=BlendMode.None
- TextureFilter=TextureFilter.None
- Color=Color.White
- LightDepth=100
- Handle=New Vec2f( 0 )
- Scale=New Vec2f( 1 )
-
- UpdateVertices()
- UpdateTexCoords()
- End
-
- Method UpdateVertices()
- _vertices.min.x=Float(_rect.Width)*(0-_handle.x)*_scale.x
- _vertices.min.y=Float(_rect.Height)*(0-_handle.y)*_scale.y
- _vertices.max.x=Float(_rect.Width)*(1-_handle.x)*_scale.x
- _vertices.max.y=Float(_rect.Height)*(1-_handle.y)*_scale.y
- _bounds.min.x=Min( _vertices.min.x,_vertices.max.x )
- _bounds.max.x=Max( _vertices.min.x,_vertices.max.x )
- _bounds.min.y=Min( _vertices.min.y,_vertices.max.y )
- _bounds.max.y=Max( _vertices.min.y,_vertices.max.y )
- _radius=_bounds.min.x*_bounds.min.x+_bounds.min.y*_bounds.min.y
- _radius=Max( _radius,_bounds.max.x*_bounds.max.x+_bounds.min.y*_bounds.min.y )
- _radius=Max( _radius,_bounds.max.x*_bounds.max.x+_bounds.max.y*_bounds.max.y )
- _radius=Max( _radius,_bounds.min.x*_bounds.min.x+_bounds.max.y*_bounds.max.y )
- _radius=Sqrt( _radius )
- End
-
- Method UpdateTexCoords()
- _texCoords.min.x=Float(_rect.min.x)/_textures[0].Width
- _texCoords.min.y=Float(_rect.min.y)/_textures[0].Height
- _texCoords.max.x=Float(_rect.max.x)/_textures[0].Width
- _texCoords.max.y=Float(_rect.max.y)/_textures[0].Height
- End
-
- End
- Class ResourceManager Extension
- Method OpenImage:Image( path:String,shader:Shader=Null )
- Local slug:="Image:name="+StripDir( StripExt( path ) )+"&shader="+(shader ? shader.Name Else "null")
-
- Local image:=Cast<Image>( OpenResource( slug ) )
- If image Return image
- Local texture:=OpenTexture( path,Null )
- If texture image=New Image( texture,shader )
-
- AddResource( slug,image )
- Return image
- End
- End
|