From 6c0b11a6bb632a5c7cd29ad8a92ce31fe929c194 Mon Sep 17 00:00:00 2001 From: Ian C Date: Wed, 8 Apr 2020 21:23:22 +0000 Subject: Removed Strict -- doesn't seem to like it anymore. --- vectorgfx.mod/vectorgfx.bmx | 1365 +++++++++++++++++++++---------------------- 1 file changed, 682 insertions(+), 683 deletions(-) (limited to 'vectorgfx.mod') 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+width 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+width 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=xoff+width 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+width 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