merging latest origin
This commit is contained in:
@@ -1454,32 +1454,48 @@ namespace AZ
|
||||
//=========================================================================
|
||||
void AssetManager::ReloadAssetFromData(const Asset<AssetData>& asset)
|
||||
{
|
||||
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
|
||||
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
|
||||
AZ_Assert(m_assets.find(asset.GetId()) != m_assets.end(), "Unable to reload asset %s because its not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(m_assets.find(asset.GetId()) == m_assets.end() || asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
|
||||
"New and old data types are mismatched!");
|
||||
bool shouldAssignAssetData = false;
|
||||
|
||||
auto found = m_assets.find(asset.GetId());
|
||||
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
|
||||
{
|
||||
return; // this will just lead to crashes down the line and the above asserts cover this.
|
||||
}
|
||||
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
|
||||
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
|
||||
AZ_Assert(
|
||||
m_assets.find(asset.GetId()) != m_assets.end(),
|
||||
"Unable to reload asset %s because it's not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(
|
||||
m_assets.find(asset.GetId()) == m_assets.end() ||
|
||||
asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
|
||||
"New and old data types are mismatched!");
|
||||
|
||||
AssetData* newData = asset.Get();
|
||||
|
||||
if (found->second != newData)
|
||||
{
|
||||
// Notify users that we are about to change asset
|
||||
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
|
||||
|
||||
// Resolve the asset handler and account for the new asset instance.
|
||||
auto found = m_assets.find(asset.GetId());
|
||||
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
|
||||
{
|
||||
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
|
||||
AZ_Assert(handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
|
||||
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
|
||||
return; // this will just lead to crashes down the line and the above asserts cover this.
|
||||
}
|
||||
|
||||
AssetData* newData = asset.Get();
|
||||
|
||||
if (found->second != newData)
|
||||
{
|
||||
// Notify users that we are about to change asset
|
||||
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
|
||||
|
||||
// Resolve the asset handler and account for the new asset instance.
|
||||
{
|
||||
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
|
||||
AZ_Assert(
|
||||
handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
|
||||
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
|
||||
}
|
||||
|
||||
shouldAssignAssetData = true;
|
||||
}
|
||||
}
|
||||
|
||||
// We specifically perform this outside of the m_assetMutex lock so that the lock isn't held at the point that
|
||||
// OnAssetReload is triggered inside of AssignAssetData. Otherwise, we open up a high potential for deadlocks.
|
||||
if (shouldAssignAssetData)
|
||||
{
|
||||
AssignAssetData(asset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <AzCore/Jobs/JobManagerComponent.h>
|
||||
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
|
||||
#include <AzCore/Memory/MemoryComponent.h>
|
||||
#include <AzCore/NativeUI/NativeUISystemComponent.h>
|
||||
#include <AzCore/Script/ScriptSystemComponent.h>
|
||||
#include <AzCore/Slice/SliceComponent.h>
|
||||
#include <AzCore/Slice/SliceSystemComponent.h>
|
||||
@@ -43,7 +42,6 @@ namespace AZ
|
||||
AssetManagerComponent::CreateDescriptor(),
|
||||
UserSettingsComponent::CreateDescriptor(),
|
||||
Debug::FrameProfilerComponent::CreateDescriptor(),
|
||||
NativeUI::NativeUISystemComponent::CreateDescriptor(),
|
||||
SliceComponent::CreateDescriptor(),
|
||||
SliceSystemComponent::CreateDescriptor(),
|
||||
SliceMetadataInfoComponent::CreateDescriptor(),
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <AzCore/Memory/AllocatorManager.h>
|
||||
#include <AzCore/Memory/MallocSchema.h>
|
||||
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
@@ -424,7 +426,7 @@ namespace AZ
|
||||
|
||||
// Now that the Allocators are initialized, the Command Line parameters can be parsed
|
||||
m_commandLine.Parse(m_argC, m_argV);
|
||||
ParseCommandLine(m_commandLine);
|
||||
SettingsRegistryMergeUtils::ParseCommandLine(m_commandLine);
|
||||
|
||||
// Create the settings registry and register it with the AZ interface system
|
||||
// This is done after the AppRoot has been calculated so that the Bootstrap.cfg
|
||||
@@ -527,10 +529,42 @@ namespace AZ
|
||||
DestroyAllocator();
|
||||
}
|
||||
|
||||
|
||||
void ReportBadEngineRoot()
|
||||
{
|
||||
AZStd::string errorMessage = {"Unable to determine a valid path to the engine.\n"
|
||||
"Check parameters such as --project-path and --engine-path and make sure they are valid.\n"};
|
||||
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
|
||||
{
|
||||
AZ::SettingsRegistryInterface::FixedValueString filePathErrorStr;
|
||||
if (registry->Get(filePathErrorStr, AZ::SettingsRegistryMergeUtils::FilePathKey_ErrorText); !filePathErrorStr.empty())
|
||||
{
|
||||
errorMessage += "Additional Info:\n";
|
||||
errorMessage += filePathErrorStr.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (auto nativeUI = AZ::Interface<AZ::NativeUI::NativeUIRequests>::Get(); nativeUI != nullptr)
|
||||
{
|
||||
nativeUI->DisplayOkDialog("O3DE Fatal Error", errorMessage.c_str(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("ComponentApplication", false, "O3DE Fatal Error: %s\n", errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Entity* ComponentApplication::Create(const Descriptor& descriptor, const StartupParameters& startupParameters)
|
||||
{
|
||||
AZ_Assert(!m_isStarted, "Component application already started!");
|
||||
|
||||
if (m_engineRoot.empty())
|
||||
{
|
||||
ReportBadEngineRoot();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_startupParameters = startupParameters;
|
||||
|
||||
m_descriptor = descriptor;
|
||||
@@ -871,46 +905,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentApplication::ParseCommandLine(const AZ::CommandLine& commandLine)
|
||||
{
|
||||
struct OptionKeyToRegsetKey
|
||||
{
|
||||
AZStd::string_view m_optionKey;
|
||||
AZStd::string m_regsetKey;
|
||||
};
|
||||
|
||||
// Provide overrides for the engine root, the project root and the project cache root
|
||||
AZStd::array commandOptions = {
|
||||
OptionKeyToRegsetKey{ "engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) },
|
||||
OptionKeyToRegsetKey{ "project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) },
|
||||
OptionKeyToRegsetKey{ "project-cache-path", AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) }
|
||||
};
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, commandOptions.size()> overrideArgs;
|
||||
|
||||
for (auto&& [optionKey, regsetKey] : commandOptions)
|
||||
{
|
||||
if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0)
|
||||
{
|
||||
// Use the last supplied command option value to override previous values
|
||||
auto overrideArg = AZStd::string::format(R"(--regset="%s=%s")", regsetKey.c_str(),
|
||||
commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str());
|
||||
overrideArgs.emplace_back(AZStd::move(overrideArg));
|
||||
}
|
||||
}
|
||||
|
||||
if (!overrideArgs.empty())
|
||||
{
|
||||
// Dump the input command line, add the additional option overrides
|
||||
// and Parse the new command line into the Component Application command line
|
||||
AZ::CommandLine::ParamContainer commandLineArgs;
|
||||
commandLine.Dump(commandLineArgs);
|
||||
commandLineArgs.insert(commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()),
|
||||
AZStd::make_move_iterator(overrideArgs.end()));
|
||||
m_commandLine.Parse(commandLineArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentApplication::MergeSettingsToRegistry(SettingsRegistryInterface& registry)
|
||||
{
|
||||
SettingsRegistryInterface::Specializations specializations;
|
||||
|
||||
@@ -332,9 +332,6 @@ namespace AZ
|
||||
/// Create the drillers
|
||||
void CreateDrillers();
|
||||
|
||||
/// Parse ComponentApplication specific command line arguments
|
||||
void ParseCommandLine(const AZ::CommandLine& commandLine);
|
||||
|
||||
virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
|
||||
|
||||
//! Sets the specializations that will be used when loading the Settings Registry. Extend this in derived
|
||||
|
||||
@@ -15,45 +15,49 @@
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
namespace NativeUI
|
||||
enum AssertAction
|
||||
{
|
||||
enum AssertAction
|
||||
{
|
||||
IGNORE_ASSERT = 0,
|
||||
IGNORE_ALL_ASSERTS,
|
||||
BREAK,
|
||||
NONE,
|
||||
};
|
||||
IGNORE_ASSERT = 0,
|
||||
IGNORE_ALL_ASSERTS,
|
||||
BREAK,
|
||||
NONE,
|
||||
};
|
||||
|
||||
class NativeUIRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
class NativeUIRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(NativeUIRequests, "{48361EE6-C1E7-4965-A13A-7425B2691817}");
|
||||
virtual ~NativeUIRequests() = default;
|
||||
|
||||
// Waits for user to select an option before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayBlockingDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, const AZStd::vector<AZStd::string>& /*options*/) const { return ""; };
|
||||
// Waits for user to select an option before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayBlockingDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, const AZStd::vector<AZStd::string>& /*options*/) const { return ""; };
|
||||
|
||||
// Waits for user to select an option ('Ok' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayOkDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
// Waits for user to select an option ('Ok' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayOkDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
|
||||
// Waits for user to select an option ('Yes', 'No' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayYesNoDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
// Waits for user to select an option ('Yes', 'No' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayYesNoDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
|
||||
// Displays an assert dialog box
|
||||
// Returns the action selected by the user
|
||||
virtual AssertAction DisplayAssertDialog(const AZStd::string& /*message*/) const { return AssertAction::NONE; };
|
||||
};
|
||||
// Displays an assert dialog box
|
||||
// Returns the action selected by the user
|
||||
virtual AssertAction DisplayAssertDialog(const AZStd::string& /*message*/) const { return AssertAction::NONE; };
|
||||
};
|
||||
|
||||
using NativeUIRequestBus = AZ::EBus<NativeUIRequests>;
|
||||
}
|
||||
}
|
||||
class NativeUIEBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
};
|
||||
|
||||
using NativeUIRequestBus = AZ::EBus<NativeUIRequests, NativeUIEBusTraits>;
|
||||
} // namespace AZ::NativeUI
|
||||
|
||||
@@ -15,50 +15,19 @@
|
||||
|
||||
#include <AzCore/NativeUI/NativeUISystemComponent.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
using namespace AZ::NativeUI;
|
||||
|
||||
void NativeUISystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
NativeUISystem::NativeUISystem()
|
||||
{
|
||||
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<NativeUISystemComponent, AZ::Component>()
|
||||
->Version(0)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* ec = serialize->GetEditContext())
|
||||
{
|
||||
ec->Class<NativeUISystemComponent>("NativeUI", "Adds basic support for native (platform specific) UI dialog boxes")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
NativeUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
NativeUISystem::~NativeUISystem()
|
||||
{
|
||||
provided.push_back(AZ_CRC("NativeUIService", 0x8ec25f87));
|
||||
NativeUIRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("NativeUIService", 0x8ec25f87));
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
(void)required;
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
(void)dependent;
|
||||
}
|
||||
|
||||
AssertAction NativeUISystemComponent::DisplayAssertDialog(const AZStd::string& message) const
|
||||
AssertAction NativeUISystem::DisplayAssertDialog(const AZStd::string& message) const
|
||||
{
|
||||
static const char* buttonNames[3] = { "Ignore", "Ignore All", "Break" };
|
||||
AZStd::vector<AZStd::string> options;
|
||||
@@ -80,7 +49,7 @@ namespace AZ
|
||||
return AssertAction::NONE;
|
||||
}
|
||||
|
||||
AZStd::string NativeUISystemComponent::DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
AZStd::string NativeUISystem::DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
{
|
||||
AZStd::vector<AZStd::string> options;
|
||||
|
||||
@@ -93,7 +62,7 @@ namespace AZ
|
||||
return DisplayBlockingDialog(title, message, options);
|
||||
}
|
||||
|
||||
AZStd::string NativeUISystemComponent::DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
AZStd::string NativeUISystem::DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
{
|
||||
AZStd::vector<AZStd::string> options;
|
||||
|
||||
@@ -106,18 +75,4 @@ namespace AZ
|
||||
|
||||
return DisplayBlockingDialog(title, message, options);
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::Activate()
|
||||
{
|
||||
NativeUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::Deactivate()
|
||||
{
|
||||
NativeUIRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
}
|
||||
} // namespace AZ::NativeUI
|
||||
|
||||
@@ -15,40 +15,24 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
namespace NativeUI
|
||||
class NativeUISystem
|
||||
: public NativeUIRequestBus::Handler
|
||||
{
|
||||
class NativeUISystemComponent
|
||||
: public AZ::Component
|
||||
, public NativeUIRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(NativeUISystemComponent, "{E996C058-4AFE-4C8C-816F-98D864D8576D}");
|
||||
public:
|
||||
AZ_RTTI(NativeUISystem, "{FF534B2C-11BE-4DEA-A5B7-A4FA96FE1EDE}", NativeUIRequests);
|
||||
AZ_CLASS_ALLOCATOR(NativeUISystem, AZ::OSAllocator, 0);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
NativeUISystem();
|
||||
~NativeUISystem() override;
|
||||
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// NativeUIRequestBus interface implementation
|
||||
AZStd::string DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const override;
|
||||
AZStd::string DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AZStd::string DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AssertAction DisplayAssertDialog(const AZStd::string& message) const override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component interface implementation
|
||||
void Init() override;
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// NativeUIRequestBus interface implementation
|
||||
AZStd::string DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const override;
|
||||
AZStd::string DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AZStd::string DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AssertAction DisplayAssertDialog(const AZStd::string& message) const override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
} // namespace AZ::NativeUI
|
||||
|
||||
@@ -699,6 +699,10 @@ Data::AssetHandler::LoadResult ScriptSystemComponent::LoadAssetData(
|
||||
script->m_scriptBuffer.resize(scriptDataLength);
|
||||
stream->Read(scriptDataLength, script->m_scriptBuffer.data());
|
||||
|
||||
// Clear cached references in the event of a successful load. This function has to be queued on
|
||||
// AssetBus where NotifyAssetReloaded is also queued, to ensure its execution before NotifyAssetReloaded
|
||||
Data::AssetBus::QueueFunction(&ScriptSystemComponent::ClearAssetReferences, this, asset.GetId());
|
||||
|
||||
return Data::AssetHandler::LoadResult::LoadComplete;
|
||||
}
|
||||
|
||||
@@ -853,7 +857,7 @@ const char* ScriptSystemComponent::GetGroup() const
|
||||
|
||||
const char* AZ::ScriptSystemComponent::GetBrowserIcon() const
|
||||
{
|
||||
return "Editor/Icons/Components/LuaScript.svg";
|
||||
return "Icons/Components/LuaScript.svg";
|
||||
}
|
||||
|
||||
AZ::Uuid AZ::ScriptSystemComponent::GetComponentTypeId() const
|
||||
|
||||
@@ -118,6 +118,7 @@ namespace AZ
|
||||
const static AZ::Crc32 StringLineEditingCompleteNotify = AZ_CRC("StringLineEditingCompleteNotify", 0x139e5fa9);
|
||||
|
||||
const static AZ::Crc32 NameLabelOverride = AZ_CRC("NameLabelOverride", 0x9ff79cab);
|
||||
const static AZ::Crc32 AssetPickerTitle = AZ_CRC_CE("AssetPickerTitle");
|
||||
const static AZ::Crc32 ChildNameLabelOverride = AZ_CRC("ChildNameLabelOverride", 0x73dd2909);
|
||||
//! Container attribute that is used to override labels for its elements given the index of the element
|
||||
const static AZ::Crc32 IndexedChildNameLabelOverride = AZ_CRC("IndexedChildNameLabelOverride", 0x5f313ac2);
|
||||
|
||||
@@ -10,91 +10,75 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ByteStreamSerializer.h"
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace ByteSerializerInternal
|
||||
{
|
||||
static JsonSerializationResult::Result Load(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context)
|
||||
{
|
||||
using JsonSerializationResult::Outcomes;
|
||||
using JsonSerializationResult::Tasks;
|
||||
|
||||
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
|
||||
|
||||
switch (inputValue.GetType())
|
||||
{
|
||||
case rapidjson::kStringType: {
|
||||
JsonByteStream buffer;
|
||||
if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength()))
|
||||
{
|
||||
JsonByteStream* valAsByteStream = static_cast<JsonByteStream*>(outputValue);
|
||||
*valAsByteStream = AZStd::move(buffer);
|
||||
return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream.");
|
||||
}
|
||||
return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed.");
|
||||
}
|
||||
case rapidjson::kArrayType:
|
||||
case rapidjson::kObjectType:
|
||||
case rapidjson::kNullType:
|
||||
case rapidjson::kFalseType:
|
||||
case rapidjson::kTrueType:
|
||||
case rapidjson::kNumberType:
|
||||
return context.Report(
|
||||
Tasks::ReadField, Outcomes::Unsupported,
|
||||
"Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers.");
|
||||
default:
|
||||
return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value.");
|
||||
}
|
||||
}
|
||||
|
||||
static JsonSerializationResult::Result StoreWithDefault(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, JsonSerializerContext& context)
|
||||
{
|
||||
using JsonSerializationResult::Outcomes;
|
||||
using JsonSerializationResult::Tasks;
|
||||
|
||||
const JsonByteStream& valAsByteStream = *static_cast<const JsonByteStream*>(inputValue);
|
||||
if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast<const JsonByteStream*>(defaultValue)))
|
||||
{
|
||||
const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size());
|
||||
outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator());
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored.");
|
||||
}
|
||||
|
||||
return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used.");
|
||||
}
|
||||
} // namespace ByteSerializerInternal
|
||||
|
||||
AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0);
|
||||
|
||||
JsonSerializationResult::Result JsonByteStreamSerializer::Load(
|
||||
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
JsonDeserializerContext& context)
|
||||
{
|
||||
using JsonSerializationResult::Outcomes;
|
||||
using JsonSerializationResult::Tasks;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<JsonByteStream>() == outputValueTypeId,
|
||||
"Unable to deserialize AZStd::vector<AZ::u8>> to json because the provided type is %s",
|
||||
outputValueTypeId.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
|
||||
|
||||
return ByteSerializerInternal::Load(outputValue, inputValue, context);
|
||||
switch (inputValue.GetType())
|
||||
{
|
||||
case rapidjson::kStringType: {
|
||||
JsonByteStream buffer;
|
||||
if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength()))
|
||||
{
|
||||
JsonByteStream* valAsByteStream = static_cast<JsonByteStream*>(outputValue);
|
||||
*valAsByteStream = AZStd::move(buffer);
|
||||
return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream.");
|
||||
}
|
||||
return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed.");
|
||||
}
|
||||
case rapidjson::kArrayType:
|
||||
case rapidjson::kObjectType:
|
||||
case rapidjson::kNullType:
|
||||
case rapidjson::kFalseType:
|
||||
case rapidjson::kTrueType:
|
||||
case rapidjson::kNumberType:
|
||||
return context.Report(
|
||||
Tasks::ReadField, Outcomes::Unsupported,
|
||||
"Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers.");
|
||||
default:
|
||||
return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value.");
|
||||
}
|
||||
}
|
||||
|
||||
JsonSerializationResult::Result JsonByteStreamSerializer::Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
|
||||
JsonSerializerContext& context)
|
||||
{
|
||||
using JsonSerializationResult::Outcomes;
|
||||
using JsonSerializationResult::Tasks;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<JsonByteStream>() == valueTypeId,
|
||||
"Unable to serialize AZStd::vector<AZ::u8> to json because the provided type is %s",
|
||||
valueTypeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
return ByteSerializerInternal::StoreWithDefault(outputValue, inputValue, defaultValue, context);
|
||||
const JsonByteStream& valAsByteStream = *static_cast<const JsonByteStream*>(inputValue);
|
||||
if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast<const JsonByteStream*>(defaultValue)))
|
||||
{
|
||||
const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size());
|
||||
outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator());
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored.");
|
||||
}
|
||||
|
||||
return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used.");
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -104,13 +104,12 @@ namespace AZ
|
||||
auto serializer = context.GetRegistrationContext()->GetSerializerForType(classData.m_typeId);
|
||||
if (serializer)
|
||||
{
|
||||
if (storeTypeId == StoreTypeId::Yes)
|
||||
ResultCode result = serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
if (storeTypeId == StoreTypeId::Yes && result.GetProcessing() != Processing::Halted)
|
||||
{
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Catastrophic,
|
||||
"Unable to store type information in a JSON Serializer primitive.");
|
||||
result.Combine(InsertTypeId(node, classData, context));
|
||||
}
|
||||
|
||||
return serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (classData.m_azRtti && (classData.m_azRtti->GetTypeTraits() & AZ::TypeTraits::is_enum) == AZ::TypeTraits::is_enum)
|
||||
@@ -128,13 +127,12 @@ namespace AZ
|
||||
serializer = context.GetRegistrationContext()->GetSerializerForType(classData.m_azRtti->GetGenericTypeId());
|
||||
if (serializer)
|
||||
{
|
||||
if (storeTypeId == StoreTypeId::Yes)
|
||||
ResultCode result = serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
if (storeTypeId == StoreTypeId::Yes && result.GetProcessing() != Processing::Halted)
|
||||
{
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Catastrophic,
|
||||
"Unable to store type information in a JSON Serializer primitive.");
|
||||
result.Combine(InsertTypeId(node, classData, context));
|
||||
}
|
||||
|
||||
return serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +147,7 @@ namespace AZ
|
||||
ResultCode result(Tasks::WriteValue);
|
||||
if (storeTypeId == StoreTypeId::Yes)
|
||||
{
|
||||
// Not using InsertTypeId here to avoid needing to create the temporary value and swap it in that call.
|
||||
node.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier),
|
||||
StoreTypeName(classData, context), context.GetJsonAllocator());
|
||||
result = ResultCode(Tasks::WriteValue, Outcomes::Success);
|
||||
@@ -569,6 +568,31 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonSerializer::InsertTypeId(
|
||||
rapidjson::Value& output, const SerializeContext::ClassData& classData, JsonSerializerContext& context)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (output.IsObject())
|
||||
{
|
||||
rapidjson::Value insertedObject(rapidjson::kObjectType);
|
||||
insertedObject.AddMember(
|
||||
rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), StoreTypeName(classData, context),
|
||||
context.GetJsonAllocator());
|
||||
|
||||
for (auto& element : output.GetObject())
|
||||
{
|
||||
insertedObject.AddMember(AZStd::move(element.name), AZStd::move(element.value), context.GetJsonAllocator());
|
||||
}
|
||||
output = AZStd::move(insertedObject);
|
||||
return ResultCode(Tasks::WriteValue, Outcomes::Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Catastrophic, "Only able to store type information in a JSON Object.");
|
||||
}
|
||||
}
|
||||
|
||||
rapidjson::Value JsonSerializer::GetExplicitDefault()
|
||||
{
|
||||
return rapidjson::Value(rapidjson::kObjectType);
|
||||
|
||||
@@ -80,6 +80,9 @@ namespace AZ
|
||||
static JsonSerializationResult::ResultCode StoreTypeName(rapidjson::Value& output,
|
||||
const Uuid& typeId, JsonSerializerContext& context);
|
||||
|
||||
static JsonSerializationResult::ResultCode InsertTypeId(
|
||||
rapidjson::Value& output, const SerializeContext::ClassData& classData, JsonSerializerContext& context);
|
||||
|
||||
static rapidjson::Value GetExplicitDefault();
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
@@ -256,7 +256,7 @@ namespace AZ
|
||||
|
||||
//! Remove the value at the provided path
|
||||
//! @param path The path to a value that should be removed
|
||||
//! @return Whether or not the value was stored at the provided path. An invalid path will return false;
|
||||
//! @return Whether or not the path was found and removed. An invalid path will return false;
|
||||
virtual bool Remove(AZStd::string_view path) = 0;
|
||||
|
||||
//! Structure which contains configuration settings for how to parse a single command line argument
|
||||
|
||||
@@ -32,17 +32,12 @@
|
||||
namespace AZ::Internal
|
||||
{
|
||||
AZ::SettingsRegistryInterface::FixedValueString GetEngineMonikerForProject(
|
||||
SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectPath)
|
||||
SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectJsonPath)
|
||||
{
|
||||
// projectPath needs to be an absolute path here.
|
||||
using namespace AZ::SettingsRegistryMergeUtils;
|
||||
bool projectJsonMerged = false;
|
||||
auto projectJsonPath = projectPath / "project.json";
|
||||
if (AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
|
||||
{
|
||||
projectJsonMerged = settingsRegistry.MergeSettingsFile(
|
||||
projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey);
|
||||
}
|
||||
bool projectJsonMerged = settingsRegistry.MergeSettingsFile(
|
||||
projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey);
|
||||
|
||||
AZ::SettingsRegistryInterface::FixedValueString engineMoniker;
|
||||
if (projectJsonMerged)
|
||||
@@ -105,12 +100,12 @@ namespace AZ::Internal
|
||||
|
||||
const auto engineMonikerKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engine_name", EngineSettingsRootKey);
|
||||
|
||||
AZStd::set<AZ::IO::FixedMaxPath> projectPathsNotFound;
|
||||
|
||||
for (EngineInfo& engineInfo : pathVisitor.m_enginePaths)
|
||||
{
|
||||
AZ::IO::FixedMaxPath engineSettingsPath{engineInfo.m_path};
|
||||
engineSettingsPath /= "engine.json";
|
||||
|
||||
if (AZ::IO::SystemFile::Exists(engineSettingsPath.c_str()))
|
||||
if (auto engineSettingsPath = AZ::IO::FixedMaxPath{engineInfo.m_path} / "engine.json";
|
||||
AZ::IO::SystemFile::Exists(engineSettingsPath.c_str()))
|
||||
{
|
||||
if (settingsRegistry.MergeSettingsFile(
|
||||
engineSettingsPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, EngineSettingsRootKey))
|
||||
@@ -119,12 +114,61 @@ namespace AZ::Internal
|
||||
}
|
||||
}
|
||||
|
||||
auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, engineInfo.m_path / projectPath);
|
||||
if (!engineMoniker.empty() && engineMoniker == engineInfo.m_moniker)
|
||||
if (auto projectJsonPath = (engineInfo.m_path / projectPath / "project.json").LexicallyNormal();
|
||||
AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
|
||||
{
|
||||
engineRoot = engineInfo.m_path;
|
||||
break;
|
||||
if (auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, projectJsonPath);
|
||||
!engineMoniker.empty() && engineMoniker == engineInfo.m_moniker)
|
||||
{
|
||||
engineRoot = engineInfo.m_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
projectPathsNotFound.insert(projectJsonPath);
|
||||
}
|
||||
|
||||
// Continue looking for candidates, remove the previous engine and project settings that were merged above.
|
||||
settingsRegistry.Remove(ProjectSettingsRootKey);
|
||||
settingsRegistry.Remove(EngineSettingsRootKey);
|
||||
}
|
||||
|
||||
if (engineRoot.empty())
|
||||
{
|
||||
AZStd::string errorStr;
|
||||
if (!projectPathsNotFound.empty())
|
||||
{
|
||||
// This case is usually encountered when a project path is given as a relative path,
|
||||
// which is assumed to be relative to an engine root.
|
||||
// When no project.json files are found this way, dump this error message about
|
||||
// which project paths were checked.
|
||||
AZStd::string projectPathsTested;
|
||||
for (const auto& path : projectPathsNotFound)
|
||||
{
|
||||
projectPathsTested.append(AZStd::string::format(" %s\n", path.c_str()));
|
||||
}
|
||||
errorStr = AZStd::string::format("No valid project was found at these locations:\n%s"
|
||||
"Please supply a valid --project-path to the application.",
|
||||
projectPathsTested.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// The other case is that a project.json was found, but after checking all the registered engines
|
||||
// none of them matched the engine moniker.
|
||||
AZStd::string enginePathsChecked;
|
||||
for (const auto& engineInfo : pathVisitor.m_enginePaths)
|
||||
{
|
||||
enginePathsChecked.append(AZStd::string::format(" %s (%s)\n", engineInfo.m_path.c_str(), engineInfo.m_moniker.c_str()));
|
||||
}
|
||||
errorStr = AZStd::string::format(
|
||||
"No engine was found in o3de_manifest.json with a name that matches the one set in the project.json.\n"
|
||||
"Engines that were checked:\n%s"
|
||||
"Please check that your engine and project have both been registered with scripts/o3de.py.", enginePathsChecked.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
settingsRegistry.Set(FilePathKey_ErrorText, errorStr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +202,7 @@ namespace AZ::Internal
|
||||
return {};
|
||||
}
|
||||
|
||||
void InjectSettingToCommandLineFront(AZ::SettingsRegistryInterface& settingsRegistry,
|
||||
void InjectSettingToCommandLineBack(AZ::SettingsRegistryInterface& settingsRegistry,
|
||||
AZStd::string_view path, AZStd::string_view value)
|
||||
{
|
||||
AZ::CommandLine commandLine;
|
||||
@@ -168,7 +212,7 @@ namespace AZ::Internal
|
||||
|
||||
auto projectPathOverride = AZStd::string::format(R"(--regset="%.*s=%.*s")",
|
||||
aznumeric_cast<int>(path.size()), path.data(), aznumeric_cast<int>(value.size()), value.data());
|
||||
paramContainer.emplace(paramContainer.begin(), AZStd::move(projectPathOverride));
|
||||
paramContainer.emplace(paramContainer.end(), AZStd::move(projectPathOverride));
|
||||
commandLine.Parse(paramContainer);
|
||||
AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine);
|
||||
}
|
||||
@@ -197,8 +241,8 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
if (!engineRoot.empty())
|
||||
{
|
||||
settingsRegistry.Set(engineRootKey, engineRoot.Native());
|
||||
// Inject the engine root into the front of the command line settings
|
||||
Internal::InjectSettingToCommandLineFront(settingsRegistry, engineRootKey, engineRoot.Native());
|
||||
// Inject the engine root at the end of the command line settings
|
||||
Internal::InjectSettingToCommandLineBack(settingsRegistry, engineRootKey, engineRoot.Native());
|
||||
return engineRoot;
|
||||
}
|
||||
}
|
||||
@@ -244,8 +288,8 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
if (!projectRoot.empty())
|
||||
{
|
||||
settingsRegistry.Set(projectRootKey, projectRoot.c_str());
|
||||
// Inject the project root into the front of the command line settings
|
||||
Internal::InjectSettingToCommandLineFront(settingsRegistry, projectRootKey, projectRoot.Native());
|
||||
// Inject the project root at the end of the command line settings
|
||||
Internal::InjectSettingToCommandLineBack(settingsRegistry, projectRootKey, projectRoot.Native());
|
||||
return projectRoot;
|
||||
}
|
||||
}
|
||||
@@ -654,7 +698,6 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
if (registry.Get(engineRootPath, FilePathKey_EngineRootFolder))
|
||||
{
|
||||
AZ::IO::FixedMaxPath mergePath{ AZStd::move(engineRootPath) };
|
||||
mergePath /= "Engine";
|
||||
mergePath /= SettingsRegistryInterface::RegistryFolder;
|
||||
registry.MergeSettingsFolder(mergePath.Native(), specializations, platform, "", scratchBuffer);
|
||||
}
|
||||
@@ -875,6 +918,49 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParseCommandLine(AZ::CommandLine& commandLine)
|
||||
{
|
||||
struct OptionKeyToRegsetKey
|
||||
{
|
||||
AZStd::string_view m_optionKey;
|
||||
AZStd::string m_regsetKey;
|
||||
};
|
||||
|
||||
// Provide overrides for the engine root, the project root and the project cache root
|
||||
AZStd::array commandOptions = {
|
||||
OptionKeyToRegsetKey{
|
||||
"engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)},
|
||||
OptionKeyToRegsetKey{
|
||||
"project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)},
|
||||
OptionKeyToRegsetKey{
|
||||
"project-cache-path",
|
||||
AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)}};
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, commandOptions.size()> overrideArgs;
|
||||
|
||||
for (auto&& [optionKey, regsetKey] : commandOptions)
|
||||
{
|
||||
if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0)
|
||||
{
|
||||
// Use the last supplied command option value to override previous values
|
||||
auto overrideArg = AZStd::string::format(
|
||||
R"(--regset="%s=%s")", regsetKey.c_str(), commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str());
|
||||
overrideArgs.emplace_back(AZStd::move(overrideArg));
|
||||
}
|
||||
}
|
||||
|
||||
if (!overrideArgs.empty())
|
||||
{
|
||||
// Dump the input command line, add the additional option overrides
|
||||
// and Parse the new command line args (write back) into the input command line.
|
||||
AZ::CommandLine::ParamContainer commandLineArgs;
|
||||
commandLine.Dump(commandLineArgs);
|
||||
commandLineArgs.insert(
|
||||
commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()), AZStd::make_move_iterator(overrideArgs.end()));
|
||||
commandLine.Parse(commandLineArgs);
|
||||
}
|
||||
}
|
||||
|
||||
bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key,
|
||||
AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings)
|
||||
{
|
||||
|
||||
@@ -55,6 +55,9 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
//! Development write storage path may be considered temporary or cache storage on some platforms
|
||||
inline static constexpr char FilePathKey_DevWriteStorage[] = "/Amazon/AzCore/Runtime/FilePaths/DevWriteStorage";
|
||||
|
||||
//! Stores error text regarding engine boot sequence when engine and project roots cannot be determined
|
||||
inline static constexpr char FilePathKey_ErrorText[] = "/Amazon/AzCore/Runtime/FilePaths/ErrorText";
|
||||
|
||||
//! Root key for where command line are stored at within the settings registry
|
||||
inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine";
|
||||
//! Key set to trigger a notification that the CommandLine has been stored within the settings registry
|
||||
@@ -219,6 +222,9 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
//! into the AZ::CommandLine instance
|
||||
bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine);
|
||||
|
||||
//! Parse a CommandLine and transform certain options into formal "regset" options
|
||||
void ParseCommandLine(AZ::CommandLine& commandLine);
|
||||
|
||||
//! Structure for configuring how values should be dumped from the Settings Registry
|
||||
struct DumperSettings
|
||||
{
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ namespace AZ
|
||||
{
|
||||
namespace NativeUI
|
||||
{
|
||||
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
{
|
||||
AZ::Android::JNI::Object object("com/amazon/lumberyard/NativeUI/LumberyardNativeUI");
|
||||
object.RegisterStaticMethod("DisplayDialog", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V");
|
||||
|
||||
+4
-9
@@ -12,16 +12,11 @@
|
||||
|
||||
#include <AzCore/NativeUI/NativeUISystemComponent.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
namespace NativeUI
|
||||
AZStd::string NativeUISystem::DisplayBlockingDialog([[maybe_unused]] const AZStd::string& title, [[maybe_unused]] const AZStd::string& message,
|
||||
[[maybe_unused]] const AZStd::vector<AZStd::string>& options) const
|
||||
{
|
||||
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
{
|
||||
AZ_UNUSED(title);
|
||||
AZ_UNUSED(message);
|
||||
AZ_UNUSED(options);
|
||||
return "";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace AZ
|
||||
{
|
||||
namespace NativeUI
|
||||
{
|
||||
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
{
|
||||
__block NSModalResponse response = -1;
|
||||
|
||||
|
||||
+1
-1
@@ -245,7 +245,7 @@ namespace AZ
|
||||
{
|
||||
namespace NativeUI
|
||||
{
|
||||
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
{
|
||||
if (options.size() >= MAX_ITEMS)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace AZ
|
||||
{
|
||||
namespace NativeUI
|
||||
{
|
||||
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
|
||||
{
|
||||
__block AZStd::string userSelection = "";
|
||||
|
||||
|
||||
@@ -449,6 +449,46 @@ namespace JsonSerializationTests
|
||||
|
||||
}
|
||||
|
||||
TEST_F(JsonSerializationTests, Load_PrimitiveForInheritedClass_LoadsCorrectClass)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
using namespace ::testing;
|
||||
|
||||
AZStd::string json = AZStd::string::format(R"(
|
||||
{
|
||||
"%s": "SimpleInheritence",
|
||||
"base_var": -88.0,
|
||||
"var1": 88,
|
||||
"var2": 42
|
||||
})",
|
||||
AZ::JsonSerialization::TypeIdFieldIdentifier);
|
||||
m_jsonDocument->Parse(json.c_str());
|
||||
|
||||
SimpleInheritence::Reflect(m_serializeContext, true);
|
||||
m_serializeContext->RegisterGenericType<AZStd::unique_ptr<BaseClass>>();
|
||||
m_jsonRegistrationContext->Serializer<JsonSerializerMock>()->HandlesType<SimpleInheritence>();
|
||||
JsonSerializerMock* mock =
|
||||
reinterpret_cast<JsonSerializerMock*>(m_jsonRegistrationContext->GetSerializerForType(azrtti_typeid<SimpleInheritence>()));
|
||||
EXPECT_CALL(*mock, Load(_, _, _, _))
|
||||
.Times(Exactly(1))
|
||||
.WillRepeatedly(Return(Result(m_deserializationSettings->m_reporting, "Test", Tasks::ReadField, Outcomes::Success, "")));
|
||||
|
||||
AZStd::unique_ptr<BaseClass> instance;
|
||||
ResultCode result = AZ::JsonSerialization::Load(instance, *m_jsonDocument, *m_deserializationSettings);
|
||||
EXPECT_NE(Processing::Halted, result.GetProcessing());
|
||||
|
||||
EXPECT_EQ(azrtti_typeid<SimpleInheritence>(), azrtti_typeid(*instance));
|
||||
|
||||
m_serializeContext->EnableRemoveReflection();
|
||||
SimpleInheritence::Reflect(m_serializeContext, true);
|
||||
m_serializeContext->DisableRemoveReflection();
|
||||
|
||||
m_jsonRegistrationContext->EnableRemoveReflection();
|
||||
m_serializeContext->RegisterGenericType<AZStd::unique_ptr<BaseClass>>();
|
||||
m_jsonRegistrationContext->Serializer<JsonSerializerMock>()->HandlesType<SimpleInheritence>();
|
||||
m_jsonRegistrationContext->DisableRemoveReflection();
|
||||
}
|
||||
|
||||
TEST_F(JsonSerializationTests, Store_TemplatedClassWithRegisteredHandler_StoreOnHandlerCalled)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
@@ -474,6 +514,52 @@ namespace JsonSerializationTests
|
||||
m_jsonRegistrationContext->DisableRemoveReflection();
|
||||
}
|
||||
|
||||
TEST_F(JsonSerializationTests, Store_PrimitiveForInheritedClass_StoreSucceedsAndTypeIdIsAdded)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
using namespace ::testing;
|
||||
|
||||
SimpleInheritence::Reflect(m_serializeContext, true);
|
||||
m_serializeContext->RegisterGenericType<AZStd::unique_ptr<BaseClass>>();
|
||||
m_jsonRegistrationContext->Serializer<JsonSerializerMock>()->HandlesType<SimpleInheritence>();
|
||||
JsonSerializerMock* mock =
|
||||
reinterpret_cast<JsonSerializerMock*>(m_jsonRegistrationContext->GetSerializerForType(azrtti_typeid<SimpleInheritence>()));
|
||||
EXPECT_CALL(*mock, Store(_, _, _, _, _))
|
||||
.Times(Exactly(1))
|
||||
.WillRepeatedly(Invoke([](rapidjson::Value& output, const void*, const void*, const AZ::Uuid&, AZ::JsonSerializerContext& context)
|
||||
{
|
||||
// Insert some values to allow verification later on.
|
||||
output.SetObject();
|
||||
output.AddMember("base_var", -88.0, context.GetJsonAllocator());
|
||||
output.AddMember("var1", 88, context.GetJsonAllocator());
|
||||
output.AddMember("var2", 42, context.GetJsonAllocator());
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Success, "");
|
||||
}));
|
||||
|
||||
AZStd::unique_ptr<BaseClass> instance{ aznew SimpleInheritence() };
|
||||
ResultCode result = AZ::JsonSerialization::Store(*m_jsonDocument, m_jsonDocument->GetAllocator(), instance, *m_serializationSettings);
|
||||
EXPECT_NE(Processing::Halted, result.GetProcessing());
|
||||
|
||||
AZStd::string compare = AZStd::string::format(R"(
|
||||
{
|
||||
"%s": "SimpleInheritence",
|
||||
"base_var": -88.0,
|
||||
"var1": 88,
|
||||
"var2": 42
|
||||
})",
|
||||
AZ::JsonSerialization::TypeIdFieldIdentifier);
|
||||
Expect_DocStrEq(compare.c_str());
|
||||
|
||||
m_serializeContext->EnableRemoveReflection();
|
||||
m_serializeContext->RegisterGenericType<AZStd::unique_ptr<BaseClass>>();
|
||||
SimpleInheritence::Reflect(m_serializeContext, true);
|
||||
m_serializeContext->DisableRemoveReflection();
|
||||
|
||||
m_jsonRegistrationContext->EnableRemoveReflection();
|
||||
m_jsonRegistrationContext->Serializer<JsonSerializerMock>()->HandlesType<SimpleInheritence>();
|
||||
m_jsonRegistrationContext->DisableRemoveReflection();
|
||||
}
|
||||
|
||||
TEST_F(JsonSerializationTests, Store_StoreWithNullPtr_ReturnsCatastrophic)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
Reference in New Issue
Block a user