/*!
	@project Rune
	@file RuHelper_Entity.h

	Copyright (c) 2004-2005 All rights reserved

	@author John Tang
	@date 2005/04/13
*/

#ifndef _RUHELPER_ENTITY_H_
#define _RUHELPER_ENTITY_H_

#include "../Scene/Base/RuEntityBase.h"
#include "../Scene/Base/RuEntityACT.h"
#include "../Fusion/RuFusion_Sojourner.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

// Movement and orientation
extern RUAPI BOOL					RuEntity_Anchor(CRuEntity *entity, IRuObject *anchorObject, REAL entityMassOffset = 5.0f, REAL testIncrement = 1.0f, REAL testRange = 5.0f);
extern RUAPI BOOL					RuEntity_Anchor(CRuEntity *entity, IRuObject *anchorObject, const CRuVector3 &defaultForward, const CRuVector3 &entityForward, REAL entityMassOffset = 5.0f, REAL testIncrement = 1.0f, REAL testRange = 5.0f);
extern RUAPI REAL					RuEntity_FindAnchorPoint(const CRuVector3 &entityPosition, IRuObject *anchorObject, REAL entityMassOffset = 5.0f, REAL testIncrement = 1.0f, REAL testRange = 5.0f);
extern RUAPI BOOL					RuEntity_CalculateMoveVector(CRuEntity *entity, const CRuVector3 &defaultForward, REAL forwardDelta, REAL rightDelta, CRuVector3 *moveVectorOut);
extern RUAPI BOOL					RuEntity_Move(CRuEntity *entity, const CRuVector3 &defaultForward, REAL forwardDelta, REAL rightDelta);
extern RUAPI BOOL					RuEntity_CalculateCollideOffsetVector(const CRuSphere &collideSphere, IRuObject *anchorObject, CRuVector3 *offsetVectorOut);
extern RUAPI BOOL					RuEntity_MoveEx(CRuEntity *entity, IRuObject *anchorObject, const CRuVector3 &defaultForward, const CRuVector3 &entityForward, const CRuVector3 &moveDelta, REAL moveSpeed, REAL elapsedTime);
extern RUAPI BOOL					RuEntity_Orient(CRuEntity *entity, const CRuVector3 &defaultForward, const CRuVector3 &entityForward, REAL entityScale);
extern RUAPI CRuVector3				RuEntity_CalculateForwardVector(CRuEntity *entity, const CRuVector3 &defaultForward);
extern RUAPI BOOL					RuEntity_Unstuck(CRuEntity *entity, IRuObject *anchorObject, REAL moveSpeed, REAL elapsedTime);

// Miscellaneous
extern RUAPI INT32					RuEntity_GetMaxMorphTargetCount(CRuEntity *entity);
extern RUAPI BOOL					RuEntity_PickTest(CRuEntity *entity, CRuCamera *camera, IRuSwapChain *swapChain, INT32 x, INT32 y, REAL *pickDistanceOut = NULL);

// Link management
extern RUAPI BOOL					RuEntity_Attach(CRuEntity *parentEntity, CRuEntity *childEntity, const char *linkName);
extern RUAPI BOOL					RuEntity_Detach(CRuEntity *parentEntity, CRuEntity *childEntity, const char *linkName);
extern RUAPI BOOL					RuEntity_DetachAll(CRuEntity *parentEntity, const char *linkName);
extern RUAPI CRuEntity*				RuEntity_FindLinkFrame(CRuEntity *entity, const char *linkName);

// Utility functions
extern RUAPI BOOL					RuEntity_EnumerateMeshes(CRuEntity *entity, CRuArrayList<IRuMesh *> &meshListOut);
extern RUAPI BOOL					RuEntity_EnumerateMaterials(CRuEntity *entity, CRuArrayList<IRuMaterial *> &materialListOut);
extern RUAPI BOOL					RuEntity_SetOption(CRuEntity *entity, RuEntityOption option, INT32 value);
extern RUAPI CRuModel*				RuEntity_FindFirstModel(CRuEntity *entity);
extern RUAPI CRuFrameHierarchy*		RuEntity_FindFirstFrameHierarchy(CRuEntity *entity);
extern RUAPI CRuACTEntity*			RuEntity_FindFirstACTEntity(CRuEntity *entity);
extern RUAPI CRuPaperdoll*			RuEntity_FindFirstPaperdoll(CRuEntity *entity);

// Transform functions
extern RUAPI BOOL					RuEntity_TransformVector_WorldToLocal(CRuEntity *entity, const CRuVector3 &v0, CRuVector3 &v0Out);

// Skeletal helpers
extern RUAPI CRuMatrix4x4&			RuHierarchy_GetSubNodeTransform(CRuFrameHierarchy *hierarchy, CRuAnimationInterpolator *interpolator, INT32 nodeIndex, CRuMatrix4x4 &transformOut);
extern RUAPI CRuMatrix4x4&			RuHierarchy_GetSubNodeParentTransform(CRuFrameHierarchy *hierarchy, CRuAnimationInterpolator *interpolator, INT32 nodeIndex, CRuMatrix4x4 &transformOut);

