
// 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::LightSource_GetAmbientLight_OutV3(void) {
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		SetVector3ToMB(DGE.m_AmbientLight);
	)
}

void CDFPGECtrl::LightSource_SetAmbientLight(float Red, float Green, float Blue) {
	CRITICAL_CODE_SECTION(
		DGE.m_AmbientLight = DVector3(Red,Green,Blue);
	)
}

int CDFPGECtrl::LightSource_Create_Point_Shadowless(float Pos_X, float Pos_Y, float Pos_Z, float Radius, float Red, float Green, float Blue) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Point_Shadowless(DVector3(Pos_X,Pos_Y,Pos_Z),Radius,DVector3(Red,Green,Blue)));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Point_Shadowless")
			Result = 0;
		}
	)
	return Result;
}

int CDFPGECtrl::LightSource_Create_Sun_Shadowless(float Dir_X, float Dir_Y, float Dir_Z, float Red, float Green, float Blue) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Sun_Shadowless(DVector3(Dir_X,Dir_Y,Dir_Z),DVector3(Red,Green,Blue)));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Sun_Shadowless")
			Result = 0;
		}
	)
	return Result;
}

int CDFPGECtrl::LightSource_Create_Spotlight_RoundAndSoft_Shadowless(float Pos_X, float Pos_Y, float Pos_Z, float Dir_X, float Dir_Y, float Dir_Z, float Up_X, float Up_Y, float Up_Z, float Radius, float Red, float Green, float Blue, float WidthSlope, float HeightSlope) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Spotlight_RoundAndSoft_Shadowless(DVector3(Pos_X,Pos_Y,Pos_Z),DVector3(Dir_X,Dir_Y,Dir_Z),DVector3(Up_X,Up_Y,Up_Z),Radius,DVector3(Red,Green,Blue), WidthSlope, HeightSlope));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Spotlight_RoundAndSoft_Shadowless")
			Result = 0;
		}
	)
	return Result;
}

int CDFPGECtrl::LightSource_Create_Spotlight_Atlas_Shadowless(float Pos_X, float Pos_Y, float Pos_Z, float Dir_X, float Dir_Y, float Dir_Z, float Up_X, float Up_Y, float Up_Z, float Radius, float Red, float Green, float Blue, float WidthSlope, float HeightSlope, float MinU, float MaxU, float MinV, float MaxV) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Spotlight_Atlas_Shadowless(DVector3(Pos_X,Pos_Y,Pos_Z),DVector3(Dir_X,Dir_Y,Dir_Z),DVector3(Up_X,Up_Y,Up_Z),Radius,DVector3(Red,Green,Blue), WidthSlope, HeightSlope, MinU, MaxU, MinV, MaxV));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Spotlight_Atlas_Shadowless")
			Result = 0;
		}
	)
	return Result;
}

int CDFPGECtrl::LightSource_Create_Spotlight_RoundAndSoft_Shadowcasting(float Pos_X, float Pos_Y, float Pos_Z, float Dir_X, float Dir_Y, float Dir_Z, float Up_X, float Up_Y, float Up_Z, float Radius, float Red, float Green, float Blue, float WidthSlope, float HeightSlope, float NearClip, float ShadowTransparency, int ResolutionGroup) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Spotlight_RoundAndSoft_Shadowcasting(DVector3(Pos_X,Pos_Y,Pos_Z),DVector3(Dir_X,Dir_Y,Dir_Z),DVector3(Up_X,Up_Y,Up_Z),Radius,DVector3(Red,Green,Blue), WidthSlope, HeightSlope,NearClip,ShadowTransparency,ResolutionGroup));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Spotlight_RoundAndSoft_Shadowcasting")
			Result = 0;
		}
	)
	return Result;
}

int CDFPGECtrl::LightSource_Create_Spotlight_Atlas_Shadowcasting(float Pos_X, float Pos_Y, float Pos_Z, float Dir_X, float Dir_Y, float Dir_Z, float Up_X, float Up_Y, float Up_Z, float Radius, float Red, float Green, float Blue, float WidthSlope, float HeightSlope, float MinU, float MaxU, float MinV, float MaxV, float NearClip, float ShadowTransparency, int ResolutionGroup) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Spotlight_Atlas_Shadowcasting(DVector3(Pos_X,Pos_Y,Pos_Z),DVector3(Dir_X,Dir_Y,Dir_Z),DVector3(Up_X,Up_Y,Up_Z),Radius,DVector3(Red,Green,Blue), WidthSlope, HeightSlope, MinU, MaxU, MinV, MaxV,NearClip,ShadowTransparency,ResolutionGroup));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Spotlight_Atlas_Shadowcasting")
			Result = 0;
		}
	)
	return Result;
}

