Merge pull request #410 from aws-lumberyard-dev/ly-sdk/phistere/LYN-2723-Merge
LYN-2723: Fixes issues with bad project or engine paths Cherry-pick: 6ce7a6d30c57c941459b43c157861df5d9143ae1
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -328,9 +328,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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -874,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 = "";
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
// Initializes the IArchive for reading archive(.pak) files
|
||||
if (auto archive = AZ::Interface<AZ::IO::IArchive>::Get(); !archive)
|
||||
if (auto archive = AZ::Interface<AZ::IO::IArchive>::Get(); archive == nullptr)
|
||||
{
|
||||
m_archive = AZStd::make_unique<AZ::IO::Archive>();
|
||||
AZ::Interface<AZ::IO::IArchive>::Register(m_archive.get());
|
||||
@@ -189,6 +189,12 @@ namespace AzFramework
|
||||
SetFileIOAliases();
|
||||
}
|
||||
|
||||
if (auto nativeUI = AZ::Interface<AZ::NativeUI::NativeUIRequests>::Get(); nativeUI == nullptr)
|
||||
{
|
||||
m_nativeUI = AZStd::make_unique<AZ::NativeUI::NativeUISystem>();
|
||||
AZ::Interface<AZ::NativeUI::NativeUIRequests>::Register(m_nativeUI.get());
|
||||
}
|
||||
|
||||
ApplicationRequests::Bus::Handler::BusConnect();
|
||||
AZ::UserSettingsFileLocatorBus::Handler::BusConnect();
|
||||
NetSystemRequestBus::Handler::BusConnect();
|
||||
@@ -205,12 +211,17 @@ namespace AzFramework
|
||||
AZ::UserSettingsFileLocatorBus::Handler::BusDisconnect();
|
||||
ApplicationRequests::Bus::Handler::BusDisconnect();
|
||||
|
||||
if (AZ::Interface<AZ::NativeUI::NativeUIRequests>::Get() == m_nativeUI.get())
|
||||
{
|
||||
AZ::Interface<AZ::NativeUI::NativeUIRequests>::Unregister(m_nativeUI.get());
|
||||
}
|
||||
m_nativeUI.reset();
|
||||
|
||||
// Unset the Archive file IO if it is set as the direct instance
|
||||
if (AZ::IO::FileIOBase::GetInstance() == m_archiveFileIO.get())
|
||||
{
|
||||
AZ::IO::FileIOBase::SetInstance(nullptr);
|
||||
}
|
||||
|
||||
m_archiveFileIO.reset();
|
||||
|
||||
// Destroy the IArchive instance
|
||||
@@ -303,7 +314,6 @@ namespace AzFramework
|
||||
azrtti_typeid<AZ::AssetManagerComponent>(),
|
||||
azrtti_typeid<AZ::UserSettingsComponent>(),
|
||||
azrtti_typeid<AZ::Debug::FrameProfilerComponent>(),
|
||||
azrtti_typeid<AZ::NativeUI::NativeUISystemComponent>(),
|
||||
azrtti_typeid<AZ::SliceComponent>(),
|
||||
azrtti_typeid<AZ::SliceSystemComponent>(),
|
||||
|
||||
@@ -372,7 +382,6 @@ namespace AzFramework
|
||||
azrtti_typeid<AZ::UserSettingsComponent>(),
|
||||
azrtti_typeid<AZ::ScriptSystemComponent>(),
|
||||
azrtti_typeid<AZ::JobManagerComponent>(),
|
||||
azrtti_typeid<AZ::NativeUI::NativeUISystemComponent>(),
|
||||
azrtti_typeid<AZ::SliceSystemComponent>(),
|
||||
|
||||
azrtti_typeid<AzFramework::AssetCatalogComponent>(),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzCore/Math/Uuid.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
@@ -187,6 +188,7 @@ namespace AzFramework
|
||||
AZStd::unique_ptr<AZ::IO::FileIOBase> m_archiveFileIO; ///> The Default file IO instance is a ArchiveFileIO.
|
||||
AZStd::unique_ptr<AZ::IO::Archive> m_archive; ///> The AZ::IO::Instance
|
||||
AZStd::unique_ptr<Implementation> m_pimpl;
|
||||
AZStd::unique_ptr<AZ::NativeUI::NativeUIRequests> m_nativeUI;
|
||||
bool m_ownsConsole = false;
|
||||
|
||||
bool m_exitMainLoopRequested = false;
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace AzFramework
|
||||
{
|
||||
// Read the wait for connection boolean from the Settings Registry
|
||||
AZ::s64 waitForConnect64{};
|
||||
if (!AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, waitForConnect64, AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, AzFramework::AssetSystem::WaitForConnect))
|
||||
if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, waitForConnect64, AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, AzFramework::AssetSystem::WaitForConnect))
|
||||
{
|
||||
outputConnectionSettings.m_waitForConnect = waitForConnect64 != 0;
|
||||
}
|
||||
|
||||
@@ -41,9 +41,10 @@ namespace AzFramework::ProjectManager
|
||||
// at the end of the function
|
||||
AZ::CommandLine commandLine;
|
||||
commandLine.Parse(argc, argv);
|
||||
AZ::SettingsRegistryImpl settingsRegistry;
|
||||
// Store the Command line to the Setting Registry
|
||||
AZ::SettingsRegistryMergeUtils::ParseCommandLine(commandLine);
|
||||
|
||||
// Store the Command line to the Setting Registry
|
||||
AZ::SettingsRegistryImpl settingsRegistry;
|
||||
AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
|
||||
@@ -68,7 +69,14 @@ namespace AzFramework::ProjectManager
|
||||
// If we were able to locate a path to a project, we're done
|
||||
if (!projectRootPath.empty())
|
||||
{
|
||||
return ProjectPathCheckResult::ProjectPathFound;
|
||||
AZ::IO::FixedMaxPath projectJsonPath = engineRootPath / projectRootPath / "project.json";
|
||||
if (AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
|
||||
{
|
||||
return ProjectPathCheckResult::ProjectPathFound;
|
||||
}
|
||||
AZ_TracePrintf(
|
||||
"ProjectManager", "Did not find a project file at location '%s', launching the Project Manager...",
|
||||
projectJsonPath.c_str());
|
||||
}
|
||||
|
||||
if (LaunchProjectManager(engineRootPath))
|
||||
|
||||
@@ -284,6 +284,10 @@ namespace AzToolsFramework
|
||||
void ToolsApplication::Start(const Descriptor& descriptor, const StartupParameters& startupParameters/* = StartupParameters()*/)
|
||||
{
|
||||
Application::Start(descriptor, startupParameters);
|
||||
if (!m_isStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_editorEntityManager.Start();
|
||||
|
||||
|
||||
@@ -5045,12 +5045,28 @@ extern "C"
|
||||
#pragma comment(lib, "Shell32.lib")
|
||||
#endif
|
||||
|
||||
struct CryAllocatorsRAII
|
||||
{
|
||||
CryAllocatorsRAII()
|
||||
{
|
||||
AZ_Assert(!AZ::AllocatorInstance<AZ::LegacyAllocator>::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it");
|
||||
AZ_Assert(!AZ::AllocatorInstance<CryStringAllocator>::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it");
|
||||
|
||||
AZ::AllocatorInstance<AZ::LegacyAllocator>::Create();
|
||||
AZ::AllocatorInstance<CryStringAllocator>::Create();
|
||||
}
|
||||
|
||||
~CryAllocatorsRAII()
|
||||
{
|
||||
AZ::AllocatorInstance<CryStringAllocator>::Destroy();
|
||||
AZ::AllocatorInstance<AZ::LegacyAllocator>::Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
{
|
||||
AZ_Assert(!AZ::AllocatorInstance<AZ::LegacyAllocator>::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it");
|
||||
AZ::AllocatorInstance<AZ::LegacyAllocator>::Create();
|
||||
AZ_Assert(!AZ::AllocatorInstance<CryStringAllocator>::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it");
|
||||
AZ::AllocatorInstance<CryStringAllocator>::Create();
|
||||
CryAllocatorsRAII cryAllocatorsRAII;
|
||||
|
||||
// ensure the EditorEventsBus context gets created inside EditorLib
|
||||
[[maybe_unused]] const auto& editorEventsContext = AzToolsFramework::EditorEvents::Bus::GetOrCreateContext();
|
||||
@@ -5058,7 +5074,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
// connect relevant buses to global settings
|
||||
gSettings.Connect();
|
||||
|
||||
CCryEditApp* theApp = new CCryEditApp();
|
||||
auto theApp = AZStd::make_unique<CCryEditApp>();
|
||||
// this does some magic to set the current directory...
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
@@ -5145,8 +5161,6 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
|
||||
}
|
||||
|
||||
delete theApp;
|
||||
|
||||
gSettings.Disconnect();
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -30,17 +30,14 @@ int main(int argc, char* argv[])
|
||||
[[maybe_unused]] const bool loaded = handle->Load(true);
|
||||
AZ_Assert(loaded, "EditorLib could not be loaded");
|
||||
|
||||
int ret = 1;
|
||||
if (auto fn = handle->GetFunction<CryEditMain>(CryEditMainName); fn != nullptr)
|
||||
{
|
||||
const int ret = AZStd::invoke(fn, argc, argv);
|
||||
|
||||
AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
|
||||
AZ::Environment::Detach();
|
||||
|
||||
return ret;
|
||||
ret = AZStd::invoke(fn, argc, argv);
|
||||
}
|
||||
|
||||
handle = {};
|
||||
AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
|
||||
AZ::Environment::Detach();
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -579,6 +579,8 @@ int rcmain(int argc, char** argv, [[maybe_unused]] char** envp)
|
||||
// on the command line
|
||||
AZ::CommandLine commandLine;
|
||||
commandLine.Parse(argc, argv);
|
||||
AZ::SettingsRegistryMergeUtils::ParseCommandLine(commandLine);
|
||||
|
||||
AZ::SettingsRegistryImpl settingsRegistry;
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
|
||||
|
||||
Reference in New Issue
Block a user