3
0

ShaderManagementConsoleTableView.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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 <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
  9. #include <AzCore/Name/Name.h>
  10. #include <AzQtComponents/Components/StyledSpinBox.h>
  11. #include <Window/ShaderManagementConsoleTableView.h>
  12. #include <QComboBox>
  13. #include <QHeaderView>
  14. namespace ShaderManagementConsole
  15. {
  16. ShaderManagementConsoleTableView::ShaderManagementConsoleTableView(
  17. const AZ::Crc32& toolId, const AZ::Uuid& documentId, QWidget* parent)
  18. : QTableWidget(parent)
  19. , m_toolId(toolId)
  20. , m_documentId(documentId)
  21. {
  22. setEditTriggers(QAbstractItemView::NoEditTriggers);
  23. setSelectionBehavior(QAbstractItemView::SelectItems);
  24. setSelectionMode(QAbstractItemView::SingleSelection);
  25. horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
  26. RebuildTable();
  27. AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
  28. }
  29. ShaderManagementConsoleTableView::~ShaderManagementConsoleTableView()
  30. {
  31. AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
  32. }
  33. void ShaderManagementConsoleTableView::OnDocumentOpened(const AZ::Uuid& documentId)
  34. {
  35. if (m_documentId == documentId)
  36. {
  37. RebuildTable();
  38. }
  39. }
  40. void ShaderManagementConsoleTableView::OnDocumentModified(const AZ::Uuid& documentId)
  41. {
  42. if (m_documentId == documentId)
  43. {
  44. RebuildTable();
  45. }
  46. }
  47. void ShaderManagementConsoleTableView::RebuildTable()
  48. {
  49. QSignalBlocker blocker(this);
  50. // Delete any active edit widget from the current selection
  51. setCellWidget(currentRow(), currentColumn(), nullptr);
  52. // Disconnect data change signal while populating the table
  53. disconnect();
  54. // Get the shader variant list source data whose options will be used to populate the table
  55. m_shaderVariantListSourceData = {};
  56. ShaderManagementConsoleDocumentRequestBus::EventResult(
  57. m_shaderVariantListSourceData, m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantListSourceData);
  58. // The number of variants corresponds to the number of rows in the table
  59. m_shaderVariantCount = m_shaderVariantListSourceData.m_shaderVariants.size();
  60. // The number of options corresponds to the number of columns in the table. This data is being pulled from the asset instead of the
  61. // shader variant list source data. The asset may contain more options that are listed in the source data. This will result in
  62. // several columns with no values.
  63. m_shaderOptionCount = {};
  64. ShaderManagementConsoleDocumentRequestBus::EventResult(
  65. m_shaderOptionCount, m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptorCount);
  66. // Only clear the table if the number of columns or rows have changed
  67. if (rowCount() != m_shaderVariantCount || columnCount() != m_shaderOptionCount)
  68. {
  69. clear();
  70. setRowCount(static_cast<int>(m_shaderVariantCount));
  71. setColumnCount(static_cast<int>(m_shaderOptionCount));
  72. }
  73. // Get a list of all of the shader option descriptors from the shader asset that will be used for the columns in the table
  74. m_shaderOptionDescriptors = {};
  75. m_shaderOptionDescriptors.reserve(columnCount());
  76. for (int column = 0; column < columnCount(); ++column)
  77. {
  78. AZ::RPI::ShaderOptionDescriptor shaderOptionDescriptor;
  79. ShaderManagementConsoleDocumentRequestBus::EventResult(
  80. shaderOptionDescriptor,
  81. m_documentId,
  82. &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor,
  83. column);
  84. m_shaderOptionDescriptors.push_back(shaderOptionDescriptor);
  85. }
  86. // Sort all of the descriptors by name so that the columns are arranged in alphabetical order
  87. AZStd::sort(
  88. m_shaderOptionDescriptors.begin(),
  89. m_shaderOptionDescriptors.end(),
  90. [](const auto& a, const auto& b)
  91. {
  92. return a.GetName().GetStringView() < b.GetName().GetStringView();
  93. });
  94. // Fill in the header of each column with the descriptor name
  95. for (int column = 0; column < columnCount(); ++column)
  96. {
  97. const auto& shaderOptionDescriptor = m_shaderOptionDescriptors[column];
  98. setHorizontalHeaderItem(column, new QTableWidgetItem(shaderOptionDescriptor.GetName().GetCStr()));
  99. }
  100. // Fill all the rows with values from each variant
  101. for (int row = 0; row < rowCount(); ++row)
  102. {
  103. const auto& shaderVariant = m_shaderVariantListSourceData.m_shaderVariants[row];
  104. setVerticalHeaderItem(row, new QTableWidgetItem(QString::number(row)));
  105. for (int column = 0; column < columnCount(); ++column)
  106. {
  107. const auto& shaderOptionDescriptor = m_shaderOptionDescriptors[column];
  108. const auto optionIt = shaderVariant.m_options.find(shaderOptionDescriptor.GetName());
  109. const AZ::Name valueName = optionIt != shaderVariant.m_options.end() ? AZ::Name(optionIt->second) : AZ::Name();
  110. setItem(row, column, new QTableWidgetItem(valueName.GetCStr()));
  111. }
  112. }
  113. // Connect to the data changed signal to listen for and apply table edits back to the document
  114. connect(this, &QTableWidget::currentCellChanged, this, &ShaderManagementConsoleTableView::OnCellSelected);
  115. connect(this, &QTableWidget::cellChanged, this, &ShaderManagementConsoleTableView::OnCellChanged);
  116. }
  117. void ShaderManagementConsoleTableView::OnCellSelected(int row, int column, int previousRow, int previousColumn)
  118. {
  119. setCellWidget(row, column, nullptr);
  120. setCellWidget(previousRow, previousColumn, nullptr);
  121. if (row < 0 || row >= m_shaderVariantListSourceData.m_shaderVariants.size())
  122. {
  123. return;
  124. }
  125. if (column < 0 || column >= m_shaderOptionDescriptors.size())
  126. {
  127. return;
  128. }
  129. const auto& shaderOptionDescriptor = m_shaderOptionDescriptors[column];
  130. const auto& shaderVariant = m_shaderVariantListSourceData.m_shaderVariants[row];
  131. const auto optionIt = shaderVariant.m_options.find(shaderOptionDescriptor.GetName());
  132. const AZ::Name valueName = optionIt != shaderVariant.m_options.end() ? AZ::Name(optionIt->second) : AZ::Name();
  133. const AZ::RPI::ShaderOptionValue value = shaderOptionDescriptor.FindValue(valueName);
  134. const AZ::RPI::ShaderOptionValue valueMin = shaderOptionDescriptor.GetMinValue();
  135. const AZ::RPI::ShaderOptionValue valueMax = shaderOptionDescriptor.GetMaxValue();
  136. switch (shaderOptionDescriptor.GetType())
  137. {
  138. case AZ::RPI::ShaderOptionType::Boolean:
  139. case AZ::RPI::ShaderOptionType::Enumeration:
  140. {
  141. QComboBox* comboBox = new QComboBox(this);
  142. comboBox->addItem("");
  143. for (uint32_t valueIndex = valueMin.GetIndex(); valueIndex <= valueMax.GetIndex(); ++valueIndex)
  144. {
  145. comboBox->addItem(shaderOptionDescriptor.GetValueName(AZ::RPI::ShaderOptionValue{ valueIndex }).GetCStr());
  146. }
  147. comboBox->setCurrentText(valueName.GetCStr());
  148. setCellWidget(row, column, comboBox);
  149. connect(comboBox, &QComboBox::currentTextChanged, this, [this, row, column](const QString& text) {
  150. item(row, column)->setText(text);
  151. });
  152. break;
  153. }
  154. case AZ::RPI::ShaderOptionType::IntegerRange:
  155. {
  156. AzQtComponents::StyledSpinBox* spinBox = new AzQtComponents::StyledSpinBox(this);
  157. spinBox->setRange(valueMin.GetIndex(), valueMax.GetIndex());
  158. spinBox->setValue(value.GetIndex());
  159. setCellWidget(row, column, spinBox);
  160. connect(spinBox, &AzQtComponents::StyledSpinBox::textChanged, this, [this, row, column](const QString& text) {
  161. item(row, column)->setText(text);
  162. });
  163. break;
  164. }
  165. }
  166. }
  167. void ShaderManagementConsoleTableView::OnCellChanged(int row, int column)
  168. {
  169. if (row < 0 || row >= m_shaderVariantListSourceData.m_shaderVariants.size())
  170. {
  171. return;
  172. }
  173. if (column < 0 || column >= m_shaderOptionDescriptors.size())
  174. {
  175. return;
  176. }
  177. // Update the shader variant list from the table data
  178. auto& shaderVariant = m_shaderVariantListSourceData.m_shaderVariants[row];
  179. const auto optionItem = horizontalHeaderItem(column);
  180. if (optionItem && !optionItem->text().isEmpty())
  181. {
  182. if (const auto variantItem = item(row, column))
  183. {
  184. // Set or clear the option based on the item text
  185. if (variantItem->text().isEmpty())
  186. {
  187. shaderVariant.m_options.erase(AZ::Name{optionItem->text().toUtf8().constData()});
  188. }
  189. else
  190. {
  191. shaderVariant.m_options[AZ::Name{optionItem->text().toUtf8().constData()}] = variantItem->text().toUtf8().constData();
  192. }
  193. }
  194. }
  195. // Temporarily disconnect the document notification bus to prevent recursive notification handling as changes are applied
  196. AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
  197. // Send the begin edit notification to signify the beginning of an undoable change
  198. AtomToolsFramework::AtomToolsDocumentRequestBus::Event(
  199. m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::BeginEdit);
  200. // Set the shader variant list source data built from the table onto the document
  201. ShaderManagementConsoleDocumentRequestBus::Event(
  202. m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::SetShaderVariantListSourceData, m_shaderVariantListSourceData);
  203. // Signify the end of the undoable change
  204. AtomToolsFramework::AtomToolsDocumentRequestBus::Event(
  205. m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::EndEdit);
  206. // Reconnect to the notification bus now that all changes have been applied
  207. AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
  208. }
  209. } // namespace ShaderManagementConsole
  210. #include <Window/moc_ShaderManagementConsoleTableView.cpp>