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

int CDFPGECtrl::Model_CreateEmpty(void) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running == false) {
			REPORT_NOT_RUNNING(L"Model_CreateEmpty")
			Result = 0;
		} else {
			Model_Struct* NewModel;
			NewModel = DGE.CreateEmptyModel();
			CopyToFixedSizePath(L"<Created using Model_CreateEmpty>",NewModel->Model.ModelProperties.FileName);
			Result = DGE.IDFromPointer(NewModel);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Delete(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Delete",Model)
		} else {
			DGE.Delete_Model(pModel);
		}
	)
}

// The string buffer is the new name
// The return value is the new part index
int CDFPGECtrl::Model_Part_Create_InSB(int Model, int PreallocatedTriangleCount) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Create_InSB",Model)
			Result = -1;
		} else if (IsSimpleName(StringBuffer) == false) {
			swprintf_s( MQ->messageBuffer, L"Model_Part_Create_InSB: Names in models may not contain illegal characters. \"%s\" from the string buffer is not a valid part name.", StringBuffer);  MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		} else {
			Result = pModel->Model.CreateNewPart(StringBuffer,PreallocatedTriangleCount);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Part_Delete(int Model, int PartIndex) {
	START_OF_CRITICAL_SECTION
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Delete",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Delete",Model,PartIndex);
		} else {
			pModel->Model.DeletePart(PartIndex);
		}
	END_OF_CRITICAL_SECTION
}

void CDFPGECtrl::Model_Part_Delete_PreserveOrder(int Model, int PartIndex) {
	START_OF_CRITICAL_SECTION
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Delete_PreserveOrder",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Delete_PreserveOrder",Model,PartIndex);
		} else {
			pModel->Model.DeletePart_PreserveOrder(PartIndex);
		}
	END_OF_CRITICAL_SECTION
}

void CDFPGECtrl::Model_Part_SwapRenderingOrder(int Model, int PartIndexA, int PartIndexB) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SwapRenderingOrder",Model)
		} else if BAD_PART(Model,PartIndexA) {
			REPORT_PART(L"Model_Part_SwapRenderingOrder",Model,PartIndexA);
		} else if BAD_PART(Model,PartIndexB) {
			REPORT_PART(L"Model_Part_SwapRenderingOrder",Model,PartIndexB);
		} else {
			pModel->Model.SwapPartRenderingOrder(PartIndexA, PartIndexB);
		}
	)
}

int CDFPGECtrl::Model_GetNumberOfParts(int Model) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetNumberOfParts",Model)
			Result = -1;
		} else {
			Result = pModel->Model.GetNumberOfParts();
		}
	)
	return Result;
}

// Returns the name to the string buffer
void CDFPGECtrl::Model_Part_GetName_OutSB(int Model, int PartIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetName_OutSB",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetName_OutSB",Model,PartIndex);
		} else {
			FillSB(pModel->Model.GetPartName(PartIndex));
		}
	)
}

// The string buffer is the new name
void CDFPGECtrl::Model_Part_SetName_InSB(int Model, int PartIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetName_InSB",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetName_InSB",Model,PartIndex);
		} else if (IsSimpleName(StringBuffer) == false) {
			swprintf_s( MQ->messageBuffer, L"Model_Part_SetName_InSB: Names in models may not contain illegal characters. \"%s\" from the string buffer is not a valid part name.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
		} else {
			pModel->Model.SetPartName(PartIndex,StringBuffer);
		}
	)
}

// Returns the new triangle index
int CDFPGECtrl::Model_Part_InsertTriangle(int Model, int PartIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_InsertTriangle",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_InsertTriangle",Model,PartIndex);
			Result = -1;
		} else {
			Result = pModel->Model.InsertTriangleToPart(PartIndex);
		}
	)
	return Result;
}

