/****************************************************************************************/
/*  ACTOR.H                                                                             */
/*                                                                                      */
/*  Author: Mike Sandige	                                                            */
/*  Description:  Actor interface		                                                */
/*                                                                                      */
/*  The contents of this file are subject to the Jet3D Public License                   */
/*  Version 1.02 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.jet3d.com                                                                */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  The Original Code is Jet3D, released December 12, 1999.                             */
/*  Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved           */
/*                                                                                      */
/****************************************************************************************/
/*   Actor
	
	This object is designed to support character animation.
	There are two basic objects to deal with.  
	
	Actor Definition (jeActor_Def)
		A jeActor_Def embodies the geometry (polygon, and bone information), 
		and a library of motions that can be applied to that geometry.

	Actor
		A jeActor is an instance of an actor definition.  The definition is used for 
		the geometry, but all additional settings, such as the bone pose, lighting information,
		and cuing information is unique for a jeActor.
	An Actor Definition is created either from an existing Actor Definition file, or from scratch by 
	first creating a jeBody and jeMotions and selecting these into an Actor.  If the Actor Definition
	is constructed from scratch, the objects selected into it (via SetBody and AddMotion) are
	then 'owned' by the actor and will be destroyed along with the Actor when it is destroyed.
    Of course, when the Actor is loaded from a file, the Body and Motion it creates as it is
	loaded are cleaned up when the Actor is destroyed.

	Once an Actor is created, prepare it for rendering and animating by calling 
	Actor_RenderPrep().  This must be called (and it must succeed) before any render or
	pose setting functions can be called.

	There are two ways to use an Actor.
	Direct Control
		One method is to directly control the skeleton configuration.  Use _SetPose() to set its 
		skeleton using a jeMotion animation.  The pose is positioned in world space relative to the 
		transform given in SetPose().  Whenever a new skeleton pose is required, call _SetPose() 
		to reposition the skeleton for a new point in time. 

		More complex positioning can be achieved by blending more than one animation.  Use
		_BlendPose() after a _SetPose() to blend the second jeMotion into the first.  Additional
		blends can be applied by additional _BlendPose() calls.  Each blend is performed on the
		the existing skeleton (the results of any previous blends).
	Cuing
		Another method is to 'cue' up motions that are applied with parameterized blending over time.
		A cued motion takes effect 'now' in time.  The Actor advances in time and repositions itself
		according to its currently cued motions with a call to _AnimationStep().  AnimationStep() 
		redefines what the actor thinks 'now' is.  This causes historical cues to be forgotten, and 
		motions that are no longer valid are cleaned up.  AnimationTestStep() can be used to position 
		the actor for potential queries with its currently cued motions at some arbitrary future time 
		- relative to the last AnimationTestStep() call.  AnimationNudge() applies a given transform 
		'instantly' to the current actor's cue list.  This is usefull for moving the actor as a 
		result of a collision with another object.

	If a motion contains joint information that does not exactly match the Actor's skeleton 
	joints, only the joints that match by name are applied.  So a jeMotion can be applied to
	a portion of the Actor, or a jeMotion that has more joint information than the skeleton can
	be applied and the extra joint information is ignored.  
	 
	Examples of this:  If the Actor is a biped and has no tail, but the motion is for a 
	biped with a tail, the jeMotion can be applied, but the tail information will be ignored.
	Also if there is a jeMotion for only a left arm, it can be applied and it will only affect
	the left arm of the Actor, and consequently its left hand and fingers, but no other 
	bones that are not children of the affected bones will be changed.

	*call setscale and setshadow after preparing the actor for rendering (renderprep)
	 	
*/

#ifndef JE_ACTOR_H
#define JE_ACTOR_H

#include "BaseType.h"
#include "ExtBox.h"
#include "Bitmap.h"

#include "Motion.h"
#include "Camera.h"
#include "jeFrustum.h"

#include "Body.h"

#include "jeWorld.h"
#include "Engine.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifndef JE_ACTOR_ENUMS
#define JE_ACTOR_ENUMS
typedef enum 
{
		JE_ACTOR_BLEND_LINEAR,		// Treats the blending amount as a linear value
		JE_ACTOR_BLEND_HERMITE		// Applies a parametric smoothing curve to the blending amount
									//  so that a linear change in BlendAmount parameters will
									//  result in a smooth (non-linear) change in blending.
} jeActor_BlendingType;

#endif

typedef struct jeActor jeActor;			// an instance of an actor
typedef struct jeActor_Def jeActor_Def;		// the deinition of an actor's geometry/bone structure

//	[MacroArt::Begin]
//	Thanks Dee(cryscan@home.net)	
JETAPI float JETCC jeActor_GetAlpha(const jeActor *A);
JETAPI void JETCC jeActor_SetAlpha(jeActor *A, float Alpha);
//	[MacroArt::End]


