
// 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.

#define DEF_GET_VAR(VARNAME) float CDFPGECtrl::Get##VARNAME(void){CRITICAL_CODE_SECTION(return VARNAME;)}
#define DEF_SET_VAR(VARNAME) void CDFPGECtrl::Set##VARNAME(float newValue){CRITICAL_CODE_SECTION(VARNAME = newValue;)}
#define DEF_GET_SET_VAR(VARNAME) DEF_GET_VAR(VARNAME) DEF_SET_VAR(VARNAME)
DEF_GET_SET_VAR(X1) DEF_GET_SET_VAR(Y1) DEF_GET_SET_VAR(Z1) DEF_GET_SET_VAR(W1)
DEF_GET_SET_VAR(X2) DEF_GET_SET_VAR(Y2) DEF_GET_SET_VAR(Z2) DEF_GET_SET_VAR(W2)
DEF_GET_SET_VAR(X3) DEF_GET_SET_VAR(Y3) DEF_GET_SET_VAR(Z3) DEF_GET_SET_VAR(W3)
DEF_GET_SET_VAR(X4) DEF_GET_SET_VAR(Y4) DEF_GET_SET_VAR(Z4) DEF_GET_SET_VAR(W4)

void CDFPGECtrl::WriteToStringBuffer(int Index, short int NewCharacter) {
	CRITICAL_CODE_SECTION(
		if (!(Index < 1 || Index > lenStringBuffer)) {
			StringBuffer[Index - 1] = (wchar_t)NewCharacter;
		}
	)
}

short int CDFPGECtrl::ReadFromStringBuffer(int Index) {
	short int Result;
	CRITICAL_CODE_SECTION(
		if (Index < 1 || Index > lenStringBuffer) {
			Result = (short int)L'?';
		} else {
			Result = (short int)StringBuffer[Index - 1];
		}
	)
	return Result;
}

int CDFPGECtrl::GetLengthOfStringBuffer(void) {
	int Result;
	CRITICAL_CODE_SECTION(
		Result = lenStringBuffer;
	)
	return Result;
}

// Side effect: The string buffer will be reset to make sure that execution is deterministic.
void CDFPGECtrl::SetLengthOfStringBuffer(int NewSize) {
	CRITICAL_CODE_SECTION(
		SetLengthOfStringBuffer_Aux(NewSize);
	)
}

int CDFPGECtrl::GetLengthOfContactBuffer(void) {
	int Result;
	CRITICAL_CODE_SECTION(
		Result = CB.ContactArray.size();
	)
	return Result;
}

int CDFPGECtrl::ReadFromContactBuffer_BodyA(int Index) {
	int Result;
	ContactResult* CR;
	CRITICAL_CODE_SECTION(
		CR = CB.GetContact(Index);
		if (CR) {
			Result = CR->BodyA_ID;
		} else {
			MQ->InsertMessage(L"ReadFromContactBuffer_BodyA: Index is out of bound. Use an index from 0 to LengthOfContactBuffer - 1.");
			Result = -1;
		}
	)
	return Result;
}
int CDFPGECtrl::ReadFromContactBuffer_BodyB(int Index) {
	int Result;
	ContactResult* CR;
	CRITICAL_CODE_SECTION(
		CR = CB.GetContact(Index);
		if (CR) {
			Result = CR->BodyB_ID;
		} else {
			MQ->InsertMessage(L"ReadFromContactBuffer_BodyB: Index is out of bound. Use an index from 0 to LengthOfContactBuffer - 1.");
			Result = -1;
		}
	)
	return Result;
}
void CDFPGECtrl::ReadFromContactBuffer_Position_OutV3(int Index) {
	ContactResult* CR;
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		CR = CB.GetContact(Index);
		if (CR) {
			SetBulletVector3ToMB(&(CR->WorldPos));
		} else {
			MQ->InsertMessage(L"ReadFromContactBuffer_Position_OutV3: Index is out of bound. Use an index from 0 to LengthOfContactBuffer - 1.");
		}
	)
}
void CDFPGECtrl::ReadFromContactBuffer_Normal_OutV3(int Index) {
	ContactResult* CR;
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		CR = CB.GetContact(Index);
		if (CR) {
			SetBulletVector3ToMB(&(CR->WorldNormal));
		} else {
			MQ->InsertMessage(L"ReadFromContactBuffer_Normal_OutV3: Index is out of bound. Use an index from 0 to LengthOfContactBuffer - 1.");
		}
	)
}
float CDFPGECtrl::ReadFromContactBuffer_Impulse(int Index) {
	float Result;
	ContactResult* CR;
	CRITICAL_CODE_SECTION(
		CR = CB.GetContact(Index);
		if (CR) {
			Result = CR->Impulse;
		} else {
			MQ->InsertMessage(L"ReadFromContactBuffer_BodyB: Index is out of bound. Use an index from 0 to LengthOfContactBuffer - 1.");
			Result = 0.0f;
		}
	)
	return Result;
}

