1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
4 #include "MaterialManager.h"
7 #include "MaterialLibrary.h"
10 #include "ModelViewport.h"
11 #include "MaterialSender.h"
13 #include <CryAnimation/ICryAnimation.h>
14 #include "ISourceControl.h"
16 #include "Util/BoostPythonHelpers.h"
18 #include "Terrain/Layer.h"
19 #include "Terrain/TerrainManager.h"
20 #include "Terrain/SurfaceType.h"
22 #include "QT/QtMainFrame.h"
24 #include <CryString/CryPath.h>
25 #include <FilePathUtil.h>
26 #include <Preferences/ViewportPreferences.h>
27 #include <QAbstractNativeEventFilter>
28 #include <QApplication>
30 static const char* MATERIALS_LIBS_PATH
= "Materials/";
31 static unsigned int s_highlightUpdateCounter
= 0;
40 static SHighlightMode g_highlightModes
[] = {
41 { 0.70f
, 0.8f
, true }, // purple
42 { 0.25f
, 0.75f
, false }, // green
43 { 0.0, 0.75f
, true } // red
46 class CMaterialHighlighter
49 void Start(CMaterial
* pMaterial
, int modeFlag
);
50 void Stop(CMaterial
* pMaterial
, int modeFlag
);
51 void GetHighlightColor(ColorF
* color
, float* intensity
, int flags
);
53 void ClearMaterials() { m_materials
.clear(); };
54 void RestoreMaterials();
57 struct SHighlightOptions
62 typedef std::map
<CMaterial
*, SHighlightOptions
> Materials
;
63 Materials m_materials
;
66 void CMaterialHighlighter::Start(CMaterial
* pMaterial
, int modeFlag
)
68 Materials::iterator it
= m_materials
.find(pMaterial
);
69 if (it
== m_materials
.end())
71 SHighlightOptions
& options
= m_materials
[pMaterial
];
72 options
.m_modeFlags
= modeFlag
;
76 SHighlightOptions
& options
= it
->second
;
77 options
.m_modeFlags
|= modeFlag
;
81 void CMaterialHighlighter::Stop(CMaterial
* pMaterial
, int modeFlag
)
84 pMaterial
->SetHighlightFlags(0);
86 Materials::iterator it
= m_materials
.find(pMaterial
);
87 if (it
== m_materials
.end())
90 SHighlightOptions
& options
= it
->second
;
91 MAKE_SURE((options
.m_modeFlags
& modeFlag
) != 0, return );
93 options
.m_modeFlags
&= ~modeFlag
;
94 if (options
.m_modeFlags
== 0)
95 m_materials
.erase(it
);
98 void CMaterialHighlighter::RestoreMaterials()
100 for (Materials::iterator it
= m_materials
.begin(); it
!= m_materials
.end(); ++it
)
103 it
->first
->SetHighlightFlags(0);
107 void CMaterialHighlighter::Update()
109 unsigned int counter
= s_highlightUpdateCounter
;
111 Materials::iterator it
;
112 for (it
= m_materials
.begin(); it
!= m_materials
.end(); ++it
)
114 // Only update each material every 4 frames
115 if (counter
++ % 4 == 0)
117 it
->first
->SetHighlightFlags(it
->second
.m_modeFlags
);
121 s_highlightUpdateCounter
= (s_highlightUpdateCounter
+ 1) % 4;
124 void CMaterialHighlighter::GetHighlightColor(ColorF
* color
, float* intensity
, int flags
)
126 MAKE_SURE(color
!= 0, return );
127 MAKE_SURE(intensity
!= 0, return );
137 if ((flags
& 1) != 0)
143 MAKE_SURE(flagIndex
< sizeof(g_highlightModes
) / sizeof(g_highlightModes
[0]), return );
145 const SHighlightMode
& mode
= g_highlightModes
[flagIndex
];
146 float t
= GetTickCount() / 1000.0f
;
147 float h
= mode
.m_colorHue
;
151 color
->fromHSV(h
+ sinf(t
* g_PI2
* 5.0f
) * 0.025f
, s
, v
);
154 if (mode
.m_continuous
)
155 *intensity
= fabsf(sinf(t
* g_PI2
/ mode
.m_period
));
157 *intensity
= max(0.0f
, sinf(t
* g_PI2
/ mode
.m_period
));
160 boost::python::list
PyGetMaterials(string materialName
= "", bool selectedOnly
= false)
162 boost::python::list result
;
164 GetIEditorImpl()->OpenDataBaseLibrary(EDB_TYPE_MATERIAL
, NULL
);
165 CMaterialManager
* pMaterialMgr
= GetIEditorImpl()->GetMaterialManager();
167 if (!materialName
.IsEmpty())
169 result
.append(PyScript::CreatePyGameMaterial((CMaterial
*)pMaterialMgr
->FindItemByName(materialName
)));
171 else if (selectedOnly
)
173 if (materialName
.IsEmpty() && pMaterialMgr
->GetSelectedItem() != NULL
)
175 result
.append(PyScript::CreatePyGameMaterial((CMaterial
*)pMaterialMgr
->GetSelectedItem()));
180 // Acquire all of the materials via iterating across the objects.
181 CBaseObjectsArray objects
;
182 GetIEditorImpl()->GetObjectManager()->GetObjects(objects
);
183 for (int i
= 0; i
< objects
.size(); i
++)
185 result
.append(PyScript::CreatePyGameMaterial((CMaterial
*)objects
[i
]->GetMaterial()));
191 BOOST_PYTHON_FUNCTION_OVERLOADS(pyGetMaterialsOverload
, PyGetMaterials
, 0, 2);
192 REGISTER_PYTHON_OVERLOAD_COMMAND(PyGetMaterials
, general
, get_materials
, pyGetMaterialsOverload
,
193 "Get all, subgroup, or selected materials in the material editor.",
194 "general.get_materials(str materialName=\'\', selectedOnly=False, levelOnly=False)");
196 //////////////////////////////////////////////////////////////////////////
197 // CMaterialManager implementation.
198 //////////////////////////////////////////////////////////////////////////
199 CMaterialManager::CMaterialManager()
200 : m_pHighlighter(new CMaterialHighlighter
)
201 , m_highlightMask(eHighlight_All
& ~(eHighlight_Breakable
| eHighlight_NoSurfaceType
))
202 , m_currentFolder("")
204 m_bUniqGuidMap
= false;
205 m_bUniqNameMap
= true;
206 m_bShadersEnumerated
= false;
208 m_bMaterialsLoaded
= false;
209 m_pLevelLibrary
= (CBaseLibrary
*)AddLibrary("Level");
210 m_pLevelLibrary
->SetLevelLibrary(true);
212 m_MatSender
= new CMaterialSender(true);
215 gEnv
->p3DEngine
->GetMaterialManager()->SetListener(this);
216 gViewportDebugPreferences
.debugFlagsChanged
.Connect(this, &CMaterialManager::OnDebugFlagsChanged
);
219 //////////////////////////////////////////////////////////////////////////
220 CMaterialManager::~CMaterialManager()
222 gViewportDebugPreferences
.debugFlagsChanged
.DisconnectObject(this);
224 delete m_pHighlighter
;
228 gEnv
->p3DEngine
->GetMaterialManager()->SetListener(NULL
);
237 //////////////////////////////////////////////////////////////////////////
238 void CMaterialManager::ClearAll()
240 SetCurrentMaterial(NULL
);
241 CBaseLibraryManager::ClearAll();
243 m_pLevelLibrary
= (CBaseLibrary
*)AddLibrary("Level");
244 m_pLevelLibrary
->SetLevelLibrary(true);
247 //////////////////////////////////////////////////////////////////////////
248 CMaterial
* CMaterialManager::CreateMaterial(const string
& sMaterialName
, XmlNodeRef
& node
, int nMtlFlags
, unsigned long nLoadingFlags
)
250 CMaterial
* pMaterial
= new CMaterial(sMaterialName
, nMtlFlags
);
254 CBaseLibraryItem::SerializeContext
serCtx(node
, true);
255 serCtx
.bUniqName
= true;
256 pMaterial
->Serialize(serCtx
);
258 if (!pMaterial
->IsPureChild() && !(pMaterial
->GetFlags() & MTL_FLAG_UIMATERIAL
))
260 RegisterItem(pMaterial
);
266 //////////////////////////////////////////////////////////////////////////
267 CMaterial
* CMaterialManager::CreateMaterial(const char* sMaterialName
, XmlNodeRef
& node
, int nMtlFlags
, unsigned long nLoadingFlags
)
269 return CreateMaterial(string(sMaterialName
), node
, nMtlFlags
, nLoadingFlags
);
272 //////////////////////////////////////////////////////////////////////////
273 void CMaterialManager::Export(XmlNodeRef
& node
)
275 XmlNodeRef libs
= node
->newChild("MaterialsLibrary");
276 for (int i
= 0; i
< GetLibraryCount(); i
++)
278 IDataBaseLibrary
* pLib
= GetLibrary(i
);
279 // Level libraries are saved in in level.
280 XmlNodeRef libNode
= libs
->newChild("Library");
283 libNode
->setAttr("Name", pLib
->GetName());
287 //////////////////////////////////////////////////////////////////////////
288 int CMaterialManager::ExportLib(CMaterialLibrary
* pLib
, XmlNodeRef
& libNode
)
292 libNode
->setAttr("Name", pLib
->GetName());
293 libNode
->setAttr("File", pLib
->GetFilename());
294 libNode
->setAttr("SandboxVersion", (const char*)GetIEditorImpl()->GetFileVersion().ToFullString());
295 // Serialize prototypes.
296 for (int j
= 0; j
< pLib
->GetItemCount(); j
++)
298 CMaterial
* pMtl
= (CMaterial
*)pLib
->GetItem(j
);
300 // Only export real used materials.
301 if (pMtl
->IsDummy() || pMtl
->IsPureChild())
304 XmlNodeRef itemNode
= libNode
->newChild("Material");
305 itemNode
->setAttr("Name", pMtl
->GetName());
311 //////////////////////////////////////////////////////////////////////////
312 void CMaterialManager::SetSelectedItem(IDataBaseItem
* pItem
)
314 m_pSelectedItem
= (CBaseLibraryItem
*)pItem
;
315 SetCurrentMaterial((CMaterial
*)pItem
);
318 //////////////////////////////////////////////////////////////////////////
319 void CMaterialManager::SetCurrentMaterial(CMaterial
* pMtl
)
321 if (m_pCurrentMaterial
)
323 // Changing current material. save old one.
324 if (m_pCurrentMaterial
->IsModified())
325 m_pCurrentMaterial
->Save();
328 m_pCurrentMaterial
= pMtl
;
329 if (m_pCurrentMaterial
)
331 m_pCurrentMaterial
->OnMakeCurrent();
332 m_pCurrentEngineMaterial
= m_pCurrentMaterial
->GetMatInfo();
336 m_pCurrentEngineMaterial
= 0;
339 m_pSelectedItem
= pMtl
;
340 m_pSelectedParent
= pMtl
? pMtl
->GetParent() : NULL
;
342 NotifyItemEvent(m_pCurrentMaterial
, EDB_ITEM_EVENT_SELECTED
);
345 //////////////////////////////////////////////////////////////////////////
346 void CMaterialManager::SetCurrentFolder(const string
& folder
)
348 m_currentFolder
= folder
;
351 //////////////////////////////////////////////////////////////////////////
352 void CMaterialManager::SetMarkedMaterials(const std::vector
<_smart_ptr
<CMaterial
>>& markedMaterials
)
354 m_markedMaterials
= markedMaterials
;
357 void CMaterialManager::OnLoadShader(CMaterial
* pMaterial
)
359 RemoveFromHighlighting(pMaterial
, eHighlight_All
);
360 AddForHighlighting(pMaterial
);
363 //////////////////////////////////////////////////////////////////////////
364 CMaterial
* CMaterialManager::GetCurrentMaterial() const
366 return m_pCurrentMaterial
;
369 //////////////////////////////////////////////////////////////////////////
370 CBaseLibraryItem
* CMaterialManager::MakeNewItem()
372 CMaterial
* pMaterial
= new CMaterial("", 0);
375 //////////////////////////////////////////////////////////////////////////
376 CBaseLibrary
* CMaterialManager::MakeNewLibrary()
378 return new CMaterialLibrary(this);
380 //////////////////////////////////////////////////////////////////////////
381 string
CMaterialManager::GetRootNodeName()
383 return "MaterialsLibs";
385 //////////////////////////////////////////////////////////////////////////
386 string
CMaterialManager::GetLibsPath()
388 if (m_libsPath
.IsEmpty())
389 m_libsPath
= MATERIALS_LIBS_PATH
;
393 //////////////////////////////////////////////////////////////////////////
394 void CMaterialManager::ReportDuplicateItem(CBaseLibraryItem
* pItem
, CBaseLibraryItem
* pOldItem
)
397 if (pOldItem
->GetLibrary())
398 sLibName
= pOldItem
->GetLibrary()->GetName();
400 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_WARNING
,
401 "Material %s with the duplicate name to the loaded material %s ignored",
402 (const char*)pItem
->GetName(), (const char*)pOldItem
->GetName());
405 //////////////////////////////////////////////////////////////////////////
406 void CMaterialManager::Serialize(XmlNodeRef
& node
, bool bLoading
)
408 //CBaseLibraryManager::Serialize( node,bLoading );
417 int CMaterialManager::GetShaderCount()
419 if (!m_bShadersEnumerated
)
422 return m_shaderList
.size();
425 const std::vector
<string
>& CMaterialManager::GetShaderList()
427 if (!m_bShadersEnumerated
)
433 void CMaterialManager::EnumerateShaders()
435 if (!m_bShadersEnumerated
)
437 IRenderer
* renderer
= GetIEditor()->GetSystem()->GetIRenderer();
443 m_shaderList
.clear();
444 m_shaderList
.reserve(100);
446 //! Enumerate Shaders.
448 string
* files
= renderer
->EF_GetShaderNames(nNumShaders
);
450 for (int i
= 0; i
< nNumShaders
; i
++)
452 m_shaderList
.push_back(files
[i
]);
455 XmlNodeRef root
= GetISystem()->GetXmlUtils()->LoadXmlFromFile("%EDITOR%/Materials/ShaderList.xml");
458 for (int i
= 0; i
< root
->getChildCount(); ++i
)
460 XmlNodeRef ChildNode
= root
->getChild(i
);
461 const char* pTagName
= ChildNode
->getTag();
462 if (!stricmp(pTagName
, "Shader"))
465 if (ChildNode
->getAttr("name", name
) && !name
.IsEmpty())
467 // make sure there is no duplication
469 for (const auto& shader
: m_shaderList
)
471 if (stricmp(name
, shader
) == 0)
480 m_shaderList
.push_back(name
);
487 std::sort(m_shaderList
.begin(), m_shaderList
.end(), [](const string
&s1
, const string
&s2
) { return stricmp(s1
, s2
) < 0; });
489 //capitalize shader names
490 for (string
& shaderName
: m_shaderList
)
492 CRY_ASSERT(shaderName
.length() > 0);
493 shaderName
.SetAt(0, toupper(shaderName
[0]));
496 m_bShadersEnumerated
= true;
503 struct SMaterialManagerFilter
: QAbstractNativeEventFilter
505 virtual bool nativeEventFilter(const QByteArray
& eventType
, void* pMessage
, long* pResult
) override
507 if (eventType
!= "windows_generic_MSG")
512 const MSG
* const pTheMessage
= (MSG
*)pMessage
;
513 if (pTheMessage
->message
!= WM_MATEDITSEND
)
518 const CWnd
* const pDlg
= GetIEditorImpl()->OpenView("Material Editor Legacy");
521 GetIEditorImpl()->GetMaterialManager()->SyncMaterialEditor();
534 static SMaterialManagerFilter
& GetInstance()
536 static SMaterialManagerFilter theInstance
;
543 //////////////////////////////////////////////////////////////////////////
544 void CMaterialManager::OnEditorNotifyEvent(EEditorNotifyEvent event
)
546 CBaseLibraryManager::OnEditorNotifyEvent(event
);
549 case eNotify_OnMainFrameInitialized
:
551 if (!GetIEditorImpl()->IsInMatEditMode())
553 qApp
->installNativeEventFilter(&SMaterialManagerFilter::GetInstance());
556 case eNotify_OnIdleUpdate
:
557 m_pHighlighter
->Update();
559 case eNotify_OnBeginGameMode
:
560 m_pHighlighter
->RestoreMaterials();
562 case eNotify_OnBeginNewScene
:
563 SetCurrentMaterial(0);
565 case eNotify_OnBeginSceneOpen
:
566 SetCurrentMaterial(0);
568 case eNotify_OnMissionChange
:
569 SetCurrentMaterial(0);
571 case eNotify_OnClearLevelContents
:
572 SetCurrentMaterial(0);
573 m_pHighlighter
->ClearMaterials();
576 SetCurrentMaterial(0);
578 gEnv
->p3DEngine
->GetMaterialManager()->SetListener(NULL
);
583 //////////////////////////////////////////////////////////////////////////
584 CMaterial
* CMaterialManager::LoadMaterial(const string
& sMaterialName
, bool bMakeIfNotFound
)
586 LOADING_TIME_PROFILE_SECTION(GetISystem());
588 string
sMaterialNameClear(sMaterialName
);
589 int nExtLen
= strlen(MATERIAL_FILE_EXT
);
590 if (sMaterialNameClear
.Right(nExtLen
) == MATERIAL_FILE_EXT
)
591 sMaterialNameClear
= sMaterialNameClear
.Left(sMaterialNameClear
.GetLength() - nExtLen
);
593 // Load material with this name if not yet loaded.
594 CMaterial
* pMaterial
= (CMaterial
*)FindItemByName(sMaterialNameClear
);
600 string filename
= PathUtil::MakeGamePath(MaterialToFilename(sMaterialNameClear
).GetString()).c_str();
601 if (filename
.GetLength() - nExtLen
< sMaterialNameClear
.GetLength() - 1)
603 // Remove game folder in the begin of material name (bad material names in cgf)
604 int nNewLenMaterialName
= filename
.GetLength() - nExtLen
;
605 if (sMaterialNameClear
[sMaterialNameClear
.GetLength() - nNewLenMaterialName
- 1] == '/' &&
606 !stricmp(sMaterialNameClear
.Right(nNewLenMaterialName
), filename
.Left(nNewLenMaterialName
)))
608 sMaterialNameClear
= sMaterialNameClear
.Right(nNewLenMaterialName
);
609 filename
= PathUtil::MakeGamePath(MaterialToFilename(sMaterialNameClear
).GetString()).c_str();
613 // Try to load material with this name again if not yet loaded.
614 pMaterial
= (CMaterial
*)FindItemByName(sMaterialNameClear
);
620 XmlNodeRef mtlNode
= GetISystem()->LoadXmlFromFile(filename
);
623 pMaterial
= CreateMaterial(sMaterialNameClear
, mtlNode
);
629 pMaterial
= new CMaterial(sMaterialNameClear
);
630 pMaterial
->SetDummy(true);
631 RegisterItem(pMaterial
);
633 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_WARNING
, "Material %s not found", (const char*)sMaterialNameClear
);
641 //////////////////////////////////////////////////////////////////////////
642 CMaterial
* CMaterialManager::LoadMaterial(const char* sMaterialName
, bool bMakeIfNotFound
)
644 return LoadMaterial(string(sMaterialName
), bMakeIfNotFound
);
647 //////////////////////////////////////////////////////////////////////////
648 static bool MaterialRequiresSurfaceType(CMaterial
* pMaterial
)
650 // Do not enforce Surface Type...
652 // ...over editor UI materials
653 if ((pMaterial
->GetFlags() & MTL_FLAG_UIMATERIAL
) != 0)
657 if (pMaterial
->GetShaderName() == "DistanceCloud" ||
658 pMaterial
->GetShaderName() == "Sky" ||
659 pMaterial
->GetShaderName() == "SkyHDR")
661 // ...over terrain materials
662 if (pMaterial
->GetShaderName() == "Terrain.Layer")
664 // ...over vegetation
665 if (pMaterial
->GetShaderName() == "Vegetation")
669 CVarBlock
* pShaderGenParams
= pMaterial
->GetShaderGenParamsVars();
670 if (pShaderGenParams
)
671 if (IVariable
* pVar
= pShaderGenParams
->FindVariable("Decal"))
682 //////////////////////////////////////////////////////////////////////////
683 int CMaterialManager::GetHighlightFlags(CMaterial
* pMaterial
) const
685 if (pMaterial
== NULL
)
688 if ((pMaterial
->GetFlags() & MTL_FLAG_NODRAW
) != 0)
693 if (pMaterial
== m_pHighlightMaterial
)
694 result
|= eHighlight_Pick
;
696 const string
& surfaceTypeName
= pMaterial
->GetSurfaceTypeName();
697 if (surfaceTypeName
.IsEmpty() && MaterialRequiresSurfaceType(pMaterial
))
698 result
|= eHighlight_NoSurfaceType
;
700 if (ISurfaceTypeManager
* pSurfaceManager
= GetIEditorImpl()->Get3DEngine()->GetMaterialManager()->GetSurfaceTypeManager())
702 const ISurfaceType
* pSurfaceType
= pSurfaceManager
->GetSurfaceTypeByName(surfaceTypeName
);
703 if (pSurfaceType
&& pSurfaceType
->GetBreakability() != 0)
704 result
|= eHighlight_Breakable
;
710 //////////////////////////////////////////////////////////////////////////
711 void CMaterialManager::AddForHighlighting(CMaterial
* pMaterial
)
713 if (pMaterial
== NULL
)
718 int highlightFlags
= (GetHighlightFlags(pMaterial
) & m_highlightMask
);
719 if (highlightFlags
!= 0)
721 m_pHighlighter
->Start(pMaterial
, highlightFlags
);
724 int count
= pMaterial
->GetSubMaterialCount();
725 for (int i
= 0; i
< count
; ++i
)
727 CMaterial
* pChild
= pMaterial
->GetSubMaterial(i
);
731 AddForHighlighting(pChild
);
735 //////////////////////////////////////////////////////////////////////////
736 void CMaterialManager::RemoveFromHighlighting(CMaterial
* pMaterial
, int mask
)
738 if (pMaterial
== NULL
)
741 m_pHighlighter
->Stop(pMaterial
, mask
);
743 int count
= pMaterial
->GetSubMaterialCount();
744 for (int i
= 0; i
< count
; ++i
)
746 CMaterial
* pChild
= pMaterial
->GetSubMaterial(i
);
750 RemoveFromHighlighting(pChild
, mask
);
754 //////////////////////////////////////////////////////////////////////////
755 void CMaterialManager::UpdateHighlightedMaterials()
757 IDataBaseItemEnumerator
* pEnum
= CBaseLibraryManager::GetItemEnumerator();
761 CMaterial
* pMaterial
= (CMaterial
*)pEnum
->GetFirst();
764 RemoveFromHighlighting(pMaterial
, eHighlight_All
);
765 AddForHighlighting(pMaterial
);
766 pMaterial
= (CMaterial
*)pEnum
->GetNext();
772 //////////////////////////////////////////////////////////////////////////
773 IMaterial
* CMaterialManager::OnLoadMaterial(const char* sMtlName
, bool bForceCreation
, unsigned long nLoadingFlags
)
775 _smart_ptr
<CMaterial
> pMaterial
= LoadMaterial(sMtlName
, bForceCreation
);
778 AddForHighlighting(pMaterial
);
779 return pMaterial
->GetMatInfo();
784 //////////////////////////////////////////////////////////////////////////
785 void CMaterialManager::OnRequestMaterial(IMaterial
* pMatInfo
)
787 const char* pcName
= pMatInfo
->GetName();
788 CMaterial
* pMaterial
= (CMaterial
*) pMatInfo
->GetUserData();
790 // LoadMaterial() will return registered items if they match
791 // It will also register items if the item is not found and the XML exists and it's not a pure child
792 if (!pMaterial
&& pcName
&& *pcName
)
793 pMaterial
= LoadMaterial(pcName
, false);
797 IMaterial
* pNewMatInfo
= pMaterial
->GetMatInfo(true);
798 assert(pNewMatInfo
== pMatInfo
);
800 // RegisterItem() can be called through multiple request of the same materials or through a cascade
801 // of calls (see above), thus prevent warning messages by calling it conditionally.
802 string fullName
= pMaterial
->GetFullName();
803 if (!fullName
.IsEmpty() && !FindItemByName(fullName
))
804 RegisterItem(pMaterial
);
808 //////////////////////////////////////////////////////////////////////////
809 void CMaterialManager::OnCreateMaterial(IMaterial
* pMatInfo
)
811 if (!(pMatInfo
->GetFlags() & MTL_FLAG_PURE_CHILD
) && !(pMatInfo
->GetFlags() & MTL_FLAG_UIMATERIAL
))
813 CMaterial
* pMaterial
= new CMaterial(pMatInfo
->GetName());
814 pMaterial
->SetFromMatInfo(pMatInfo
);
815 RegisterItem(pMaterial
);
817 AddForHighlighting(pMaterial
);
822 //////////////////////////////////////////////////////////////////////////
823 void CMaterialManager::OnDeleteMaterial(IMaterial
* pMaterial
)
825 CMaterial
* pMtl
= (CMaterial
*)pMaterial
->GetUserData();
828 RemoveFromHighlighting(pMtl
, eHighlight_All
);
829 pMtl
->ClearMatInfo();
833 //////////////////////////////////////////////////////////////////////////
834 CMaterial
* CMaterialManager::FromIMaterial(IMaterial
* pMaterial
)
838 CMaterial
* pMtl
= (CMaterial
*)pMaterial
->GetUserData();
842 //////////////////////////////////////////////////////////////////////////
843 void CMaterialManager::SaveAllLibs()
847 //////////////////////////////////////////////////////////////////////////
848 string
CMaterialManager::FilenameToMaterial(const string
& filename
)
850 string name
= PathUtil::RemoveExtension(filename
.GetString()).c_str();
851 name
.Replace('\\', '/');
853 string sDataFolder
= PathUtil::GetGameFolder();
854 // Remove "DATA_FOLDER/" sub path from the filename.
855 if (name
.GetLength() > (sDataFolder
.GetLength()) && strnicmp(name
, sDataFolder
, sDataFolder
.GetLength()) == 0)
857 name
= name
.Mid(sDataFolder
.GetLength() + 1); // skip the slash...
861 // Remove "materials/" sub path from the filename.
862 if (name.GetLength() > sizeof(MATERIALS_PATH)-1 && strnicmp(name,MATERIALS_PATH,sizeof(MATERIALS_PATH)-1) == 0)
864 //name = name.Mid(sizeof(MATERIALS_PATH)+1);
870 //////////////////////////////////////////////////////////////////////////
871 string
CMaterialManager::MaterialToFilename(const string
& sMaterialName
, bool bForWriting
)
873 string filename
= PathUtil::ReplaceExtension(sMaterialName
.GetString(), MATERIAL_FILE_EXT
).c_str();
877 //////////////////////////////////////////////////////////////////////////
878 bool CMaterialManager::DeleteMaterial(CMaterial
* pMtl
)
881 _smart_ptr
<CMaterial
> _ref(pMtl
);
882 if (pMtl
== GetCurrentMaterial())
883 SetCurrentMaterial(NULL
);
887 // Unassign this material from all objects.
888 CBaseObjectsArray objects
;
889 GetIEditorImpl()->GetObjectManager()->GetObjects(objects
);
891 for (i
= 0; i
< objects
.size(); i
++)
893 CBaseObject
* pObject
= objects
[i
];
894 if (pObject
->GetMaterial() == pMtl
)
896 pObject
->SetMaterial(NULL
);
899 // Delete it from all sub materials.
900 for (i
= 0; i
< m_pLevelLibrary
->GetItemCount(); i
++)
902 CMaterial
* pMultiMtl
= (CMaterial
*)m_pLevelLibrary
->GetItem(i
);
903 if (pMultiMtl
->IsMultiSubMaterial())
905 for (int slot
= 0; slot
< pMultiMtl
->GetSubMaterialCount(); slot
++)
907 if (pMultiMtl
->GetSubMaterial(slot
) == pMultiMtl
)
909 // Clear this sub material slot.
910 pMultiMtl
->SetSubMaterial(slot
, 0);
916 // Delete file on disk.
917 if (!pMtl
->GetFilename().IsEmpty())
919 if (!::DeleteFile(pMtl
->GetFilename()))
926 //////////////////////////////////////////////////////////////////////////
927 bool CMaterialManager::SelectSaveMaterial(string
& itemName
, const char* defaultStartPath
)
930 if (defaultStartPath
&& defaultStartPath
[0] != '\0')
932 startPath
= defaultStartPath
;
936 startPath
= string(PathUtil::GetGameFolder()) + "/Materials";
940 if (!CFileUtil::SelectSaveFile("Material Files (*.mtl)|*.mtl", "mtl", startPath
, filename
))
945 filename
= PathUtil::ToDosPath(filename
.GetString()).c_str();
947 itemName
= PathUtil::AbsolutePathToGamePath(filename
.GetString()).c_str();
948 itemName
= PathUtil::RemoveExtension(itemName
.GetString()).c_str();
949 if (itemName
.IsEmpty())
955 //////////////////////////////////////////////////////////////////////////
956 CMaterial
* CMaterialManager::SelectNewMaterial(int nMtlFlags
, const char* szStartPath
)
963 else if (m_pCurrentMaterial
)
965 path
= PathUtil::GetPathWithoutFilename(m_pCurrentMaterial
->GetFilename());
969 path
= m_currentFolder
;
972 if (!SelectSaveMaterial(itemName
, path
))
975 if (FindItemByName(itemName
))
977 Warning("Material with name %s already exist", (const char*)itemName
);
981 _smart_ptr
<CMaterial
> mtl
= CreateMaterial(itemName
, XmlNodeRef(), nMtlFlags
);
984 SetCurrentMaterial(mtl
);
988 //////////////////////////////////////////////////////////////////////////
989 void CMaterialManager::Command_Create()
991 SelectNewMaterial(0);
994 //////////////////////////////////////////////////////////////////////////
995 void CMaterialManager::Command_CreateMulti()
997 SelectNewMaterial(MTL_FLAG_MULTI_SUBMTL
);
1000 //////////////////////////////////////////////////////////////////////////
1001 void CMaterialManager::Command_ConvertToMulti()
1003 CMaterial
* pMaterial
= GetCurrentMaterial();
1005 if (pMaterial
&& pMaterial
->GetSubMaterialCount() == 0)
1007 pMaterial
->ConvertToMultiMaterial();
1009 pMaterial
->Reload();
1010 SetSelectedItem(pMaterial
->GetSubMaterial(0));
1014 Warning(pMaterial
? "material.convert_to_multi called on invalid material setup" : "material.convert_to_multi called while no material selected");
1018 //////////////////////////////////////////////////////////////////////////
1019 void CMaterialManager::Command_Duplicate()
1021 CMaterial
* pSrcMtl
= GetCurrentMaterial();
1025 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_WARNING
, "material.duplicate_current called while no materials selected");
1029 if (GetIEditorImpl()->IsSourceControlAvailable())
1031 uint32 attrib
= pSrcMtl
->GetFileAttributes();
1033 if ((attrib
& SCC_FILE_ATTRIBUTE_INPAK
) && (attrib
& SCC_FILE_ATTRIBUTE_MANAGED
) && !(attrib
& SCC_FILE_ATTRIBUTE_NORMAL
))
1035 // Get latest for making folders with right case
1036 GetIEditorImpl()->GetSourceControl()->GetLatestVersion(pSrcMtl
->GetFilename());
1040 if (pSrcMtl
!= 0 && !pSrcMtl
->IsPureChild())
1042 string name
= MakeUniqItemName(pSrcMtl
->GetName());
1043 // Create a new material.
1044 _smart_ptr
<CMaterial
> pMtl
= DuplicateMaterial(name
, pSrcMtl
);
1048 SetSelectedItem(pMtl
);
1053 //////////////////////////////////////////////////////////////////////////
1054 CMaterial
* CMaterialManager::DuplicateMaterial(const char* newName
, CMaterial
* pOriginal
)
1058 assert(0 && "NULL newName passed into " __FUNCTION__
);
1063 assert(0 && "NULL pOriginal passed into " __FUNCTION__
);
1067 XmlNodeRef node
= GetISystem()->CreateXmlNode("Material");
1068 CBaseLibraryItem::SerializeContext
ctx(node
, false);
1069 ctx
.bCopyPaste
= true;
1070 pOriginal
->Serialize(ctx
);
1072 return CreateMaterial(newName
, node
, pOriginal
->GetFlags());
1075 //////////////////////////////////////////////////////////////////////////
1076 void CMaterialManager::Command_Merge()
1079 string defaultMaterialPath
;
1080 if (m_pCurrentMaterial
)
1081 defaultMaterialPath
= PathUtil::GetPathWithoutFilename(m_pCurrentMaterial
->GetFilename());
1082 if (!SelectSaveMaterial(itemName
, defaultMaterialPath
))
1085 _smart_ptr
<CMaterial
> pNewMaterial
= CreateMaterial(itemName
, XmlNodeRef(), MTL_FLAG_MULTI_SUBMTL
);
1087 size_t numRecords
= m_markedMaterials
.size();
1088 size_t subMaterialIndex
= 0;
1089 for (size_t i
= 0; i
< numRecords
; ++i
)
1091 _smart_ptr
<CMaterial
>& pMaterial
= m_markedMaterials
[i
];
1092 int subMaterialCount
= pMaterial
->GetSubMaterialCount();
1093 pNewMaterial
->SetSubMaterialCount(pNewMaterial
->GetSubMaterialCount() + subMaterialCount
);
1094 for (size_t j
= 0; j
< subMaterialCount
; ++j
)
1096 CMaterial
* pSubMaterial
= pMaterial
->GetSubMaterial(j
);
1097 CMaterial
* pNewSubMaterial
= 0;
1100 // generate unique name
1101 string name
= pSubMaterial
->GetName();
1102 size_t nameIndex
= 0;
1104 bool nameUpdated
= true;
1107 nameUpdated
= false;
1108 for (size_t k
= 0; k
< subMaterialIndex
; ++k
)
1110 if (pNewMaterial
->GetSubMaterial(k
)->GetName() == name
)
1113 name
.Format("%s%02d", pSubMaterial
->GetName(), nameIndex
);
1119 pNewSubMaterial
= DuplicateMaterial(name
, pSubMaterial
);
1121 pNewMaterial
->SetSubMaterial(subMaterialIndex
, pNewSubMaterial
);
1126 pNewMaterial
->Update();
1127 pNewMaterial
->Save();
1128 SetCurrentMaterial(pNewMaterial
);
1131 //////////////////////////////////////////////////////////////////////////
1132 void CMaterialManager::Command_Delete()
1134 CMaterial
* pMtl
= GetCurrentMaterial();
1137 CUndo
undo("Delete Material");
1139 str
.Format(_T("Delete Material %s?\r\nNote: Material file %s will also be deleted."),
1140 (const char*)pMtl
->GetName(), (const char*)pMtl
->GetFilename());
1141 if (MessageBox(AfxGetMainWnd()->GetSafeHwnd(), str
, _T("Delete Confirmation"), MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
1143 DeleteMaterial(pMtl
);
1144 SetCurrentMaterial(0);
1149 void CMaterialManager::Command_CreateTerrainLayer()
1151 CMaterial
* pMaterial
= GetCurrentMaterial();
1157 string sMaterialPath
= pMaterial
? pMaterial
->GetName() : "";
1158 bool bFound
= false;
1159 CTerrainManager
* terrainManager
= GetIEditorImpl()->GetTerrainManager();
1161 for (int i
= 0, n
= terrainManager
->GetLayerCount(); i
< n
; ++i
)
1163 CLayer
* pCurLayer
= terrainManager
->GetLayer(i
);
1164 CSurfaceType
* pSurfaceType
= pCurLayer
->GetSurfaceType();
1166 if (pSurfaceType
&& stricmp(pSurfaceType
->GetMaterial(), sMaterialPath
.GetBuffer()) == 0)
1175 MessageBox(AfxGetMainWnd()->GetSafeHwnd(), _T("There's already a terrain layer with that material."), _T("Existing layer"), MB_ICONEXCLAMATION
);
1179 pLayer
= new CLayer
;
1180 pLayer
->SetLayerName(PathUtil::GetFile(sMaterialPath
.c_str()));
1181 pLayer
->LoadTexture(string(PathUtil::GetGameFolder() + "/Textures/Terrain/Default.dds"));
1182 pLayer
->GetOrRequestLayerId();
1183 terrainManager
->AddLayer(pLayer
);
1184 pLayer
->AssignMaterial(sMaterialPath
);
1185 terrainManager
->ReloadSurfaceTypes(true, false);
1188 for (int i
= 0, n
= terrainManager
->GetLayerCount(); i
< n
; ++i
)
1189 terrainManager
->GetLayer(i
)->SetSelected(false);
1191 pLayer
->SetSelected(true);
1192 GetIEditorImpl()->Notify(eNotify_OnInvalidateControls
);
1195 //////////////////////////////////////////////////////////////////////////
1196 void CMaterialManager::Command_AssignToSelection()
1198 CMaterial
* pMtl
= GetCurrentMaterial();
1201 CUndo
undo("Assign Material");
1202 const CSelectionGroup
* pSel
= GetIEditorImpl()->GetSelection();
1203 if (pMtl
->IsPureChild())
1205 int nSelectionCount
= pSel
->GetCount();
1206 bool bAllDesignerObject
= nSelectionCount
== 0 ? false : true;
1207 for (int i
= 0; i
< nSelectionCount
; ++i
)
1209 if (pSel
->GetObject(i
)->GetType() != OBJTYPE_SOLID
)
1211 bAllDesignerObject
= false;
1215 if (!bAllDesignerObject
)
1217 if (MessageBox(AfxGetMainWnd()->GetSafeHwnd(), _T("You can assign submaterials to objects only for preview purpose. This assignment will not be saved with the level and will not be exported to the game."), _T("Assign Submaterial"), MB_OKCANCEL
| MB_ICONINFORMATION
) == IDCANCEL
)
1221 if (!pSel
->IsEmpty())
1223 for (int i
= 0; i
< pSel
->GetCount(); i
++)
1225 pSel
->GetObject(i
)->SetMaterial(pMtl
);
1226 pSel
->GetObject(i
)->UpdateGroup();
1227 pSel
->GetObject(i
)->UpdatePrefab();
1231 CViewport
* pViewport
= GetIEditorImpl()->GetActiveView();
1234 pViewport
->Drop(CPoint(-1, -1), pMtl
);
1238 //////////////////////////////////////////////////////////////////////////
1239 void CMaterialManager::Command_ResetSelection()
1241 const CSelectionGroup
* pSel
= GetIEditorImpl()->GetSelection();
1242 if (!pSel
->IsEmpty())
1244 CUndo
undo("Reset Material");
1245 for (int i
= 0; i
< pSel
->GetCount(); i
++)
1247 CBaseObject
* pObject
= pSel
->GetObject(i
);
1248 pObject
->SetMaterial(0);
1249 pObject
->UpdatePrefab();
1252 CViewport
* pViewport
= GetIEditorImpl()->GetActiveView();
1255 pViewport
->Drop(CPoint(-1, -1), 0);
1259 //////////////////////////////////////////////////////////////////////////
1260 void CMaterialManager::Command_SelectAssignedObjects()
1262 CMaterial
* pMtl
= GetCurrentMaterial();
1265 CUndo
undo("Select Object(s)");
1266 CBaseObjectsArray objects
;
1267 GetIEditorImpl()->GetObjectManager()->GetObjects(objects
);
1268 for (int i
= 0; i
< objects
.size(); i
++)
1270 CBaseObject
* pObject
= objects
[i
];
1271 if (pObject
->GetMaterial() == pMtl
|| pObject
->GetRenderMaterial() == pMtl
)
1273 if (pObject
->IsHidden() || pObject
->IsFrozen())
1275 GetIEditorImpl()->GetObjectManager()->SelectObject(pObject
);
1281 //////////////////////////////////////////////////////////////////////////
1282 void CMaterialManager::Command_SelectFromObject()
1284 if (GetIEditorImpl()->IsInPreviewMode())
1286 CViewport
* pViewport
= GetIEditorImpl()->GetActiveView();
1287 if (pViewport
&& pViewport
->GetType() == ET_ViewportModel
)
1289 CMaterial
* pMtl
= static_cast<CMaterial
*>(((CModelViewport
*)pViewport
)->GetMaterial());
1290 SetCurrentMaterial(pMtl
);
1295 const CSelectionGroup
* pSel
= GetIEditorImpl()->GetSelection();
1296 if (pSel
->IsEmpty())
1299 for (int i
= 0; i
< pSel
->GetCount(); i
++)
1301 CMaterial
* pMtl
= (CMaterial
*)pSel
->GetObject(i
)->GetRenderMaterial();
1304 SetCurrentMaterial(pMtl
);
1310 //////////////////////////////////////////////////////////////////////////
1311 void CMaterialManager::PickPreviewMaterial(HWND hWndCaller
)
1313 XmlNodeRef data
= XmlHelpers::CreateXmlNode("ExportMaterial");
1314 CMaterial
* pMtl
= GetCurrentMaterial();
1318 if (pMtl
->IsPureChild() && pMtl
->GetParent())
1319 pMtl
= pMtl
->GetParent();
1321 if (pMtl
->GetFlags() & MTL_FLAG_WIRE
)
1322 data
->setAttr("Flag_Wire", 1);
1323 if (pMtl
->GetFlags() & MTL_FLAG_2SIDED
)
1324 data
->setAttr("Flag_2Sided", 1);
1326 data
->setAttr("Name", pMtl
->GetName());
1327 data
->setAttr("FileName", pMtl
->GetFilename());
1329 XmlNodeRef node
= data
->newChild("Material");
1331 CBaseLibraryItem::SerializeContext
serCtx(node
, false);
1332 pMtl
->Serialize(serCtx
);
1334 if (!pMtl
->IsMultiSubMaterial())
1336 XmlNodeRef texturesNode
= node
->findChild("Textures");
1339 for (int i
= 0; i
< texturesNode
->getChildCount(); i
++)
1341 XmlNodeRef texNode
= texturesNode
->getChild(i
);
1343 if (texNode
->getAttr("File", file
))
1346 if (file
.size() >= 2 && file
.c_str()[0] == '.' && (file
.c_str()[1] == '/' || file
.c_str()[1] == '\\'))
1348 // Texture file location is relative to material file folder
1349 file
= PathUtil::Make(PathUtil::GetPathWithoutFilename(pMtl
->GetFilename()), &file
.c_str()[2]);
1352 char sFullFilenameLC
[MAX_PATH
];
1353 GetCurrentDirectory(MAX_PATH
, sFullFilenameLC
);
1354 cry_strcat(sFullFilenameLC
, "\\");
1355 cry_strcat(sFullFilenameLC
, PathUtil::GamePathToCryPakPath(file
.GetString()));
1356 texNode
->setAttr("File", sFullFilenameLC
);
1363 XmlNodeRef childsNode
= node
->findChild("SubMaterials");
1366 int nSubMtls
= childsNode
->getChildCount();
1367 for (int i
= 0; i
< nSubMtls
; i
++)
1369 XmlNodeRef node
= childsNode
->getChild(i
);
1370 XmlNodeRef texturesNode
= node
->findChild("Textures");
1373 for (int i
= 0; i
< texturesNode
->getChildCount(); i
++)
1375 XmlNodeRef texNode
= texturesNode
->getChild(i
);
1377 if (texNode
->getAttr("File", file
))
1380 if (file
.size() >= 2 && file
.c_str()[0] == '.' && (file
.c_str()[1] == '/' || file
.c_str()[1] == '\\'))
1382 // Texture file location is relative to material file folder
1383 file
= PathUtil::Make(PathUtil::GetPathWithoutFilename(pMtl
->GetFilename()), &file
.c_str()[2]);
1386 char sFullFilenameLC
[MAX_PATH
];
1387 GetCurrentDirectory(MAX_PATH
, sFullFilenameLC
);
1388 cry_strcat(sFullFilenameLC
, "\\");
1389 cry_strcat(sFullFilenameLC
, PathUtil::GamePathToCryPakPath(file
.GetString()));
1390 texNode
->setAttr("File", sFullFilenameLC
);
1391 //texNode->setAttr( "File", Path::GamePathToFullPath(file) );
1399 m_MatSender
->SendMessage(eMSM_GetSelectedMaterial
, data
);
1402 //////////////////////////////////////////////////////////////////////////
1403 void CMaterialManager::SyncMaterialEditor()
1408 if (!m_MatSender
->GetMessage())
1411 if (m_MatSender
->m_h
.msg
== eMSM_Create
)
1413 XmlNodeRef node
= m_MatSender
->m_node
->findChild("Material");
1420 XmlNodeRef root
= m_MatSender
->m_node
;
1421 root
->getAttr("Name", sMtlName
);
1422 root
->getAttr("MaxFile", sMaxFile
);
1425 root
->getAttr("IsMulti", IsMulti
);
1429 nMtlFlags
|= MTL_FLAG_MULTI_SUBMTL
;
1431 if (root
->haveAttr("Flag_Wire"))
1432 nMtlFlags
|= MTL_FLAG_WIRE
;
1433 if (root
->haveAttr("Flag_2Sided"))
1434 nMtlFlags
|= MTL_FLAG_2SIDED
;
1436 _smart_ptr
<CMaterial
> pMtl
= SelectNewMaterial(nMtlFlags
, PathUtil::GetPathWithoutFilename(sMaxFile
));
1443 node
->delAttr("Shader"); // Remove shader attribute.
1444 XmlNodeRef texturesNode
= node
->findChild("Textures");
1447 for (int i
= 0; i
< texturesNode
->getChildCount(); i
++)
1449 XmlNodeRef texNode
= texturesNode
->getChild(i
);
1451 if (texNode
->getAttr("File", file
))
1453 //make path relative to the project specific game folder
1454 string newfile
= PathUtil::AbsolutePathToGamePath(file
.GetString()).c_str();
1455 if (newfile
.GetLength() > 0)
1457 texNode
->setAttr("File", file
);
1464 XmlNodeRef childsNode
= node
->findChild("SubMaterials");
1467 int nSubMtls
= childsNode
->getChildCount();
1468 for (int i
= 0; i
< nSubMtls
; i
++)
1470 XmlNodeRef node
= childsNode
->getChild(i
);
1471 node
->delAttr("Shader"); // Remove shader attribute.
1472 XmlNodeRef texturesNode
= node
->findChild("Textures");
1475 for (int i
= 0; i
< texturesNode
->getChildCount(); i
++)
1477 XmlNodeRef texNode
= texturesNode
->getChild(i
);
1479 if (texNode
->getAttr("File", file
))
1481 //make path relative to the project specific game folder
1482 string newfile
= PathUtil::AbsolutePathToGamePath(file
.GetString()).c_str();
1483 if (newfile
.GetLength() > 0)
1485 texNode
->setAttr("File", file
);
1493 CBaseLibraryItem::SerializeContext
ctx(node
, true);
1495 pMtl
->Serialize(ctx
);
1499 SetCurrentMaterial(0);
1500 SetCurrentMaterial(pMtl
);
1503 if (m_MatSender
->m_h
.msg
== eMSM_GetSelectedMaterial
)
1505 PickPreviewMaterial(m_MatSender
->m_h
.GetMaxHWND());
1509 //////////////////////////////////////////////////////////////////////////
1510 void CMaterialManager::InitMatSender()
1514 HWND mainWnd
= (HWND
)CEditorMainFrame::GetInstance()->winId();
1515 CRY_ASSERT(mainWnd
);
1517 m_MatSender
->Create();
1518 m_MatSender
->SetupWindows(mainWnd
, mainWnd
);
1519 XmlNodeRef node
= XmlHelpers::CreateXmlNode("Temp");
1520 m_MatSender
->SendMessage(eMSM_Init
, node
);
1523 void CMaterialManager::OnDebugFlagsChanged()
1525 int debugFlags
= gViewportDebugPreferences
.GetDebugFlags();
1527 int mask
= GetHighlightMask();
1528 if (debugFlags
& DBG_HIGHLIGHT_BREAKABLE
)
1529 mask
|= eHighlight_Breakable
;
1531 mask
&= ~eHighlight_Breakable
;
1533 if (debugFlags
& DBG_HIGHLIGHT_MISSING_SURFACE_TYPE
)
1534 mask
|= eHighlight_NoSurfaceType
;
1536 mask
&= ~eHighlight_NoSurfaceType
;
1538 SetHighlightMask(mask
);
1541 //////////////////////////////////////////////////////////////////////////
1542 void CMaterialManager::GotoMaterial(CMaterial
* pMaterial
)
1545 GetIEditorImpl()->OpenDataBaseLibrary(EDB_TYPE_MATERIAL
, pMaterial
);
1548 //////////////////////////////////////////////////////////////////////////
1549 void CMaterialManager::GotoMaterial(IMaterial
* pMtl
)
1553 CMaterial
* pEdMaterial
= FromIMaterial(pMtl
);
1555 GetIEditorImpl()->OpenDataBaseLibrary(EDB_TYPE_MATERIAL
, pEdMaterial
);
1559 //////////////////////////////////////////////////////////////////////////
1560 void CMaterialManager::SetHighlightedMaterial(CMaterial
* pMtl
)
1562 if (m_pHighlightMaterial
)
1563 RemoveFromHighlighting(m_pHighlightMaterial
, eHighlight_Pick
);
1565 m_pHighlightMaterial
= pMtl
;
1566 if (m_pHighlightMaterial
)
1567 AddForHighlighting(m_pHighlightMaterial
);
1570 //////////////////////////////////////////////////////////////////////////
1571 void CMaterialManager::HighlightedMaterialChanged(CMaterial
* pMtl
)
1576 RemoveFromHighlighting(pMtl
, eHighlight_All
);
1577 AddForHighlighting(pMtl
);
1580 //////////////////////////////////////////////////////////////////////////
1581 void CMaterialManager::SetHighlightMask(int highlightMask
)
1583 if (m_highlightMask
!= highlightMask
)
1585 m_highlightMask
= highlightMask
;
1587 UpdateHighlightedMaterials();
1591 //////////////////////////////////////////////////////////////////////////
1592 void CMaterialManager::GatherResources(IMaterial
* pMaterial
, CUsedResources
& resources
)
1597 int nSubMtlCount
= pMaterial
->GetSubMtlCount();
1598 if (nSubMtlCount
> 0)
1600 for (int i
= 0; i
< nSubMtlCount
; i
++)
1602 GatherResources(pMaterial
->GetSubMtl(i
), resources
);
1607 SShaderItem
& shItem
= pMaterial
->GetShaderItem();
1608 if (shItem
.m_pShaderResources
)
1610 SInputShaderResourcesPtr res
= gEnv
->pRenderer
->EF_CreateInputShaderResource();
1611 shItem
.m_pShaderResources
->ConvertToInputResource(res
);
1613 for (int i
= 0; i
< EFTT_MAX
; i
++)
1615 if (!res
->m_Textures
[i
].m_Name
.empty())
1617 resources
.Add(res
->m_Textures
[i
].m_Name
.c_str());
1624 ///////////////////////////////////////////////////////////////////////////
1625 void CMaterialManager::GetHighlightColor(ColorF
* color
, float* intensity
, int flags
)
1627 MAKE_SURE(m_pHighlighter
, return );
1628 m_pHighlighter
->GetHighlightColor(color
, intensity
, flags
);
1631 void CMaterialManager::CreateTerrainLayerFromMaterial(CMaterial
* pMaterial
)
1637 string sMaterialPath
= pMaterial
? pMaterial
->GetName() : "";
1638 bool bFound
= false;
1639 CTerrainManager
* terrainManager
= GetIEditorImpl()->GetTerrainManager();
1641 for (int i
= 0, n
= terrainManager
->GetLayerCount(); i
< n
; ++i
)
1643 CLayer
* pCurLayer
= terrainManager
->GetLayer(i
);
1644 CSurfaceType
* pSurfaceType
= pCurLayer
->GetSurfaceType();
1646 if (pSurfaceType
&& stricmp(pSurfaceType
->GetMaterial(), sMaterialPath
.c_str()) == 0)
1655 pLayer
= new CLayer
;
1656 pLayer
->SetLayerName(PathUtil::GetFile(sMaterialPath
.c_str()));
1657 pLayer
->LoadTexture(string(PathUtil::GetGameFolder() + "/Textures/Terrain/Default.dds"));
1658 pLayer
->GetOrRequestLayerId();
1659 terrainManager
->AddLayer(pLayer
);
1660 pLayer
->AssignMaterial(sMaterialPath
);
1661 terrainManager
->ReloadSurfaceTypes(true, false);
1664 for (int i
= 0, n
= terrainManager
->GetLayerCount(); i
< n
; ++i
)
1665 terrainManager
->GetLayer(i
)->SetSelected(false);
1667 pLayer
->SetSelected(true);
1668 GetIEditorImpl()->Notify(eNotify_OnInvalidateControls
);