//---------------------------------------------------------------------------------
//   Creation/Destruction functions
//---------------------------------------------------------------------------------
	// Create an 'empty' Actor Definition.
JETAPI jeActor_Def *JETCC jeActor_DefCreate(void);

	// Create an Actor Definition from a file image.
JETAPI jeActor_Def *JETCC jeActor_DefCreateFromFile(jeVFile *pFile);

	// Create an additional reference (owner) for the Actor_Definition
JETAPI void JETCC jeActor_DefCreateRef(jeActor_Def *pActorDefinition);

	// Destroy a jeActor_Def (its jeBody and its jeMotions)  Actors that rely on this definition become invalid.
	// can fail if there are actors still referencing this definition.
JETAPI jeBoolean JETCC jeActor_DefDestroy(jeActor_Def **pActorDefinition);

	// Create an Actor instance associated with the given Actor Definition 
	//JETAPI jeActor *JETCC jeActor_Create(jeActor_Def *ActorDefinition);
	//JETAPI jeActor *JETCC jeActor_Create(void);

// Incarnadine:  The above function should be considered obsolete.  It is used internally by the system,
// but shouldn't be used by the end-user.  The proper way to create an actor is via jeObject_Create("Actor").
// If you need direct access to the actor, use:  pActor = (jeActor*)jeObject_GetInstance(pObject);
//
// Example Actor Creation:
// ---------------------------------------
//	jeObject* pJetObject = jeObject_Create("Actor");
//	jeActor* pActor = (jeActor*)jeObject_GetInstance(pJetObject);
//	jeActor_SetActorDef(pActor,pActorDef);
//	jeWorld_AddObject(pWorld, pJetObject);

	// Create an additional reference (owner) for the Actor
JETAPI void JETCC jeActor_CreateRef(jeActor *Actor);

	// Give the Actor Definition a Body.  jeActor becomes responsible for its destruction.
	// sets up default materials as referenced by the Body.
JETAPI jeBoolean JETCC jeActor_SetBody( jeActor_Def *ActorDefinition, jeBody *jeBodyGeometry);

	// Adds a jeMotion to the Actor Definition's library.  The ActorDefinition becomes responsible for its destruction.
	// returns the library index to the new jeMotion.
JETAPI jeBoolean JETCC jeActor_AddMotion(jeActor_Def *ActorDefinition, jeMotion *M, int *Index);

	// Destroy an Actor.  
JETAPI jeBoolean JETCC jeActor_Destroy(jeActor **pA);

JETAPI jeBoolean JETCC jeActor_DefIsValid(const jeActor_Def *A);
JETAPI jeBoolean JETCC jeActor_IsValid(const jeActor *A);

//---------------------------------------------------------------------------------
//   Queries 
//---------------------------------------------------------------------------------

	// In general: Objects retuned from Get functions should not not be destroyed. 
	// if ownership is desired, call the objects _CreateRef() function to create another owner. 
	// (An 'owner' has access to the object regardless of the number of other owners, and 
	// an owner must call the object's _Destroy() function to relinquish ownership )

	// Returns the Actor Definition associated with Actor A
JETAPI jeActor_Def *JETCC jeActor_GetActorDef(const jeActor *A);

	// Writes an existing jeActor to a file image.  Returns JE_TRUE on success, JE_FALSE on failure.
JETAPI jeBoolean JETCC jeActor_DefWriteToFile(const jeActor_Def *A, jeVFile *pFile);
	
	// Returns a jeBody pointer from the jeActor 
JETAPI jeBody *JETCC jeActor_GetBody(const jeActor_Def *ActorDefinition);

	// Returns JE_TRUE if the actor definition has a bone named 'Name'
JETAPI jeBoolean JETCC jeActor_DefHasBoneNamed(const jeActor_Def *Ad, const char *Name );

	// Selects a blending type.  BlendingType only affects the meaning of the 
	// BlendAmount parameter for the blend functions.  Can be changed anytime.
JETAPI void JETCC jeActor_SetBlendingType( jeActor *A, jeActor_BlendingType BlendingType );

	// Returns the number of jeMotions in the jeActors jeMotion library.
JETAPI int JETCC jeActor_GetMotionCount(const jeActor_Def *ActorDefinition);

	// Returns a jeMotion pointer from the jeActors jeMotion library
	//   This is an aliased pointer - Not a copy.  Changes to this motion will be reflected
	//   in the actor.  Destroying this return motion will confuse the actor.
	// Index must be in range [0..jeActor_GetMotionCount-1]
JETAPI jeMotion *JETCC jeActor_GetMotionByIndex(const jeActor_Def *ActorDefinition, int Index );

	// Returns a jeMotion pointer from the jeActors jeMotion library
	//   This is an aliased pointer - Not a copy.  Changes to this motion will be reflected
	//   in the actor.  Destroying this return motion will confuse the actor.
	// if there is no motion that matches the given name, the return value will be NULL
