//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007-2008)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: effect_d3d10.cpp
//      Краткое описание: Effect. DirectX 10 platform
//

#ifdef GD_D3D10

#include <Darkstar/Graphic System/Effect/effect.hpp>
#include <Darkstar/Kernel/logh.hpp>
#include <Darkstar/Graphic System/render_state.hpp>
#include <Darkstar/Graphic System/Effect/effect_manager.hpp>
#include <Darkstar/Graphic System/Direct3D/graphicDriver.hpp>

using namespace gs;
using ker::Log;

bool Effect::setBool(const std::string& name, const bool* value)
{
	return cur_technique->const_table->setBoolArray(name, value, 1);
};

bool Effect::setBoolArray(const std::string& name, const bool* values, const unsigned int count)
{
	return cur_technique->const_table->setBoolArray(name, values, count);
};

bool Effect::setFloat(const std::string& name, const float* value)
{
	return cur_technique->const_table->setFloatArray(name, value, 1);
};

bool Effect::setFloatArray(const std::string& name, const float* values, const unsigned int count)
{
	return cur_technique->const_table->setFloatArray(name, values, count);
};

bool Effect::setInt(const std::string& name, const int* value)
{
	return cur_technique->const_table->setIntArray(name, value, 1);
};

bool Effect::setIntArray(const std::string& name, const int* values, const unsigned int count)
{
	return cur_technique->const_table->setIntArray(name, values, count);
};

bool Effect::setMatrix4x4(const std::string& name, const math::Matr4* value)
{
	return cur_technique->const_table->setFloatArray(name, &math::Matr4(*value)[0][0], 16);
};
bool Effect::setMatrix4x4Array(const std::string& name, const math::Matr4* values, const unsigned int count)
{
	unsigned int float_number = count << 4;
	shared_array<float> nv;
	try
	{
		nv.reset(new float[float_number]);
	}
	catch(std::bad_alloc&)
	{
		lerr << "Cannot find enough memory to allocate. Size = " << (float_number << 2) << " bytes";
		return false;
	};
	for(unsigned int i = 0; i < count; ++i)
	{
		unsigned int pitch = i << 4;
		for(unsigned int j = 0; j < 4; ++j)
		{
			math::Vect4 row = values[i][j];
			unsigned int npitch = pitch + (j << 2);
			nv[npitch] = row.x;
			nv[npitch + 1] = row.y;
			nv[npitch + 2] = row.z;
			nv[npitch + 3] = row.w;
		};
	};
	return cur_technique->const_table->setFloatArray(name, nv.get(), float_number);
};

bool Effect::setVect2(const std::string& name, const math::Vect2* value)
{
	return cur_technique->const_table->setFloatArray(name, &(math::Vect2(*value))[0], 2);
};

bool Effect::setVect3(const std::string& name, const math::Vect3* value)
{
	return cur_technique->const_table->setFloatArray(name, &(math::Vect3(*value))[0], 3);
};

bool Effect::setVect3Array(const std::string& name, const math::Vect3* values, const unsigned int count)
{
	shared_array<float> nv;
	unsigned int float_num = count*4;
	try
	{
		nv.reset(new float[float_num]);
	}
	catch(std::bad_alloc&)
	{
		lerr << "Cannot find enough memory to allocate. Size = " << (float_num << 2) << " bytes";
		return false;
	};
	unsigned int index = 0;
	for(unsigned int i = 0; i < count; ++i)
	{
		index = i*4;
		nv[index] = values[i].x;
		nv[index + 1] = values[i].y;
		nv[index + 2] = values[i].z;
		nv[index + 3] = 0;
	};
	return cur_technique->const_table->setFloatArray(name, nv.get(), float_num);
};

bool Effect::setVect4(const std::string& name, const math::Vect4* value)
{
	return cur_technique->const_table->setFloatArray(name, &math::Vect4(*value)[0], 4);
};

bool Effect::setVect4Array(const std::string& name, const math::Vect4* values, const unsigned int count)
{
	unsigned int float_num = count << 2;
	shared_array<float> nv;
	try
	{
		nv.reset(new float[float_num]);
	}
	catch(std::bad_alloc&)
	{
		lerr << "Cannot find enough memory to allocate. Size = " << (float_num << 2) << " bytes";
		return false;
	};
	unsigned int index = 0;
	for(unsigned int i = 0 ; i < count; ++i)
	{
		index = i << 2;
		nv[index] = values[i].x;
		nv[index + 1] = values[i].y;
		nv[index + 2] = values[i].z;
		nv[index + 3] = values[i].w;
	};
	return cur_technique->const_table->setFloatArray(name, nv.get(), float_num);
};

bool Effect::setTexture(const std::string& name, const shared_ptr<rs::BaseTexture>& texture)
{
	if(!getIsConstantExist(name))
		return false;
	short ci = getConstantIndex(name);
	CONSTANT_TYPE type = cur_technique->const_table->getConstantType(name);
	ID3D10ShaderResourceView* srv = texture->getShaderResourceView();
	switch(type)
	{
	case VS_CONST:
		{
			GraphicDriver::ptr()->getDevice()->VSSetShaderResources(ci, 1, &srv);
		};break;
	case PS_CONST:
		{
			GraphicDriver::ptr()->getDevice()->PSSetShaderResources(ci, 1, &srv);
		};break;
	default:
		{
			lwar << "Error type of sample with name = " << name;
			return false;
		};
	};
	return true;
};

#endif