int CDFPGECtrl::Model_Part_GetTriangleCount(int Model, int PartIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetTriangleCount",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetTriangleCount",Model,PartIndex);
			Result = -1;
		} else {
			Result = pModel->Model.GetTriangleCountFromPart(PartIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Part_Vertice_SetPos(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetPos",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetPos",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetPos",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetPos(PartIndex,TriangleIndex,VerticeIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetTexCoord(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float U1, float V1, float U2, float V2) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetTexCoord",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetTexCoord",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetTexCoord",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetTexCoord(PartIndex,TriangleIndex,VerticeIndex,DVector4(U1,V1,U2,V2));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetColor(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float Red, float Green, float Blue, float Alpha) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetColor",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetColor",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetColor",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetColor(PartIndex,TriangleIndex,VerticeIndex,DVector4(Red,Green,Blue,Alpha));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetNormal(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetNormal",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetNormal",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetNormal",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetNormal(PartIndex,TriangleIndex,VerticeIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetA(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float X, float Y, float Z, float W) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetA",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetA",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetA",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetA(PartIndex,TriangleIndex,VerticeIndex,DVector4(X,Y,Z,W));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetB(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float X, float Y, float Z, float W) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetB",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetB",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetB",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetB(PartIndex,TriangleIndex,VerticeIndex,DVector4(X,Y,Z,W));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetBoneData(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float X, float Y, float Z, float W) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetBoneData",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetBoneData",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetBoneData",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetBoneData(PartIndex,TriangleIndex,VerticeIndex,DVector4(X,Y,Z,W));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_SetSelected(int Model, int PartIndex, int TriangleIndex, int VerticeIndex, float Selected) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_SetSelected",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_SetSelected",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_SetSelected",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.Vertice_SetSelected(PartIndex,TriangleIndex,VerticeIndex,Selected);
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetPos_OutV3(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetPos_OutV3",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetPos_OutV3",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetPos_OutV3",Model,PartIndex,TriangleIndex);
		} else {
			SetVector3ToMB(pModel->Model.Vertice_GetPos(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetTexCoord_OutV4(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetTexCoord_OutV4",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetTexCoord_OutV4",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetTexCoord_OutV4",Model,PartIndex,TriangleIndex);
		} else {
			SetVector4ToMB(pModel->Model.Vertice_GetTexCoord(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetColor_OutV4(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetColor_OutV4",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetColor_OutV4",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetColor_OutV4",Model,PartIndex,TriangleIndex);
		} else {
			SetVector4ToMB(pModel->Model.Vertice_GetColor(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetNormal_OutV3(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetNormal_OutV3",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetNormal_OutV3",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetNormal_OutV3",Model,PartIndex,TriangleIndex);
		} else {
			SetVector3ToMB(pModel->Model.Vertice_GetNormal(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetA_OutV4(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetA_OutV4",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetA_OutV4",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetA_OutV4",Model,PartIndex,TriangleIndex);
		} else {
			SetVector4ToMB(pModel->Model.Vertice_GetA(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetB_OutV4(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetB_OutV4",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetB_OutV4",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetB_OutV4",Model,PartIndex,TriangleIndex);
		} else {
			SetVector4ToMB(pModel->Model.Vertice_GetB(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

void CDFPGECtrl::Model_Part_Vertice_GetBoneData_OutV4(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetBoneData_OutV4",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetBoneData_OutV4",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetBoneData_OutV4",Model,PartIndex,TriangleIndex);
		} else {
			SetVector4ToMB(pModel->Model.Vertice_GetBoneData(PartIndex,TriangleIndex,VerticeIndex));
		}
	)
}

float CDFPGECtrl::Model_Part_Vertice_GetSelected(int Model, int PartIndex, int TriangleIndex, int VerticeIndex) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Vertice_GetSelected",Model)
			Result = 0.0f;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Vertice_GetSelected",Model,PartIndex);
			Result = 0.0f;
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Vertice_GetSelected",Model,PartIndex,TriangleIndex);
			Result = 0.0f;
		} else {
			Result = pModel->Model.Vertice_GetSelected(PartIndex,TriangleIndex,VerticeIndex);
		}
	)
	return Result;
}

int CDFPGECtrl::Model_LoadFromFile_Aux(void) {
	int Result;
	Model_Struct* pModel;
	wchar_t* FileContent;
	wchar_t* BOM;
	Try_Start_Ctrl {
		if (lengthOfString_wide(StringBuffer) > 259) {
			MQ->InsertMessage(L"Model_LoadFromFile_InSB: The filename in the string buffer is too long.");
			Result = -1;
		}
	} Try_Else_Ctrl {
		swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while measuring the length of the filename.", Filename); MQ->InsertMessage(MQ->messageBuffer);
		Result = -1;
	}
	Try_Start_Ctrl {
		if (replaceAfterDot(StringBuffer,Filename,L"dmf") == false) {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because the filename is too long.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
	} Try_Else_Ctrl {
		swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while replacing the file extension.", Filename); MQ->InsertMessage(MQ->messageBuffer);
		Result = -1;
	}
	Try_Start_Ctrl {
		FileContent = LoadTextAsANSI_wide(Filename);
	} Try_Else_Ctrl {
		swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while loading the text.", Filename); MQ->InsertMessage(MQ->messageBuffer);
		Result = -1;
	}
	if (FileContent == NULL) {
		swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded.", Filename); MQ->InsertMessage(MQ->messageBuffer);
		Result = -1;
	} else {
		Try_Start_Ctrl {
			BOM = GetBOM_wide(FileContent);
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while reading the byte order mark.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
		if (BOM != NULL) {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" is not ANSI encoded. It is encoded as %s", Filename, BOM); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
		Try_Start_Ctrl {
			pModel = DGE.CreateEmptyModel();
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while creating an empty model.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
		Try_Start_Ctrl {
			DGE.Parser_AddModelDataFromString(&(pModel->Model),FileContent,Filename);
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while creating geometry from file content.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
		Try_Start_Ctrl {
			SAFE_DELETE(FileContent)
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while releasing an allocation of the file content.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
		
		Try_Start_Ctrl {
			CopyToFixedSizePath(Filename,pModel->Model.ModelProperties.FileName);
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while saving the filename to a fixed size string.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
		
		Try_Start_Ctrl {
			Result = DGE.IDFromPointer(pModel);
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be loaded because of access violation while getting the returned ID.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
	}
	return Result;
}

int CDFPGECtrl::Model_LoadFromFile_InSB(void) {
	int Result;
	CRITICAL_CODE_SECTION(
		Result = Model_LoadFromFile_Aux();
	)
	return Result;
}

int CDFPGECtrl::Model_SaveToFile_Aux(int Model) {
	int Result;
	Try_Start_Ctrl {
		if (lengthOfString_wide(StringBuffer) > 259) {
			MQ->InsertMessage(L"Model_SaveToFile_InSB: The filename in the string buffer is too long.");
			Result = 0;
		}
	} Try_Else_Ctrl {
		swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be saved because of access violation while measuring the length of the filename.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
		Result = -1;
	}
	if (replaceAfterDot(StringBuffer,Filename,L"dmf") == false) {
		swprintf_s( MQ->messageBuffer, L"Model_SaveToFile_InSB: The model \"%s\" could not be saved because the filename is too long.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
		Result = -1;
	} else {
		Try_Start_Ctrl {
			GET_FROM_REF(Model,Model)
			if BAD_REF(Model) {
				REPORT_TYPE(Model,L"Model_SaveToFile_InSB",Model)
				Result = 0;
			} else {
				char* NewFileContent;
				NewFileContent = DGE.Generator_WriteModelDataToString(pModel);
				if (SaveTextAsANSI(Filename,NewFileContent)) {
					Result = 1;
				} else {
					// Unable to save
					swprintf_s( MQ->messageBuffer, L"Model_SaveToFile_InSB: The model could not be saved to \"%s\".", Filename); MQ->InsertMessage(MQ->messageBuffer);
					Result = 0;
				}
				SAFE_DELETE(NewFileContent)
			}
		} Try_Else_Ctrl {
			swprintf_s( MQ->messageBuffer, L"Model_LoadFromFile_InSB: The model \"%s\" could not be saved because of access violation.", Filename); MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		}
	}
	return Result;
}

int CDFPGECtrl::Model_SaveToFile_InSB(int Model) {
	int Result;
	CRITICAL_CODE_SECTION(
		Result = Model_SaveToFile_Aux(Model);
	)
	return Result;
}

void CDFPGECtrl::Model_Part_SetTexture(int Model, int PartIndex, int TextureChannel, int Texture) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		GET_FROM_REF_ALLOW_ZERO(Texture,Texture)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetTexture",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetTexture",Model,PartIndex);
		} else if BAD_TEXTURE_CHANNEL(TextureChannel) {
			REPORT_TEXTURE_CHANNEL(L"Model_Part_SetTexture",TextureChannel);
		} else if (Texture == 0) {
			pModel->Model.SetPartTexture(PartIndex,TextureChannel,NULL);
		} else if BAD_REF(Texture) {
			MQ->InsertMessage(L"Model_Part_SetTexture: Texture is not 0 or a valid texture reference.");
		} else {
			if (pTexture->Locked == false) {
				MQ->InsertMessage(L"Model_Part_SetTexture: The texture is not locked and can be deleted by the engine. Only unlock resources when you are done with using them. Using unlocked resources is as bad as writing to unallocated memory.");
			}
			pModel->Model.SetPartTexture(PartIndex,TextureChannel,pTexture);
		}
	)
}

void CDFPGECtrl::Model_Part_SetTextureOverride(int Model, int PartIndex, int TextureChannel, int OverrideChannel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetTextureOverride",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetTextureOverride",Model,PartIndex);
		} else if BAD_TEXTURE_CHANNEL(TextureChannel) {
			REPORT_TEXTURE_CHANNEL(L"Model_Part_SetTextureOverride",TextureChannel);
		} else if (OverrideChannel < -1 || OverrideChannel > 15) {
			MQ->InsertMessage(L"Model_Part_SetTextureOverride: OverrideChannel is not a valid override channel. -1 means no override from the instance. 0..15 means that an instance texture in the given channel will be shown instead of the model's texture.");
		} else {
			pModel->Model.SetPartTextureOverride(PartIndex,TextureChannel,OverrideChannel);
		}
	)
}

void CDFPGECtrl::Model_Part_SetShader(int Model, int PartIndex, int ShaderChannel, int MaterialShader) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		GET_FROM_REF_ALLOW_ZERO(Shader,MaterialShader)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetShader",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetShader",Model,PartIndex);
		} else if BAD_SHADER_CHANNEL(ShaderChannel) {
			REPORT_SHADER_CHANNEL(L"Model_Part_SetShader",ShaderChannel)
		} else if (MaterialShader == 0) {
			pModel->Model.SetPartShader(PartIndex,ShaderChannel,NULL);
		} else if BAD_REF(MaterialShader) {
			MQ->InsertMessage(L"Model_Part_SetShader: MaterialShader is not 0 or a valid shader.");
		} else if (pMaterialShader->ShaderType != ShaderType_Material) {
			MQ->InsertMessage(L"Model_Part_SetShader: MaterialShader is a valid shader but not a material shader.");
		} else {
			if (pMaterialShader->Locked == false) {
				MQ->InsertMessage(L"Model_Part_SetShader: The shader is not locked and can be deleted by the engine. Only unlock resources when you are done with using them. Using unlocked resources is as bad as writing to unallocated memory.");
			}
			pModel->Model.SetPartShader(PartIndex,ShaderChannel,pMaterialShader);
		}
	)
}

int CDFPGECtrl::Model_Part_GetTexture(int Model, int PartIndex, int TextureChannel) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetTexture",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetTexture",Model,PartIndex);
			Result = -1;
		} else if BAD_TEXTURE_CHANNEL(TextureChannel) {
			REPORT_TEXTURE_CHANNEL(L"Model_Part_GetTexture",TextureChannel);
			Result = -1;
		} else {
			Texture_Struct* pTexture;
			pTexture = pModel->Model.GetPartTexture(PartIndex,TextureChannel);
			if BAD_REF(Texture) {
				Result = 0;
			} else {
				Result = DGE.IDFromPointer(pTexture);
			}
		}
	)
	return Result;
}

int CDFPGECtrl::Model_Part_GetTextureOverride(int Model, int PartIndex, int TextureChannel) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetTextureOverride",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetTextureOverride",Model,PartIndex);
			Result = -1;
		} else if BAD_TEXTURE_CHANNEL(TextureChannel) {
			REPORT_TEXTURE_CHANNEL(L"Model_Part_GetTextureOverride",TextureChannel);
			Result = -1;
		} else {
			Result = pModel->Model.GetPartTextureOverride(PartIndex,TextureChannel);
		}
	)
	return Result;
}

int CDFPGECtrl::Model_Part_GetShader(int Model, int PartIndex, int ShaderChannel) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetShader",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetShader",Model,PartIndex);
			Result = -1;
		} else if BAD_SHADER_CHANNEL(ShaderChannel) {
			REPORT_SHADER_CHANNEL(L"Model_Part_GetShader",ShaderChannel)
			Result = -1;
		} else {
			Shader_Struct* pShader;
			pShader = pModel->Model.GetPartShader(PartIndex,ShaderChannel);
			if BAD_REF(Shader) {
				Result = 0;
			} else {
				Result = DGE.IDFromPointer(pShader);
			}
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Part_SetTexture_ByName_InSB(int Model, int PartIndex, int TextureChannel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetTexture_ByName_InSB",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetTexture_ByName_InSB",Model,PartIndex);
		} else if BAD_TEXTURE_CHANNEL(TextureChannel) {
			REPORT_TEXTURE_CHANNEL(L"Model_Part_SetTexture_ByName_InSB",TextureChannel);
		} else if (lenStringBuffer == 0) {
			pModel->Model.SetPartTexture(PartIndex,TextureChannel,NULL);
		} else {
			// Load texture from resources
			if (IsSimpleName(StringBuffer) == false) {
				swprintf_s( MQ->messageBuffer, L"Model_Part_SetTexture_ByName_InSB: The extensionless filename in the string buffer may not contain illegal characters. \"%s\" is not an allowed filename in the engine.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
			} else {
				if (removeExtension(StringBuffer,Filename)) {
					pModel->Model.SetPartTexture(PartIndex,TextureChannel,DGE.Texture_Load(Filename,false));
				} else {
					swprintf_s( MQ->messageBuffer, L"Model_Part_SetTexture_ByName_InSB: The filename in the string buffer was too long. Filename = \"%s\".\n",StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
				}
			}
		}
	)
}

void CDFPGECtrl::Model_Part_SetShader_ByName_InSB(int Model, int PartIndex, int ShaderChannel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetShader_ByName_InSB",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetShader_ByName_InSB",Model,PartIndex);
		} else if BAD_SHADER_CHANNEL(ShaderChannel) {
			REPORT_SHADER_CHANNEL(L"Model_Part_SetShader_ByName_InSB",ShaderChannel)
		} else if (lenStringBuffer == 0) {
			pModel->Model.SetPartShader(PartIndex,ShaderChannel,NULL);
		} else {
			// Load from resources as material
			if (IsSimpleName(StringBuffer) == false) {
				swprintf_s( MQ->messageBuffer, L"Model_Part_SetShader_ByName_InSB: The filename in the string buffer may not contain illegal characters. \"%s\" is not an allowed filename in the engine.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
			} else {
				if (removeExtension(StringBuffer,Filename)) {
					pModel->Model.SetPartShader(PartIndex,ShaderChannel,DGE.Shader_Load(Filename,ShaderType_Material,false));
				} else {
					swprintf_s( MQ->messageBuffer, L"Model_Part_SetShader_ByName_InSB: The filename in the string buffer was too long. Filename = \"%s\".\n",StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
				}
			}
		}
	)
}

void CDFPGECtrl::Model_Part_GetTextureName_OutSB(int Model, int PartIndex, int TextureChannel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetTextureName_OutSB",Model)
			FillSB(L"");
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetTextureName_OutSB",Model,PartIndex);
		} else if BAD_TEXTURE_CHANNEL(TextureChannel) {
			REPORT_TEXTURE_CHANNEL(L"Model_Part_GetTextureName_OutSB",TextureChannel);
			FillSB(L"");
		} else {
			Texture_Struct* pTexture;
			pTexture = pModel->Model.GetPartTexture(PartIndex,TextureChannel);
			if BAD_REF(Texture) {
				FillSB(L"");
			} else {
				FillSB(pTexture->FileName);
			}
		}
	)
}

void CDFPGECtrl::Model_Part_GetShaderName_OutSB(int Model, int PartIndex, int ShaderChannel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetShaderName_OutSB",Model)
			FillSB(L"");
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetShaderName_OutSB",Model,PartIndex);
		} else if BAD_SHADER_CHANNEL(ShaderChannel) {
			REPORT_SHADER_CHANNEL(L"Model_Part_GetShaderName_OutSB",ShaderChannel)
			FillSB(L"");
		} else {
			Shader_Struct* pShader;
			pShader = pModel->Model.GetPartShader(PartIndex,ShaderChannel);
			if BAD_REF(Shader) {
				FillSB(L"");
			} else {
				FillSB(pShader->FileName);
			}
		}
	)
}

