//-----------------------------------------------------------------------
bool HardwareSkinning::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
{
	bool isValid = true;
	Technique* pFirstTech = srcPass->getParent()->getParent()->getTechnique(0);
	const Any& hsAny = pFirstTech->getUserObjectBindings().getUserAny(HS_DATA_BIND_NAME);

	if (hsAny.isEmpty() == false)
	{
		HardwareSkinning::SkinningData pData =
			(any_cast<HardwareSkinning::SkinningData>(hsAny));
		isValid = pData.isValid;
		
		//If the skinning data is being passed through the material, we need to create an instance of the appropriate
		//skinning type and set its parameters here
		setHardwareSkinningParam(pData.maxBoneCount, pData.maxWeightCount, pData.skinningType, 
					 pData.correctAntipodalityHandling, pData.scalingShearingSupport);
	}

	//If there is no associated technique, default to linear skinning as a pass-through
	if(mActiveTechnique.isNull())
	{
		setHardwareSkinningParam(0, 0, ST_LINEAR, false, false);
	}

	int boneCount = mActiveTechnique->getBoneCount();
	int weightCount = mActiveTechnique->getWeightCount();

	bool doBoneCalculations =  isValid &&
		(boneCount != 0) && (boneCount <= 256) &&
		(weightCount != 0) && (weightCount <= 4) &&
		((mCreator == NULL) || (boneCount <= mCreator->getMaxCalculableBoneCount()));

	mActiveTechnique->setDoBoneCalculations(doBoneCalculations);

	if ((doBoneCalculations) && (mCreator))
	{
		//update the receiver and caster materials
		if (dstPass->getParent()->getShadowCasterMaterial().isNull())
		{
			dstPass->getParent()->setShadowCasterMaterial(
				mCreator->getCustomShadowCasterMaterial(mSkinningType, weightCount - 1));
		}

		if (dstPass->getParent()->getShadowReceiverMaterial().isNull())
		{
			dstPass->getParent()->setShadowReceiverMaterial(
				mCreator->getCustomShadowReceiverMaterial(mSkinningType, weightCount - 1));
		}
	}

	return true;
}
	//------------------------------------------------------------------------
	MatGenParams MaterialUtil::getMatGenParams(const MaterialPtr& _material)
	{
		if(!_material->getNumTechniques())
			return MatGenParams();
		
		Technique* technique = _material->getTechnique(0);
		UserObjectBindings& uob = technique->getUserObjectBindings();
		Any matGenParamsAny = uob.getUserAny( USER_MAT_GEN_PARAMS );
		
		if(matGenParamsAny.isEmpty())
			return MatGenParams();

		return *any_cast<MatGenParams>(&matGenParamsAny);
	}
	//------------------------------------------------------------------------
	MtlPtr MaterialUtil::getMtl(const MaterialPtr& _material)
	{
		if(!_material->getNumTechniques())
			return MtlPtr();
		
		Technique* technique = _material->getTechnique(0);
		UserObjectBindings& uob = technique->getUserObjectBindings();
		Any mtlAny = uob.getUserAny( USER_MTL );
		
		if(mtlAny.isEmpty())
			return MtlPtr();

		MtlPtr mtl = *any_cast<MtlPtr>(&mtlAny);
		return mtl;		
	}
		static MaterialInternal* get(const MaterialPtr& _material)
		{
			Technique* technique = _material->getTechnique(0);
			UserObjectBindings& uob = technique->getUserObjectBindings();
			const Any& any = uob.getUserAny();
			if(any.isEmpty())
			{
				MaterialInternal* ret = new MaterialInternal;
				uob.setUserAny(Any(MaterialInternalPtr(ret)));
				return ret;
			}
			MaterialInternalPtr ptr = any.operator ()<MaterialInternalPtr>();
			MaterialInternal* ret = ptr.get();
			return ret;
		}
	//------------------------------------------------------------------------
	MtlPtr MaterialUtil::getMtl(const MaterialPtr& _material, MatGenParams& _rMatGenParams)
	{
		if(!_material->getNumTechniques())
			return MtlPtr();
		
		Technique* technique = _material->getTechnique(0);
		UserObjectBindings& uob = technique->getUserObjectBindings();
		Any mtlAny = uob.getUserAny( USER_MTL );
		Any matGenParamsAny = uob.getUserAny( USER_MAT_GEN_PARAMS );
		
		if(mtlAny.isEmpty() || matGenParamsAny.isEmpty())
			return MtlPtr();

		MtlPtr mtl = *any_cast<MtlPtr>(&mtlAny);
		_rMatGenParams = *any_cast<MatGenParams>(&matGenParamsAny);
		return mtl;	
	}
	//------------------------------------------------------------------------
	MaterialPtr MaterialUtil::generateMaterial(const MtlPtr& _mtl, const MatGenParams& _matGenParams)
	{
		MaterialPtr material;
		Mtl::MaterialHandles::iterator it = _mtl->mMaterialHandles.find(_matGenParams);
		if(it != _mtl->mMaterialHandles.end())
		{
			// Material was generated already, just return it
			// (Materials can be shared.)
			ResourceHandle handle = it->second;
			material = MaterialManager::getSingleton().getByHandle(handle);
		}
		else
		{
			// Generate a new material
			String materialName = s_MaterialNameGenerator.generate();
			material = MaterialManager::getSingleton().create(materialName, StringUtil::BLANK);
			
			// We need a material generator.
			MaterialGenerator* generator = MaterialGeneratorRegistration::getSingleton().getGenerator();

			// Initalise the material with the specified params.
			generator->_updateMaterial(material, _mtl, _matGenParams);

			// Store the smart pointer to the mtl and the material generation params
			// in the material's "user any" member.
			if(!material->getNumTechniques())
			{
				MaterialManager::getSingleton().remove( (ResourcePtr) material);
				return MaterialPtr();
			}
			Technique* technique = material->getTechnique(0);
			UserObjectBindings& uob = technique->getUserObjectBindings();
			uob.setUserAny( USER_MTL, (Any) _mtl );
			uob.setUserAny( USER_MAT_GEN_PARAMS, (Any) _matGenParams );

			// Store the handle to the new material in the mtl.
			ResourceHandle handle = material->getHandle();
			_mtl->mMaterialHandles.insert(std::make_pair(_matGenParams, handle));
		}
		return material;
	}