diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index d31ea6334c..4e5dadb13c 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -25,7 +25,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/physics/TestSuite_Main.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -39,7 +39,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/physics/TestSuite_Periodic.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -71,7 +71,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -85,7 +85,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE sandbox TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Sandbox.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -101,7 +101,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/WhiteBox/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -120,7 +120,7 @@ endif() # TEST_SUITE main # TEST_SERIAL # PATH ${CMAKE_CURRENT_LIST_DIR}/NvCloth/TestSuite_Active.py -# TIMEOUT 3600 +# TIMEOUT 1500 # RUNTIME_DEPENDENCIES # Legacy::Editor # Legacy::CryRenderNULL @@ -136,7 +136,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE sandbox TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -154,7 +154,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/PythonAssetBuilder - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL @@ -173,7 +173,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -196,7 +196,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/dyn_veg PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark" - TIMEOUT 36000 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -212,7 +212,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE sandbox PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/dyn_veg PYTEST_MARKS "SUITE_sandbox" - TIMEOUT 36000 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -228,7 +228,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/dyn_veg PYTEST_MARKS "SUITE_periodic" - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -244,7 +244,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/landscape_canvas PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark" - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -259,7 +259,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/landscape_canvas PYTEST_MARKS "SUITE_periodic" - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -274,7 +274,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SERIAL TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/gradient_signal - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -292,7 +292,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/editor - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor Legacy::CryRenderNULL diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt index de3e04e67e..6a865ee690 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt @@ -100,7 +100,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL - TIMEOUT 3600 + TIMEOUT 1500 TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessor @@ -123,7 +123,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL - TIMEOUT 3600 + TIMEOUT 1500 TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessorBatch diff --git a/Code/Framework/AzCore/AzCore/AzCoreModule.cpp b/Code/Framework/AzCore/AzCore/AzCoreModule.cpp index 3c93ae5561..3d074455cc 100644 --- a/Code/Framework/AzCore/AzCore/AzCoreModule.cpp +++ b/Code/Framework/AzCore/AzCore/AzCoreModule.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,6 @@ namespace AZ AssetManagerComponent::CreateDescriptor(), UserSettingsComponent::CreateDescriptor(), Debug::FrameProfilerComponent::CreateDescriptor(), - NativeUI::NativeUISystemComponent::CreateDescriptor(), SliceComponent::CreateDescriptor(), SliceSystemComponent::CreateDescriptor(), SliceMetadataInfoComponent::CreateDescriptor(), diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index c55f565615..d0f277a6b8 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -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::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 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; diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h index 3ebcf39d95..8617aa5f2e 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h @@ -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 diff --git a/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h b/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h index 5055540874..f45295d221 100644 --- a/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h +++ b/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h @@ -15,45 +15,49 @@ #include #include -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& /*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& /*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; - } -} + 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; +} // namespace AZ::NativeUI diff --git a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp index cf0c2872f1..bed066018a 100644 --- a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp @@ -15,50 +15,19 @@ #include -namespace AZ +namespace AZ::NativeUI { - using namespace AZ::NativeUI; - - void NativeUISystemComponent::Reflect(AZ::ReflectContext* context) + NativeUISystem::NativeUISystem() { - if (AZ::SerializeContext* serialize = azrtti_cast(context)) - { - serialize->Class() - ->Version(0) - ; - - if (AZ::EditContext* ec = serialize->GetEditContext()) - { - ec->Class("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 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 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 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 diff --git a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h index 2d5cc36ffc..771b9a2af9 100644 --- a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h +++ b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h @@ -15,40 +15,24 @@ #include #include -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& 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& 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 diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp index f12da5c60e..015554538f 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp @@ -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; } diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index 58cfa0d049..768841cc09 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -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 diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 34f1bdef89..56dfbdcb71 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -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 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(path.size()), path.data(), aznumeric_cast(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 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) { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index 10b3c2f18b..4e00c0e6ec 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -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 { diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp b/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp index b9f7e87b4b..b43044f0b3 100644 --- a/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp +++ b/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp @@ -22,7 +22,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& 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"); diff --git a/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp b/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp index 6a24415ec5..ceba9d2701 100644 --- a/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp +++ b/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp @@ -12,16 +12,11 @@ #include -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& options) const { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const - { - AZ_UNUSED(title); - AZ_UNUSED(message); - AZ_UNUSED(options); - return ""; - } + return {}; } } diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm b/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm index 4af67a1d54..801adaf4ea 100644 --- a/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm +++ b/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm @@ -26,7 +26,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { __block NSModalResponse response = -1; diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp index a5dd65512f..f88cea5313 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp @@ -245,7 +245,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { if (options.size() >= MAX_ITEMS) { diff --git a/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm b/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm index 835a7fb5e7..62f07f7483 100644 --- a/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm +++ b/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm @@ -18,7 +18,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { __block AZStd::string userSelection = ""; diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index 4b75a3d1cf..ba313812ce 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -175,7 +175,7 @@ namespace AzFramework } // Initializes the IArchive for reading archive(.pak) files - if (auto archive = AZ::Interface::Get(); !archive) + if (auto archive = AZ::Interface::Get(); archive == nullptr) { m_archive = AZStd::make_unique(); AZ::Interface::Register(m_archive.get()); @@ -189,6 +189,12 @@ namespace AzFramework SetFileIOAliases(); } + if (auto nativeUI = AZ::Interface::Get(); nativeUI == nullptr) + { + m_nativeUI = AZStd::make_unique(); + AZ::Interface::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::Get() == m_nativeUI.get()) + { + AZ::Interface::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(), azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), @@ -372,7 +382,6 @@ namespace AzFramework azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.h b/Code/Framework/AzFramework/AzFramework/Application/Application.h index fdc0ddcfb7..4d7e45a423 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.h +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,7 @@ namespace AzFramework AZStd::unique_ptr m_archiveFileIO; ///> The Default file IO instance is a ArchiveFileIO. AZStd::unique_ptr m_archive; ///> The AZ::IO::Instance AZStd::unique_ptr m_pimpl; + AZStd::unique_ptr m_nativeUI; bool m_ownsConsole = false; bool m_exitMainLoopRequested = false; diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp b/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp index 618fd92ac1..727d5051fa 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp @@ -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; } diff --git a/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp index 7ab61df70e..a221d126bd 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include namespace AzFramework @@ -50,36 +50,34 @@ namespace AzFramework void AzFrameworkConfigurationSystemComponent::Activate() { - // Create the defaults scene and associate the GameEntityContext with it. - AZ::Outcome createSceneOutcome = AZ::Failure("SceneSystemRequests bus not responding."); - SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequests::CreateScene, "default"); + AZ::Outcome, AZStd::string> createSceneOutcome = + SceneSystemInterface::Get()->CreateScene(Scene::MainSceneName); if (createSceneOutcome) { - Scene* scene = createSceneOutcome.GetValue(); - bool success = false; - EntityContextId gameEntityContextId = EntityContextId::CreateNull(); - GameEntityContextRequestBus::BroadcastResult(gameEntityContextId, &GameEntityContextRequests::GetGameEntityContextId); - - if (!gameEntityContextId.IsNull()) + AZStd::shared_ptr scene = createSceneOutcome.TakeValue(); + EntityContext* gameEntityContext = nullptr; + GameEntityContextRequestBus::BroadcastResult(gameEntityContext, &GameEntityContextRequests::GetGameEntityContextInstance); + if (gameEntityContext != nullptr) { - SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequests::SetSceneForEntityContextId, gameEntityContextId, scene); + [[maybe_unused]] bool result = scene->SetSubsystem(gameEntityContext); + AZ_Assert(result, "Unable to register main entity context with the main scene."); + } + else + { + AZ_Assert(false, "Unable to retrieve the game entity context instance."); } - AZ_Assert(success, "The application was unable to setup a scene for the game entity context, this should always work"); } else { - AZ_Assert(false, "%s", createSceneOutcome.GetError().data()); + AZ_Assert(false, "Unable to create main scene due to: %s", createSceneOutcome.GetError().c_str()); } } void AzFrameworkConfigurationSystemComponent::Deactivate() { - bool success = false; - SceneSystemRequestBus::BroadcastResult( - success, &AzFramework::SceneSystemRequestBus::Events::RemoveScene, "default"); - - AZ_Assert(success, "\"default\" scene was not removed"); + [[maybe_unused]] bool success = SceneSystemInterface::Get()->RemoveScene(Scene::MainSceneName); + AZ_Assert(success, "Unable to remove the main scene."); } void AzFrameworkConfigurationSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp index ad3173ed56..60c70a25bb 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "EntityContext.h" @@ -37,6 +39,30 @@ namespace AzFramework } } + AZStd::shared_ptr EntityContext::FindContainingScene(const EntityContextId& contextId) + { + auto sceneSystem = SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Attempting to retrieve the scene containing a entity context before the scene system is available."); + + AZStd::shared_ptr result; + sceneSystem->IterateActiveScenes([&result, &contextId](const AZStd::shared_ptr& scene) + { + EntityContext** entityContext = scene->FindSubsystemInScene(); + if (entityContext && (*entityContext)->GetContextId() == contextId) + { + result = scene; + // Result found, returning. + return false; + } + else + { + // No match, continuing to search for containing scene. + return true; + } + }); + return result; + } + //========================================================================= // EntityContext ctor //========================================================================= diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h index f59a40f52b..c44429b6de 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,7 @@ namespace AZ namespace AzFramework { - class EntityContext; + class Scene; /** * Provides services for a group of entities under the umbrella of a given context. @@ -47,9 +48,11 @@ namespace AzFramework , public EntityOwnershipServiceNotificationBus::Handler { public: - AZ_TYPE_INFO(EntityContext, "{4F98A6B9-C7B5-450E-8A8A-30EEFC411EF5}"); + /// The type used to store entity in AzFramework::Scene. + using SceneStorageType = EntityContext*; + EntityContext(AZ::SerializeContext* serializeContext = nullptr); EntityContext(const EntityContextId& contextId, AZ::SerializeContext* serializeContext = nullptr); EntityContext(const EntityContextId& contextId, AZStd::unique_ptr entityOwnershipService, @@ -75,6 +78,7 @@ namespace AzFramework ////////////////////////////////////////////////////////////////////////// static void Reflect(AZ::ReflectContext* context); + static AZStd::shared_ptr FindContainingScene(const EntityContextId& contextId); protected: diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h index ac638127ff..eb3a03ab51 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h @@ -66,6 +66,8 @@ namespace AzFramework */ virtual EntityContextId GetGameEntityContextId() = 0; + virtual EntityContext* GetGameEntityContextInstance() = 0; + /** * Creates an entity in the game context. * @param name A name for the new entity. diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h index 3f15027ac7..482b2133ca 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h @@ -51,6 +51,7 @@ namespace AzFramework ////////////////////////////////////////////////////////////////////////// // GameEntityContextRequestBus AZ::Uuid GetGameEntityContextId() override { return GetContextId(); } + EntityContext* GetGameEntityContextInstance() override { return this; } void ResetGameContext() override; AZ::Entity* CreateGameEntity(const char* name) override; BehaviorEntity CreateGameEntityForBehaviorContext(const char* name) override; diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index 7e968ffcd8..ea8fd75cfd 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -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)) diff --git a/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp b/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp index 1d55ec9711..23d74f7578 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp +++ b/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp @@ -14,9 +14,9 @@ #include #include +#include #include #include -#include #include #include @@ -30,11 +30,11 @@ namespace AzFramework { IntersectorBus::Handler::BusConnect(m_contextId); IntersectionNotificationBus::Handler::BusConnect(m_contextId); - Scene* scene = nullptr; - SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, m_contextId); + + AZStd::shared_ptr scene = EntityContext::FindContainingScene(m_contextId); if (scene) { - scene->SetSubsystem(this); + scene->SetSubsystem(this); } } @@ -42,11 +42,12 @@ namespace AzFramework { IntersectorBus::Handler::BusDisconnect(); IntersectionNotificationBus::Handler::BusDisconnect(); - Scene* scene = nullptr; - SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, m_contextId); + + AZStd::shared_ptr scene = EntityContext::FindContainingScene(m_contextId); if (scene) { - scene->UnsetSubsystem(); + [[maybe_unused]] bool result = scene->UnsetSubsystem(this); + AZ_Assert(result, "Failed to unregister Intersector with scene"); } } diff --git a/Code/Framework/AzFramework/AzFramework/Render/Intersector.h b/Code/Framework/AzFramework/AzFramework/Render/Intersector.h index 5852310c21..65ba6b0ea9 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/Intersector.h +++ b/Code/Framework/AzFramework/AzFramework/Render/Intersector.h @@ -33,6 +33,8 @@ namespace AzFramework , protected IntersectionNotificationBus::Handler { public: + AZ_TYPE_INFO(AzFramework::RenderGeometry::Intersector, "{4CCA7971-CD83-4856-ADEA-89CEB41FB197}"); + Intersector(AzFramework::EntityContextId contextId); ~Intersector(); diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp b/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp index 98905b4574..5bdfb94fa1 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp @@ -14,13 +14,102 @@ namespace AzFramework { - Scene::Scene(AZStd::string_view name) - : m_name(name) + Scene::Scene(AZStd::string name) + : m_name(AZStd::move(name)) { } - const AZStd::string& Scene::GetName() + Scene::Scene(AZStd::string name, AZStd::shared_ptr parent) + : m_name(AZStd::move(name)) + , m_parent(AZStd::move(parent)) + { + } + + Scene::~Scene() + { + m_removalEvent.Signal(*this, RemovalEventType::Destroyed); + } + + const AZStd::string& Scene::GetName() const { return m_name; } + + const AZStd::shared_ptr& Scene::GetParent() + { + return m_parent; + } + + AZStd::shared_ptr Scene::GetParent() const + { + return m_parent; + } + + bool Scene::IsAlive() const + { + return m_isAlive; + } + + void Scene::ConnectToEvents(RemovalEvent::Handler& handler) + { + handler.Connect(m_removalEvent); + } + + void Scene::ConnectToEvents(SubsystemEvent::Handler& handler) + { + handler.Connect(m_subsystemEvent); + } + + AZStd::any* Scene::FindSubsystem(const AZ::TypeId& typeId) + { + AZStd::any* result = FindSubsystemInScene(typeId); + return (!result && m_parent) ? m_parent->FindSubsystem(typeId) : result; + } + + const AZStd::any* Scene::FindSubsystem(const AZ::TypeId& typeId) const + { + return const_cast(this)->FindSubsystem(typeId); + } + + AZStd::any* Scene::FindSubsystemInScene(const AZ::TypeId& typeId) + { + // Spot check that the internal arrays remain consistent. + AZ_Assert( + m_systemKeys.size() == m_systemObjects.size(), "Key and object list in AzFramework::Scene '%s' have gone out of sync.", + m_name.c_str()); + + const size_t m_systemKeysCount = m_systemKeys.size(); + for (size_t i = 0; i < m_systemKeysCount; ++i) + { + if (m_systemKeys[i] != typeId) + { + continue; + } + else + { + return &m_systemObjects[i]; + } + } + return nullptr; + } + + const AZStd::any* Scene::FindSubsystemInScene(const AZ::TypeId& typeId) const + { + return const_cast(this)->FindSubsystemInScene(typeId); + } + + void Scene::MarkForDestruction() + { + m_isAlive = false; + m_removalEvent.Signal(*this, RemovalEventType::Zombified); + } + + void Scene::RemoveSubsystem(size_t index, const AZ::TypeId& subsystemType) + { + m_systemKeys[index] = m_systemKeys.back(); + m_systemObjects[index] = AZStd::move(m_systemObjects.back()); + m_systemKeys.pop_back(); + m_systemObjects.pop_back(); + m_subsystemEvent.Signal(*this, SubsystemEventType::Removed, subsystemType); + } } diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.h b/Code/Framework/AzFramework/AzFramework/Scene/Scene.h index 6b365dae0f..78fea316eb 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/Scene.h +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.h @@ -11,10 +11,14 @@ */ #pragma once +#include #include #include #include +#include #include +#include +#include namespace AzFramework { @@ -24,71 +28,100 @@ namespace AzFramework AZ_TYPE_INFO(Scene, "{DB449BB3-7A95-434D-BC61-47ACBB1F3436}"); AZ_CLASS_ALLOCATOR(Scene, AZ::SystemAllocator, 0); - explicit Scene(AZStd::string_view name); + friend class ISceneSystem; - const AZStd::string& GetName(); + constexpr static AZStd::string_view MainSceneName = "Main"; + constexpr static AZStd::string_view EditorMainSceneName = "Editor"; + + enum class RemovalEventType + { + Zombified, // The scene has be marked for destruction and is no longer visible in the scene system. + Destroyed, // The scene has been destroyed. + }; + using RemovalEvent = AZ::Event; + enum class SubsystemEventType + { + Added, + Removed + }; + using SubsystemEvent = AZ::Event; + + explicit Scene(AZStd::string name); + Scene(AZStd::string name, AZStd::shared_ptr parent); + ~Scene(); + + [[nodiscard]] const AZStd::string& GetName() const; + + [[nodiscard]] const AZStd::shared_ptr& GetParent(); + [[nodiscard]] AZStd::shared_ptr GetParent() const; + + [[nodiscard]] bool IsAlive() const; + + void ConnectToEvents(RemovalEvent::Handler& handler); + void ConnectToEvents(SubsystemEvent::Handler& handler); // Set the instance of a subsystem associated with this scene. template - bool SetSubsystem(T* system); + bool SetSubsystem(T&& system); // Unset the instance of a subsystem associated with this scene. template bool UnsetSubsystem(); - // Get the instance of a subsystem associated with this scene. + // Unset the instance of the exact system associated with this scene. + // Use this to make sure the expected instance is removed or to make sure type deduction is done in the same way as during setting. + template + bool UnsetSubsystem(const T& system); + + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] AZStd::any* FindSubsystem(const AZ::TypeId& typeId); + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] const AZStd::any* FindSubsystem(const AZ::TypeId& typeId) const; + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. template - T* GetSubsystem(); + [[nodiscard]] T* FindSubsystem(); + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. + template + [[nodiscard]] const T* FindSubsystem() const; + + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] AZStd::any* FindSubsystemInScene(const AZ::TypeId& typeId); + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] const AZStd::any* FindSubsystemInScene(const AZ::TypeId& typeId) const; + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + template + [[nodiscard]] T* FindSubsystemInScene(); + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + template + [[nodiscard]] const T* FindSubsystemInScene() const; private: + void MarkForDestruction(); + void RemoveSubsystem(size_t index, const AZ::TypeId& subsystemType); - AZStd::string m_name; + RemovalEvent m_removalEvent; + SubsystemEvent m_subsystemEvent; // Storing keys separate from data to optimize for fast key search. AZStd::vector m_systemKeys; - AZStd::vector m_systemPointers; + AZStd::vector m_systemObjects; + + // Name that identifies the scene. + AZStd::string m_name; + // Parent to this scene. Any subsystems are inherited from the parent but can be overwritten locally. + AZStd::shared_ptr m_parent; + // If false, the scene has been removed from scene system and can no longer be found. As soon as all handles to the scene are + // released it will be destroyed. + bool m_isAlive{ true }; }; - - template - bool Scene::SetSubsystem(T* system) - { - if (GetSubsystem() != nullptr) - { - return false; - } - m_systemKeys.push_back(T::RTTI_Type()); - m_systemPointers.push_back(system); - return true; - } - - template - bool Scene::UnsetSubsystem() - { - for (size_t i = 0; i < m_systemKeys.size(); ++i) - { - if (m_systemKeys.at(i) == T::RTTI_Type()) - { - m_systemKeys.at(i) = m_systemKeys.back(); - m_systemKeys.pop_back(); - m_systemPointers.at(i) = m_systemPointers.back(); - m_systemPointers.pop_back(); - return true; - } - } - return false; - } - - template - T* Scene::GetSubsystem() - { - for (size_t i = 0; i < m_systemKeys.size(); ++i) - { - if (m_systemKeys.at(i) == T::RTTI_Type()) - { - return reinterpret_cast(m_systemPointers.at(i)); - } - } - return nullptr; - } - } // AzFramework + +#include diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl new file mode 100644 index 0000000000..b0c1a18b08 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl @@ -0,0 +1,108 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +namespace AzFramework +{ + template + bool Scene::SetSubsystem(T&& system) + { + const AZ::TypeId& targetType = azrtti_typeid(); + for (const AZ::TypeId& key : m_systemKeys) + { + if (key == targetType) + { + return false; + } + } + + m_systemKeys.push_back(targetType); + m_systemObjects.emplace_back(AZStd::forward(system)); + m_subsystemEvent.Signal(*this, SubsystemEventType::Added, targetType); + return true; + } + + template + bool Scene::UnsetSubsystem() + { + const AZ::TypeId& targetType = azrtti_typeid(); + const size_t m_systemKeysCount = m_systemKeys.size(); + for (size_t i = 0; i < m_systemKeysCount; ++i) + { + if (m_systemKeys[i] != targetType) + { + continue; + } + else + { + RemoveSubsystem(i, targetType); + return true; + } + } + return false; + } + + template + bool Scene::UnsetSubsystem(const T& system) + { + const AZ::TypeId& targetType = azrtti_typeid(); + const size_t systemKeysCount = m_systemKeys.size(); + for (size_t i = 0; i < systemKeysCount; ++i) + { + if (m_systemKeys[i] != targetType) + { + continue; + } + else + { + [[maybe_unused]] T* instance = AZStd::any_cast(&m_systemObjects[i]); + AZ_Assert( + instance && *instance == system, + "Subsystem being released matched type, but wasn't pointing to the same system that was stored."); + RemoveSubsystem(i, targetType); + return true; + } + } + return false; + } + + template + T* Scene::FindSubsystem() + { + const AZ::TypeId& targetType = azrtti_typeid(); + AZStd::any* subSystem = FindSubsystem(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } + + template + const T* Scene::FindSubsystem() const + { + const AZ::TypeId& targetType = azrtti_typeid(); + const AZStd::any* subSystem = FindSubsystem(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } + + template + T* Scene::FindSubsystemInScene() + { + const AZ::TypeId& targetType = azrtti_typeid(); + AZStd::any* subSystem = FindSubsystemInScene(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } + + template + const T* Scene::FindSubsystemInScene() const + { + const AZ::TypeId& targetType = azrtti_typeid(); + const AZStd::any* subSystem = FindSubsystemInScene(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h deleted file mode 100644 index c75a8ceb9a..0000000000 --- a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ -#pragma once - -#include -#include - -namespace AzFramework -{ - // Forward declarations - class Scene; - - //! Interface used to create, get, or destroy scenes. - class SceneSystemRequests - : public AZ::EBusTraits - { - public: - - virtual ~SceneSystemRequests() = default; - - //! Single handler policy since there should only be one instance of this system component. - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - - //! Creates a scene with a given name. - //! - If there is already a scene with the provided name this will return AZ::Failure(). - //! - If isDefault is set to true and there is already a default scene, the default scene will be switched to this one. - virtual AZ::Outcome CreateScene(AZStd::string_view name) = 0; - - //! Gets a scene with a given name - //! - If a scene does not exist with the given name, nullptr is returned. - virtual Scene* GetScene(AZStd::string_view name) = 0; - - //! Gets all the scenes that currently exist. - virtual AZStd::vector GetAllScenes() = 0; - - //! Remove a scene with a given name and return if the operation was successful. - //! - If the removed scene is the default scene, there will no longer be a default scene. - virtual bool RemoveScene(AZStd::string_view name) = 0; - - //! Add a mapping from the provided EntityContextId to a Scene - //! - If a scene is already associated with this EntityContextId, nothing is changed and false is returned. - virtual bool SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) = 0; - - //! Remove a mapping from the provided EntityContextId to a Scene - //! - If no scene is found from the provided EntityContextId, false is returned. - virtual bool RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) = 0; - - //! Get the scene associated with an EntityContextId - //! - If no scene is found for the provided EntityContextId, nullptr is returned. - virtual Scene* GetSceneFromEntityContextId(EntityContextId entityContextId) = 0; - }; - - using SceneSystemRequestBus = AZ::EBus; - - //! Interface used for notifications from the scene system - class SceneSystemNotifications - : public AZ::EBusTraits - { - public: - - virtual ~SceneSystemNotifications() = default; - - //! There can be multiple listeners to changes in the scene system. - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Called when a scene has been created. - virtual void SceneCreated(Scene& /*scene*/) {}; - - //! Called just before a scene is removed. - virtual void SceneAboutToBeRemoved(Scene& /*scene*/) {}; - - }; - - using SceneSystemNotificationBus = AZ::EBus; - - //! Interface used for notifications about individual scenes - class SceneNotifications - : public AZ::EBusTraits - { - public: - - virtual ~SceneNotifications() = default; - - //! There can be multiple listeners to changes in the scene system. - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Bus is listened to using the pointer of the scene - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; - - //! Specifies that events are addressed by the pointer to the scene - using BusIdType = Scene*; - - //! Called just before a scene is removed. - virtual void SceneAboutToBeRemoved() {}; - - //! Called when an entity context is mapped to this scene. - virtual void EntityContextMapped(EntityContextId /*entityContextId*/) {}; - - //! Called when an entity context is unmapped from this scene. - virtual void EntityContextUnmapped(EntityContextId /*entityContextId*/) {}; - }; - - using SceneNotificationBus = AZ::EBus; - -} // AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp index 909880ff55..e677be4643 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace AzFramework { @@ -41,14 +41,10 @@ namespace AzFramework void SceneSystemComponent::Activate() { - // Connect busses - SceneSystemRequestBus::Handler::BusConnect(); } void SceneSystemComponent::Deactivate() { - // Disconnect Busses - SceneSystemRequestBus::Handler::BusDisconnect(); } void SceneSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) @@ -61,140 +57,105 @@ namespace AzFramework incompatible.push_back(AZ_CRC("SceneSystemComponentService", 0xd8975435)); } - AZ::Outcome SceneSystemComponent::CreateScene(AZStd::string_view name) + AZ::Outcome, AZStd::string> SceneSystemComponent::CreateScene(AZStd::string_view name) { - Scene* existingScene = GetScene(name); + return CreateSceneWithParent(name, nullptr); + } + AZ::Outcome, AZStd::string> SceneSystemComponent::CreateSceneWithParent( + AZStd::string_view name, AZStd::shared_ptr parent) + { + const AZStd::shared_ptr& existingScene = GetScene(name); if (existingScene) { return AZ::Failure("A scene already exists with this name."); } - auto newScene = AZStd::make_unique(name); - Scene* scenePointer = newScene.get(); - m_scenes.push_back(AZStd::move(newScene)); - SceneSystemNotificationBus::Broadcast(&SceneSystemNotificationBus::Events::SceneCreated, *scenePointer); - return AZ::Success(scenePointer); + auto newScene = AZStd::make_shared(name, AZStd::move(parent)); + m_activeScenes.push_back(newScene); + { + AZStd::lock_guard lock(m_eventMutex); + m_events.Signal(EventType::SceneCreated, newScene); + } + return AZ::Success(AZStd::move(newScene)); } - Scene* SceneSystemComponent::GetScene(AZStd::string_view name) + AZStd::shared_ptr SceneSystemComponent::GetScene(AZStd::string_view name) { - auto sceneIterator = AZStd::find_if(m_scenes.begin(), m_scenes.end(), + auto sceneIterator = AZStd::find_if(m_activeScenes.begin(), m_activeScenes.end(), [name](auto& scene) -> bool { return scene->GetName() == name; } ); - return sceneIterator == m_scenes.end() ? nullptr : sceneIterator->get(); + return sceneIterator == m_activeScenes.end() ? nullptr : *sceneIterator; } - AZStd::vector SceneSystemComponent::GetAllScenes() + void SceneSystemComponent::IterateActiveScenes(const ActiveIterationCallback& callback) { - AZStd::vector scenes; - scenes.resize_no_construct(m_scenes.size()); - - for (size_t i = 0; i < m_scenes.size(); ++i) + bool keepGoing = true; + auto end = m_activeScenes.end(); + for (auto it = m_activeScenes.begin(); it != end && keepGoing; ++it) { - scenes.at(i) = m_scenes.at(i).get(); + keepGoing = callback(*it); + } + } + + void SceneSystemComponent::IterateZombieScenes(const ZombieIterationCallback& callback) + { + bool keepGoing = true; + auto end = m_zombieScenes.end(); + for (auto it = m_zombieScenes.begin(); it != end && keepGoing;) + { + if (!it->expired()) + { + keepGoing = callback(*(it->lock())); + ++it; + } + else + { + *it = m_zombieScenes.back(); + m_zombieScenes.pop_back(); + end = m_zombieScenes.end(); + } } - return scenes; } bool SceneSystemComponent::RemoveScene(AZStd::string_view name) { - for (size_t i = 0; i < m_scenes.size(); ++i) + for (AZStd::shared_ptr& scene : m_activeScenes) { - auto& scenePtr = m_scenes.at(i); - if (scenePtr->GetName() == name) + if (scene->GetName() == name) { - // Remove any entityContext mappings. - Scene* scene = scenePtr.get(); - for (auto entityContextScenePairIt = m_entityContextToScenes.begin(); entityContextScenePairIt != m_entityContextToScenes.end();) + MarkSceneForDestruction(*scene); { - AZStd::pair& pair = *entityContextScenePairIt; - if (pair.second == scene) - { - // swap and pop back. - *entityContextScenePairIt = m_entityContextToScenes.back(); - m_entityContextToScenes.pop_back(); - } - else - { - ++entityContextScenePairIt; - } + AZStd::lock_guard lock(m_eventMutex); + m_events.Signal(EventType::ScenePendingRemoval, scene); } - SceneSystemNotificationBus::Broadcast(&SceneSystemNotificationBus::Events::SceneAboutToBeRemoved, *scene); - SceneNotificationBus::Event(scene, &SceneNotificationBus::Events::SceneAboutToBeRemoved); - - m_scenes.erase(&scenePtr); + // Zombies are weak pointers that are kept around for situations where there's a delay in deleting the scene. This can happen + // if there are outstanding calls like in-progress async calls or resources locked by hardware. A weak_ptr of the original + // scene is kept so the zombie scene can still be found through iteration as it may require additional calls such as Tick calls. + m_zombieScenes.push_back(scene); + scene = AZStd::move(m_activeScenes.back()); + m_activeScenes.pop_back(); + // The scene may not be held onto anymore, so check here to see if the previously added zombie can be released. + if (m_zombieScenes.back().expired()) + { + m_zombieScenes.pop_back(); + } return true; } } - AZ_Warning("SceneSystemComponent", false, "Attempting to remove scene name \"%.*s\", but that scene was not found.", static_cast(name.size()), name.data()); + AZ_Warning("SceneSystemComponent", false, R"(Attempting to remove scene name "%.*s", but that scene was not found.)", AZ_STRING_ARG(name)); return false; } - bool SceneSystemComponent::SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) + void SceneSystemComponent::ConnectToEvents(SceneEvent::Handler& handler) { - Scene* existingSceneForEntityContext = GetSceneFromEntityContextId(entityContextId); - if (existingSceneForEntityContext) - { - // This entity context is already mapped and must be unmapped explictely before it can be changed. - char entityContextIdString[EntityContextId::MaxStringBuffer]; - entityContextId.ToString(entityContextIdString, sizeof(entityContextIdString)); - AZ_Warning("SceneSystemComponent", false, "Failed to set a scene for entity context %s, scene is already set for that entity context.", entityContextIdString); - - return false; - } - m_entityContextToScenes.emplace_back(entityContextId, scene); - SceneNotificationBus::Event(scene, &SceneNotificationBus::Events::EntityContextMapped, entityContextId); - return true; + AZStd::lock_guard lock(m_eventMutex); + handler.Connect(m_events); } - - bool SceneSystemComponent::RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) - { - if (!scene || entityContextId.IsNull()) - { - return false; - } - - for (auto entityContextScenePairIt = m_entityContextToScenes.begin(); entityContextScenePairIt != m_entityContextToScenes.end();) - { - AZStd::pair& pair = *entityContextScenePairIt; - if (!(pair.first == entityContextId && pair.second == scene)) - { - ++entityContextScenePairIt; - } - else - { - // swap and pop back. - *entityContextScenePairIt = m_entityContextToScenes.back(); - m_entityContextToScenes.pop_back(); - - SceneNotificationBus::Event(scene, &SceneNotificationBus::Events::EntityContextUnmapped, entityContextId); - return true; - } - } - - char entityContextIdString[EntityContextId::MaxStringBuffer]; - entityContextId.ToString(entityContextIdString, sizeof(entityContextIdString)); - AZ_Warning("SceneSystemComponent", false, "Failed to remove scene \"%.*s\" for entity context %s, entity context is not currently mapped to that scene.", static_cast(scene->GetName().size()), scene->GetName().data(), entityContextIdString); - return false; - } - - Scene* SceneSystemComponent::GetSceneFromEntityContextId(EntityContextId entityContextId) - { - for (AZStd::pair& pair : m_entityContextToScenes) - { - if (pair.first == entityContextId) - { - return pair.second; - } - } - return nullptr; - } - -} // AzFramework +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h index 085efcd898..a5497bdb87 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h @@ -13,18 +13,18 @@ #include #include -#include +#include +#include #include namespace AzFramework { class SceneSystemComponent : public AZ::Component - , public SceneSystemRequestBus::Handler + , public SceneSystemInterface::Registrar { public: - - AZ_COMPONENT(SceneSystemComponent, "{7AC53AF0-BE1A-437C-BE3E-4D6A998DA945}", AZ::Component); + AZ_COMPONENT(SceneSystemComponent, "{7AC53AF0-BE1A-437C-BE3E-4D6A998DA945}", AZ::Component, ISceneSystem); SceneSystemComponent(); ~SceneSystemComponent() override; @@ -41,24 +41,26 @@ namespace AzFramework static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); ////////////////////////////////////////////////////////////////////////// - // SceneSystemRequestsBus::Handler + // SceneSystemInterface overrides ////////////////////////////////////////////////////////////////////////// - AZ::Outcome CreateScene(AZStd::string_view name) override; - Scene* GetScene(AZStd::string_view name) override; - AZStd::vector GetAllScenes() override; + AZ::Outcome, AZStd::string> CreateScene(AZStd::string_view name) override; + AZ::Outcome, AZStd::string> CreateSceneWithParent( + AZStd::string_view name, AZStd::shared_ptr parent) override; + [[nodiscard]] AZStd::shared_ptr GetScene(AZStd::string_view name) override; + void IterateActiveScenes(const ActiveIterationCallback& callback) override; + void IterateZombieScenes(const ZombieIterationCallback& callback) override; bool RemoveScene(AZStd::string_view name) override; - bool SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) override; - bool RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) override; - Scene* GetSceneFromEntityContextId(EntityContextId entityContextId) override; + void ConnectToEvents(SceneEvent::Handler& handler) override; private: + AZ_DISABLE_COPY_MOVE(SceneSystemComponent); - AZ_DISABLE_COPY(SceneSystemComponent); - - // Container of scene in order of creation - AZStd::vector> m_scenes; - - // Map of entity context Ids to scenes. Using a vector because lookups will be common, but the size will be small. - AZStd::vector> m_entityContextToScenes; + AZStd::vector> m_activeScenes; + AZStd::vector> m_zombieScenes; + // Using a mutex around the events as other threads may respond to a new/deleted scene by making + // local updates and unregistering themselves. Since Scene is single threaded, no updates (other + // then unregistering an event) should be done from other threads though. + AZStd::recursive_mutex m_eventMutex; + SceneEvent m_events; }; } diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h new file mode 100644 index 0000000000..48dca7ed29 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h @@ -0,0 +1,88 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace AzFramework +{ + //! Interface used to create, get, or destroy scenes. + //! This interface is single thread and is intended to be called from a single thread, commonly the main thread. The exception + //! is connecting events, which is thread safe. + class ISceneSystem + { + public: + AZ_RTTI(AzFramework::ISceneSystem, "{DAE482A8-88AE-4BD3-8A5B-52D19A96E15F}"); + AZ_DISABLE_COPY_MOVE(ISceneSystem); + + enum class EventType + { + SceneCreated, + ScenePendingRemoval + }; + using SceneEvent = AZ::Event&>; + + ISceneSystem() = default; + virtual ~ISceneSystem() = default; + + using ActiveIterationCallback = AZStd::function& scene)>; + using ZombieIterationCallback = AZStd::function; + + //! Creates a scene with a given name. + //! - If there is already a scene with the provided name this will return AZ::Failure(). + virtual AZ::Outcome, AZStd::string> CreateScene(AZStd::string_view name) = 0; + + //! Creates a scene with a given name and a parent. + //! - If there is already a scene with the provided name this will return AZ::Failure(). + virtual AZ::Outcome, AZStd::string> CreateSceneWithParent( + AZStd::string_view name, AZStd::shared_ptr parent) = 0; + + //! Gets a scene with a given name + //! - If a scene does not exist with the given name, nullptr is returned. + [[nodiscard]] virtual AZStd::shared_ptr GetScene(AZStd::string_view name) = 0; + + //! Iterates over all scenes that are in active use. Iteration stops if the callback returns false or all scenes have been listed. + virtual void IterateActiveScenes(const ActiveIterationCallback& callback) = 0; + //! Iterates over all zombie scenes. Zombie scenes are scenes that have been removed but still have references held on to. This can + //! happen because scenes hold on to subsystems that can't immediately be deleted. These subsystems may still require being called + //! such as a periodic tick. Iteration stops if the callback returns false or all scenes have been listed. + virtual void IterateZombieScenes(const ZombieIterationCallback& callback) = 0; + + //! Remove a scene with a given name and return if the operation was successful. + virtual bool RemoveScene(AZStd::string_view name) = 0; + + //! Connects the provided handler to the events that are called after scenes are created or before they get removed. + virtual void ConnectToEvents(SceneEvent::Handler& handler) = 0; + + protected: + // Strictly a forwarding function to call private functions on the scene. + void MarkSceneForDestruction(Scene& scene) { scene.MarkForDestruction(); } + }; + + using SceneSystemInterface = AZ::Interface; + + // EBus wrapper for ScriptCanvas + class ISceneSystemRequests + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + }; + using ILoggerRequestBus = AZ::EBus; +} // AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index 312a3766ac..b126a192ac 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -194,10 +194,11 @@ set(FILES Logging/MissingAssetLogger.h Logging/MissingAssetNotificationBus.h Scene/Scene.h + Scene/Scene.inl Scene/Scene.cpp - Scene/SceneSystemBus.h Scene/SceneSystemComponent.h Scene/SceneSystemComponent.cpp + Scene/SceneSystemInterface.h Script/ScriptComponent.h Script/ScriptComponent.cpp Script/ScriptDebugAgentBus.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 50315e9d7a..ed7fb1515f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -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(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h index cee47f55ef..7d08d87c3b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h @@ -49,6 +49,8 @@ namespace AzToolsFramework /// Retrieve the Id of the editor entity context. virtual AzFramework::EntityContextId GetEditorEntityContextId() = 0; + virtual AzFramework::EntityContext* GetEditorEntityContextInstance() = 0; + /// Creates an entity in the editor context. /// \return the EntityId for the created Entity virtual AZ::EntityId CreateNewEditorEntity(const char* name) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h index 9a9a2dcff0..2313f27437 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h @@ -77,6 +77,7 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // EditorEntityContextRequestBus AzFramework::EntityContextId GetEditorEntityContextId() override { return GetContextId(); } + AzFramework::EntityContext* GetEditorEntityContextInstance() override { return this; } void ResetEditorContext() override; AZ::EntityId CreateNewEditorEntity(const char* name) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp index 9a191f93de..089037bbf3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp @@ -769,12 +769,12 @@ namespace AzToolsFramework template void EditorVertexSelectionBase::DisplayViewport2d( - const AzFramework::ViewportInfo& /*viewportInfo*/, + const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); - m_editorBoxSelect.Display2d(debugDisplay); + m_editorBoxSelect.Display2d(viewportInfo, debugDisplay); } template diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp index 9fda3fa291..f3c6a014cd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include @@ -56,22 +56,47 @@ namespace AzToolsFramework void AzToolsFrameworkConfigurationSystemComponent::Activate() { - // Associate the EditorEntityContext with the default scene. + // Create the editor specific child scene to the main scene and add the editor entity context to it. AzFramework::EntityContextId editorEntityContextId; EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); - AzFramework::Scene* defaultScene = nullptr; - AzFramework::SceneSystemRequestBus::BroadcastResult(defaultScene, &AzFramework::SceneSystemRequests::GetScene, "default"); - - if (!editorEntityContextId.IsNull() && defaultScene) + if (!editorEntityContextId.IsNull()) { - bool success = false; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequests::SetSceneForEntityContextId, editorEntityContextId, defaultScene); + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Scene system not available to create the editor scene."); + AZStd::shared_ptr mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName); + if (mainScene) + { + AZ::Outcome, AZStd::string> editorScene = + sceneSystem->CreateSceneWithParent(AzFramework::Scene::EditorMainSceneName, mainScene); + if (editorScene.IsSuccess()) + { + AzFramework::EntityContext* editorEntityContext = nullptr; + EditorEntityContextRequestBus::BroadcastResult( + editorEntityContext, &EditorEntityContextRequests::GetEditorEntityContextInstance); + if (editorEntityContext != nullptr) + { + [[maybe_unused]] bool contextAdded = + editorScene.GetValue()->SetSubsystem(editorEntityContext); + AZ_Assert(contextAdded, "Unable to add editor entity context to scene."); + } + } + else + { + AZ_Assert(false, "Failed to create editor scene because: %s", editorScene.GetError().c_str()); + } + } + else + { + AZ_Assert(false, "No main scene to parent the editor scene under."); + } } } void AzToolsFrameworkConfigurationSystemComponent::Deactivate() { + [[maybe_unused]] bool success = AzFramework::SceneSystemInterface::Get()->RemoveScene(AzFramework::Scene::EditorMainSceneName); + AZ_Assert(success, "Unable to remove the main editor scene."); } void AzToolsFrameworkConfigurationSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp index d9cf4af944..2e467caa4c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp @@ -13,6 +13,7 @@ #include "EditorBoxSelect.h" #include +#include #include @@ -72,7 +73,7 @@ namespace AzToolsFramework m_previousModifiers = mouseInteraction.m_mouseInteraction.m_keyboardModifiers; } - void EditorBoxSelect::Display2d(AzFramework::DebugDisplayRequests& debugDisplay) + void EditorBoxSelect::Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -82,12 +83,15 @@ namespace AzToolsFramework debugDisplay.SetLineWidth(s_boxSelectLineWidth); debugDisplay.SetColor(s_boxSelectColor); - debugDisplay.DrawWireBox( - AZ::Vector3( - static_cast(m_boxSelectRegion->x()), static_cast(m_boxSelectRegion->y()), 0.0f), - AZ::Vector3( - static_cast(m_boxSelectRegion->x()) + static_cast(m_boxSelectRegion->width()), - static_cast(m_boxSelectRegion->y()) + static_cast(m_boxSelectRegion->height()), 0.0f)); + AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize; + + debugDisplay.DrawWireQuad2d( + AZ::Vector2( + aznumeric_cast(m_boxSelectRegion->x()), aznumeric_cast(m_boxSelectRegion->y())) / viewportSize, + AZ::Vector2( + aznumeric_cast(m_boxSelectRegion->x()) + aznumeric_cast(m_boxSelectRegion->width()), + aznumeric_cast(m_boxSelectRegion->y()) + aznumeric_cast(m_boxSelectRegion->height())) / viewportSize, + 0.f); debugDisplay.DepthTestOn(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h index d9fca58168..7f50b16325 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h @@ -42,7 +42,7 @@ namespace AzToolsFramework const ViewportInteraction::MouseInteractionEvent& mouseInteraction); /// Responsible for drawing the 2d box representing the selection in screen space. - void Display2d(AzFramework::DebugDisplayRequests& debugDisplay); + void Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay); /// Custom drawing behavior to happen during a box select. void DisplayScene( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index a558e5895d..ec22a2f7c8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -3494,7 +3494,7 @@ namespace AzToolsFramework DrawAxisGizmo(viewportInfo, debugDisplay); - m_boxSelect.Display2d(debugDisplay); + m_boxSelect.Display2d(viewportInfo, debugDisplay); } void EditorTransformComponentSelection::RefreshSelectedEntityIds() diff --git a/Code/Framework/Tests/NetBindingMocks.h b/Code/Framework/Tests/NetBindingMocks.h index 3f280383f5..a07cae0077 100644 --- a/Code/Framework/Tests/NetBindingMocks.h +++ b/Code/Framework/Tests/NetBindingMocks.h @@ -42,6 +42,7 @@ namespace UnitTest MOCK_METHOD3(InstantiateDynamicSlice, AzFramework::SliceInstantiationTicket(const AZ::Data::Asset&, const AZ::Transform&, const AZ::IdUtils::Remapper::IdMapper&)); MOCK_METHOD0(GetGameEntityContextId, AzFramework::EntityContextId()); + MOCK_METHOD0(GetGameEntityContextInstance, AzFramework::EntityContext*()); MOCK_METHOD1(CreateGameEntity, AZ::Entity*(const char*)); MOCK_METHOD1(AddGameEntity, void (AZ::Entity*)); MOCK_METHOD1(DestroyGameEntity, void (const AZ::EntityId&)); diff --git a/Code/Framework/Tests/Scene.cpp b/Code/Framework/Tests/Scene.cpp index a31dcc4c6e..a9affe3a01 100644 --- a/Code/Framework/Tests/Scene.cpp +++ b/Code/Framework/Tests/Scene.cpp @@ -130,6 +130,8 @@ namespace SceneUnitTest m_systemEntity->CreateComponent(); m_systemEntity->CreateComponent(); m_systemEntity->Activate(); + + m_sceneSystem = AzFramework::SceneSystemInterface::Get(); } void TearDown() override @@ -146,167 +148,119 @@ namespace SceneUnitTest AZ::IO::FileIOBase* m_prevFileIO; AZ::ComponentApplication m_app; AZ::Entity* m_systemEntity = nullptr; + AzFramework::ISceneSystem* m_sceneSystem = nullptr; }; TEST_F(SceneTest, CreateScene) - { - Scene* scene = nullptr; - AZ::Outcome createSceneOutcome = AZ::Failure(""); - + { // A scene should be able to be created with a given name. - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, "TestScene"); + AZ::Outcome, AZStd::string> createSceneOutcome = m_sceneSystem->CreateScene("TestScene"); EXPECT_TRUE(createSceneOutcome.IsSuccess()) << "Unable to create a scene."; // The scene pointer returned should be valid - scene = createSceneOutcome.GetValue(); - EXPECT_TRUE(scene != nullptr) << "Scene creation reported success, but no scene actually was actually returned."; + AZStd::shared_ptr scene = createSceneOutcome.TakeValue(); + EXPECT_NE(scene, nullptr) << "Scene creation reported success, but no scene actually was actually returned."; // Attempting to create another scene with the same name should fail. - createSceneOutcome = AZ::Failure(""); - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, "TestScene"); + createSceneOutcome = m_sceneSystem->CreateScene("TestScene"); EXPECT_TRUE(!createSceneOutcome.IsSuccess()) << "Should not be able to create two scenes with the same name."; } TEST_F(SceneTest, GetScene) { - Scene* createdScene = nullptr; - Scene* retrievedScene = nullptr; - Scene* nullScene = nullptr; - const static AZStd::string_view s_sceneName = "TestScene"; + constexpr AZStd::string_view sceneName = "TestScene"; - AZ::Outcome createSceneOutcome = AZ::Failure(""); - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, s_sceneName); - createdScene = createSceneOutcome.GetValue(); + AZ::Outcome, AZStd::string> createSceneOutcome = m_sceneSystem->CreateScene(sceneName); + AZStd::shared_ptr createdScene = createSceneOutcome.TakeValue(); // Should be able to get a scene by name, and it should match the scene that was created. - AzFramework::SceneSystemRequestBus::BroadcastResult(retrievedScene, &AzFramework::SceneSystemRequestBus::Events::GetScene, s_sceneName); - EXPECT_TRUE(retrievedScene != nullptr) << "Attempting to get scene by name resulted in nullptr."; - EXPECT_TRUE(retrievedScene == createdScene) << "Retrieved scene does not match created scene."; + AZStd::shared_ptr retrievedScene = m_sceneSystem->GetScene(sceneName); + EXPECT_NE(retrievedScene, nullptr) << "Attempting to get scene by name resulted in nullptr."; + EXPECT_EQ(retrievedScene, createdScene) << "Retrieved scene does not match created scene."; // An invalid name should return a null scene. - AzFramework::SceneSystemRequestBus::BroadcastResult(nullScene, &AzFramework::SceneSystemRequestBus::Events::GetScene, "non-existant scene"); - EXPECT_TRUE(nullScene == nullptr) << "Should not be able to retrieve a scene that wasn't created."; + AZStd::shared_ptr nullScene = m_sceneSystem->GetScene("non-existant scene"); + EXPECT_EQ(nullScene, nullptr) << "Should not be able to retrieve a scene that wasn't created."; } TEST_F(SceneTest, RemoveScene) { - Scene* createdScene = nullptr; - const static AZStd::string_view s_sceneName = "TestScene"; + constexpr AZStd::string_view sceneName = "TestScene"; - AZ::Outcome createSceneOutcome = AZ::Failure(""); - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, s_sceneName); - createdScene = createSceneOutcome.GetValue(); - - bool success = false; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequestBus::Events::RemoveScene, s_sceneName); + AZ::Outcome, AZStd::string> createSceneOutcome = m_sceneSystem->CreateScene(sceneName); + bool success = m_sceneSystem->RemoveScene(sceneName); EXPECT_TRUE(success) << "Failed to remove the scene that was just created."; - success = true; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequestBus::Events::RemoveScene, "non-existant scene"); + success = m_sceneSystem->RemoveScene("non-existant scene"); EXPECT_FALSE(success) << "Remove scene returned success for a non-existant scene."; } - TEST_F(SceneTest, GetAllScenes) + TEST_F(SceneTest, IterateActiveScenes) { constexpr size_t NumScenes = 5; - Scene* scenes[NumScenes] = { nullptr }; + AZStd::shared_ptr scenes[NumScenes] = {nullptr}; for (size_t i = 0; i < NumScenes; ++i) { - AZ::Outcome createSceneOutcome = AZ::Failure(""); - AZStd::string sceneName = AZStd::string::format("scene %zu", i); - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, sceneName); - scenes[i] = createSceneOutcome.GetValue(); + AZ::Outcome, AZStd::string> createSceneOutcome = m_sceneSystem->CreateScene(sceneName); + scenes[i] = createSceneOutcome.TakeValue(); } - AZStd::vector retrievedScenes; - AzFramework::SceneSystemRequestBus::BroadcastResult(retrievedScenes, &AzFramework::SceneSystemRequestBus::Events::GetAllScenes); - - EXPECT_EQ(NumScenes, retrievedScenes.size()) << "GetAllScenes() returned a different number of scenes than those created."; - - for (size_t i = 0; i < NumScenes; ++i) - { - EXPECT_EQ(scenes[i], retrievedScenes.at(i)) << "GetAllScenes() returned scenes in a different order than they were created."; - } + size_t index = 0; + m_sceneSystem->IterateActiveScenes([&index, &scenes](const AZStd::shared_ptr& scene) + { + EXPECT_EQ(scenes[index++], scene); + return true; + }); } - TEST_F(SceneTest, EntityContextSceneMapping) + TEST_F(SceneTest, IterateZombieScenes) { - AZStd::unique_ptr m_entityOwnershipService = - AZStd::make_unique(AZ::Uuid::CreateNull(), m_app.GetSerializeContext()); - // Create the entity context, entity, and component - EntityContext* testEntityContext = new EntityContext(AZ::Uuid::CreateRandom(), AZStd::move(m_entityOwnershipService)); - testEntityContext->InitContext(); - EntityContextId testEntityContextId = testEntityContext->GetContextId(); - AZ::Entity* testEntity = testEntityContext->CreateEntity("TestEntity"); - TestComponent* testComponent = testEntity->CreateComponent(); + constexpr size_t NumScenes = 5; - // Try to activate an entity and get the scene before a scene has been set. This should fail. - TestComponentConfig failConfig; - failConfig.m_activateFunction = [](TestComponent* component) + AZStd::shared_ptr scenes[NumScenes] = {nullptr}; + + // Create zombies. + for (size_t i = 0; i < NumScenes; ++i) { - (void)component; - Scene* scene = nullptr; - EntityContextId entityContextId = EntityContextId::CreateNull(); + AZStd::string sceneName = AZStd::string::format("scene %zu", i); + AZ::Outcome, AZStd::string> createSceneOutcome = m_sceneSystem->CreateScene(sceneName); + scenes[i] = createSceneOutcome.TakeValue(); + m_sceneSystem->RemoveScene(sceneName); + } - AzFramework::EntityIdContextQueryBus::BroadcastResult(entityContextId, &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId); + // Check to make sure there are no more active scenes. + size_t index = 0; + m_sceneSystem->IterateActiveScenes([&index, &scenes](const AZStd::shared_ptr&) + { + index++; + return true; + }); + EXPECT_EQ(0, index); - // A null scene should be returned since a scene has not been set for this entity context. - AzFramework::SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, entityContextId); - EXPECT_TRUE(scene == nullptr) << "Found a scene when one shouldn't exist."; - }; - - testComponent->SetConfiguration(failConfig); - testComponent->Activate(); - testComponent->Deactivate(); + // Check that the scenes are still returned as zombies. + index = 0; + m_sceneSystem->IterateZombieScenes([&index, &scenes](Scene& scene) + { + EXPECT_EQ(scenes[index++].get(), &scene); + return true; + }); - // Create the scene - AZ::Outcome createSceneOutcome = AZ::Failure(""); - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, "TestScene"); - Scene* scene = createSceneOutcome.GetValue(); - - // Map the Entity context to the scene - bool success = false; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequestBus::Events::SetSceneForEntityContextId, testEntityContextId, scene); - EXPECT_TRUE(success) << "Unable to associate an entity context with a scene."; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequestBus::Events::SetSceneForEntityContextId, testEntityContextId, scene); - EXPECT_FALSE(success) << "Attempting to map an entity context to a scene that's already mapped, this should not work."; - - // Now it should be possible to get the scene from the entity context within an Entity's Activate() - TestComponentConfig successConfig; - successConfig.m_activateFunction = [](TestComponent* component) + // Check that all scenes are removed when there are no more handles. + for (size_t i = 0; i < NumScenes; ++i) { - (void)component; - Scene* scene = nullptr; - EntityContextId entityContextId = EntityContextId::CreateNull(); - - AzFramework::EntityIdContextQueryBus::BroadcastResult(entityContextId, &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId); - - // A scene should be returned since a scene has been set for this entity context. - AzFramework::SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, entityContextId); - EXPECT_TRUE(scene != nullptr) << "Could not find a scene for the entity context."; - }; - - testComponent->SetConfiguration(successConfig); - testComponent->Activate(); - testComponent->Deactivate(); - - // Now remove the entity context / scene association and make sure things fail again. - success = false; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequestBus::Events::RemoveSceneForEntityContextId, testEntityContextId, nullptr); - EXPECT_FALSE(success) << "Should not be able to remove an entity context from a scene it's not associated with."; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequestBus::Events::RemoveSceneForEntityContextId, testEntityContextId, scene); - EXPECT_TRUE(success) << "Was not able to remove an entity context from a scene it's associated with."; - - testComponent->SetConfiguration(failConfig); - testComponent->Activate(); - testComponent->Deactivate(); - - delete testEntityContext; // This should also clean up owned entities / components. + scenes[i].reset(); + } + index = 0; + m_sceneSystem->IterateZombieScenes([&index, &scenes](Scene&) { + index++; + return true; + }); + EXPECT_EQ(0, index); } // Test classes for use in the SceneSystem test. These can't be defined in the test itself due to some functions created by AZ_RTTI not having a body which breaks VS2015. @@ -324,30 +278,48 @@ namespace SceneUnitTest TEST_F(SceneTest, SceneSystem) { // Create the scene - AZ::Outcome createSceneOutcome = AZ::Failure(""); - AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequestBus::Events::CreateScene, "TestScene"); - AzFramework::Scene* scene = createSceneOutcome.GetValue(); + AZ::Outcome, AZStd::string> createSceneOutcome = m_sceneSystem->CreateScene("TestScene"); + EXPECT_TRUE(createSceneOutcome.IsSuccess()); + AZStd::shared_ptr scene = createSceneOutcome.TakeValue(); // Set a class on the Scene Foo1* foo1a = new Foo1(); EXPECT_TRUE(scene->SetSubsystem(foo1a)); // Get that class back from the Scene - EXPECT_EQ(foo1a, scene->GetSubsystem()); + EXPECT_EQ(foo1a, *scene->FindSubsystem()); // Try to set the same class type twice, this should fail. Foo1* foo1b = new Foo1(); EXPECT_FALSE(scene->SetSubsystem(foo1b)); delete foo1b; + // Add a child scene + createSceneOutcome = m_sceneSystem->CreateSceneWithParent("ChildScene", scene); + EXPECT_TRUE(createSceneOutcome.IsSuccess()); + AZStd::shared_ptr childScene = createSceneOutcome.TakeValue(); + + // Get class back from parent scene. + EXPECT_EQ(foo1a, *childScene->FindSubsystem()); + + // Find overloaded version of class on child scene. + Foo1* foo1c = new Foo1(); + EXPECT_TRUE(childScene->SetSubsystem(foo1c)); + EXPECT_EQ(foo1c, *childScene->FindSubsystem()); + + // Unset system on child scene, using alternative unset function. + EXPECT_TRUE(childScene->UnsetSubsystem(foo1c)); + delete foo1c; + // Try to un-set a class that was never set, this should fail. EXPECT_FALSE(scene->UnsetSubsystem()); // Unset the class that was previously set EXPECT_TRUE(scene->UnsetSubsystem()); + delete foo1a; - // Make sure that the previsouly set class was really removed. - EXPECT_EQ(nullptr, scene->GetSubsystem()); + // Make sure that the previously set class was really removed. + EXPECT_EQ(nullptr, scene->FindSubsystem()); } } // UnitTest diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp index ce76137466..3d17e77bb0 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp @@ -90,9 +90,6 @@ void ShaderPropertyEditor::onEditClicked() } void MaterialPropertyEditor::onEditClicked() { - QString name = GetValue(); - IDataBaseItem *pItem = GetIEditor()->GetMaterialManager()->FindItemByName(name); - GetIEditor()->OpenMaterialLibrary(pItem); } void MaterialPropertyEditor::onButton2Clicked() diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index aed53d6e8b..b0e00de020 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -605,8 +605,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe editMenu.AddSeparator(); // Lock Selection - editMenu.AddAction(ID_EDIT_FREEZE); - // NEWMENUS: NEEDS IMPLEMENTATION //// Unlock Selection //auto unlockSelectionMenu = editMenu.Get()->addAction(tr("Unlock Selection")); @@ -614,11 +612,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe //// Unlock Last Locked //auto unlockLastLockedMenu = editMenu.Get()->addAction(tr("Unlock Last Locked")); - // Unlock All - editMenu.AddAction(ID_EDIT_UNFREEZEALL); - - editMenu.AddSeparator(); - // Editor Settings auto editorSettingsMenu = editMenu.AddMenu(tr("Editor Settings")); diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 3f28717072..dcc978433c 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -389,14 +389,9 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDIT_DELETE, OnEditDelete) ON_COMMAND(ID_MOVE_OBJECT, OnMoveObject) ON_COMMAND(ID_RENAME_OBJ, OnRenameObj) - ON_COMMAND(ID_SET_HEIGHT, OnSetHeight) ON_COMMAND(ID_EDITMODE_MOVE, OnEditmodeMove) ON_COMMAND(ID_EDITMODE_ROTATE, OnEditmodeRotate) ON_COMMAND(ID_EDITMODE_SCALE, OnEditmodeScale) - ON_COMMAND(ID_OBJECTMODIFY_SETAREA, OnObjectSetArea) - ON_COMMAND(ID_OBJECTMODIFY_SETHEIGHT, OnObjectSetHeight) - ON_COMMAND(ID_OBJECTMODIFY_FREEZE, OnObjectmodifyFreeze) - ON_COMMAND(ID_OBJECTMODIFY_UNFREEZE, OnObjectmodifyUnfreeze) ON_COMMAND(ID_UNDO, OnUndo) ON_COMMAND(ID_TOOLBAR_WIDGET_REDO, OnUndo) // Can't use the same ID, because for the menu we can't have a QWidgetAction, while for the toolbar we want one ON_COMMAND(ID_IMPORT_ASSET, OnOpenAssetImporter) @@ -424,8 +419,6 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDIT_HIDE, OnEditHide) ON_COMMAND(ID_EDIT_SHOW_LAST_HIDDEN, OnEditShowLastHidden) ON_COMMAND(ID_EDIT_UNHIDEALL, OnEditUnhideall) - ON_COMMAND(ID_EDIT_FREEZE, OnEditFreeze) - ON_COMMAND(ID_EDIT_UNFREEZEALL, OnEditUnfreezeall) ON_COMMAND(ID_SNAP_TO_GRID, OnSnap) @@ -477,7 +470,6 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_ROTATESELECTION_YAXIS, OnRotateselectionYaxis) ON_COMMAND(ID_ROTATESELECTION_ZAXIS, OnRotateselectionZaxis) ON_COMMAND(ID_ROTATESELECTION_ROTATEANGLE, OnRotateselectionRotateangle) - ON_COMMAND(ID_MODIFY_OBJECT_HEIGHT, OnObjectSetHeight) ON_COMMAND(ID_EDIT_RENAMEOBJECT, OnEditRenameobject) ON_COMMAND(ID_CHANGEMOVESPEED_INCREASE, OnChangemovespeedIncrease) ON_COMMAND(ID_CHANGEMOVESPEED_DECREASE, OnChangemovespeedDecrease) @@ -500,7 +492,6 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_OPEN_ASSET_BROWSER, OnOpenAssetBrowserView) ON_COMMAND(ID_OPEN_AUDIO_CONTROLS_BROWSER, OnOpenAudioControlsEditor) - ON_COMMAND(ID_OPEN_MATERIAL_EDITOR, OnOpenMaterialEditor) ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch) ON_COMMAND(ID_DISPLAY_SHOWHELPERS, OnShowHelpers) ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView) @@ -2734,10 +2725,6 @@ void CCryEditApp::OnRenameObj() { } -void CCryEditApp::OnSetHeight() -{ -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnEditmodeMove() { @@ -2807,167 +2794,6 @@ void CCryEditApp::OnUpdateEditmodeScale(QAction* action) action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Scale); } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnObjectSetArea() -{ - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - if (!pSelection->IsEmpty()) - { - bool ok = false; - int fractionalDigitCount = 2; - float area = aznumeric_caster(QInputDialog::getDouble(AzToolsFramework::GetActiveWindow(), QObject::tr("Insert Value"), QStringLiteral(""), 0, std::numeric_limits::lowest(), std::numeric_limits::max(), fractionalDigitCount, &ok)); - if (!ok) - { - return; - } - - GetIEditor()->BeginUndo(); - for (int i = 0; i < pSelection->GetCount(); i++) - { - CBaseObject* obj = pSelection->GetObject(i); - obj->SetArea(area); - } - GetIEditor()->AcceptUndo("Set Area"); - GetIEditor()->SetModifiedFlag(); - GetIEditor()->SetModifiedModule(eModifiedBrushes); - } - else - { - QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(), QObject::tr("No objects selected")); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnObjectSetHeight() -{ - AzFramework::EntityContextId editorContextId; - AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( - editorContextId, &AzToolsFramework::EditorEntityContextRequests::GetEditorEntityContextId); - - CSelectionGroup* sel = GetIEditor()->GetObjectManager()->GetSelection(); - - if (!sel->IsEmpty()) - { - // Retrieve the Z origin from where height is messured from - auto getZOrigin = [&](const Vec3& pos, [[maybe_unused]] AZ::EntityId entityId) - { - float z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - if (z != pos.z) - { - float zdown = FLT_MAX; - float zup = FLT_MAX; - AzFramework::RenderGeometry::RayRequest ray; - ray.m_startWorldPosition = LYVec3ToAZVec3(pos); - ray.m_onlyVisible = true; - if (entityId.IsValid()) // Don't check height against self - { - ray.m_entityFilter.m_ignoreEntities.insert(entityId); - } - // Down - ray.m_endWorldPosition = LYVec3ToAZVec3(pos - Vec3(0, 0, 4000)); - { - AzFramework::RenderGeometry::RayResult result; - AzFramework::RenderGeometry::IntersectorBus::EventResult(result, editorContextId, - &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray); - if (result) - { - zdown = result.m_worldPosition.GetZ(); - } - } - // Up - ray.m_endWorldPosition = LYVec3ToAZVec3(pos + Vec3(0, 0, 4000)); - { - AzFramework::RenderGeometry::RayResult result; - AzFramework::RenderGeometry::IntersectorBus::EventResult(result, editorContextId, - &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray); - if (result) - { - zup = result.m_worldPosition.GetZ(); - } - } - if (zdown != FLT_MAX && zup != FLT_MAX) - { - if (fabs(zup - z) < fabs(zdown - z)) - { - z = zup; - } - else - { - z = zdown; - } - } - else if (zup != FLT_MAX) - { - z = zup; - } - else if (zdown != FLT_MAX) - { - z = zdown; - } - } - return z; - }; - - - float height = 0; - if (sel->GetCount() == 1) - { - CBaseObject* obj = sel->GetObject(0); - Vec3 pos = obj->GetWorldPos(); - AZ::EntityId entityId; - if (obj->GetType() == OBJTYPE_AZENTITY) - { - entityId = static_cast(obj)->GetAssociatedEntityId(); - } - height = pos.z - getZOrigin(pos, entityId); - } - - bool ok = false; - int fractionalDigitCount = 2; - height = aznumeric_caster(QInputDialog::getDouble(AzToolsFramework::GetActiveWindow(), QObject::tr("Enter Height"), QStringLiteral(""), height, -10000, 10000, fractionalDigitCount, &ok)); - if (!ok) - { - return; - } - - CUndo undo("Set Height"); - for (int i = 0; i < sel->GetCount(); i++) - { - CBaseObject* obj = sel->GetObject(i); - Matrix34 wtm = obj->GetWorldTM(); - Vec3 pos = wtm.GetTranslation(); - AZ::EntityId entityId; - if (obj->GetType() == OBJTYPE_AZENTITY) - { - entityId = static_cast(obj)->GetAssociatedEntityId(); - } - float z = getZOrigin(pos, entityId); - pos.z = z + height; - wtm.SetTranslation(pos); - obj->SetWorldTM(wtm, eObjectUpdateFlags_UserInput); - } - - GetIEditor()->SetModifiedFlag(); - GetIEditor()->SetModifiedModule(eModifiedBrushes); - } - else - { - QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(), QObject::tr("No objects selected")); - } -} - -void CCryEditApp::OnObjectmodifyFreeze() -{ - // Freeze selection. - OnEditFreeze(); -} - -void CCryEditApp::OnObjectmodifyUnfreeze() -{ - // Unfreeze all. - OnEditUnfreezeall(); -} - void CCryEditApp::OnViewSwitchToGame() { if (IsInPreviewMode()) @@ -3883,54 +3709,6 @@ void CCryEditApp::OnEditUnhideall() } } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnEditFreeze() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - // Freeze selection. - CSelectionGroup* sel = GetIEditor()->GetSelection(); - if (!sel->IsEmpty()) - { - AzToolsFramework::ScopedUndoBatch undo("Lock Selected Entities"); - - // We need to iterate over the list of selected objects in reverse order - // because when the objects are locked, they are removed from the - // selection so you would end up with the last selected object not - // being locked - int numSelected = sel->GetCount(); - for (int i = numSelected - 1; i >= 0; --i) - { - // Duplicated object names can exist in the case of prefab objects so passing a name as a script parameter and processing it couldn't be exact. - sel->GetObject(i)->SetFrozen(true); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateEditFreeze(QAction* action) -{ - OnUpdateEditHide(action); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnEditUnfreezeall() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - if (QMessageBox::question( - AzToolsFramework::GetActiveWindow(), QObject::tr("Unlock All"), - QObject::tr("Are you sure you want to unlock all the objects?"), - QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Yes) - { - // Unfreeze all. - AzToolsFramework::ScopedUndoBatch undo("Unlock all Entities"); - GetIEditor()->GetObjectManager()->UnfreezeAll(); - } - } -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSnap() { @@ -4618,12 +4396,6 @@ void CCryEditApp::OnMaterialGetmaterial() GetIEditor()->GetMaterialManager()->Command_SelectFromObject(); } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnOpenMaterialEditor() -{ - QtViewPaneManager::instance()->OpenPane(LyViewPane::MaterialEditor); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnOpenAssetBrowserView() { @@ -5045,12 +4817,28 @@ extern "C" #pragma comment(lib, "Shell32.lib") #endif +struct CryAllocatorsRAII +{ + CryAllocatorsRAII() + { + AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); + AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); + + AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); + } + + ~CryAllocatorsRAII() + { + AZ::AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); + } +}; + + extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) { - AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); - AZ::AllocatorInstance::Create(); - AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); - AZ::AllocatorInstance::Create(); + CryAllocatorsRAII cryAllocatorsRAII; // ensure the EditorEventsBus context gets created inside EditorLib [[maybe_unused]] const auto& editorEventsContext = AzToolsFramework::EditorEvents::Bus::GetOrCreateContext(); @@ -5058,7 +4846,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(); // this does some magic to set the current directory... { QCoreApplication app(argc, argv); @@ -5145,8 +4933,6 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) } - delete theApp; - gSettings.Disconnect(); return ret; diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index 7b96ab3827..2cbb34dd9f 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -220,17 +220,12 @@ public: void DeleteSelectedEntities(bool includeDescendants); void OnMoveObject(); void OnRenameObj(); - void OnSetHeight(); void OnEditmodeMove(); void OnEditmodeRotate(); void OnEditmodeScale(); - void OnObjectSetArea(); - void OnObjectSetHeight(); void OnUpdateEditmodeMove(QAction* action); void OnUpdateEditmodeRotate(QAction* action); void OnUpdateEditmodeScale(QAction* action); - void OnObjectmodifyFreeze(); - void OnObjectmodifyUnfreeze(); void OnUndo(); void OnOpenAssetImporter(); void OnUpdateSelected(QAction* action); @@ -388,9 +383,6 @@ private: void OnUpdateEditHide(QAction* action); void OnEditShowLastHidden(); void OnEditUnhideall(); - void OnEditFreeze(); - void OnUpdateEditFreeze(QAction* action); - void OnEditUnfreezeall(); void OnSnap(); void OnWireframe(); void OnUpdateWireframe(QAction* action); @@ -459,7 +451,6 @@ private: void OnUpdateSwitchToSelectedCamera(QAction* action); void OnSwitchcameraNext(); void OnOpenProceduralMaterialEditor(); - void OnOpenMaterialEditor(); void OnOpenAssetBrowserView(); void OnOpenTrackView(); void OnOpenAudioControlsEditor(); diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 04fc689ace..691d53ba3d 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -2814,14 +2814,16 @@ void EditorViewportWidget::RestoreViewportAfterGameMode() void EditorViewportWidget::UpdateScene() { - AZStd::vector scenes; - AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes); - if (scenes.size() > 0) + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + if (sceneSystem) { - AZ::RPI::SceneNotificationBus::Handler::BusDisconnect(); - auto scene = scenes[0]; - m_renderViewport->SetScene(scene); - AZ::RPI::SceneNotificationBus::Handler::BusConnect(m_renderViewport->GetViewportContext()->GetRenderScene()->GetId()); + AZStd::shared_ptr mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName); + if (mainScene) + { + AZ::RPI::SceneNotificationBus::Handler::BusDisconnect(); + m_renderViewport->SetScene(mainScene); + AZ::RPI::SceneNotificationBus::Handler::BusConnect(m_renderViewport->GetViewportContext()->GetRenderScene()->GetId()); + } } } diff --git a/Code/Sandbox/Editor/EditorViewportWidget.h b/Code/Sandbox/Editor/EditorViewportWidget.h index f2a40b34a5..472f7e3c62 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.h +++ b/Code/Sandbox/Editor/EditorViewportWidget.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Code/Sandbox/Editor/ErrorReportDialog.cpp b/Code/Sandbox/Editor/ErrorReportDialog.cpp index 8c29da91ce..83839f3e08 100644 --- a/Code/Sandbox/Editor/ErrorReportDialog.cpp +++ b/Code/Sandbox/Editor/ErrorReportDialog.cpp @@ -519,11 +519,6 @@ void CErrorReportDialog::OnReportItemDblClick(const QModelIndex& index) } bDone = true; } - if (pError && pError->pItem != NULL) - { - GetIEditor()->OpenMaterialLibrary(pError->pItem); - bDone = true; - } if (!bDone && pError && GetIEditor()->GetActiveView()) { @@ -581,11 +576,6 @@ void CErrorReportDialog::OnReportHyperlink(const QModelIndex& index) GetIEditor()->SelectObject(pError->pObject); bDone = true; } - if (pError && pError->pItem != NULL) - { - GetIEditor()->OpenMaterialLibrary(pError->pItem); - bDone = true; - } if (!bDone && pError && GetIEditor()->GetActiveView()) { diff --git a/Code/Sandbox/Editor/IEditor.h b/Code/Sandbox/Editor/IEditor.h index 90fb8823e7..4a26e7475f 100644 --- a/Code/Sandbox/Editor/IEditor.h +++ b/Code/Sandbox/Editor/IEditor.h @@ -632,9 +632,6 @@ struct IEditor virtual RefCoordSys GetReferenceCoordSys() = 0; virtual XmlNodeRef FindTemplate(const QString& templateName) = 0; virtual void AddTemplate(const QString& templateName, XmlNodeRef& tmpl) = 0; - //! Open material library and select specified item. - //! If parameter is NULL current selection in material library does not change. - virtual void OpenMaterialLibrary(IDataBaseItem* pItem = NULL) = 0; virtual const QtViewPane* OpenView(QString sViewClassName, bool reuseOpen = true) = 0; virtual QWidget* FindView(QString viewClassName) = 0; diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index 561953d729..04d7b88fb6 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -1013,29 +1013,6 @@ IDataBaseManager* CEditorImpl::GetDBItemManager(EDataBaseItemType itemType) return 0; } -void CEditorImpl::OpenMaterialLibrary(IDataBaseItem* item) -{ - EDataBaseItemType type = item ? item->GetType() : EDB_TYPE_MATERIAL; - AZ_Assert(type == EDB_TYPE_MATERIAL, "Call to OpenMaterialLibrary with non-material data base item"); - - if (type == EDB_TYPE_MATERIAL) - { - QtViewPaneManager::instance()->OpenPane(LyViewPane::MaterialEditor); - - // This is a workaround for a timing issue where the material editor - // gets in a bad state while it is being polished for the first time - // while loading a material at the same time, so delay the setting - // of the material until the next event queue check - QTimer::singleShot(0, [this, item] { - IDataBaseManager* pManager = GetDBItemManager(EDB_TYPE_MATERIAL); - if (pManager) - { - pManager->SetSelectedItem(item); - } - }); - } -} - bool CEditorImpl::SelectColor(QColor& color, QWidget* parent) { const AZ::Color c = AzQtComponents::fromQColor(color); diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index a99fa234b9..cde1012b94 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -237,7 +237,6 @@ public: RefCoordSys GetReferenceCoordSys(); XmlNodeRef FindTemplate(const QString& templateName); void AddTemplate(const QString& templateName, XmlNodeRef& tmpl); - void OpenMaterialLibrary(IDataBaseItem* pItem = NULL); const QtViewPane* OpenView(QString sViewClassName, bool reuseOpened = true) override; diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index b28a80967a..b51a3d7a4a 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -135,7 +135,6 @@ public: MOCK_METHOD0(GetReferenceCoordSys, RefCoordSys()); MOCK_METHOD1(FindTemplate, XmlNodeRef(const QString& )); MOCK_METHOD2(AddTemplate, void(const QString& , XmlNodeRef& )); - MOCK_METHOD1(OpenMaterialLibrary, void (IDataBaseItem*)); MOCK_METHOD2(OpenView, const QtViewPane* (QString , bool )); MOCK_METHOD1(FindView, QWidget* (QString )); MOCK_METHOD1(CloseView, bool(const char* )); diff --git a/Code/Sandbox/Editor/LyViewPaneNames.h b/Code/Sandbox/Editor/LyViewPaneNames.h index c0c2dbdb45..3ea793b9c7 100644 --- a/Code/Sandbox/Editor/LyViewPaneNames.h +++ b/Code/Sandbox/Editor/LyViewPaneNames.h @@ -43,7 +43,6 @@ namespace LyViewPane static const char* const TerrainEditor = "Terrain Editor"; static const char* const TerrainTool = "Terrain Tool"; static const char* const TerrainTextureLayers = "Terrain Texture Layers"; - static const char* const MaterialEditor = "Material Editor"; static const char* const ParticleEditor = "Particle Editor"; static const char* const LensFlareEditor = "Lens Flare Editor"; static const char* const TimeOfDayEditor = "Time Of Day"; diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 2915ca9c2e..a18cec12f0 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -435,13 +435,6 @@ MainWindow::MainWindow(QWidget* parent) setAcceptDrops(true); -#ifdef Q_OS_WIN - if (auto aed = QAbstractEventDispatcher::instance()) - { - aed->installNativeEventFilter(this); - } -#endif - // special handling for escape key (outside ActionManager) auto* escapeAction = new QAction(this); escapeAction->setShortcut(QKeySequence(Qt::Key_Escape)); @@ -508,13 +501,6 @@ void MainWindow::SetActiveView(CLayoutViewPane* v) MainWindow::~MainWindow() { -#ifdef Q_OS_WIN - if (auto aed = QAbstractEventDispatcher::instance()) - { - aed->removeNativeEventFilter(this); - } -#endif - AzToolsFramework::SourceControlNotificationBus::Handler::BusDisconnect(); delete m_toolbarManager; @@ -938,22 +924,6 @@ void MainWindow::InitActions() am->AddAction(ID_MODIFY_UNLINK, tr("Un-Parent")); } - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - // implemented by EditorTransformComponentSelection when the new Viewport Interaction Model is enabled - am->AddAction(ID_EDIT_FREEZE, tr("Lock selection")) - .SetShortcut(tr("L")) - .SetToolTip(tr("Lock selection (L)")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateEditFreeze) - .SetIcon(Style::icon("Locked")) - .SetApplyHoverEffect(); - am->AddAction(ID_EDIT_UNFREEZEALL, tr("Unlock all")) - .SetShortcut(tr("Ctrl+L")) - .SetToolTip(tr("Unlock All (Ctrl+L)")) - .SetIcon(Style::icon("Unlocked")) - .SetApplyHoverEffect(); - } - am->AddAction(ID_EDIT_HOLD, tr("&Hold")) .SetShortcut(tr("Ctrl+Alt+H")) .SetToolTip(tr("&Hold (Ctrl+Alt+H)")) @@ -987,7 +957,6 @@ void MainWindow::InitActions() } // Modify actions - am->AddAction(ID_MODIFY_OBJECT_HEIGHT, tr("Set Object(s) Height...")); am->AddAction(ID_EDIT_RENAMEOBJECT, tr("Rename Object(s)...")) .SetStatusTip(tr("Rename Object")); @@ -1202,10 +1171,6 @@ void MainWindow::InitActions() if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) { - am->AddAction(ID_GENERATORS_LIGHTING, tr("&Sun Trajectory Tool")) - .SetIcon(Style::icon("Lighting")) - .SetApplyHoverEffect() - .SetStatusTip(tr("Bring up the terrain lighting dialog")); am->AddAction(ID_TERRAIN_TIMEOFDAY, tr("Time Of Day")) .SetStatusTip(tr("Open Time of Day Editor")); } @@ -1300,14 +1265,6 @@ void MainWindow::InitActions() .SetToolTip(tr("Open Asset Browser")) .SetApplyHoverEffect(); - if (!AZ::Interface::Get()) - { - am->AddAction(ID_OPEN_MATERIAL_EDITOR, tr(LyViewPane::MaterialEditor)) - .SetToolTip(tr("Open Material Editor")) - .SetIcon(Style::icon("Material")) - .SetApplyHoverEffect(); - } - AZ::EBusReduceResult> emfxEnabled(false); using AnimationRequestBus = AzToolsFramework::EditorAnimationSystemRequestsBus; using AnimationSystemType = AzToolsFramework::EditorAnimationSystemRequests::AnimationSystem; @@ -1360,14 +1317,6 @@ void MainWindow::InitActions() .SetApplyHoverEffect() .Connect(&QAction::triggered, this, &MainWindow::OnGotoSelected); - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - am->AddAction(ID_OBJECTMODIFY_SETHEIGHT, tr("Set object(s) height")) - .SetIcon(QIcon(":/MainWindow/toolbars/object_toolbar-03.svg")) - .SetApplyHoverEffect() - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelected); - } - // Misc Toolbar Actions am->AddAction(ID_OPEN_SUBSTANCE_EDITOR, tr("Open Substance Editor")) .SetApplyHoverEffect(); @@ -2215,35 +2164,6 @@ void MainWindow::RegisterOpenWndCommands() } } -void MainWindow::MatEditSend(int param) -{ - if (param == eMSM_Init || GetIEditor()->IsInMatEditMode()) - { - // In MatEditMode this message is handled by CMatEditMainDlg, which doesn't have - // any view panes and opens MaterialDialog directly. - return; - } - - if (QtViewPaneManager::instance()->OpenPane(LyViewPane::MaterialEditor)) - { - GetIEditor()->GetMaterialManager()->SyncMaterialEditor(); - } -} - -#ifdef Q_OS_WIN -bool MainWindow::nativeEventFilter([[maybe_unused]] const QByteArray &eventType, void *message, long *) -{ - MSG* msg = static_cast(message); - if (msg->message == WM_MATEDITSEND) // For supporting 3ds Max Exporter, Windows Only - { - MatEditSend(msg->wParam); - return true; - } - - return false; -} -#endif - bool MainWindow::event(QEvent* event) { #ifdef Q_OS_MAC diff --git a/Code/Sandbox/Editor/MainWindow.h b/Code/Sandbox/Editor/MainWindow.h index cafa719589..adf271b383 100644 --- a/Code/Sandbox/Editor/MainWindow.h +++ b/Code/Sandbox/Editor/MainWindow.h @@ -24,13 +24,11 @@ #include #include #include -#include #include "Include/SandboxAPI.h" #include #include #include -#include #include "IEditor.h" #endif @@ -93,9 +91,6 @@ class SANDBOX_API MainWindow : public QMainWindow , public IEditorNotifyListener , private AzToolsFramework::SourceControlNotificationBus::Handler -#ifdef Q_OS_WIN - , public QAbstractNativeEventFilter -#endif { AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING @@ -160,13 +155,9 @@ public: void UpdateToolsMenu(); int ViewPaneVersion() const; - void MatEditSend(int param); LevelEditorMenuHandler* GetLevelEditorMenuHandler() { return m_levelEditorMenuHandler; } -#ifdef Q_OS_WIN - bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override; -#endif bool event(QEvent* event) override; void OnGotoSliceRoot(); diff --git a/Code/Sandbox/Editor/Material/MaterialManager.cpp b/Code/Sandbox/Editor/Material/MaterialManager.cpp index 3c21a74d97..51460ff34a 100644 --- a/Code/Sandbox/Editor/Material/MaterialManager.cpp +++ b/Code/Sandbox/Editor/Material/MaterialManager.cpp @@ -1668,25 +1668,13 @@ void CMaterialManager::InitMatSender() } ////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GotoMaterial(CMaterial* pMaterial) +void CMaterialManager::GotoMaterial([[maybe_unused]] CMaterial* pMaterial) { - if (pMaterial) - { - GetIEditor()->OpenMaterialLibrary(pMaterial); - } } ////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GotoMaterial(_smart_ptr pMtl) +void CMaterialManager::GotoMaterial([[maybe_unused]] _smart_ptr pMtl) { - if (pMtl) - { - CMaterial* pEdMaterial = FromIMaterial(pMtl); - if (pEdMaterial) - { - GetIEditor()->OpenMaterialLibrary(pEdMaterial); - } - } } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index 15d04bd5c0..ce2c3a9ca4 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -75,13 +75,10 @@ #define IDC_PLATFORM_SALEM 2759 #define IDC_GROUPBOX_GLOBALTAGS 2916 #define IDC_GROUPBOX_FRAGMENTTAGS 2917 -#define ID_PARTICLE_EDITOR 2922 #define ID_RESOURCES_GENERATECGFTHUMBNAILS 32894 #define ID_RESOURCES_REDUCEWORKINGSET 32896 #define ID_EDIT_HIDE 32898 #define ID_EDIT_UNHIDEALL 32899 -#define ID_EDIT_FREEZE 32900 -#define ID_EDIT_UNFREEZEALL 32901 #define ID_RELOAD_TERRAIN 32902 #define ID_VIEW_GRIDSETTINGS 32904 #define ID_VIEW_CONFIGURELAYOUT 32906 @@ -125,7 +122,6 @@ #define ID_EDIT_SELECTNONE 33377 #define ID_WIREFRAME 33410 #define ID_FILE_GENERATETERRAINTEXTURE 33445 -#define ID_GENERATORS_LIGHTING 33446 #define ID_GENERATORS_STATICOBJECTS 33447 #define ID_GENERATORS_TEXTURE 33448 #define ID_FILE_IMPORT 33457 @@ -136,17 +132,12 @@ #define ID_EDIT_DELETE 33480 #define ID_MOVE_OBJECT 33481 #define ID_RENAME_OBJ 33483 -#define ID_SET_HEIGHT 33484 #define ID_FETCH 33496 #define ID_EDITMODE_ROTATE 33506 #define ID_EDITMODE_SCALE 33507 #define ID_EDITMODE_MOVE 33508 #define ID_SELECTION_DELETE 33512 #define ID_EDIT_ESCAPE 33513 -#define ID_OBJECTMODIFY_SETAREA 33514 -#define ID_OBJECTMODIFY_SETHEIGHT 33515 -#define ID_OBJECTMODIFY_FREEZE 33517 -#define ID_OBJECTMODIFY_UNFREEZE 33518 #define ID_UNDO 33524 #define ID_EDIT_CLONE 33525 #define ID_GOTO_SELECTED 33535 @@ -230,7 +221,6 @@ #define ID_VIEW_OPENVIEWPANE 33709 #define ID_VIEW_OPENPANE_FIRST 33712 #define ID_VIEW_OPENPANE_LAST 33811 -#define ID_OPEN_MATERIAL_EDITOR 33822 #define ID_OPEN_EMOTIONFX_EDITOR 39742 #define ID_BRUSH_CSGSUBSTRUCT 33837 #define ID_MATERIAL_PICKTOOL 33842 @@ -320,7 +310,6 @@ #define ID_SNAP_TO_ANGLE_RANGE_END 34330 #define ID_MODIFY_LINK 34355 #define ID_MODIFY_UNLINK 34356 -#define ID_MODIFY_OBJECT_HEIGHT 34357 #define ID_MODIFY_GOTO_SELECTION 34358 #define ID_VIEW_LAYOUT_FIRST 34363 #define ID_VIEW_LAYOUT_LAST 34377 diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index c1758405ca..0e757dad7c 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -609,14 +609,6 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const AmazonToolbar t = AmazonToolbar("Object", QObject::tr("Object Toolbar")); t.SetMainToolbar(true); t.AddAction(ID_GOTO_SELECTED, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_OBJECTMODIFY_SETHEIGHT, ORIGINAL_TOOLBAR_VERSION); - - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_EDIT_FREEZE, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_EDIT_UNFREEZEALL, ORIGINAL_TOOLBAR_VERSION); - } return t; } @@ -636,19 +628,9 @@ AmazonToolbar ToolbarManager::GetPlayConsoleToolbar() const AmazonToolbar ToolbarManager::GetEditorsToolbar() const { AmazonToolbar t = AmazonToolbar("Editors", QObject::tr("Editors Toolbar")); - if( !AZ::Interface::Get() && !GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - t.AddAction(ID_OPEN_MATERIAL_EDITOR, ORIGINAL_TOOLBAR_VERSION); - } t.AddAction(ID_OPEN_AUDIO_CONTROLS_BROWSER, ORIGINAL_TOOLBAR_VERSION); - if (!AZ::Interface::Get()) - { - t.AddAction(ID_PARTICLE_EDITOR, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_GENERATORS_LIGHTING, ORIGINAL_TOOLBAR_VERSION); - } - return t; } diff --git a/Code/Sandbox/Editor/TrackView/AtomOutputFrameCapture.cpp b/Code/Sandbox/Editor/TrackView/AtomOutputFrameCapture.cpp index 86410a0211..9508c4e265 100644 --- a/Code/Sandbox/Editor/TrackView/AtomOutputFrameCapture.cpp +++ b/Code/Sandbox/Editor/TrackView/AtomOutputFrameCapture.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace TrackView { diff --git a/Code/Sandbox/Editor/main.cpp b/Code/Sandbox/Editor/main.cpp index 013dc4ff69..17c177e9d3 100644 --- a/Code/Sandbox/Editor/main.cpp +++ b/Code/Sandbox/Editor/main.cpp @@ -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(CryEditMainName); fn != nullptr) { - const int ret = AZStd::invoke(fn, argc, argv); - - AZ::AllocatorInstance::Destroy(); - AZ::Environment::Detach(); - - return ret; + ret = AZStd::invoke(fn, argc, argv); } + handle = {}; AZ::AllocatorInstance::Destroy(); AZ::Environment::Detach(); - return 1; + return ret; } diff --git a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp index 86e00bfd41..b152e5ed4f 100644 --- a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp @@ -713,7 +713,7 @@ namespace AssetUtilities } // Update Settings Registry with new token - AZStd::string azNewAllowedList{ newAllowedList.join(', ').toUtf8().constData() }; + AZStd::string azNewAllowedList{ newAllowedList.join(',').toUtf8().constData() }; settingsRegistry->Set(allowedListKey, azNewAllowedList); return AssetUtilsInternal::DumpAssetProcessorUserSettingsToFile(*settingsRegistry, assetProcessorUserSetregPath); diff --git a/Code/Tools/RC/ResourceCompiler/main.cpp b/Code/Tools/RC/ResourceCompiler/main.cpp index 02dbd406d8..67a585aaa4 100644 --- a/Code/Tools/RC/ResourceCompiler/main.cpp +++ b/Code/Tools/RC/ResourceCompiler/main.cpp @@ -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, {}); diff --git a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h index ee7f37adf3..b20535810c 100644 --- a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h +++ b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h @@ -13,7 +13,7 @@ #include -#include +#include #include namespace AZ { @@ -43,15 +43,15 @@ namespace AZ EBusConnectionPolicy::Connect(busPtr, context, handler, connectLock, id); // Check if bootstrap scene already exists and fire notifications if it does - AZStd::vector scenes; - AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes); - AZ_Assert(scenes.size() > 0, "AzFramework didn't set up any scenes."); + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Notification bus called before the scene system has been initialized."); + AZStd::shared_ptr mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName); + AZ_Assert(mainScene, "AzFramework didn't set up any scenes."); - // Assume first scene is the default scene - AZ::RPI::Scene* defaultScene = scenes.at(0)->GetSubsystem(); - if (defaultScene && defaultScene->GetDefaultRenderPipeline()) + AZ::RPI::ScenePtr* defaultScene = mainScene->FindSubsystem(); + if (defaultScene && *defaultScene && (*defaultScene)->GetDefaultRenderPipeline()) { - handler->OnBootstrapSceneReady(defaultScene); + handler->OnBootstrapSceneReady(defaultScene->get()); } } }; diff --git a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h index 807c00fce6..bd0c2d93d5 100644 --- a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h +++ b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h @@ -13,7 +13,7 @@ #include -#include +#include #include namespace AZ::Render::Bootstrap diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index 099e9062cf..ddf0ae9274 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -269,7 +269,7 @@ namespace AZ // Register scene to RPI system so it will be processed/rendered per tick RPI::RPISystemInterface::Get()->RegisterScene(atomScene); - scene->SetSubsystem(atomScene.get()); + scene->SetSubsystem(atomScene); atomSceneHandle = atomScene; @@ -279,11 +279,19 @@ namespace AZ void BootstrapSystemComponent::CreateDefaultScene() { // Bind atomScene to the GameEntityContext's AzFramework::Scene - AZStd::vector scenes; - AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes); - AZ_Assert(scenes.size() > 0, "Error: Scenes missing during system component initialization"); // This should never happen unless scene creation has changed. - m_defaultFrameworkScene = scenes[0]; - m_defaultScene = GetOrCreateAtomSceneFromAzScene(m_defaultFrameworkScene); + m_defaultFrameworkScene = AzFramework::SceneSystemInterface::Get()->GetScene(AzFramework::Scene::MainSceneName); + // This should never happen unless scene creation has changed. + AZ_Assert(m_defaultFrameworkScene, "Error: Scenes missing during system component initialization"); + m_sceneRemovalHandler = AzFramework::Scene::RemovalEvent::Handler( + [this](AzFramework::Scene&, AzFramework::Scene::RemovalEventType eventType) + { + if (eventType == AzFramework::Scene::RemovalEventType::Zombified) + { + m_defaultFrameworkScene.reset(); + } + }); + m_defaultFrameworkScene->ConnectToEvents(m_sceneRemovalHandler); + m_defaultScene = GetOrCreateAtomSceneFromAzScene(m_defaultFrameworkScene.get()); } bool BootstrapSystemComponent::EnsureDefaultRenderPipelineInstalledForScene(AZ::RPI::ScenePtr scene, AZ::RPI::ViewportContextPtr viewportContext) @@ -405,15 +413,6 @@ namespace AZ AzFramework::WindowNotificationBus::Handler::BusDisconnect(); } - void BootstrapSystemComponent::SceneAboutToBeRemoved(AzFramework::Scene& scene) - { - if (&scene == m_defaultFrameworkScene) - { - // Set to nullptr so we don't try to unbind the RPI::Scene from it later. - m_defaultFrameworkScene = nullptr; - } - } - AzFramework::NativeWindowHandle BootstrapSystemComponent::GetDefaultWindowHandle() { return m_windowHandle; diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h index f655272350..7323a54221 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -45,7 +45,6 @@ namespace AZ , public TickBus::Handler , public AzFramework::WindowNotificationBus::Handler , public AzFramework::AssetCatalogEventBus::Handler - , private AzFramework::SceneSystemNotificationBus::Handler , public AzFramework::WindowSystemNotificationBus::Handler , public AzFramework::WindowSystemRequestBus::Handler , public Render::Bootstrap::DefaultWindowBus::Handler @@ -90,9 +89,6 @@ namespace AZ // AzFramework::AssetCatalogEventBus::Handler overrides ... void OnCatalogLoaded(const char* catalogFile) override; - // AzFramework::SceneSystemNotificationBus::Handler overrides ... - void SceneAboutToBeRemoved(AzFramework::Scene& scene) override; - // AzFramework::WindowSystemNotificationBus::Handler overrides ... void OnWindowCreated(AzFramework::NativeWindowHandle windowHandle) override; @@ -104,12 +100,14 @@ namespace AZ void CreateWindowContext(); + AzFramework::Scene::RemovalEvent::Handler m_sceneRemovalHandler; + AZStd::unique_ptr m_nativeWindow; AzFramework::NativeWindowHandle m_windowHandle = nullptr; RPI::ViewportContextPtr m_viewportContext; RPI::ScenePtr m_defaultScene = nullptr; - AzFramework::Scene* m_defaultFrameworkScene = nullptr; + AZStd::shared_ptr m_defaultFrameworkScene = nullptr; float m_simulateTime = 0; float m_deltaTime = 0.016f; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader index c6180c8873..95ffc36a11 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader @@ -10,6 +10,7 @@ "type": "Compute" } ] - } + }, + "DisabledRHIBackends": ["metal"] } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index f9b3f5f72d..566144bab8 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -12,6 +12,7 @@ "type": "Compute" } ] - } + }, + "DisabledRHIBackends": ["metal"] } diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 04175c461f..60bf487de3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -731,11 +731,12 @@ namespace AZ } } } - + // Remove unnecessary camera views in shadow properties - for (uint16_t lightIndex = 0; lightIndex < aznumeric_cast(m_shadowProperties.GetDataCount()); ++lightIndex) + auto& shadowPropertiesVector = m_shadowProperties.GetDataVector(); + for (ShadowProperty& shadowProperty : shadowPropertiesVector) { - AZStd::unordered_map>& cascades = m_shadowProperties.GetData(lightIndex).m_segments; + auto& cascades = shadowProperty.m_segments; for (auto it = cascades.begin(); it != cascades.end();) { if (AZStd::find(cameraViews.begin(), cameraViews.end(), it->first) != cameraViews.end()) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp index 8a349083ea..5be1303434 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp @@ -263,7 +263,7 @@ namespace AZ RHI::ImageInitRequest request; request.m_image = m_classificationImage[m_currentImageIndex].get(); request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::ClassificationImageFormat); - RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeClassificationImage image"); } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp index 6a0e618830..143ae1a08c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp @@ -294,7 +294,7 @@ namespace AZ // probe classification { - RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetClassificationImageAttachmentId(), diffuseProbeGrid->GetClassificationImage()); + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetClassificationImageAttachmentId(), diffuseProbeGrid->GetClassificationImage()); AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeClassificationImage"); RHI::ImageScopeAttachmentDescriptor desc; diff --git a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp index f1c41576ef..90499be8b8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp @@ -31,6 +31,11 @@ #include #include +#include + +#if defined(OPEN_IMAGE_IO_ENABLED) +#include +#endif namespace AZ { @@ -38,6 +43,41 @@ namespace AZ { AZ_ENUM_DEFINE_REFLECT_UTILITIES(FrameCaptureResult); +#if defined(OPEN_IMAGE_IO_ENABLED) + AZ_CVAR(unsigned int, + r_pngCompressionLevel, + 3, // A compression level of 3 seems like the best default in terms of file size and saving speeds + nullptr, + ConsoleFunctorFlags::Null, + "Sets the compression level for saving png screenshots. Valid values are from 0 to 8" + ); + + FrameCaptureOutputResult PngFrameCaptureOutput( + const AZStd::string& outputFilePath, const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) + { + using namespace OIIO; + AZStd::unique_ptr out = ImageOutput::create(outputFilePath.c_str()); + if (out) + { + ImageSpec spec( + readbackResult.m_imageDescriptor.m_size.m_width, + readbackResult.m_imageDescriptor.m_size.m_height, + AZ::RHI::GetFormatComponentCount(readbackResult.m_imageDescriptor.m_format) + ); + spec.attribute("png:compressionLevel", r_pngCompressionLevel); + + if (out->open(outputFilePath.c_str(), spec)) + { + out->write_image(TypeDesc::UINT8, readbackResult.m_dataBuffer->data()); + out->close(); + return FrameCaptureOutputResult{FrameCaptureResult::Success, AZStd::nullopt}; + } + } + + return FrameCaptureOutputResult{FrameCaptureResult::InternalError, "Unable to save frame capture output to " + outputFilePath}; + } +#endif + FrameCaptureOutputResult DdsFrameCaptureOutput( const AZStd::string& outputFilePath, const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) { @@ -377,7 +417,6 @@ namespace AZ if (readbackResult.m_attachmentType == AZ::RHI::AttachmentType::Buffer) { // write buffer data to the data file - AZ::IO::FileIOStream fileStream(m_outputFilePath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath); if (fileStream.IsOpen()) { @@ -418,6 +457,18 @@ namespace AZ m_result = ddsFrameCapture.m_result; m_latestCaptureInfo = ddsFrameCapture.m_errorMessage.value_or(""); } +#if defined(OPEN_IMAGE_IO_ENABLED) + else if (extension == "png") + { + AZStd::string folderPath; + AzFramework::StringFunc::Path::GetFolderPath(m_outputFilePath.c_str(), folderPath); + AZ::IO::SystemFile::CreateDir(folderPath.c_str()); + + const auto frameCaptureResult = PngFrameCaptureOutput(m_outputFilePath, readbackResult); + m_result = frameCaptureResult.m_result; + m_latestCaptureInfo = frameCaptureResult.m_errorMessage.value_or(""); + } +#endif else { m_latestCaptureInfo = AZStd::string::format("Only supports saving image to ppm or dds files"); diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/platform_windows.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/platform_windows.cmake index f5b9ea77a2..b12b5de9ce 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/platform_windows.cmake +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/platform_windows.cmake @@ -9,3 +9,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_BUILD_DEPENDENCIES + PRIVATE + 3rdParty::OpenImageIO + 3rdParty::ilmbase +) + +# [GFX-TODO] Add macro defintion in OpenImageIO 3rd party find cmake file +set(LY_COMPILE_DEFINITIONS + PRIVATE + OPEN_IMAGE_IO_ENABLED +) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h index 3238785d81..ee54b16fea 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -35,7 +35,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index 2c11ef9a41..a66471e038 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -28,6 +28,8 @@ #include #include +#include + namespace AZ { namespace RPI @@ -71,12 +73,15 @@ namespace AZ Scene* Scene::GetSceneForEntityContextId(AzFramework::EntityContextId entityContextId) { // Find the scene for this entity context. - AzFramework::Scene* scene = nullptr; - AzFramework::SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, entityContextId); + AZStd::shared_ptr scene = AzFramework::EntityContext::FindContainingScene(entityContextId); if (scene) { // Get the RPI::Scene subsystem from the AZFramework Scene. - return scene->GetSubsystem(); + RPI::ScenePtr* scenePtr = scene->FindSubsystem(); + if (scenePtr) + { + return scenePtr->get(); + } } return nullptr; } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index dd71bbc431..5dbbf04f1b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -82,7 +82,7 @@ namespace AtomToolsFramework AZ::RPI::ConstViewportContextPtr GetViewportContext() const; //! Creates an AZ::RPI::ScenePtr for the given scene and assigns it to the current ViewportContext. //! If useDefaultRenderPipeline is specified, this will initialize the scene with a rendering pipeline. - void SetScene(AzFramework::Scene* scene, bool useDefaultRenderPipeline = true); + void SetScene(const AZStd::shared_ptr& scene, bool useDefaultRenderPipeline = true); //! Gets the default camera that's been automatically registered to our ViewportContext. AZ::RPI::ViewPtr GetDefaultCamera(); AZ::RPI::ConstViewPtr GetDefaultCamera() const; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 0f1e5718db..483b4bc55b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -118,7 +118,7 @@ namespace AtomToolsFramework return m_viewportContext; } - void RenderViewportWidget::SetScene(AzFramework::Scene* scene, bool useDefaultRenderPipeline) + void RenderViewportWidget::SetScene(const AZStd::shared_ptr& scene, bool useDefaultRenderPipeline) { if (scene == nullptr) { @@ -128,7 +128,7 @@ namespace AtomToolsFramework AZ::RPI::ScenePtr atomScene; auto initializeScene = [&](AZ::Render::Bootstrap::Request* bootstrapRequests) { - atomScene = bootstrapRequests->GetOrCreateAtomSceneFromAzScene(scene); + atomScene = bootstrapRequests->GetOrCreateAtomSceneFromAzScene(scene.get()); if (useDefaultRenderPipeline) { // atomScene may already have a default render pipeline installed. @@ -416,9 +416,7 @@ namespace AtomToolsFramework } AzFramework::ScreenPoint position = AzFramework::WorldToScreen( worldPosition, - currentView->GetViewToWorldMatrix(), - currentView->GetViewToClipMatrix(), - AZ::Vector2{aznumeric_cast(width()), aznumeric_cast(height())} + GetCameraState() ); return {position.m_x, position.m_y}; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index e1bfaa3872..53a2dc2ce6 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -88,10 +88,12 @@ namespace MaterialEditor m_scene->SetShaderResourceGroupCallback(callback); // Bind m_defaultScene to the GameEntityContext's AzFramework::Scene - AZStd::vector scenes; - AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes); - AZ_Assert(scenes.size() > 0, "Error: Scenes missing during system component initialization"); // This should never happen unless scene creation has changed. - scenes.at(0)->SetSubsystem(m_scene.get()); + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "MaterialViewportRenderer was unable to get the scene system during construction."); + AZStd::shared_ptr mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName); + // This should never happen unless scene creation has changed. + AZ_Assert(mainScene, "Main scenes missing during system component initialization"); + mainScene->SetSubsystem(m_scene); // Create a render pipeline from the specified asset for the window context and add the pipeline to the scene AZ::Data::Asset pipelineAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(m_defaultPipelineAssetPath.c_str(), AZ::RPI::AssetUtils::TraceLevel::Error); @@ -275,6 +277,13 @@ namespace MaterialEditor } m_lightHandles.clear(); + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "MaterialViewportRenderer was unable to get the scene system during destruction."); + AZStd::shared_ptr mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName); + // This should never happen unless scene creation has changed. + AZ_Assert(mainScene, "Main scenes missing during system component destruction"); + mainScene->UnsetSubsystem(m_scene); + m_swapChainPass = nullptr; AZ::RPI::RPISystemInterface::Get()->UnregisterScene(m_scene); m_scene = nullptr; diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index 77f15284f1..bee6d31275 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -1263,7 +1263,12 @@ namespace AZ::AtomBridge const char* text, bool center) { - AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); + auto fontQueryInterface = AZ::Interface::Get(); + if (!fontQueryInterface) + { + return; + } + AzFramework::FontDrawInterface* fontDrawInterface = fontQueryInterface->GetDefaultFontDrawInterface(); if (!fontDrawInterface || !text || size == 0.0f) { return; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index 2969e35a51..fbefc84aad 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include @@ -40,7 +40,6 @@ namespace AZ class AtomFont : public ICryFont , public AzFramework::FontQueryInterface - , public AzFramework::SceneSystemNotificationBus::Handler { friend class FFont; @@ -92,8 +91,7 @@ namespace AZ AzFramework::FontDrawInterface* GetFontDrawInterface(AzFramework::FontId fontId) const override; AzFramework::FontDrawInterface* GetDefaultFontDrawInterface() const override; - // SceneSystemNotificationBus handlers - void SceneAboutToBeRemoved(AzFramework::Scene& scene) override; + void SceneAboutToBeRemoved(AzFramework::Scene& scene); // Atom DynamicDraw interface management @@ -137,6 +135,8 @@ namespace AZ XmlNodeRef LoadFontFamilyXml(const char* fontFamilyName, string& outputDirectory, string& outputFullPath); private: + AzFramework::ISceneSystem::SceneEvent::Handler m_sceneEventHandler; + FontMap m_fonts; FontFamilyMap m_fontFamilies; //!< Map font family names to weak ptrs so we can construct shared_ptrs but not keep a ref ourselves. FontFamilyReverseLookupMap m_fontFamilyReverseLookup; //::Register(this); + + m_sceneEventHandler = AzFramework::ISceneSystem::SceneEvent::Handler( + [this](AzFramework::ISceneSystem::EventType eventType, const AZStd::shared_ptr& scene) + { + if (eventType == AzFramework::ISceneSystem::EventType::ScenePendingRemoval) + { + SceneAboutToBeRemoved(*scene); + } + }); + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Font created before the scene system is available."); + sceneSystem->ConnectToEvents(m_sceneEventHandler); } AZ::AtomFont::~AtomFont() @@ -851,12 +863,14 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o void AZ::AtomFont::SceneAboutToBeRemoved(AzFramework::Scene& scene) { - AZ::RPI::Scene* rpiScene = scene.GetSubsystem(); - - AZStd::lock_guard lock(m_sceneToDynamicDrawMutex); - if ( auto it = m_sceneToDynamicDrawMap.find(rpiScene); it != m_sceneToDynamicDrawMap.end()) + AZ::RPI::ScenePtr* rpiScene = scene.FindSubsystem(); + if (rpiScene) { - m_sceneToDynamicDrawMap.erase(it); + AZStd::lock_guard lock(m_sceneToDynamicDrawMutex); + if (auto it = m_sceneToDynamicDrawMap.find(rpiScene->get()); it != m_sceneToDynamicDrawMap.end()) + { + m_sceneToDynamicDrawMap.erase(it); + } } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 54babd3bc1..7805a92cd1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -103,12 +103,15 @@ namespace AZ::Render void DiskLightDelegate::SetEnableShutters(bool enabled) { Base::SetEnableShutters(enabled); - GetFeatureProcessor()->SetConstrainToConeLight(GetLightHandle(), true); + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetConstrainToConeLight(GetLightHandle(), true); + } } void DiskLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) { - if (GetShuttersEnabled()) + if (GetShuttersEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); } @@ -117,12 +120,16 @@ namespace AZ::Render void DiskLightDelegate::SetEnableShadow(bool enabled) { Base::SetEnableShadow(enabled); - GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled); + + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled); + } } void DiskLightDelegate::SetShadowmapMaxSize(ShadowmapSize size) { - if (GetShadowsEnabled()) + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size); } @@ -130,7 +137,7 @@ namespace AZ::Render void DiskLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method) { - if (GetShadowsEnabled()) + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method); } @@ -138,7 +145,7 @@ namespace AZ::Render void DiskLightDelegate::SetSofteningBoundaryWidthAngle(float widthInDegrees) { - if (GetShadowsEnabled()) + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetSofteningBoundaryWidthAngle(GetLightHandle(), DegToRad(widthInDegrees)); } @@ -146,7 +153,7 @@ namespace AZ::Render void DiskLightDelegate::SetPredictionSampleCount(uint32_t count) { - if (GetShadowsEnabled()) + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count); } @@ -154,7 +161,7 @@ namespace AZ::Render void DiskLightDelegate::SetFilteringSampleCount(uint32_t count) { - if (GetShadowsEnabled()) + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count); } @@ -162,7 +169,7 @@ namespace AZ::Render void DiskLightDelegate::SetPcfMethod(PcfMethod method) { - if (GetShadowsEnabled()) + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp index a2a24c3055..073b74d4bc 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp @@ -23,7 +23,10 @@ namespace AZ : LightDelegateBase(entityId, isVisible) { InitBase(entityId); - GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + } } float SimplePointLightDelegate::CalculateAttenuationRadius(float lightThreshold) const { @@ -39,7 +42,10 @@ namespace AZ void SimplePointLightDelegate::HandleShapeChanged() { - GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + } } void SimplePointLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp index 705a71571a..5ce8f6d563 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp @@ -24,8 +24,11 @@ namespace AZ::Render void SimpleSpotLightDelegate::HandleShapeChanged() { - GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); - GetFeatureProcessor()->SetDirection(GetLightHandle(), GetTransform().GetBasisZ()); + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + GetFeatureProcessor()->SetDirection(GetLightHandle(), GetTransform().GetBasisZ()); + } } float SimpleSpotLightDelegate::CalculateAttenuationRadius(float lightThreshold) const @@ -42,7 +45,10 @@ namespace AZ::Render void SimpleSpotLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) { - GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); + } } void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp index eb38e02a2e..8a0bd86965 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 9d2196de2b..deab9d2715 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp index 005e9a6ff5..c7349adefa 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.cpp index 815a2c276a..695868fb05 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h index 28e98082d0..a915e20591 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h @@ -42,7 +42,7 @@ namespace AZ RPI::ScenePtr m_scene; AZStd::string m_sceneName = "Material Thumbnail Scene"; AZStd::string m_pipelineName = "Material Thumbnail Pipeline"; - AzFramework::Scene* m_frameworkScene = nullptr; + AZStd::shared_ptr m_frameworkScene; RPI::RenderPipelinePtr m_renderPipeline; AZStd::unique_ptr m_entityContext; AZStd::vector m_passHierarchy; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp index 2a447ce3ec..100b0f61cd 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp @@ -100,24 +100,15 @@ namespace AZ data->m_scene->SetShaderResourceGroupCallback(callback); // Bind m_defaultScene to the GameEntityContext's AzFramework::Scene - Outcome createSceneOutcome; - AzFramework::SceneSystemRequestBus::BroadcastResult( - createSceneOutcome, - &AzFramework::SceneSystemRequests::CreateScene, - data->m_sceneName); + auto* sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Thumbnail system failed to get scene system implementation."); + Outcome, AZStd::string> createSceneOutcome = + sceneSystem->CreateScene(data->m_sceneName); AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str()); // This should never happen unless scene creation has changed. - createSceneOutcome.GetValue()->SetSubsystem(data->m_scene.get()); - data->m_frameworkScene = createSceneOutcome.GetValue(); - data->m_frameworkScene->SetSubsystem(data->m_scene.get()); - - bool success = false; - AzFramework::SceneSystemRequestBus::BroadcastResult( - success, - &AzFramework::SceneSystemRequests::SetSceneForEntityContextId, - data->m_entityContext->GetContextId(), - data->m_frameworkScene); - AZ_Assert(success, "Unable to set entity context on AzFramework::Scene: %s", data->m_sceneName.c_str()); + data->m_frameworkScene = createSceneOutcome.TakeValue(); + data->m_frameworkScene->SetSubsystem(data->m_scene); + data->m_frameworkScene->SetSubsystem(data->m_entityContext.get()); // Create a render pipeline from the specified asset for the window context and add the pipeline to the scene RPI::RenderPipelineDescriptor pipelineDesc; pipelineDesc.m_mainViewTagName = "MainCamera"; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp index 03ab03336d..bad7c2fe38 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -49,11 +49,13 @@ namespace AZ m_context->GetData()->m_scene->Deactivate(); m_context->GetData()->m_scene->RemoveRenderPipeline(m_context->GetData()->m_renderPipeline->GetId()); RPI::RPISystemInterface::Get()->UnregisterScene(m_context->GetData()->m_scene); - bool sceneRemovedSuccessfully = false; - AzFramework::SceneSystemRequestBus::BroadcastResult( - sceneRemovedSuccessfully, - &AzFramework::SceneSystemRequests::RemoveScene, - m_context->GetData()->m_sceneName); + + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Thumbnail system failed to get scene system implementation."); + [[maybe_unused]] bool sceneRemovedSuccessfully = sceneSystem->RemoveScene(m_context->GetData()->m_sceneName); + AZ_Assert( + sceneRemovedSuccessfully, "Thumbnail system was unable to remove scene '%s' from the scene system.", + m_context->GetData()->m_sceneName.c_str()); m_context->GetData()->m_scene = nullptr; m_context->GetData()->m_renderPipeline = nullptr; } diff --git a/Gems/Blast/Code/CMakeLists.txt b/Gems/Blast/Code/CMakeLists.txt index aabb6646aa..6c90357364 100644 --- a/Gems/Blast/Code/CMakeLists.txt +++ b/Gems/Blast/Code/CMakeLists.txt @@ -43,6 +43,7 @@ ly_add_target( ly_add_target( NAME Blast ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} NAMESPACE Gem + OUTPUT_NAME Blast.Gem FILES_CMAKE blast_shared_files.cmake INCLUDE_DIRECTORIES @@ -89,8 +90,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( NAME Blast.Editor GEM_MODULE - NAMESPACE Gem + OUTPUT_NAME Blast.Editor.Gem AUTOMOC FILES_CMAKE blast_editor_shared_files.cmake @@ -119,6 +120,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME Blast.Tests MODULE NAMESPACE Gem + OUTPUT_NAME Blast.Tests.Gem FILES_CMAKE blast_tests_files.cmake INCLUDE_DIRECTORIES @@ -142,6 +144,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME Blast.Editor.Tests MODULE NAMESPACE Gem + OUTPUT_NAME Blast.Editor.Tests.Gem FILES_CMAKE blast_editor_tests_files.cmake INCLUDE_DIRECTORIES diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp index 6bc7044cab..ff8c0db660 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp @@ -414,9 +414,17 @@ namespace EMotionFX } } + // Add missing keyframes at the end of the animation to match all keytracks' duration. + motionData->FixMissingEndKeyframes(); + // Let's prepare the motion data in the type we want. // This can later be extended with other types of motion data like least square fit curves etc. motionData->UpdateDuration(); + if (!motionData->VerifyIntegrity()) + { + AZ_Error(SceneUtil::ErrorWindow, false, "Data integrity issue in '%s'.", motionGroup.GetName().c_str()); + return SceneEvents::ProcessingResult::Failure; + } // Get the sample rate we have setup or that we have used. // Also make sure we don't sample at higher rate than we want. @@ -435,6 +443,11 @@ namespace EMotionFX } AZ_TracePrintf("EMotionFX", "Motion sample rate = %f", sampleRate); motionData->RemoveRedundantKeyframes(samplingRule ? !samplingRule->GetKeepDuration() : false); // Clear any tracks of non-animated parts. + if (!motionData->VerifyIntegrity()) + { + AZ_Error(SceneUtil::ErrorWindow, false, "Data integrity issue after removing redundant keyframes for '%s'.", motionGroup.GetName().c_str()); + return SceneEvents::ProcessingResult::Failure; + } // Create the desired type of motion data, based on what is selected in the motion sampling rule. MotionData* finalMotionData = nullptr; @@ -473,11 +486,16 @@ namespace EMotionFX InitAndOptimizeMotionData(finalMotionData, motionData, sampleRate, samplingRule.get(), rootJoints); } + if (!finalMotionData->VerifyIntegrity()) + { + AZ_Error(SceneUtil::ErrorWindow, false, "Data integrity issue in the final animation for '%s'.", motionGroup.GetName().c_str()); + return SceneEvents::ProcessingResult::Failure; + } + // Delete the data that we created out of the Scene API as it is no longer needed as we already extracted all the data from it // into our finalMotionData. delete motionData; context.m_motion.SetMotionData(finalMotionData); - return SceneEvents::ProcessingResult::Success; } } // namespace Pipeline diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index f5503ad6a5..cc4e206e08 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -775,7 +775,7 @@ namespace EMotionFX } // for all submotions motion->UpdateDuration(); - + AZ_Assert(motion->GetMotionData()->VerifyIntegrity(), "Data integrity issue in animation '%s'.", motion->GetName()); return true; } @@ -1572,7 +1572,7 @@ namespace EMotionFX } // for all submotions motion->UpdateDuration(); - + AZ_Assert(motion->GetMotionData()->VerifyIntegrity(), "Data integrity issue in animation '%s'.", motion->GetName()); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h index d9a6572ae4..53af107913 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h @@ -195,6 +195,7 @@ namespace EMotionFX virtual bool IsMorphAnimated(size_t morphDataIndex) const = 0; virtual bool IsFloatAnimated(size_t floatDataIndex) const = 0; virtual void UpdateDuration() {} + virtual bool VerifyIntegrity() const { return true; } void Resize(size_t numJoints, size_t numMorphs, size_t numFloats); void Clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp index 8a58300b88..0a746ed917 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp @@ -375,10 +375,48 @@ namespace EMotionFX return true; } + template + void NonUniformMotionData::FixMissingEndKeyframes(KeyTrackType& keytrack, float endTimeToMatch) + { + if (keytrack.m_times.empty() || keytrack.m_values.empty()) + { + return; + } + + if (!AZ::IsClose(keytrack.m_times.back(), endTimeToMatch, AZ::Constants::FloatEpsilon)) + { + keytrack.m_times.emplace_back(endTimeToMatch); + keytrack.m_values.emplace_back(keytrack.m_values.back()); + } + } + + void NonUniformMotionData::FixMissingEndKeyframes() + { + UpdateDuration(); + + for (JointData& jointData : m_jointData) + { + FixMissingEndKeyframes(jointData.m_positionTrack, m_duration); + FixMissingEndKeyframes(jointData.m_rotationTrack, m_duration); + +#ifndef EMFX_SCALE_DISABLED + FixMissingEndKeyframes(jointData.m_scaleTrack, m_duration); +#endif + } + + for (FloatData& morphData : m_morphData) + { + FixMissingEndKeyframes(morphData.m_track, m_duration); + } + + for (FloatData& floatData : m_floatData) + { + FixMissingEndKeyframes(floatData.m_track, m_duration); + } + } + void NonUniformMotionData::UpdateDuration() { - AZ_Assert(VerifyIntegrity(), "Data integrity issue!"); - for (const JointData& jointData : m_jointData) { if (!jointData.m_positionTrack.m_times.empty()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h index 15b082caba..bd710c3453 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h @@ -82,7 +82,15 @@ namespace EMotionFX void ClearMorphSamples(size_t morphDataIndex) override; void ClearFloatSamples(size_t floatDataIndex) override; - bool VerifyIntegrity() const; + bool VerifyIntegrity() const override; + + //! Animation tracks in the DCC tool formats are often stored individually, each having its own duration. + //! For the motion data, it is required to have tracks with the same duration and e.g. a position track + //! has to match the duration of a morph track. This will be automatically fixed by adding missing + //! keyframes at the end of the tracks to match the animation's global duration. The value of these + //! are the same as the last one of the given track so that they freeze at that value. + void FixMissingEndKeyframes(); + void ScaleData(float scaleFactor) override; void UpdateDuration() override; @@ -155,6 +163,9 @@ namespace EMotionFX void RemoveMorphSampleData(size_t morphDataIndex) override; void RemoveFloatSampleData(size_t floatDataIndex) override; + template + void FixMissingEndKeyframes(KeyTrackType& keytrack, float endTimeToMatch); + private: AZStd::vector m_jointData; AZStd::vector m_morphData; diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h index ea927a1453..edb2f4ae73 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h @@ -29,7 +29,7 @@ namespace Multiplayer { public: AZ_CLASS_ALLOCATOR(NetworkPrefabProcessor, AZ::SystemAllocator, 0); - AZ_RTTI(NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor); + AZ_RTTI(Multiplayer::NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor); ~NetworkPrefabProcessor() override = default; diff --git a/Gems/Multiplayer/Registry/prefab.tools.setreg b/Gems/Multiplayer/Registry/prefab.tools.setreg index 4f20f88df9..7f25cf9a43 100644 --- a/Gems/Multiplayer/Registry/prefab.tools.setreg +++ b/Gems/Multiplayer/Registry/prefab.tools.setreg @@ -9,14 +9,17 @@ { "Stack": { + "PlayInEditor": + [ + { "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover" }, + { "$type": "Multiplayer::NetworkPrefabProcessor" }, + { "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor" } + ], "GameObjectCreation": [ { "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover" }, - { "$type": "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}" }, - { - "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor", - "SerializationFormat": "Text" // Options are "Binary" (default) or "Text". Prefer "Binary" for performance. - } + { "$type": "Multiplayer::NetworkPrefabProcessor" }, + { "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor" } ] } } diff --git a/Gems/NvCloth/Code/CMakeLists.txt b/Gems/NvCloth/Code/CMakeLists.txt index 983e7ff8f8..d83190a05c 100644 --- a/Gems/NvCloth/Code/CMakeLists.txt +++ b/Gems/NvCloth/Code/CMakeLists.txt @@ -43,6 +43,7 @@ ly_add_target( ly_add_target( NAME NvCloth ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} NAMESPACE Gem + OUTPUT_NAME NvCloth.Gem FILES_CMAKE nvcloth_shared_files.cmake INCLUDE_DIRECTORIES @@ -83,8 +84,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( NAME NvCloth.Editor GEM_MODULE - NAMESPACE Gem + OUTPUT_NAME NvCloth.Editor.Gem FILES_CMAKE nvcloth_editor_shared_files.cmake INCLUDE_DIRECTORIES @@ -109,6 +110,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME NvCloth.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem + OUTPUT_NAME NvCloth.Tests.Gem FILES_CMAKE nvcloth_tests_files.cmake INCLUDE_DIRECTORIES @@ -134,6 +136,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME NvCloth.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem + OUTPUT_NAME NvCloth.Editor.Tests.Gem FILES_CMAKE nvcloth_editor_tests_files.cmake INCLUDE_DIRECTORIES diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt index e6f8fc7188..386e48221e 100644 --- a/Gems/PhysX/Code/CMakeLists.txt +++ b/Gems/PhysX/Code/CMakeLists.txt @@ -52,6 +52,7 @@ ly_add_target( ly_add_target( NAME PhysX ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} NAMESPACE Gem + OUTPUT_NAME PhysX.Gem FILES_CMAKE ${physx_shared_files} COMPILE_DEFINITIONS @@ -118,8 +119,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( NAME PhysX.Editor GEM_MODULE - NAMESPACE Gem + OUTPUT_NAME PhysX.Editor.Gem AUTOMOC FILES_CMAKE physx_editor_shared_files.cmake @@ -147,6 +148,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME PhysX.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem + OUTPUT_NAME PhysX.Tests.Gem FILES_CMAKE physx_tests_files.cmake INCLUDE_DIRECTORIES @@ -166,7 +168,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googlebenchmark( NAME Gem::PhysX.Benchmarks TARGET Gem::PhysX.Tests - TIMEOUT 2400 #40mins + TIMEOUT 1500 #25mins ) list(APPEND testTargets PhysX.Tests) @@ -175,6 +177,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME PhysX.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem + OUTPUT_NAME PhysX.Editor.Tests.Gem FILES_CMAKE physx_editor_tests_files.cmake INCLUDE_DIRECTORIES diff --git a/Gems/PhysXDebug/Code/CMakeLists.txt b/Gems/PhysXDebug/Code/CMakeLists.txt index a3730e5bcf..f198f6f26e 100644 --- a/Gems/PhysXDebug/Code/CMakeLists.txt +++ b/Gems/PhysXDebug/Code/CMakeLists.txt @@ -25,6 +25,7 @@ endif() ly_add_target( NAME PhysXDebug ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} NAMESPACE Gem + OUTPUT_NAME PhysXDebug.Gem FILES_CMAKE ${physx_files} INCLUDE_DIRECTORIES @@ -47,8 +48,8 @@ ly_add_target( if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( NAME PhysXDebug.Editor GEM_MODULE - NAMESPACE Gem + OUTPUT_NAME PhysXDebug.Editor.Gem FILES_CMAKE ${physx_editor_files} COMPILE_DEFINITIONS diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 921613cea8..5e11b17c54 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -234,7 +234,7 @@ namespace ScriptCanvas AZStd::set sortedVariables; for (const auto& variablePair : sourceVariables) { - if (variablePair.second.GetScope() == VariableFlags::Scope::Graph) + if (variablePair.second.GetScope() != VariableFlags::Scope::FunctionReadOnly) { sortedVariables.insert(&variablePair.second); } @@ -244,14 +244,19 @@ namespace ScriptCanvas // #functions2 slot<->variable consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering m_sourceVariableByDatum.insert(AZStd::make_pair(datum, &variablePair.second)); } + } for (auto& sourceVariable : sortedVariables) { auto datum = sourceVariable->GetDatum(); AZ_Assert(datum != nullptr, "the datum must be valid"); + // #functions2 slot<->variable check to verify if it is a member variable - auto variable = AddMemberVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()); + auto variable = sourceVariable->GetScope() == VariableFlags::Scope::Graph + ? AddMemberVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()) + : AddVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()); + variable->m_isExposedToConstruction = sourceVariable->IsComponentProperty(); // also, all nodeables with !empty editor data have to be exposed // \todo future optimizations will involve checking equality against a default constructed object @@ -1205,7 +1210,13 @@ namespace ScriptCanvas } auto& variableNamesInStart = ModStaticVariablesNames(startNode); - variableNamesInStart.insert(variableNamesInStart.end(), m_staticVariableNames.begin(), m_staticVariableNames.end()); + for (auto& staticVariable : m_staticVariableNames) + { + if (AZStd::find(variableNamesInStart.begin(), variableNamesInStart.end(), staticVariable) == variableNamesInStart.end()) + { + variableNamesInStart.push_back(staticVariable); + } + } } void AbstractCodeModel::CreateUserFunctionDefinition(const Node& node, const Slot& entrySlot) @@ -1598,7 +1609,7 @@ namespace ScriptCanvas const AZStd::pair* AbstractCodeModel::FindStaticVariable(VariableConstPtr variable) const { auto iter = AZStd::find_if - (m_staticVariableNames.begin() + ( m_staticVariableNames.begin() , m_staticVariableNames.end() , [&](const auto& candidate) { return candidate.first == variable; }); @@ -2701,15 +2712,20 @@ namespace ScriptCanvas AZStd::string name = AddTranslationVariableName(AZStd::string::format("s_%sCloneSource", staticVariable->m_name.c_str())); staticVariableNames.push_back({ staticVariable, name }); - if (!staticVariable->m_isMember) + if (!staticVariable->m_isMember && !staticVariable->m_isFromFunctionDefinitionSlot) { if (staticVariable->m_source) { - ModStaticVariablesNames(staticVariable->m_source).push_back({ staticVariable, name }); - } - else - { - AddError(nullptr, aznew Internal::ParseError(AZ::EntityId(), "Missing source for local variable that requires static initializer")); + auto& localStatics = ModStaticVariablesNames(staticVariable->m_source); + auto iter = AZStd::find_if + ( localStatics.begin() + , localStatics.end() + , [&](const auto& candidate) { return candidate.first == staticVariable; }); + + if (iter == localStatics.end()) + { + localStatics.push_back({ staticVariable, name }); + } } } } @@ -4392,6 +4408,7 @@ namespace ScriptCanvas // Scope and name are initialized later variable->m_sourceSlotId = slot->GetId(); + variable->m_isFromFunctionDefinitionSlot = true; variablesBySlots.insert({ slot, variable }); m_variables.push_back(variable); } @@ -4997,6 +5014,24 @@ namespace ScriptCanvas m_variableUse.localVariables.insert(usage.localVariables.begin(), usage.localVariables.end()); m_variableUse.memberVariables.insert(usage.memberVariables.begin(), usage.memberVariables.end()); + + for (auto variable : m_variableUse.localVariables) + { + if (const AZStd::pair* pair = FindStaticVariable(variable)) + { + auto& localStatics = ModStaticVariablesNames(execution); + auto iter = AZStd::find_if + (localStatics.begin() + , localStatics.end() + , [&](const auto& candidate) { return candidate.first == variable; }); + + if (iter == localStatics.end()) + { + localStatics.push_back(*pair); + } + } + } + m_variableUseByExecution.emplace(execution, listener.MoveUsedVariables()); return (!usage.usesExternallyInitializedVariables) && usesOnlyLocalVariables && listener.IsPure(); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h index c2605dce45..ab047fb580 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h @@ -269,6 +269,7 @@ namespace ScriptCanvas bool m_isUnused = false; // used for multiple return situations, and to prevent compile errors bool m_isExposedToConstruction = false; bool m_isDebugOnly = false; + bool m_isFromFunctionDefinitionSlot = false; Variable() = default; Variable(Datum&& datum); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp index e0dd016140..8063a35896 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp @@ -26,6 +26,39 @@ #include "GraphToLua.h" +namespace GraphToLuaUtilityCpp +{ + AZStd::string EqualSigns(size_t numEqualSignsRequired) + { + AZStd::string equalSigns = ""; + while (numEqualSignsRequired--) + { + equalSigns += "="; + } + + return equalSigns; + } + + AZStd::string MakeLongBracketString(const AZStd::string& formattedString) + { + size_t numEqualSignsRequired = 0; + + for (;;) + { + auto candidate = AZStd::string::format("]%s]", EqualSigns(numEqualSignsRequired).c_str()); + + if (formattedString.find(candidate) == AZStd::string::npos) + { + break; + } + + ++numEqualSignsRequired; + } + + return EqualSigns(numEqualSignsRequired); + } +} + namespace ScriptCanvas { namespace Translation @@ -352,7 +385,11 @@ namespace ScriptCanvas } case Data::eType::String: - return AZStd::string::format("\"%s\"", datum.GetAs()->data()); + { + const AZStd::string& formattedString = *datum.GetAs(); + const AZStd::string bracketString = GraphToLuaUtilityCpp::MakeLongBracketString(formattedString); + return AZStd::string::format("[%s[%s]%s]", bracketString.c_str(), formattedString.c_str(), bracketString.c_str()); + } case Data::eType::EntityID: return EntityIdValueToString(*datum.GetAs(), config); diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUnique.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUnique.scriptcanvas new file mode 100644 index 0000000000..25c990db9c --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUnique.scriptcanvas @@ -0,0 +1,2771 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUniqueFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUniqueFunction.scriptcanvas new file mode 100644 index 0000000000..95dd804bd5 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUniqueFunction.scriptcanvas @@ -0,0 +1,2155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_StringSanitization.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_StringSanitization.scriptcanvas new file mode 100644 index 0000000000..c5bef2768b --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_StringSanitization.scriptcanvas @@ -0,0 +1,1461 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index 3e727ca3db..a46bb3323b 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -90,6 +90,11 @@ public: } }; +TEST_F(ScriptCanvasTestFixture, StringSanitization) +{ + RunUnitTestGraph("LY_SC_UnitTest_StringSanitization"); +} + TEST_F(ScriptCanvasTestFixture, InterpretedHelloWorld) { RunUnitTestGraph("LY_SC_UnitTest_HelloWorld"); @@ -135,6 +140,11 @@ TEST_F(ScriptCanvasTestFixture, InterpretedEventHandlerDisconnect) RunUnitTestGraph("LY_SC_UnitTest_EventHandlerDisconnect", runSpec); } +TEST_F(ScriptCanvasTestFixture, FunctionLocalStaticsUnique) +{ + RunUnitTestGraph("LY_SC_UnitTest_FunctionLocalStaticsUnique"); +} + TEST_F(ScriptCanvasTestFixture, FunctionContainerInputTest) { RunUnitTestGraph("LY_SC_UnitTest_FunctionContainerInputTest"); diff --git a/Registry/Platform/Windows/streamer.game.setreg b/Registry/Platform/Windows/streamer.game.setreg index f45f009b03..7788227fb5 100644 --- a/Registry/Platform/Windows/streamer.game.setreg +++ b/Registry/Platform/Windows/streamer.game.setreg @@ -73,7 +73,7 @@ "MaxFileHandles": 1024, "MaxMetaDataCache": 1024, "Overcommit": 8, - "EnableFileSharing": false, + "EnableFileSharing": true, "EnableUnbufferedReads": false }, { diff --git a/Registry/Platform/Windows/streamer.test.setreg b/Registry/Platform/Windows/streamer.test.setreg index a87dc599c8..13e4fa2d57 100644 --- a/Registry/Platform/Windows/streamer.test.setreg +++ b/Registry/Platform/Windows/streamer.test.setreg @@ -21,7 +21,7 @@ "MaxFileHandles": 1024, "MaxMetaDataCache": 1024, "Overcommit": 8, - "EnableFileSharing": false, + "EnableFileSharing": true, "EnableUnbufferedReads": true, "MinimalReporting": true }, diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index 6bd809ec41..5ba8d9a11b 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -24,8 +24,8 @@ ly_set(LY_PYTEST_EXECUTABLE ${LY_PYTHON_CMD} -B -m pytest -v --tb=short --show-c ly_set(LY_TEST_GLOBAL_KNOWN_SUITE_NAMES "smoke" "main" "periodic" "benchmark" "sandbox") ly_set(LY_TEST_GLOBAL_KNOWN_REQUIREMENTS "gpu") -# Set default to 20 minutes -ly_set(LY_TEST_DEFAULT_TIMEOUT 1200) +# Set default test aborts to 25 minutes, avoids hitting the CI pipeline inactivity timeout usually set to 30 minutes +ly_set(LY_TEST_DEFAULT_TIMEOUT 1500) # Add the CMake Test targets for each suite if testing is supported if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) @@ -115,6 +115,8 @@ function(ly_add_test) # Set default test module timeout if(NOT ly_add_test_TIMEOUT) set(ly_add_test_TIMEOUT ${LY_TEST_DEFAULT_TIMEOUT}) + elseif(ly_add_test_TIMEOUT GREATER LY_TEST_DEFAULT_TIMEOUT) + message(WARNING "TIMEOUT for test ${ly_add_test_NAME} set at ${ly_add_test_TIMEOUT} seconds which is longer than the default of ${LY_TEST_DEFAULT_TIMEOUT}. Allowing a single module to run exceedingly long creates problems in a CI pipeline.") endif() if(NOT ly_add_test_TEST_COMMAND) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index b5dc7a30ef..fb3a7b1b09 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -159,15 +159,15 @@ function(ly_generate_target_config_file NAME) elseif(target_type STREQUAL MODULE_LIBRARY) string(APPEND target_location "\"\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$\"") elseif(target_type STREQUAL SHARED_LIBRARY) - string(APPEND target_location "\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"") + string(APPEND target_location "\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"") string(APPEND target_file_contents "ly_add_dependencies(${NAME} \"\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$\")\n") else() # STATIC_LIBRARY, OBJECT_LIBRARY, INTERFACE_LIBRARY string(APPEND target_location "\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"") endif() - string(APPEND target_file_contents + string(APPEND target_file_contents "set(target_location ${target_location}) -set_target_properties(${NAME} +set_target_properties(${NAME} PROPERTIES $<$:IMPORTED_LOCATION \"\${target_location}\"> IMPORTED_LOCATION_$> \"\${target_location}\" @@ -327,11 +327,18 @@ function(ly_setup_others) COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} ) - # Gem Source Assets + # Gem Source Assets and Registry # Find all gem directories relative to the CMake Source Dir - file(GLOB_RECURSE gems_assets_path RELATIVE ${CMAKE_SOURCE_DIR} "Gems/*/Assets") - foreach (gem_assets_path ${gems_assets_path}) + file( + GLOB_RECURSE + gems_assets_path + LIST_DIRECTORIES TRUE + RELATIVE "${CMAKE_SOURCE_DIR}/" + "Gems/*" + ) + list(FILTER gems_assets_path INCLUDE REGEX "/(Assets|Registry)$") + foreach (gem_assets_path ${gems_assets_path}) set(gem_abs_assets_path ${CMAKE_SOURCE_DIR}/${gem_assets_path}/) if (EXISTS ${gem_abs_assets_path}) # The trailing slash is IMPORTANT here as that is needed to prevent diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index bb9bd4ff48..98f31eddea 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -504,9 +504,8 @@ try { envVars['IS_UNIX'] = 1 } withEnv(GetEnvStringList(envVars)) { + def build_job_name = build_job.key try { - def build_job_name = build_job.key - CreateSetupStage(pipelineConfig, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars).call() if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages @@ -517,12 +516,6 @@ try { } else { CreateBuildStage(pipelineConfig, platform.key, build_job.key, envVars).call() } - - if (env.MARS_REPO && platform.value.build_types[build_job_name].PARAMETERS.containsKey('TEST_METRICS') && platform.value.build_types[build_job_name].PARAMETERS.TEST_METRICS == 'True') { - def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY - def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION - CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() - } } catch(Exception e) { // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java @@ -537,6 +530,11 @@ try { } } finally { + if (env.MARS_REPO && platform.value.build_types[build_job_name].PARAMETERS.containsKey('TEST_METRICS') && platform.value.build_types[build_job_name].PARAMETERS.TEST_METRICS == 'True') { + def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY + def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION + CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() + } CreateTeardownStage(envVars).call() } } diff --git a/scripts/build/lambda/delete_github_branch_ebs.py b/scripts/build/lambda/delete_github_branch_ebs.py index 8163cee762..d933f23bfb 100644 --- a/scripts/build/lambda/delete_github_branch_ebs.py +++ b/scripts/build/lambda/delete_github_branch_ebs.py @@ -80,6 +80,10 @@ def create_response(status, success=0, failure=0, repository_name=None, branch_n 'statusCode': 401, 'body': 'Unauthorized', 'isBase64Encoded': 'false' + }, + 'unsupported': { + 'statusCode': 204, + 'isBase64Encoded': 'false' } } return response[status] @@ -90,17 +94,24 @@ def lambda_handler(event, context): if event.get('resource', '') == '/delete-github-branch-ebs': headers = event['headers'] payload = event['body'] - if headers['X-GitHub-Event'] == 'delete': - # Validate github webhook request here since request body cannot be passed to API Gateway lambda authorizer. - if verify_signature(headers, payload): - # Convert payload from string type to json to get repository name and branch name - payload = json.loads(payload) - repository_name = payload['repository']['full_name'] + # Validate github webhook request here since request body cannot be passed to API Gateway lambda authorizer. + if verify_signature(headers, payload): + # Convert payload from string type to json to get repository name and branch name + payload = json.loads(payload) + repository_name = payload['repository']['full_name'] + if headers['X-GitHub-Event'] == 'delete': + # On Github branch/tag delete event branch_name = payload['ref'] - (success, failure) = delete_volumes(repository_name, branch_name) - if not failure: - return create_response('success', success, failure, repository_name, branch_name) - else: - return create_response('failure', success, failure, repository_name, branch_name) + elif headers['X-GitHub-Event'] == 'pull_request' and payload['action'] == 'closed': + # On Github pull request closed event + pull_request_number = payload['number'] + branch_name = f'PR-{pull_request_number}' else: - return create_response('unauthorized') + return create_response('unsupported') + (success, failure) = delete_volumes(repository_name, branch_name) + if not failure: + return create_response('success', success, failure, repository_name, branch_name) + else: + return create_response('failure', success, failure, repository_name, branch_name) + else: + return create_response('unauthorized') diff --git a/scripts/bundler/get_shader_list.py b/scripts/bundler/get_shader_list.py index d8e05cb35e..2a275cce96 100644 --- a/scripts/bundler/get_shader_list.py +++ b/scripts/bundler/get_shader_list.py @@ -55,7 +55,7 @@ def get_shader_list(project_path, asset_platform, shader_type, shader_platform, parser = argparse.ArgumentParser(description='Gets the shader list for a specific platform from the current shader compiler server') -parser.add_argument('-g', 'project-path', type=pathlib.Path, required=True, help="Path to the project") +parser.add_argument('-g', '--project-path', type=pathlib.Path, required=True, help="Path to the project") parser.add_argument('asset-platform', type=str, help="The asset cache sub folder to use for shader generation") parser.add_argument('shader-type', type=str, help="The shader type to use") parser.add_argument('-p', '--shader_platform', type=str, required=False, default='', help="The target platform to generate shaders for.")