JETAPI jeMotion *JETCC jeActor_GetMotionByName(const jeActor_Def *ActorDefinition, const char *Name );

	// Returns a motion name given an ActorDef and a motion index.
JETAPI const char *JETCC jeActor_GetMotionName(const jeActor_Def *ActorDefinition, int Index );

	// Returns the number of materials for an instance of an actor.
JETAPI int JETCC jeActor_GetMaterialCount(const jeActor *A);

	// Returns the current material for an instance of an actor
JETAPI jeBoolean JETCC jeActor_GetMaterial(const jeActor *Actor, int MaterialIndex,
										jeBitmap **Bitmap, jeFloat *Red, jeFloat *Green, jeFloat *Blue, jeUVMapper* pMapper);

	// Allows a material to be overriden in an actor instance
JETAPI jeBoolean JETCC jeActor_SetMaterial(jeActor *Actor, int MaterialIndex,
										jeBitmap *Bitmap,  jeFloat Red,  jeFloat Green,  jeFloat Blue, jeUVMapper Mapper);



	// Gets the current transform for a single bone in A.  (actor space->world space transform)
	// with a NULL BoneName, this returns the current 'root' transform
JETAPI jeBoolean JETCC jeActor_GetBoneTransform(const jeActor *A, const char *BoneName, jeXForm3d *Transform);
	
	// Gets the extent box (axial-aligned bounding box) for a given bone (for the current pose)
	// if BoneName is NULL, gets the a general bounding box from the body of the actor if it has been set.
JETAPI jeBoolean JETCC jeActor_GetBoneExtBox(const jeActor *A,
										 const char *BoneName,jeExtBox *ExtBox);

	// Gets the non-axial-aligned bounding box for a given bone (for the current pose)
	//  The box is specified by a corner, and
	//  a non-normalized orientation transform.  Add DX,DY,DZ components 
	//  of the orientation to get other corners of the box
	// if BoneName is NULL, gets the a general bounding box from the body of the actor if it has been set.
JETAPI jeBoolean JETCC jeActor_GetBoneBoundingBox(const jeActor *A,
														 const char *BoneName,
														 jeVec3d *Corner,
														 jeVec3d *DX,
														 jeVec3d *DY,
														 jeVec3d *DZ);

	// Gets the current axial-aligned bounding box for an actor's bone configuration
	// takes all bones into account
JETAPI jeBoolean JETCC jeActor_GetDynamicExtBox( const jeActor *A, jeExtBox *ExtBox);
	
	// Gets an assigned general non changing bounding box from the actor
JETAPI jeBoolean JETCC jeActor_GetExtBox(const jeActor *A, jeExtBox *ExtBox);

	// Sets an assigned general non changing bounding box from the actor
JETAPI jeBoolean JETCC jeActor_SetExtBox(jeActor *A, const jeExtBox *ExtBox,
					const char *CenterBoxOnThisNamedBone);		// NULL uses root position of actor

	// Gets the rendering hint bounding box from the actor
	//   if the RenderHintExtBox is disabled, Enabled is JE_FALSE, and the box returned has zero dimensions, 
	//   centered at the root position of the actor.  If the RenderHintExtBox is enabled, Enabled is
	//   JE_TRUE, and the box returned is the one set with _SetRenderHintExtBox, offset by the 
	//   bone position of the bone named in _SetRenderHintExtBox().
JETAPI jeBoolean JETCC jeActor_GetRenderHintExtBox(const jeActor *A, jeExtBox *Box, jeBoolean *Enabled);

	// Sets a rendering hint bounding box from the actor.  Increases performance by 
	//   enabling the rendering of the actor to occur only if the box is visible.
	//   If the box is not visible, a detailed analysis of the actor's current geometry is avoided.
	//   This does allow errors to occur: 
	//   If the actor has a bit of geometry that extends outside this box for some
	//   animation, that extended geometry may not be drawn, if the box if off-screen.   
	//   If the render hint box is not set, the engine will make no conservative assumptions 
	//   about the visibility of an actor - it will always be drawn if any portion of it is
	//   visible.
	//   To attach the box to the 'root' bone, pass NULL for CenterBoxOnThisNamedBone
	//   For disabling the hint box: (disabled is default) pass Box with zero mins and maxs
JETAPI jeBoolean JETCC jeActor_SetRenderHintExtBox(jeActor *A, const jeExtBox *Box,
												const char *CenterBoxOnThisNamedBone );


	// Returns the pointer which was set with jeActor_SetUserData.  NULL if not set.
JETAPI void *JETCC jeActor_GetUserData(const jeActor *A);

	// Sets the actors user data pointer to the given value.  For clients only.
JETAPI void JETCC jeActor_SetUserData(jeActor *A, void *UserData);


