#include "Mix/Private/Scene/Common/ActorSensor.h"

#include "Mix/Private/Dynamics/Sensor.h"
#include "Mix/Dynamics/IShape.h"
#include "Mix/Scene/IRendererObject.h"

namespace Mix{ namespace Scene{ namespace Common{
	
////////////////////////////////////////////////////////////////////////////////////////////////////
// フィルター
////////////////////////////////////////////////////////////////////////////////////////////////////

const UInt16 ActorSensor::FILTER_GROUP	= Mix::Dynamics::OF_SENSOR;
const UInt16 ActorSensor::FILTER_MASK	= Mix::Dynamics::OF_DEFAULT | Mix::Dynamics::OF_STATIC | Mix::Dynamics::OF_KINEMATIC;
	
////////////////////////////////////////////////////////////////////////////////////////////////////
// ActorSensor
////////////////////////////////////////////////////////////////////////////////////////////////////

ActorSensor* ActorSensor::CreateInstance( const wchar_t* pName, const Mix::Matrix4x4& centerMat, Mix::Dynamics::ISensor* pObject )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, ActorSensor, pName, centerMat, pObject );
}

ActorSensor* ActorSensor::CreateInstance( Mix::Scene::IRendererObject* pOwner, const wchar_t* pName, const Mix::Matrix4x4& centerMat, Mix::Dynamics::ISensor* pObject )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, ActorSensor, pOwner, pName, centerMat, pObject );
}

ActorSensor::ActorSensor( const wchar_t* pName, const Mix::Matrix4x4& centerMat, Mix::Dynamics::ISensor* pObject ) :
m_pOwner( NULL ),
m_Name( L"" ),
m_CenterMat( centerMat ),
m_pObject( NULL )
{
	MIX_ASSERT( pName != NULL );
	MIX_ASSERT( pObject != NULL );

	m_Name = pName;

	MIX_ADD_REF( pObject );
	m_pObject = pObject;

	m_pObject->SetFilterGroup( ActorSensor::FILTER_GROUP );
	m_pObject->SetFilterMask( ActorSensor::FILTER_MASK );

	DynamicsObject::Initialize( this );
}

ActorSensor::ActorSensor( Mix::Scene::IRendererObject* pOwner, const wchar_t* pName, const Mix::Matrix4x4& centerMat, Mix::Dynamics::ISensor* pObject ) :
m_pOwner( NULL ),
m_Name( L"" ),
m_CenterMat( centerMat ),
m_pObject( NULL )
{
	MIX_ASSERT( pOwner != NULL );
	MIX_ASSERT( pName != NULL );
	MIX_ASSERT( pObject != NULL );

	m_pOwner = pOwner;

	m_Name = pName;

	MIX_ADD_REF( pObject );
	m_pObject = pObject;

	m_pObject->SetFilterGroup( ActorSensor::FILTER_GROUP );
	m_pObject->SetFilterMask( ActorSensor::FILTER_MASK );

	DynamicsObject::Initialize( this );
}

ActorSensor::~ActorSensor( void )
{
	MIX_ASSERT( m_pOwner == NULL );
	MIX_RELEASE( m_pObject );
}

void ActorSensor::SetOwner( Mix::Scene::IRendererObject* pOwner )
{
	MIX_ASSERT( pOwner != NULL );
	MIX_ASSERT( m_pOwner == NULL );

	m_pOwner = pOwner;
}

void ActorSensor::Reset( const Mix::Matrix4x4& baseMat )
{
	MIX_ASSERT( m_pObject != NULL );

	Mix::Matrix4x4 worldMat = m_CenterMat * baseMat;

	m_pObject->SetWorldTransform( worldMat.GetRotation(), worldMat.GetTranslation() );
}

Mix::Dynamics::ISensor* ActorSensor::GetInternalSensorPtr( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject;
}

