
// zlib open source license
//
// Copyright (c) 2010 to 2013 David Forsgren Piuva
// 
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// 
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 
//    1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 
//    2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 
//    3. This notice may not be removed or altered from any source
//    distribution.

void CDFPGECtrl::Constraint_Delete(int Constraint) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_Delete",Constraint)
		} else {
			DGE.Delete_Constraint(pConstraint);
		}
	)
}

void CDFPGECtrl::Constraint_SetEnabled(int Constraint, bool Enabled) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_SetEnabled",Constraint)
		} else {
			pConstraint->Constraint->setEnabled(Enabled);
		}
	)
}

int CDFPGECtrl::Constraint_IsEnabled(int Constraint) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_IsEnabled",Constraint)
			Result = -1;
		} else {
			if (pConstraint->Constraint->isEnabled()) {
				Result = 1;
			} else {
				Result = 0;
			}
		}
	)
	return Result;
}

#define MAKE_CONSTRAINT_CONSRUCTOR_SHELL_CONTENT_1(METHOD,RETURN_VALUE) \
	int Result; \
	CRITICAL_CODE_SECTION( \
		GET_FROM_REF(RigidBody,RigidBody) \
		if BAD_REF(RigidBody) { \
			REPORT_TYPE(RigidBody,METHOD,RigidBody) \
			Result = 0; \
		} else { \
			Result = RETURN_VALUE##; \
		} \
	) \
	return Result;

#define MAKE_CONSTRAINT_CONSRUCTOR_SHELL_CONTENT_2(METHOD,RETURN_VALUE) \
	int Result; \
	CRITICAL_CODE_SECTION( \
		GET_FROM_REF(RigidBody,RigidBodyA) \
		GET_FROM_REF(RigidBody,RigidBodyB) \
		if BAD_REF(RigidBodyA) { \
			REPORT_TYPE(RigidBody,METHOD,RigidBodyA) \
			Result = 0; \
		} else if BAD_REF(RigidBodyB) { \
			REPORT_TYPE(RigidBody,METHOD,RigidBodyB) \
			Result = 0; \
		} else { \
			Result = RETURN_VALUE##; \
		} \
	) \
	return Result;

int CDFPGECtrl::Constraint_Create_PointToPoint_1(int RigidBody,float Point_X,float Point_Y,float Point_Z) {
	MAKE_CONSTRAINT_CONSRUCTOR_SHELL_CONTENT_1(
		L"Constraint_Create_PointToPoint_1",
		DGE.IDFromPointer(DGE.Constraint_Create_PointToPoint_1(pRigidBody,Point_X,Point_Y,Point_Z))
	)
}

int CDFPGECtrl::Constraint_Create_PointToPoint_2(int RigidBodyA,int RigidBodyB,float PointA_X,float PointA_Y,float PointA_Z,float PointB_X,float PointB_Y,float PointB_Z) {
	MAKE_CONSTRAINT_CONSRUCTOR_SHELL_CONTENT_2(
		L"Constraint_Create_PointToPoint_2",
		DGE.IDFromPointer(DGE.Constraint_Create_PointToPoint_2(pRigidBodyA,pRigidBodyB,PointA_X,PointA_Y,PointA_Z,PointB_X,PointB_Y,PointB_Z))
	)
}

int CDFPGECtrl::Constraint_Create_Hinge_1(int RigidBody,float Pivot_X,float Pivot_Y,float Pivot_Z,float Axis_X,float Axis_Y,float Axis_Z) {
	MAKE_CONSTRAINT_CONSRUCTOR_SHELL_CONTENT_1(
		L"Constraint_Create_Hinge_1",
		DGE.IDFromPointer(DGE.Constraint_Create_Hinge_1(pRigidBody,Pivot_X,Pivot_Y,Pivot_Z,Axis_X,Axis_Y,Axis_Z))
	)
}

int CDFPGECtrl::Constraint_Create_Hinge_2(int RigidBodyA,int RigidBodyB,float PivotA_X,float PivotA_Y,float PivotA_Z,float PivotB_X,float PivotB_Y,float PivotB_Z,float AxisA_X,float AxisA_Y,float AxisA_Z,float AxisB_X,float AxisB_Y,float AxisB_Z) {
	MAKE_CONSTRAINT_CONSRUCTOR_SHELL_CONTENT_2(
		L"Constraint_Create_Hinge_2",
		DGE.IDFromPointer(DGE.Constraint_Create_Hinge_2(pRigidBodyA,pRigidBodyB,PivotA_X,PivotA_Y,PivotA_Z,PivotB_X,PivotB_Y,PivotB_Z,AxisA_X,AxisA_Y,AxisA_Z,AxisB_X,AxisB_Y,AxisB_Z))
	)
}

void CDFPGECtrl::Constraint_Hinge_Motor_Enable(int Constraint, bool Enabled) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_Hinge_Motor_Enable",Constraint)
		} else if (pConstraint->ConstraintType != ConstraintType_Hinge_1 && pConstraint->ConstraintType != ConstraintType_Hinge_2 ) {
			MQ->InsertMessage(L"Constraint_Hinge_Motor_Enable: The constraint is not a hinge constraint.");
		} else {
			((btHingeConstraint*)(pConstraint->Constraint))->enableMotor(Enabled);
		}
	)
}

int CDFPGECtrl::Constraint_Hinge_Motor_IsEnabled(int Constraint) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		Result = -1;
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_Hinge_Motor_IsEnabled",Constraint)
		} else if (pConstraint->ConstraintType != ConstraintType_Hinge_1 && pConstraint->ConstraintType != ConstraintType_Hinge_2 ) {
			MQ->InsertMessage(L"Constraint_Hinge_Motor_IsEnabled: The constraint is not a hinge constraint.");
		} else {
			if (((btHingeConstraint*)(pConstraint->Constraint))->getEnableAngularMotor()) {
				Result = 1;
			} else {
				Result = 0;
			}
		}
	)
	return Result;
}

void CDFPGECtrl::Constraint_Hinge_Motor_Control(int Constraint, bool Enabled, float TargetVelocity, float MaxImpulse) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_Hinge_Motor_Control",Constraint)
		} else if (pConstraint->ConstraintType != ConstraintType_Hinge_1 && pConstraint->ConstraintType != ConstraintType_Hinge_2 ) {
			MQ->InsertMessage(L"Constraint_Hinge_Motor_Control: The constraint is not a hinge constraint.");
		} else if (MaxImpulse < 0.0f) {
			MQ->InsertMessage(L"Constraint_Hinge_Motor_Control: MaxImpulse is not allowed to be negative.");
		} else {
			((btHingeConstraint*)(pConstraint->Constraint))->enableAngularMotor(Enabled,TargetVelocity,MaxImpulse);
		}
	)
}

int CDFPGECtrl::Constraint_GetRigidBodyA(int Constraint) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_GetRigidBodyA",Constraint)
			Result = -1;
		} else {
			if (pConstraint->BodyA) {
				Result = pConstraint->BodyA->ID;
			} else {
				Result = 0;
			}
		}
	)
	return Result;
}

int CDFPGECtrl::Constraint_GetRigidBodyB(int Constraint) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Constraint,Constraint)
		if BAD_REF(Constraint) {
			REPORT_TYPE(Constraint,L"Constraint_GetRigidBodyB",Constraint)
			Result = -1;
		} else {
			if (pConstraint->BodyB) {
				Result = pConstraint->BodyB->ID;
			} else {
				Result = 0;
			}
		}
	)
	return Result;
}
