From 5b148b1f40351098cfdabd89448caa33dfb00394 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 22 Jul 2021 17:37:44 -0500 Subject: [PATCH 1/8] Convert legacy XML handling to rapidxml Updates the Audio Controls Editor code to use rapidxml instead of legacy xml apis. Further makes improvements to path manipulations away from strings towards PathView apis and similar. Fixes some issues encountered with memory management when handling xml data that did not occur previously. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Source/Editor/AudioSystemEditor_wwise.cpp | 205 ++++++--- .../Source/Editor/AudioSystemEditor_wwise.h | 4 +- .../Code/Source/Editor/AudioWwiseLoader.cpp | 21 +- .../Code/Include/Editor/ACETypes.h | 4 + .../Code/Include/Editor/IAudioSystemEditor.h | 8 +- .../Code/Include/Engine/ATLCommon.h | 1 + .../Code/Include/Engine/AudioFileUtils.h | 17 +- .../Code/Source/Editor/AudioControl.h | 53 ++- .../Editor/AudioControlsEditorWindow.cpp | 39 +- .../Source/Editor/AudioControlsLoader.cpp | 407 +++++++++--------- .../Code/Source/Editor/AudioControlsLoader.h | 11 +- .../Source/Editor/AudioControlsWriter.cpp | 183 +++++--- .../Code/Source/Editor/AudioControlsWriter.h | 25 +- .../Source/Editor/QAudioControlEditorIcons.h | 4 +- .../Code/Source/Engine/ATLComponents.cpp | 8 +- 15 files changed, 580 insertions(+), 410 deletions(-) diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp index 4dfafa132a..5bad3ecf1c 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp @@ -19,10 +19,7 @@ #include #include -#include -#include -#include -#include +#include void InitWwiseResources() { @@ -217,28 +214,34 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - TConnectionPtr CAudioSystemEditor_wwise::CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType) + TConnectionPtr CAudioSystemEditor_wwise::CreateConnectionFromXMLNode(AZ::rapidxml::xml_node* node, EACEControlType atlControlType) { if (node) { - const AZStd::string tag(node->getTag()); - TImplControlType type = TagToType(tag); + AZStd::string_view element(node->name()); + TImplControlType type = TagToType(element); if (type != AUDIO_IMPL_INVALID_TYPE) { - AZStd::string name(node->getAttr(Audio::WwiseXmlTags::WwiseNameAttribute)); - AZStd::string localized(node->getAttr(Audio::WwiseXmlTags::WwiseLocalizedAttribute)); + AZStd::string name; + AZStd::string_view localized; - // Legacy Preload support - if (localized.empty()) + if (auto nameAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseNameAttribute, 0, false); + nameAttr != nullptr) { - localized = node->getAttr(Audio::WwiseXmlTags::Legacy::WwiseLocalizedAttribute); + name = nameAttr->value(); } - bool isLocalized = AZ::StringFunc::Equal(localized.c_str(), "true"); + if (auto localizedAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseLocalizedAttribute, 0, false); + localizedAttr != nullptr) + { + localized = localizedAttr->value(); + } - // If control not found, create a placeholder. - // We want to keep that connection even if it's not in the middleware. - // The user could be using the engine without the wwise project + bool isLocalized = AZ::StringFunc::Equal(localized, "true"); + + // If the control wasn't found, create a placeholder. + // We want to see that connection even if it's not in the middleware. + // User could be viewing the editor without a middleware project. IAudioSystemControl* control = GetControlByName(name, isLocalized); if (!control) { @@ -250,27 +253,26 @@ namespace AudioControls } } - // If it's a switch we actually connect to one of the states within the switch + // If it's a switch we connect to one of the states within the switch if (type == eWCT_WWISE_SWITCH_GROUP || type == eWCT_WWISE_GAME_STATE_GROUP) { - if (node->getChildCount() == 1) + if (auto childNode = node->first_node(); + childNode != nullptr) { - node = node->getChild(0); - if (node) + AZStd::string childName; + if (auto childNameAttr = childNode->first_attribute(Audio::WwiseXmlTags::WwiseNameAttribute, 0, false); + childNameAttr != nullptr) { - AZStd::string childName(node->getAttr(Audio::WwiseXmlTags::WwiseNameAttribute)); - - IAudioSystemControl* childControl = GetControlByName(childName, false, control); - if (!childControl) - { - childControl = CreateControl(SControlDef(childName, type == eWCT_WWISE_SWITCH_GROUP ? eWCT_WWISE_SWITCH : eWCT_WWISE_GAME_STATE, false, control)); - } - control = childControl; + childName = childNameAttr->value(); } - } - else - { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "Audio Controls Editor (Wwise): Error reading connection to Wwise control %s", name.c_str()); + + IAudioSystemControl* childControl = GetControlByName(childName, false, control); + if (!childControl) + { + childControl = CreateControl(SControlDef( + childName, type == eWCT_WWISE_SWITCH_GROUP ? eWCT_WWISE_SWITCH : eWCT_WWISE_GAME_STATE, false, control)); + } + control = childControl; } } @@ -289,16 +291,19 @@ namespace AudioControls float mult = 1.0f; float shift = 0.0f; - if (node->haveAttr(Audio::WwiseXmlTags::WwiseMutiplierAttribute)) + + if (auto multAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseMutiplierAttribute, 0, false); + multAttr != nullptr) { - const AZStd::string multProperty(node->getAttr(Audio::WwiseXmlTags::WwiseMutiplierAttribute)); - mult = AZStd::stof(multProperty); + mult = AZStd::stof(AZStd::string(multAttr->value())); } - if (node->haveAttr(Audio::WwiseXmlTags::WwiseShiftAttribute)) + + if (auto shiftAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseShiftAttribute, 0, false); + shiftAttr != nullptr) { - const AZStd::string shiftProperty(node->getAttr(Audio::WwiseXmlTags::WwiseShiftAttribute)); - shift = AZStd::stof(shiftProperty); + shift = AZStd::stof(AZStd::string(shiftAttr->value())); } + connection->m_mult = mult; connection->m_shift = shift; return connection; @@ -308,11 +313,12 @@ namespace AudioControls TStateConnectionPtr connection = AZStd::make_shared(control->GetId()); float value = 0.0f; - if (node->haveAttr(Audio::WwiseXmlTags::WwiseValueAttribute)) + if (auto valueAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseValueAttribute, 0, false); + valueAttr != nullptr) { - const AZStd::string valueProperty(node->getAttr(Audio::WwiseXmlTags::WwiseValueAttribute)); - value = AZStd::stof(valueProperty); + value = AZStd::stof(AZStd::string(valueAttr->value())); } + connection->m_value = value; return connection; } @@ -329,28 +335,50 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - XmlNodeRef CAudioSystemEditor_wwise::CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) + AZ::rapidxml::xml_node* CAudioSystemEditor_wwise::CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) { const IAudioSystemControl* control = GetControl(connection->GetID()); if (control) { + XmlAllocator& xmlAllocator(AudioControls::s_xmlAllocator); + switch (control->GetType()) { case AudioControls::eWCT_WWISE_SWITCH: + [[fallthrough]]; case AudioControls::eWCT_WWISE_SWITCH_GROUP: + [[fallthrough]]; case AudioControls::eWCT_WWISE_GAME_STATE: + [[fallthrough]]; case AudioControls::eWCT_WWISE_GAME_STATE_GROUP: { const IAudioSystemControl* parent = control->GetParent(); if (parent) { - XmlNodeRef switchNode = GetISystem()->CreateXmlNode(TypeToTag(parent->GetType()).data()); - switchNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, parent->GetName().c_str()); + AZStd::string_view parentType = TypeToTag(parent->GetType()); + auto switchNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(parentType.data()) + ); - XmlNodeRef stateNode = switchNode->createNode(Audio::WwiseXmlTags::WwiseValueTag); - stateNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); - switchNode->addChild(stateNode); + auto switchNameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(parent->GetName().c_str()) + ); + auto stateNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + Audio::WwiseXmlTags::WwiseValueTag + ); + + auto stateNameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + switchNode->append_attribute(switchNameAttr); + stateNode->append_attribute(stateNameAttr); + switchNode->append_node(stateNode); return switchNode; } break; @@ -358,51 +386,98 @@ namespace AudioControls case AudioControls::eWCT_WWISE_RTPC: { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); + auto connectionNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(TypeToTag(control->GetType()).data()) + ); + + auto nameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + connectionNode->append_attribute(nameAttr); if (atlControlType == eACET_RTPC) { AZStd::shared_ptr rtpcConnection = AZStd::static_pointer_cast(connection); - if (rtpcConnection->m_mult != 1.0f) + if (rtpcConnection->m_mult != 1.f) { - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseMutiplierAttribute, rtpcConnection->m_mult); + auto multAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseMutiplierAttribute, + xmlAllocator.allocate_string(AZStd::to_string(rtpcConnection->m_mult).c_str()) + ); + + connectionNode->append_attribute(multAttr); } - if (rtpcConnection->m_shift != 0.0f) + + if (rtpcConnection->m_shift != 0.f) { - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseShiftAttribute, rtpcConnection->m_shift); + auto shiftAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseShiftAttribute, + xmlAllocator.allocate_string(AZStd::to_string(rtpcConnection->m_shift).c_str()) + ); + + connectionNode->append_attribute(shiftAttr); } } else if (atlControlType == eACET_SWITCH_STATE) { AZStd::shared_ptr stateConnection = AZStd::static_pointer_cast(connection); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseValueAttribute, stateConnection->m_value); + + auto valueAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseValueAttribute, + xmlAllocator.allocate_string(AZStd::to_string(stateConnection->m_value).c_str()) + ); + + connectionNode->append_attribute(valueAttr); } + return connectionNode; } case AudioControls::eWCT_WWISE_EVENT: - { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); - return connectionNode; - } - + [[fallthrough]]; case AudioControls::eWCT_WWISE_AUX_BUS: { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); + auto connectionNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(TypeToTag(control->GetType()).data()) + ); + + auto nameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + connectionNode->append_attribute(nameAttr); return connectionNode; } case AudioControls::eWCT_WWISE_SOUND_BANK: { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); + auto connectionNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(TypeToTag(control->GetType()).data()) + ); + + auto nameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + connectionNode->append_attribute(nameAttr); + if (control->IsLocalized()) { - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseLocalizedAttribute, "true"); + auto locAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseLocalizedAttribute, + xmlAllocator.allocate_string("true") + ); + + connectionNode->append_attribute(locAttr); } + return connectionNode; } } diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h index 14708a5816..25c621de76 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h @@ -77,8 +77,8 @@ namespace AudioControls EACEControlType ImplTypeToATLType(TImplControlType type) const override; TImplControlTypeMask GetCompatibleTypes(EACEControlType atlControlType) const override; TConnectionPtr CreateConnectionToControl(EACEControlType atlControlType, IAudioSystemControl* middlewareControl) override; - TConnectionPtr CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType) override; - XmlNodeRef CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) override; + TConnectionPtr CreateConnectionFromXMLNode(AZ::rapidxml::xml_node* node, EACEControlType atlControlType) override; + AZ::rapidxml::xml_node* CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) override; const AZStd::string_view GetTypeIcon(TImplControlType type) const override; const AZStd::string_view GetTypeIconSelected(TImplControlType type) const override; AZStd::string GetName() const override; diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp index 30320a567f..1a3ff121f8 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp @@ -17,12 +17,6 @@ #include #include -#include -#include -#include -#include - -using namespace PathUtil; namespace AudioControls { @@ -68,8 +62,7 @@ namespace AudioControls for (const auto& filePath : foundFiles) { AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", filePath.c_str()); - AZStd::string fileName; - AZ::StringFunc::Path::GetFullFileName(filePath.c_str(), fileName); + AZ::IO::PathView fileName = filePath.Filename(); if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(filePath.c_str())) { @@ -79,15 +72,15 @@ namespace AudioControls // we load only one as all of them should have the // same content (in the future we want to have a // consistency report to highlight if this is not the case) - m_localizationFolder = fileName; + m_localizationFolder.assign(fileName.Native().data(), fileName.Native().size()); LoadSoundBanks(rootFolder, m_localizationFolder, true); isLocalizedLoaded = true; } } - else if (AZ::StringFunc::Find(fileName.c_str(), Audio::Wwise::BankExtension) != AZStd::string::npos - && !AZ::StringFunc::Equal(fileName.c_str(), Audio::Wwise::InitBank)) + else if (fileName.Extension() == Audio::Wwise::BankExtension && !AZ::StringFunc::Equal(fileName.Native(), Audio::Wwise::InitBank)) { - m_audioSystemImpl->CreateControl(SControlDef(fileName, eWCT_WWISE_SOUND_BANK, isLocalized, nullptr, subPath)); + m_audioSystemImpl->CreateControl( + SControlDef(AZStd::string{ fileName.Native() }, eWCT_WWISE_SOUND_BANK, isLocalized, nullptr, subPath)); } } } @@ -103,14 +96,14 @@ namespace AudioControls if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(filePath.c_str())) { - LoadControlsInFolder(filePath); + LoadControlsInFolder(filePath.Native()); } else { // Open the file, read into an xmlDoc, and call LoadControls with the root xml node... AZ_TracePrintf("AudioWwiseLoader", "Loading Xml from '%s'", filePath.c_str()); - Audio::ScopedXmlLoader xmlFileLoader(filePath); + Audio::ScopedXmlLoader xmlFileLoader(filePath.Native()); if (!xmlFileLoader.HasError()) { LoadControl(xmlFileLoader.GetRootNode()); diff --git a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h index cc1e35028c..0bfaa6640c 100644 --- a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h +++ b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace AudioControls { @@ -39,4 +40,7 @@ namespace AudioControls using FilepathSet = AZStd::set; + using XmlAllocator = AZ::rapidxml::memory_pool<>; + inline static XmlAllocator s_xmlAllocator; + } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h b/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h index 5196e2f0bc..5a9c773a32 100644 --- a/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h +++ b/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h @@ -12,12 +12,10 @@ #include #include #include +#include #include -#include -#include - namespace AudioControls { class IAudioSystemEditor; @@ -117,14 +115,14 @@ namespace AudioControls //! @param node XML node where the connection is defined. //! @param atlControlType The type of the ATL control you are connecting to. //! @return A pointer to the newly created connection. - virtual TConnectionPtr CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType) = 0; + virtual TConnectionPtr CreateConnectionFromXMLNode(AZ::rapidxml::xml_node* node, EACEControlType atlControlType) = 0; //! When serializing connections between controls this function will be called once per connection to serialize its properties. //! This function should be in sync with CreateConnectionToControl as whatever it's written here will have to be read there. //! @param connection Connection to serialize. //! @param atlControlType Type of the ATL control that has this connection. //! @return XML node with the connection serialized. - virtual XmlNodeRef CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) = 0; + virtual AZ::rapidxml::xml_node* CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) = 0; //! Whenever a connection is removed from an ATL control this function should be called. //! To keep the system informed of which controls have been connected and which ones haven't. diff --git a/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h b/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h index dae411fd00..45997b1262 100644 --- a/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h +++ b/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h @@ -47,6 +47,7 @@ namespace Audio static constexpr const char* ATLInternalNameAttribute = "atl_internal_name"; static constexpr const char* ATLTypeAttribute = "atl_type"; static constexpr const char* ATLConfigGroupAttribute = "atl_config_group_name"; + static constexpr const char* ATLPathAttribute = "path"; static constexpr const char* ATLDataLoadType = "AutoLoad"; diff --git a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h index 5f071fef63..37952eaa1a 100644 --- a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h +++ b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include @@ -20,22 +21,26 @@ namespace Audio /*! * FindFilesInPath */ - static AZStd::vector FindFilesInPath(const AZStd::string_view folderPath, const char* filter) + static AZStd::vector FindFilesInPath(const AZStd::string_view folderPath, const char* filter) { - AZStd::vector foundFiles; + AZStd::vector foundFiles; AZ::IO::FileIOBase::FindFilesCallbackType findFilesCallback = [&foundFiles](const char* file) -> bool { - foundFiles.emplace_back(file); + foundFiles.emplace_back(AZ::IO::FixedMaxPath{ file }.LexicallyNormal()); return true; }; - auto fileIO = AZ::IO::FileIOBase::GetInstance(); - if (fileIO) + if (auto fileIO = AZ::IO::FileIOBase::GetInstance(); + fileIO != nullptr) { AZ::IO::Result result = fileIO->FindFiles(folderPath.data(), filter, findFilesCallback); + if (result == AZ::IO::ResultCode::Success) + { + return AZStd::move(foundFiles); + } } - return foundFiles; + return {}; } /*! diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index f7c856fb46..9335429fd4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -11,13 +11,11 @@ #include #include +#include #include #include -#include -#include - namespace AudioControls { class CATLControlsModel; @@ -25,15 +23,52 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// struct SRawConnectionData { - SRawConnectionData(XmlNodeRef node, bool isValid) - : m_xmlNode(node) - , m_isValid(isValid) - {} + SRawConnectionData(AZ::rapidxml::xml_node* node, bool isValid) + { + m_xmlNode = DeepCopyNode(node); + m_isValid = isValid; + } - XmlNodeRef m_xmlNode; + AZ::rapidxml::xml_node* m_xmlNode{ nullptr }; // indicates if the connection is valid for the currently loaded middleware - bool m_isValid; + bool m_isValid{ false }; + + // Rapid XML provides a 'copy_node' utility that will copy an entire node tree, + // but it only copies pointers of any strings in the node names and values. + // This causes problems with storing raw xml nodes as this class does because strings + // will be pointing into the memory pool of an xml document that has gone out of scope. + // This function is a rewritten version of 'copy_node' that does the deep copy of strings + // into the new destination tree. + static AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) + { + AZ::rapidxml::xml_node* destNode = nullptr; + if (srcNode) + { + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + destNode = xmlAlloc.allocate_node(srcNode->type()); + + destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size()); + destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size()); + + for (AZ::rapidxml::xml_node* child = srcNode->first_node(); child != nullptr; child = child->next_sibling()) + { + destNode->append_node(DeepCopyNode(child)); + } + + for (AZ::rapidxml::xml_attribute* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute()) + { + destNode->append_attribute(xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(attr->name(), attr->name_size()), + xmlAlloc.allocate_string(attr->value(), attr->value_size()), + attr->name_size(), + attr->value_size() + )); + } + } + + return destNode; + } }; using TXmlNodeList = AZStd::vector; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp index b352534510..d19cfe7adb 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp @@ -10,21 +10,31 @@ #include #include +#include + +#include + #include #include #include #include #include -#include -#include + + #include #include #include #include + + +#include +#include #include -#include #include +#include + + #include #include #include @@ -318,19 +328,24 @@ namespace AudioControls // once we can listen to delete messages from Asset system, this can be changed to an EBus handler. const char* controlsPath = nullptr; Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); - AZStd::string sControlsPath(Path::GetEditingGameDataFolder()); - AZ::StringFunc::Path::Join(sControlsPath.c_str(), controlsPath, sControlsPath); - Audio::SAudioManagerRequestData oParseGlobalRequestData(sControlsPath.c_str(), Audio::eADS_GLOBAL); + + AZ::IO::FixedMaxPath controlsFolder{ controlsPath }; + + Audio::SAudioManagerRequestData oParseGlobalRequestData(controlsFolder.c_str(), Audio::eADS_GLOBAL); oConfigDataRequest.pData = &oParseGlobalRequestData; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oConfigDataRequest); // parse the AudioSystem level-specific config data - AZStd::string levelName{ GetIEditor()->GetLevelName().toUtf8().data() }; - AZ::StringFunc::Path::Join(sControlsPath.c_str(), "levels", sControlsPath); - AZ::StringFunc::Path::Join(sControlsPath.c_str(), levelName.c_str(), sControlsPath); - Audio::SAudioManagerRequestData oParseLevelRequestData(sControlsPath.c_str(), Audio::eADS_LEVEL_SPECIFIC); - oConfigDataRequest.pData = &oParseLevelRequestData; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oConfigDataRequest); + AZStd::string levelName; + AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); + if (!levelName.empty() && levelName != "Untitled") + { + controlsFolder /= "levels"; + controlsFolder /= levelName; + Audio::SAudioManagerRequestData oParseLevelRequestData(controlsFolder.c_str(), Audio::eADS_LEVEL_SPECIFIC); + oConfigDataRequest.pData = &oParseLevelRequestData; + Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oConfigDataRequest); + } // inform the middleware specific plugin that the data has been saved // to disk (in case it needs to update something) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index c247abf855..e0eba868d6 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -11,26 +11,21 @@ #include #include +#include #include #include #include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include #include -using namespace PathUtil; - namespace AudioControls { //-------------------------------------------------------------------------------------------// @@ -91,100 +86,81 @@ namespace AudioControls { const CUndoSuspend suspendUndo; - // Get the partial path (relative under asset root) where the controls live. + // Get the relative path (under asset root) where the controls live. const char* controlsPath = nullptr; Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); // Get the full path up to asset root. - AZStd::string controlsFullPath(Path::GetEditingGameDataFolder()); - AZ::StringFunc::Path::Join(controlsFullPath.c_str(), controlsPath, controlsFullPath); + AZ::IO::FixedMaxPath controlsFullPath = AZ::Utils::GetProjectPath(); + controlsFullPath /= controlsPath; // load the global controls - LoadAllLibrariesInFolder(controlsFullPath, ""); + LoadAllLibrariesInFolder(controlsFullPath.Native(), ""); - // load the level specific controls - auto cryPak = gEnv->pCryPak; + AZ::IO::FixedMaxPath searchPath = controlsFullPath / LoaderStrings::LevelsSubFolder; - AZStd::string searchMask; - AZ::StringFunc::Path::Join(controlsFullPath.c_str(), LoaderStrings::LevelsSubFolder, searchMask); - AZ::StringFunc::Path::Join(searchMask.c_str(), "*", searchMask, true, false); - AZ::IO::ArchiveFileIterator handle = cryPak->FindFirst(searchMask.c_str()); - if (handle) + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*"); + + for (const auto& file : foundFiles) { - do + if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(file.c_str())) { - if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory) + AZStd::string levelName{ file.Filename().Native() }; + LoadAllLibrariesInFolder(controlsFullPath.Native(), levelName); + + if (!m_atlControlsModel->ScopeExists(levelName)) { - AZStd::string_view name = handle.m_filename; - if (name != "." && name != "..") - { - LoadAllLibrariesInFolder(controlsFullPath, name); - if (!m_atlControlsModel->ScopeExists(name)) - { - // if the control doesn't exist it - // means it is not a real level in the - // project so it is flagged as LocalOnly - m_atlControlsModel->AddScope(name, true); - } - } + // If the scope doesn't exist it means it is not a real + // level in the project so it's flagged as LocalOnly + m_atlControlsModel->AddScope(levelName, true); } } - while (handle = cryPak->FindNext(handle)); - cryPak->FindClose(handle); } + CreateDefaultControls(); } //-------------------------------------------------------------------------------------------// void CAudioControlsLoader::LoadAllLibrariesInFolder(const AZStd::string_view folderPath, const AZStd::string_view level) { - AZStd::string path(folderPath); - if (path.back() != AZ_CORRECT_FILESYSTEM_SEPARATOR) - { - path.append(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); - } + AZ::IO::FixedMaxPath searchPath{ folderPath }; if (!level.empty()) { - path.append(LoaderStrings::LevelsSubFolder); - path.append(GetSlash()); - path.append(level); - path.append(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); + searchPath /= LoaderStrings::LevelsSubFolder; + searchPath /= level; } - AZStd::string searchPath = path + "*.xml"; - auto cryPak = gEnv->pCryPak; - AZ::IO::ArchiveFileIterator handle = cryPak->FindFirst(searchPath.c_str()); - if (handle) + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*.xml"); + + for (auto& file : foundFiles) { - do + Audio::ScopedXmlLoader xmlLoader(file.Native()); + if (xmlLoader.HasError()) { - AZStd::string filename = path + AZStd::string{ static_cast(handle.m_filename) }; - AZ::StringFunc::Path::Normalize(filename); - XmlNodeRef root = GetISystem()->LoadXmlFromFile(filename.c_str()); - if (root) + AZ_Warning("AudioControlsLoader", false, "Unable to load the xml file '%s'", file.c_str()); + continue; + } + + auto xmlRootNode = xmlLoader.GetRootNode(); + if (xmlRootNode && azstricmp(xmlRootNode->name(), Audio::ATLXmlTags::RootNodeTag) == 0) + { + AZ::IO::PathView fileName = file.Filename(); + + AZStd::to_lower(file.Native().begin(), file.Native().end()); + m_loadedFilenames.insert(file.c_str()); + + if (auto nameAttr = xmlRootNode->first_attribute(Audio::ATLXmlTags::ATLNameAttribute, 0, false); nameAttr != nullptr) { - AZStd::string tag = root->getTag(); - if (tag == Audio::ATLXmlTags::RootNodeTag) - { - AZStd::to_lower(filename.begin(), filename.end()); - m_loadedFilenames.insert(filename.c_str()); - AZStd::string file = static_cast(handle.m_filename); - if (root->haveAttr(Audio::ATLXmlTags::ATLNameAttribute)) - { - file = root->getAttr(Audio::ATLXmlTags::ATLNameAttribute); - } - AZ::StringFunc::Path::StripExtension(file); - LoadControlsLibrary(root, folderPath, level, file); - } + fileName = nameAttr->value(); } else { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "(Audio Controls Editor) Failed parsing ATL Library '%s'", filename.c_str()); + fileName = fileName.Stem(); } - } while (handle = cryPak->FindNext(handle)); - cryPak->FindClose(handle); + LoadControlsLibrary(xmlRootNode, folderPath, level, fileName.Native()); + } } } @@ -233,74 +209,93 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsLoader::LoadControlsLibrary(XmlNodeRef rootNode, [[maybe_unused]] const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName) + void CAudioControlsLoader::LoadControlsLibrary( + const AZ::rapidxml::xml_node* rootNode, + [[maybe_unused]] const AZStd::string_view filePath, + const AZStd::string_view level, + const AZStd::string_view fileName) { QStandardItem* rootFolderItem = AddUniqueFolderPath(m_layoutModel->invisibleRootItem(), QString(fileName.data())); if (rootFolderItem && rootNode) { - const int numControlTypes = rootNode->getChildCount(); - for (int i = 0; i < numControlTypes; ++i) + auto controlTypeNode = rootNode->first_node(); // e.g. "AudioTriggers", "AudioRtpcs", etc + while (controlTypeNode) { - XmlNodeRef node = rootNode->getChild(i); - const int numControls = node->getChildCount(); - for (int j = 0; j < numControls; ++j) + auto controlNode = controlTypeNode->first_node(); // e.g. "ATLTrigger", "ATLRtpc", etc + while (controlNode) { - LoadControl(node->getChild(j), rootFolderItem, level); + LoadControl(controlNode, rootFolderItem, level); + controlNode = controlNode->next_sibling(); } + controlTypeNode = controlTypeNode->next_sibling(); } } } //-------------------------------------------------------------------------------------------// - CATLControl* CAudioControlsLoader::LoadControl(XmlNodeRef node, QStandardItem* folderItem, const AZStd::string_view scope) + CATLControl* CAudioControlsLoader::LoadControl(AZ::rapidxml::xml_node* node, QStandardItem* folderItem, const AZStd::string_view scope) { CATLControl* control = nullptr; - if (node) + + AZStd::string controlPath; + if (auto controlPathAttr = node->first_attribute("path", 0, false); + controlPathAttr != nullptr) { - QStandardItem* parentItem = AddUniqueFolderPath(folderItem, QString(node->getAttr(LoaderStrings::PathAttribute))); - if (parentItem) + controlPath = controlPathAttr->value(); + } + + QStandardItem* parentItem = AddUniqueFolderPath(folderItem, QString(controlPath.c_str())); + if (parentItem) + { + AZStd::string name; + if (auto nameAttr = node->first_attribute(Audio::ATLXmlTags::ATLNameAttribute, 0, false); + nameAttr != nullptr) { - const AZStd::string name = node->getAttr(Audio::ATLXmlTags::ATLNameAttribute); - const EACEControlType controlType = TagToType(node->getTag()); + name = nameAttr->value(); + } - control = m_atlControlsModel->CreateControl(name, controlType); - if (control) + const EACEControlType controlType = TagToType(node->name()); + + control = m_atlControlsModel->CreateControl(name, controlType); + if (control) + { + QStandardItem* item = new QAudioControlItem(QString(control->GetName().c_str()), control); + if (item) { - QStandardItem* item = new QAudioControlItem(QString(control->GetName().c_str()), control); - if (item) - { - parentItem->appendRow(item); - } - - switch (controlType) - { - case eACET_SWITCH: - { - const int numStates = node->getChildCount(); - for (int i = 0; i < numStates; ++i) - { - CATLControl* stateControl = LoadControl(node->getChild(i), item, scope); - if (stateControl) - { - stateControl->SetParent(control); - control->AddChild(stateControl); - } - } - break; - } - case eACET_PRELOAD: - { - LoadPreloadConnections(node, control); - break; - } - default: - { - LoadConnections(node, control); - break; - } - } - control->SetScope(scope); + parentItem->appendRow(item); } + + switch (controlType) + { + case eACET_SWITCH: + { + auto switchStateNode = node->first_node(); + while (switchStateNode) + { + CATLControl* stateControl = LoadControl(switchStateNode, item, scope); + if (stateControl) + { + stateControl->SetParent(control); + control->AddChild(stateControl); + } + + switchStateNode = switchStateNode->next_sibling(); + } + break; + } + case eACET_PRELOAD: + { + LoadPreloadConnections(node, control); + break; + } + default: + { + LoadConnections(node, control); + break; + } + } + + control->SetScope(scope); } } @@ -310,44 +305,37 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// void CAudioControlsLoader::LoadScopes() { - AZStd::string levelsFolderPath; - AZ::StringFunc::Path::Join(Path::GetEditingGameDataFolder().c_str(), LoaderStrings::LevelsSubFolder, levelsFolderPath); - LoadScopesImpl(levelsFolderPath); + AZ::IO::FixedMaxPath levelsFolderPath = AZ::Utils::GetProjectPath(); + levelsFolderPath /= "Levels"; + LoadScopesImpl(levelsFolderPath.Native()); } //-------------------------------------------------------------------------------------------// void CAudioControlsLoader::LoadScopesImpl(const AZStd::string_view levelsFolder) { - AZStd::string search; - AZ::StringFunc::Path::Join(levelsFolder.data(), "*", search, true, false); - auto cryPak = gEnv->pCryPak; - AZ::IO::ArchiveFileIterator handle = cryPak->FindFirst(search.c_str()); - if (handle) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ::IO::FixedMaxPath searchPath{ levelsFolder }; + + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*"); + for (auto& file : foundFiles) { - do + AZ::IO::PathView filePath{ file }; + AZ::IO::PathView fileName = filePath.Filename(); + if (fileIO->IsDirectory(filePath.Native().data())) { - AZStd::string name = static_cast(handle.m_filename); - if (name != "." && name != ".." && !name.empty()) + LoadScopesImpl((searchPath / fileName).Native()); + } + else + { + AZ::IO::PathView fileExt = filePath.Extension(); + if (fileExt == ".ly" || fileExt == ".cry" || fileExt == ".prefab") { - if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory) - { - AZ::StringFunc::Path::Join(levelsFolder.data(), name.c_str(), search); - LoadScopesImpl(search); - } - else - { - AZStd::string extension; - AZ::StringFunc::Path::GetExtension(name.c_str(), extension, false); - if (extension.compare("cry") == 0 || extension.compare("ly") == 0) - { - AZ::StringFunc::Path::StripExtension(name); - m_atlControlsModel->AddScope(name); - } - } + AZ::IO::PathView fileStem = filePath.Stem(); + // May need to verify that .prefabs are the actual "level" prefab + // i.e. that it matches levels//.prefab + m_atlControlsModel->AddScope(fileStem.Native()); } } - while (handle = cryPak->FindNext(handle)); - cryPak->FindClose(handle); } } @@ -475,100 +463,80 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsLoader::LoadConnections(XmlNodeRef rootNode, CATLControl* control) + void CAudioControlsLoader::LoadConnections(AZ::rapidxml::xml_node* rootNode, CATLControl* control) { - if (!rootNode || !control) + if (control && rootNode && m_audioSystemImpl) { - return; - } - - const int numChildren = rootNode->getChildCount(); - for (int i = 0; i < numChildren; ++i) - { - XmlNodeRef node = rootNode->getChild(i); - const AZStd::string tag = node->getTag(); - if (m_audioSystemImpl) + auto childNode = rootNode->first_node(); + while (childNode) { - TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(node, control->GetType()); + TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(childNode, control->GetType()); if (connection) { control->AddConnection(connection); } - control->m_connectionNodes.push_back(SRawConnectionData(node, connection != nullptr)); + + control->m_connectionNodes.push_back(SRawConnectionData(childNode, connection != nullptr)); + + childNode = childNode->next_sibling(); } } } //-------------------------------------------------------------------------------------------// - void CAudioControlsLoader::LoadPreloadConnections(XmlNodeRef node, CATLControl* control) + void CAudioControlsLoader::LoadPreloadConnections(AZ::rapidxml::xml_node* node, CATLControl* control) { - if (!node || !control) + if (!control || !node || !m_audioSystemImpl) { return; } - AZStd::string type = node->getAttr(Audio::ATLXmlTags::ATLTypeAttribute); - if (type.compare(Audio::ATLXmlTags::ATLDataLoadType) == 0) + AZStd::string type; + if (auto typeAttr = node->first_attribute(Audio::ATLXmlTags::ATLTypeAttribute, 0, false); + typeAttr != nullptr) { - control->SetAutoLoad(true); - } - else - { - control->SetAutoLoad(false); + type = typeAttr->value(); } - // Legacy Preload XML parsing... - // Read all the platform definitions for this control - XmlNodeRef platformsGroupNode = node->findChild(Audio::ATLXmlTags::ATLPlatformsTag); - if (platformsGroupNode) + control->SetAutoLoad(type == Audio::ATLXmlTags::ATLDataLoadType); + + auto platformGroupNode = node->first_node(Audio::ATLXmlTags::ATLPlatformsTag, 0, false); + if (platformGroupNode) { + // Legacy preload parsing... // Don't parse the platform groups xml chunk anymore. // Read the connection information for all connected preloads... - const int numChildren = node->getChildCount(); - for (int i = 0; i < numChildren; ++i) + auto configGroupNode = node->first_node(Audio::ATLXmlTags::ATLConfigGroupTag, 0, false); + while (configGroupNode) { - XmlNodeRef groupNode = node->getChild(i); - const AZStd::string tag = groupNode->getTag(); - if (tag.compare(Audio::ATLXmlTags::ATLConfigGroupTag) != 0) - { - continue; - } - - const AZStd::string groupName = groupNode->getAttr(Audio::ATLXmlTags::ATLNameAttribute); - const int numConnections = groupNode->getChildCount(); - for (int j = 0; j < numConnections; ++j) - { - XmlNodeRef connectionNode = groupNode->getChild(j); - if (connectionNode && m_audioSystemImpl) - { - TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); - if (connection) - { - control->AddConnection(connection); - } - control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); - } - } - } - } - else - { - // New Preload XML parsing... - const int numChildren = node->getChildCount(); - for (int i = 0; i < numChildren; ++i) - { - XmlNodeRef connectionNode = node->getChild(i); - if (connectionNode && m_audioSystemImpl) + auto connectionNode = configGroupNode->first_node(); + while (connectionNode) { TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); if (connection) { control->AddConnection(connection); } - control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + connectionNode = connectionNode->next_sibling(); } + configGroupNode = configGroupNode->next_sibling(); + } + } + else + { + // New format preload parsing... + auto connectionNode = node->first_node(); + while (connectionNode) + { + TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); + if (connection) + { + control->AddConnection(connection); + } + control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + connectionNode = connectionNode->next_sibling(); } } } @@ -586,15 +554,28 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, const AZStd::string& switchName, const AZStd::string& stateName) + CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, [[maybe_unused]] const AZStd::string& switchName, const AZStd::string& stateName) { CATLControl* childControl = m_atlControlsModel->CreateControl(stateName, eACET_SWITCH_STATE, parentControl); - XmlNodeRef requestNode = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::ATLSwitchRequestTag); - requestNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, switchName.c_str()); - XmlNodeRef valueNode = requestNode->createNode(Audio::ATLXmlTags::ATLValueTag); - valueNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, stateName.c_str()); - requestNode->addChild(valueNode); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + AZ::rapidxml::xml_node* requestNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLSwitchRequestTag)); + + AZ::rapidxml::xml_attribute* switchNameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(switchName.c_str())); + + requestNode->append_attribute(switchNameAttr); + + AZ::rapidxml::xml_node* valueNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLValueTag)); + + AZ::rapidxml::xml_attribute* stateNameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(stateName.c_str())); + + valueNode->append_attribute(stateNameAttr); + + requestNode->append_node(valueNode); childControl->m_connectionNodes.push_back(SRawConnectionData(requestNode, false)); return childControl; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h index bee55289e3..290327b946 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h @@ -10,12 +10,11 @@ #pragma once #include +#include #include #include -#include - #include class QStandardItemModel; @@ -38,11 +37,11 @@ namespace AudioControls private: void LoadAllLibrariesInFolder(const AZStd::string_view folderPath, const AZStd::string_view level); - void LoadControlsLibrary(XmlNodeRef rootNode, const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName); - CATLControl* LoadControl(XmlNodeRef node, QStandardItem* folderItem, const AZStd::string_view scope); + void LoadControlsLibrary(const AZ::rapidxml::xml_node* rootNode, const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName); + CATLControl* LoadControl(AZ::rapidxml::xml_node* node, QStandardItem* folderItem, const AZStd::string_view scope); - void LoadPreloadConnections(XmlNodeRef node, CATLControl* control); - void LoadConnections(XmlNodeRef rootNode, CATLControl* control); + void LoadPreloadConnections(AZ::rapidxml::xml_node* node, CATLControl* control); + void LoadConnections(AZ::rapidxml::xml_node* rootNode, CATLControl* control); void CreateDefaultControls(); QStandardItem* AddControl(CATLControl* control, QStandardItem* folderItem); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index bb7409e179..80f05804f1 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -9,29 +9,28 @@ #include +#include +#include #include #include +#include +#include #include #include -#include #include #include #include + #include #include #include -#include -#include -#include #include #include #include -using namespace PathUtil; - namespace AudioControls { namespace WriterStrings @@ -80,6 +79,18 @@ namespace AudioControls index = index.sibling(++i, 0); } + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + AZStd::for_each( + m_foundLibraryPaths.begin(), m_foundLibraryPaths.end(), + [fileIO](AZStd::string& libraryPath) -> void + { + AZStd::optional newLength = fileIO->ConvertToAlias(libraryPath.data(), libraryPath.size()); + if (newLength) + { + libraryPath.resize_no_construct(*newLength); + } + AZStd::to_lower(libraryPath.begin(), libraryPath.end()); + }); // Delete libraries that don't exist anymore from disk FilepathSet librariesToDelete; @@ -103,7 +114,10 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// void CAudioControlsWriter::WriteLibrary(const AZStd::string_view libraryName, QModelIndex root) { - if (root.isValid()) + const char* controlsPath = nullptr; + Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); + + if (root.isValid() && controlsPath) { TLibraryStorage library; int i = 0; @@ -114,68 +128,63 @@ namespace AudioControls child = root.model()->index(++i, 0, root); } - const char* controlsPath = nullptr; - Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); - for (auto& libraryPair : library) { - AZStd::string libraryPath; + AZ::IO::FixedMaxPath libraryPath{ controlsPath }; const AZStd::string& scope = libraryPair.first; if (scope.empty()) { // no scope, file at the root level - libraryPath.append(controlsPath); - AZ::StringFunc::Path::Join(libraryPath.c_str(), libraryName.data(), libraryPath); - libraryPath.append(WriterStrings::LibraryExtension); + libraryPath /= libraryName; + libraryPath.ReplaceExtension(WriterStrings::LibraryExtension); } else { // with scope, inside level folder - libraryPath.append(controlsPath); - libraryPath.append(WriterStrings::LevelsSubFolder); - AZ::StringFunc::Path::Join(libraryPath.c_str(), scope.c_str(), libraryPath); - AZ::StringFunc::Path::Join(libraryPath.c_str(), libraryName.data(), libraryPath); - libraryPath.append(WriterStrings::LibraryExtension); + libraryPath /= AZ::IO::FixedMaxPath{ WriterStrings::LevelsSubFolder } / scope / libraryName; + libraryPath.ReplaceExtension(WriterStrings::LibraryExtension); } - // should be able to change this back to GamePathToFullPath once a path normalization bug has been fixed: - AZStd::string fullFilePath; - AZ::StringFunc::Path::Join(Path::GetEditingGameDataFolder().c_str(), libraryPath.c_str(), fullFilePath); - AZStd::to_lower(fullFilePath.begin(), fullFilePath.end()); + AZ::IO::FixedMaxPath fullFilePath = AZ::Utils::GetProjectPath(); + fullFilePath /= libraryPath; m_foundLibraryPaths.insert(fullFilePath.c_str()); const SLibraryScope& libScope = libraryPair.second; if (libScope.m_isDirty) { - XmlNodeRef fileNode = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::RootNodeTag); - fileNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, libraryName.data()); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + AZ::rapidxml::xml_node* fileNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::RootNodeTag)); + + AZ::rapidxml::xml_attribute* nameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(libraryName.data())); + + fileNode->append_attribute(nameAttr); for (int ii = 0; ii < eACET_NUM_TYPES; ++ii) { - if (ii != eACET_SWITCH_STATE) // switch_states are written inside the switches + if (libScope.m_nodes[ii] && libScope.m_nodes[ii]->first_node() != nullptr) { - if (libScope.m_nodes[ii]->getChildCount() > 0) - { - fileNode->addChild(libScope.m_nodes[ii]); - } + fileNode->append_node(libScope.m_nodes[ii]); } } - if (QFileInfo::exists(fullFilePath.c_str())) + if (auto fileInfo = QFileInfo(fullFilePath.c_str()); + fileInfo.exists()) { - const DWORD fileAttributes = GetFileAttributes(fullFilePath.c_str()); - if (fileAttributes & FILE_ATTRIBUTE_READONLY) + if (!fileInfo.isWritable()) { - // file is read-only - CheckOutFile(fullFilePath); + // file exists and is read-only + CheckOutFile(fullFilePath.Native()); } - fileNode->saveToFile(fullFilePath.c_str()); + + [[maybe_unused]] bool writeOk = WriteXmlToFile(fullFilePath.Native(), fileNode); } else { - // save the file, CheckOutFile will add it, since it's new - fileNode->saveToFile(fullFilePath.c_str()); - CheckOutFile(fullFilePath); + // since it's a new file, save the file first, CheckOutFile will add it + [[maybe_unused]] bool writeOk = WriteXmlToFile(fullFilePath.Native(), fileNode); + CheckOutFile(fullFilePath.Native()); } } } @@ -249,14 +258,63 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::WriteControlToXml(XmlNodeRef node, CATLControl* control, const AZStd::string_view path) + bool CAudioControlsWriter::WriteXmlToFile(const AZStd::string_view filepath, AZ::rapidxml::xml_node* rootNode) { + if (!rootNode) + { + return false; + } + + using namespace AZ::IO; + AZStd::string docString; + ByteContainerStream stringStream(&docString); + + AZ::rapidxml::xml_document xmlDoc; + xmlDoc.append_node(rootNode); + + RapidXMLStreamWriter streamWriter(&stringStream); + AZ::rapidxml::print(streamWriter.Iterator(), xmlDoc); + streamWriter.FlushCache(); + + constexpr int openMode = + (SystemFile::SF_OPEN_WRITE_ONLY | SystemFile::SF_OPEN_CREATE | SystemFile::SF_OPEN_CREATE_PATH); + + if (SystemFile fileOut; + fileOut.Open(filepath.data(), openMode)) + { + auto bytesWritten = fileOut.Write(docString.data(), docString.size()); + return (bytesWritten == docString.size()); + } + return false; + } + + //-------------------------------------------------------------------------------------------// + void CAudioControlsWriter::WriteControlToXml(AZ::rapidxml::xml_node* node, CATLControl* control, const AZStd::string_view path) + { + if (!node || !control) + { + return; + } + + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + const EACEControlType type = control->GetType(); - XmlNodeRef childNode = node->createNode(TypeToTag(type).data()); - childNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, control->GetName().c_str()); + AZStd::string_view typeName = TypeToTag(type); + + AZ::rapidxml::xml_node* childNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(typeName.data())); + + AZ::rapidxml::xml_attribute* nameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(control->GetName().c_str())); + + childNode->append_attribute(nameAttr); + if (!path.empty()) { - childNode->setAttr("path", path.data()); + AZ::rapidxml::xml_attribute* pathAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLPathAttribute), xmlAlloc.allocate_string(path.data())); + + childNode->append_attribute(pathAttr); } if (type == eACET_SWITCH) @@ -271,7 +329,11 @@ namespace AudioControls { if (control->IsAutoLoad()) { - childNode->setAttr(Audio::ATLXmlTags::ATLTypeAttribute, Audio::ATLXmlTags::ATLDataLoadType); + AZ::rapidxml::xml_attribute* loadAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLTypeAttribute), + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLDataLoadType)); + + childNode->append_attribute(loadAttr); } // New Preloads XML... @@ -282,38 +344,39 @@ namespace AudioControls WriteConnectionsToXml(childNode, control); } - node->addChild(childNode); + node->append_node(childNode); } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::WriteConnectionsToXml(XmlNodeRef node, CATLControl* control) + void CAudioControlsWriter::WriteConnectionsToXml(AZ::rapidxml::xml_node* node, CATLControl* control) { - if (control && m_audioSystemImpl) + if (node && control && m_audioSystemImpl) { TXmlNodeList otherNodes = control->m_connectionNodes; - auto end = AZStd::remove_if(otherNodes.begin(), otherNodes.end(), - [](const SRawConnectionData& node) + auto end = AZStd::remove_if( + otherNodes.begin(), otherNodes.end(), + [](const SRawConnectionData& connection) { - return node.m_isValid; + return connection.m_isValid; } ); otherNodes.erase(end, otherNodes.end()); for (auto& connectionNode : otherNodes) { - node->addChild(connectionNode.m_xmlNode); + node->append_node(SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode)); } const size_t size = control->ConnectionCount(); for (size_t i = 0; i < size; ++i) { - TConnectionPtr connection = control->GetConnectionAt(i); - if (connection) + if (TConnectionPtr connection = control->GetConnectionAt(i); + connection != nullptr) { - XmlNodeRef childNode = m_audioSystemImpl->CreateXMLNodeFromConnection(connection, control->GetType()); - if (childNode) + if (auto childNode = m_audioSystemImpl->CreateXMLNodeFromConnection(connection, control->GetType()); + childNode != nullptr) { - node->addChild(childNode); + node->append_node(childNode); control->m_connectionNodes.push_back(SRawConnectionData(childNode, true)); } } @@ -322,24 +385,24 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::CheckOutFile(const AZStd::string& filepath) + void CAudioControlsWriter::CheckOutFile(const AZStd::string_view filepath) { IEditor* editor = GetIEditor(); IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->CheckoutFile(filepath.c_str(), nullptr); + fileUtil->CheckoutFile(filepath.data(), nullptr); } } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::DeleteLibraryFile(const AZStd::string& filepath) + void CAudioControlsWriter::DeleteLibraryFile(const AZStd::string_view filepath) { IEditor* editor = GetIEditor(); IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->DeleteFromSourceControl(filepath.c_str(), nullptr); + fileUtil->DeleteFromSourceControl(filepath.data(), nullptr); } } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h index 9e3978b94b..1414f6725d 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h @@ -16,10 +16,9 @@ #include #include #include -#include + #include -#include class QStandardItemModel; @@ -33,15 +32,16 @@ namespace AudioControls { SLibraryScope() { - m_nodes[eACET_TRIGGER] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::TriggersNodeTag); - m_nodes[eACET_RTPC] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::RtpcsNodeTag); - m_nodes[eACET_SWITCH] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::SwitchesNodeTag); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + m_nodes[eACET_TRIGGER] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::TriggersNodeTag); + m_nodes[eACET_RTPC] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::RtpcsNodeTag); + m_nodes[eACET_SWITCH] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::SwitchesNodeTag); m_nodes[eACET_SWITCH_STATE] = nullptr; - m_nodes[eACET_ENVIRONMENT] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::EnvironmentsNodeTag); - m_nodes[eACET_PRELOAD] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::PreloadsNodeTag); + m_nodes[eACET_ENVIRONMENT] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::EnvironmentsNodeTag); + m_nodes[eACET_PRELOAD] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::PreloadsNodeTag); } - XmlNodeRef m_nodes[eACET_NUM_TYPES]; + AZ::rapidxml::xml_node* m_nodes[eACET_NUM_TYPES]; bool m_isDirty = false; }; @@ -56,12 +56,13 @@ namespace AudioControls private: void WriteLibrary(const AZStd::string_view libraryName, QModelIndex root); void WriteItem(QModelIndex index, const AZStd::string& path, TLibraryStorage& library, bool isParentModified); - void WriteControlToXml(XmlNodeRef node, CATLControl* control, const AZStd::string_view path); - void WriteConnectionsToXml(XmlNodeRef node, CATLControl* control); + void WriteControlToXml(AZ::rapidxml::xml_node* node, CATLControl* control, const AZStd::string_view path); + void WriteConnectionsToXml(AZ::rapidxml::xml_node* node, CATLControl* control); bool IsItemModified(QModelIndex index); - void CheckOutFile(const AZStd::string& filepath); - void DeleteLibraryFile(const AZStd::string& filepath); + bool WriteXmlToFile(const AZStd::string_view filepath, AZ::rapidxml::xml_node* rootNode); + void CheckOutFile(const AZStd::string_view filepath); + void DeleteLibraryFile(const AZStd::string_view filepath); CATLControlsModel* m_atlModel; QStandardItemModel* m_layoutModel; diff --git a/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h b/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h index ce77125443..4d322a49d9 100644 --- a/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h +++ b/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h @@ -31,7 +31,7 @@ namespace AudioControls iconFile = ":/Icons/Switch_Icon.svg"; break; case AudioControls::eACET_SWITCH_STATE: - iconFile = ":/Icons/Property_Icon.svg"; + iconFile = ":/Icons/Property_Icon.png"; break; case AudioControls::eACET_ENVIRONMENT: iconFile = ":/Icons/Environment_Icon.svg"; @@ -41,7 +41,7 @@ namespace AudioControls break; default: // should make a "default"/empty icon... - iconFile = ":/Icons/RTPC_Icon.svg"; + iconFile = ":/Icons/Unassigned.svg"; } QIcon icon(iconFile); diff --git a/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp b/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp index ca9cb214e2..7010012e87 100644 --- a/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp @@ -1005,14 +1005,14 @@ namespace Audio AZStd::string searchPath; AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath); - AZStd::vector foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); + auto foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); for (const auto& file : foundFiles) { AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(file.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", file.c_str()); g_audioLogger.Log(eALT_ALWAYS, "Loading Audio Controls Library: '%s'", file.c_str()); - Audio::ScopedXmlLoader xmlFileLoader(file); + Audio::ScopedXmlLoader xmlFileLoader(file.Native()); if (xmlFileLoader.HasError()) { continue; @@ -1053,14 +1053,14 @@ namespace Audio AZStd::string searchPath; AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath); - AZStd::vector foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); + auto foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); for (const auto& file : foundFiles) { AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(file.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", file.c_str()); g_audioLogger.Log(eALT_ALWAYS, "Loading Audio Preloads Library: '%s'", file.c_str()); - Audio::ScopedXmlLoader xmlFileLoader(file); + Audio::ScopedXmlLoader xmlFileLoader(file.Native()); if (xmlFileLoader.HasError()) { continue; From 976272d9cf9d2e22dceb6eea011d2f993854d320 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 22 Jul 2021 21:06:04 -0500 Subject: [PATCH 2/8] Cleans up more legacy code from ACE Rewrote some code to replace gEnv->pCryPak and ISystem usage. One place was grabbing a Camera view from ISystem, replaced with simple identity matrix. Cleaned up include headers. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Code/Source/Editor/ATLControlsModel.cpp | 1 - .../Code/Source/Editor/ATLControlsPanel.cpp | 5 --- .../Code/Source/Editor/AudioControl.cpp | 1 - .../Editor/AudioControlsEditorPlugin.cpp | 12 ++---- .../Editor/AudioControlsEditorWindow.cpp | 39 ++++++------------- .../Source/Editor/AudioControlsEditorWindow.h | 1 - .../Source/Editor/AudioControlsLoader.cpp | 1 - .../Source/Editor/AudioResourceSelectors.cpp | 1 - .../Code/Source/Editor/AudioSystemPanel.cpp | 3 -- .../Source/Editor/ImplementationManager.cpp | 2 - .../Source/Editor/ImplementationManager.h | 3 -- .../Code/Source/Editor/InspectorPanel.cpp | 1 - .../Code/Source/Editor/QConnectionsWidget.cpp | 1 - 13 files changed, 14 insertions(+), 57 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp index 4fbc2a72c4..7bcce84ea4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp @@ -13,7 +13,6 @@ #include #include #include -#include namespace AudioControls { diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp index 6503e83545..48a16e54e6 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp @@ -16,13 +16,8 @@ #include #include #include -#include -#include -#include -#include #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp index 40c1cd3c79..c0a8fb8dde 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include namespace AudioControls diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index b8761c4d62..973cb836a0 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -14,9 +14,6 @@ #include #include -#include -#include -#include #include #include @@ -28,7 +25,6 @@ using namespace AudioControls; -using namespace PathUtil; CATLControlsModel CAudioControlsEditorPlugin::ms_ATLModel; QATLTreeModel CAudioControlsEditorPlugin::ms_layoutModel; @@ -152,20 +148,18 @@ void CAudioControlsEditorPlugin::ExecuteTrigger(const AZStd::string_view sTrigge Audio::AudioSystemRequestBus::BroadcastResult(ms_nAudioTriggerID, &Audio::AudioSystemRequestBus::Events::GetAudioTriggerID, sTriggerName.data()); if (ms_nAudioTriggerID != INVALID_AUDIO_CONTROL_ID) { - const CCamera& camera = GetIEditor()->GetSystem()->GetViewCamera(); - Audio::SAudioRequest request; request.nFlags = Audio::eARF_PRIORITY_NORMAL; - const AZ::Matrix3x4 cameraMatrix = LYTransformToAZMatrix3x4(camera.GetMatrix()); + const AZ::Matrix3x4 listenerTxfm = AZ::Matrix3x4::CreateIdentity(); - Audio::SAudioListenerRequestData requestData(cameraMatrix); + Audio::SAudioListenerRequestData requestData(listenerTxfm); requestData.oNewPosition.NormalizeForwardVec(); requestData.oNewPosition.NormalizeUpVec(); request.pData = &requestData; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, request); - ms_pIAudioProxy->SetPosition(cameraMatrix); + ms_pIAudioProxy->SetPosition(listenerTxfm); ms_pIAudioProxy->ExecuteTrigger(ms_nAudioTriggerID); } } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp index d19cfe7adb..54a8ce616d 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp @@ -9,7 +9,6 @@ #include -#include #include #include @@ -18,22 +17,14 @@ #include #include #include +#include #include - - -#include #include #include #include - - -#include -#include -#include -#include - #include +#include #include #include @@ -41,6 +32,7 @@ #include #include + void InitACEResources() { Q_INIT_RESOURCE(AudioControlsEditorUI); @@ -116,25 +108,16 @@ namespace AudioControls { m_fileSystemWatcher.addPath(folder.data()); - AZStd::string search; - AZ::StringFunc::Path::Join(folder.data(), "*", search, true, false); - auto pCryPak = gEnv->pCryPak; - AZ::IO::ArchiveFileIterator handle = pCryPak->FindFirst(search.c_str()); - if (handle) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + auto foundFiles = Audio::FindFilesInPath(folder, "*"); + for (auto& file : foundFiles) { - do + if (fileIO->IsDirectory(file.c_str())) { - AZStd::string sName = static_cast(handle.m_filename); - if (!sName.empty() && sName[0] != '.') - { - if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory) - { - AZ::StringFunc::Path::Join(folder.data(), sName.c_str(), sName); - StartWatchingFolder(sName); - } - } - } while (handle = pCryPak->FindNext(handle)); - pCryPak->FindClose(handle); + AZ::IO::FixedMaxPath resolvedPath; + fileIO->ReplaceAlias(resolvedPath, file); + StartWatchingFolder(file.Native()); + } } } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h index bfa08828ac..761f0c1a8e 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h @@ -12,7 +12,6 @@ #if !defined(Q_MOC_RUN) #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index e0eba868d6..8714fd21da 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp index 90c50ac741..f0c9ebe3d1 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp index 99f615d1fe..deccfc1364 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp @@ -12,10 +12,7 @@ #include #include #include -#include -#include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp index fc146a109d..bee5c1dd51 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp @@ -14,8 +14,6 @@ #include #include #include -#include -#include //-----------------------------------------------------------------------------------------------// diff --git a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h index dd6d61d310..70a99fcc0e 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h +++ b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h @@ -10,9 +10,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include -#include - #include #endif diff --git a/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp b/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp index a9e2046348..318aea211c 100644 --- a/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp index 8a6fece85c..b65e690f1b 100644 --- a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include From 91dcbe7fed88592507dcf9f41e2102ee0990b8d8 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 22 Jul 2021 21:17:41 -0500 Subject: [PATCH 3/8] Fixes minor mistake in helper function desc Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/AudioControl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index 9335429fd4..494b0465bd 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -34,11 +34,11 @@ namespace AudioControls // indicates if the connection is valid for the currently loaded middleware bool m_isValid{ false }; - // Rapid XML provides a 'copy_node' utility that will copy an entire node tree, + // Rapid XML provides a 'clone_node' utility that will copy an entire node tree, // but it only copies pointers of any strings in the node names and values. // This causes problems with storing raw xml nodes as this class does because strings // will be pointing into the memory pool of an xml document that has gone out of scope. - // This function is a rewritten version of 'copy_node' that does the deep copy of strings + // This function is a rewritten version of 'clone_node' that does the deep copy of strings // into the new destination tree. static AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { From d385f6ed99170d0c50c9f8e0543d4abee648c03f Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 23 Jul 2021 11:29:47 -0500 Subject: [PATCH 4/8] Addresses feedback from PR review Change DeepCopyNode utility to return a unique_ptr, fix up some string/path usages to avoid temporaries, etc. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Code/Source/Editor/AudioWwiseLoader.cpp | 4 +--- .../Code/Include/Editor/ACETypes.h | 2 +- .../Code/Include/Engine/AudioFileUtils.h | 2 +- .../Code/Source/Editor/AudioControl.cpp | 2 +- .../Code/Source/Editor/AudioControl.h | 12 +++++----- .../Source/Editor/AudioControlsWriter.cpp | 22 +++++++------------ 6 files changed, 18 insertions(+), 26 deletions(-) diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp index 1a3ff121f8..616a30994c 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include @@ -77,7 +75,7 @@ namespace AudioControls isLocalizedLoaded = true; } } - else if (fileName.Extension() == Audio::Wwise::BankExtension && !AZ::StringFunc::Equal(fileName.Native(), Audio::Wwise::InitBank)) + else if (fileName.Extension() == Audio::Wwise::BankExtension && fileName != Audio::Wwise::InitBank) { m_audioSystemImpl->CreateControl( SControlDef(AZStd::string{ fileName.Native() }, eWCT_WWISE_SOUND_BANK, isLocalized, nullptr, subPath)); diff --git a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h index 0bfaa6640c..1ff6112056 100644 --- a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h +++ b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h @@ -41,6 +41,6 @@ namespace AudioControls using FilepathSet = AZStd::set; using XmlAllocator = AZ::rapidxml::memory_pool<>; - inline static XmlAllocator s_xmlAllocator; + inline XmlAllocator s_xmlAllocator; } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h index 37952eaa1a..65122662b1 100644 --- a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h +++ b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h @@ -26,7 +26,7 @@ namespace Audio AZStd::vector foundFiles; AZ::IO::FileIOBase::FindFilesCallbackType findFilesCallback = [&foundFiles](const char* file) -> bool { - foundFiles.emplace_back(AZ::IO::FixedMaxPath{ file }.LexicallyNormal()); + foundFiles.emplace_back(AZ::IO::PathView{ file }.LexicallyNormal()); return true; }; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp index c0a8fb8dde..ce268022a8 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp @@ -345,7 +345,7 @@ namespace AudioControls { for (auto& connectionNode : m_connectionNodes) { - if (TConnectionPtr connection = audioSystemImpl->CreateConnectionFromXMLNode(connectionNode.m_xmlNode, m_type)) + if (TConnectionPtr connection = audioSystemImpl->CreateConnectionFromXMLNode(connectionNode.m_xmlNode.get(), m_type)) { AddConnection(connection); connectionNode.m_isValid = true; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index 494b0465bd..c53f4aa831 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -25,11 +25,11 @@ namespace AudioControls { SRawConnectionData(AZ::rapidxml::xml_node* node, bool isValid) { - m_xmlNode = DeepCopyNode(node); + m_xmlNode = AZStd::move(DeepCopyNode(node)); m_isValid = isValid; } - AZ::rapidxml::xml_node* m_xmlNode{ nullptr }; + AZStd::unique_ptr> m_xmlNode{}; // indicates if the connection is valid for the currently loaded middleware bool m_isValid{ false }; @@ -40,20 +40,20 @@ namespace AudioControls // will be pointing into the memory pool of an xml document that has gone out of scope. // This function is a rewritten version of 'clone_node' that does the deep copy of strings // into the new destination tree. - static AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) + [[nodiscard]] static AZStd::unique_ptr> DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { - AZ::rapidxml::xml_node* destNode = nullptr; + AZStd::unique_ptr> destNode{}; if (srcNode) { XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); - destNode = xmlAlloc.allocate_node(srcNode->type()); + destNode.reset(xmlAlloc.allocate_node(srcNode->type())); destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size()); destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size()); for (AZ::rapidxml::xml_node* child = srcNode->first_node(); child != nullptr; child = child->next_sibling()) { - destNode->append_node(DeepCopyNode(child)); + destNode->append_node(DeepCopyNode(child).release()); } for (AZ::rapidxml::xml_attribute* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute()) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index 80f05804f1..973da60c90 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -352,19 +352,13 @@ namespace AudioControls { if (node && control && m_audioSystemImpl) { - TXmlNodeList otherNodes = control->m_connectionNodes; - auto end = AZStd::remove_if( - otherNodes.begin(), otherNodes.end(), - [](const SRawConnectionData& connection) - { - return connection.m_isValid; - } - ); - otherNodes.erase(end, otherNodes.end()); - - for (auto& connectionNode : otherNodes) + for (auto& connectionNode : control->m_connectionNodes) { - node->append_node(SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode)); + if (!connectionNode.m_isValid) + { + auto nodeCopy = SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode.get()); + node->append_node(nodeCopy.release()); + } } const size_t size = control->ConnectionCount(); @@ -391,7 +385,7 @@ namespace AudioControls IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->CheckoutFile(filepath.data(), nullptr); + fileUtil->CheckoutFile(AZ::IO::FixedMaxPath{ filepath }.c_str(), nullptr); } } @@ -402,7 +396,7 @@ namespace AudioControls IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->DeleteFromSourceControl(filepath.data(), nullptr); + fileUtil->DeleteFromSourceControl(AZ::IO::FixedMaxPath{ filepath }.c_str(), nullptr); } } From ce2fc6c1e6cfe31ac6ed2264c0930574c3305ebe Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 23 Jul 2021 11:43:03 -0500 Subject: [PATCH 5/8] Addresses one more piece of feedback Updates a call to ConvertToAlias to use PathView. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index 973da60c90..91f9aa5138 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -84,10 +84,10 @@ namespace AudioControls m_foundLibraryPaths.begin(), m_foundLibraryPaths.end(), [fileIO](AZStd::string& libraryPath) -> void { - AZStd::optional newLength = fileIO->ConvertToAlias(libraryPath.data(), libraryPath.size()); - if (newLength) + if (auto newPathOpt = fileIO->ConvertToAlias(AZ::IO::PathView{ libraryPath }); + newPathOpt.has_value()) { - libraryPath.resize_no_construct(*newLength); + libraryPath = newPathOpt.value().Native(); } AZStd::to_lower(libraryPath.begin(), libraryPath.end()); }); From dff425764ab95c58c62307c293f08db7a1f32dc2 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 23 Jul 2021 12:17:34 -0500 Subject: [PATCH 6/8] Fix some minor things Removes unnecessary things added during development. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/AudioControl.h | 2 +- Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index c53f4aa831..37e67c815c 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -42,7 +42,7 @@ namespace AudioControls // into the new destination tree. [[nodiscard]] static AZStd::unique_ptr> DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { - AZStd::unique_ptr> destNode{}; + AZStd::unique_ptr> destNode; if (srcNode) { XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index 8714fd21da..220cd32b5c 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -553,7 +553,7 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, [[maybe_unused]] const AZStd::string& switchName, const AZStd::string& stateName) + CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, const AZStd::string& switchName, const AZStd::string& stateName) { CATLControl* childControl = m_atlControlsModel->CreateControl(stateName, eACET_SWITCH_STATE, parentControl); From 41ebcefe667252c30549e6b2ac81b3c12b4d21e0 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 26 Jul 2021 15:23:31 -0500 Subject: [PATCH 7/8] Restoring include headers that were removed These removals caused build errors on non-unity builds. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp | 1 + Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp index 7bcce84ea4..4fbc2a72c4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace AudioControls { diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h index 761f0c1a8e..bfa08828ac 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h @@ -12,6 +12,7 @@ #if !defined(Q_MOC_RUN) #include #include +#include #include #include From ed6dbb48f4b292d17518c478ece4212922a070cc Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 26 Jul 2021 18:19:07 -0500 Subject: [PATCH 8/8] Fixes failing tests and linux compile error Replaced a 'uint32' with AZ::u32 to fix a linux compile error that likely came about after cleaning up includes. Rewrites a failing unit test after the code under test was updated from CryPak to AZ::IO. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Code/Editor/Util/UndoUtil.h | 2 +- .../Code/Tests/AudioSystemEditorTest.cpp | 111 +++++++++++------- 2 files changed, 69 insertions(+), 44 deletions(-) diff --git a/Code/Editor/Util/UndoUtil.h b/Code/Editor/Util/UndoUtil.h index f352eb317b..e825647f6b 100644 --- a/Code/Editor/Util/UndoUtil.h +++ b/Code/Editor/Util/UndoUtil.h @@ -31,7 +31,7 @@ public: static void Record(IUndoObject* undo); private: - static const uint32 scDescSize = 256; + static const AZ::u32 scDescSize = 256; char m_description[scDescSize]; bool m_bCancelled; bool m_bStartedRecord; diff --git a/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp b/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp index a486e24326..0debe128e2 100644 --- a/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp +++ b/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp @@ -10,54 +10,45 @@ #include #include +#include + #include #include -#include -#include -#include - using ::testing::NiceMock; using namespace AudioControls; namespace CustomMocks { - class AudioControlsEditorTest_CryPakMock - : public CryPakMock + class AudioControlsEditorTest_FileIOMock + : public AZ::IO::MockFileIOBase { public: - AZ_TEST_CLASS_ALLOCATOR(AudioControlsEditorTest_CryPakMock) + AZ_TEST_CLASS_ALLOCATOR(AudioControlsEditorTest_FileIOMock); - AudioControlsEditorTest_CryPakMock(const char* levelName) - : m_levelName(levelName) - {} - - AZ::IO::ArchiveFileIterator FindFirst([[maybe_unused]] AZStd::string_view dir, AZ::IO::IArchive::EFileSearchType) override + AudioControlsEditorTest_FileIOMock() { - AZ::IO::FileDesc fileDesc; - fileDesc.nSize = sizeof(AZ::IO::FileDesc); - // Add a filename and file description reference to the TestFindData map to make sure the file iterator is valid - m_findData = new TestFindData(); - m_findData->m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ static_cast(m_findData.get()), m_levelName, fileDesc }); - return m_findData->Fetch(); } - AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator iter) override + bool IsDirectory([[maybe_unused]] const char* path) override { - return ++iter; + return false; + } + + AZ::IO::Result FindFiles( + [[maybe_unused]] const char* path, + [[maybe_unused]] const char* filter, + AZ::IO::FileIOBase::FindFilesCallbackType callback) override + { + if (callback) + { + callback(m_levelName.c_str()); + return AZ::IO::ResultCode::Success; + } + return AZ::IO::ResultCode::Error; } - // public: for easy resetting... AZStd::string m_levelName; - - // Add an inherited FindData class to control the adding of a mapfile which indicates that a FileIterator is valid - struct TestFindData - : AZ::IO::FindData - { - using AZ::IO::FindData::m_fileSet; - }; - - AZStd::intrusive_ptr m_findData; }; } // namespace CustomMocks @@ -75,10 +66,6 @@ protected: void SetupEnvironment() override { m_allocatorScope.ActivateAllocators(); - - m_stubEnv.pCryPak = nullptr; - m_stubEnv.pFileIO = nullptr; - gEnv = &m_stubEnv; } void TeardownEnvironment() override @@ -87,30 +74,68 @@ protected: } private: - AZ::AllocatorScope m_allocatorScope; - SSystemGlobalEnvironment m_stubEnv; + AZ::AllocatorScope m_allocatorScope; }; AZ_UNIT_TEST_HOOK(new AudioControlsEditorTestEnvironment); -TEST(AudioControlsEditorTest, AudioControlsLoader_LoadScopes_ScopesAreAdded) +class AudioControlsEditorTest + : public ::testing::Test { - ASSERT_TRUE(gEnv != nullptr); - ASSERT_TRUE(gEnv->pCryPak == nullptr); +public: + void SetUp() override + { + // Store and remove the existing fileIO... + m_prevFileIO = AZ::IO::FileIOBase::GetInstance(); + if (m_prevFileIO) + { + AZ::IO::FileIOBase::SetInstance(nullptr); + } - NiceMock m_cryPakMock("ly_extension.ly"); - gEnv->pCryPak = &m_cryPakMock; + // Replace with a new FileIO Mock... + m_fileIO = AZStd::make_unique(); + AZ::IO::FileIOBase::SetInstance(m_fileIO.get()); + } + void TearDown() override + { + // Destroy our LocalFileIO... + m_fileIO.reset(); + + // Replace the old fileIO (set instance to null first)... + AZ::IO::FileIOBase::SetInstance(nullptr); + if (m_prevFileIO) + { + AZ::IO::FileIOBase::SetInstance(m_prevFileIO); + m_prevFileIO = nullptr; + } + } + +protected: + AZ::IO::FileIOBase* m_prevFileIO = nullptr; + AZStd::unique_ptr m_fileIO; +}; + +TEST_F(AudioControlsEditorTest, AudioControlsLoader_LoadScopes_ScopesAreAdded) +{ CATLControlsModel atlModel; CAudioControlsLoader loader(&atlModel, nullptr, nullptr); + m_fileIO->m_levelName = "ly_extension.ly"; loader.LoadScopes(); EXPECT_TRUE(atlModel.ScopeExists("ly_extension")); - m_cryPakMock.m_levelName = "cry_extension.cry"; + m_fileIO->m_levelName = "cry_extension.cry"; loader.LoadScopes(); EXPECT_TRUE(atlModel.ScopeExists("cry_extension")); + m_fileIO->m_levelName = "prefab_extension.prefab"; + loader.LoadScopes(); + EXPECT_TRUE(atlModel.ScopeExists("prefab_extension")); + + m_fileIO->m_levelName = "spawnable_extension.spawnable"; + loader.LoadScopes(); + EXPECT_FALSE(atlModel.ScopeExists("spawnable_extension")); + atlModel.ClearScopes(); - gEnv->pCryPak = nullptr; }