// Collision functions
extern RUAPI BOOL					RuCollision_TestAABB(const CRuAABB &aabb, IRuObject *anchorObject);
extern RUAPI BOOL					RuCollision_TestSphere(const CRuSphere &testSphere, IRuObject *anchorObject);

// ACT functions
extern RUAPI BOOL					RuACT_HasMotion(CRuEntity *entity, const char *motionName, BOOL firstACTOnly = TRUE);

extern RUAPI BOOL					RuACT_SupportsMotionChannel(CRuEntity *entity, UINT32 channel);
extern RUAPI BOOL					RuACT_PauseChannel(CRuEntity *entity, UINT32 channel);
extern RUAPI BOOL					RuACT_ResumeChannel(CRuEntity *entity, UINT32 channel);

extern RUAPI BOOL					RuACT_PlayPersistentMotion(CRuEntity *entity, BOOL forceReset = FALSE);
extern RUAPI BOOL					RuACT_PlayMotion(CRuEntity *entity, const char *motionName, REAL blendTime = 0.0f, BOOL forceReset = FALSE);
extern RUAPI BOOL					RuACT_PlayMotion(CRuEntity *entity, INT32 motionID, REAL blendTime = 0.0f, BOOL forceReset = FALSE);
extern RUAPI BOOL					RuACT_PlayMotionEx(CRuEntity *entity, UINT32 channel, const char *motionName, REAL blendTime = 0.0f, BOOL forceReset = FALSE, REAL channelWeight = 1.0f, REAL leadIn = 0.0f, REAL leadOut = 0.0f, REAL expectedMotionScale = 0.0f);
extern RUAPI BOOL					RuACT_SwapMotion(CRuEntity *entity, UINT32 srcChannel, UINT32 destChannel);
extern RUAPI BOOL					RuACT_ClearMotion(CRuEntity *entity, UINT32 channel, REAL fadeDuration);
extern RUAPI BOOL					RuACT_IsMotionComplete(CRuEntity *entity, UINT32 channel = 0xFFFFFFFF);
extern RUAPI const char*			RuACT_GetActiveMotionName(CRuEntity *entity, UINT32 channel = 0xFFFFFFFF);
extern RUAPI REAL					RuACT_GetActiveMotionTime(CRuEntity *entity, UINT32 channel = 0xFFFFFFFF);
extern RUAPI BOOL					RuACT_CheckForController(CRuEntity *entity, UINT32 channel, const CRuRTTI &controllerType, BOOL firstACTOnly = TRUE);
extern RUAPI BOOL					RuACT_CheckForEvent(CRuEntity *entity, UINT32 channel, RuEntityEvent eventType, REAL *startTimeOut = NULL, BOOL firstACTOnly = TRUE);
extern RUAPI BOOL					RuACT_PlugMissingMotions(CRuEntity *entity, const char *commandStream, BOOL firstACTOnly = TRUE);

// Paperdoll functions
extern RUAPI BOOL					RuPaperdoll_SetColorCodes(CRuEntity *entity, INT32 color0Code, INT32 color1Code);
extern RUAPI BOOL					RuPaperdoll_SetComponent(CRuEntity *entity, const char *partName, const char *componentName);
extern RUAPI BOOL					RuPaperdoll_Build(CRuEntity *entity);

// Miscellaneous
extern RUAPI const char*			RuEnumConverter_ToString(RuTextureChannel texChannel);

// ************************************************************************************************************************************************************

class CRuGlobalEventManager_Sample : public IRuEntityEventListener
{
protected:
	CRuEntity_Container_Impl*				m_controllerFrame;				//!< Frame that contains all controllers

public:
											CRuGlobalEventManager_Sample();
	virtual									~CRuGlobalEventManager_Sample();

	void									Update(REAL elapsedTime);

	virtual BOOL							HandleEvent(CRuEntity *entity, INT32 eventID, INT32 eventParameter0, INT32 eventParameter1, const char *eventString, REAL eventDuration, void *userData);
};

// ************************************************************************************************************************************************************

extern char*				g_ruACT_DefaultMotionChart;

// ************************************************************************************************************************************************************


inline void test(CRuVector3 entityPosition, IRuObject *colObject)
{
	for(int i = 0; i < 10000; ++i)
	{
//		moo = RuEntity_FindAnchorPoint(entityPosition, colObject);

		CRuCollisionQuery_Segment_Nearest colQuery;
		colQuery.m_colSegment = CRuSegment3(entityPosition + CRuVector3(0.0f, 5.0f, 0.0f), entityPosition - CRuVector3(0.0f, 5.0f, 0.0f));
		if(colObject->GetType().IsSubClassOf(CRuEntity::Type))
		{
			static_cast<CRuEntity *>(colObject)->QueryCollision(&colQuery);
		}
		else if(colObject->GetType().IsSubClassOf(IRuCollisionHierarchy::Type))
		{
			static_cast<IRuCollisionHierarchy *>(colObject)->QueryCollision(&colQuery);
		}
	}
}

// ************************************************************************************************************************************************************

#pragma managed

#endif