//--------------------------------------------------------------------------------
//   Posing and Rendering
//--------------------------------------------------------------------------------


	// Prepares the jeActor for rendering and posing.  Call Once once the actor is fully created.
	// Must be called prior to render/pose/setworldtransform 
JETAPI jeBoolean JETCC jeActor_AttachEngine( jeActor *A, jeEngine *pEngine);
JETAPI jeBoolean JETCC jeActor_DetachEngine(jeActor *A, jeEngine *pEngine);

	// Draws the jeActor.  (RenderPrep must be called first)
JETAPI jeBoolean JETCC jeActor_RenderThroughFrustum(
		const jeActor	*A, 
		jeEngine		*Engine, 
		jeWorld			*World, 
		jeCamera		*Camera, 
		const jeFrustum *Frustum);

	// force the actor to be re-lit with static lighting
JETAPI jeBoolean JETCC jeActor_Render(
		const jeActor	*A, 
		jeEngine		*Engine, 
		jeWorld			*World, 
		const jeCamera	*Camera);

JETAPI void jeActor_ForceStaticRelighting(jeActor* pActor);

	// Poses the actor in its default pose
	// Transform is where to position the root for this pose.
	//  if Transform is NULL, the root for the pose is assumed to be the root of the actor.
JETAPI void JETCC jeActor_ClearPose(jeActor *A, const jeXForm3d *Transform);

	// Poses the actor using given motion M at a time offset of Time
	// Transform is where to position the root for this pose.
	//  if Transform is NULL, the root for the pose is assumed to be the root of the actor.
JETAPI void JETCC jeActor_SetPose(jeActor *A, const jeMotion *Motion, jeFloat Time, const jeXForm3d *Transform);

	// Blends the current pose of the jeActor with 
	//  a new pose using motion M at a time offset of Time
	// A BlendAmount of 0 will result in the existing pose, A BlendAmount of 1 will
	// result in the new pose from M.  The BlendingType set by _SetBlendingType() determines
	// the blending function between 0 and 1
	// Transform is where to position the root for this pose.
	//  if Transform is NULL, the root for the pose is assumed to be the root of the actor.
JETAPI void JETCC jeActor_BlendPose(jeActor *A, const jeMotion *Motion, jeFloat Time,
						const jeXForm3d *Transform, jeFloat BlendAmount);


JETAPI jeBoolean JETCC jeActor_GetBoneAttachment(const jeActor *A, const char *BoneName, jeXForm3d *Transform);
JETAPI jeBoolean JETCC jeActor_SetBoneAttachment(jeActor *A, const char *BoneName, jeXForm3d *Transform);

JETAPI jeBoolean JETCC jeActor_Attach( jeActor *Slave,  const char *SlaveBoneName,
						const jeActor *Master, const char *MasterBoneName, 
						const jeXForm3d *Attachment);

JETAPI void JETCC jeActor_Detach(jeActor *Slave);


JETAPI jeBoolean JETCC jeActor_SetLightingOptions(jeActor *A,
									jeBoolean UseFillLight,				// JE_TRUE or JE_FALSE
									const jeVec3d *FillLightNormal,		// normalized vector
									jeFloat FillLightRed,				// 0 .. 255
									jeFloat FillLightGreen,				// 0 .. 255
									jeFloat FillLightBlue,				// 0 .. 255
									jeFloat AmbientLightRed,			// 0 .. 255
									jeFloat AmbientLightGreen,			// 0 .. 255
									jeFloat AmbientLightBlue,			// 0 .. 255
									jeBoolean AmbientLightFromFloor,	// JE_TRUE or JE_FALSE
									int MaximumDynamicLightsToUse,		// 0 for none
									int MaximumStaticLightsToUse, // 0 for none
									const char *LightReferenceBoneName,	//NULL for root
									jeBoolean PerBoneLighting);			
									// if JE_TRUE, then dynamic lighting attenuation and direction is computed
									// for each bone.  if JE_FALSE, then the computations are relative to the 
									// single bone named by the LightReferenceBoneName


JETAPI jeBoolean JETCC jeActor_GetLightingOptions(const jeActor *A,
									jeBoolean *UseFillLight,			// JE_TRUE or JE_FALSE
									jeVec3d *FillLightNormal,			// normalized vector
									jeFloat *FillLightRed,				// 0 .. 255
									jeFloat *FillLightGreen,			// 0 .. 255
									jeFloat *FillLightBlue,				// 0 .. 255
									jeFloat *AmbientLightRed,			// 0 .. 255
									jeFloat *AmbientLightGreen,			// 0 .. 255
									jeFloat *AmbientLightBlue,			// 0 .. 255
									jeBoolean *UseAmbientLightFromFloor,// JE_TRUE or JE_FALSE
									int *MaximumDynamicLightsToUse,
									int *MaximumStaticLightsToUse,		
									const char **LightReferenceBoneName,
									jeBoolean *PerBoneLighting);		// NULL for root


