summaryrefslogtreecommitdiff
path: root/materialsystem/cmaterialdict.cpp
blob: 9eb8f0be999735f54d7eea9e9e9914faf7975f95 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//========= 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();
}