Merge pull request #2382 from aws-lumberyard-dev/audio/amzn-phist/RemoveLegacyXml
Replaces usage of legacy XML apis with RapidXml
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -19,10 +19,7 @@
|
||||
#include <AudioSystemControl_wwise.h>
|
||||
#include <Common_wwise.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <Util/PathUtil.h>
|
||||
#include <QDir>
|
||||
|
||||
void InitWwiseResources()
|
||||
{
|
||||
@@ -217,28 +214,34 @@ namespace AudioControls
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
TConnectionPtr CAudioSystemEditor_wwise::CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType)
|
||||
TConnectionPtr CAudioSystemEditor_wwise::CreateConnectionFromXMLNode(AZ::rapidxml::xml_node<char>* 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<CStateToRtpcConnection>(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<char>* 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<const CRtpcConnection> rtpcConnection = AZStd::static_pointer_cast<const CRtpcConnection>(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<const CStateToRtpcConnection> stateConnection = AZStd::static_pointer_cast<const CStateToRtpcConnection>(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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<char>* node, EACEControlType atlControlType) override;
|
||||
AZ::rapidxml::xml_node<char>* 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;
|
||||
|
||||
@@ -9,20 +9,12 @@
|
||||
|
||||
#include <AudioWwiseLoader.h>
|
||||
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
#include <AudioSystemEditor_wwise.h>
|
||||
#include <AudioFileUtils.h>
|
||||
#include <Config_wwise.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <Util/PathUtil.h>
|
||||
|
||||
using namespace PathUtil;
|
||||
|
||||
namespace AudioControls
|
||||
{
|
||||
@@ -68,8 +60,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 +70,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 && fileName != 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 +94,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());
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
|
||||
namespace AudioControls
|
||||
{
|
||||
@@ -39,4 +40,7 @@ namespace AudioControls
|
||||
|
||||
using FilepathSet = AZStd::set<AZStd::string>;
|
||||
|
||||
using XmlAllocator = AZ::rapidxml::memory_pool<>;
|
||||
inline XmlAllocator s_xmlAllocator;
|
||||
|
||||
} // namespace AudioControls
|
||||
|
||||
@@ -12,12 +12,10 @@
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
|
||||
#include <ACETypes.h>
|
||||
|
||||
#include <platform.h>
|
||||
#include <IXml.h>
|
||||
|
||||
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<char>* 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<char>* 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.
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
@@ -20,22 +21,26 @@ namespace Audio
|
||||
/*!
|
||||
* FindFilesInPath
|
||||
*/
|
||||
static AZStd::vector<AZStd::string> FindFilesInPath(const AZStd::string_view folderPath, const char* filter)
|
||||
static AZStd::vector<AZ::IO::FixedMaxPath> FindFilesInPath(const AZStd::string_view folderPath, const char* filter)
|
||||
{
|
||||
AZStd::vector<AZStd::string> foundFiles;
|
||||
AZStd::vector<AZ::IO::FixedMaxPath> foundFiles;
|
||||
AZ::IO::FileIOBase::FindFilesCallbackType findFilesCallback = [&foundFiles](const char* file) -> bool
|
||||
{
|
||||
foundFiles.emplace_back(file);
|
||||
foundFiles.emplace_back(AZ::IO::PathView{ 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 {};
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -16,13 +16,8 @@
|
||||
#include <ATLControlsModel.h>
|
||||
#include <AudioControl.h>
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <Cry_Camera.h>
|
||||
#include <IAudioSystem.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
#include <IEditor.h>
|
||||
#include <QAudioControlEditorIcons.h>
|
||||
|
||||
#include <QWidgetAction>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <AudioControlsEditorUndo.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IEditor.h>
|
||||
#include <ImplementationManager.h>
|
||||
|
||||
namespace AudioControls
|
||||
@@ -346,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;
|
||||
|
||||
@@ -11,13 +11,11 @@
|
||||
|
||||
#include <ACETypes.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
|
||||
#include <IAudioConnection.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <IXml.h>
|
||||
|
||||
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<char>* node, bool isValid)
|
||||
{
|
||||
m_xmlNode = AZStd::move(DeepCopyNode(node));
|
||||
m_isValid = isValid;
|
||||
}
|
||||
|
||||
XmlNodeRef m_xmlNode;
|
||||
AZStd::unique_ptr<AZ::rapidxml::xml_node<char>> m_xmlNode{};
|
||||
|
||||
// indicates if the connection is valid for the currently loaded middleware
|
||||
bool m_isValid;
|
||||
bool m_isValid{ false };
|
||||
|
||||
// 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 'clone_node' that does the deep copy of strings
|
||||
// into the new destination tree.
|
||||
[[nodiscard]] static AZStd::unique_ptr<AZ::rapidxml::xml_node<char>> DeepCopyNode(AZ::rapidxml::xml_node<char>* srcNode)
|
||||
{
|
||||
AZStd::unique_ptr<AZ::rapidxml::xml_node<char>> destNode;
|
||||
if (srcNode)
|
||||
{
|
||||
XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator);
|
||||
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<char>* child = srcNode->first_node(); child != nullptr; child = child->next_sibling())
|
||||
{
|
||||
destNode->append_node(DeepCopyNode(child).release());
|
||||
}
|
||||
|
||||
for (AZ::rapidxml::xml_attribute<char>* 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<SRawConnectionData>;
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
#include <AudioControlsLoader.h>
|
||||
#include <AudioControlsWriter.h>
|
||||
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <Cry_Camera.h>
|
||||
#include <Include/IResourceSelectorHost.h>
|
||||
|
||||
#include <IAudioSystem.h>
|
||||
@@ -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<Audio::eALRT_SET_POSITION> requestData(cameraMatrix);
|
||||
Audio::SAudioListenerRequestData<Audio::eALRT_SET_POSITION> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,21 +9,22 @@
|
||||
|
||||
#include <AudioControlsEditorWindow.h>
|
||||
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include <ATLControlsModel.h>
|
||||
#include <ATLControlsPanel.h>
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <AudioControlsEditorUndo.h>
|
||||
#include <AudioFileUtils.h>
|
||||
#include <AudioSystemPanel.h>
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <DockTitleBarWidget.h>
|
||||
#include <IAudioSystem.h>
|
||||
#include <ImplementationManager.h>
|
||||
#include <InspectorPanel.h>
|
||||
#include <ISystem.h>
|
||||
#include <QAudioControlEditorIcons.h>
|
||||
#include <Util/PathUtil.h>
|
||||
|
||||
#include <DockTitleBarWidget.h>
|
||||
|
||||
#include <QPaintEvent>
|
||||
#include <QPushButton>
|
||||
@@ -31,6 +32,7 @@
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
void InitACEResources()
|
||||
{
|
||||
Q_INIT_RESOURCE(AudioControlsEditorUI);
|
||||
@@ -106,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<AZStd::string_view>(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,19 +311,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<Audio::eAMRT_PARSE_CONTROLS_DATA> oParseGlobalRequestData(sControlsPath.c_str(), Audio::eADS_GLOBAL);
|
||||
|
||||
AZ::IO::FixedMaxPath controlsFolder{ controlsPath };
|
||||
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_PARSE_CONTROLS_DATA> 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<Audio::eAMRT_PARSE_CONTROLS_DATA> 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<Audio::eAMRT_PARSE_CONTROLS_DATA> 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)
|
||||
|
||||
@@ -10,27 +10,21 @@
|
||||
#include <AudioControlsLoader.h>
|
||||
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <ACEEnums.h>
|
||||
#include <ATLCommon.h>
|
||||
#include <ATLControlsModel.h>
|
||||
#include <AudioFileUtils.h>
|
||||
#include <IAudioSystem.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
#include <QAudioControlTreeWidget.h>
|
||||
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <IEditor.h>
|
||||
#include <ISystem.h>
|
||||
#include <StringUtils.h>
|
||||
#include <Util/PathUtil.h>
|
||||
#include <Util/UndoUtil.h>
|
||||
|
||||
#include <QStandardItem>
|
||||
|
||||
using namespace PathUtil;
|
||||
|
||||
namespace AudioControls
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
@@ -91,100 +85,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<AZStd::string_view>(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<AZStd::string_view>(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 +208,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<char>* 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<char>* 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 +304,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<AZStd::string_view>(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/<levelname>/<levelname>.prefab
|
||||
m_atlControlsModel->AddScope(fileStem.Native());
|
||||
}
|
||||
}
|
||||
while (handle = cryPak->FindNext(handle));
|
||||
cryPak->FindClose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,100 +462,80 @@ namespace AudioControls
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
void CAudioControlsLoader::LoadConnections(XmlNodeRef rootNode, CATLControl* control)
|
||||
void CAudioControlsLoader::LoadConnections(AZ::rapidxml::xml_node<char>* 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<char>* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -590,11 +557,24 @@ namespace AudioControls
|
||||
{
|
||||
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<char>* requestNode =
|
||||
xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLSwitchRequestTag));
|
||||
|
||||
AZ::rapidxml::xml_attribute<char>* switchNameAttr = xmlAlloc.allocate_attribute(
|
||||
xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(switchName.c_str()));
|
||||
|
||||
requestNode->append_attribute(switchNameAttr);
|
||||
|
||||
AZ::rapidxml::xml_node<char>* valueNode =
|
||||
xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLValueTag));
|
||||
|
||||
AZ::rapidxml::xml_attribute<char>* 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;
|
||||
|
||||
@@ -10,12 +10,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
|
||||
#include <ACETypes.h>
|
||||
#include <AudioControl.h>
|
||||
|
||||
#include <IXml.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
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<char>* rootNode, const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName);
|
||||
CATLControl* LoadControl(AZ::rapidxml::xml_node<char>* 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<char>* node, CATLControl* control);
|
||||
void LoadConnections(AZ::rapidxml::xml_node<char>* rootNode, CATLControl* control);
|
||||
|
||||
void CreateDefaultControls();
|
||||
QStandardItem* AddControl(CATLControl* control, QStandardItem* folderItem);
|
||||
|
||||
@@ -9,29 +9,28 @@
|
||||
|
||||
#include <AudioControlsWriter.h>
|
||||
|
||||
#include <AzCore/IO/ByteContainerStream.h>
|
||||
#include <AzCore/IO/TextStreamWriters.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzCore/XML/rapidxml_print.h>
|
||||
|
||||
#include <ACEEnums.h>
|
||||
#include <ATLControlsModel.h>
|
||||
#include <CryFile.h>
|
||||
#include <IAudioSystem.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
|
||||
#include <IEditor.h>
|
||||
#include <Include/IFileUtil.h>
|
||||
#include <Include/ISourceControl.h>
|
||||
#include <ISystem.h>
|
||||
#include <StringUtils.h>
|
||||
#include <Util/PathUtil.h>
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QStandardItemModel>
|
||||
#include <QFileInfo>
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
if (auto newPathOpt = fileIO->ConvertToAlias(AZ::IO::PathView{ libraryPath });
|
||||
newPathOpt.has_value())
|
||||
{
|
||||
libraryPath = newPathOpt.value().Native();
|
||||
}
|
||||
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<char>* fileNode =
|
||||
xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::RootNodeTag));
|
||||
|
||||
AZ::rapidxml::xml_attribute<char>* 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<char>* rootNode)
|
||||
{
|
||||
if (!rootNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using namespace AZ::IO;
|
||||
AZStd::string docString;
|
||||
ByteContainerStream stringStream(&docString);
|
||||
|
||||
AZ::rapidxml::xml_document<char> 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<char>* 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<char>* childNode =
|
||||
xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(typeName.data()));
|
||||
|
||||
AZ::rapidxml::xml_attribute<char>* 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<char>* 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<char>* 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,33 @@ 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<char>* 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)
|
||||
{
|
||||
return node.m_isValid;
|
||||
}
|
||||
);
|
||||
otherNodes.erase(end, otherNodes.end());
|
||||
|
||||
for (auto& connectionNode : otherNodes)
|
||||
for (auto& connectionNode : control->m_connectionNodes)
|
||||
{
|
||||
node->addChild(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();
|
||||
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 +379,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(AZ::IO::FixedMaxPath{ filepath }.c_str(), 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(AZ::IO::FixedMaxPath{ filepath }.c_str(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#include <ACETypes.h>
|
||||
#include <ATLCommon.h>
|
||||
#include <AudioControl.h>
|
||||
#include <ISystem.h>
|
||||
|
||||
#include <QModelIndex>
|
||||
|
||||
#include <IXml.h>
|
||||
|
||||
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<char>* 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<char>* node, CATLControl* control, const AZStd::string_view path);
|
||||
void WriteConnectionsToXml(AZ::rapidxml::xml_node<char>* 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<char>* rootNode);
|
||||
void CheckOutFile(const AZStd::string_view filepath);
|
||||
void DeleteLibraryFile(const AZStd::string_view filepath);
|
||||
|
||||
CATLControlsModel* m_atlModel;
|
||||
QStandardItemModel* m_layoutModel;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include <ATLControlsResourceDialog.h>
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <IEditor.h>
|
||||
#include <Include/IResourceSelectorHost.h>
|
||||
#include <QAudioControlEditorIcons.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
@@ -12,10 +12,7 @@
|
||||
#include <ATLControlsModel.h>
|
||||
#include <AudioControl.h>
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <CryFile.h>
|
||||
#include <CryPath.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
#include <IEditor.h>
|
||||
#include <QAudioControlEditorIcons.h>
|
||||
|
||||
#include <QWidgetAction>
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include <ATLControlsModel.h>
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
#include <IConsole.h>
|
||||
#include <IEditor.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------//
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/Module/DynamicModuleHandle.h>
|
||||
|
||||
#include <QObject>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <ACETypes.h>
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IEditor.h>
|
||||
#include <QAudioControlEditorIcons.h>
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <AudioControlsEditorPlugin.h>
|
||||
#include <IAudioSystemControl.h>
|
||||
#include <IAudioSystemEditor.h>
|
||||
#include <IEditor.h>
|
||||
#include <ImplementationManager.h>
|
||||
|
||||
#include <QDropEvent>
|
||||
|
||||
@@ -1005,14 +1005,14 @@ namespace Audio
|
||||
AZStd::string searchPath;
|
||||
AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath);
|
||||
|
||||
AZStd::vector<AZStd::string> 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<AZStd::string> 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;
|
||||
|
||||
@@ -10,54 +10,45 @@
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/AllocatorScope.h>
|
||||
|
||||
#include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
|
||||
|
||||
#include <AudioControlsLoader.h>
|
||||
#include <ATLControlsModel.h>
|
||||
|
||||
#include <platform.h>
|
||||
#include <ISystem.h>
|
||||
#include <Mocks/ICryPakMock.h>
|
||||
|
||||
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<AZ::IO::FindData*>(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<TestFindData> 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<AZ::OSAllocator, AZ::SystemAllocator, AZ::LegacyAllocator, CryStringAllocator> m_allocatorScope;
|
||||
SSystemGlobalEnvironment m_stubEnv;
|
||||
AZ::AllocatorScope<AZ::OSAllocator, AZ::SystemAllocator> 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<CustomMocks::AudioControlsEditorTest_CryPakMock> m_cryPakMock("ly_extension.ly");
|
||||
gEnv->pCryPak = &m_cryPakMock;
|
||||
// Replace with a new FileIO Mock...
|
||||
m_fileIO = AZStd::make_unique<CustomMocks::AudioControlsEditorTest_FileIOMock>();
|
||||
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<CustomMocks::AudioControlsEditorTest_FileIOMock> 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user