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+width 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 cannot 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()