source-engine/materialsystem/cmaterialdict.cpp

172 lines
5.3 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "pch_materialsystem.h"
#define MATSYS_INTERNAL
#include "cmaterialdict.h"
#include "materialsystem_global.h"
#include "filesystem.h"
#include "imaterialinternal.h"
// NOTE: This must be the last file included!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// sort function
//-----------------------------------------------------------------------------
bool CMaterialDict::MaterialLessFunc( const MaterialLookup_t& src1,
const MaterialLookup_t& src2 )
{
Assert( ThreadInMainThread() );
// Always sort manually-created materials to the front
if ( src1.m_bManuallyCreated != src2.m_bManuallyCreated )
return src1.m_bManuallyCreated;
return src1.m_Name < src2.m_Name;
}
//-----------------------------------------------------------------------------
// sort function for missing materials
//-----------------------------------------------------------------------------
bool CMaterialDict::MissingMaterialLessFunc( const MissingMaterial_t& src1,
const MissingMaterial_t& src2 )
{
Assert( ThreadInMainThread() );
return src1.m_Name < src2.m_Name;
}
void CMaterialDict::Shutdown( )
{
Assert( ThreadInMainThread() );
// Clean up all materials..
RemoveAllMaterials();
// FIXME: Could dump list here...
if ( m_MissingList.Count() )
DevMsg( "%s m_MissingList count: %d\n", __FUNCTION__, m_MissingList.Count() );
m_MissingList.RemoveAll();
}
//-----------------------------------------------------------------------------
// Adds/removes the material to the list of all materials
//-----------------------------------------------------------------------------
void CMaterialDict::AddMaterialToMaterialList( IMaterialInternal *pMaterial )
{
Assert( ThreadInMainThread() );
MaterialLookup_t lookup;
lookup.m_pMaterial = pMaterial;
lookup.m_Name = pMaterial->GetName();
lookup.m_bManuallyCreated = pMaterial->IsManuallyCreated();
m_MaterialDict.Insert( lookup );
}
void CMaterialDict::RemoveMaterialFromMaterialList( IMaterialInternal *pMaterial )
{
Assert( ThreadInMainThread() );
// Gotta iterate over this manually; name-based lookup is bogus if there are two
// materials with the same name, which can happen for procedural materials
// First remove all the subrect materials, because they'll point at their material pages.
MaterialHandle_t i;
MaterialHandle_t iNext = InvalidMaterial();
for (i = FirstMaterial(); i != InvalidMaterial(); i = iNext )
{
iNext = NextMaterial(i);
if ( m_MaterialDict[i].m_pMaterial == pMaterial )
{
m_MaterialDict.RemoveAt( i );
break;
}
}
Assert( i != InvalidMaterial() );
#ifdef _DEBUG
for ( i = iNext; i != InvalidMaterial(); i = NextMaterial(i) )
{
Assert( m_MaterialDict[i].m_pMaterial != pMaterial );
}
#endif
}
//-----------------------------------------------------------------------------
// Adds, removes materials
//-----------------------------------------------------------------------------
IMaterialInternal* CMaterialDict::AddMaterial( char const* pName, const char *pTextureGroupName )
{
Assert( ThreadInMainThread() );
IMaterialInternal *pMaterial = IMaterialInternal::CreateMaterial( pName, pTextureGroupName );
Assert( pMaterial && pMaterial->IsRealTimeVersion() );
AddMaterialToMaterialList( pMaterial );
return pMaterial;
}
void CMaterialDict::RemoveMaterial( IMaterialInternal* pMaterial )
{
Assert( ThreadInMainThread() );
Assert( (pMaterial == NULL) || pMaterial->IsRealTimeVersion() );
RemoveMaterialFromMaterialList( pMaterial );
}
IMaterialInternal *CMaterialDict::AddMaterialSubRect( const char *pName, const char *pTextureGroupName, KeyValues *pKeyValues, KeyValues *pPatchKeyValues )
{
Assert( ThreadInMainThread() );
IMaterialInternal *pMaterial = IMaterialInternal::CreateMaterialSubRect( pName, pTextureGroupName, pKeyValues, pPatchKeyValues, true );
Assert( pMaterial );
AddMaterialToMaterialList( pMaterial );
return pMaterial;
}
void CMaterialDict::RemoveMaterialSubRect( IMaterialInternal *pMaterial )
{
Assert( ThreadInMainThread() );
RemoveMaterialFromMaterialList( pMaterial );
IMaterialInternal::DestroyMaterialSubRect( pMaterial );
}
void CMaterialDict::RemoveMaterialFromMaterialList( MaterialHandle_t h )
{
Assert( ThreadInMainThread() );
m_MaterialDict.RemoveAt( h );
}
void CMaterialDict::RemoveAllMaterialsFromMaterialList()
{
Assert( ThreadInMainThread() );
m_MaterialDict.RemoveAll();
}
void CMaterialDict::RemoveAllMaterials()
{
Assert( ThreadInMainThread() );
// First remove all the subrect materials, because they'll point at their material pages.
MaterialHandle_t i, iNext;
for (i = FirstMaterial(); i != InvalidMaterial(); i = iNext )
{
iNext = NextMaterial(i);
IMaterialInternal *pMaterial = GetMaterialInternal( i );
if ( pMaterial->InMaterialPage() )
{
IMaterialInternal::DestroyMaterialSubRect( pMaterial );
RemoveMaterialFromMaterialList( i );
}
}
// Now get rid of the rest of the materials, including the pages.
for (i = FirstMaterial(); i != InvalidMaterial(); i = NextMaterial(i) )
{
IMaterialInternal::DestroyMaterial( GetMaterialInternal( i ) );
}
RemoveAllMaterialsFromMaterialList();
}