void CDFPGECtrl::Model_SetFilterUsingName_InSB(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_SetFilterUsingName_InSB",Model)
		} else {
			pModel->Model.SetFilterUsingName(StringBuffer,L"Model_SetFilterUsingName_InSB");
		}
	)
}

void CDFPGECtrl::Model_GetFilterName_OutSB(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetFilterName_OutSB",Model)
			FillSB(L"");
		} else {
			FillSB(pModel->Model.GetFilterName());
		}
	)
}

void CDFPGECtrl::Model_SetCullingUsingName_InSB(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_SetCullingUsingName_InSB",Model)
		} else {
			pModel->Model.SetCullingUsingName(StringBuffer,L"Model_SetCullingUsingName_InSB");
		}
	)
}

void CDFPGECtrl::Model_GetCullingName_OutSB(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetCullingName_OutSB",Model)
			FillSB(L"");
		} else {
			FillSB(pModel->Model.GetCullingName());
		}
	)
}

void CDFPGECtrl::Model_Part_DeleteTriangle(int Model, int PartIndex, int TriangleIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_DeleteTriangle",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_DeleteTriangle",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_DeleteTriangle",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.DeleteTriangle(PartIndex,TriangleIndex);
		}
	)
}

void CDFPGECtrl::Model_Part_DeleteTriangle_PreserveOrder(int Model, int PartIndex, int TriangleIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_DeleteTriangle_PreserveOrder",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_DeleteTriangle_PreserveOrder",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_DeleteTriangle_PreserveOrder",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.DeleteTriangle_PreserveOrder(PartIndex,TriangleIndex);
		}
	)
}

