/' Copyright (c) 2007 Scott Lembcke
 * 
 * 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.
 '/

'' Forward declarations required for defining other structs.
type cpShapePTR as cpShape ptr
type cpShapeClassPTR as cpShapeClass ptr


type cpSegmentQueryInfo
	as cpShapePTR	shape	'' shape that was hit, NULL if no collision
	as cpFloat	t		'' Distance along query segment, will always be in the range [0, 1].
	as cpVect	n		'' normal of hit surface
end type

enum cpShapeType
	CP_CIRCLE_SHAPE
	CP_SEGMENT_SHAPE
	CP_POLY_SHAPE
	CP_NUM_SHAPES
end enum

'' Shape class. Holds function pointers and type data.
type cpShapeClass
	as cpShapeType	type
	
	'' Called by cpShapeCacheBB().
	cacheData as function cdecl( byval as cpShapePTR, byval as cpVect, byval as cpVect ) as cpBB
	'' Called to by cpShapeDestroy().
	destroy as sub cdecl( byval as cpShapePTR )
	
	'' called by cpShapePointQuery().
	pointQuery as function cdecl( byval as cpShapePTR, byval as cpVect ) as cpBool
	
	'' called by cpShapeSegmentQuery()
	segmentQuery as sub cdecl( byval as cpShapePTR, byval as cpVect, byval as cpVect, byval as cpSegmentQueryInfo ptr )
end type


' Basic shape struct that the others inherit from.
type cpShape
	'' The "class" of a shape as defined above 
	klass	as const cpShapeClass ptr

	'' cpBody that the shape is attached to.
	as cpBody ptr	body

	'' Cached BBox for the shape.
	as cpBB			bb
	
	'' Sensors invoke callbacks, but do not generate collisions
	as cpBool		sensor
	
	'' *** Surface properties.
	
	'' Coefficient of restitution. (elasticity)
	as cpFloat		e
	'' Coefficient of friction.
	as cpFloat		u
	'' Surface velocity used when solving for friction.
	as cpVect		surface_v

	'' *** User Definable Fields

	'' User defined data pointer for the shape.
	as cpDataPointer	data
	
	'' User defined collision type for the shape.
	as cpCollisionType	collision_type
	'' User defined collision group for the shape.
	as cpGroup			group
	'' User defined layer bitmask for the shape.
	as cpLayers			layers
	
	'' *** Internally Used Fields
	
	'' Shapes form a linked list when added to space on a non-NULL body
	as cpShapePTR		next
	
	'' Unique id used as the hash value.
	as cpHashValue	hashid
end type

' Low level shape initialization func.
declare function cpShapeInit cdecl alias "cpShapeInit" ( byval shape as cpShape ptr, byval stype as cpShapeType, byval body as cpBody ptr ) as cpShape ptr

' Basic destructor functions. (allocation functions are not shared)
declare sub cpShapeDestroy cdecl alias "cpShapeDestroy" ( byval shape as cpShape ptr )
declare sub cpShapeFree cdecl alias "cpShapeFree" ( byval shape as cpShape ptr )

' Cache the BBox of the shape.
declare function cpShapeCacheBB cdecl alias "cpShapeCacheBB" ( byval shape as cpShape ptr ) as cpBB

'' Test if a point lies within a shape.
declare function cpShapePointQuery cdecl alias "cpShapePointQuery" ( byval as cpShape ptr, byval as cpVect ) as cpBool

' Cannot modify data in strings, so these #defines have been replaced and are now translated manually
'#define CP_DeclareShapeGetter(typename, typereturn, name) declare function typename##Get##name cdecl alias "typename##Get##name" ( byval shape as cpShape ptr ) as typereturn

' Circle shape structure.
type cpCircleShape
	as cpShape	shape
		
	' Center. (body space coordinates)
	as cpVect	c
	' Radius.
	as cpFloat	r
	
	' Transformed center. (world space coordinates)
	as cpVect	tc
end type

' Basic allocation functions for cpCircleShape.
declare function cpCircleShapeAlloc cdecl alias "cpCircleShapeAlloc" ( ) as cpCircleShape ptr
declare function cpCircleShapeInit cdecl alias "cpCircleShapeInit" ( byval circle as cpCircleShape ptr, byval body as cpBody ptr, byval radius as cpFloat, byval offset as cpVect ) as cpCircleShape ptr
declare function cpCircleShapeNew cdecl alias "cpCircleShapeNew" ( byval body as cpBody ptr, byval radius as cpFloat, byval offset as cpVect ) as cpShape ptr

declare function cpCircleShapeGetOffset cdecl alias "cpCircleShapeGetOffset" ( byval shape as cpShape ptr ) as cpVect
declare function cpCircleShapeGetRadius cdecl alias "cpCircleShapeGetRadius" ( byval shape as cpShape ptr ) as cpFloat

'' Segment shape structure.
type cpSegmentShape
	as cpShape	shape
	
	'' Endpoints and normal of the segment. (body space coordinates)
	as cpVect	a, b, n
	'' Radius of the segment. (Thickness)
	as cpFloat	r

	'' Transformed endpoints and normal. (world space coordinates)
	as cpVect	ta, tb, tn
end type

' Basic allocation functions for cpSegmentShape.
declare function cpSegmentShapeAlloc cdecl alias "cpSegmentShapeAlloc" ( ) as cpSegmentShape ptr
declare function cpSegmentShapeInit cdecl alias "cpSegmentShapeInit" ( byval as cpSegmentShape ptr, byval as cpBody ptr, byval as cpVect, byval as cpVect, byval as cpFloat ) as cpSegmentShape ptr
declare function cpSegmentShapeNew cdecl alias "cpSegmentShapeNew" ( byval as cpBody ptr, byval as cpVect, byval as cpVect, byval as cpFloat ) as cpShape ptr

declare function cpSegmentShapeGetA cdecl alias "cpSegmentShapeGetA" ( byval shape as cpShape ptr ) as cpVect
declare function cpSegmentShapeGetB cdecl alias "cpSegmentShapeGetB" ( byval shape as cpShape ptr ) as cpVect
declare function cpSegmentShapeGetNormal cdecl alias "cpSegmentShapeGetNormal" ( byval shape as cpShape ptr ) as cpVect
declare function cpSegmentShapeGetRadius cdecl alias "cpSegmentShapeGetRadius" ( byval shape as cpShape ptr ) as cpFloat

'' For determinism, you can reset the shape id counter.
declare sub cpResetShapeIdCounter cdecl alias "cpResetShapeIdCounter" ()

'' Directed segment queries against individual shapes.
declare sub cpSegmentQueryInfoPrint cdecl alias "cpSegmentQueryInfoPrint" ( byval as cpSegmentQueryInfo ptr )

declare function cpShapeSegmentQuery cdecl alias "cpShapeSegmentQuery" ( byval as cpShape ptr, byval as cpVect, byval as cpVect, byval as cpSegmentQueryInfo ptr ) as cpBool

function cpSegmentQueryHitPoint cdecl alias "cpSegmentQueryHitPoint" ( byval s as cpVect, byval e as cpVect, byval info as cpSegmentQueryInfo ) as cpVect
	return cpvlerp( s, e, info.t )
end function

function cpSegmentQueryHitDist cdecl alias "cpSegmentQueryHitDist" ( byval s as cpVect, byval e as cpVect, byval info as cpSegmentQueryInfo ) as cpFloat
	return cpvdist( s, e ) * info.t
end function

