// Copyright Epic Games, Inc. All Rights Reserved.

#include "DatasmithMaxWriter.h"

#include "DatasmithExportOptions.h"
#include "DatasmithMaxSceneParser.h"

FString FDatasmithMaxMatWriter::DumpBitmapThea(TSharedPtr<IDatasmithCompositeTexture>& CompTex, BitmapTex* InBitmapTex, const TCHAR* Prefix, bool bForceInvert, bool bIsGrayscale)
{
	BitmapTex* Texture = (BitmapTex*)InBitmapTex->GetReference(0);
	return DumpBitmap(CompTex, Texture, Prefix, bForceInvert, bIsGrayscale);
}

void FDatasmithMaxMatWriter::GetTheaTexmap(TSharedRef< IDatasmithScene > DatasmithScene, BitmapTex* InBitmapTex)
{
	BitmapTex* Texture = (BitmapTex*)InBitmapTex->GetReference(0);
	GetRegularTexmap(DatasmithScene, Texture);
}

void FDatasmithMaxMatWriter::ExportTheaSubmaterial(TSharedRef< IDatasmithScene > DatasmithScene, TSharedPtr< IDatasmithShaderElement >& MaterialShader, Mtl* Material, EDSMaterialType MaterialType)
{
	int NumParamBlocks = Material->NumParamBlocks();

	bool bDiffuseTexEnable = false;
	bool bReflectanceTexEnable = false;
	bool bReflectance90TexEnable = false;
	bool bTranslucentTexEnable = false;
	bool bReflectanceEnable = false;
	bool bTransmittanceTexEnable = false;
	bool bAbsorptionTexEnable = false;
	bool bNormalEnable = false;

	float BumpAmount = 0.f;
	float Roughness = 0.1f;

	for (int j = 0; j < NumParamBlocks; j++)
	{
		IParamBlock2* ParamBlock2 = Material->GetParamBlockByID((short)j);
		// The the descriptor to 'decode'
		ParamBlockDesc2* ParamBlockDesc = ParamBlock2->GetDesc();
		// Loop through all the defined parameters therein
		for (int i = 0; i < ParamBlockDesc->count; i++)
		{
			const ParamDef& ParamDefinition = ParamBlockDesc->paramdefs[i];

			if (FCString::Stricmp(ParamDefinition.int_name, TEXT("diffuse_tex")) == 0)
			{
				if (ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime()) != NULL)
				{
					bDiffuseTexEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance_tex")) == 0)
			{
				if (ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime()) != NULL)
				{
					bReflectanceEnable = true;
					bReflectanceTexEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance90_tex")) == 0)
			{
				if (ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime()) != NULL)
				{
					bReflectance90TexEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("translucent_tex")) == 0)
			{
				if (ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime()) != NULL)
				{
					bTranslucentTexEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("transmittance_tex")) == 0)
			{
				if (ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime()) != NULL)
				{
					bTransmittanceTexEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("coat_absorption_tex")) == 0)
			{
				if (ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime()) != NULL)
				{
					bAbsorptionTexEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance")) == 0)
			{
				BMM_Color_fl Color = (BMM_Color_fl)ParamBlock2->GetColor(ParamDefinition.ID, GetCOREInterface()->GetTime());
				if (!(Color.r == 0 && Color.g == 0 && Color.b == 0))
				{
					bReflectanceEnable = true;
				}
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("normal")) == 0)
			{
				bNormalEnable = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("bump")) == 0)
			{
				BumpAmount = (float)ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("Roughness")) == 0)
			{
				Roughness = (float)ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) / 100.0f;
			}
		}
		ParamBlock2->ReleaseDesc();
	}

	for (int j = 0; j < NumParamBlocks; j++)
	{
		IParamBlock2* ParamBlock2 = Material->GetParamBlockByID((short)j);
		// The the descriptor to 'decode'
		ParamBlockDesc2* ParamBlockDesc = ParamBlock2->GetDesc();
		// Loop through all the defined parameters therein
		for (int i = 0; i < ParamBlockDesc->count; i++)
		{
			const ParamDef& ParamDefinition = ParamBlockDesc->paramdefs[i];

			if (MaterialType == EDSMaterialType::TheaBasic)
			{
				if (FCString::Stricmp(ParamDefinition.int_name, TEXT("use_custom_curve")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("fresnel_curve_values")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("trace_refl")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("absorption_val")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("IOR")) == 0)
				{
					MaterialShader->SetIOR( ParamBlock2->GetFloat(ParamDefinition.ID, GetCOREInterface()->GetTime()) );
					MaterialShader->SetIORRefra( ParamBlock2->GetFloat(ParamDefinition.ID, GetCOREInterface()->GetTime()) );
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("extinction")) == 0)
				{
					MaterialShader->SetIORk( ParamBlock2->GetFloat(ParamDefinition.ID, GetCOREInterface()->GetTime()) );
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("sigma")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("anisotropy")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("micro_on")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("micro_height")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("micro_width")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("aniso_rot")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("diffuse_tex")) == 0 && bDiffuseTexEnable == true)
				{
					Texmap* LocalTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
					DumpTexture(DatasmithScene, MaterialShader->GetDiffuseComp(), LocalTex, DATASMITH_DIFFUSETEXNAME, DATASMITH_DIFFUSECOLNAME, false, false);
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("Diffuse")) == 0 && bDiffuseTexEnable == false)
				{
					BMM_Color_fl Color = (BMM_Color_fl)ParamBlock2->GetColor(ParamDefinition.ID, GetCOREInterface()->GetTime());

					// compensation since thea color picker is not affected by colorGamma
					Color.r = pow(Color.r, FDatasmithExportOptions::ColorGamma);
					Color.g = pow(Color.g, FDatasmithExportOptions::ColorGamma);
					Color.b = pow(Color.b, FDatasmithExportOptions::ColorGamma);
					MaterialShader->GetDiffuseComp()->AddSurface(FDatasmithMaxMatHelper::MaxColorToFLinearColor(Color));
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance_tex")) == 0 && bReflectanceTexEnable == true)
				{
					Texmap* LocalTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
					DumpTexture(DatasmithScene, MaterialShader->GetRefleComp(), LocalTex, DATASMITH_REFLETEXNAME, DATASMITH_REFLECOLNAME, false, false);
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance")) == 0 && bReflectanceTexEnable == false)
				{
					BMM_Color_fl Color = (BMM_Color_fl)ParamBlock2->GetColor(ParamDefinition.ID, GetCOREInterface()->GetTime());

					// compensation since thea color picker is not affected by colorGamma
					Color.r = pow(Color.r, FDatasmithExportOptions::ColorGamma);
					Color.g = pow(Color.g, FDatasmithExportOptions::ColorGamma);
					Color.b = pow(Color.b, FDatasmithExportOptions::ColorGamma);
					if (Color.r != 0 || Color.g != 0 || Color.b != 0)
					{
						MaterialShader->GetRefleComp()->AddSurface(FDatasmithMaxMatHelper::MaxColorToFLinearColor(Color));
					}
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("translucent_tex")) == 0 && bTranslucentTexEnable == true)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("Translucent")) == 0 && bTranslucentTexEnable == false)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance90_tex")) == 0 && bReflectance90TexEnable == true && bReflectanceEnable == true)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("reflectance90")) == 0 && bReflectance90TexEnable == false && bReflectanceEnable == true)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("absorption_col")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("sigma_tex")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("roughness_tex")) == 0)
				{
					Texmap* LocalTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
					if (LocalTex)
					{
						if (Roughness == 1)
						{
							DumpTexture(DatasmithScene, MaterialShader->GetRoughnessComp(), LocalTex, DATASMITH_ROUGHNESSTEXNAME, DATASMITH_ROUGHNESSVALUENAME, false, true);
						}
						else
						{
							DumpWeightedTexture(DatasmithScene, MaterialShader->GetRoughnessComp(), LocalTex, BMM_Color_fl(0.0, 0.0, 0.0, 0.0), Roughness, DATASMITH_ROUGHNESSTEXNAME, DATASMITH_ROUGHNESSVALUENAME, false, true);
						}
					}
					else
					{
						// already readed roughnessvalue
						if (!bReflectanceEnable)
						{
							MaterialShader->GetRoughnessComp()->AddParamVal1( IDatasmithCompositeTexture::ParamVal(0.75f, TEXT("Roughness")) );
						}
						else
						{
							MaterialShader->GetRoughnessComp()->AddParamVal1( IDatasmithCompositeTexture::ParamVal(Roughness, TEXT("Roughness")) );
						}
					}
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("anisotropy_tex")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("aniso_rot_tex")) == 0)
				{
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("bump_tex")) == 0)
				{
					Texmap* LocalTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
					if (BumpAmount > 0 && LocalTex != NULL)
					{
						MaterialShader->SetBumpAmount( sqrt(BumpAmount / 100.0f) );
						if (bNormalEnable)
						{
							DumpNormalTexture(DatasmithScene, MaterialShader->GetNormalComp(), LocalTex, DATASMITH_NORMALTEXNAME, DATASMITH_NORMALTEXNAME, false, false);
						}
						else
						{
							if (FDatasmithMaxMatHelper::GetTextureClass(LocalTex) == EDSBitmapType::NormalMap)
							{
								DumpTexture(DatasmithScene, MaterialShader->GetNormalComp(), LocalTex, DATASMITH_NORMALTEXNAME, DATASMITH_NORMALTEXNAME, false, false);
								DumpTexture(DatasmithScene, MaterialShader->GetBumpComp(), LocalTex, DATASMITH_BUMPTEXNAME, DATASMITH_BUMPTEXNAME, false, true);
							}
							else
							{
								DumpTexture(DatasmithScene, MaterialShader->GetBumpComp(), LocalTex, DATASMITH_BUMPTEXNAME, DATASMITH_BUMPTEXNAME, false, true);
							}
						}
					}
				}
			}
			// glossy
			else if (MaterialType == EDSMaterialType::TheaGlossy)
			{
				Texmap* GlossyTransTex = NULL;
				BMM_Color_fl GlossyTransColor = BMM_Color_fl(0, 0, 0, 0);
				if (FCString::Stricmp(ParamDefinition.int_name, TEXT("transmittance_tex")) == 0 && bTransmittanceTexEnable == true)
				{
					Texmap* LocalTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
					GlossyTransTex = LocalTex;
					DumpTexture(DatasmithScene, MaterialShader->GetTransComp(), LocalTex, DATASMITH_TRANSPTEXNAME, DATASMITH_TRANSPCOLNAME, false, false);
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("transmittance")) == 0 && bTransmittanceTexEnable == false)
				{
					BMM_Color_fl Color = (BMM_Color_fl)ParamBlock2->GetColor(ParamDefinition.ID, GetCOREInterface()->GetTime());

					// compensation since thea color picker is not affected by colorGamma
					Color.r = pow(Color.r, FDatasmithExportOptions::ColorGamma);
					Color.g = pow(Color.g, FDatasmithExportOptions::ColorGamma);
					Color.b = pow(Color.b, FDatasmithExportOptions::ColorGamma);
					GlossyTransColor = Color;
					MaterialShader->GetTransComp()->AddSurface(FDatasmithMaxMatHelper::MaxColorToFLinearColor(Color));
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("roughnessTr_on")) == 0)
				{
					// mBsdf.setBooleanParameter("Rough Tr.",(bool)ParamBlock2->GetInt(ParamDefinition.ID,GetCOREInterface()->GetTime()));
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("roughnessTr")) == 0)
				{
					// mBsdf.setRealParameter("Roughness Tr.",(float)ParamBlock2->GetInt(ParamDefinition.ID,GetCOREInterface()->GetTime())/100.0f);
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("roughnessTr_tex")) == 0)
				{
					/*Texmap* LocalTex =ParamBlock2->GetTexmap(ParamDefinition.ID,GetCOREInterface()->GetTime());
					addCustomTexture(LocalTex,mBsdf,"./Roughness Tr. Map/");*/
					continue;
				}

				if (GlossyTransTex == NULL && GlossyTransColor.r == 0 && GlossyTransColor.g == 0 && GlossyTransColor.b == 0)
				{
					MaterialShader->SetMetal(1.0);
				}
			}
			// COATING
			else if (MaterialType == EDSMaterialType::TheaCoating)
			{
				if (FCString::Stricmp(ParamDefinition.int_name, TEXT("coat_absorption_col")) == 0 && bAbsorptionTexEnable == false)
				{
					/*BMM_Color_fl Color = (BMM_Color_fl)ParamBlock2->GetColor(ParamDefinition.ID, GetCOREInterface()->GetTime());
					if (!(Color.r == 0 && Color.g == 0 && Color.b == 0))
					{
					TheaSDK::Texture mTex = (TheaSDK::Texture)mBsdf.addObject("./Absorption Map/", "Constant Texture", "");
					mTex.setRgbParameter("Color", TheaSDK::Rgb(Color.r, Color.g, Color.b));
					}*/
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("coat_absorption_tex")) == 0 && bAbsorptionTexEnable == true)
				{
					/*Texmap* LocalTex =ParamBlock2->GetTexmap(ParamDefinition.ID,GetCOREInterface()->GetTime());
					addCustomTexture(LocalTex,mBsdf,"./Absorption Map/");*/
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("thickness_tex")) == 0)
				{
					/*Texmap* LocalTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
					addCustomTexture(LocalTex, mBsdf, "./Thickness Map/");*/
					continue;
				}
			}
			// THIN FILM
			else if (MaterialType == EDSMaterialType::TheaFilm)
			{
				if (FCString::Stricmp(ParamDefinition.int_name, TEXT("thin_bump")) == 0)
				{
					// mBsdf.setRealParameter("Bump Strength",(float)ParamBlock2->GetInt(ParamDefinition.ID,GetCOREInterface()->GetTime())/100.0f);
					continue;
				}
				else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("thin_normal")) == 0)
				{
					// mBsdf.setBooleanParameter("Normal Mapping",(bool)ParamBlock2->GetInt(ParamDefinition.ID,GetCOREInterface()->GetTime()));
					continue;
				}
			}
		}
		ParamBlock2->ReleaseDesc();
	}

	if (MaterialType == EDSMaterialType::TheaFilm)
	{
		BMM_Color_fl Color(1.0f, 1.0f, 1.0f, 1.0f);
		MaterialShader->GetRefleComp()->AddSurface(FDatasmithMaxMatHelper::MaxColorToFLinearColor(Color));
		MaterialShader->SetIORRefra(1.05);
	}
}

