Torque3D Documentation / _generateds / materialManager.cpp

materialManager.cpp

Engine/source/materials/materialManager.cpp

More...

Public Functions

DefineEngineFunction(addMaterialMapping , void , (const char *texName, const char *matName) , "(string texName, string matName)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@brief Maps the given texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">material.\n\n</a>" "Generates <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> console warning before <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">overwriting.\n\n</a>" "<a href="/coding/class/classmaterial/">Material</a> maps are used by terrain and interiors <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> triggering " "effects when an object moves onto <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> terrain " "block or interior surface using the associated <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">texture.\n\n</a>" "@ingroup Materials" )
DefineEngineFunction(dumpMaterialInstances , void , () , "@brief Dumps <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> formatted list of currently allocated material instances <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" "@ingroup Materials" )
DefineEngineFunction(getMapEntry , const char * , (const char *texName) , "@hide" )
DefineEngineFunction(getMaterialInstances , void , (BaseMaterialDefinition *target, GuiTreeViewCtrl *tree) , (nullAsType< BaseMaterialDefinition * >(), nullAsType< GuiTreeViewCtrl * >()) , "@brief Dumps <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> formatted list of currently allocated material instances <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" "@ingroup Materials" )
DefineEngineFunction(getMaterialMapping , const char * , (const char *texName) , "(string texName)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@brief Returns the name of the material mapped <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">texture.\n\n</a>" "If no materials are found, an empty string is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">returned.\n\n</a>" " @param texName Name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">texture\n\n</a>" " @ingroup Materials" )
DefineEngineFunction(reInitMaterials , void , () , "@brief Flushes all procedural shaders and re-initializes all active material <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">instances.\n\n</a>" "@ingroup Materials" )

Detailed Description

Public Variables

 MODULE_END 
 MODULE_INIT 
 MODULE_SHUTDOWN 

Public Functions

DefineEngineFunction(addMaterialMapping , void , (const char *texName, const char *matName) , "(string texName, string matName)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@brief Maps the given texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">material.\n\n</a>" "Generates <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> console warning before <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">overwriting.\n\n</a>" "<a href="/coding/class/classmaterial/">Material</a> maps are used by terrain and interiors <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> triggering " "effects when an object moves onto <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> terrain " "block or interior surface using the associated <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">texture.\n\n</a>" "@ingroup Materials" )

DefineEngineFunction(dumpMaterialInstances , void , () , "@brief Dumps <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> formatted list of currently allocated material instances <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" "@ingroup Materials" )

DefineEngineFunction(getMapEntry , const char * , (const char *texName) , "@hide" )

DefineEngineFunction(getMaterialInstances , void , (BaseMaterialDefinition *target, GuiTreeViewCtrl *tree) , (nullAsType< BaseMaterialDefinition * >(), nullAsType< GuiTreeViewCtrl * >()) , "@brief Dumps <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> formatted list of currently allocated material instances <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" "@ingroup Materials" )

DefineEngineFunction(getMaterialMapping , const char * , (const char *texName) , "(string texName)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@brief Returns the name of the material mapped <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">texture.\n\n</a>" "If no materials are found, an empty string is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">returned.\n\n</a>" " @param texName Name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">texture\n\n</a>" " @ingroup Materials" )

DefineEngineFunction(reInitMaterials , void , () , "@brief Flushes all procedural shaders and re-initializes all active material <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">instances.\n\n</a>" "@ingroup Materials" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "materials/materialManager.h"
 26
 27#include "materials/matInstance.h"
 28#include "materials/materialFeatureTypes.h"
 29#include "lighting/lightManager.h"
 30#include "core/util/safeDelete.h"
 31#include "shaderGen/shaderGen.h"
 32#include "core/module.h"
 33#include "console/consoleTypes.h"
 34#include "console/engineAPI.h"
 35
 36#include "gui/controls/guiTreeViewCtrl.h"
 37
 38MODULE_BEGIN( MaterialManager )
 39
 40   MODULE_INIT_BEFORE( GFX )
 41   MODULE_SHUTDOWN_BEFORE( GFX )
 42   
 43   MODULE_INIT
 44   {
 45      MaterialManager::createSingleton();
 46   }
 47   
 48   MODULE_SHUTDOWN
 49   {
 50      MaterialManager::deleteSingleton();
 51   }
 52
 53MODULE_END;
 54
 55
 56MaterialManager::MaterialManager()
 57{
 58   VECTOR_SET_ASSOCIATION( mMatInstanceList );
 59
 60   mDt = 0.0f; 
 61   mAccumTime = 0.0f; 
 62   mLastTime = 0; 
 63   mWarningInst = NULL;
 64   
 65   GFXDevice::getDeviceEventSignal().notify( this, &MaterialManager::_handleGFXEvent );
 66
 67   // Make sure we get activation signals
 68   // and that we're the last to get them.
 69   LightManager::smActivateSignal.notify( this, &MaterialManager::_onLMActivate, 9999 );
 70
 71   mMaterialSet = NULL;
 72
 73   mUsingDeferred = false;
 74
 75   mFlushAndReInit = false;
 76
 77   mDefaultAnisotropy = 1;
 78   Con::addVariable( "$pref::Video::defaultAnisotropy", TypeS32, &mDefaultAnisotropy, 
 79      "@brief Global variable defining the default anisotropy value.\n\n"
 80      "Controls the default anisotropic texture filtering level for all materials, including the terrain. "
 81      "This value can be changed at runtime to see its affect without reloading.\n\n "
 82      "@ingroup Materials");
 83   Con::NotifyDelegate callabck( this, &MaterialManager::_updateDefaultAnisotropy );
 84   Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck );
 85
 86   Con::NotifyDelegate callabck2( this, &MaterialManager::_onDisableMaterialFeature );
 87   Con::setVariable( "$pref::Video::disableNormalMapping", "false" );
 88   Con::addVariableNotify( "$pref::Video::disableNormalMapping", callabck2 );
 89   Con::setVariable( "$pref::Video::disableCubemapping", "false" );
 90   Con::addVariableNotify( "$pref::Video::disableCubemapping", callabck2 );
 91   Con::setVariable( "$pref::Video::disableParallaxMapping", "false" );
 92   Con::addVariableNotify( "$pref::Video::disableParallaxMapping", callabck2 );
 93}
 94
 95MaterialManager::~MaterialManager()
 96{
 97   GFXDevice::getDeviceEventSignal().remove( this, &MaterialManager::_handleGFXEvent );  
 98   LightManager::smActivateSignal.remove( this, &MaterialManager::_onLMActivate );
 99
100   SAFE_DELETE( mWarningInst );
101
102#ifndef TORQUE_SHIPPING
103   DebugMaterialMap::Iterator itr = mMeshDebugMaterialInsts.begin();
104
105   for ( ; itr != mMeshDebugMaterialInsts.end(); itr++ )
106      delete itr->value;
107#endif
108}
109
110void MaterialManager::_onLMActivate( const char *lm, bool activate )
111{
112   if ( !activate )
113      return;
114
115   // Since the light manager usually swaps shadergen features
116   // and changes system wide shader defines we need to completely
117   // flush and rebuild all the material instances.
118
119   mFlushAndReInit = true;
120}
121
122void MaterialManager::_updateDefaultAnisotropy()
123{
124   // Update all the materials.
125   Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
126   for ( ; iter != mMatInstanceList.end(); iter++ )
127      (*iter)->updateStateBlocks();
128}
129
130Material * MaterialManager::allocateAndRegister(const String &objectName, const String &mapToName)
131{
132   Material *newMat = new Material();
133
134   if ( mapToName.isNotEmpty() )
135      newMat->mMapTo = mapToName;
136
137   bool registered = newMat->registerObject(objectName );
138   AssertFatal( registered, "Unable to register material" );
139
140   if (registered)
141      Sim::getRootGroup()->addObject( newMat );
142   else
143   {
144      delete newMat;
145      newMat = NULL;
146   }
147
148   return newMat;
149}
150
151Material * MaterialManager::getMaterialDefinitionByName(const String &matName)
152{
153   // Get the material
154   Material * foundMat;
155
156   if(!Sim::findObject(matName, foundMat))
157   {
158      Con::errorf("MaterialManager: Unable to find material '%s'", matName.c_str());
159      return NULL;
160   }
161
162   return foundMat;
163}
164
165Material* MaterialManager::getMaterialDefinitionByMapTo(const String& mapTo)
166{
167   // Get the material
168   Material* foundMat = nullptr;
169
170   for (SimSet::iterator itr = mMaterialSet->begin(); itr != mMaterialSet->end(); ++itr)
171   {
172      // Fetch our listed materials.
173      Material* materialDef = dynamic_cast<Material*>(*itr);
174      if (materialDef && materialDef->mMapTo.compare(mapTo, 0U, String::NoCase) == 0)
175      {
176         //We have a match, so keep it and bail the loop
177         foundMat = materialDef;
178         break;
179      }
180   }
181
182   return foundMat;
183}
184
185BaseMatInstance* MaterialManager::createMatInstance(const String &matName)
186{
187   BaseMaterialDefinition* mat = NULL;
188   if (Sim::findObject(matName, mat))
189      return mat->createMatInstance();
190
191   return NULL;
192}
193
194BaseMatInstance* MaterialManager::createMatInstance(  const String &matName, 
195                                                      const GFXVertexFormat *vertexFormat )
196{
197   return createMatInstance( matName, getDefaultFeatures(), vertexFormat );
198}
199
200BaseMatInstance* MaterialManager::createMatInstance(  const String &matName, 
201                                                      const FeatureSet& features, 
202                                                      const GFXVertexFormat *vertexFormat )
203{
204   BaseMatInstance* mat = createMatInstance(matName);
205   if (mat)
206   {
207      mat->init( features, vertexFormat );
208      return mat;
209   }
210
211   return NULL;
212}
213
214BaseMatInstance  * MaterialManager::createWarningMatInstance()
215{
216   Material *warnMat = static_cast<Material*>(Sim::findObject("WarningMaterial"));
217
218   BaseMatInstance   *warnMatInstance = NULL;
219
220   if( warnMat != NULL )
221   {
222      warnMatInstance = warnMat->createMatInstance();
223
224      GFXStateBlockDesc desc;
225      desc.setCullMode(GFXCullNone);
226      warnMatInstance->addStateBlockDesc(desc);
227
228      warnMatInstance->init(  getDefaultFeatures(), 
229                              getGFXVertexFormat<GFXVertexPNTTB>() );
230   }
231
232   return warnMatInstance;
233}
234
235// Gets the global warning material instance, callers should not free this copy
236BaseMatInstance * MaterialManager::getWarningMatInstance()
237{
238   if (!mWarningInst)
239      mWarningInst = createWarningMatInstance();
240
241   return mWarningInst;
242}
243
244#ifndef TORQUE_SHIPPING
245BaseMatInstance * MaterialManager::createMeshDebugMatInstance(const LinearColorF &meshColor)
246{
247   String  meshDebugStr = String::ToString( "Torque_MeshDebug_%d", meshColor.getRGBAPack() );
248
249   Material *debugMat;
250   if (!Sim::findObject(meshDebugStr,debugMat))
251   {
252      debugMat = allocateAndRegister( meshDebugStr );
253
254      debugMat->mDiffuse[0] = meshColor;
255      debugMat->mEmissive[0] = true;
256   }
257
258   BaseMatInstance   *debugMatInstance = NULL;
259
260   if( debugMat != NULL )
261   {
262      debugMatInstance = debugMat->createMatInstance();
263
264      GFXStateBlockDesc desc;
265      desc.setCullMode(GFXCullNone);
266      desc.fillMode = GFXFillWireframe;
267      debugMatInstance->addStateBlockDesc(desc);
268
269      // Disable fog and other stuff.
270      FeatureSet debugFeatures;
271      debugFeatures.addFeature( MFT_DiffuseColor );
272      debugMatInstance->init( debugFeatures, getGFXVertexFormat<GFXVertexPCN>() );
273   }
274
275   return debugMatInstance;
276}
277
278// Gets the global material instance for a given color, callers should not free this copy
279BaseMatInstance *MaterialManager::getMeshDebugMatInstance(const LinearColorF &meshColor)
280{
281   DebugMaterialMap::Iterator itr = mMeshDebugMaterialInsts.find( meshColor.getRGBAPack() );
282
283   BaseMatInstance   *inst  = NULL;
284
285   if ( itr == mMeshDebugMaterialInsts.end() )
286      inst = createMeshDebugMatInstance( meshColor );
287   else
288      inst = itr->value;
289
290   mMeshDebugMaterialInsts.insert( meshColor.getRGBAPack(), inst );
291
292   return inst;
293}
294#endif
295
296void MaterialManager::mapMaterial(const String & textureName, const String & materialName)
297{
298   if (getMapEntry(textureName).isNotEmpty())
299   {
300      if (!textureName.equal("unmapped_mat", String::NoCase))
301         Con::warnf(ConsoleLogEntry::General, "Warning, overwriting material for: %s", textureName.c_str());
302   }
303
304   mMaterialMap[String::ToLower(textureName)] = materialName;
305}
306
307String MaterialManager::getMapEntry(const String & textureName) const
308{
309   MaterialMap::ConstIterator iter = mMaterialMap.find(String::ToLower(textureName));
310   if ( iter == mMaterialMap.end() )
311      return String();
312   return iter->value;
313}
314
315void MaterialManager::flushAndReInitInstances()
316{
317   // Clear the flag if its set.
318   mFlushAndReInit = false;   
319
320   // Check to see if any shader preferences have changed.
321   recalcFeaturesFromPrefs();
322
323   // First we flush all the shader gen shaders which will
324   // invalidate all GFXShader* to them.
325   SHADERGEN->flushProceduralShaders();   
326   mFlushSignal.trigger();
327
328   // First do a pass deleting all hooks as they can contain
329   // materials themselves.  This means we have to restart the
330   // loop every time we delete any hooks... lame.
331   Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
332   while ( iter != mMatInstanceList.end() )
333   {
334      if ( (*iter)->deleteAllHooks() != 0 )
335      {
336         // Restart the loop.
337         iter = mMatInstanceList.begin();
338         continue;
339      }
340
341      iter++;
342   }
343
344   // Now do a pass re-initializing materials.
345   iter = mMatInstanceList.begin();
346   for ( ; iter != mMatInstanceList.end(); iter++ )
347      (*iter)->reInit();
348}
349
350// Used in the materialEditor. This flushes the material preview object so it can be reloaded easily.
351void MaterialManager::flushInstance( BaseMaterialDefinition *target )
352{
353   Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
354   while ( iter != mMatInstanceList.end() )
355   {
356      if ( (*iter)->getMaterial() == target )
357      {
358        (*iter)->deleteAllHooks();
359        return;
360      }
361     iter++;
362   }
363}
364
365void MaterialManager::reInitInstance( BaseMaterialDefinition *target )
366{
367   Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
368   for ( ; iter != mMatInstanceList.end(); iter++ )
369   {
370      if ( (*iter)->getMaterial() == target )
371         (*iter)->reInit();
372   }
373}
374
375void MaterialManager::updateTime()
376{
377   U32 curTime = Sim::getCurrentTime();
378   if(curTime > mLastTime)
379   {
380      mDt =  (curTime - mLastTime) / 1000.0f;
381      mLastTime = curTime;
382      mAccumTime += mDt;
383   }
384   else
385      mDt = 0.0f;
386}
387
388SimSet * MaterialManager::getMaterialSet()
389{
390   if(!mMaterialSet)
391      mMaterialSet = static_cast<SimSet*>( Sim::findObject( "MaterialSet" ) );
392
393   AssertFatal( mMaterialSet, "MaterialSet not found" );
394   return mMaterialSet;
395}
396
397void MaterialManager::dumpMaterialInstances( BaseMaterialDefinition *target ) const
398{
399   if ( !mMatInstanceList.size() )
400      return;
401
402   if ( target )
403      Con::printf( "--------------------- %s MatInstances ---------------------", target->getName() );
404   else
405      Con::printf( "--------------------- MatInstances %d ---------------------", mMatInstanceList.size() );
406
407   for( U32 i=0; i<mMatInstanceList.size(); i++ )
408   {
409      BaseMatInstance *inst = mMatInstanceList[i];
410      
411      if ( target && inst->getMaterial() != target )
412         continue;
413
414      inst->dumpShaderInfo();
415
416      Con::printf( "" );
417   }
418
419   Con::printf( "---------------------- Dump complete ----------------------");
420}
421
422void MaterialManager::getMaterialInstances(BaseMaterialDefinition* target, GuiTreeViewCtrl* materailInstanceTree)
423{
424   if (!mMatInstanceList.size())
425      return;
426
427   if (!target)
428   {
429      Con::errorf("Can't form a list without a specific MaterialDefinition");
430      return;
431   }
432
433   if (!materailInstanceTree)
434   {
435      Con::errorf("Requires a valid GuiTreeViewCtrl object to populate data into!");
436      return;
437   }
438
439   U32 matItem = materailInstanceTree->insertItem(0, target->getName());
440
441   for (U32 i = 0; i < mMatInstanceList.size(); i++)
442   {
443      BaseMatInstance* inst = mMatInstanceList[i];
444
445      if (target && inst->getMaterial() != target)
446         continue;
447
448      inst->getShaderInfo(materailInstanceTree, matItem);
449   }
450}
451
452void MaterialManager::_track( MatInstance *matInstance )
453{
454   mMatInstanceList.push_back( matInstance );
455}
456
457void MaterialManager::_untrack( MatInstance *matInstance )
458{
459   mMatInstanceList.remove( matInstance );
460}
461
462void MaterialManager::recalcFeaturesFromPrefs()
463{
464   mDefaultFeatures.clear();
465   FeatureType::addDefaultTypes( &mDefaultFeatures );
466
467   mExclusionFeatures.setFeature(   MFT_NormalMap, 
468                                    Con::getBoolVariable( "$pref::Video::disableNormalMapping", false ) );
469
470   mExclusionFeatures.setFeature(   MFT_CubeMap, 
471                                    Con::getBoolVariable( "$pref::Video::disableCubemapping", false ) );
472
473   mExclusionFeatures.setFeature(   MFT_Parallax, 
474                                    Con::getBoolVariable( "$pref::Video::disableParallaxMapping", false ) );
475}
476
477bool MaterialManager::_handleGFXEvent( GFXDevice::GFXDeviceEventType event_ )
478{
479   switch ( event_ )
480   {
481      case GFXDevice::deInit:
482         recalcFeaturesFromPrefs();
483         break;
484
485      case GFXDevice::deDestroy :
486         SAFE_DELETE( mWarningInst );
487         break;
488
489      case GFXDevice::deStartOfFrame:
490         if ( mFlushAndReInit )
491            flushAndReInitInstances();
492         break;
493
494      default:
495         break;
496   }
497
498   return true;
499}
500
501DefineEngineFunction( reInitMaterials, void, (),,
502   "@brief Flushes all procedural shaders and re-initializes all active material instances.\n\n" 
503   "@ingroup Materials")
504{
505   MATMGR->flushAndReInitInstances();
506}
507
508DefineEngineFunction( addMaterialMapping, void, (const char * texName, const char * matName), , "(string texName, string matName)\n"
509   "@brief Maps the given texture to the given material.\n\n"
510   "Generates a console warning before overwriting.\n\n"
511   "Material maps are used by terrain and interiors for triggering "
512   "effects when an object moves onto a terrain "
513   "block or interior surface using the associated texture.\n\n"
514   "@ingroup Materials")
515{
516   MATMGR->mapMaterial(texName, matName);
517}
518
519DefineEngineFunction( getMaterialMapping, const char*, (const char * texName), , "(string texName)\n"
520   "@brief Returns the name of the material mapped to this texture.\n\n"
521   "If no materials are found, an empty string is returned.\n\n"
522   "@param texName Name of the texture\n\n"
523   "@ingroup Materials")
524{
525   return MATMGR->getMapEntry(texName).c_str();
526}
527
528DefineEngineFunction( dumpMaterialInstances, void, (), ,
529   "@brief Dumps a formatted list of currently allocated material instances to the console.\n\n"
530   "@ingroup Materials")
531{
532   MATMGR->dumpMaterialInstances();
533}
534
535DefineEngineFunction(getMaterialInstances, void, (BaseMaterialDefinition* target, GuiTreeViewCtrl* tree), (nullAsType<BaseMaterialDefinition*>(), nullAsType<GuiTreeViewCtrl*>()),
536   "@brief Dumps a formatted list of currently allocated material instances to the console.\n\n"
537   "@ingroup Materials")
538{
539   if (target == nullptr || tree == nullptr)
540      return;
541
542   MATMGR->getMaterialInstances(target, tree);
543}
544
545DefineEngineFunction( getMapEntry, const char*, (const char * texName), ,
546   "@hide")
547{
548   return MATMGR->getMapEntry( String(texName) );
549}
550