//----------------------------------------------------------------------------
MaterialTechnique *MaterialInstance::_RefreshMaterial(
	const std::string &mtlFilename,
	const std::string &intanceTechName, ShaderParametersPtr* &vp,
	ShaderParametersPtr* &pp, bool shareMtl, MaterialPtr &outMtl, 
	int &outTechIndex)
{
	// we reload the mtl
	outMtl = PX2_MATERIALMAN.GetMaterial(mtlFilename.c_str(), 
		intanceTechName.c_str(), shareMtl);
	assertion(outMtl != 0, "Material must be specified.\n");

	MaterialTechnique* technique = outMtl->GetTechnique(intanceTechName,
		outTechIndex);

	int newNumPass = technique->GetNumPasses();
	if (0 == vp)
		vp = new1<ShaderParametersPtr>(newNumPass);
	if (0 == pp)
		pp = new1<ShaderParametersPtr>(newNumPass);

	for (int p = 0; p < newNumPass; ++p)
	{
		MaterialPass* pass = technique->GetPass(p);
		VertexShader *vs = pass->GetVertexShader();
		PixelShader *ps = pass->GetPixelShader();

		_CreateConstants(vp[p], vs);
		_CreateConstants(pp[p], ps);
	}

	return technique;
}
//----------------------------------------------------------------------------
MaterialInstance::MaterialInstance (const Material* material,
											int techniqueIndex)
											:
mMaterial((Material*)material),  // conceptual constness
mIsShareMtl(false),
mTechniqueIndex(techniqueIndex),
mNumPasses(0),
mVertexParameters(0),
mPixelParameters(0),
mIsNeedUpdate(false)
{
	assertion(material != 0, "Material must be specified.\n");
	assertion(
		0 <= techniqueIndex && techniqueIndex < material->GetNumTechniques(),
		"Invalid technique index.\n");

	MaterialTechnique* technique = mMaterial->GetTechnique(mTechniqueIndex);
	mNumPasses = technique->GetNumPasses();
	mVertexParameters = new1<ShaderParametersPtr>(mNumPasses);
	mPixelParameters = new1<ShaderParametersPtr>(mNumPasses);
	int p;
	for (p = 0; p < mNumPasses; ++p)
	{
		MaterialPass* pass = technique->GetPass(p);
		mVertexParameters[p] =
			new0 ShaderParameters(pass->GetVertexShader());
		mVertexParameters[p]->SetName("VParams_" + StringHelp::IntToString(p));
		mPixelParameters[p] =
			new0 ShaderParameters(pass->GetPixelShader());
		mPixelParameters[p]->SetName("PParams_" + StringHelp::IntToString(p));
	}
}
//----------------------------------------------------------------------------
void MaterialInstance::Update(double appTime, double elapsedTime)
{
	PX2_UNUSED(appTime);
	PX2_UNUSED(elapsedTime);

	if (mIsNeedUpdate)
	{
		if (!mMaterialFilename.empty() && !mInstanceTechName.empty())
		{
			MaterialPtr newMaterial;
			int newTechIndex = 0;
			ShaderParametersPtr *newVertexParameters = 0;
			ShaderParametersPtr *newPixelParameters = 0;

			MaterialTechnique *tech = _RefreshMaterial(mMaterialFilename, mInstanceTechName,
				newVertexParameters, newPixelParameters, mIsShareMtl, newMaterial, newTechIndex);
			int newNumPasses = tech->GetNumPasses();

			if (newNumPasses <= mNumPasses)
			{
				for (int i = 0; i < newNumPasses; i++)
				{
					_CopyParams(mVertexParameters[i], newVertexParameters[i]);
					_CopyParams(mPixelParameters[i], newPixelParameters[i]);

					newMaterial->GetPass(newTechIndex, i)->SetAlphaProperty(mMaterial->GetAlphaProperty(mTechniqueIndex, i));
					newMaterial->GetPass(newTechIndex, i)->SetCullProperty(mMaterial->GetCullProperty(mTechniqueIndex, i));
					newMaterial->GetPass(newTechIndex, i)->SetDepthProperty(mMaterial->GetDepthProperty(mTechniqueIndex, i));
					newMaterial->GetPass(newTechIndex, i)->SetOffsetProperty(mMaterial->GetOffsetProperty(mTechniqueIndex, i));
					newMaterial->GetPass(newTechIndex, i)->SetStencilProperty(mMaterial->GetStencilProperty(mTechniqueIndex, i));
					newMaterial->GetPass(newTechIndex, i)->SetWireProperty(mMaterial->GetWireProperty(mTechniqueIndex, i));


				}
			}

			for (int i = 0; i < mNumPasses; i++) 
			{
				mVertexParameters[i] = 0;
				mPixelParameters[i] = 0;
			}
			delete1(mVertexParameters);
			delete1(mPixelParameters);

			mNumPasses = newNumPasses;
			mMaterial = newMaterial;
			mTechniqueIndex = newTechIndex;
			mVertexParameters = newVertexParameters;
			mPixelParameters = newPixelParameters;
		}

		mIsNeedUpdate = false;
	}

	_SetDepthTexture();
}
//----------------------------------------------------------------------------
MaterialInstance::MaterialInstance(const std::string &mtlFilename, 
	const std::string &techName, bool shareMtl) :
	mIsShareMtl(shareMtl),
	mTechniqueIndex(0),
	mMaterialFilename(mtlFilename),
	mInstanceTechName(techName),
	mNumPasses(0),
	mVertexParameters(0),
	mPixelParameters(0),
	mIsNeedUpdate(false)
{
	MaterialTechnique *tech = _RefreshMaterial(mMaterialFilename, mInstanceTechName,
		mVertexParameters, mPixelParameters, mIsShareMtl, mMaterial, mTechniqueIndex);

	mNumPasses = tech->GetNumPasses();
}
//-----------------------------------------------------------------------------
void ProjTreeItem::SetTreeLevel(ProjTreeLevel level, bool isShowHelpNode)
{
	mTreeLevel = level;
	mIsShowHelpNode = isShowHelpNode;

	Project *proj = DynamicCast<Project>(mObject);
	Scene *scene = DynamicCast<Scene>(mObject);
	if (proj || scene)
		return;

	Actor *actor = DynamicCast<Actor>(mObject);
	Movable *mov = DynamicCast<Movable>(mObject);
	Node *node = DynamicCast<Node>(mObject);
	Renderable *renderable = DynamicCast<Renderable>(mObject);
	EffectableController *effectableCtrl = DynamicCast<EffectableController>(mObject);
	Material *mtl = DynamicCast<Material>(mObject);
	MaterialTechnique *mtlTechnique = DynamicCast<MaterialTechnique>(mObject);
	MaterialPass *mtlPass = DynamicCast<MaterialPass>(mObject);

	if (!mObject)
	{ // IT_CATALOG
		for (int i = 0; i < (int)mChildItems.size(); i++)
		{
			ProjTreeItem *item = mChildItems[i];
			if (item) item->SetTreeLevel(level, isShowHelpNode);
		}
		return;
	}
	else
	{
		ClearChildren();
	}

	bool addCtrl = false;
	bool addModule = false;
	bool addNode = false;
	bool addMaterial = false;

	if (PTL_GENERAL == mTreeLevel)
	{
	}
	else if (PTL_CHILDREN == mTreeLevel)
	{
		if (!scene && !proj && node)
		{
			addNode = true;
		}
	}
	else if (PTL_CONTROLS == mTreeLevel)
	{
		if (!scene && !proj && mov)
		{
			addCtrl = true;
		}

		if (!scene && !proj && node)
		{
			addNode = true;
		}

		if (effectableCtrl)
		{
			addModule = true;
		}
	}
	else if (PTL_MATERIALS == mTreeLevel)
	{
		if (!scene && !proj && mov)
		{
			addCtrl = true;
		}

		if (!scene && !proj && node)
		{
			addNode = true;
		}

		if (renderable)
		{
			addMaterial = true;
		}
	}
	else if (PTL_DETAIL == mTreeLevel)
	{
		if (!scene && !proj && mov)
		{
			addCtrl = true;
		}

		if (!scene && !proj && node)
		{
			addNode = true;
		}

		if (renderable)
		{
			addMaterial = true;
		}
	}

	if (addCtrl)
	{
		int numCtrls = mov->GetNumControllers();
		for (int i = 0; i < numCtrls; i++)
		{
			Controller *ctrl = mov->GetController(i);

			AddChild(ctrl, mIconID, mTreeLevel, mIsShowHelpNode);
		}
	}

	if (addMaterial)
	{
		MaterialInstance *mtlInst = renderable->GetMaterialInstance();
		Material *mtl = mtlInst->GetMaterial();
		AddChild(mtl, mIconID, mTreeLevel, mIsShowHelpNode);
	}
	if (mtl)
	{
		int numTechniques = mtl->GetNumTechniques();
		for (int i = 0; i < numTechniques; i++)
		{
			MaterialTechnique *mtlTechnique = mtl->GetTechnique(i);
			AddChild(mtlTechnique, mIconID, mTreeLevel, isShowHelpNode);
		}
	}
	if (mtlTechnique)
	{
		int numPasses = mtlTechnique->GetNumPasses();
		for (int i = 0; i < numPasses; i++)
		{
			MaterialPass *mtlPass = mtlTechnique->GetPass(i);
			AddChild(mtlPass, mIconID, mTreeLevel, isShowHelpNode);
		}
	}
	if (mtlPass)
	{
		AddChild(mtlPass->GetVertexShader(), mIconID, mTreeLevel, isShowHelpNode);
		AddChild(mtlPass->GetPixelShader(), mIconID, mTreeLevel, isShowHelpNode);

		AddChild(mtlPass->GetAlphaProperty(), mIconID, mTreeLevel, isShowHelpNode);
		AddChild(mtlPass->GetCullProperty(), mIconID, mTreeLevel, isShowHelpNode);
		AddChild(mtlPass->GetDepthProperty(), mIconID, mTreeLevel, isShowHelpNode);
		AddChild(mtlPass->GetOffsetProperty(), mIconID, mTreeLevel, isShowHelpNode);
		AddChild(mtlPass->GetStencilProperty(), mIconID, mTreeLevel, isShowHelpNode);
		AddChild(mtlPass->GetWireProperty(), mIconID, mTreeLevel, isShowHelpNode);
	}

	if (addModule)
	{
		int numModules = effectableCtrl->GetNumModules();
		for (int i = 0; i < numModules; i++)
		{
			EffectModule *module = effectableCtrl->GetModule(i);
			AddChild(module, mIconID, mTreeLevel, mIsShowHelpNode);
		}
	}

	if (addNode)
	{
		int numChildren = node->GetNumChildren();
		for (int i = 0; i < numChildren; i++)
		{
			Movable *child = node->GetChild(i);
			if (child)
			{
				bool ingore = false;
				if (!isShowHelpNode && ("HelpNode" == child->GetName()))
					ingore = true;

				if (!ingore)
				{
					AddChild(child, mIconID, mTreeLevel, mIsShowHelpNode);
				}
			}
		}
	}
}