void CDFPGECtrl::Model_Part_SwapTriangleRenderingOrder(int Model, int PartIndex, int TriangleIndexA, int TriangleIndexB) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SwapTriangleRenderingOrder",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SwapTriangleRenderingOrder",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndexA) {
			REPORT_TRI(L"Model_Part_SwapTriangleRenderingOrder",Model,PartIndex,TriangleIndexA);
		} else if BAD_TRI(Model,PartIndex,TriangleIndexB) {
			REPORT_TRI(L"Model_Part_SwapTriangleRenderingOrder",Model,PartIndex,TriangleIndexB);
		} else {
			pModel->Model.SwapTriangleRenderingOrder(PartIndex,TriangleIndexA, TriangleIndexB);
		}
	)
}

int CDFPGECtrl::Model_CreateCopy(int SourceModel) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,SourceModel)
		if BAD_REF(SourceModel) {
			REPORT_TYPE(Model,L"Model_CreateCopy",SourceModel)
			Result = -1;
		} else {
			Result = DGE.IDFromPointer(DGE.Model_DuplicateModel(pSourceModel));
		}
	)
	return Result;
}

void CDFPGECtrl::Model_CopyAllParts(int SourceModel, int DestModel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,SourceModel)
		GET_FROM_REF(Model,DestModel)
		if BAD_REF(SourceModel) {
			REPORT_TYPE(Model,L"Model_CopyAllParts",SourceModel)
		} else if BAD_REF(DestModel) {
			REPORT_TYPE(Model,L"Model_CopyAllParts",DestModel)
		} else if (SourceModel == DestModel) {
			MQ->InsertMessage(L"Model_CopyAllParts: The source model is the destination model.");
		} else {
			DGE.Model_CopyAllParts(pSourceModel,pDestModel);
		}
	)
}