ActorSensor* ActorSensor::Clone( void )
{
	Mix::Scene::Common::ActorSensor* pDstSensor = NULL;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// オブジェクトを複製
	////////////////////////////////////////////////////////////////////////////////////////////////////

	Mix::Dynamics::IShape* pSrcShape = NULL;
	Mix::Dynamics::Sensor* pDstObject = NULL;

	m_pObject->GetShape( &pSrcShape );
	MIX_ASSERT( pSrcShape != NULL );

	pDstObject = Mix::Dynamics::Sensor::CreateInstance( pSrcShape );
	if( pDstObject != NULL )
	{
		if( pDstObject->Initialize( m_Name.GetConstPtr() ) == True )
		{
			pDstObject->SetMaterial( m_pObject->GetMaterial() );

			//ワールドトランスフォームはあとで設定
		}
		else
		{
			MIX_RELEASE( pSrcShape );
			return NULL;
		}
	}
	else
	{
		MIX_RELEASE( pSrcShape );
		return NULL;
	}

	MIX_RELEASE( pSrcShape );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 自身を複製
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pDstSensor = Mix::Scene::Common::ActorSensor::CreateInstance( m_Name.GetConstPtr(), m_CenterMat, pDstObject );
	if( pDstSensor == NULL )
	{
		MIX_RELEASE( pDstObject );
		return NULL;
	}

	MIX_RELEASE( pDstObject );

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return pDstSensor;
}

void ActorSensor::Dispose( void )
{
	m_pOwner = NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::Common::DynamicsObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Dynamics::IObject* ActorSensor::GetInternalObjectPtr( void ) const
{
	return m_pObject;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IActorSensor
////////////////////////////////////////////////////////////////////////////////////////////////////

const wchar_t* ActorSensor::GetName( void ) const
{
	return m_Name.GetConstPtr();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::ISensor
////////////////////////////////////////////////////////////////////////////////////////////////////

UInt16 ActorSensor::GetFilterGroup( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetFilterGroup();
}

void ActorSensor::SetFilterGroup( UInt16 filterGroup )
{
	MIX_ASSERT( m_pObject != NULL );

	m_pObject->SetFilterGroup( filterGroup );
}


UInt16 ActorSensor::GetFilterMask( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetFilterMask();
}

void ActorSensor::SetFilterMask( UInt16 filterMask )
{
	MIX_ASSERT( m_pObject != NULL );

	m_pObject->SetFilterMask( filterMask );
}

const Mix::Dynamics::MATERIAL& ActorSensor::GetMaterial( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterial();
}

void ActorSensor::SetMaterial( const Mix::Dynamics::MATERIAL& material )
{
	MIX_ASSERT( m_pObject != NULL );

	m_pObject->SetMaterial( material );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDynamicsObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IDynamicsObject::TYPE ActorSensor::GetType( void ) const
{
	return Mix::Scene::IDynamicsObject::ACTOR_SENSOR;
}

Boolean ActorSensor::GetOwner( Mix::Scene::IRendererObject** ppOwner )
{
	if( m_pOwner != NULL )
	{
		MIX_ADD_REF( m_pOwner );
		( *ppOwner ) = m_pOwner;
	}
	else
	{
		return False;
	}

	return True;
}

Mix::Scene::IRendererObject* ActorSensor::GetOwnerPtr( void ) const
{
	return m_pOwner;
}

Mix::Matrix4x4 ActorSensor::GetWorldMatrix( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetWorldMatrix();
}

Mix::Quaternion ActorSensor::GetWorldRotation( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetWorldRotation();
}

Mix::Vector3 ActorSensor::GetWorldPosition( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetWorldPosition();
}

Boolean ActorSensor::HasContactListener( void ) const
{
	return DynamicsObject::HasContactListener();
}

Boolean ActorSensor::ContainsContactListener( Mix::Scene::IContactListener* pListener ) const
{
	return DynamicsObject::ContainsContactListener( pListener );
}

Boolean ActorSensor::AddContactListener( Mix::Scene::IContactListener* pListener )
{
	return DynamicsObject::AddContactListener( pListener );
}

Boolean ActorSensor::RemoveContactListener( Mix::Scene::IContactListener* pListener )
{
	return DynamicsObject::RemoveContactListener( pListener );
}

void ActorSensor::ClearContactListener( void )
{
	DynamicsObject::ClearContactListener();
}

Int32 ActorSensor::GetUserIndex( void )  const
{
	return DynamicsObject::GetUserIndex();
}

void ActorSensor::SetUserIndex( Int32 index )
{
	DynamicsObject::SetUserIndex( index );
}

void* ActorSensor::GetUserPtr( void ) const
{
	return DynamicsObject::GetUserPtr();
}

void ActorSensor::SetUserPtr( void* ptr )
{
	DynamicsObject::SetUserPtr( ptr );
}

}}}
