diff options
Diffstat (limited to 'vectorgfx.mod/vectorgfx.bmx')
-rw-r--r-- | vectorgfx.mod/vectorgfx.bmx | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/vectorgfx.mod/vectorgfx.bmx b/vectorgfx.mod/vectorgfx.bmx new file mode 100644 index 0000000..f504141 --- /dev/null +++ b/vectorgfx.mod/vectorgfx.bmx @@ -0,0 +1,406 @@ +Rem +bbdoc: noddybox.vectorgfx +EndRem +Module noddybox.vectorgfx + +ModuleInfo "Framework: 2D Vector Graphics classes" +ModuleInfo "Copyright: Public Domain" +ModuleInfo "Author: Ian Cowburn" +ModuleInfo "Version: $Revision$" + +' $Id$ + +Strict +Import brl.linkedlist +Import brl.math +Import brl.endianstream +Import brl.max2d +Import noddybox.vector +Import noddybox.algorithm + +Rem +bbdoc: Defines a method for drawing vector lines +EndRem +Type TVectorGfxLineStyle Abstract + Method Draw:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, colmap:TVectorGfxCollisionMap) Abstract +End Type + +Rem +bbdoc: Set to use solid lines for drawing. +about: This mode draws vector lines as solid colour lines using the current alpha, and is the default mode. +EndRem +Function VectorGfxSetSolid() + Static.linedraw=New LineSolid +End Function + +Rem +bbdoc: Set to use alpha lines for drawing. +about: This mode draws vector lines using a @line_alpha for the lines, except for the end-points drawn with @end_alpha. +EndRem +Function VectorGfxSetAlpha(line_alpha:Double,end_alpha:Double) + Local l:LineAlpha=New LineAlpha + l.la=line_alpha + l.ea=end_alpha + Static.linedraw=l +End Function + +Rem +bbdoc: Set to use thick lines for drawing. +about: This mode draws vector lines using solid line, surrounded by points of alpha @line_alpha. +EndRem +Function VectorGfxSetThickAlpha(line_alpha:Double) + Local l:ThickAlpha=New ThickAlpha + l.a=line_alpha + Static.linedraw=l +End Function + +Rem +bbdoc: Defines a vector graphics collision map. +about: Collisions in the library a defined using a bitmask (allowing 32 collision masks). +EndRem +Type TVectorGfxCollisionMap + + Field width:Int + Field height:Int + Field xoff:Int + Field yoff:Int + Field data:Int[,] + + Rem + bbdoc: Create a collision map. + returns: The created collision map. + about: @width and @height are the size of the collision map. + EndRem + Function Create:TVectorGfxCollisionMap(width:Int, height:Int) + Local o:TVectorGfxCollisionMap=New TVectorGfxCollisionMap + + o.width=width + o.height=height + o.xoff=0 + o.yoff=0 + o.data=New Int[width,height] + + Return o + End Function + + Rem + bbdoc: Set the offset of the collision map. + about: @x and @y are the offsets into the co-ordinate space where the collision map lives. + EndRem + Method SetOffset(x:Int, y:Int) + xoff=x + yoff=y + End Method + + Rem + bbdoc: Set a collision point. + returns: The current collision mask for that point, or zero if the point is out of the map's range. + about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space) + EndRem + Method SetCollision(x:Int, y:Int, id:Int) + If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height + Return 0 + EndIf + + x:-xoff + y:-yoff + + Local cur:Int=data[x,y] + + data[x,y]:|id + + Return cur + End Method + + Rem + bbdoc: Clear the collision map + EndRem + Method Clear() + For Local x:Int=0 Until width + For Local y:Int=0 Until height + data[x,y]=0 + Next + Next + End Method +End Type + + +Rem +bbdoc: Defines a 2D vector graphics object +EndRem +Type TVectorGfxObject + Field lines:TList + + Rem + bbdoc: The X co-ordinate of the object + EndRem + Field x:Int + Rem + bbdoc: The Y co-ordinate of the object + EndRem + Field y:Int + Rem + bbdoc: The angle of the object, as degrees*10. Must be within the range 0-3599 inclusive. + EndRem + Field ang:Int + + Rem + bbdoc: Creates a new empty object + returns: The created object. + EndRem + Method New() + lines=CreateList() + x=0 + y=0 + ang=0 + End Method + + Rem + bbdoc: Adds a line to the object. + about: @line is the line to add. + EndRem + Method AddLine(line:TVectorGfxLine) + lines.AddLast(line) + End Method + + Rem + bbdoc: Removes a line from the object. + about: @line is the line to remove. + EndRem + Method RemoveLine(line:TVectorGfxLine) + lines.Remove(line) + End Method + + Rem + bbdoc: Loads the object from the supplied @filename. + returns: The loaded object, or null if the file could not be opened. + EndRem + Function Load:TVectorGfxObject(filename:String) + Local s:TStream=ReadStream(filename) + + If Not s + Return Null + EndIf + + s=LittleEndianStream(s) + Local o:TVectorGfxObject=New TVectorGfxObject + + o.x=s.ReadInt() + o.y=s.ReadInt() + o.ang=s.ReadInt() + + Local i:Int=s.ReadInt() + + For Local f=0 Until i + o.AddLine(TVectorGfxLine.Load(s)) + Next + + s.Close() + + Return o + End Function + + Rem + bbdoc: Saves the object to the supplied @filename. + EndRem + Method Save(filename:String) + Local s:TStream=WriteStream(filename) + + If Not s + Return Null + EndIf + + s=LittleEndianStream(s) + + s.WriteInt(x) + s.WriteInt(y) + s.WriteInt(ang) + s.WriteInt(lines.Count()) + + For Local l:TVectorGfxLine=EachIn lines + l.Save(s) + Next + + s.Close() + End Method + + Rem + bbdoc: Draw the object. + returns: A bitmask of collisions. + about: Draws the object. @colmap <u>cannot</u> be null - use a small collision map instead if you're uninterested in collisions + EndRem + Method Draw:Int(colmap:TVectorGfxCollisionMap) + Local col:Int=0 + For Local l:TVectorGfxLine=EachIn lines + Local p1:TAlgoPoint=DoRotate(l.x1,l.y1,ang) + Local p2:TAlgoPoint=DoRotate(l.x2,l.y2,ang) + + col:|Static.linedraw.draw(x+p1.x,y+p1.y,x+p2.x,y+p2.y,l.r,l.g,l.b,l.id,colmap) + Next + + Return col + End Method +End Type + +Rem +bbdoc: Defines a line +EndRem +Type TVectorGfxLine + Field x1:Int + Field y1:Int + Field x2:Int + Field y2:Int + Field id:Int + Field r:Int + Field g:Int + Field b:Int + + Rem + bbdoc: Create a line. + returns: The created line. + about: @x1, @y1, @x2 and @y2 are the co-ordinates of the line. @r, @g and @b is the line's colour. @id is the collision map mask for the line. + EndRem + Function Create:TVectorGfxLine(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int) + Local o:TVectorGfxLine=New TVectorGfxLine + + o.x1=x1 + o.y1=y1 + o.x2=x2 + o.y2=y2 + o.r=r + o.g=g + o.b=b + o.id=id + + Return o + End Function + + Rem + bbdoc: This is for internal library use. + EndRem + Function Load:TVectorGfxLine(s:TStream) + Local o:TVectorGfxLine + o=New TVectorGfxLine + o.x1=s.ReadInt() + o.y1=s.ReadInt() + o.x2=s.ReadInt() + o.y2=s.ReadInt() + o.r=s.ReadInt() + o.g=s.ReadInt() + o.b=s.ReadInt() + o.id=s.ReadInt() + Return o + End Function + + Rem + bbdoc: This is for internal library use. + EndRem + Method Save:TVectorGfxLine(s:TStream) + s.WriteInt(x1) + s.WriteInt(y1) + s.WriteInt(x2) + s.WriteInt(y2) + s.WriteInt(r) + s.WriteInt(g) + s.WriteInt(b) + s.WriteInt(id) + End Method +End Type + +Private + +Type Static + Global linedraw:TVectorGfxLineStyle + + Function Init() + linedraw=New LineSolid + End Function +End Type + +Type LineSolid Extends TVectorGfxLineStyle + Method Draw:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, colmap:TVectorGfxCollisionMap) + Local mask:Int=0 + Local lp:TList=DoLine(x1,y1,x2,y2) + + SetColor(r,g,b) + + For Local p:TAlgoPoint=EachIn lp + mask:|colmap.SetCollision(p.x,p.y,id) + Plot(p.x,p.y) + Next + + Return mask + End Method +End Type + +Type LineAlpha Extends TVectorGfxLineStyle + Field la:Double + Field ea:Double + + Method Draw:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, colmap:TVectorGfxCollisionMap) + Local mask:Int=0 + Local lp:TList=DoLine(x1,y1,x2,y2) + Local p:TAlgoPoint + Local a:Double=GetAlpha() + + SetColor(r,g,b) + SetAlpha(ea) + + p=TAlgoPoint(lp.RemoveFirst()) + + mask:|colmap.SetCollision(p.x,p.y,id) + Plot(p.x,p.y) + + If lp.Count()=0 + Return id + EndIf + + p=TAlgoPoint(lp.RemoveLast()) + + mask:|colmap.SetCollision(p.x,p.y,id) + Plot(p.x,p.y) + + SetAlpha(la) + + For Local p:TAlgoPoint=EachIn lp + mask:|colmap.SetCollision(p.x,p.y,id) + Plot(p.x,p.y) + Next + + SetAlpha(a) + + Return mask + End Method +End Type + + +Type ThickAlpha Extends TVectorGfxLineStyle + Field a:Double + + Method PlotPoint(x,y) + SetAlpha(a) + DrawLine(x-1,y-1,x+1,y-1,False) + DrawLine(x+1,y-1,x+1,y+1,False) + DrawLine(x+1,y+1,x-1,y+1,False) + DrawLine(x-1,y+1,x-1,y-1,False) + SetAlpha(1.0) + Plot(x,y) + End Method + + Method Draw:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, colmap:TVectorGfxCollisionMap) + Local mask:Int=0 + Local lp:TList=DoLine(x1,y1,x2,y2) + + SetColor(r,g,b) + + For Local p:TAlgoPoint=EachIn lp + mask:|colmap.SetCollision(p.x,p.y,id) + PlotPoint(p.x,p.y) + Next + + Return mask + + End Method +End Type + +Static.Init()
\ No newline at end of file |