void FDatasmithMaxMatWriter::ExportTheaMaterial(TSharedRef< IDatasmithScene > DatasmithScene, TSharedPtr< IDatasmithMaterialElement >& MaterialElement, Mtl* Material)
{
	TSharedPtr< IDatasmithShaderElement > MaterialShader = FDatasmithSceneFactory::CreateShader((TCHAR*)Material->GetName().data());

	int NumParamBlocks = Material->NumParamBlocks();
	Mtl* SubMaterial = NULL;
	bool bClippingEnabled;

	Mtl* LayerMtl[4] = {NULL, NULL, NULL, NULL};
	Mtl* StackedMtl[4] = {NULL, NULL, NULL, NULL};

	Texmap* LayerMtlMask[4] = {NULL, NULL, NULL, NULL};
	Texmap* StackedMtlMask[4] = {NULL, NULL, NULL, NULL};

	float LayerMtlWeight[4] = {0, 0, 0, 0};
	float StackedMtlWeight[4] = {0, 0, 0, 0};

	bool bClipEnabled = false;
	Texmap* ClipTex = NULL;
	bool bSoftClip = false;
	bool bClipByAmount = false;
	float ClipAmount = 1.0;

	bool bDisplaceEnabled = true;
	Texmap* DisplaceTex = NULL;
	int DisplaceSubdivs = 4;
	float DisplaceAmount = 10;

	bool bEmitEnabled = false;
	int EmitMode = 0;
	BMM_Color_fl EmitColor = 0;
	Texmap* EmitTex = 0;
	int EmitKelvin = 0;
	int EmitUnit = 0;
	float EmitPower = 0;

	// read layered (horizontal) and stacked (vertical) materials
	for (int j = 0; j < NumParamBlocks; j++)
	{
		IParamBlock2* ParamBlock2 = Material->GetParamBlockByID((short)j);
		// The the descriptor to 'decode'
		ParamBlockDesc2* ParamBlockDesc = ParamBlock2->GetDesc();
		// Loop through all the defined parameters therein
		for (int i = 0; i < ParamBlockDesc->count; i++)
		{
			const ParamDef& ParamDefinition = ParamBlockDesc->paramdefs[i];

			if (FCString::Stricmp(ParamDefinition.int_name, TEXT("clip_enabled")) == 0)
			{
				bClippingEnabled = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("materialList")) == 0)
			{
				LayerMtl[0] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 0);
				LayerMtl[1] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 1);
				LayerMtl[2] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 2);
				LayerMtl[3] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 3);
				StackedMtl[0] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 4);
				StackedMtl[1] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 5);
				StackedMtl[2] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 6);
				StackedMtl[3] = ParamBlock2->GetMtl(ParamDefinition.ID, GetCOREInterface()->GetTime(), 7);
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("maskList")) == 0)
			{
				LayerMtlMask[0] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 0);
				LayerMtlMask[1] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 1);
				LayerMtlMask[2] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 2);
				LayerMtlMask[3] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 3);
				StackedMtlMask[0] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 4);
				StackedMtlMask[1] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 5);
				StackedMtlMask[2] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 6);
				StackedMtlMask[3] = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime(), 7);
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("amountList")) == 0)
			{
				LayerMtlWeight[0] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 0)) / 100.0f;
				LayerMtlWeight[1] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 1)) / 100.0f;
				LayerMtlWeight[2] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 2)) / 100.0f;
				LayerMtlWeight[3] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 3)) / 100.0f;
				StackedMtlWeight[0] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 4)) / 100.0f;
				StackedMtlWeight[1] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 5)) / 100.0f;
				StackedMtlWeight[2] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 6)) / 100.0f;
				StackedMtlWeight[3] = float(ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime(), 7)) / 100.0f;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("disp_enabled")) == 0)
			{
				bDisplaceEnabled = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("clip_enabled")) == 0)
			{
				bClipEnabled = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("clip_tex")) == 0)
			{
				ClipTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("disp_tex")) == 0)
			{
				DisplaceTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("soft")) == 0)
			{
				bSoftClip = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("visibility")) == 0)
			{
				bClipByAmount = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("visibilityValue")) == 0)
			{
				ClipAmount = ParamBlock2->GetFloat(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("disp_height")) == 0)
			{
				DisplaceAmount = ParamBlock2->GetFloat(ParamDefinition.ID, GetCOREInterface()->GetTime()) * 2.0f;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("disp_subdiv")) == 0)
			{
				DisplaceSubdivs = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("emit_enabled")) == 0)
			{
				bEmitEnabled = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime()) != 0;
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("emit_color_scale")) == 0)
			{
				EmitMode = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("EmitColor")) == 0)
			{
				EmitColor = (BMM_Color_fl)ParamBlock2->GetColor(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("emit_tex")) == 0)
			{
				EmitTex = ParamBlock2->GetTexmap(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("emit_kelvin")) == 0)
			{
				EmitKelvin = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("unit")) == 0)
			{
				EmitUnit = ParamBlock2->GetInt(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
			else if (FCString::Stricmp(ParamDefinition.int_name, TEXT("power")) == 0)
			{
				EmitPower = ParamBlock2->GetFloat(ParamDefinition.ID, GetCOREInterface()->GetTime());
			}
		}
		ParamBlock2->ReleaseDesc();
	}

	if (bClipEnabled)
	{
		if (ClipTex)
		{
			if (bSoftClip)
			{
				DumpTexture(DatasmithScene, MaterialShader->GetMaskComp(), ClipTex, DATASMITH_CLIPTEXNAME, DATASMITH_CLIPTEXNAME, false, true);
			}
			else
			{
				DumpTexture(DatasmithScene, MaterialShader->GetTransComp(), ClipTex, DATASMITH_TRANSPTEXNAME, DATASMITH_TRANSPCOLNAME, false, false);
			}
		}
		else
		{
			if (bClipByAmount)
			{
				float ColorValue = 1.0f - ClipAmount;
				BMM_Color_fl Color(ColorValue, ColorValue, ColorValue, 1.0f);
				// compensation since thea color picker is not affected by colorGamma
				Color.r = pow(Color.r, FDatasmithExportOptions::ColorGamma);
				Color.g = pow(Color.g, FDatasmithExportOptions::ColorGamma);
				Color.b = pow(Color.b, FDatasmithExportOptions::ColorGamma);
				MaterialShader->GetTransComp()->AddSurface(FDatasmithMaxMatHelper::MaxColorToFLinearColor(Color));
			}
		}
	}

	if (bDisplaceEnabled)
	{
		if (DisplaceTex)
		{
			DumpTexture(DatasmithScene, MaterialShader->GetDisplaceComp(), DisplaceTex, DATASMITH_CLIPTEXNAME, DATASMITH_CLIPTEXNAME, false, true);
			MaterialShader->SetDisplace( DisplaceAmount );
			MaterialShader->SetDisplaceSubDivision( DisplaceSubdivs );
		}
	}

	if (bEmitEnabled)
	{
		if (EmitMode == 0)
		{
			if (EmitTex)
			{
				DumpTexture(DatasmithScene, MaterialShader->GetEmitComp(), EmitTex, DATASMITH_EMITTEXNAME, DATASMITH_EMITCOLNAME, false, false);
			}
			else
			{
				// compensation since thea color picker is not affected by colorGamma
				EmitColor.r = pow(EmitColor.r, FDatasmithExportOptions::ColorGamma);
				EmitColor.g = pow(EmitColor.g, FDatasmithExportOptions::ColorGamma);
				EmitColor.b = pow(EmitColor.b, FDatasmithExportOptions::ColorGamma);
				MaterialShader->GetEmitComp()->AddSurface(FDatasmithMaxMatHelper::MaxColorToFLinearColor(EmitColor));
			}
		}
		else
		{
			MaterialShader->SetEmitTemperature( (float)EmitKelvin );
		}
	}

	TArray< TSharedPtr< IDatasmithShaderElement > > AllShaders;
	AllShaders.Add(MaterialShader);
	// Export the first valid layered material
	for (int i = 3; i >= 0; i--)
	{
		if (LayerMtl[i] != NULL)
		{
			if (FDatasmithMaxMatHelper::GetMaterialClass(LayerMtl[i]) == EDSMaterialType::TheaBasic || FDatasmithMaxMatHelper::GetMaterialClass(LayerMtl[i]) == EDSMaterialType::TheaGlossy || FDatasmithMaxMatHelper::GetMaterialClass(LayerMtl[i]) == EDSMaterialType::TheaFilm)
			{
				SubMaterial = LayerMtl[i];
			}
		}
	}

	if (SubMaterial != NULL)
	{

		// DatasmithShaderElement MaterialShader((TCHAR*)Material->GetName().data());
		switch (FDatasmithMaxMatHelper::GetMaterialClass(SubMaterial))
		{
		case EDSMaterialType::TheaBasic:
			ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), SubMaterial, EDSMaterialType::TheaBasic);
			break;
		case EDSMaterialType::TheaGlossy:
			ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), SubMaterial, EDSMaterialType::TheaGlossy);
			break;
		case EDSMaterialType::TheaFilm:
			ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), SubMaterial, EDSMaterialType::TheaFilm);
			break;
		}
	}

	// Export the stacked material, coating is a special case

	int CoatingLayer = -1;
	for (int i = 0; i < 4; i++)
	{
		if (StackedMtl[i] != NULL)
		{
			if (FDatasmithMaxMatHelper::GetMaterialClass(StackedMtl[i]) == EDSMaterialType::TheaCoating)
			{
				CoatingLayer = i;
			}
			else
			{
				TSharedPtr< IDatasmithShaderElement > MatShaderStacked = FDatasmithSceneFactory::CreateShader((TCHAR*)StackedMtl[i]->GetName().data());
				AllShaders.Add(MatShaderStacked);

				switch (FDatasmithMaxMatHelper::GetMaterialClass(StackedMtl[i]))
				{
				case EDSMaterialType::TheaBasic:
					ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), StackedMtl[i], EDSMaterialType::TheaBasic);
					break;
				case EDSMaterialType::TheaGlossy:
					ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), StackedMtl[i], EDSMaterialType::TheaGlossy);
					break;
				case EDSMaterialType::TheaFilm:
					ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), StackedMtl[i], EDSMaterialType::TheaFilm);
					break;
				}

				AllShaders.Last()->SetBlendMode( EDatasmithBlendMode::Alpha );
				AllShaders.Last()->SetIsStackedLayer(true);

				if (StackedMtlMask[i])
				{
					DumpTexture(DatasmithScene, AllShaders.Last()->GetWeightComp(), StackedMtlMask[i], DATASMITH_DIFFUSETEXNAME, DATASMITH_DIFFUSECOLNAME, false, false);
				}
				else
				{
					AllShaders.Last()->GetWeightComp()->AddParamVal1( IDatasmithCompositeTexture::ParamVal(StackedMtlWeight[i], TEXT("StackedMatWeight")) );
				}
			}
		}
	}

	// if reflection is only on the coating we put it on the base
	if (CoatingLayer != -1 && AllShaders.Num() == 1 && AllShaders[0]->GetRefleComp()->GetParamSurfacesCount() == 0)
	{
		ExportTheaSubmaterial(DatasmithScene, AllShaders[0], StackedMtl[CoatingLayer], EDSMaterialType::TheaCoating); // overwrite some parameters like reflection
	}
	else
	{
		if (CoatingLayer != -1)
		{
			TSharedPtr< IDatasmithShaderElement > MatShaderStacked = FDatasmithSceneFactory::CreateShader((TCHAR*)StackedMtl[CoatingLayer]->GetName().data());
			AllShaders.Add(MatShaderStacked);

			ExportTheaSubmaterial(DatasmithScene, AllShaders.Last(), StackedMtl[CoatingLayer], EDSMaterialType::TheaCoating);

			AllShaders.Last()->SetBlendMode( EDatasmithBlendMode::ClearCoat );
			AllShaders.Last()->SetIsStackedLayer(true);

			if (StackedMtlMask[CoatingLayer])
			{
				DumpTexture(DatasmithScene, AllShaders.Last()->GetWeightComp(), StackedMtlMask[CoatingLayer], DATASMITH_DIFFUSETEXNAME, DATASMITH_DIFFUSECOLNAME, false, false);
			}
			else
			{
				AllShaders.Last()->GetWeightComp()->AddParamVal1( IDatasmithCompositeTexture::ParamVal(StackedMtlWeight[CoatingLayer], TEXT("StackedWeight")) );
			}
		}
	}

	for (int i = 1; i < AllShaders.Num(); i++)
	{
		AllShaders[i]->SetDisplace( AllShaders[0]->GetDisplace() );
		AllShaders[i]->SetDisplaceComp( AllShaders[0]->GetDisplaceComp() );
		AllShaders[i]->SetDisplaceSubDivision( AllShaders[0]->GetDisplaceSubDivision() );

		AllShaders[i]->SetEmitComp( AllShaders[0]->GetEmitComp() );
		AllShaders[i]->SetEmitPower( AllShaders[0]->GetEmitPower() );
		AllShaders[i]->SetEmitTemperature( AllShaders[0]->GetEmitTemperature() );

		AllShaders[i]->SetMaskComp( AllShaders[0]->GetMaskComp() );
	}

	for (int i = 0; i < AllShaders.Num(); i++)
	{
		MaterialElement->AddShader(AllShaders[i]);
	}
}
