EditorMaterialComponentSlot.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Atom/RPI.Edit/Common/AssetUtils.h>
  9. #include <Atom/RPI.Edit/Material/MaterialSourceData.h>
  10. #include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
  11. #include <AzCore/Asset/AssetSerializer.h>
  12. #include <AzCore/RTTI/BehaviorContext.h>
  13. #include <AzCore/Serialization/EditContext.h>
  14. #include <AzCore/Serialization/SerializeContext.h>
  15. #include <AzToolsFramework/API/ToolsApplicationAPI.h>
  16. #include <Material/EditorMaterialComponentExporter.h>
  17. #include <Material/EditorMaterialComponentInspector.h>
  18. #include <Material/EditorMaterialComponentSlot.h>
  19. #include <Material/EditorMaterialModelUvNameMapInspector.h>
  20. AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
  21. #include <QAction>
  22. #include <QByteArray>
  23. #include <QCursor>
  24. #include <QDataStream>
  25. #include <QMenu>
  26. AZ_POP_DISABLE_WARNING
  27. namespace AZ
  28. {
  29. namespace Render
  30. {
  31. // Update serialized data to the new format and data types
  32. bool EditorMaterialComponentSlot::ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  33. {
  34. if (classElement.GetVersion() < 2)
  35. {
  36. constexpr AZ::u32 materialIdDataCrc = AZ_CRC_CE("id");
  37. AZStd::pair<MaterialAssignmentLodIndex, AZ::Data::AssetId> oldId;
  38. if (!classElement.GetChildData(materialIdDataCrc, oldId))
  39. {
  40. AZ_Error("AZ::Render::EditorMaterialComponentSlot::ConvertVersion", false, "Failed to get id element");
  41. return false;
  42. }
  43. if (!classElement.RemoveElementByName(materialIdDataCrc))
  44. {
  45. AZ_Error("AZ::Render::EditorMaterialComponentSlot::ConvertVersion", false, "Failed to remove id element");
  46. return false;
  47. }
  48. const MaterialAssignmentId newId(oldId.first, oldId.second.m_subId);
  49. classElement.AddElementWithData(context, "id", newId);
  50. }
  51. if (classElement.GetVersion() < 4)
  52. {
  53. constexpr AZ::u32 matModUvOverridesCrc = AZ_CRC_CE("matModUvOverrides");
  54. AZStd::unordered_map<uint32_t, AZ::Name> oldMatModUvOverrides;
  55. if (classElement.GetChildData(matModUvOverridesCrc, oldMatModUvOverrides))
  56. {
  57. // This feature is very new, so we assume that any existing matModUvOverrides data is empty.
  58. AZ_Error("AZ::Render::EditorMaterialComponentSlot::ConvertVersion", oldMatModUvOverrides.empty(), "Conversion from old matModUvOverrides is not supported. The new overrides map will be empty.");
  59. // We just consume the old element to avoid reporting errors about an unknown class ID when serialization continues.
  60. classElement.RemoveElementByName(matModUvOverridesCrc);
  61. }
  62. }
  63. if (classElement.GetVersion() < 5)
  64. {
  65. classElement.RemoveElementByName(AZ_CRC_CE("matModUvOverrides"));
  66. classElement.RemoveElementByName(AZ_CRC_CE("propertyOverrides"));
  67. }
  68. return true;
  69. }
  70. void EditorMaterialComponentSlot::Reflect(ReflectContext* context)
  71. {
  72. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  73. {
  74. serializeContext->Class<EditorMaterialComponentSlot>()
  75. ->Version(7, &EditorMaterialComponentSlot::ConvertVersion)
  76. ->Field("id", &EditorMaterialComponentSlot::m_id)
  77. ->Field("materialAsset", &EditorMaterialComponentSlot::m_materialAsset)
  78. ;
  79. if (AZ::EditContext* editContext = serializeContext->GetEditContext())
  80. {
  81. editContext->Class<EditorMaterialComponentSlot>(
  82. "EditorMaterialComponentSlot", "")
  83. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  84. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  85. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  86. ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMaterialComponentSlot::m_materialAsset, "Material Asset", "")
  87. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorMaterialComponentSlot::OnMaterialChangedFromRPE)
  88. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  89. ->Attribute(AZ::Edit::Attributes::DefaultAsset, &EditorMaterialComponentSlot::GetDefaultAssetId)
  90. ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &EditorMaterialComponentSlot::GetLabel)
  91. ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true)
  92. ->Attribute("ThumbnailCallback", &EditorMaterialComponentSlot::OpenPopupMenu)
  93. ->Attribute("ThumbnailIcon", &EditorMaterialComponentSlot::GetPreviewPixmapData)
  94. ;
  95. }
  96. }
  97. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  98. {
  99. behaviorContext->Class<EditorMaterialComponentSlot>("EditorMaterialComponentSlot")
  100. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
  101. ->Attribute(AZ::Script::Attributes::Category, "Editor")
  102. ->Attribute(AZ::Script::Attributes::Module, "editor")
  103. ->Constructor()
  104. ->Constructor<const EditorMaterialComponentSlot&>()
  105. ->Property("id", BehaviorValueProperty(&EditorMaterialComponentSlot::m_id))
  106. ->Property("materialAsset", BehaviorValueProperty(&EditorMaterialComponentSlot::m_materialAsset))
  107. ->Method("GetPreviewPixmapData", &EditorMaterialComponentSlot::GetPreviewPixmapData)
  108. ->Method("GetActiveAssetId", &EditorMaterialComponentSlot::GetActiveAssetId)
  109. ->Method("GetDefaultAssetId", &EditorMaterialComponentSlot::GetDefaultAssetId)
  110. ->Method("GetLabel", &EditorMaterialComponentSlot::GetLabel)
  111. ->Method("HasSourceData", &EditorMaterialComponentSlot::HasSourceData)
  112. ->Method("SetAsset", &EditorMaterialComponentSlot::SetAsset)
  113. ->Method("SetAssetId", &EditorMaterialComponentSlot::SetAssetId)
  114. ->Method("Clear", &EditorMaterialComponentSlot::Clear)
  115. ->Method("ClearMaterial", &EditorMaterialComponentSlot::ClearMaterial)
  116. ->Method("ClearProperties", &EditorMaterialComponentSlot::ClearProperties)
  117. ->Method("OpenMaterialExporter", &EditorMaterialComponentSlot::OpenMaterialExporter)
  118. ->Method("OpenMaterialEditor", &EditorMaterialComponentSlot::OpenMaterialEditor)
  119. ->Method("OpenMaterialInspector", &EditorMaterialComponentSlot::OpenMaterialInspector)
  120. ->Method("OpenUvNameMapInspector", &EditorMaterialComponentSlot::OpenUvNameMapInspector)
  121. ->Method("ExportMaterial", &EditorMaterialComponentSlot::ExportMaterial)
  122. ;
  123. }
  124. }
  125. EditorMaterialComponentSlot::EditorMaterialComponentSlot(
  126. const AZ::EntityId& entityId, const MaterialAssignmentId& materialAssignmentId)
  127. : m_entityId(entityId)
  128. , m_id(materialAssignmentId)
  129. {
  130. bool isOverridden = false;
  131. MaterialComponentRequestBus::EventResult(
  132. isOverridden, m_entityId, &MaterialComponentRequestBus::Events::IsMaterialAssetIdOverridden, m_id);
  133. AZ::Data::AssetId assetId = {};
  134. MaterialComponentRequestBus::EventResult(assetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialAssetId, m_id);
  135. if (assetId.IsValid())
  136. {
  137. AZ::Data::AssetBus::Handler::BusConnect(assetId);
  138. if (isOverridden)
  139. {
  140. m_materialAsset = AZ::Data::Asset<AZ::RPI::MaterialAsset>(assetId, AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid());
  141. }
  142. }
  143. EditorMaterialSystemComponentNotificationBus::Handler::BusConnect();
  144. }
  145. EditorMaterialComponentSlot::~EditorMaterialComponentSlot()
  146. {
  147. EditorMaterialSystemComponentNotificationBus::Handler::BusDisconnect();
  148. AZ::Data::AssetBus::Handler::BusDisconnect();
  149. }
  150. AZStd::vector<char> EditorMaterialComponentSlot::GetPreviewPixmapData() const
  151. {
  152. // Don't display a custom image if there is no material asset assigned to this slot.
  153. if (!GetActiveAssetId().IsValid())
  154. {
  155. return {};
  156. }
  157. // Don't display a custom image if no properties have been overridden. It will fall back to the default thumbnail.
  158. bool hasPropertiesOverridden = false;
  159. MaterialComponentRequestBus::EventResult(
  160. hasPropertiesOverridden, m_entityId, &MaterialComponentRequestBus::Events::HasPropertiesOverridden, m_id);
  161. if (!hasPropertiesOverridden)
  162. {
  163. return {};
  164. }
  165. QPixmap pixmap;
  166. EditorMaterialSystemComponentRequestBus::BroadcastResult(
  167. pixmap, &EditorMaterialSystemComponentRequestBus::Events::GetRenderedMaterialPreview, m_entityId, m_id);
  168. if (pixmap.isNull())
  169. {
  170. if (m_updatePreview)
  171. {
  172. UpdatePreview();
  173. }
  174. return {};
  175. }
  176. QByteArray pixmapBytes;
  177. QDataStream stream(&pixmapBytes, QIODevice::WriteOnly);
  178. stream << pixmap;
  179. return AZStd::vector<char>(pixmapBytes.begin(), pixmapBytes.end());
  180. }
  181. AZ::Data::AssetId EditorMaterialComponentSlot::GetActiveAssetId() const
  182. {
  183. AZ::Data::AssetId assetId = {};
  184. MaterialComponentRequestBus::EventResult(
  185. assetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialAssetId, m_id);
  186. return assetId;
  187. }
  188. AZ::Data::AssetId EditorMaterialComponentSlot::GetDefaultAssetId() const
  189. {
  190. AZ::Data::AssetId assetId = {};
  191. MaterialComponentRequestBus::EventResult(
  192. assetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_id);
  193. return assetId;
  194. }
  195. AZStd::string EditorMaterialComponentSlot::GetLabel() const
  196. {
  197. AZStd::string label;
  198. MaterialComponentRequestBus::EventResult(label, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialLabel, m_id);
  199. return label;
  200. }
  201. bool EditorMaterialComponentSlot::HasSourceData() const
  202. {
  203. // The slot only has valid source data if the source path is valid and the file has the correct extension
  204. const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(GetActiveAssetId());
  205. return !sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension);
  206. }
  207. void EditorMaterialComponentSlot::SetAsset(const Data::Asset<RPI::MaterialAsset>& asset)
  208. {
  209. m_materialAsset = asset;
  210. OnDataChanged({ m_entityId }, true);
  211. }
  212. void EditorMaterialComponentSlot::SetAssetId(const Data::AssetId& assetId)
  213. {
  214. SetAsset(AZ::Data::Asset<AZ::RPI::MaterialAsset>(assetId, AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid()));
  215. }
  216. void EditorMaterialComponentSlot::Clear()
  217. {
  218. MaterialComponentRequestBus::Event(
  219. m_entityId, &MaterialComponentRequestBus::Events::SetPropertyValues, m_id, MaterialPropertyOverrideMap());
  220. MaterialComponentRequestBus::Event(
  221. m_entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id, AZ::RPI::MaterialModelUvOverrideMap());
  222. SetAsset({});
  223. }
  224. void EditorMaterialComponentSlot::ClearMaterial()
  225. {
  226. SetAsset({});
  227. }
  228. void EditorMaterialComponentSlot::ClearProperties()
  229. {
  230. MaterialComponentRequestBus::Event(
  231. m_entityId, &MaterialComponentRequestBus::Events::SetPropertyValues, m_id, MaterialPropertyOverrideMap());
  232. MaterialComponentRequestBus::Event(
  233. m_entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id, AZ::RPI::MaterialModelUvOverrideMap());
  234. OnDataChanged({ m_entityId }, false);
  235. }
  236. void EditorMaterialComponentSlot::OpenMaterialExporter(const AzToolsFramework::EntityIdSet& entityIdsToEdit)
  237. {
  238. // Because we are generating a source material from this specific slot there is only one entry
  239. // But we still need to allow the user to reconfigure it using the dialog
  240. EditorMaterialComponentExporter::ExportItemsContainer exportItems;
  241. exportItems.emplace_back(GetDefaultAssetId(), GetLabel());
  242. if (EditorMaterialComponentExporter::OpenExportDialog(exportItems))
  243. {
  244. const auto& exportItem = exportItems.front();
  245. if (EditorMaterialComponentExporter::ExportMaterialSourceData(exportItem))
  246. {
  247. if (const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0))
  248. {
  249. m_materialAsset = AZ::Data::Asset<AZ::RPI::MaterialAsset>(
  250. assetIdOutcome.GetValue(), AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid());
  251. OnDataChanged(entityIdsToEdit, true);
  252. }
  253. }
  254. }
  255. }
  256. void EditorMaterialComponentSlot::ExportMaterial(const AZStd::string& exportPath, bool overwrite)
  257. {
  258. EditorMaterialComponentExporter::ProgressDialog progressDialog("Generating materials", "Generating material...", 1);
  259. EditorMaterialComponentExporter::ExportItem exportItem(GetDefaultAssetId(), GetLabel(), exportPath);
  260. exportItem.SetOverwrite(overwrite);
  261. if (EditorMaterialComponentExporter::ExportMaterialSourceData(exportItem))
  262. {
  263. const AZ::Data::AssetInfo assetInfo = progressDialog.ProcessItem(exportItem);
  264. if (assetInfo.m_assetId.IsValid())
  265. {
  266. SetAssetId(assetInfo.m_assetId);
  267. progressDialog.CompleteItem();
  268. }
  269. }
  270. }
  271. void EditorMaterialComponentSlot::OpenMaterialCanvas() const
  272. {
  273. EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenMaterialCanvas, "");
  274. }
  275. void EditorMaterialComponentSlot::OpenMaterialEditor() const
  276. {
  277. EditorMaterialSystemComponentRequestBus::Broadcast(
  278. &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialEditor,
  279. AZ::RPI::AssetUtils::GetSourcePathByAssetId(GetActiveAssetId()));
  280. }
  281. void EditorMaterialComponentSlot::OpenMaterialInspector(const AzToolsFramework::EntityIdSet& entityIdsToEdit)
  282. {
  283. EditorMaterialSystemComponentRequestBus::Broadcast(
  284. &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialInspector, m_entityId, entityIdsToEdit, m_id);
  285. }
  286. void EditorMaterialComponentSlot::OpenUvNameMapInspector(const AzToolsFramework::EntityIdSet& entityIdsToEdit)
  287. {
  288. if (GetActiveAssetId().IsValid())
  289. {
  290. AZStd::unordered_set<AZ::Name> modelUvNames;
  291. MaterialConsumerRequestBus::EventResult(modelUvNames, m_entityId, &MaterialConsumerRequestBus::Events::GetModelUvNames);
  292. RPI::MaterialModelUvOverrideMap matModUvOverrides;
  293. MaterialComponentRequestBus::EventResult(
  294. matModUvOverrides, m_entityId, &MaterialComponentRequestBus::Events::GetModelUvOverrides, m_id);
  295. auto applyMatModUvOverrideChangedCallback = [&](const RPI::MaterialModelUvOverrideMap& matModUvOverrides)
  296. {
  297. for (const AZ::EntityId& entityId : entityIdsToEdit)
  298. {
  299. MaterialComponentRequestBus::Event(
  300. entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id, matModUvOverrides);
  301. }
  302. };
  303. if (EditorMaterialComponentInspector::OpenInspectorDialog(
  304. GetActiveAssetId(), matModUvOverrides, modelUvNames, applyMatModUvOverrideChangedCallback))
  305. {
  306. OnDataChanged(entityIdsToEdit, false);
  307. }
  308. }
  309. }
  310. void EditorMaterialComponentSlot::OpenPopupMenu([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType)
  311. {
  312. const auto& entityIdsToEdit = EditorMaterialComponentUtil::GetSelectedEntitiesFromActiveInspector();
  313. const bool hasMatchingSlots = EditorMaterialComponentUtil::DoEntitiesHaveMatchingMaterialSlots(m_entityId, entityIdsToEdit);
  314. const bool hasMatchingMaterialTypes = EditorMaterialComponentUtil::DoEntitiesHaveMatchingMaterialTypes(m_entityId, entityIdsToEdit, m_id);
  315. QMenu menu;
  316. QAction* action = nullptr;
  317. action = menu.addAction("Generate/Manage Source Material...", [this, entityIdsToEdit]() { OpenMaterialExporter(entityIdsToEdit); });
  318. action->setEnabled(GetDefaultAssetId().IsValid() && hasMatchingSlots);
  319. menu.addSeparator();
  320. action = menu.addAction("Open Material Editor...", [this]() { OpenMaterialEditor(); });
  321. action = menu.addAction("Open Material Canvas...", [this]() { OpenMaterialCanvas(); });
  322. action = menu.addAction("Open Material Instance Editor...", [this, entityIdsToEdit]() { OpenMaterialInspector(entityIdsToEdit); });
  323. action->setEnabled(GetActiveAssetId().IsValid() && hasMatchingMaterialTypes);
  324. action = menu.addAction("Open Material Instance UV Map Editor...", [this, entityIdsToEdit]() { OpenUvNameMapInspector(entityIdsToEdit); });
  325. action->setEnabled(GetActiveAssetId().IsValid() && hasMatchingMaterialTypes);
  326. menu.addSeparator();
  327. action = menu.addAction("Clear Material Instance Overrides", [this, entityIdsToEdit]() {
  328. for (const AZ::EntityId& entityId : entityIdsToEdit)
  329. {
  330. MaterialComponentRequestBus::Event(
  331. entityId, &MaterialComponentRequestBus::Events::SetPropertyValues, m_id, MaterialPropertyOverrideMap());
  332. MaterialComponentRequestBus::Event(
  333. entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id,
  334. AZ::RPI::MaterialModelUvOverrideMap());
  335. }
  336. OnDataChanged(entityIdsToEdit, false);
  337. });
  338. action = menu.addAction("Clear Material And Properties", [this, entityIdsToEdit]() {
  339. m_materialAsset = {};
  340. for (const AZ::EntityId& entityId : entityIdsToEdit)
  341. {
  342. MaterialComponentRequestBus::Event(
  343. entityId, &MaterialComponentRequestBus::Events::SetPropertyValues, m_id, MaterialPropertyOverrideMap());
  344. MaterialComponentRequestBus::Event(
  345. entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id,
  346. AZ::RPI::MaterialModelUvOverrideMap());
  347. }
  348. OnDataChanged(entityIdsToEdit, true);
  349. });
  350. menu.exec(QCursor::pos());
  351. }
  352. void EditorMaterialComponentSlot::OnMaterialChangedFromRPE()
  353. {
  354. // Because this function is being from an edit context attribute it will automatically be applied to all selected entities
  355. OnDataChanged({ m_entityId }, true);
  356. }
  357. void EditorMaterialComponentSlot::OnDataChanged(const AzToolsFramework::EntityIdSet& entityIdsToEdit, bool updateAsset)
  358. {
  359. // Handle undo, update configuration, and refresh the inspector to display the new values
  360. AzToolsFramework::ScopedUndoBatch undoBatch("Material slot changed.");
  361. for (const AZ::EntityId& entityId : entityIdsToEdit)
  362. {
  363. AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(
  364. &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, entityId);
  365. if (updateAsset)
  366. {
  367. MaterialComponentRequestBus::Event(
  368. entityId, &MaterialComponentRequestBus::Events::SetMaterialAssetId, m_id, m_materialAsset.GetId());
  369. }
  370. EditorMaterialSystemComponentRequestBus::Broadcast(
  371. &EditorMaterialSystemComponentRequestBus::Events::RenderMaterialPreview, entityId, m_id);
  372. MaterialComponentNotificationBus::Event(entityId, &MaterialComponentNotifications::OnMaterialsEdited);
  373. }
  374. m_updatePreview = false;
  375. // Reconnect the asset bus to the current active material asset ID so that the preview can be refreshed if the asset changes
  376. AZ::Data::AssetId assetId = {};
  377. MaterialComponentRequestBus::EventResult(assetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialAssetId, m_id);
  378. if (!AZ::Data::AssetBus::Handler::BusIsConnectedId(assetId))
  379. {
  380. AZ::Data::AssetBus::Handler::BusDisconnect();
  381. if (assetId.IsValid())
  382. {
  383. AZ::Data::AssetBus::Handler::BusConnect(assetId);
  384. }
  385. }
  386. // Refresh the attributes and values for the inspector UI
  387. AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
  388. &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
  389. }
  390. void EditorMaterialComponentSlot::OnRenderMaterialPreviewReady(
  391. [[maybe_unused]] const AZ::EntityId& entityId,
  392. [[maybe_unused]] const AZ::Render::MaterialAssignmentId& materialAssignmentId,
  393. [[maybe_unused]] const QPixmap& pixmap)
  394. {
  395. if (entityId == m_entityId && materialAssignmentId == m_id)
  396. {
  397. AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
  398. &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
  399. }
  400. }
  401. void EditorMaterialComponentSlot::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
  402. {
  403. UpdatePreview();
  404. }
  405. void EditorMaterialComponentSlot::UpdatePreview() const
  406. {
  407. m_updatePreview = false;
  408. bool hasPropertiesOverridden = false;
  409. MaterialComponentRequestBus::EventResult(
  410. hasPropertiesOverridden, m_entityId, &MaterialComponentRequestBus::Events::HasPropertiesOverridden, m_id);
  411. if (!hasPropertiesOverridden)
  412. {
  413. return;
  414. }
  415. EditorMaterialSystemComponentRequestBus::Broadcast(
  416. &EditorMaterialSystemComponentRequestBus::Events::RenderMaterialPreview, m_entityId, m_id);
  417. }
  418. } // namespace Render
  419. } // namespace AZ