JETAPI void JETCC jeActor_SetScale(jeActor *A, jeFloat ScaleX,jeFloat ScaleY,jeFloat ScaleZ);

JETAPI jeBoolean JETCC jeActor_SetShadow(jeActor *A, 
						jeBoolean DoShadow, 
						jeFloat Radius,
						const jeBitmap *ShadowMap,
						const char * BoneName);

//  Animation Cuing API:
// high level Actor animation:  The principle is that motions can be applied to an actor
// and the actor will keep track of which motions are currently appropriate.  Call 
//	_AnimationStep() to compute a new pose for an elapsed time interval.  The new pose
//  will take into account all motions that are 'currently' cued up to be set or blended.


	// cue up a new motion.  The motion begins at the current time.  The motion can be 
	// blended in or out over time and time scaled.  If the return value is JE_FALSE, the 
	// animation was not cued up (failure implies Actor is incompletely initialized).
JETAPI jeBoolean JETCC jeActor_AnimationCue( 
		jeActor *A,						// actor to apply animation to
		jeMotion *Motion,				// motion to Cue
		jeFloat TimeScaleFactor,		// time scale to apply to cued motion
		jeFloat TimeIntoMotion,			// time offset to begin motion with (Not TimeScaled)
		jeFloat BlendTime,				// time to apply a blend. 
		jeFloat BlendFromAmount,		// blend value at current time
		jeFloat BlendToAmount,			// blend value after BlendTime time has elapsed
		const jeXForm3d *MotionTransform);	// local transform to adjust motion by (NULL implies NO transform)

	// removes the last animation cue that was cued up.  Can be called repeatedly to successively
	// remove older and older cues.  Returns JE_TRUE when a cue was removed, JE_FALSE if there 
	// are no cues to remove.
JETAPI jeBoolean JETCC jeActor_AnimationRemoveLastCue( jeActor *A );

	// applies a time step to actor A.  re-poses the actor according to all currently applicable
	// Animation Cues. (failure implies Actor is incompletely initialized)
JETAPI jeBoolean JETCC jeActor_AnimationStep(jeActor *A, jeFloat DeltaTime );

	// applies a 'temporary' time step to actor A.  re-poses the actor according to all 
	// currently appliciable cues.  (failure implies Actor is incompletely initialized)
	// DeltaTime is always relative to the the last AnimationStep()
JETAPI jeBoolean JETCC jeActor_AnimationTestStep(jeActor *A, jeFloat DeltaTime);

	// optimized version of jeActor_AnimationStep.  Limits calculations to the bone named BoneName, and it's 
	// parents.  BoneName will be correctly computed, but the other bones will be wrong.  This is usefull for 
	// moving and animating an actor that is not actually visible.  Rendering and queries will be 'optimized'
	// until the actor is given any pose or animation that doesn't go through jeActor_AnimationStepBoneOptimized() or 
	//  jeActor_AnimationTestStepBoneOptimized().  BoneName can be NULL to compute only 'root' bone.
JETAPI jeBoolean JETCC jeActor_AnimationStepBoneOptimized(jeActor *A, jeFloat DeltaTime, const char *BoneName );

	// optimized version of jeActor_AnimationTestStep.  Limits calculations to the bone named BoneName, and it's 
	// parents.  BoneName will be correctly computed, but the other bones will be wrong.  This is usefull for 
	// moving and animating an actor that is not actually visible.  Rendering and queries will be 'optimized'
	// until the actor is given any pose or animation that doesn't go through jeActor_AnimationStepBoneOptimized() or 
	//  jeActor_AnimationTestStepBoneOptimized().  BoneName can be NULL to compute only 'root' bone.
JETAPI jeBoolean JETCC jeActor_AnimationTestStepBoneOptimized(jeActor *A, jeFloat DeltaTime, const char *BoneName);


	// applies an 'immediate' offset to the animated actor
JETAPI jeBoolean JETCC jeActor_AnimationNudge(jeActor *A, jeXForm3d *Offset);


JETAPI jeBoolean JETCC jeActor_GetAnimationEvent(jeActor *A,						
	const char **ppEventString);		// Return data, if return value is JE_TRUE

JETAPI jeBoolean JETCC jeActor_GetIndexedBoneWorldSpaceVertexLocations(const jeActor* pActor, int boneIndex, int aSize,
	jeVec3d* pVerts);

JETAPI jeBoolean JETCC jeActor_GetNamedBoneWorldSpaceVertexLocations(const jeActor* pActor, const char* pBoneName, int aSize,
	jeVec3d* pVerts);

	// returns number of actors that are currently created.
JETAPI int JETCC jeActor_GetCount(void);

//========================================================================================
// --- Actor Collision by Incarnadine
// (Modified by Icestorm)