int CDFPGECtrl::Model_Part_Triangle_CreateCopy(int SourceModel, int SourcePartIndex, int SourceTriangleIndex, int DestModel, int DestPartIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,SourceModel)
		GET_FROM_REF(Model,DestModel)
		if BAD_REF(SourceModel) {
			REPORT_TYPE(Model,L"Model_Part_Triangle_CreateCopy",SourceModel);
			Result = -1;
		} else if BAD_REF(DestModel) {
			REPORT_TYPE(Model,L"Model_Part_Triangle_CreateCopy",DestModel);
			Result = -1;
		} else if BAD_PART(SourceModel,SourcePartIndex) {
			REPORT_PART(L"Model_Part_Triangle_CreateCopy",SourceModel,SourcePartIndex);
			Result = -1;
		} else if BAD_PART(DestModel,DestPartIndex) {
			REPORT_PART(L"Model_Part_Triangle_CreateCopy",DestModel,DestPartIndex);
			Result = -1;
		} else if BAD_TRI(SourceModel,SourcePartIndex,SourceTriangleIndex) {
			REPORT_TRI(L"Model_Part_Triangle_CreateCopy",SourceModel,SourcePartIndex,SourceTriangleIndex);
			Result = -1;
		} else {
			Result = DGE.Model_DuplicateTriangle(pDestModel,DestPartIndex,pSourceModel,SourcePartIndex,SourceTriangleIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Part_Triangle_Flip(int Model, int PartIndex, int TriangleIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_Triangle_Flip",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_Triangle_Flip",Model,PartIndex);
		} else if BAD_TRI(Model,PartIndex,TriangleIndex) {
			REPORT_TRI(L"Model_Part_Triangle_Flip",Model,PartIndex,TriangleIndex);
		} else {
			pModel->Model.FlipTriangle(PartIndex,TriangleIndex);
		}
	)
}

void CDFPGECtrl::Model_Part_SetMinDetailLevel(int Model, int PartIndex, int DetailLevel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetMinDetailLevel",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetMinDetailLevel",Model,PartIndex);
		} else if (DetailLevel < 0 || DetailLevel > 2) {
			MQ->InsertMessage(L"Model_Part_SetMinDetailLevel: DetailLevel is not a valid detail level. 0 = low, 1 = medium and 2 = high");
		} else {
			pModel->Model.SetPartMinDetailLevel(PartIndex,DetailLevel);
		}
	)
}

int CDFPGECtrl::Model_Part_GetMinDetailLevel(int Model, int PartIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetMinDetailLevel",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetMinDetailLevel",Model,PartIndex);
			Result = -1;
		} else {
			Result = pModel->Model.GetPartMinDetailLevel(PartIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Part_SetMaxDetailLevel(int Model, int PartIndex, int DetailLevel) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_SetMaxDetailLevel",Model)
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_SetMaxDetailLevel",Model,PartIndex);
		} else if (DetailLevel < 0 || DetailLevel > 2) {
			MQ->InsertMessage(L"Model_Part_SetMaxDetailLevel: DetailLevel is not a valid detail level. 0 = low, 1 = medium and 2 = high");
		} else {
			pModel->Model.SetPartMaxDetailLevel(PartIndex,DetailLevel);
		}
	)
}

int CDFPGECtrl::Model_Part_GetMaxDetailLevel(int Model, int PartIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Part_GetMaxDetailLevel",Model)
			Result = -1;
		} else if BAD_PART(Model,PartIndex) {
			REPORT_PART(L"Model_Part_GetMaxDetailLevel",Model,PartIndex);
			Result = -1;
		} else {
			Result = pModel->Model.GetPartMaxDetailLevel(PartIndex);
		}
	)
	return Result;
}

int CDFPGECtrl::Model_GetNumberOfBones(int Model) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetNumberOfBones",Model)
			Result = -1;
		} else {
			Result = pModel->Model.GetNumberOfBones();
		}
	)
	return Result;
}

int CDFPGECtrl::Model_Bone_Create_InSB(int Model) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_Create_InSB",Model)
			Result = -1;
		} else if (pModel->Model.GetNumberOfBones() >= MaxNumberOfBones) {
			MQ->InsertMessage(L"Model_Bone_Create_InSB: The bone could not be created because the model already contain the maximum number of bones.");
			Result = -1;
		} else if (IsSimpleName(StringBuffer) == false) {
			swprintf_s( MQ->messageBuffer, L"Model_Bone_Create_InSB: Names in models may not contain illegal characters. \"%s\" from the string buffer is not a valid bone name.", StringBuffer);  MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		} else {
			Result = pModel->Model.CreateNewBone(StringBuffer);
		}
	)
	return Result;
}

// Returns the name to the string buffer
void CDFPGECtrl::Model_Bone_GetName_OutSB(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetName_OutSB",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetName_OutSB",Model,BoneIndex);
		} else {
			FillSB(pModel->Model.GetBoneName(BoneIndex));
		}
	)
}

// The string buffer is the new name
void CDFPGECtrl::Model_Bone_SetName_InSB(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetName_InSB",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetName_InSB",Model,BoneIndex);
		} else if (IsSimpleName(StringBuffer) == false) {
			swprintf_s( MQ->messageBuffer, L"Model_Bone_SetName_InSB: Names in models may not contain illegal characters. \"%s\" from the string buffer is not a valid bone name.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
		} else {
			pModel->Model.SetBoneName(BoneIndex,StringBuffer);
		}
	)
}