int CDFPGECtrl::LightSource_Create_Sun_Shadowcasting_SingleLayer(float Pos_X, float Pos_Y, float Pos_Z, float Dir_X, float Dir_Y, float Dir_Z, float Up_X, float Up_Y, float Up_Z, float NearClip, float FarClip, float Red, float Green, float Blue, float HalfWidth, float HalfHeight, float ShadowTransparency, int ResolutionGroup, float OutsideIntensity, float FadeSize) {
	int Result;
	CRITICAL_CODE_SECTION(
		if (DGE.m_Running) {
			Result = DGE.IDFromPointer(DGE.LightSource_Create_Sun_Shadowcasting_SingleLayer(DVector3(Pos_X,Pos_Y,Pos_Z),DVector3(Dir_X,Dir_Y,Dir_Z),DVector3(Up_X,Up_Y,Up_Z),NearClip,FarClip,DVector3(Red,Green,Blue),HalfWidth,HalfHeight,ShadowTransparency,ResolutionGroup,OutsideIntensity,FadeSize));
		} else {
			REPORT_NOT_RUNNING(L"LightSource_Create_Sun_Shadowcasting_SingleLayer")
			Result = 0;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_Delete(int LightSource) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_Delete",LightSource)
		} else {
			DGE.Delete_LightSource(pLightSource);
		}
	)
}

void CDFPGECtrl::LightSource_SetRadius(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetRadius",LightSource)
		} else {
			pLightSource->ShaderData.Radius = NewValue;
		}
	)
}

float CDFPGECtrl::LightSource_GetRadius(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetRadius",LightSource)
		} else {
			Result = pLightSource->ShaderData.Radius;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetNearClip(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetNearClip",LightSource)
		} else if (pLightSource->IsOrthogonal == 0 && NewValue < 0.001f) {
			pLightSource->ShaderData.NearClip = 0.001f;
		} else {
			pLightSource->ShaderData.NearClip = NewValue;
		}
	)
}

float CDFPGECtrl::LightSource_GetNearClip(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetNearClip",LightSource)
		} else {
			Result = pLightSource->ShaderData.NearClip;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetWidthSlope(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetWidthSlope",LightSource)
		} else {
			pLightSource->ShaderData.WidthSlope = NewValue;
		}
	)
}

float CDFPGECtrl::LightSource_GetWidthSlope(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetWidthSlope",LightSource)
		} else {
			Result = pLightSource->ShaderData.WidthSlope;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetHeightSlope(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetHeightSlope",LightSource)
		} else {
			pLightSource->ShaderData.HeightSlope = NewValue;
		}
	)
}

float CDFPGECtrl::LightSource_GetHeightSlope(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetHeightSlope",LightSource)
		} else {
			Result = pLightSource->ShaderData.HeightSlope;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetColor(int LightSource, float Red, float Green, float Blue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetColor",LightSource)
		} else {
			pLightSource->ShaderData.Color = DVector3(Red,Green,Blue);
		}
	)
}

void CDFPGECtrl::LightSource_GetColor_OutV3(int LightSource) {
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetColor_OutV3",LightSource)
		} else {
			SetVector3ToMB(pLightSource->ShaderData.Color);
		}
	)
}

void CDFPGECtrl::LightSource_SetPos(int LightSource, float X, float Y, float Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetPos",LightSource)
		} else {
			pLightSource->ShaderData.Pos = DVector3(X,Y,Z);
		}
	)
}

void CDFPGECtrl::LightSource_GetPos_OutV3(int LightSource) {
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetPos_OutV3",LightSource)
		} else {
			SetVector3ToMB(pLightSource->ShaderData.Pos);
		}
	)
}

void CDFPGECtrl::LightSource_SetDirection(int LightSource, float Dir_X, float Dir_Y, float Dir_Z, float Up_X, float Up_Y, float Up_Z) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetDirection",LightSource)
		} else {
			DVector3 NormalizedUpVector;
			DVector3 NormalizedDirection;
			NormalizedDirection = NormalizeVec3(DVector3(Dir_X,Dir_Y,Dir_Z));
			NormalizedUpVector = NormalizeVec3(DVector3(Up_X,Up_Y,Up_Z));
			pLightSource->ShaderData.ZAxis = NormalizedDirection;
			pLightSource->ShaderData.XAxis = NormalizeVec3(CrossVec3(NormalizedUpVector,NormalizedDirection));
			pLightSource->ShaderData.YAxis = NormalizeVec3(CrossVec3(NormalizedDirection,pLightSource->ShaderData.XAxis));
		}
	)
}