//========================================================================================
//	jeActor_MoveCollision
//     This function checks an Actor to see if it collides with other Actors in the world or
// with the world itself.  The current Actor position is irrelevant as it assumes the actor
// is moving on a path from Front to Back.  The actor's collision box must have previously
// been properly set.
//
//========================================================================================
JETAPI jeBoolean	jeActor_MoveCollision(	jeActor *Actor, 
											const jeWorld *World, 
											const jeVec3d *Front, 
											const jeVec3d *Back,											
											jeCollisionInfo *CollisionInfo);

//========================================================================================
//	jeActor_RotateCollision
//     This function checks an Actor to see if it collides with other Actors in the world or
// with the world itself during a rotation (orientation) change.  This isn't really needed if 
// you're not using bone level collisions.  If you are, it's very necessary in order to keep 
// your actors in the world.
//
//========================================================================================
JETAPI jeBoolean	jeActor_RotateCollision(jeActor *Actor,
											const jeWorld *World,											
											const jeXForm3d *NewTransform, 
											jeCollisionInfo *CollisionInfo);

//========================================================================================
//	jeActor_AnimationCollision
//     This function checks an Actor to see if it collides with other Actors in the world or
// with the world itself during an animation change.  This isn't really needed if 
// you're not using bone level collisions.  If you are, it's very necessary in order to keep 
// your actors in the world.
//
//========================================================================================
JETAPI jeBoolean	jeActor_AnimationCollision(jeActor *Actor,
											const jeWorld *World,											
											const jeFloat DeltaTime, 
											jeCollisionInfo *CollisionInfo);

//========================================================================================
//	jeActor_Collision
//      Tests to see if a Box moving along a path from Front to Back collides with the Actor.
//  The Actor's bounding box must have previously been set and Box must be relative to
//  the path (meaning not in world-space coordinates).
//
//========================================================================================
JETAPI jeBoolean	jeActor_Collision(	jeActor	*Actor, 
											const jeWorld* World, 
											const jeExtBox	*Box, 
											const jeVec3d	*Front, 
											const jeVec3d	*Back, 
											jeCollisionInfo *CollisionInfo);

// Added by Icestorm
//========================================================================================
//	jeActor_ChangeBoxCollision
//      Tests to see if a Box changing from FrontBox to BackBox collides with the Actor.
//  The Actor's bounding box must have previously been set and Box must be relative to
//  the path (meaning not in world-space coordinates).
//
//========================================================================================
JETAPI jeBoolean	jeActor_ChangeBoxCollision( jeActor			*Actor,
											    const jeWorld	*World,
												const jeVec3d	*Pos,
												const jeExtBox	*FrontBox,
												const jeExtBox	*BackBox,
												jeChangeBoxCollisionInfo *CollisionInfo);

// These functions manipulate the bone list used when checking for a bone level collision.
JETAPI void			JETCC jeActor_AddCollisionBone(jeActor *Actor, const char* BoneName);
JETAPI void			JETCC jeActor_RemoveCollisionBone(jeActor *Actor, const char* BoneName);
JETAPI jeBoolean	JETCC jeActor_HasCollisionBone(const jeActor *Actor, const char* BoneName);
JETAPI char*		JETCC jeActor_GetNextCollisionBone(jeActor *Actor, char *BoneName);
// Icestorm Begin
JETAPI char*		JETCC jeActor_GetNextCollisionBoneWithExtBoxes(	jeActor		*Actor,
																	char		*BoneName,
																	jeExtBox	*PrevBox,
																	jeExtBox	*CurrBox);
JETAPI void			JETCC jeActor_RecalcCollisionBones(jeActor *Actor);
 // Icestorm End
JETAPI void			JETCC jeActor_SetCollidedBone(jeActor* Actor, char *BoneName);
JETAPI char*		JETCC jeActor_GetCollidedBone(const jeActor* Actor);


// This function is used to set whether or not a particular Actor should be checked
// during a collision test.  Three Flags are possible, you should set ONLY one:
//   COLLIDE_EMPTY - This actor can not collide against anything or have other objects collide with it.
//   COLLIDE_SOLID - This actor can collide with other objects and have other objects collide with it.
//   COLLIDE_INVISIBLE - This actor can collide with other objects, but other objects can not collide with it.
// Actors are initialized with a COLLIDE_SOLID state.
#define COLLIDE_EMPTY (1<<12)
#define COLLIDE_SOLID  (1<<13)
#define COLLIDE_INVISIBLE (1<<14)
JETAPI void			JETCC jeActor_SetCollisionFlags(jeActor* Actor, const uint32 Flags);
JETAPI uint32		JETCC jeActor_GetCollisionFlags(const jeActor* Actor);

// -- End Actor Collision

//========================================================================================
// Incarnadine: Begin Actor Object Functions
JETAPI void			JETCC jeActor_InitObject(const jeActor *A,jeObject *O);

JETAPI jeBoolean	JETCC jeActor_RegisterObjectDef(void);