void CDFPGECtrl::Model_Bone_SwapHierarchyOrder(int Model, int BoneIndexA, int BoneIndexB) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SwapHierarchyOrder",Model)
		} else if BAD_BONE(Model,BoneIndexA) {
			REPORT_BONE(L"Model_Bone_SwapHierarchyOrder",Model,BoneIndexA);
		} else if BAD_BONE(Model,BoneIndexB) {
			REPORT_BONE(L"Model_Bone_SwapHierarchyOrder",Model,BoneIndexB);
		} else {
			pModel->Model.SwapBoneHierarchyOrder(BoneIndexA, BoneIndexB);
		}
	)
}

void CDFPGECtrl::Model_Bone_SetParentIndex(int Model, int BoneIndex, int ParentIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetParentIndex",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetParentIndex",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetParentIndex(BoneIndex,ParentIndex);
		}
	)
}

int CDFPGECtrl::Model_Bone_GetParentIndex(int Model, int BoneIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetParentIndex",Model)
			Result = -1;
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetParentIndex",Model,BoneIndex);
			Result = -1;
		} else {
			Result = pModel->Model.Bone_GetParentIndex(BoneIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Bone_SetLength(int Model, int BoneIndex, float Length) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetLength",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetLength",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetLength(BoneIndex,Length);
		}
	)
}

float CDFPGECtrl::Model_Bone_GetLength(int Model, int BoneIndex) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetLength",Model)
			Result = 0.0f;
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetLength",Model,BoneIndex);
			Result = 0.0f;
		} else {
			Result = pModel->Model.Bone_GetLength(BoneIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Bone_SetObjectSpacePos(int Model, int BoneIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetObjectSpacePos",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetObjectSpacePos",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetObjectSpacePos(BoneIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Bone_GetObjectSpacePos_OutV3(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetObjectSpacePos_OutV3",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetObjectSpacePos_OutV3",Model,BoneIndex);
		} else {
			SetVector3ToMB(pModel->Model.Bone_GetObjectSpacePos(BoneIndex));
		}
	)
}

void CDFPGECtrl::Model_Bone_SetParentSpacePos(int Model, int BoneIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetParentSpacePos",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetParentSpacePos",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetParentSpacePos(BoneIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Bone_GetParentSpacePos_OutV3(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetParentSpacePos_OutV3",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetParentSpacePos_OutV3",Model,BoneIndex);
		} else {
			SetVector3ToMB(pModel->Model.Bone_GetParentSpacePos(BoneIndex));
		}
	)
}

void CDFPGECtrl::Model_Bone_SetYAxis(int Model, int BoneIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetYAxis",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetYAxis",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetYAxis(BoneIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Bone_GetYAxis_OutV3(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetYAxis_OutV3",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetYAxis_OutV3",Model,BoneIndex);
		} else {
			SetVector3ToMB(pModel->Model.Bone_GetYAxis(BoneIndex));
		}
	)
}

void CDFPGECtrl::Model_Bone_SetZAxis(int Model, int BoneIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetZAxis",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetZAxis",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetZAxis(BoneIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Bone_GetZAxis_OutV3(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetZAxis_OutV3",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetZAxis_OutV3",Model,BoneIndex);
		} else {
			SetVector3ToMB(pModel->Model.Bone_GetZAxis(BoneIndex));
		}
	)
}

void CDFPGECtrl::Model_Bone_SetUserData(int Model, int BoneIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_SetUserData",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_SetUserData",Model,BoneIndex);
		} else {
			pModel->Model.Bone_SetUserData(BoneIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Bone_GetUserData_OutV3(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_GetUserData_OutV3",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_GetUserData_OutV3",Model,BoneIndex);
		} else {
			SetVector3ToMB(pModel->Model.Bone_GetUserData(BoneIndex));
		}
	)
}

void CDFPGECtrl::Model_Bone_Delete(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_Delete",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_Delete",Model,BoneIndex);
		} else {
			pModel->Model.DeleteBone(BoneIndex);
		}
	)
}

void CDFPGECtrl::Model_Bone_Delete_PreserveOrder(int Model, int BoneIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Bone_Delete_PreserveOrder",Model)
		} else if BAD_BONE(Model,BoneIndex) {
			REPORT_BONE(L"Model_Bone_Delete_PreserveOrder",Model,BoneIndex);
		} else {
			pModel->Model.DeleteBone_PreserveOrder(BoneIndex);
		}
	)
}

float CDFPGECtrl::Model_GetBoundingSphereRadius(int Model) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetBoundingSphereRadius",Model)
			Result = 0.0f;
		} else {
			pModel->Model.UpdateEverythingIfNeeded();
			Result = pModel->Model.Radius;
		}
	)
	return Result;
}

float CDFPGECtrl::Model_GetBoundMultiplier(int Model) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetBoundMultiplier",Model)
			Result = 1.0f;
		} else {
			Result = pModel->Model.ModelProperties.BoundMultiplier;
		}
	)
	return Result;
}

void CDFPGECtrl::Model_SetBoundMultiplier(int Model, float Multiplier) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_SetBoundMultiplier",Model)
		} else {
			pModel->Model.ModelProperties.BoundMultiplier = Multiplier;
		}
	)
}

void CDFPGECtrl::Model_GetBoundingBoxMinimum_OutV3(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetBoundingBoxMinimum_OutV3",Model)
		} else {
			pModel->Model.UpdateEverythingIfNeeded();
			SetVector3ToMB(pModel->Model.ObjectSpaceMin);
		}
	)
}

void CDFPGECtrl::Model_GetBoundingBoxMaximum_OutV3(int Model) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetBoundingBoxMaximum_OutV3",Model)
		} else {
			pModel->Model.UpdateEverythingIfNeeded();
			SetVector3ToMB(pModel->Model.ObjectSpaceMax);
		}
	)
}

