From d8afec36cd2390521b87468ce682d7fc229714f1 Mon Sep 17 00:00:00 2001 From: sweeneys Date: Mon, 26 Apr 2021 12:38:00 -0700 Subject: [PATCH 01/30] Change test module default timeouts to 25 minutes to unblock Periodic and Sandbox CI builds, without incurring the costs involved with increased log verbosity. --- .../Gem/PythonTests/CMakeLists.txt | 32 +++++++++---------- .../asset_processor_tests/CMakeLists.txt | 4 +-- Gems/PhysX/Code/CMakeLists.txt | 2 +- cmake/LYTestWrappers.cmake | 6 ++-- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index c23d92d60a..e9b3095809 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -25,7 +25,7 @@ add_subdirectory(assetpipeline) # TEST_SUITE main # TEST_SERIAL # PATH ${CMAKE_CURRENT_LIST_DIR}/physics/TestSuite_Active.py -# TIMEOUT 3600 +# TIMEOUT 1500 # RUNTIME_DEPENDENCIES # Legacy::Editor # Legacy::CryRenderNULL @@ -39,7 +39,7 @@ add_subdirectory(assetpipeline) # TEST_SUITE sandbox # TEST_SERIAL # PATH ${CMAKE_CURRENT_LIST_DIR}/physics/TestSuite_Sandbox.py -# TIMEOUT 3600 +# TIMEOUT 1500 # RUNTIME_DEPENDENCIES # Legacy::Editor # Legacy::CryRenderNULL @@ -57,7 +57,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 @@ -71,7 +71,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 @@ -88,7 +88,7 @@ endif() # TEST_SUITE main # TEST_SERIAL # PATH ${CMAKE_CURRENT_LIST_DIR}/WhiteBox/TestSuite_Active.py -# TIMEOUT 3600 +# TIMEOUT 1500 # RUNTIME_DEPENDENCIES # Legacy::Editor # Legacy::CryRenderNULL @@ -107,7 +107,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 @@ -123,7 +123,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 @@ -141,7 +141,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 @@ -160,7 +160,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -183,7 +183,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 @@ -200,7 +200,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 @@ -217,7 +217,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 @@ -234,7 +234,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 @@ -250,7 +250,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 @@ -266,7 +266,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 @@ -284,7 +284,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/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt index e6f8fc7188..faadc3f8b2 100644 --- a/Gems/PhysX/Code/CMakeLists.txt +++ b/Gems/PhysX/Code/CMakeLists.txt @@ -166,7 +166,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) 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) From 22a8885502607cbe236cfb6994a11b43729c2e16 Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 28 Apr 2021 12:10:29 -0700 Subject: [PATCH 02/30] Fixing test metrics to run on test failures --- scripts/build/Jenkins/Jenkinsfile | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index bb9bd4ff48..07a4023674 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -505,6 +505,8 @@ try { } withEnv(GetEnvStringList(envVars)) { try { + def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY + def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION def build_job_name = build_job.key CreateSetupStage(pipelineConfig, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars).call() @@ -517,12 +519,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 +533,14 @@ try { } } finally { + try { + 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') { + CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() + } + } + catch(Exception e) { + echo "Test metrics failed due to: ${e}" + } CreateTeardownStage(envVars).call() } } From c554a7b17eeedf339c956c9cbd5bc20935df38a4 Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 28 Apr 2021 14:22:31 -0700 Subject: [PATCH 03/30] Moved variable assigments and removed try/catch block for test metrics --- scripts/build/Jenkins/Jenkinsfile | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 07a4023674..58d5baa2a4 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -505,8 +505,6 @@ try { } withEnv(GetEnvStringList(envVars)) { try { - def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY - def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION def build_job_name = build_job.key CreateSetupStage(pipelineConfig, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars).call() @@ -533,13 +531,10 @@ try { } } finally { - try { - 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') { - CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() - } - } - catch(Exception e) { - echo "Test metrics failed due to: ${e}" + 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() } From 7dd7e82d861b9c9db96391c7af619b15e6ab6a6d Mon Sep 17 00:00:00 2001 From: Eric Phister <52085794+amzn-phist@users.noreply.github.com> Date: Wed, 28 Apr 2021 18:54:02 -0500 Subject: [PATCH 04/30] LYN-2723: Fixes issues with bad project or engine paths (#369) * Setup NativeUIRequests as an AZ::Interface. Adds a NativeUISystemComponent to AzFramework Application. * Renames NativeUISystemComponent (class) to NativeUISystem, since it's no longer a Component. * Minor update to SettingsRegistryInterface::Remove doc-comments for accuracy. * Fixes to make an early fatal shutdown of Editor occur without crash. * LYN-2723: Updates startup to handle errors: engine root is empty, no valid project.json found (mismatched engine name), or bad project path (launch project picker dialog). * LYN-2723: Minor formatting/spelling edits. * LYN-2723: Moves ParseCommandLine from ComponentApplication to SettingsRegistryMergeUtils so it can be used in more places. * Misc fixes. 'wait_for_connect' setting wasn't being properly applied to AP connection settings. Fix infinite loop in CCmdLine::Next. * LYN-2723: Addresses review feedback. * LYN-2723: Reverts some changes that caused a unit test to fail. * LYN-2723: Reverts one more change that was unnecessary. --- Code/Framework/AzCore/AzCore/AzCoreModule.cpp | 2 - .../AzCore/Component/ComponentApplication.cpp | 76 +++++----- .../AzCore/Component/ComponentApplication.h | 3 - .../AzCore/AzCore/NativeUI/NativeUIRequests.h | 72 +++++----- .../NativeUI/NativeUISystemComponent.cpp | 63 ++------- .../AzCore/NativeUI/NativeUISystemComponent.h | 50 +++---- .../AzCore/AzCore/Settings/SettingsRegistry.h | 2 +- .../Settings/SettingsRegistryMergeUtils.cpp | 131 +++++++++++++++--- .../Settings/SettingsRegistryMergeUtils.h | 6 + .../NativeUISystemComponent_Android.cpp | 2 +- .../NativeUISystemComponent_Unimplemented.cpp | 13 +- .../NativeUI/NativeUISystemComponent_Mac.mm | 2 +- .../NativeUISystemComponent_Windows.cpp | 2 +- .../NativeUI/NativeUISystemComponent_iOS.mm | 2 +- .../AzFramework/Application/Application.cpp | 17 ++- .../AzFramework/Application/Application.h | 2 + .../Asset/AssetSystemComponentHelper.cpp | 2 +- .../ProjectManager/ProjectManager.cpp | 14 +- .../Application/ToolsApplication.cpp | 4 + Code/Sandbox/Editor/CryEdit.cpp | 28 +++- Code/Sandbox/Editor/main.cpp | 11 +- Code/Tools/RC/ResourceCompiler/main.cpp | 2 + 22 files changed, 281 insertions(+), 225 deletions(-) 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/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 27f6f222dd..ed56803ef2 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; } } @@ -875,6 +919,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/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/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/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index b3eaaddc42..68b7a8a2a2 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -5045,12 +5045,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 +5074,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) // connect relevant buses to global settings gSettings.Connect(); - CCryEditApp* theApp = new CCryEditApp(); + auto theApp = AZStd::make_unique(); // this does some magic to set the current directory... { QCoreApplication app(argc, argv); @@ -5145,8 +5161,6 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) } - delete theApp; - gSettings.Disconnect(); return ret; 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/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, {}); From a90793cb94fc28c5bb234093626521b6d4288eaf Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 28 Apr 2021 17:40:49 -0700 Subject: [PATCH 05/30] Fix viewport box selection rendering --- .../Manipulators/EditorVertexSelection.cpp | 4 ++-- .../ViewportSelection/EditorBoxSelect.cpp | 16 ++++++++++------ .../ViewportSelection/EditorBoxSelect.h | 2 +- .../EditorTransformComponentSelection.cpp | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) 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/ViewportSelection/EditorBoxSelect.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp index d9cf4af944..091dcccf18 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( + AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize; + + debugDisplay.DrawWireQuad2d( + AZ::Vector2( + static_cast(m_boxSelectRegion->x()), static_cast(m_boxSelectRegion->y())) / viewportSize, + AZ::Vector2( static_cast(m_boxSelectRegion->x()) + static_cast(m_boxSelectRegion->width()), - static_cast(m_boxSelectRegion->y()) + static_cast(m_boxSelectRegion->height()), 0.0f)); + static_cast(m_boxSelectRegion->y()) + static_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 433602e6d8..fa34b48e2d 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() From 9311dc4cb9710072a8f9748159ba21da31147f89 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 28 Apr 2021 17:42:43 -0700 Subject: [PATCH 06/30] Fix RenderViewportWidget::ViewportWorldToScreen, which fixes box selection --- .../Code/Source/Viewport/RenderViewportWidget.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 0f1e5718db..31ee110062 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -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}; } From 186066edc101dcb660de65736f1884d9d9561e3b Mon Sep 17 00:00:00 2001 From: pruiksma Date: Wed, 28 Apr 2021 20:36:35 -0500 Subject: [PATCH 07/30] [ATOM-15380] Cherry picking changes from 1.0 - cfdb70978868aa5d0040d3b79994a26e9f82ca39 --- [ATOM-15380] Fix cases where light delegates will attempt to set properties on the feature processor without having a valid handle. --- .../Source/CoreLights/DiskLightDelegate.cpp | 25 ++++++++++++------- .../CoreLights/SimplePointLightDelegate.cpp | 10 ++++++-- .../CoreLights/SimpleSpotLightDelegate.cpp | 12 ++++++--- 3 files changed, 33 insertions(+), 14 deletions(-) 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 From 389846c45c91e5175189b309842661481f31c774 Mon Sep 17 00:00:00 2001 From: moudgils Date: Wed, 28 Apr 2021 21:24:10 -0700 Subject: [PATCH 08/30] Disable metal shaders that dont cross compile correctly --- .../Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader | 3 ++- .../Shaders/PostProcessing/LuminanceHistogramGenerator.shader | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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"] } From f52975be83c4ddd6579b3726d5737370ef2d464c Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 28 Apr 2021 22:40:41 -0700 Subject: [PATCH 09/30] use long brackets to implement SC strings in Lua --- .../Translation/GraphToLuaUtility.cpp | 39 +- ...C_UnitTest_StringSanitization.scriptcanvas | 1461 +++++++++++++++++ .../Tests/ScriptCanvas_RuntimeInterpreted.cpp | 5 + 3 files changed, 1504 insertions(+), 1 deletion(-) create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_StringSanitization.scriptcanvas 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_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..a73c3c41a1 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"); From 1b8c62f2941623b4da9f0274e801fb78000179dd Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 28 Apr 2021 23:04:32 -0700 Subject: [PATCH 10/30] Fixed out of scope variable --- scripts/build/Jenkins/Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 58d5baa2a4..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 From cbf5a3f5b12af9e826acb1e86cd516ac4c3310ca Mon Sep 17 00:00:00 2001 From: nvsickle Date: Thu, 29 Apr 2021 00:06:37 -0700 Subject: [PATCH 11/30] Use aznumeric_cast in EditorBoxSelect::Display2d --- .../AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp index 091dcccf18..2e467caa4c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp @@ -87,10 +87,10 @@ namespace AzToolsFramework debugDisplay.DrawWireQuad2d( AZ::Vector2( - static_cast(m_boxSelectRegion->x()), static_cast(m_boxSelectRegion->y())) / viewportSize, + aznumeric_cast(m_boxSelectRegion->x()), aznumeric_cast(m_boxSelectRegion->y())) / viewportSize, AZ::Vector2( - static_cast(m_boxSelectRegion->x()) + static_cast(m_boxSelectRegion->width()), - static_cast(m_boxSelectRegion->y()) + static_cast(m_boxSelectRegion->height())) / viewportSize, + 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(); From f65ef56654ba0ad7afc8cb74d9517572f77ab6ee Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Thu, 29 Apr 2021 01:02:47 -0700 Subject: [PATCH 12/30] Added maybe_unsed to result codes that are only used in Asserts. --- .../Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp | 2 +- .../Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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; From ca8335f9f4e6f3d016da42686d4706ede4a792a3 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 29 Apr 2021 14:33:55 +0100 Subject: [PATCH 13/30] Enabled file sharing in the Dev mode for the Streamer --- Engine/Registry/Platform/Windows/streamer.game.setreg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/Registry/Platform/Windows/streamer.game.setreg b/Engine/Registry/Platform/Windows/streamer.game.setreg index f45f009b03..7788227fb5 100644 --- a/Engine/Registry/Platform/Windows/streamer.game.setreg +++ b/Engine/Registry/Platform/Windows/streamer.game.setreg @@ -73,7 +73,7 @@ "MaxFileHandles": 1024, "MaxMetaDataCache": 1024, "Overcommit": 8, - "EnableFileSharing": false, + "EnableFileSharing": true, "EnableUnbufferedReads": false }, { From 7e633d907e750e1cd511ccaff411da97c0f8fe45 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 29 Apr 2021 16:26:13 +0100 Subject: [PATCH 14/30] Enabled NetworkPrefabProcessor for Ctrl+G --- .../Code/Source/Pipeline/NetworkPrefabProcessor.h | 2 +- Gems/Multiplayer/Registry/prefab.tools.setreg | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) 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" } ] } } From 45fd86c2bf958399366cd2ee9729bac3092209a4 Mon Sep 17 00:00:00 2001 From: sharmajs-amzn <82233357+sharmajs-amzn@users.noreply.github.com> Date: Thu, 29 Apr 2021 08:27:34 -0700 Subject: [PATCH 15/30] {LYN-2848} Asset Processor: Modifying the Allowed or Rejected list merges previously existing Connections into one record (#363) {LYN-2848} Asset Processor: Modifying the Allowed or Rejected list merges previously existing Connections into one record https://jira.agscollab.com/browse/LYN-2848 launched ap gui and tested manually. --- Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 5e4094b2588b2ee56d0681fdca9a9c5f2bd509b1 Mon Sep 17 00:00:00 2001 From: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> Date: Thu, 29 Apr 2021 08:50:48 -0700 Subject: [PATCH 16/30] Revamped AzFramework::Scene (#332) Updated AzFramework::Scene to allow it to serve as the one-stop location for localized singletons. Localized singletons in this case are instance that can only occur once in an environment but multiple times within an application. As an example, this allows settings up a single camera per viewport for instance. Highlights of changes: Replaced the original ebuses with interfaces and events for easy of use and performance. Removed the Entity Context specific code and moved that to new locations within the Entity Context itself. Allowed basic inheritance. If a subsystem isn't found in a scene the parent can optionally be searched. Scenes can enter a zombie state and avoid immediately being deleted. This is needed for situations where subsystems can't be destroyed until async calls have been completed. --- ...zFrameworkConfigurationSystemComponent.cpp | 34 ++- .../AzFramework/Entity/EntityContext.cpp | 26 +++ .../AzFramework/Entity/EntityContext.h | 8 +- .../AzFramework/Entity/GameEntityContextBus.h | 2 + .../Entity/GameEntityContextComponent.h | 1 + .../AzFramework/Render/Intersector.cpp | 15 +- .../AzFramework/Render/Intersector.h | 2 + .../AzFramework/AzFramework/Scene/Scene.cpp | 95 +++++++- .../AzFramework/AzFramework/Scene/Scene.h | 133 ++++++----- .../AzFramework/AzFramework/Scene/Scene.inl | 108 +++++++++ .../AzFramework/Scene/SceneSystemBus.h | 114 ---------- .../Scene/SceneSystemComponent.cpp | 167 ++++++-------- .../AzFramework/Scene/SceneSystemComponent.h | 38 ++-- .../AzFramework/Scene/SceneSystemInterface.h | 88 ++++++++ .../AzFramework/azframework_files.cmake | 3 +- .../Entity/EditorEntityContextBus.h | 2 + .../Entity/EditorEntityContextComponent.h | 1 + ...sFrameworkConfigurationSystemComponent.cpp | 41 +++- Code/Framework/Tests/NetBindingMocks.h | 1 + Code/Framework/Tests/Scene.cpp | 208 ++++++++---------- Code/Sandbox/Editor/EditorViewportWidget.cpp | 16 +- Code/Sandbox/Editor/EditorViewportWidget.h | 2 +- .../TrackView/AtomOutputFrameCapture.cpp | 2 +- .../Atom/Bootstrap/BootstrapNotificationBus.h | 16 +- .../Atom/Bootstrap/BootstrapRequestBus.h | 2 +- .../Code/Source/BootstrapSystemComponent.cpp | 29 ++- .../Code/Source/BootstrapSystemComponent.h | 10 +- .../RPI/Code/Include/Atom/RPI.Public/Scene.h | 2 +- .../Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 11 +- .../Viewport/RenderViewportWidget.h | 2 +- .../Source/Viewport/RenderViewportWidget.cpp | 4 +- .../Viewport/MaterialViewportRenderer.cpp | 17 +- .../AtomDebugDisplayViewportInterface.cpp | 7 +- .../AtomLyIntegration/AtomFont/AtomFont.h | 8 +- .../AtomFont/Code/Source/AtomFont.cpp | 24 +- .../DiffuseProbeGridComponentController.cpp | 2 +- .../Source/Mesh/MeshComponentController.cpp | 2 +- .../ReflectionProbeComponentController.cpp | 2 +- .../SkinnedMesh/SkinnedMeshDebugDisplay.cpp | 2 +- .../Rendering/ThumbnailRendererData.h | 2 +- .../ThumbnailRendererSteps/InitializeStep.cpp | 23 +- .../ReleaseResourcesStep.cpp | 14 +- 42 files changed, 757 insertions(+), 529 deletions(-) create mode 100644 Code/Framework/AzFramework/AzFramework/Scene/Scene.inl delete mode 100644 Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h create mode 100644 Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h 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/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/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/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/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/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index d319fe1d52..9165809c7f 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/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/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/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..f282aaebee 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. 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/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; } From aa2188c59a27a34c3c35010e1c5361e9a16c01fc Mon Sep 17 00:00:00 2001 From: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> Date: Thu, 29 Apr 2021 09:18:22 -0700 Subject: [PATCH 17/30] Enabled file sharing when AZ::IO::Streamer in tests and when the game is run in DevMode. --- Registry/Platform/Windows/streamer.game.setreg | 2 +- Registry/Platform/Windows/streamer.test.setreg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 }, From 51a8696f69503b0821ff037b64402c6783254005 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 29 Apr 2021 11:19:34 -0500 Subject: [PATCH 18/30] [LYN-3419] First pass of removing unused logic for old viewport interaction model. --- .../PropertyGenericCtrl.cpp | 3 - .../Editor/Core/LevelEditorMenuHandler.cpp | 7 - Code/Sandbox/Editor/CryEdit.cpp | 228 ------------------ Code/Sandbox/Editor/CryEdit.h | 9 - Code/Sandbox/Editor/ErrorReportDialog.cpp | 10 - Code/Sandbox/Editor/IEditor.h | 3 - Code/Sandbox/Editor/IEditorImpl.cpp | 23 -- Code/Sandbox/Editor/IEditorImpl.h | 1 - Code/Sandbox/Editor/Lib/Tests/IEditorMock.h | 1 - Code/Sandbox/Editor/LyViewPaneNames.h | 1 - Code/Sandbox/Editor/MainWindow.cpp | 80 ------ Code/Sandbox/Editor/MainWindow.h | 9 - .../Editor/Material/MaterialManager.cpp | 16 +- Code/Sandbox/Editor/Resource.h | 11 - Code/Sandbox/Editor/ToolbarManager.cpp | 18 -- 15 files changed, 2 insertions(+), 418 deletions(-) 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 ea42fc16a2..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() { 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/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; } From 771a7a25aa4bf8cbafd85459b370eef22ade6105 Mon Sep 17 00:00:00 2001 From: Aaron Ruiz Mora Date: Thu, 29 Apr 2021 18:00:06 +0100 Subject: [PATCH 19/30] Adding OUTPUT_NAME to physics gems shared libraries to avoid conflicting with their 3rdParty libraries --- Gems/Blast/Code/CMakeLists.txt | 5 ++++- Gems/NvCloth/Code/CMakeLists.txt | 5 ++++- Gems/PhysX/Code/CMakeLists.txt | 5 ++++- Gems/PhysXDebug/Code/CMakeLists.txt | 3 ++- 4 files changed, 14 insertions(+), 4 deletions(-) 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/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..e1b13d92c4 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 @@ -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 From 13cf0be08a856a75d423cb2911fd8635689d6ea2 Mon Sep 17 00:00:00 2001 From: luissemp Date: Thu, 29 Apr 2021 10:09:35 -0700 Subject: [PATCH 20/30] Restored the code that clears the Lua asset cache --- .../AzCore/AzCore/Script/ScriptSystemComponent.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp index f12da5c60e..d428b91a19 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp @@ -349,7 +349,7 @@ ScriptLoadResult ScriptSystemComponent::LoadAndGetNativeContext(const Data::Asse // Check if already loaded auto scriptIt = container->m_loadedScripts.find(asset.GetId().m_guid); - if (scriptIt != container->m_loadedScripts.end()) + if (scriptIt != container->m_loadedScripts.end() && scriptIt->second.m_scriptAsset.Get()) { lua_rawgeti(lua, LUA_REGISTRYINDEX, scriptIt->second.m_tableReference); @@ -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; } From f5a9aaff5b11819ab46e8f96d0337aacccd3500d Mon Sep 17 00:00:00 2001 From: luissemp Date: Thu, 29 Apr 2021 10:12:09 -0700 Subject: [PATCH 21/30] Removed temporary debugging test --- Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp index d428b91a19..015554538f 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp @@ -349,7 +349,7 @@ ScriptLoadResult ScriptSystemComponent::LoadAndGetNativeContext(const Data::Asse // Check if already loaded auto scriptIt = container->m_loadedScripts.find(asset.GetId().m_guid); - if (scriptIt != container->m_loadedScripts.end() && scriptIt->second.m_scriptAsset.Get()) + if (scriptIt != container->m_loadedScripts.end()) { lua_rawgeti(lua, LUA_REGISTRYINDEX, scriptIt->second.m_tableReference); From 1234a3785a4b6dff80eaa44313564d357ab94e8f Mon Sep 17 00:00:00 2001 From: sweeneys Date: Thu, 29 Apr 2021 11:19:45 -0700 Subject: [PATCH 22/30] Fix shader list tool bug mixing positional and non-positional argparse flags --- scripts/bundler/get_shader_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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.") From a746223c65c6bc9c836eeace299d0ffd4c68c8da Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Thu, 29 Apr 2021 12:01:32 -0700 Subject: [PATCH 23/30] Change AtomSampleViewer screenshots to use png (#336) Add functionality to capture png screenshots. --- .../Source/FrameCaptureSystemComponent.cpp | 53 ++++++++++++++++++- .../Platform/Windows/platform_windows.cmake | 11 ++++ 2 files changed, 63 insertions(+), 1 deletion(-) 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 +) From 9df8ac76d4898aac5b4d6078c1034b93c907718d Mon Sep 17 00:00:00 2001 From: scottr Date: Thu, 29 Apr 2021 12:57:11 -0700 Subject: [PATCH 24/30] [install_gem_assets_fix] fixed glob/filter logic for finding gem asset directories to install --- cmake/Platform/Common/Install_common.cmake | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index b5dc7a30ef..0356a0dcf4 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}\" @@ -329,9 +329,16 @@ function(ly_setup_others) # Gem Source Assets # 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_CURRENT_SOURCE_DIR}/" + "Gems/*" + ) + list(FILTER gems_assets_path INCLUDE REGEX "/Assets$") + 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 From 54e06b0f635c5dff6423fa3853842b9a598d2ef8 Mon Sep 17 00:00:00 2001 From: Shirang Jia Date: Thu, 29 Apr 2021 14:07:19 -0700 Subject: [PATCH 25/30] Update EBS deletion labmda to handle PR closed event (#406) * Update EBS deletion labmda to handle PR closed event * Remove print used for debugging --- .../build/lambda/delete_github_branch_ebs.py | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) 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') From ce17170bae028b9b36182ab376bdb9a689962c12 Mon Sep 17 00:00:00 2001 From: scottr Date: Thu, 29 Apr 2021 14:40:49 -0700 Subject: [PATCH 26/30] [install_gem_assets_fix] revert gem asset folder glob to use CMAKE_SOURCE_DIR instead of CMAKE_CURRENT_SOURCE_DIR --- cmake/Platform/Common/Install_common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 0356a0dcf4..82238170f7 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -333,7 +333,7 @@ function(ly_setup_others) GLOB_RECURSE gems_assets_path LIST_DIRECTORIES TRUE - RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/" + RELATIVE "${CMAKE_SOURCE_DIR}/" "Gems/*" ) list(FILTER gems_assets_path INCLUDE REGEX "/Assets$") From 109605a733d95e91a510fe96d8e9a202baa0e00f Mon Sep 17 00:00:00 2001 From: pruiksma Date: Thu, 29 Apr 2021 16:44:24 -0500 Subject: [PATCH 27/30] Cherry pick 06044522763512b78ae504f658a3e7cb5f99996c from 1.0 to main. [ATOM-15427] Fixing crash in DirectionalLightFeatureProcessor caused by incorrect use of a container. --- .../Source/CoreLights/DirectionalLightFeatureProcessor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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()) From 37f0b44de47c90c29df8eceb8f901fcab8245db8 Mon Sep 17 00:00:00 2001 From: scottr Date: Thu, 29 Apr 2021 16:01:15 -0700 Subject: [PATCH 28/30] [install_gem_assets_fix] include the Registry folder in the gem install filtering --- cmake/Platform/Common/Install_common.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 82238170f7..fb3a7b1b09 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -327,7 +327,7 @@ 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 @@ -336,7 +336,7 @@ function(ly_setup_others) RELATIVE "${CMAKE_SOURCE_DIR}/" "Gems/*" ) - list(FILTER gems_assets_path INCLUDE REGEX "/Assets$") + 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}/) From 1d7fc92930cabf633f545eceb5f5dc872968a6f7 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Thu, 29 Apr 2021 18:19:14 -0700 Subject: [PATCH 29/30] Fixes errors in function scope variables that require static initialization --- .../Grammar/AbstractCodeModel.cpp | 55 +- .../Include/ScriptCanvas/Grammar/Primitives.h | 1 + ...st_FunctionLocalStaticsUnique.scriptcanvas | 2771 +++++++++++++++++ ...ionLocalStaticsUniqueFunction.scriptcanvas | 2155 +++++++++++++ .../Tests/ScriptCanvas_RuntimeInterpreted.cpp | 5 + 5 files changed, 4977 insertions(+), 10 deletions(-) create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUnique.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_FunctionLocalStaticsUniqueFunction.scriptcanvas 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/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/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index a73c3c41a1..a46bb3323b 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -140,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"); From aa5ddbf532977a0eb35447238b446f36784c7741 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Fri, 30 Apr 2021 07:21:52 +0200 Subject: [PATCH 30/30] [LYN-3344] EMotionFX: Data integrity error, missing keyframe at the end of the animation (#418) Animation tracks in the DCC tool formats are often stored individually, each having its own duration. For EMotion FX 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. * Added function that adds missing keyframes to match the individual tracks' duration for the non-uniform motion data in emfx. * Added data integrity checks for various stages of the motion data builder / motion exporter. * Checking for data integrity issues with an assert in the emfx importer. This is just a safety check and we don't need that for release builds as they should be captured at asset processing time already. --- .../RCExt/Motion/MotionDataBuilder.cpp | 20 ++++++++- .../Source/Importer/ChunkProcessors.cpp | 4 +- .../EMotionFX/Source/MotionData/MotionData.h | 1 + .../MotionData/NonUniformMotionData.cpp | 42 ++++++++++++++++++- .../Source/MotionData/NonUniformMotionData.h | 13 +++++- 5 files changed, 74 insertions(+), 6 deletions(-) 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;