// Must be called prior to using your actor, imediately after Create!
JETAPI void JETCC jeActor_SetActorDef(jeActor *A, jeActor_Def *Def);

JETAPI jeBoolean JETCC jeActor_GetXForm(
	const jeActor* Actor,	// object instance data
	jeXForm3d	*Xf );		// where to store xform
JETAPI jeBoolean JETCC jeActor_SetXForm(
	jeActor* Actor,	// object instance data
	const jeXForm3d	*Xf );		// where to store xform
// Incarnadine: End Actor Object Functions
//========================================================================================


//========================================================================================
// Incarnadine: Begin ActorObj Property Defs
enum
{

	// scale
	//ACTOROBJ_SCALEGROUP_ID = PROPERTY_LOCAL_DATATYPE_START,
	ACTOROBJ_SCALEX_ID = PROPERTY_LOCAL_DATATYPE_START,
	/*ACTOROBJ_SCALEY_ID,
	ACTOROBJ_SCALEZ_ID,*/
	//ACTOROBJ_SCALEGROUPEND_ID,

	// ambient color
	ACTOROBJ_AMBIENTLIGHTGROUP_ID,
	ACTOROBJ_AMBIENTLIGHT_ID,
	ACTOROBJ_AMBIENTLIGHTRED_ID,
	ACTOROBJ_AMBIENTLIGHTGREEN_ID,
	ACTOROBJ_AMBIENTLIGHTBLUE_ID,
	ACTOROBJ_AMBIENTLIGHTGROUPEND_ID,

	// fill light
	ACTOROBJ_FILLIGHTGROUP_ID,
	ACTOROBJ_FILLLIGHT_ID,
	ACTOROBJ_FILLLIGHTRED_ID,
	ACTOROBJ_FILLLIGHTGREEN_ID,
	ACTOROBJ_FILLLIGHTBLUE_ID,
	ACTOROBJ_FILLLIGHTUSE_ID,
	ACTOROBJ_FILLLIGHTNORMALACTORRELATIVE_ID,
	ACTOROBJ_FILLLIGHTNORMAL_ID,
	ACTOROBJ_FILLLIGHTNORMALX_ID,
	ACTOROBJ_FILLLIGHTNORMALY_ID,
	ACTOROBJ_FILLLIGHTNORMALZ_ID,
	ACTOROBJ_FILLLIGHTNORMALEND_ID,
	ACTOROBJ_FILLIGHTGROUPEND_ID,

	// collision box
	ACTOROBJ_COLLISIONEXTBOXGROUP_ID,
	ACTOROBJ_COLLISIONEXTBOXDISPLAY_ID,
	ACTOROBJ_COLLISIONEXTBOXMINX_ID,
	ACTOROBJ_COLLISIONEXTBOXMINY_ID,
	ACTOROBJ_COLLISIONEXTBOXMINZ_ID,
	ACTOROBJ_COLLISIONEXTBOXMAXX_ID,
	ACTOROBJ_COLLISIONEXTBOXMAXY_ID,
	ACTOROBJ_COLLISIONEXTBOXMAXZ_ID,
	ACTOROBJ_COLLISIONEXTBOXGROUPEND_ID,

	// render box
	ACTOROBJ_RENDEREXTBOXGROUP_ID,
	ACTOROBJ_RENDEREXTBOXDISPLAY_ID,
	ACTOROBJ_RENDEREXTBOXMINX_ID,
	ACTOROBJ_RENDEREXTBOXMINY_ID,
	ACTOROBJ_RENDEREXTBOXMINZ_ID,
	ACTOROBJ_RENDEREXTBOXMAXX_ID,
	ACTOROBJ_RENDEREXTBOXMAXY_ID,
	ACTOROBJ_RENDEREXTBOXMAXZ_ID,
	ACTOROBJ_RENDEREXTBOXGROUPEND_ID,

	//
	ACTOROBJ_PERBONELIGHTING_ID,
	ACTOROBJ_USEAMBIENTLIGHTFROMFLOOR_ID,
	ACTOROBJ_MAXIMUMDYNAMICLIGHTSTOUSE_ID,
	ACTOROBJ_MAXIMUMSTATICLIGHTSTOUSE_ID,
	ACTOROBJ_MOTIONTIMESCALE_ID,

	// lists
	ACTOROBJ_LIST_ID,
	ACTOROBJ_MOTIONLIST_ID,
	ACTOROBJ_LIGHTREFERENCEBONENAMELIST_ID,

	// materials
	ACTOROBJ_MATERIALGROUP_ID,
	ACTOROBJ_MATERIALLIST_ID,
	/*ACTOROBJ_MATERIALRED_ID,
	ACTOROBJ_MATERIALGREEN_ID,
	ACTOROBJ_MATERIALBLUE_ID,*/
	ACTOROBJ_MATERIALOVERIDE_ID,
	ACTOROBJ_MATERIALMAPPER_ID,
	ACTOROBJ_MATERIALGROUPEND_ID,