int CDFPGECtrl::Model_Shape_Create_InSB(int Model, int ShapeType) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_Create_InSB",Model)
			Result = -1;
		} else if (IsSimpleName(StringBuffer) == false) {
			swprintf_s( MQ->messageBuffer, L"Model_Shape_Create_InSB: Names in models may not contain illegal characters. \"%s\" from the string buffer is not a valid Shape name.", StringBuffer);  MQ->InsertMessage(MQ->messageBuffer);
			Result = -1;
		} else {
			Result = pModel->Model.CreateNewShape(StringBuffer, ShapeType);
		}
	)
	return Result;
}

// Returns the name to the string buffer
void CDFPGECtrl::Model_Shape_GetName_OutSB(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetName_OutSB",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetName_OutSB",Model,ShapeIndex);
		} else {
			FillSB(pModel->Model.GetShapeName(ShapeIndex));
		}
	)
}

// The string buffer is the new name
void CDFPGECtrl::Model_Shape_SetName_InSB(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetName_InSB",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetName_InSB",Model,ShapeIndex);
		} else if (IsSimpleName(StringBuffer) == false) {
			swprintf_s( MQ->messageBuffer, L"Model_Shape_SetName_InSB: Names in models may not contain illegal characters. \"%s\" from the string buffer is not a valid Shape name.", StringBuffer); MQ->InsertMessage(MQ->messageBuffer);
		} else {
			pModel->Model.SetShapeName(ShapeIndex,StringBuffer);
		}
	)
}

void CDFPGECtrl::Model_Shape_Delete(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_Delete",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_Delete",Model,ShapeIndex);
		} else {
			pModel->Model.DeleteShape(ShapeIndex);
		}
	)
}

void CDFPGECtrl::Model_Shape_Delete_PreserveOrder(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_Delete_PreserveOrder",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_Delete_PreserveOrder",Model,ShapeIndex);
		} else {
			pModel->Model.DeleteShape_PreserveOrder(ShapeIndex);
		}
	)
}

int CDFPGECtrl::Model_GetNumberOfShapes(int Model) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_GetNumberOfShapes",Model)
			Result = -1;
		} else {
			Result = pModel->Model.GetNumberOfShapes();
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_SetPos(int Model, int ShapeIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetPos",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetPos",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetPos(ShapeIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Shape_GetPos_OutV3(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetPos_OutV3",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetPos_OutV3",Model,ShapeIndex);
		} else {
			SetVector3ToMB(pModel->Model.Shape_GetPos(ShapeIndex));
		}
	)
}

void CDFPGECtrl::Model_Shape_SetXAxis(int Model, int ShapeIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetXAxis",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetXAxis",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetXAxis(ShapeIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Shape_GetXAxis_OutV3(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetXAxis_OutV3",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetXAxis_OutV3",Model,ShapeIndex);
		} else {
			SetVector3ToMB(pModel->Model.Shape_GetXAxis(ShapeIndex));
		}
	)
}

void CDFPGECtrl::Model_Shape_SetYAxis(int Model, int ShapeIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetYAxis",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetYAxis",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetYAxis(ShapeIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Shape_GetYAxis_OutV3(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetYAxis_OutV3",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetYAxis_OutV3",Model,ShapeIndex);
		} else {
			SetVector3ToMB(pModel->Model.Shape_GetYAxis(ShapeIndex));
		}
	)
}

void CDFPGECtrl::Model_Shape_SetZAxis(int Model, int ShapeIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetZAxis",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetZAxis",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetZAxis(ShapeIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Shape_GetZAxis_OutV3(int Model, int ShapeIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetZAxis_OutV3",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetZAxis_OutV3",Model,ShapeIndex);
		} else {
			SetVector3ToMB(pModel->Model.Shape_GetZAxis(ShapeIndex));
		}
	)
}

void CDFPGECtrl::Model_Shape_SetShapeType(int Model, int ShapeIndex, int ShapeType) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetShapeType",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetShapeType",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetShapeType(ShapeIndex,ShapeType);
		}
	)
}

int CDFPGECtrl::Model_Shape_GetShapeType(int Model, int ShapeIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetShapeType",Model)
			Result = -1;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetShapeType",Model,ShapeIndex);
			Result = -1;
		} else {
			Result = pModel->Model.Shape_GetShapeType(ShapeIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_SetCollisionType(int Model, int ShapeIndex, int CollisionType) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetCollisionType",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetCollisionType",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetCollisionType(ShapeIndex,CollisionType);
		}
	)
}

int CDFPGECtrl::Model_Shape_GetCollisionType(int Model, int ShapeIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetCollisionType",Model)
			Result = -1;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetCollisionType",Model,ShapeIndex);
			Result = -1;
		} else {
			Result = pModel->Model.Shape_GetCollisionType(ShapeIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_SetRadius(int Model, int ShapeIndex, float Radius) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetRadius",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetRadius",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetRadius(ShapeIndex,Radius);
		}
	)
}

float CDFPGECtrl::Model_Shape_GetRadius(int Model, int ShapeIndex) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetRadius",Model)
			Result = -1.0f;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetRadius",Model,ShapeIndex);
			Result = -1.0f;
		} else {
			Result = pModel->Model.Shape_GetRadius(ShapeIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_SetHalfWidth(int Model, int ShapeIndex, float HalfWidth) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetHalfWidth",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetHalfWidth",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetHalfWidth(ShapeIndex,HalfWidth);
		}
	)
}

float CDFPGECtrl::Model_Shape_GetHalfWidth(int Model, int ShapeIndex) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetHalfWidth",Model)
			Result = -1.0f;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetHalfWidth",Model,ShapeIndex);
			Result = -1.0f;
		} else {
			Result = pModel->Model.Shape_GetHalfWidth(ShapeIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_SetHalfHeight(int Model, int ShapeIndex, float HalfHeight) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetHalfHeight",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetHalfHeight",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetHalfHeight(ShapeIndex,HalfHeight);
		}
	)
}