void CDFPGECtrl::LightSource_GetAxisSystem_OutM3(int LightSource) {
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetAxisSystem_OutM3",LightSource)
		} else {
			X1 = pLightSource->ShaderData.XAxis.x;
			Y1 = pLightSource->ShaderData.XAxis.y;
			Z1 = pLightSource->ShaderData.XAxis.z;
			X2 = pLightSource->ShaderData.YAxis.x;
			Y2 = pLightSource->ShaderData.YAxis.y;
			Z2 = pLightSource->ShaderData.YAxis.z;
			X3 = pLightSource->ShaderData.ZAxis.x;
			Y3 = pLightSource->ShaderData.ZAxis.y;
			Z3 = pLightSource->ShaderData.ZAxis.z;
		}
	)
}

void CDFPGECtrl::LightSource_SetTextureAtlasRect(int LightSource, float MinU, float MaxU, float MinV, float MaxV) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetTextureAtlasRect",LightSource)
		} else {
			pLightSource->ShaderData.TextureAtlasRect = DVector4(MinU, MaxU, MinV, MaxV);
		}
	)
}

void CDFPGECtrl::LightSource_GetTextureAtlasRect_OutV4(int LightSource) {
	CRITICAL_CODE_SECTION(
		ClearMatrixBuffer();
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetTextureAtlasRect_OutV4",LightSource)
		} else {
			SetVector4ToMB(pLightSource->ShaderData.TextureAtlasRect);
		}
	)
}

void CDFPGECtrl::LightSource_SetShadowTransparency(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetShadowTransparency",LightSource)
		} else {
			pLightSource->ShaderData.ShadowTransparency = ClampFloat(0.0f,NewValue,1.0f);
		}
	)
}

float CDFPGECtrl::LightSource_GetShadowTransparency(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetShadowTransparency",LightSource)
		} else {
			Result = pLightSource->ShaderData.ShadowTransparency;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetResolutionGroup(int LightSource, int NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetResolutionGroup",LightSource)
		} else {
			if (NewValue < 0) {
				pLightSource->ResolutionGroup = 0;
			} else if (NewValue > QASmallestSize) {
				pLightSource->ResolutionGroup = QASmallestSize;
			} else {
				pLightSource->ResolutionGroup = NewValue;
			}
		}
	)
}

int CDFPGECtrl::LightSource_GetResolutionGroup(int LightSource) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetResolutionGroup",LightSource)
		} else {
			Result = pLightSource->ResolutionGroup;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_ClearShadows(void) {
	CRITICAL_CODE_SECTION(
		DGE.ClearShadows();
	)
}

void CDFPGECtrl::LightSource_SetDepthAtlasResolution(int WidthAndHeight) {
	CRITICAL_CODE_SECTION(
		if (WidthAndHeight != 1024 && WidthAndHeight != 2048 && WidthAndHeight != 4096 && WidthAndHeight != 8192) {
			swprintf_s( MQ->messageBuffer, L"LightSource_SetDepthAtlasResolution: %i is not a valid resolution for the depth buffer. WidthAndHeight must be 1024, 2048, 4096 or 8192.", WidthAndHeight);  MQ->InsertMessage(MQ->messageBuffer);
		} else {
			DGE.DepthBuffer_SetSize(&DGE.m_DepthAtlas, WidthAndHeight, WidthAndHeight);
			DGE.ClearShadows();
		}
	)
}

int CDFPGECtrl::LightSource_GetDepthAtlasResolution(void) {
	int Result;
	CRITICAL_CODE_SECTION(
		Result = DGE.m_DepthAtlas.CurrentWidth;
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetOutsideIntensity(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetOutsideIntensity",LightSource)
		} else {
			pLightSource->OutsideIntensity = ClampFloat(0.0f, NewValue, 1.0f);
		}
	)
}

float CDFPGECtrl::LightSource_GetOutsideIntensity(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetOutsideIntensity",LightSource)
		} else {
			Result = pLightSource->OutsideIntensity;
		}
	)
	return Result;
}


void CDFPGECtrl::LightSource_SetFadeSize(int LightSource, float NewValue) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetFadeSize",LightSource)
		} else {
			pLightSource->FadeSize = ClampFloat(0.001f, NewValue, 1.0f);
		}
	)
}

float CDFPGECtrl::LightSource_GetFadeSize(int LightSource) {
	float Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetFadeSize",LightSource)
		} else {
			Result = pLightSource->FadeSize;
		}
	)
	return Result;
}

void CDFPGECtrl::LightSource_SetEnabled(int LightSource, bool Enabled) {
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_SetEnabled",LightSource)
		} else {
			pLightSource->EnabledByUser = Enabled;
		}
	)
}

int CDFPGECtrl::LightSource_GetEnabled(int LightSource) {
	int Result;
	CRITICAL_CODE_SECTION(
		GET_FROM_REF(LightSource,LightSource)
		if BAD_REF(LightSource) {
			REPORT_TYPE(LightSource,L"LightSource_GetEnabled",LightSource)
		} else {
			if (pLightSource->EnabledByUser) {
				Result = 1;
			} else {
				Result = 0;
			}
		}
	)
	return Result;
}
