summaryrefslogtreecommitdiff
path: root/vectorgfx.mod
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2020-04-08 21:23:22 +0000
committerIan C <ianc@noddybox.co.uk>2020-04-08 21:23:22 +0000
commit6c0b11a6bb632a5c7cd29ad8a92ce31fe929c194 (patch)
tree81d8972c24c12b4e1ec51a853ce0bee5737e2a56 /vectorgfx.mod
parent2fc5b1e06854d1cb1e5ad59ceb6d8748a9d82f32 (diff)
Removed Strict -- doesn't seem to like it anymore.
Diffstat (limited to 'vectorgfx.mod')
-rw-r--r--vectorgfx.mod/vectorgfx.bmx1365
1 files changed, 682 insertions, 683 deletions
diff --git a/vectorgfx.mod/vectorgfx.bmx b/vectorgfx.mod/vectorgfx.bmx
index 06018a8..a44635f 100644
--- a/vectorgfx.mod/vectorgfx.bmx
+++ b/vectorgfx.mod/vectorgfx.bmx
@@ -1,683 +1,682 @@
-' Copyright (c) 2006 Ian Cowburn
-'
-' Permission is hereby granted, free of charge, to any person obtaining a copy of
-' this software and associated documentation files (the "Software"), to deal in
-' the Software without restriction, including without limitation the rights to
-' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-' of the Software, and to permit persons to whom the Software is furnished to do
-' so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included in all
-' copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-' SOFTWARE.
-'
-' $Id$
-'
-Rem
-bbdoc: noddybox.vectorgfx
-EndRem
-Module noddybox.vectorgfx
-
-ModuleInfo "Framework: 2D Vector Graphics classes"
-ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
-ModuleInfo "Author: Ian Cowburn"
-ModuleInfo "Version: $Revision$"
-
-Strict
-Import brl.linkedlist
-Import brl.math
-Import brl.endianstream
-Import brl.max2d
-Import noddybox.vector
-Import noddybox.algorithm
-
-Rem
-bbdoc: Wibble
-about: Wobble
-EndRem
-
-Rem
-bbdoc: Defines a method for drawing vector lines
-about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module.
-EndRem
-Type TVectorGfxLineStyle Abstract
- Rem
- bbdoc: Draws a vector line using IDs and @TVectorGfxCollisionMap method.
- returns: The or'ed mask of all collision IDs overwritten in @colmap by this line, or zero if @colmap is null.
- about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b.
- about: @id, @obj and @line must be written into the collision map @colmap if @colmap is not null and @actor is false.
- about: If @colmap is set and @actor true, then collisions must be returned but no points written into the collision map.
- about: If @colmap is set, @actor is true and @list is not null then any collisions should be recorded into this list
- about: (no requirement for duplicate checking).
- EndRem
- Method LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList) Abstract
-
- Rem
- bbdoc: Draws a vector line using the point list method.
- about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b.
- about: If list is not null, then the points drawn must be stored in the list as @TVectorGfxPoint objects.
- about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module.
- EndRem
- Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList) 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 a custom drawing method.
-EndRem
-Function VectorGfxSetCustom(linedraw:TVectorGfxLineStyle)
- Static.linedraw=linedraw
-End Function
-
-Rem
-bbdoc: Defines a point in the vector graphics collision map.
-EndRem
-Type TVectorGfxCollision
- Rem
- bbdoc: The X co-ordinate of this collision (in the object co-ordinate space).
- EndRem
- Field x:Int
-
- Rem
- bbdoc: The Y co-ordinate of this collision (in the object co-ordinate space).
- EndRem
- Field y:Int
-
- Rem
- bbdoc: The collision masks at this point.
- EndRem
- Field mask:Int
-
- Rem
- bbdoc: The last vector object that wrote at this point.
- EndRem
- Field obj:TVectorGfxObject
-
- Rem
- bbdoc: The index of the line in the last vector object that wrote at this point.
- EndRem
- Field line:Int
-
- Function Create:TVectorGfxCollision(x:Int, y:Int, mask:Int, obj:TVectorGfxObject, line:Int)
- Local o:TVectorGfxCollision=New TVectorGfxCollision
- o.x=x
- o.y=y
- o.mask=mask
- o.obj=obj
- o.line=line
- Return o
- End Function
-End Type
-
-
-Rem
-bbdoc: Defines a vector graphics collision map.
-about: Collisions using this method in the library are 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:TVectorGfxCollision[,]
-
- 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.Clear()
- 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: Get a collision point.
- returns: The collision point, or null if nothing drawn there.
- about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space)
- EndRem
- Method GetCollision:TVectorGfxCollision(x:Int, y:Int)
- If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height
- Return Null
- Else
- Return data[x-xoff,y-yoff]
- EndIf
- 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:Int(x:Int, y:Int, id:Int, obj:TVectorGfxObject, line:Int)
- If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height
- Return 0
- EndIf
-
- Local ax:Int=x-xoff
- Local ay:Int=y-yoff
-
- Local cur:TVectorGfxCollision=data[ax,ay]
-
- If Not cur
- cur=TVectorGfxCollision.Create(x,y,id,obj,line)
- data[ax,ay]=cur
- Else
- cur.mask:|id
- cur.obj=obj
- cur.line=line
- EndIf
-
- Return cur.mask
- End Method
-
- Rem
- bbdoc: Clear the collision map
- EndRem
- Method Clear()
- data=New TVectorGfxCollision[width,height]
- End Method
-End Type
-
-
-Rem
-bbdoc: Defines a 2D vector graphics object
-EndRem
-Type TVectorGfxObject
- Rem
- bbdoc: The points making up this object
- EndRem
- Field points:TVectorGfxPoint[]
- Rem
- bbdoc: The lines making up this object
- EndRem
- Field lines:TVectorGfxLine[]
- 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 minimum X co-ordinate of the object. Only valid after a call to SetPoints().
- EndRem
- Field min_x:Int
- Rem
- bbdoc: The maximum X co-ordinate of the object. Only valid after a call to SetPoints().
- EndRem
- Field max_x:Int
- Rem
- bbdoc: The minimum Y co-ordinate of the object. Only valid after a call to SetPoints().
- EndRem
- Field min_y:Int
- Rem
- bbdoc: The maximum Y co-ordinate of the object. Only valid after a call to SetPoints().
- EndRem
- Field max_y:Int
- Rem
- bbdoc: The width of the object. Only valid after a call to SetPoints().
- EndRem
- Field width:Int
- Rem
- bbdoc: The height of the object. Only valid after a call to SetPoints().
- EndRem
- Field height: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: The scale of the object.
- EndRem
- Field scale:Double
-
- Field rotated:TVectorGfxPoint[]
-
- Rem
- bbdoc: Creates a new empty object
- returns: The created object.
- EndRem
- Method New()
- points=Null
- lines=Null
- rotated=Null
- x=0
- y=0
- min_x=9999999
- min_y=9999999
- max_x=-9999999
- max_y=-9999999
- width=0
- height=0
- ang=0
- scale=1
- End Method
-
- Rem
- bbdoc: Clones this object
- about: Returns a copy of this object, with its own copy of the line and points.
- EndRem
- Method Clone:TVectorGfxObject()
- Local o:TVectorGfxObject=New TVectorGfxObject
- o.x=x
- o.y=y
- o.min_x=min_x
- o.min_y=min_y
- o.max_x=max_x
- o.max_y=max_y
- o.width=width
- o.height=height
- o.ang=ang
- o.scale=scale
- o.SetPoints(points)
- o.SetLines(lines)
- Return o
- End Method
-
- Rem
- bbdoc: Sets the points for this object
- about: @pa is an array of points for this object.
- EndRem
- Method SetPoints(pa:Object[])
- points=New TVectorGfxPoint[pa.length]
- For Local f:Int=0 Until pa.length
- points[f]=TVectorGfxPoint(pa[f])
- min_x=Min(min_x,points[f].x)
- min_y=Min(min_y,points[f].y)
- max_x=Max(max_x,points[f].x)
- max_y=Max(max_y,points[f].y)
- Next
- width=max_x-min_x
- height=max_y-min_y
- End Method
-
- Rem
- bbdoc: Sets the lines for this object.
- about: @la is the array of lines for this object.
- EndRem
- Method SetLines(la:Object[])
- lines=New TVectorGfxLine[la.length]
- For Local f:Int=0 Until la.length
- lines[f]=TVectorGfxLine(la[f])
- Next
- End Method
-
- Rem
- bbdoc: Whether a point is inside the object
- returns: True if the point lies inside the object. The object is assumed to be a closed polygon for this test.
- about: @cx, @cy is the point to test.
- about: This routine is based on code from comp.graphics.algorithms FAQ 2.03
- EndRem
- Method IsInside:Int(cx:Int, cy:Int)
- If rotated=Null
- Return False
- EndIf
-
- Local cross:Int=False
-
- For Local l:TVectorGfxLine=EachIn lines
- Local x1:Int=x+rotated[l.i1].x
- Local y1:Int=y+rotated[l.i1].y
- Local x2:Int=x+rotated[l.i2].x
- Local y2:Int=y+rotated[l.i2].y
-
- If ((((y1<=cy) And (cy<y2)) Or ((y2<=cy) And (cy<y1))) And (cx < (x2 - x1) * (cy - y1) / (y2 - y1) + x1))
- cross=Not cross
- EndIf
- Next
-
- Return cross
- End Method
-
- Rem
- bbdoc: A line's adjusted co-ordinates.
- returns: The rotated and scaled points (in object co-ordinates) of the line.
- about: @i is the index of the line to return the points for.
- about: Calling it before drawing the object will return null.
- EndRem
- Method AdjustedCoords:TVectorGfxPoint[](i:Int)
- If rotated=Null
- Return Null
- EndIf
-
- Local p:TVectorGfxPoint[]=New TVectorGfxPoint[2]
- Local l:TVectorGfxLine=lines[i]
- p[0]=rotated[l.i1]
- p[1]=rotated[l.i2]
- Return p
- End Method
-
- Rem
- bbdoc: A line's normal.
- returns: The normal of the selected line.
- about: @i is the index of the line to return the normal of. This will return the normal due to the rotation of the object after the object is drawn.
- about: Calling it before drawing the object will return null.
- EndRem
- Method Normal:TVector(i:Int)
- If rotated=Null
- Return Null
- EndIf
-
- Local l:TVectorGfxLine=lines[i]
- Local v:TVector=TVector.Create(rotated[l.i2].y-rotated[l.i1].y,rotated[l.i1].x-rotated[l.i2].x)
- v.Normalise()
- Return v
- 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 l:TList=CreateList()
- Local i:Int=s.ReadInt()
-
- For Local f=0 Until i
- l.AddLast(TVectorGfxPoint.Load(s))
- Next
-
- o.SetPoints(l.ToArray())
-
- l.Clear()
-
- i=s.ReadInt()
-
- For Local f=0 Until i
- l.AddLast(TVectorGfxLine.Load(s))
- Next
-
- o.SetLines(l.ToArray())
-
- 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(points.length)
- For Local p:TVectorGfxPoint=EachIn points
- p.Save(s)
- Next
-
- s.WriteInt(lines.length)
- For Local l:TVectorGfxLine=EachIn lines
- l.Save(s)
- Next
-
- s.Close()
- End Method
-
- Rem
- bbdoc: Draw the object, not bothering about collisions.
- EndRem
- Method Draw()
- rotated=New TVectorGfxPoint[points.length]
-
- For Local f:Int=0 Until points.length
- Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
- rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
- Next
-
- For Local l:TVectorGfxLine=EachIn lines
- Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,0,Self,0,Null,True,Null)
- Next
- End Method
-
- Rem
- bbdoc: Draw the object, using the collision map routines.
- returns: A bitmask of collisions.
- about: Draws the object. If @colmap is null then no collision processing takes place.
- about: If @actor is true then collision processing takes place, but the object will
- about: not write into the collision map.
- about: If @list is not null then any collisions will be written into this list. This only applies if @colmap is set and @actor true.
- EndRem
- Method DrawToCollisionMap:Int(colmap:TVectorGfxCollisionMap=Null, actor:Int=False, list:TList=Null)
- Local col:Int=0
-
- rotated=New TVectorGfxPoint[points.length]
-
- For Local f:Int=0 Until points.length
- Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
- rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
- Next
-
- Local i:Int=0
-
- For Local l:TVectorGfxLine=EachIn lines
- col:|Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,l.id,Self,i,colmap,actor,list)
- i:+1
- Next
-
- Return col
- End Method
-
- Rem
- bbdoc: Draw the object, using returning a point list.
- returns: The list of points plotted as @TVectorGfxPoint objects.
- EndRem
- Method DrawToPointList:TList()
- Local list:TList=CreateList()
- Local col:Int=0
-
- rotated=New TVectorGfxPoint[points.length]
-
- For Local f:Int=0 Until points.length
- Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
- rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
- Next
-
- Local i:Int=0
-
- For Local l:TVectorGfxLine=EachIn lines
- col:|Static.linedraw.LineToPointList(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,list)
- i:+1
- Next
-
- Return list
- End Method
-End Type
-
-Rem
-bbdoc: Defines a point
-EndRem
-Type TVectorGfxPoint
- Rem
- bbdoc: The X co-ordinate of the point
- EndRem
- Field x:Int
- Rem
- bbdoc: The Y co-ordinate of the point
- EndRem
- Field y:Int
-
- Rem
- bbdoc: Create a point.
- returns: The created point.
- about: @x and @y are the co-ordinates of the point.
- EndRem
- Function Create:TVectorGfxPoint(x:Int, y:Int)
- Local o:TVectorGfxPoint=New TVectorGfxPoint
- o.x=x
- o.y=y
- Return o
- End Function
-
- Function Load:TVectorGfxPoint(s:TStream)
- Local o:TVectorGfxPoint
- o=New TVectorGfxPoint
- o.x=s.ReadInt()
- o.y=s.ReadInt()
- Return o
- End Function
-
- Method Save(s:TStream)
- s.WriteInt(x)
- s.WriteInt(y)
- End Method
-End Type
-
-Rem
-bbdoc: Defines a line
-EndRem
-Type TVectorGfxLine
- Field i1:Int
- Field i2:Int
- Field id:Int
- Field r:Int
- Field g:Int
- Field b:Int
-
- Rem
- bbdoc: Create a line.
- returns: The created line.
- about: @i1 and @i2 are the indexes into the point list. @r, @g and @b is the line's colour. @id is the collision map mask for the line.
- EndRem
- Function Create:TVectorGfxLine(i1:Int, i2:Int, r:Int, g:Int, b:Int, id:Int)
- Local o:TVectorGfxLine=New TVectorGfxLine
-
- o.i1=i1
- o.i2=i2
- o.r=r
- o.g=g
- o.b=b
- o.id=id
-
- Return o
- End Function
-
- Function Load:TVectorGfxLine(s:TStream)
- Local o:TVectorGfxLine
- o=New TVectorGfxLine
- o.i1=s.ReadInt()
- o.i2=s.ReadInt()
- o.r=s.ReadInt()
- o.g=s.ReadInt()
- o.b=s.ReadInt()
- o.id=s.ReadInt()
- Return o
- End Function
-
- Method Save:TVectorGfxLine(s:TStream)
- s.WriteInt(i1)
- s.WriteInt(i2)
- 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 LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList)
- Local mask:Int=0
- Local lp:TList=DoLine(x1,y1,x2,y2)
-
- SetColor(r,g,b)
-
- For Local p:TAlgoPoint=EachIn lp
- If colmap
- If actor
- Local c:TVectorGfxCollision=colmap.GetCollision(p.x,p.y)
-
- If c
- mask:|c.mask
- If list
- list.AddLast(c)
- EndIf
- EndIf
- Else
- mask:|colmap.SetCollision(p.x,p.y,id,obj,line)
- EndIf
- EndIf
- Plot(p.x,p.y)
- Next
-
- Return mask
- End Method
-
- Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList)
- Local mask:Int=0
- Local lp:TList=DoLine(x1,y1,x2,y2)
-
- SetColor(r,g,b)
-
- For Local p:TAlgoPoint=EachIn lp
- Plot(p.x,p.y)
- list.AddLast(TVectorGfxPoint.Create(p.x,p.y))
- Next
-
- Return mask
- End Method
-End Type
-
-Static.Init()
+' Copyright (c) 2006 Ian Cowburn
+'
+' Permission is hereby granted, free of charge, to any person obtaining a copy of
+' this software and associated documentation files (the "Software"), to deal in
+' the Software without restriction, including without limitation the rights to
+' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+' of the Software, and to permit persons to whom the Software is furnished to do
+' so, subject to the following conditions:
+'
+' The above copyright notice and this permission notice shall be included in all
+' copies or substantial portions of the Software.
+'
+' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+' SOFTWARE.
+'
+' $Id$
+'
+Rem
+bbdoc: noddybox.vectorgfx
+EndRem
+Module noddybox.vectorgfx
+
+ModuleInfo "Framework: 2D Vector Graphics classes"
+ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
+ModuleInfo "Author: Ian Cowburn"
+ModuleInfo "Version: $Revision$"
+
+Import brl.linkedlist
+Import brl.math
+Import brl.endianstream
+Import brl.max2d
+Import noddybox.vector
+Import noddybox.algorithm
+
+Rem
+bbdoc: Wibble
+about: Wobble
+EndRem
+
+Rem
+bbdoc: Defines a method for drawing vector lines
+about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module.
+EndRem
+Type TVectorGfxLineStyle Abstract
+ Rem
+ bbdoc: Draws a vector line using IDs and @TVectorGfxCollisionMap method.
+ returns: The or'ed mask of all collision IDs overwritten in @colmap by this line, or zero if @colmap is null.
+ about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b.
+ about: @id, @obj and @line must be written into the collision map @colmap if @colmap is not null and @actor is false.
+ about: If @colmap is set and @actor true, then collisions must be returned but no points written into the collision map.
+ about: If @colmap is set, @actor is true and @list is not null then any collisions should be recorded into this list
+ about: (no requirement for duplicate checking).
+ EndRem
+ Method LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList) Abstract
+
+ Rem
+ bbdoc: Draws a vector line using the point list method.
+ about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b.
+ about: If list is not null, then the points drawn must be stored in the list as @TVectorGfxPoint objects.
+ about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module.
+ EndRem
+ Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList) 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 a custom drawing method.
+EndRem
+Function VectorGfxSetCustom(linedraw:TVectorGfxLineStyle)
+ Static.linedraw=linedraw
+End Function
+
+Rem
+bbdoc: Defines a point in the vector graphics collision map.
+EndRem
+Type TVectorGfxCollision
+ Rem
+ bbdoc: The X co-ordinate of this collision (in the object co-ordinate space).
+ EndRem
+ Field x:Int
+
+ Rem
+ bbdoc: The Y co-ordinate of this collision (in the object co-ordinate space).
+ EndRem
+ Field y:Int
+
+ Rem
+ bbdoc: The collision masks at this point.
+ EndRem
+ Field mask:Int
+
+ Rem
+ bbdoc: The last vector object that wrote at this point.
+ EndRem
+ Field obj:TVectorGfxObject
+
+ Rem
+ bbdoc: The index of the line in the last vector object that wrote at this point.
+ EndRem
+ Field line:Int
+
+ Function Create:TVectorGfxCollision(x:Int, y:Int, mask:Int, obj:TVectorGfxObject, line:Int)
+ Local o:TVectorGfxCollision=New TVectorGfxCollision
+ o.x=x
+ o.y=y
+ o.mask=mask
+ o.obj=obj
+ o.line=line
+ Return o
+ End Function
+End Type
+
+
+Rem
+bbdoc: Defines a vector graphics collision map.
+about: Collisions using this method in the library are 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:TVectorGfxCollision[,]
+
+ 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.Clear()
+ 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: Get a collision point.
+ returns: The collision point, or null if nothing drawn there.
+ about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space)
+ EndRem
+ Method GetCollision:TVectorGfxCollision(x:Int, y:Int)
+ If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height
+ Return Null
+ Else
+ Return data[x-xoff,y-yoff]
+ EndIf
+ 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:Int(x:Int, y:Int, id:Int, obj:TVectorGfxObject, line:Int)
+ If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height
+ Return 0
+ EndIf
+
+ Local ax:Int=x-xoff
+ Local ay:Int=y-yoff
+
+ Local cur:TVectorGfxCollision=data[ax,ay]
+
+ If Not cur
+ cur=TVectorGfxCollision.Create(x,y,id,obj,line)
+ data[ax,ay]=cur
+ Else
+ cur.mask:|id
+ cur.obj=obj
+ cur.line=line
+ EndIf
+
+ Return cur.mask
+ End Method
+
+ Rem
+ bbdoc: Clear the collision map
+ EndRem
+ Method Clear()
+ data=New TVectorGfxCollision[width,height]
+ End Method
+End Type
+
+
+Rem
+bbdoc: Defines a 2D vector graphics object
+EndRem
+Type TVectorGfxObject
+ Rem
+ bbdoc: The points making up this object
+ EndRem
+ Field points:TVectorGfxPoint[]
+ Rem
+ bbdoc: The lines making up this object
+ EndRem
+ Field lines:TVectorGfxLine[]
+ 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 minimum X co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field min_x:Int
+ Rem
+ bbdoc: The maximum X co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field max_x:Int
+ Rem
+ bbdoc: The minimum Y co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field min_y:Int
+ Rem
+ bbdoc: The maximum Y co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field max_y:Int
+ Rem
+ bbdoc: The width of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field width:Int
+ Rem
+ bbdoc: The height of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field height: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: The scale of the object.
+ EndRem
+ Field scale:Double
+
+ Field rotated:TVectorGfxPoint[]
+
+ Rem
+ bbdoc: Creates a new empty object
+ returns: The created object.
+ EndRem
+ Method New()
+ points=Null
+ lines=Null
+ rotated=Null
+ x=0
+ y=0
+ min_x=9999999
+ min_y=9999999
+ max_x=-9999999
+ max_y=-9999999
+ width=0
+ height=0
+ ang=0
+ scale=1
+ End Method
+
+ Rem
+ bbdoc: Clones this object
+ about: Returns a copy of this object, with its own copy of the line and points.
+ EndRem
+ Method Clone:TVectorGfxObject()
+ Local o:TVectorGfxObject=New TVectorGfxObject
+ o.x=x
+ o.y=y
+ o.min_x=min_x
+ o.min_y=min_y
+ o.max_x=max_x
+ o.max_y=max_y
+ o.width=width
+ o.height=height
+ o.ang=ang
+ o.scale=scale
+ o.SetPoints(points)
+ o.SetLines(lines)
+ Return o
+ End Method
+
+ Rem
+ bbdoc: Sets the points for this object
+ about: @pa is an array of points for this object.
+ EndRem
+ Method SetPoints(pa:Object[])
+ points=New TVectorGfxPoint[pa.length]
+ For Local f:Int=0 Until pa.length
+ points[f]=TVectorGfxPoint(pa[f])
+ min_x=Min(min_x,points[f].x)
+ min_y=Min(min_y,points[f].y)
+ max_x=Max(max_x,points[f].x)
+ max_y=Max(max_y,points[f].y)
+ Next
+ width=max_x-min_x
+ height=max_y-min_y
+ End Method
+
+ Rem
+ bbdoc: Sets the lines for this object.
+ about: @la is the array of lines for this object.
+ EndRem
+ Method SetLines(la:Object[])
+ lines=New TVectorGfxLine[la.length]
+ For Local f:Int=0 Until la.length
+ lines[f]=TVectorGfxLine(la[f])
+ Next
+ End Method
+
+ Rem
+ bbdoc: Whether a point is inside the object
+ returns: True if the point lies inside the object. The object is assumed to be a closed polygon for this test.
+ about: @cx, @cy is the point to test.
+ about: This routine is based on code from comp.graphics.algorithms FAQ 2.03
+ EndRem
+ Method IsInside:Int(cx:Int, cy:Int)
+ If rotated=Null
+ Return False
+ EndIf
+
+ Local cross:Int=False
+
+ For Local l:TVectorGfxLine=EachIn lines
+ Local x1:Int=x+rotated[l.i1].x
+ Local y1:Int=y+rotated[l.i1].y
+ Local x2:Int=x+rotated[l.i2].x
+ Local y2:Int=y+rotated[l.i2].y
+
+ If ((((y1<=cy) And (cy<y2)) Or ((y2<=cy) And (cy<y1))) And (cx < (x2 - x1) * (cy - y1) / (y2 - y1) + x1))
+ cross=Not cross
+ EndIf
+ Next
+
+ Return cross
+ End Method
+
+ Rem
+ bbdoc: A line's adjusted co-ordinates.
+ returns: The rotated and scaled points (in object co-ordinates) of the line.
+ about: @i is the index of the line to return the points for.
+ about: Calling it before drawing the object will return null.
+ EndRem
+ Method AdjustedCoords:TVectorGfxPoint[](i:Int)
+ If rotated=Null
+ Return Null
+ EndIf
+
+ Local p:TVectorGfxPoint[]=New TVectorGfxPoint[2]
+ Local l:TVectorGfxLine=lines[i]
+ p[0]=rotated[l.i1]
+ p[1]=rotated[l.i2]
+ Return p
+ End Method
+
+ Rem
+ bbdoc: A line's normal.
+ returns: The normal of the selected line.
+ about: @i is the index of the line to return the normal of. This will return the normal due to the rotation of the object after the object is drawn.
+ about: Calling it before drawing the object will return null.
+ EndRem
+ Method Normal:TVector(i:Int)
+ If rotated=Null
+ Return Null
+ EndIf
+
+ Local l:TVectorGfxLine=lines[i]
+ Local v:TVector=TVector.Create(rotated[l.i2].y-rotated[l.i1].y,rotated[l.i1].x-rotated[l.i2].x)
+ v.Normalise()
+ Return v
+ 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 l:TList=CreateList()
+ Local i:Int=s.ReadInt()
+
+ For Local f=0 Until i
+ l.AddLast(TVectorGfxPoint.Load(s))
+ Next
+
+ o.SetPoints(l.ToArray())
+
+ l.Clear()
+
+ i=s.ReadInt()
+
+ For Local f=0 Until i
+ l.AddLast(TVectorGfxLine.Load(s))
+ Next
+
+ o.SetLines(l.ToArray())
+
+ 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(points.length)
+ For Local p:TVectorGfxPoint=EachIn points
+ p.Save(s)
+ Next
+
+ s.WriteInt(lines.length)
+ For Local l:TVectorGfxLine=EachIn lines
+ l.Save(s)
+ Next
+
+ s.Close()
+ End Method
+
+ Rem
+ bbdoc: Draw the object, not bothering about collisions.
+ EndRem
+ Method Draw()
+ rotated=New TVectorGfxPoint[points.length]
+
+ For Local f:Int=0 Until points.length
+ Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
+ rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
+ Next
+
+ For Local l:TVectorGfxLine=EachIn lines
+ Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,0,Self,0,Null,True,Null)
+ Next
+ End Method
+
+ Rem
+ bbdoc: Draw the object, using the collision map routines.
+ returns: A bitmask of collisions.
+ about: Draws the object. If @colmap is null then no collision processing takes place.
+ about: If @actor is true then collision processing takes place, but the object will
+ about: not write into the collision map.
+ about: If @list is not null then any collisions will be written into this list. This only applies if @colmap is set and @actor true.
+ EndRem
+ Method DrawToCollisionMap:Int(colmap:TVectorGfxCollisionMap=Null, actor:Int=False, list:TList=Null)
+ Local col:Int=0
+
+ rotated=New TVectorGfxPoint[points.length]
+
+ For Local f:Int=0 Until points.length
+ Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
+ rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
+ Next
+
+ Local i:Int=0
+
+ For Local l:TVectorGfxLine=EachIn lines
+ col:|Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,l.id,Self,i,colmap,actor,list)
+ i:+1
+ Next
+
+ Return col
+ End Method
+
+ Rem
+ bbdoc: Draw the object, using returning a point list.
+ returns: The list of points plotted as @TVectorGfxPoint objects.
+ EndRem
+ Method DrawToPointList:TList()
+ Local list:TList=CreateList()
+ Local col:Int=0
+
+ rotated=New TVectorGfxPoint[points.length]
+
+ For Local f:Int=0 Until points.length
+ Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
+ rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
+ Next
+
+ Local i:Int=0
+
+ For Local l:TVectorGfxLine=EachIn lines
+ col:|Static.linedraw.LineToPointList(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,list)
+ i:+1
+ Next
+
+ Return list
+ End Method
+End Type
+
+Rem
+bbdoc: Defines a point
+EndRem
+Type TVectorGfxPoint
+ Rem
+ bbdoc: The X co-ordinate of the point
+ EndRem
+ Field x:Int
+ Rem
+ bbdoc: The Y co-ordinate of the point
+ EndRem
+ Field y:Int
+
+ Rem
+ bbdoc: Create a point.
+ returns: The created point.
+ about: @x and @y are the co-ordinates of the point.
+ EndRem
+ Function Create:TVectorGfxPoint(x:Int, y:Int)
+ Local o:TVectorGfxPoint=New TVectorGfxPoint
+ o.x=x
+ o.y=y
+ Return o
+ End Function
+
+ Function Load:TVectorGfxPoint(s:TStream)
+ Local o:TVectorGfxPoint
+ o=New TVectorGfxPoint
+ o.x=s.ReadInt()
+ o.y=s.ReadInt()
+ Return o
+ End Function
+
+ Method Save(s:TStream)
+ s.WriteInt(x)
+ s.WriteInt(y)
+ End Method
+End Type
+
+Rem
+bbdoc: Defines a line
+EndRem
+Type TVectorGfxLine
+ Field i1:Int
+ Field i2:Int
+ Field id:Int
+ Field r:Int
+ Field g:Int
+ Field b:Int
+
+ Rem
+ bbdoc: Create a line.
+ returns: The created line.
+ about: @i1 and @i2 are the indexes into the point list. @r, @g and @b is the line's colour. @id is the collision map mask for the line.
+ EndRem
+ Function Create:TVectorGfxLine(i1:Int, i2:Int, r:Int, g:Int, b:Int, id:Int)
+ Local o:TVectorGfxLine=New TVectorGfxLine
+
+ o.i1=i1
+ o.i2=i2
+ o.r=r
+ o.g=g
+ o.b=b
+ o.id=id
+
+ Return o
+ End Function
+
+ Function Load:TVectorGfxLine(s:TStream)
+ Local o:TVectorGfxLine
+ o=New TVectorGfxLine
+ o.i1=s.ReadInt()
+ o.i2=s.ReadInt()
+ o.r=s.ReadInt()
+ o.g=s.ReadInt()
+ o.b=s.ReadInt()
+ o.id=s.ReadInt()
+ Return o
+ End Function
+
+ Method Save:TVectorGfxLine(s:TStream)
+ s.WriteInt(i1)
+ s.WriteInt(i2)
+ 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 LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList)
+ Local mask:Int=0
+ Local lp:TList=DoLine(x1,y1,x2,y2)
+
+ SetColor(r,g,b)
+
+ For Local p:TAlgoPoint=EachIn lp
+ If colmap
+ If actor
+ Local c:TVectorGfxCollision=colmap.GetCollision(p.x,p.y)
+
+ If c
+ mask:|c.mask
+ If list
+ list.AddLast(c)
+ EndIf
+ EndIf
+ Else
+ mask:|colmap.SetCollision(p.x,p.y,id,obj,line)
+ EndIf
+ EndIf
+ Plot(p.x,p.y)
+ Next
+
+ Return mask
+ End Method
+
+ Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList)
+ Local mask:Int=0
+ Local lp:TList=DoLine(x1,y1,x2,y2)
+
+ SetColor(r,g,b)
+
+ For Local p:TAlgoPoint=EachIn lp
+ Plot(p.x,p.y)
+ list.AddLast(TVectorGfxPoint.Create(p.x,p.y))
+ Next
+
+ Return mask
+ End Method
+End Type
+
+Static.Init()