// Internal

void CDFPGECtrl::FillSB(wchar_t* NewString) {
	int Length; int i;
	Length = lengthOfString_wide(NewString);
	SetLengthOfStringBuffer_Aux(Length);
	LoopForward(0,i,Length - 1) {
		StringBuffer[i] = (wchar_t)NewString[i];
	}
}

void CDFPGECtrl::SetLengthOfStringBuffer_Aux(int newSize) {
	if ((newSize + 1) > allocatedStringBuffer) {
		SAFE_DELETE(StringBuffer)
		allocatedStringBuffer = newSize + 1;
		StringBuffer = new wchar_t[allocatedStringBuffer];
	}
	lenStringBuffer = newSize;
	ClearStringBuffer();
}

void CDFPGECtrl::ClearStringBuffer(void) {
	int i;
	LoopForward(0,i,allocatedStringBuffer-1) {
		StringBuffer[i] = 0;
	}
}

void CDFPGECtrl::ClearMatrixBuffer(void) {
	X1 = 0.0f; Y1 = 0.0f; Z1 = 0.0f; W1 = 0.0f;
	X2 = 0.0f; Y2 = 0.0f; Z2 = 0.0f; W2 = 0.0f;
	X3 = 0.0f; Y3 = 0.0f; Z3 = 0.0f; W3 = 0.0f;
	X4 = 0.0f; Y4 = 0.0f; Z4 = 0.0f; W4 = 0.0f;
}

void CDFPGECtrl::Set4x4MatrixToMB(DMatrix NewMatrix) {
	X1 = NewMatrix._11; Y1 = NewMatrix._12; Z1 = NewMatrix._13; W1 = NewMatrix._14;
	X2 = NewMatrix._21; Y2 = NewMatrix._22; Z2 = NewMatrix._23; W2 = NewMatrix._24;
	X3 = NewMatrix._31; Y3 = NewMatrix._32; Z3 = NewMatrix._33; W3 = NewMatrix._34;
	X4 = NewMatrix._41; Y4 = NewMatrix._42; Z4 = NewMatrix._43; W4 = NewMatrix._44;
}
void CDFPGECtrl::SetVector4ToMB(DVector4 NewVector) {
	X1 = NewVector.x; Y1 = NewVector.y; Z1 = NewVector.z; W1 = NewVector.w;
}
void CDFPGECtrl::SetVector3ToMB(DVector3 NewVector) {
	X1 = NewVector.x; Y1 = NewVector.y; Z1 = NewVector.z;
}
void CDFPGECtrl::SetVector2ToMB(DVector2 NewVector) {
	X1 = NewVector.x; Y1 = NewVector.y;
}

void CDFPGECtrl::SetBulletTransformToMB(btTransform* NewTrans) {
	float M[12];
	btVector3 T;
	NewTrans->getBasis().getOpenGLSubMatrix(M);
	T = NewTrans->getOrigin();
	X1 = M[0];
	Y1 = M[1];
	Z1 = M[2];
	W1 = 0;
	X2 = M[4];
	Y2 = M[5];
	Z2 = M[6];
	W2 = 0;
	X3 = M[8];
	Y3 = M[9];
	Z3 = M[10];
	W3 = 0;
	X4 = T.getX();
	Y4 = T.getY();
	Z4 = T.getZ();
	W4 = 1;
}
void CDFPGECtrl::SetBulletVector4ToMB(btVector4* NewVector) {
	X1 = NewVector->getX(); Y1 = NewVector->getY(); Z1 = NewVector->getZ(); W1 = NewVector->getW();
}
void CDFPGECtrl::SetBulletVector3ToMB(btVector3* NewVector) {
	X1 = NewVector->getX(); Y1 = NewVector->getY(); Z1 = NewVector->getZ();
}
