AudioControl.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. #pragma once
  9. #include <ACETypes.h>
  10. #include <AzCore/std/string/string_view.h>
  11. #include <AzCore/XML/rapidxml.h>
  12. #include <IAudioConnection.h>
  13. #include <IAudioSystemControl.h>
  14. namespace AudioControls
  15. {
  16. class CATLControlsModel;
  17. //-------------------------------------------------------------------------------------------//
  18. struct SRawConnectionData
  19. {
  20. SRawConnectionData(AZ::rapidxml::xml_node<char>* node, bool isValid)
  21. {
  22. m_xmlNode = DeepCopyNode(node);
  23. m_isValid = isValid;
  24. }
  25. AZ::rapidxml::xml_node<char>* m_xmlNode = nullptr;
  26. // indicates if the connection is valid for the currently loaded middleware
  27. bool m_isValid{ false };
  28. private:
  29. // Rapid XML provides a 'clone_node' utility that will copy an entire node tree,
  30. // but it only copies pointers of any strings in the node names and values.
  31. // This causes problems with storage of xml trees, as this class does, because strings
  32. // will be pointing into an xml document's file buffer that has gone out of scope.
  33. // This function is a rewritten version of 'clone_node' that does the deep copy of strings
  34. // into the new destination tree.
  35. [[nodiscard]] AZ::rapidxml::xml_node<char>* DeepCopyNode(AZ::rapidxml::xml_node<char>* srcNode)
  36. {
  37. if (!srcNode)
  38. {
  39. return nullptr;
  40. }
  41. XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator);
  42. AZ::rapidxml::xml_node<char>* destNode = xmlAlloc.allocate_node(srcNode->type());
  43. destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size());
  44. destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size());
  45. for (AZ::rapidxml::xml_node<char>* child = srcNode->first_node(); child != nullptr; child = child->next_sibling())
  46. {
  47. destNode->append_node(DeepCopyNode(child));
  48. }
  49. for (AZ::rapidxml::xml_attribute<char>* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute())
  50. {
  51. destNode->append_attribute(xmlAlloc.allocate_attribute(
  52. xmlAlloc.allocate_string(attr->name(), attr->name_size()),
  53. xmlAlloc.allocate_string(attr->value(), attr->value_size()),
  54. attr->name_size(),
  55. attr->value_size()
  56. ));
  57. }
  58. return destNode;
  59. }
  60. };
  61. using TXmlNodeList = AZStd::vector<SRawConnectionData>;
  62. //-------------------------------------------------------------------------------------------//
  63. class CATLControl
  64. {
  65. friend class CAudioControlsLoader;
  66. friend class CAudioControlsWriter;
  67. friend class CUndoControlModified;
  68. public:
  69. CATLControl() = default;
  70. CATLControl(const AZStd::string& controlName, CID id, EACEControlType type, CATLControlsModel* atlControlsModel);
  71. ~CATLControl();
  72. CID GetId() const;
  73. AZStd::string GetName() const;
  74. CATLControl* GetParent() const;
  75. AZStd::string GetScope() const;
  76. EACEControlType GetType() const;
  77. bool HasScope() const;
  78. bool IsAutoLoad() const;
  79. void SetAutoLoad(bool isAutoLoad);
  80. void SetName(const AZStd::string_view name);
  81. void SetParent(CATLControl* parent);
  82. void SetScope(const AZStd::string_view scope);
  83. size_t ChildCount() const
  84. {
  85. return m_children.size();
  86. }
  87. CATLControl* GetChild(size_t index) const
  88. {
  89. return (index < m_children.size() ? m_children[index] : nullptr);
  90. }
  91. void AddChild(CATLControl* childControl)
  92. {
  93. if (childControl)
  94. {
  95. m_children.push_back(childControl);
  96. }
  97. }
  98. void RemoveChild(CATLControl* childControl)
  99. {
  100. if (childControl)
  101. {
  102. m_children.erase(AZStd::remove(m_children.begin(), m_children.end(), childControl), m_children.end());
  103. }
  104. }
  105. size_t ConnectionCount() const;
  106. TConnectionPtr GetConnectionAt(size_t index) const;
  107. TConnectionPtr GetConnection(CID id) const;
  108. TConnectionPtr GetConnection(IAudioSystemControl* middlewareControl) const;
  109. void AddConnection(TConnectionPtr connection);
  110. void RemoveConnection(TConnectionPtr connection);
  111. void RemoveConnection(IAudioSystemControl* middlewareControl);
  112. void ClearConnections();
  113. void ReloadConnections();
  114. bool IsFullyConnected() const;
  115. void SignalControlAboutToBeModified();
  116. void SignalControlModified();
  117. void SignalConnectionAdded(IAudioSystemControl* middlewareControl);
  118. void SignalConnectionRemoved(IAudioSystemControl* middlewareControl);
  119. bool SwitchStateConnectionCheck(IAudioSystemControl* middlewareControl);
  120. private:
  121. void SetId(CID id);
  122. void SetType(EACEControlType type);
  123. CID m_id = ACE_INVALID_CID;
  124. EACEControlType m_type = eACET_TRIGGER;
  125. AZStd::string m_name;
  126. AZStd::string m_scope;
  127. AZStd::vector<TConnectionPtr> m_connectedControls;
  128. AZStd::vector<CATLControl*> m_children;
  129. CATLControlsModel* m_atlControlsModel = nullptr;
  130. CATLControl* m_parent = nullptr;
  131. bool m_isAutoLoad = true;
  132. // All the raw connection nodes. Used for reloading the data when switching middleware.
  133. TXmlNodeList m_connectionNodes;
  134. };
  135. } // namespace AudioControls