Exemplo n.º 1
0
void CMFXLibrary::LoadFromXml( SLoadingEnvironment& loadingEnvironment )
{
	CryLogAlways("[MFX] Loading FXLib '%s' ...", loadingEnvironment.libraryName.c_str());

	INDENT_LOG_DURING_SCOPE();

	for (int i = 0; i < loadingEnvironment.libraryParamsNode->getChildCount(); ++i)
	{
		XmlNodeRef currentEffectNode = loadingEnvironment.libraryParamsNode->getChild(i);
		if (!currentEffectNode)
			continue;

		TMFXContainerPtr pContainer = MaterialEffectsUtils::CreateContainer();
		pContainer->BuildFromXML(currentEffectNode);

		const TMFXNameId& effectName = pContainer->GetParams().name;
		const bool effectAdded = AddContainer(effectName, pContainer);
		if (effectAdded)
		{
			loadingEnvironment.AddLibraryContainer(loadingEnvironment.libraryName, pContainer);
		}
		else
		{
			GameWarning("[MFX] Effect (at line %d) '%s:%s' already present, skipping redefinition!", currentEffectNode->getLine(), loadingEnvironment.libraryName.c_str(), effectName.c_str());
		}
	}
}
SMFXResourceListPtr CMaterialEffects::GetResources(TMFXEffectId effectId) const
{
	SMFXResourceListPtr pResourceList = SMFXResourceList::Create();
	
	TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
	if (pEffectContainer)
	{
		pEffectContainer->GetResources(*pResourceList);
	}

  return pResourceList;
}
TMFXEffectId CMaterialEffects::GetEffectIdByName(const char* libName, const char* effectName)
{
	if (!CMaterialEffectsCVars::Get().mfx_Enable)
		return InvalidEffectId;

	const TMFXContainerPtr pEffectContainer = InternalGetEffect(libName, effectName);
	if (pEffectContainer)
	{
		return pEffectContainer->GetParams().effectId;
	}

	return InvalidEffectId;
}
void CMaterialEffects::SetCustomParameter(TMFXEffectId effectId, const char* customParameter, const SMFXCustomParamValue& customParameterValue)
{
	FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);

	if (!CMaterialEffectsCVars::Get().mfx_Enable)
		return;

	TMFXContainerPtr pEffect = InternalGetEffect(effectId);
	if (pEffect)
	{
		pEffect->SetCustomParameter(customParameter, customParameterValue);	
	}
}
void CMaterialEffects::StopEffect(TMFXEffectId effectId)
{
	TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
	if (pEffectContainer)
	{
		SMFXResourceListPtr resources = SMFXResourceList::Create();
		pEffectContainer->GetResources(*resources);

		SMFXFlowGraphListNode *pNext=resources->m_flowGraphList;
		while (pNext)
		{
			GetFGManager()->EndFGEffect(pNext->m_flowGraphParams.name);
			pNext=pNext->pNext;
		}
	}
}
bool CMaterialEffects::ExecuteEffect(TMFXEffectId effectId, SMFXRunTimeEffectParams& params)
{
  FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
	
  if (!CMaterialEffectsCVars::Get().mfx_Enable)
		return false;

	bool success = false;
	TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
	if (pEffectContainer)
	{
		const float delay = pEffectContainer->GetParams().delay;
		if ((delay > 0.0f) && !(params.playflags & eMFXPF_Disable_Delay))
		{
			TimedEffect(pEffectContainer, params);
		}
		else
		{
			pEffectContainer->Execute(params);
		}
		success = true;

#ifdef MATERIAL_EFFECTS_DEBUG
		if (CMaterialEffectsCVars::Get().mfx_DebugVisual)
		{
			if (effectId != InvalidEffectId)
			{
				m_pVisualDebug->AddEffectDebugVisual(effectId, params);
			}
		}
#endif

	}

	return success;
}
bool CMaterialEffects::PlayBreakageEffect(ISurfaceType* pSurfaceType, const char* breakageType, const SMFXBreakageParams& breakageParams)
{
	if (pSurfaceType == 0)
		return false;

	CryFixedStringT<128> fxName ("Breakage:");
	fxName+=breakageType;
	TMFXEffectId effectId = this->GetEffectId(fxName.c_str(), pSurfaceType->GetId());
	if (effectId == InvalidEffectId)
		return false;

	// only play sound at the moment
	SMFXRunTimeEffectParams params;
	params.playflags = eMFXPF_Audio;

	// if hitpos is set, use it
	// otherwise use matrix (hopefully been set or 0,0,0)
	if (breakageParams.CheckFlag(SMFXBreakageParams::eBRF_HitPos) && breakageParams.GetHitPos().IsZero() == false)
		params.pos = breakageParams.GetHitPos();
	else
		params.pos = breakageParams.GetMatrix().GetTranslation();

	//params.soundSemantic = eSoundSemantic_Physics_General;

	const Vec3& hitImpulse = breakageParams.GetHitImpulse();
	const float strength = hitImpulse.GetLengthFast();
	params.AddAudioRtpc("strength", strength);
	const float mass = NormalizeMass(breakageParams.GetMass());
	params.AddAudioRtpc("mass", mass);

	if (CMaterialEffectsCVars::Get().mfx_Debug & 2)
	{
		TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
		if (pEffectContainer != NULL)
		{
			CryLogAlways("[MFX]: %s:%s FX=%s:%s Pos=%f,%f,%f NormMass=%f  F=%f Imp=%f,%f,%f  RealMass=%f Vel=%f,%f,%f",
				breakageType, pSurfaceType->GetName(), pEffectContainer->GetParams().libraryName.c_str(), pEffectContainer->GetParams().name.c_str(),
				params.pos[0],params.pos[1],params.pos[2], 
				mass,
				strength, 
				breakageParams.GetHitImpulse()[0],
				breakageParams.GetHitImpulse()[1],
				breakageParams.GetHitImpulse()[2],
				breakageParams.GetMass(),
				breakageParams.GetVelocity()[0],
				breakageParams.GetVelocity()[1],
				breakageParams.GetVelocity()[2]
				);
		}
	}

	/*
	if (breakageParams.GetMass() == 0.0f)
	{
		int a = 0;
	}
	*/


	const bool bSuccess = ExecuteEffect(effectId, params);

	return bSuccess;
}
void CMaterialEffects::LoadSpreadSheet()
{
	m_bDataInitialized = true;

	Reset(false);

	CryComment("[MFX] Init");

	IXmlTableReader* const pXmlTableReader = gEnv->pSystem->GetXmlUtils()->CreateXmlTableReader();
	if (!pXmlTableReader)
	{
		GameWarning("[MFX] XML system failure");
		return;
	}

	// The root node. 
	XmlNodeRef root = gEnv->pSystem->LoadXmlFromFile( MATERIAL_EFFECTS_SPREADSHEET_FILE );
	if (!root)
	{
		// The file wasn't found, or the wrong file format was used
		GameWarning("[MFX] File not found or wrong file type: %s", MATERIAL_EFFECTS_SPREADSHEET_FILE);
		pXmlTableReader->Release();
		return;
	}

	CryComment("[MFX] Loaded: %s", MATERIAL_EFFECTS_SPREADSHEET_FILE);

	if (!pXmlTableReader->Begin(root))
	{
		GameWarning("[MFX] Table not found");
		pXmlTableReader->Release();
		return;
	}

	// temporary multimap: we store effectstring -> [TIndexPairs]+ there
	typedef std::vector<TIndexPair> TIndexPairVec;
	typedef std::map<CConstCharArray, TIndexPairVec, less_CConstCharArray> TEffectStringToIndexPairVecMap;
	TEffectStringToIndexPairVecMap tmpEffectStringToIndexPairVecMap;

	int rowCount = 0;
	int warningCount = 0;

	CConstCharArray cell;
	string cellString; // temporary string

	// When we've gone down more rows than we have columns, we've entered special object space
	int maxCol = 0;
	std::vector<CConstCharArray> colOrder;
	std::vector<CConstCharArray> rowOrder;

	m_surfaceIdToMatrixEntry.resize(0);
	m_surfaceIdToMatrixEntry.resize(kMaxSurfaceCount, TIndex(0));
	m_ptrToMatrixEntryMap.clear();
	m_customConvert.clear();

	// Iterate through the table's rows
	for (;;)
	{
		int nRowIndex = -1;
		if (!pXmlTableReader->ReadRow(nRowIndex))
			break;

		// Iterate through the row's columns
		for (;;)
		{
			int colIndex = -1;
			if (!pXmlTableReader->ReadCell(colIndex, cell.ptr, cell.count))
				break;

			if (cell.count <= 0)
				continue;

			cellString.assign(cell.ptr, cell.count);

			if (rowCount == 0 && colIndex > 0)
			{
				const int matId = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetSurfaceTypeByName(cellString.c_str(), "MFX", true)->GetId();
				if (matId != 0 || /* matId == 0 && */ stricmp(cellString.c_str(), "mat_default") == 0) // if matId != 0 or it's the mat_default name
				{
					// CryLogAlways("[MFX] Material found: %s [ID=%d] [mapping to row/col=%d]", cellString.c_str(), matId, colCount);
					if (m_surfaceIdToMatrixEntry.size() < matId)
					{
						m_surfaceIdToMatrixEntry.resize(matId+1);
						if (matId >= kMaxSurfaceCount)
						{
							assert (false && "MaterialEffects.cpp: SurfaceTypes exceeds 256. Reconsider implementation.");
							CryLogAlways("MaterialEffects.cpp: SurfaceTypes exceeds %d. Reconsider implementation.", kMaxSurfaceCount);
						}
					}
					m_surfaceIdToMatrixEntry[matId] = colIndex;
				}
				else
				{
					GameWarning("MFX WARNING: Material not found: %s", cellString.c_str());
					++warningCount;
				}
				colOrder.push_back(cell);
			} 
			else if (rowCount > 0 && colIndex > 0)
			{
				//CryLog("[MFX] Event found: %s", cellString.c_str());
				tmpEffectStringToIndexPairVecMap[cell].push_back(TIndexPair(rowCount, colIndex));
			} 
			else if (rowCount > maxCol && colIndex == 0)
			{	
				IEntityClass *pEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(cellString.c_str());
				//CryLog("[MFX] Object class ID: %d", (int)pEntityClass);
				if (pEntityClass)
				{
					// CryComment("[MFX] Found EntityClass based entry: %s [mapping to row/col=%d]", cellString.c_str(), rowCount);
					m_ptrToMatrixEntryMap[pEntityClass] = rowCount;
				}
				else
				{
					// CryComment("[MFX] Found Custom entry: %s [mapping to row/col=%d]", cellString.c_str(), rowCount);
					cellString.MakeLower();
					m_customConvert[cellString] = rowCount;
					++warningCount;
				}
			}
			else if (rowCount > 0 && colIndex == 0)
			{
				rowOrder.push_back(cell);
			}
			// Heavy-duty debug info
			//CryLog("[MFX] celldata = %s at (%d, %d) rowCount=%d colIndex=%d maxCol=%d", curCellData->getContent(), i, j, rowCount, colIndex, maxCol);

			// Check if this is the furthest column we've seen thus far
			if (colIndex > maxCol)
				maxCol = colIndex;

			SLICE_AND_SLEEP();
		}
		// Increment row counter
		++rowCount;
	}

	// now postprocess the tmpEffectStringIndexPairVecMap and generate the m_matmatArray
	{
		// create the matmat array.
		// +1, because index pairs are in range [1..rowCount][1..maxCol]
		m_surfacesLookupTable.Create(rowCount+1,maxCol+1);
		TEffectStringToIndexPairVecMap::const_iterator iter = tmpEffectStringToIndexPairVecMap.begin();
		TEffectStringToIndexPairVecMap::const_iterator iterEnd = tmpEffectStringToIndexPairVecMap.end();
		string libName;
		string effectName;
		string tmpString;
		while (iter != iterEnd)
		{
			// lookup effect
			tmpString.assign(iter->first.ptr, iter->first.count);
			ToEffectString(tmpString, libName, effectName);
			TMFXContainerPtr pEffectContainer = InternalGetEffect(libName, effectName);
			TMFXEffectId effectId = pEffectContainer ? pEffectContainer->GetParams().effectId : InvalidEffectId;
			TIndexPairVec::const_iterator vecIter = iter->second.begin();
			TIndexPairVec::const_iterator vecIterEnd = iter->second.end();
			while (vecIter != vecIterEnd)
			{
				const TIndexPair& indexPair = *vecIter;
				// CryLogAlways("[%d,%d]->%d '%s'", indexPair.first, indexPair.second, effectId, tmpString.c_str());
				m_surfacesLookupTable(indexPair.first,indexPair.second) = effectId;
				++vecIter;
			}
			++iter;
		}
	}

	if (CMaterialEffectsCVars::Get().mfx_Debug > 0)
	{
		CryLogAlways("[MFX] RowCount=%d MaxCol=%d (*=%d)", rowCount, maxCol,rowCount*maxCol);
		for (int y=0; y<m_surfacesLookupTable.m_nRows; ++y)
		{
			for (int x=0; x<m_surfacesLookupTable.m_nCols; ++x)
			{
				TMFXEffectId idRowCol = m_surfacesLookupTable.GetValue(y,x, USHRT_MAX);
				assert (idRowCol != USHRT_MAX);
				TMFXContainerPtr pEffectRowCol = InternalGetEffect(idRowCol);
				if (pEffectRowCol)
				{
					CryLogAlways("[%d,%d] -> %d '%s:%s'", y, x, idRowCol, pEffectRowCol->GetParams().libraryName.c_str(), pEffectRowCol->GetParams().name.c_str());
					if (y<m_surfacesLookupTable.m_nCols)
					{
						TMFXEffectId idColRow = m_surfacesLookupTable.GetValue(x,y, USHRT_MAX);
						assert (idColRow != USHRT_MAX);
						TMFXContainerPtr pEffectColRow = InternalGetEffect(idColRow);
						if (idRowCol != idColRow)
						{
							if (pEffectColRow)
							{
								GameWarning("[MFX] Identity mismatch: ExcelRowCol %d:%d: %s:%s != %s:%s", y+1, x+1, 
									pEffectRowCol->GetParams().libraryName.c_str(), pEffectRowCol->GetParams().name.c_str(),
									pEffectColRow->GetParams().libraryName.c_str(), pEffectColRow->GetParams().name.c_str());
							}
							else
							{
								GameWarning("[MFX] Identity mismatch: ExcelRowCol %d:%d: %s:%s != [not found]", y+1, x+1, 
									pEffectRowCol->GetParams().libraryName.c_str(), pEffectRowCol->GetParams().name.c_str());
							}
						}
					}
				}
			}
		}
	}

	// check that we have the same number of columns and rows
	if (colOrder.size() > rowOrder.size())
	{
		GameWarning("[MFX] Found %d Columns, but not enough rows specified (%d)", (int32)colOrder.size(), (int32)rowOrder.size());
	}

	// check that column order matches row order
	if (CMaterialEffectsCVars::Get().mfx_Debug > 0)
	{
		string colName;
		string rowName;
		for (int i=0;i<colOrder.size(); ++i)
		{
			colName.assign(colOrder[i].ptr, colOrder[i].count);
			if (i < rowOrder.size())
			{
				rowName.assign(rowOrder[i].ptr, rowOrder[i].count);
			}
			else
			{
				rowName.clear();
			}
			// CryLogAlways("ExcelColRow=%d col=%s row=%s", i+2, colName.c_str(), rowName.c_str());
			if (colName != rowName)
			{
				GameWarning("ExcelColRow=%d: %s != %s", i+2, colName.c_str(), rowName.c_str());
			}
		}
	}

	pXmlTableReader->Release();
}