float CDFPGECtrl::Model_Shape_GetHalfHeight(int Model, int ShapeIndex) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetHalfHeight",Model)
			Result = -1.0f;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetHalfHeight",Model,ShapeIndex);
			Result = -1.0f;
		} else {
			Result = pModel->Model.Shape_GetHalfHeight(ShapeIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_SetHalfDepth(int Model, int ShapeIndex, float HalfDepth) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetHalfDepth",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetHalfDepth",Model,ShapeIndex);
		} else {
			pModel->Model.Shape_SetHalfDepth(ShapeIndex,HalfDepth);
		}
	)
}

float CDFPGECtrl::Model_Shape_GetHalfDepth(int Model, int ShapeIndex) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetHalfDepth",Model)
			Result = -1.0f;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetHalfDepth",Model,ShapeIndex);
			Result = -1.0f;
		} else {
			Result = pModel->Model.Shape_GetHalfDepth(ShapeIndex);
		}
	)
	return Result;
}

int CDFPGECtrl::Model_Shape_GetNumberOfPoints(int Model, int ShapeIndex) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetNumberOfPoints",Model)
			Result = -1;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetNumberOfPoints",Model,ShapeIndex);
			Result = -1;
		} else {
			Result = pModel->Model.Shape_GetNumberOfPoints(ShapeIndex);
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_GetPoint_OutV3(int Model, int ShapeIndex, int PointIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetPoint_OutV3",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetPoint_OutV3",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndex) {
			REPORT_POINT(L"Model_Shape_GetPoint_OutV3",Model,ShapeIndex,PointIndex);
		} else {
			SetVector3ToMB(pModel->Model.Shape_GetPoint(ShapeIndex,PointIndex));
		}
	)
}

void CDFPGECtrl::Model_Shape_SetPoint(int Model, int ShapeIndex, int PointIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetPoint",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetPoint",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndex) {
			REPORT_POINT(L"Model_Shape_SetPoint",Model,ShapeIndex,PointIndex);
		} else {
			pModel->Model.Shape_SetPoint(ShapeIndex,PointIndex,DVector3(X,Y,Z));
		}
	)
}

void CDFPGECtrl::Model_Shape_GetPointDir_OutV3(int Model, int ShapeIndex, int PointIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		ClearMatrixBuffer();
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_GetPointDir_OutV3",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_GetPointDir_OutV3",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndex) {
			REPORT_POINT(L"Model_Shape_GetPointDir_OutV3",Model,ShapeIndex,PointIndex);
		} else {
			SetVector3ToMB(pModel->Model.Shape_GetPointDir(ShapeIndex,PointIndex));
		}
	)
}

void CDFPGECtrl::Model_Shape_SetPointDir(int Model, int ShapeIndex, int PointIndex, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SetPointDir",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SetPointDir",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndex) {
			REPORT_POINT(L"Model_Shape_SetPointDir",Model,ShapeIndex,PointIndex);
		} else {
			pModel->Model.Shape_SetPointDir(ShapeIndex,PointIndex,DVector3(X,Y,Z));
		}
	)
}

// Returns the new point index
int CDFPGECtrl::Model_Shape_InsertPoint(int Model, int ShapeIndex, float X, float Y, float Z) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_InsertPoint",Model)
			Result = -1;
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_InsertPoint",Model,ShapeIndex);
			Result = -1;
		} else {
			Result = pModel->Model.Shape_InsertPointToShape(ShapeIndex,DVector3(X,Y,Z));
		}
	)
	return Result;
}

void CDFPGECtrl::Model_Shape_DeletePoint(int Model, int ShapeIndex, int PointIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_DeletePoint",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_DeletePoint",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndex) {
			REPORT_POINT(L"Model_Shape_DeletePoint",Model,ShapeIndex,PointIndex);
		} else {
			pModel->Model.Shape_DeletePoint(ShapeIndex,PointIndex);
		}
	)
}

void CDFPGECtrl::Model_Shape_DeletePoint_PreserveOrder(int Model, int ShapeIndex, int PointIndex) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_DeletePoint_PreserveOrder",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_DeletePoint_PreserveOrder",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndex) {
			REPORT_POINT(L"Model_Shape_DeletePoint_PreserveOrder",Model,ShapeIndex,PointIndex);
		} else {
			pModel->Model.Shape_DeletePoint_PreserveOrder(ShapeIndex,PointIndex);
		}
	)
}

void CDFPGECtrl::Model_Shape_SwapOrder(int Model, int ShapeIndexA, int ShapeIndexB) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SwapOrder",Model)
		} else if BAD_SHAPE(Model,ShapeIndexA) {
			REPORT_SHAPE(L"Model_Shape_SwapOrder",Model,ShapeIndexA);
		} else if BAD_SHAPE(Model,ShapeIndexB) {
			REPORT_SHAPE(L"Model_Shape_SwapOrder",Model,ShapeIndexB);
		} else {
			pModel->Model.SwapShapeOrder(ShapeIndexA,ShapeIndexB);
		}
	)
}

void CDFPGECtrl::Model_Shape_SwapPointOrder(int Model, int ShapeIndex, int PointIndexA, int PointIndexB) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(Model,Model)
		if BAD_REF(Model) {
			REPORT_TYPE(Model,L"Model_Shape_SwapPointOrder",Model)
		} else if BAD_SHAPE(Model,ShapeIndex) {
			REPORT_SHAPE(L"Model_Shape_SwapPointOrder",Model,ShapeIndex);
		} else if BAD_POINT(Model,ShapeIndex,PointIndexA) {
			REPORT_POINT(L"Model_Shape_SwapPointOrder",Model,ShapeIndex,PointIndexA);
		} else if BAD_POINT(Model,ShapeIndex,PointIndexB) {
			REPORT_POINT(L"Model_Shape_SwapPointOrder",Model,ShapeIndex,PointIndexB);
		} else {
			pModel->Model.SwapPointOrder(ShapeIndex,PointIndexA,PointIndexB);
		}
	)
}