	//
	ACTOROBJ_LAST_ID

};
enum
{

	// scale
	//ACTOROBJ_SCALEGROUP_INDEX = 0,
	ACTOROBJ_SCALEX_INDEX = 0,
	/*ACTOROBJ_SCALEY_INDEX,
	ACTOROBJ_SCALEZ_INDEX,*/
	//ACTOROBJ_SCALEGROUPEND_INDEX,

	// ambient color
	ACTOROBJ_AMBIENTLIGHTGROUP_INDEX,
	ACTOROBJ_AMBIENTLIGHT_INDEX,
	ACTOROBJ_AMBIENTLIGHTRED_INDEX,
	ACTOROBJ_AMBIENTLIGHTGREEN_INDEX,
	ACTOROBJ_AMBIENTLIGHTBLUE_INDEX,
	ACTOROBJ_AMBIENTLIGHTGROUPEND_INDEX,

	// fill light
	ACTOROBJ_FILLIGHTGROUP_INDEX,
	ACTOROBJ_FILLLIGHT_INDEX,
	ACTOROBJ_FILLLIGHTRED_INDEX,
	ACTOROBJ_FILLLIGHTGREEN_INDEX,
	ACTOROBJ_FILLLIGHTBLUE_INDEX,
	ACTOROBJ_FILLLIGHTUSE_INDEX,
	ACTOROBJ_FILLLIGHTNORMALACTORRELATIVE_INDEX,
	ACTOROBJ_FILLLIGHTNORMAL_INDEX,
	ACTOROBJ_FILLLIGHTNORMALX_INDEX,
	ACTOROBJ_FILLLIGHTNORMALY_INDEX,
	ACTOROBJ_FILLLIGHTNORMALZ_INDEX,
	ACTOROBJ_FILLLIGHTNORMALEND_INDEX,
	ACTOROBJ_FILLIGHTGROUPEND_INDEX,

	// collision box
	ACTOROBJ_COLLISIONEXTBOXGROUP_INDEX,
	ACTOROBJ_COLLISIONEXTBOXDISPLAY_INDEX,
	ACTOROBJ_COLLISIONEXTBOXMINX_INDEX,
	ACTOROBJ_COLLISIONEXTBOXMINY_INDEX,
	ACTOROBJ_COLLISIONEXTBOXMINZ_INDEX,
	ACTOROBJ_COLLISIONEXTBOXMAXX_INDEX,
	ACTOROBJ_COLLISIONEXTBOXMAXY_INDEX,
	ACTOROBJ_COLLISIONEXTBOXMAXZ_INDEX,
	ACTOROBJ_COLLISIONEXTBOXGROUPEND_INDEX,

	// render box
	ACTOROBJ_RENDEREXTBOXGROUP_INDEX,
	ACTOROBJ_RENDEREXTBOXDISPLAY_INDEX,
	ACTOROBJ_RENDEREXTBOXMINX_INDEX,
	ACTOROBJ_RENDEREXTBOXMINY_INDEX,
	ACTOROBJ_RENDEREXTBOXMINZ_INDEX,
	ACTOROBJ_RENDEREXTBOXMAXX_INDEX,
	ACTOROBJ_RENDEREXTBOXMAXY_INDEX,
	ACTOROBJ_RENDEREXTBOXMAXZ_INDEX,
	ACTOROBJ_RENDEREXTBOXGROUPEND_INDEX,

	//
	ACTOROBJ_PERBONELIGHTING_INDEX,
	ACTOROBJ_USEAMBIENTLIGHTFROMFLOOR_INDEX,
	ACTOROBJ_MAXIMUMDYNAMICLIGHTSTOUSE_INDEX,
	ACTOROBJ_MAXIMUMSTATICLIGHTSTOUSE_INDEX,
	ACTOROBJ_MOTIONTIMESCALE_INDEX,

	// lists	
	ACTOROBJ_LIST_INDEX,
	ACTOROBJ_MOTIONLIST_INDEX,
	ACTOROBJ_LIGHTREFERENCEBONENAMELIST_INDEX,

	// materials
	ACTOROBJ_MATERIALGROUP_INDEX,
	ACTOROBJ_MATERIALLIST_INDEX,
	/*ACTOROBJ_MATERIALRED_INDEX,
	ACTOROBJ_MATERIALGREEN_INDEX,
	ACTOROBJ_MATERIALBLUE_INDEX,*/
	ACTOROBJ_MATERIALOVERIDE_INDEX,
	ACTOROBJ_MATERIALMAPPER_INDEX,
	ACTOROBJ_MATERIALGROUPEND_INDEX,

	// end marker
	ACTOROBJ_LAST_INDEX

};
// Incarnadine: End ActorObj Property Defs
//========================================================================================

//========================================================================================

#ifdef __cplusplus
}
#endif


#endif
