NodeListSelectionWidget.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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 <SceneAPI/SceneCore/Containers/Scene.h>
  9. #include <SceneAPI/SceneCore/Containers/SceneGraph.h>
  10. #include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
  11. #include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
  12. #include <SceneAPI/SceneUI/SceneWidgets/ManifestWidget.h>
  13. #include <SceneAPI/SceneUI/RowWidgets/NodeListSelectionWidget.h>
  14. namespace AZ
  15. {
  16. namespace SceneAPI
  17. {
  18. namespace UI
  19. {
  20. AZ_CLASS_ALLOCATOR_IMPL(NodeListSelectionWidget, SystemAllocator);
  21. NodeListSelectionWidget::NodeListSelectionWidget(QWidget* parent)
  22. : QComboBox(parent)
  23. , m_classTypeId(Uuid::CreateNull())
  24. , m_exactClassTypeMatch(false)
  25. , m_hasDirtyList(true)
  26. , m_useShortNames(false)
  27. , m_excludeEndPoints(false)
  28. , m_defaultToDisabled(false)
  29. {
  30. connect(this, &QComboBox::currentTextChanged, this, &NodeListSelectionWidget::OnTextChange);
  31. }
  32. void NodeListSelectionWidget::SetCurrentSelection(const AZStd::string& selection)
  33. {
  34. m_currentSelection = selection;
  35. if (!m_hasDirtyList)
  36. {
  37. SetSelection();
  38. }
  39. }
  40. AZStd::string NodeListSelectionWidget::GetCurrentSelection() const
  41. {
  42. return currentText().toStdString().c_str();
  43. }
  44. void NodeListSelectionWidget::AddDisabledOption(const AZStd::string& option)
  45. {
  46. m_disabledOption = option;
  47. m_hasDirtyList = true;
  48. }
  49. void NodeListSelectionWidget::AddDisabledOption(AZStd::string&& option)
  50. {
  51. m_disabledOption = AZStd::move(option);
  52. m_hasDirtyList = true;
  53. }
  54. const AZStd::string& NodeListSelectionWidget::GetDisabledOption() const
  55. {
  56. return m_disabledOption;
  57. }
  58. void NodeListSelectionWidget::UseShortNames(bool use)
  59. {
  60. m_useShortNames = use;
  61. m_hasDirtyList = true;
  62. }
  63. void NodeListSelectionWidget::ExcludeEndPoints(bool exclude)
  64. {
  65. m_excludeEndPoints = exclude;
  66. m_hasDirtyList = true;
  67. }
  68. void NodeListSelectionWidget::DefaultToDisabled(bool value)
  69. {
  70. m_defaultToDisabled = value;
  71. m_hasDirtyList = true;
  72. }
  73. void NodeListSelectionWidget::SetClassTypeId(const Uuid& classTypeId)
  74. {
  75. m_classTypeId = classTypeId;
  76. m_hasDirtyList = true;
  77. }
  78. void NodeListSelectionWidget::ClearClassTypeId()
  79. {
  80. m_classTypeId = Uuid::CreateNull();
  81. m_hasDirtyList = true;
  82. }
  83. void NodeListSelectionWidget::UseExactClassTypeMatch(bool exactMatch)
  84. {
  85. m_exactClassTypeMatch = exactMatch;
  86. m_hasDirtyList = true;
  87. }
  88. void NodeListSelectionWidget::OnTextChange(const QString& text)
  89. {
  90. if (!m_hasDirtyList)
  91. {
  92. m_currentSelection = text.toStdString().c_str();
  93. emit valueChanged(m_currentSelection);
  94. }
  95. }
  96. void NodeListSelectionWidget::showEvent(QShowEvent* event)
  97. {
  98. if (m_hasDirtyList)
  99. {
  100. clear();
  101. ManifestWidget* mainWidget = ManifestWidget::FindRoot(this);
  102. AZ_Assert(mainWidget, "NodeListSelectionWidget is not an (in)direct child of the ManifestWidget.");
  103. if (!mainWidget)
  104. {
  105. return;
  106. }
  107. const Containers::SceneGraph& graph = mainWidget->GetScene()->GetGraph();
  108. BuildList(graph);
  109. AddDisabledOption();
  110. SetSelection();
  111. setEnabled(count() > 1);
  112. m_hasDirtyList = false;
  113. }
  114. QComboBox::showEvent(event);
  115. }
  116. void NodeListSelectionWidget::BuildList(const Containers::SceneGraph& graph)
  117. {
  118. QStringList entries;
  119. auto view = Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage());
  120. for (auto it = view.begin(); it != view.end(); ++it)
  121. {
  122. if (!it->second || it->first.GetPathLength() == 0)
  123. {
  124. continue;
  125. }
  126. if (!IsCorrectType(*it->second))
  127. {
  128. continue;
  129. }
  130. if (m_excludeEndPoints)
  131. {
  132. Containers::SceneGraph::NodeIndex index = graph.ConvertToNodeIndex(it.GetFirstIterator());
  133. if (graph.IsNodeEndPoint(index))
  134. {
  135. continue;
  136. }
  137. }
  138. AddEntry(entries, it->first);
  139. }
  140. if (!entries.empty())
  141. {
  142. entries.removeDuplicates();
  143. addItems(entries);
  144. }
  145. }
  146. bool NodeListSelectionWidget::IsCorrectType(const DataTypes::IGraphObject& object) const
  147. {
  148. if (m_classTypeId.IsNull())
  149. {
  150. return true;
  151. }
  152. if (m_exactClassTypeMatch)
  153. {
  154. return object.RTTI_GetType() == m_classTypeId;
  155. }
  156. else
  157. {
  158. return object.RTTI_IsTypeOf(m_classTypeId);
  159. }
  160. }
  161. void NodeListSelectionWidget::AddEntry(QStringList& comboListEntries, const Containers::SceneGraph::Name& name)
  162. {
  163. if (m_useShortNames)
  164. {
  165. const char* shortName = name.GetName();
  166. comboListEntries.append(QString(shortName));
  167. }
  168. else
  169. {
  170. const char* pathName = name.GetPath();
  171. comboListEntries.append(QString(pathName));
  172. }
  173. }
  174. void NodeListSelectionWidget::SetSelection()
  175. {
  176. QString entryName = m_currentSelection.c_str();
  177. int index = findText(entryName);
  178. if (m_disabledOption.empty())
  179. {
  180. if (index >= 0)
  181. {
  182. setCurrentIndex(index);
  183. }
  184. else
  185. {
  186. if (!isEditable())
  187. {
  188. // If not freeform editable, and no disabled option available to set to first entry.
  189. setCurrentIndex(0);
  190. }
  191. else
  192. {
  193. setEditText(entryName);
  194. }
  195. }
  196. }
  197. else
  198. {
  199. // Check against index 1 as an empty string will return the separator.
  200. if (index >= 0 && index != 1)
  201. {
  202. setCurrentIndex(index);
  203. }
  204. else if (!m_defaultToDisabled && count() >= 2)
  205. {
  206. // Pick third option as the first is the default followed
  207. // by the separator.
  208. setCurrentIndex(2);
  209. }
  210. else if (!isEditable())
  211. {
  212. // If not editable and no match was found, set to first entry.
  213. setCurrentIndex(0);
  214. }
  215. else
  216. {
  217. setEditText(entryName);
  218. }
  219. }
  220. }
  221. void NodeListSelectionWidget::AddDisabledOption()
  222. {
  223. if (!m_disabledOption.empty())
  224. {
  225. insertItem(0, m_disabledOption.c_str());
  226. // Only add a separator if the disabled option isn't the only entry.
  227. if (count() > 1)
  228. {
  229. insertSeparator(1);
  230. }
  231. }
  232. }
  233. } // UI
  234. } // SceneAPI
  235. } // AZ
  236. #include <RowWidgets/moc_NodeListSelectionWidget.cpp>